Browse Source

审批驳回/积分申诉

walter 10 months ago
parent
commit
a6b3aaadca

+ 704 - 0
src/components/AppealInfo.vue

@@ -0,0 +1,704 @@
+<template>
+  <van-popup
+    v-model="showAppealInfo"
+    :position="position"
+    duration="0.2"
+    :style="{ height: height, width: width, 'background-color': 'rgb(245, 245, 245)' }"
+    @open="onOpen"
+    @closed="onClosed"
+  >
+    <div style="height: 100%;width: 100%">
+      <van-nav-bar
+        title="申诉信息"
+        :left-arrow="true"
+        @click-left="showAppealInfo = false"
+        @click-right="showActions = true"
+        fixed
+      >
+        <template slot="right" v-if="canActions">
+          <van-icon name="bars"/>
+        </template>
+      </van-nav-bar>
+      <div class="container" v-if="appealInfo" >
+        <div class="card-box">
+          <van-row type="flex" justify="center" gutter="10" align="center">
+            <van-col span="6" style="text-align: right">
+              <userImage
+                :img_url="appealInfo.employee_img_url"
+                :user_name="appealInfo.employee_name"
+              />
+            </van-col>
+            <van-col span="10" style="text-align: left" class="font-flex-word">
+              <span style="line-height: 0.8rem;">{{appealInfo.employee_name}}</span>
+            </van-col>
+            <van-col span="8">
+              <van-tag :type="appealStatusType(appealInfo.status)" size="medium" >{{appealStatusMap[appealInfo.status] || '--'}}</van-tag>
+            </van-col>
+          </van-row>
+          <van-divider/>
+          <div class="card-content">
+            <p><van-tag type="primary" size="medium">{{appealInfo.create_time}}</van-tag>&nbsp;发起复议申请</p>
+            <p>共<van-tag type="primary" size="medium">{{appealInfo.events.length}}</van-tag>&nbsp;条积分事件</p>
+            <p v-if="appealInfo.global_remark">申请原因&nbsp;:&nbsp;<van-tag type="primary" size="medium">{{appealInfo.global_remark}}</van-tag></p>
+            <template v-if="appealInfo.complete_time">
+              <p><van-tag type="primary" size="medium">{{appealInfo.complete_time}}</van-tag>&nbsp;审批结束</p>
+            </template>
+          </div>
+        </div>
+        <van-collapse v-model="activeNames" accordion>
+          <van-collapse-item name="process">
+            <template slot="title">
+              <span class="content-font">审批流程</span>
+            </template>
+            <van-steps direction="vertical" :active="appealInfo.process.length - 1" >
+              <van-step v-for="(item,index) in appealInfo.process" :key="index" >
+                <div class="card-box">
+                  <div class="card-content" style="text-align: left;line-height: 0.25rem;">
+                    <p>阶段{{item.step}}&nbsp;<van-tag :type="processStatusType(item.status)" size="medium">{{processStatusMap[item.status] || '--'}}</van-tag></p>
+                    <p>发起人&nbsp;:&nbsp;{{item.publisher_name}}</p>
+                    <p>发起时间&nbsp;:&nbsp;{{item.create_time}}</p>
+                    <p>审批人&nbsp;:&nbsp;{{item.reviewer_name}}</p>
+                    <p v-if="item.remark" class="font-flex-word">审批意见&nbsp;:&nbsp;{{item.remark}}</p>
+                    <p v-if="item.complete_time">完结时间&nbsp;:&nbsp;{{item.complete_time}}</p>
+                  </div>
+                </div>
+              </van-step>
+            </van-steps>
+          </van-collapse-item>
+          <van-collapse-item name="events">
+            <template slot="title">
+              <span class="content-font">{{appealInfo.events.length + '条积分'}}</span>
+            </template>
+            <div class="card-box" v-for="(item,index) in appealInfo.events" :key="index">
+              <div class="card-content1">
+                <p>积分&nbsp;:&nbsp;{{item.point + ' ' + ptName(item.pt_id)}} <van-tag :type="pointStatusType(item.status)" >{{pointStatusMap[item.status] || '--'}}</van-tag> </p>
+                <p style="line-height: 0.5rem">积分备注&nbsp;:&nbsp;{{item.event_remark}}</p>
+                <p>时间&nbsp;:&nbsp;{{item.event_time}}</p>
+                <p v-if="item.appeal_remark" >复议原因&nbsp;:&nbsp;{{item.appeal_remark}}</p>
+                <p v-if="item.delete_time" >已删除&nbsp;:&nbsp;{{item.delete_time}}</p>
+              </div>
+            </div>
+          </van-collapse-item>
+          <van-collapse-item name="logs">
+            <template slot="title">
+              <span class="content-font">{{appealInfo.logs.length + '条操作日志'}}</span>
+            </template>
+            <p v-for="(item,index) in appealInfo.logs" :key="index" class="content-font font-flex-word">
+              <van-tag type="primary" size="medium" v-if="item.create_time" >{{item.create_time}}</van-tag>
+              {{item.msg}}
+            </p>
+          </van-collapse-item>
+        </van-collapse>
+      </div>
+    </div>
+
+    <van-action-sheet
+      v-model="showActions"
+      :actions="appealActions"
+      @select="actionSelect"
+      close-on-click-action
+    />
+
+<!--  拒绝审批  -->
+    <van-dialog
+      v-model="showReviewRefuse"
+      title="拒绝审批"
+      :show-cancel-button="false"
+      :show-confirm-button="false"
+    >
+      <van-form @submit="refuseReview">
+        <van-cell-group>
+          <van-cell><Mtextarea v-model="formData.remark" placeholder="原因说明(选填)"></Mtextarea></van-cell>
+        </van-cell-group>
+        <van-row type="flex" justify="center" gutter="10" style="margin: 0.1rem;">
+          <van-col span="12">
+            <van-button round block type="warning" native-type="button" @click="closeRefuseReview">
+              取消
+            </van-button>
+          </van-col>
+          <van-col span="12">
+            <van-button round block type="info" native-type="submit">
+              提交
+            </van-button>
+          </van-col>
+        </van-row>
+      </van-form>
+    </van-dialog>
+
+<!--  驳回重填  -->
+    <van-dialog
+      v-model="showReviewRejectRewrite"
+      title="驳回重填"
+      :show-cancel-button="false"
+      :show-confirm-button="false"
+    >
+      <van-form @submit="rejectRewrite">
+        <van-cell-group>
+          <van-cell><Mtextarea v-model="formData.remark" placeholder="原因说明(选填)"></Mtextarea></van-cell>
+        </van-cell-group>
+
+        <van-row type="flex" justify="center" gutter="10" style="margin: 0.1rem;">
+          <van-col span="12">
+            <van-button round block type="warning" native-type="button" @click="closeRejectRewrite">
+              取消
+            </van-button>
+          </van-col>
+          <van-col span="12">
+            <van-button round block type="info" native-type="submit">
+              提交
+            </van-button>
+          </van-col>
+        </van-row>
+      </van-form>
+    </van-dialog>
+
+
+<!--  递交审批  -->
+    <van-dialog
+      v-model="showReviewSubmit"
+      title="递交审批"
+      :show-cancel-button="false"
+      :show-confirm-button="false"
+    >
+      <van-form @submit="reviewSubmit">
+        <van-cell-group>
+          <EmployeeSelectorCell
+            title="递交审批"
+            v-model="formData.reviewer"
+            :multi="false"
+            icon-type="records"
+            :employee_list="userInfo.employee_detail.superior_list"
+            :is_employee_list="true"
+          />
+        </van-cell-group>
+
+        <van-cell-group>
+          <van-cell><Mtextarea v-model="formData.remark" placeholder="原因说明(选填)"></Mtextarea></van-cell>
+        </van-cell-group>
+
+        <van-row type="flex" justify="center" gutter="10" style="margin: 0.1rem;">
+          <van-col span="12">
+            <van-button round block type="warning" native-type="button" @click="closeReviewSubmit">
+              取消
+            </van-button>
+          </van-col>
+          <van-col span="12">
+            <van-button round block type="info" native-type="submit">
+              提交
+            </van-button>
+          </van-col>
+        </van-row>
+      </van-form>
+    </van-dialog>
+
+<!--  审批通过  -->
+    <van-dialog
+      v-model="showReviewApproval"
+      title="通过"
+      :show-cancel-button="false"
+      :show-confirm-button="false"
+    >
+      <van-form @submit="reviewApproval">
+        <van-cell-group>
+          <van-cell><Mtextarea v-model="formData.remark" placeholder="原因说明(选填)"></Mtextarea></van-cell>
+        </van-cell-group>
+        <van-row type="flex" justify="center" gutter="10" style="margin: 0.1rem;">
+          <van-col span="12">
+            <van-button round block type="warning" native-type="button" @click="closeReviewApproval">
+              取消
+            </van-button>
+          </van-col>
+          <van-col span="12">
+            <van-button round block type="info" native-type="submit">
+              提交
+            </van-button>
+          </van-col>
+        </van-row>
+      </van-form>
+    </van-dialog>
+
+<!--  重新填写  -->
+<!--    <van-dialog-->
+<!--      v-model="showRewrite"-->
+<!--      title="复议记录"-->
+<!--      :show-cancel-button="false"-->
+<!--      :show-confirm-button="false"-->
+<!--    >-->
+
+<!--    </van-dialog>-->
+    <AppealRewrite
+      v-if="appealInfo"
+      :visible.sync="showRewrite"
+      :id="appealInfo.id"
+      @hasSubmit="handleRewriteSubmit"
+    />
+
+
+  </van-popup>
+</template>
+
+<script>
+import Vue from "vue";
+import {NavBar,Steps,Step,Collapse,CollapseItem,Dialog} from "vant";
+import EmployeeSelectorCell from "./EmployeeSelectorCell.vue";
+import Mtextarea from "./Mtextarea2.vue";
+import AppealRewrite from "./AppealRewrite.vue";
+Vue.use(NavBar)
+  .use(Steps)
+  .use(Step)
+  .use(Collapse)
+  .use(CollapseItem)
+  .use(Dialog)
+
+export default {
+  name: 'appealInfo',
+  components: {AppealRewrite, Mtextarea, EmployeeSelectorCell},
+  props: {
+    visible:{
+      type: Boolean,
+      default : false
+    },
+    position:{
+      type: String,
+      default: 'bottom'
+    },
+    id:{
+      type: Number,
+      default: 0
+    },
+    height:{
+      type: String,
+      default: '100%'
+    },
+    width:{
+      type: String,
+      default: '100%'
+    }
+  },
+  data(){
+    return {
+      userInfo: this.$userInfo(),
+      showAppealInfo:this.visible,
+      hasOpen:false,
+      hasSubmit:false,
+      loading:false,
+      appealInfo:null,
+      appealStatusMap:{
+        0:'全部',
+        1:'审批中',
+        2:'审批通过',
+        3:'驳回重填',
+        4:'撤回重填',
+        5:'拒绝'
+      },
+      pointStatusMap:{
+        1:'正常',
+        2:'已删除',
+        3:'已通过申述并删除'
+      },
+      processStatusMap:{
+        1:'待处理',
+        2:'审批通过',
+        3:'递交审批',
+        4:'拒绝',
+        5:'驳回重填',
+        6:'撤回上个节点重填',
+        7:'复议撤回',
+      },
+      pts:this.$getTypes,
+      formData:{
+        remark:'',
+        reviewer:[]
+      },
+      rewriteData:{
+        events:[],
+        globalRemark:'',
+        reviewerId:'',
+        reviewerName:'',
+        employeeSelected: { dept: [], employee: [] },
+      },
+      showReviewRefuse:false,
+      showReviewRejectRewrite:false,
+      showReviewApproval:false,
+      showReviewerSelector:false,
+      showReviewSubmit:false,
+      submitting:false,
+      showEventSelector:false,
+      showRewrite:false,
+      activeNames:'process',
+      showActions:false,
+      actions:{
+        delete:{name:'删除复议',action:'delete',loading:false,disabled:false},
+        refuse:{name:'拒绝',action:'refuse',loading:false,disabled:false},
+        rejectRewrite:{name:'驳回重填',action:'rejectRewrite',loading:false,disabled:false},
+        cancel:{name:'撤回审批',action:'cancel',loading:false,disabled:false},
+        cancelAppeal:{name:'撤回复议',action:'cancelAppeal',loading:false,disabled:false},
+        rewrite:{name:'重新填写',action:'rewrite',loading:false,disabled:false},
+        submit:{name:'递交审批',action:'submit',loading:false,disabled:false},
+        approval:{name:'通过',action:'approval',loading:false,disabled:false},
+      }
+    }
+  },
+  watch:{
+    showAppealInfo(v){
+      this.$emit('update:visible', v)
+    },
+    visible(v){
+      this.showAppealInfo = v
+    }
+  },
+  computed:{
+    appealActions(){
+      let actions = []
+      if (!this.appealInfo) return actions
+      if (this.appealInfo.can_delete) actions.push(this.actions.delete)
+      if (this.appealInfo.can_refuse) actions.push(this.actions.refuse)
+      if (this.appealInfo.can_reject_rewrite) actions.push(this.actions.rejectRewrite)
+      if (this.appealInfo.can_cancel) actions.push(this.actions.cancel)
+      if (this.appealInfo.can_cancel_appeal) actions.push(this.actions.cancelAppeal)
+      if (this.appealInfo.can_rewrite) actions.push(this.actions.rewrite)
+      if (this.appealInfo.can_submit) actions.push(this.actions.submit)
+      if (this.appealInfo.can_approval) actions.push(this.actions.approval)
+      return actions
+    },
+    canActions(){
+      return this.appealActions.length > 0
+    }
+  },
+  methods:{
+    initData(){
+      this.formData.remark = ''
+      this.formData.reviewer = []
+      this.hasSubmit = false
+      this.appealInfo = null
+      this.showReviewRefuse = false
+      this.showReviewRejectRewrite = false
+      this.showReviewApproval = false
+      this.showReviewerSelector = false
+      this.showReviewSubmit = false
+      this.showRewrite = false
+      this.showEventSelector = false
+      this.submitting = false
+    },
+    onOpen(){
+      this.hasOpen = true
+      this.initData()
+      this.getAppealInfo()
+    },
+    onClosed(){
+      this.hasOpen = false
+      this.activeNames = 'process'
+      if (this.hasSubmit) this.$emit('hasSubmit')
+      this.$emit('closeInfo')
+    },
+    getAppealInfo(){
+      if (!this.$props.id) return
+      let self = this
+      self.loading = true
+      self.$axiosUser('get','api/pro/integral/appeal/info',{appeal_id:this.$props.id})
+        .then(res => {
+          if (res.data.code === 1) self.appealInfo = res.data.data
+        })
+        .finally(() => {
+          self.loading = false
+        })
+    },
+    appealStatusType(status){
+      const map = {
+        1:'primary',
+        2:'success',
+        3:'warning',
+        4:'warning',
+        5:'danger'
+      }
+      return map[status] || 'info'
+    },
+    processStatusType(status){
+      const map = {
+        1:'primary',
+        2:'success',
+        3:'success',
+        4:'danger',
+        5:'warning',
+        6:'warning',
+        7:'primary',
+      }
+      return map[status] || 'info'
+    },
+    ptName(ptId){
+      let item = this.pts.find(item => item.id === ptId)
+      return item ? item.name : ''
+    },
+    pointStatusType(status){
+      switch (status){
+        case 2:
+        case 3:
+          return 'warning'
+        default:
+          return "success"
+      }
+    },
+    actionSelect(item){
+      switch (item.action){
+        case 'delete':
+          Dialog.confirm({
+            title:'删除复议',
+            message:'删除复议后将不可恢复,确认提交吗',
+            showCancelButton:true,
+            confirmButtonText:'提交',
+            cancelButtonText:'取消',
+          })
+            .then(() => {
+              this.removeAppeal()
+            })
+            .catch(() => {})
+          break;
+        case 'refuse':
+          this.showReviewRefuse = true
+          break;
+        case 'rejectRewrite':
+          this.showReviewRejectRewrite = true
+          break;
+        case 'cancel':
+          Dialog.confirm({
+            title:'撤回审批',
+            message:'审批撤回后可以重新编辑内容重新提交',
+            showCancelButton:true,
+            confirmButtonText:'提交',
+            cancelButtonText:'取消',
+          })
+            .then(() => {
+              this.reviewCancel()
+            })
+            .catch(() => {})
+          break;
+        case 'cancelAppeal':
+          Dialog.confirm({
+            title:'撤回复议',
+            message:'复议撤回后可以重新编辑内容重新提交',
+            showCancelButton:true,
+            confirmButtonText:'提交',
+            cancelButtonText:'取消',
+          })
+            .then(() => {
+              this.appealCancel()
+            })
+            .catch(() => {})
+          break;
+        case 'rewrite':
+          this.showRewrite = true
+          break;
+        case 'submit':
+          this.showReviewSubmit = true
+          break;
+        case 'approval':
+          this.showReviewApproval = true
+          break;
+      }
+    },
+    removeAppeal(){
+      if (!this.appealInfo) return
+      let self = this
+      self.submitting = true
+      let params = {
+        appeal_id:self.appealInfo.id
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/remove',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.showAppealInfo = false
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    refuseReview(){
+      if (!this.appealInfo) return
+      let self = this
+      self.submitting = true
+      let params = {
+        appeal_id:self.appealInfo.id,
+        remark:self.formData.remark
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/review/refuse',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+            self.showReviewRefuse = false
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    closeRefuseReview(){
+      this.showReviewRefuse = false
+    },
+    rejectRewrite(){
+      if (!this.appealInfo) return
+      let self = this
+      self.submitting = true
+      let params = {
+        appeal_id:self.appealInfo.id,
+        remark:self.formData.remark
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/review/reject',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+            self.showReviewRejectRewrite = false
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    closeRejectRewrite(){
+      this.showReviewRejectRewrite = false
+    },
+    reviewSubmit(){
+      if (!this.appealInfo) return
+      let self = this
+      self.submitting = true
+      let params = {
+        appeal_id:self.appealInfo.id,
+        reviewer_id:self.formData.reviewer[0].id,
+        remark:self.formData.remark
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/review/submit',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+            self.showReviewSubmit = false
+          }else {
+            self.$message.error(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    closeReviewSubmit(){
+      this.showReviewSubmit = false
+    },
+    reviewApproval(){
+      if (!this.appealInfo) return
+      let self = this
+      self.submitting = true
+      let params = {
+        appeal_id:self.appealInfo.id,
+        remark:self.formData.remark
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/review/approval',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+            self.showReviewApproval = false
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    closeReviewApproval(){
+      this.showReviewApproval = false
+    },
+    reviewCancel(){
+      if (!this.appealInfo) return
+      this.submitting = true
+      let self = this
+      self.$axiosUser('post','api/pro/integral/appeal/review/cancel',{appeal_id:self.appealInfo.id})
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    appealCancel(){
+      if (!this.appealInfo) return
+      this.submitting = true
+      let self = this
+      self.$axiosUser('post','api/pro/integral/appeal/cancel',{appeal_id:self.appealInfo.id})
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.getAppealInfo()
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.submitting = false
+        })
+    },
+    handleRewriteSubmit(){
+      this.hasSubmit = true
+      this.getAppealInfo()
+    }
+  },
+}
+</script>
+
+
+<style scoped lang="less">
+.container {
+  position: relative;
+  width: 100%;
+  margin-top: 1.5rem;
+
+  & .card-box{
+    margin: 0.2rem;
+    padding: 0.1rem;
+    border-radius: 0.3rem;
+    border: 1px solid #ebeef5;
+    background-color: #ffffff;
+    overflow: hidden;
+    color: #303133;
+    text-align: center;
+    box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
+
+    & .card-content{
+      font-size: 0.25rem;
+      line-height: 0.5rem;
+      color: #909399;
+    }
+
+    & .card-content1{
+      font-size: 0.25rem;
+      line-height: 0.25rem;
+      color: #909399;
+      text-align: left;
+    }
+
+  }
+
+  .content-font{
+    font-size: 0.25rem;
+    line-height: 0.25rem;
+    color: #909399;
+    text-align: left;
+  }
+
+}
+
+</style>

+ 245 - 0
src/components/AppealRewrite.vue

@@ -0,0 +1,245 @@
+<template>
+  <van-popup
+    v-model="showAppealRewrite"
+    position="bottom"
+    duration="0.2"
+    :style="{height: '100%', width:'100%','background-colorr': 'rgb(245, 245, 245)'}"
+    @open="onOpen"
+    @closed="onClosed"
+  >
+    <van-nav-bar
+      title="申述重写"
+      :left-arrow="true"
+      @click-left="showAppealRewrite = false"
+      @click-right="showActions = true"
+      fixed
+    >
+      <template slot="right" v-if="canActions">
+        <van-icon name="bars"/>
+      </template>
+    </van-nav-bar>
+
+    <div :style="{marginTop:'1rem',height:'90%'}">
+      <van-notice-bar
+        left-icon="volume-o"
+        text="手机端暂不支持添加积分事件,请在电脑端操作"
+      />
+      <van-form>
+        <van-cell-group>
+          <EmployeeSelectorCell
+            title="递交审批"
+            v-model="rewriteData.reviewer"
+            :multi="false"
+            icon-type="records"
+            :employee_list="userInfo.employee_detail.superior_list"
+            :is_employee_list="true"
+          />
+        </van-cell-group>
+        <van-cell-group>
+          <van-cell>
+            <Mtextarea v-model="rewriteData.globalRemark" :text_max="100" placeholder="申诉原因"/>
+          </van-cell>
+        </van-cell-group>
+        <div class="card-box">
+          <div class="box-header">
+            <span v-if="rewriteData.events.length > 0">共{{rewriteData.events.length}}条积分事件</span>
+            <span v-else>暂无积分事件</span>
+          </div>
+          <van-divider/>
+          <div class="box-content">
+            <div v-for="(item,index) in rewriteData.events" :key="index" class="box-content-item">
+              <div class="box-content-item-title">
+                <van-tag type="primary" size="medium" closeable @close="deleteEvent(item)" >{{item.remark}}</van-tag>
+              </div>
+              <div class="box-content-item-content">
+                <Mtextarea :text_max="100" placeholder="申诉原因" v-model="item.appeal_remark"/>
+              </div>
+            </div>
+          </div>
+        </div>
+      </van-form>
+    </div>
+
+
+    <van-action-sheet
+      v-model="showActions"
+      :actions="[actionRewrite]"
+      @select="actionSelect"
+      close-on-click-action
+    />
+
+  </van-popup>
+</template>
+
+<script>
+import EmployeeSelectorCell from "./EmployeeSelectorCell.vue";
+import Mtextarea from "./Mtextarea2.vue";
+export default {
+  name: "AppealRewrite",
+  components:{Mtextarea,EmployeeSelectorCell},
+  props:{
+    visible:{
+      type: Boolean,
+      default : false
+    },
+    id:{
+      type: Number,
+      default: 0
+    },
+  },
+  data(){
+    return {
+      userInfo:this.$userInfo(),
+      hasOpen:false,
+      showAppealRewrite:false,
+      showActions:false,
+      hasSubmit: false,
+      pts:this.$getTypes,
+      appealInfo:null,
+      rewriteData:{
+        events:[],
+        globalRemark:'',
+        reviewer:[]
+      },
+      loading:false,
+      actionRewrite:{name:'提交',action:'rewrite',loading:false,disabled:false},
+      submitting:false,
+    }
+  },
+  watch:{
+    showAppealRewrite(v){
+      this.$emit('update:visible',v)
+    },
+    visible(v){
+      this.showAppealRewrite = v
+    }
+  },
+  computed:{
+    canActions(){
+      return this.appealInfo && this.appealInfo.can_rewrite && this.rewriteData.reviewer.length === 1 && this.rewriteData.events.length >= 1 && !this.submitting
+    }
+  },
+  methods:{
+    onOpen(){
+      this.hasOpen = true
+      this.getAppealInfo()
+    },
+    onClosed(){
+      this.hasOpen = false
+      if (this.hasSubmit) this.$emit('hasSubmit')
+    },
+    initRewriteData(){
+      if (!this.appealInfo) return
+      this.rewriteData.events = this.appealInfo.events.map(event => {
+        let pt = this.pts.find(item => item.id === event.pt_id)
+        pt = pt ? pt.name : ''
+        return {
+          id:event.id,
+          remark:`${event.point} ${pt} ${event.event_time} ${event.event_remark}`,
+          appeal_remark:event.appeal_remark
+        }
+      })
+      this.rewriteData.globalRemark = this.appealInfo.global_remark
+      let node = this.appealInfo.process.find(item => item.step === 1)
+      if (node){
+        this.rewriteData.reviewer = []
+        this.rewriteData.reviewer.push({id: node.reviewer_id,name: node.reviewer_name,img_url:node.reviewer_img_url})
+      }
+
+    },
+    getAppealInfo(){
+      if (!this.id) return
+      let self = this
+      self.loading = true
+      self.$axiosUser('get','api/pro/integral/appeal/info',{appeal_id:this.id})
+        .then((res) => {
+          if (res.data.code === 1){
+            self.appealInfo = res.data.data
+            self.initRewriteData()
+          }
+        })
+        .finally(() => {
+          self.loading = false
+        })
+    },
+    deleteEvent(event){
+      let index = this.rewriteData.events.indexOf(event)
+      if (index >= 0) this.rewriteData.events.splice(index,1)
+    },
+    actionSelect(action){
+      if (action.action === 'rewrite') this.rewriteAppeal()
+
+    },
+    rewriteAppeal(){
+      let self = this
+      if (!self.canActions) return
+
+      let params = {
+        appeal_id:self.appealInfo.id,
+        reviewer_id:self.rewriteData.reviewer[0].id,
+        remark:self.rewriteData.globalRemark,
+        events:self.rewriteData.events.map(item => {
+          return {id:item.id,remark:item.appeal_remark}
+        })
+      }
+
+
+      self.submitting = true
+      self.$toast.loading({ message: '正在处理',overlay:true,duration:0})
+      self.$axiosUser('post','api/pro/integral/appeal/rewrite',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.hasSubmit = true
+            self.submitting = false
+            self.showAppealRewrite = false
+          }
+          self.$toast(res.data.msg)
+          self.$toast.clear()
+        })
+        .finally(() => {})
+    }
+  }
+}
+</script>
+
+<style scoped lang="less">
+.card-box{
+  margin: 0.2rem auto;
+  border-radius: 0.3rem;
+  border: 1px solid #ebeef5;
+  background-color: #ffffff;
+  overflow: hidden;
+  color: #303133;
+  text-align: center;
+  min-height: 70%;
+  width: 95%;
+  box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1);
+
+  & .box-header{
+    height: 0.5rem;
+    line-height: 0.5rem;
+  }
+
+  & .box-content{
+    margin-bottom: 1rem;
+
+    & .box-content-item{
+      width: 95%;
+      margin: 0.3rem auto 0;
+
+      & .box-content-item-title{
+         padding: 0 0.3rem;
+      }
+
+      & .box-content-item-content{
+        padding: 0 0.3rem;
+        margin-top: 0.2rem;
+        border: 0.02rem solid #ebeef5;
+      }
+
+
+    }
+  }
+
+}
+</style>

+ 30 - 0
src/components/IntegralEventSelector.vue

@@ -0,0 +1,30 @@
+<template>
+
+</template>
+
+<script>
+export default {
+  name: "IntegralEventSelector",
+  props:{
+    visible:{
+      type: Boolean,
+      default:false
+    },
+    eid:{
+      type: Number,
+      default:0
+    },
+    selected:{
+      type: Array,
+      default: () => []
+    },
+    max:{
+      type: Number,
+      default: 100
+    }
+  }
+}
+</script>
+<style scoped lang="less">
+
+</style>

+ 5 - 5
src/components/TabsList.vue

@@ -11,13 +11,13 @@
       </van-tabs>
       <div class="list-search__bar">
         <span class="list-filter__btn" v-if="showToolBar" @click="onFilterIconClick">
-          <icon name="tab_filter" width="0.4rem" height="0.4rem"></icon>
+          <icon name="tab_filter" width="0.4rem" height="0.4rem" class="van-hairline--left"></icon>
         </span>
         <span class="list-filter__btn" v-else @click="tips">
           <icon name="tab_filter" width="0.4rem" height="0.4rem"></icon>
         </span>
       </div>
-      
+
     </div>
     <div class="tab-list__content">
       <scroller
@@ -43,7 +43,7 @@
         <van-loading v-if="loding" type="spinner" />
       </scroller>
     </div>
-    
+
     <div ref="popupContainer"  class="popup-container"  :style="popupContainerStyle"  v-show="showPopupContainer">
       <van-popup
         v-model="popupSearchBar"
@@ -60,7 +60,7 @@
         </div>
       </van-popup>
     </div>
-    
+
   </div>
 </template>
 <script>
@@ -96,7 +96,7 @@ export default {
       this.tabsOption.forEach(o => activeTabSatus[o.value] = 1)
     }
 
-    return {
+    return  {
       loding: false,
       activeTab: activeTab,
       activeTabName: activeTabName,

+ 1 - 1
src/point/view/audit/integralAudit.vue

@@ -113,7 +113,7 @@
 
         <van-cell-group v-if="!isCreator">
           <EmployeeSelectorCell
-            title="递交审批"
+            title="审批"
             v-model="reviewer"
             :multi="false"
             iconType="records"

+ 358 - 0
src/point/view/integral/appealList.vue

@@ -0,0 +1,358 @@
+<template>
+  <div>
+    <van-nav-bar title="申诉记录" left-text="返回" @click-left="$route_back" left-arrow >
+      <template slot="right" v-if="currentTab === 'my'">
+        <van-dropdown-menu>
+          <van-dropdown-item v-model="searchForm.status" :options="appealStatus" />
+        </van-dropdown-menu>
+      </template>
+    </van-nav-bar>
+    <van-tabs
+      v-model="currentTab"
+      :border="false"
+      title-active-color="#26A2FF"
+      color="#FFFFFF"
+    >
+      <van-tab v-for="item in tabs" :key="item.name" :title="item.title" :name="item.name" />
+    </van-tabs>
+    <div class="content-list">
+      <scroller
+        ref="scroller"
+        :on-refresh="onRefresh"
+        :on-infinite="onInfinite"
+        no-data-text="我也是有底线的"
+        :list="list"
+      >
+        <van-cell v-for="item in list" :key="item.id" @click="openDetail(item.id)" >
+          <template slot="title">
+            <van-row>
+              <van-col span="4">
+                <div style="width: 100%; text-align: center;">
+                  <userImage
+                    :img_url="item.employee_img_url"
+                    :user_name="item.employee_name"
+                  />
+                </div>
+              </van-col>
+              <van-col span="6" class="font-flex-word" style="text-align: center">
+                <span style="font-size: 0.35rem;line-height: 0.8rem">
+                  {{item.employee_name}}
+                </span>
+              </van-col>
+              <van-col span="14" class="font-flex-word" >
+                <span style="font-size: 0.35rem;line-height: 0.8rem">
+                  提交了
+                  <van-tag type="primary" round size="medium">{{item.event_count <= 1000 ? item.event_count : '1000+'}}</van-tag>
+                  条积分复议
+                </span>
+              </van-col>
+            </van-row>
+            <van-row  type="flex" justify="end">
+              <van-col span="8" style="text-align: center;">
+                <span style="font-size: 0.3rem;line-height: 0.8rem; " class="input-ccc">{{item.create_time}}</span>
+              </van-col>
+              <van-col span="8" style="text-align: center;line-height: 0.8rem">
+                <van-tag :type="statusType(item.status)" size="medium" mark>{{appealStatusMap[item.status] || ''}}</van-tag>
+              </van-col>
+            </van-row>
+          </template>
+        </van-cell>
+      </scroller>
+    </div>
+
+    <AppealInfo
+      :visible.sync="showAppealInfo"
+      :id="appealId"
+      @closeInfo="closeDetail"
+      @hasSubmit="refresh"
+    />
+  </div>
+</template>
+
+<script>
+import Vue from "vue";
+import {DropdownMenu,DropdownItem,Card} from "vant";
+import AppealInfo from "@/components/AppealInfo.vue";
+Vue.use(DropdownMenu).use(DropdownItem).use(Card)
+export default {
+  name: "appeal",
+  components: {AppealInfo},
+  data(){
+    return {
+      first:true,
+      userInfo:this.$userInfo(),
+      currentTab:'waiting',
+      tabs:[
+        {name:'waiting',title:'待处理'},
+        {name:'my',title:'我的'},
+        {name:'join',title:'参与'},
+      ],
+      searchForm:{
+        status: 3,
+        page: 1,
+        pageSize: 10,
+        hasFinish:false,
+      },
+      list:[],
+      appealStatusMap:{
+        0:'全部',
+        1:'审批中',
+        2:'审批通过',
+        3:'驳回重填',
+        4:'撤回重填',
+        5:'拒绝'
+      },
+      appealStatus:[
+        {
+          value:0,
+          text:'全部'
+        },
+        {
+          value:1,
+          text:'审批中'
+        },
+        {
+          value:2,
+          text:'审批通过'
+        },
+        {
+          value:3,
+          text:'驳回重填'
+        },
+        {
+          value:4,
+          text:'撤回重填'
+        },
+        {
+          value:5,
+          text:'拒绝'
+        },
+      ],
+      showToolBar:false,
+      loading:false,
+      showAppealInfo:false,
+      appealId:0
+    }
+  },
+  methods:{
+    initData(){
+      this.list = []
+      this.currentTab = 'waiting'
+      this.initSearchForm()
+    },
+    initSearchForm(){
+      this.searchForm.status = 3
+      this.searchForm.page = 1
+      this.searchForm.pageSize = 10
+      this.searchForm.hasFinish = false
+    },
+    initPage(){
+      this.searchForm.hasFinish = false
+      this.searchForm.page = 1
+      this.searchForm.pageSize = 10
+    },
+    refresh(){
+      this.initPage()
+      this.$refs.scroller.finishInfinite(false)
+      this.$refs.scroller.triggerPullToRefresh()
+    },
+    statusType(status){
+      let map = {
+        1:'primary',
+        2:'success',
+        3:'warning',
+        4:'warning',
+        5:'danger',
+      }
+      return map[status] || 'primary'
+    },
+    onRefresh(finishPullToRefresh){
+      this.initPage()
+      this.getList(finishPullToRefresh)
+    },
+    onInfinite(finishInfinite){
+      if (this.searchForm.hasFinish) {
+        finishInfinite()
+        this.$refs.scroller.finishPullToRefresh()
+        return
+      }
+      this.searchForm.page++
+      this.getList(finishInfinite)
+    },
+
+    getList(callback){
+      switch (this.currentTab) {
+        case 'waiting':
+          this.getListForWaiting(callback)
+          break;
+        case 'my':
+          this.getPublishList(callback)
+          break;
+        case 'join':
+          this.getJoinList(callback)
+          break;
+      }
+    },
+    getListForWaiting(callback){
+      let self = this
+      self.loading = true
+      let params = {
+        last_reviewer_id:self.userInfo.id,
+        status:1,
+        page:self.searchForm.page,
+        page_size:self.searchForm.pageSize
+      }
+
+      self.$axiosUser('get','/api/pro/integral/appeal/list',params)
+        .then(res => {
+          if (res.data.code === 1){
+            if (self.searchForm.page === 1){
+              self.list = res.data.data.list
+            }else {
+              self.list = self.list.concat(res.data.data.list)
+            }
+            callback && callback()    //将后台获取的数据,复制到vue组件的数据源后,再进行调用done函数。如果在之前调用,会循环调用。如果不调用这个函数,上拉获取数据函数调用不成功
+
+            self.$refs.scroller.finishPullToRefresh()   //停止下拉刷新  loading动画
+
+            self.searchForm.hasFinish = res.data.data.list.length !== self.searchForm.pageSize
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)    //当参数为false时,上拉获取数据可以重新调用。当参数为true,上拉获取数据回调函数停止使用,下拉下部不再显示loading,会显示‘’暂无更多数据
+          }else {
+            self.searchForm.hasFinish = true
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)
+          }
+        })
+        .finally(() => {
+          self.loading = false
+        })
+    },
+    getPublishList(callback){
+      let self = this
+      self.loading = true
+      let params = {
+        status:self.searchForm.status,
+        page:self.searchForm.page,
+        page_size:self.searchForm.pageSize
+      }
+
+      self.$axiosUser('get','/api/pro/integral/appeal/list/publisher',params)
+        .then(res => {
+          if (res.data.code === 1){
+            if (self.searchForm.page === 1){
+              self.list = res.data.data.list
+            }else {
+              self.list = self.list.concat(res.data.data.list)
+            }
+            callback && callback()    //将后台获取的数据,复制到vue组件的数据源后,再进行调用done函数。如果在之前调用,会循环调用。如果不调用这个函数,上拉获取数据函数调用不成功
+
+            self.$refs.scroller.finishPullToRefresh()   //停止下拉刷新  loading动画
+
+            self.searchForm.hasFinish = res.data.data.list.length !== self.searchForm.pageSize
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)    //当参数为false时,上拉获取数据可以重新调用。当参数为true,上拉获取数据回调函数停止使用,下拉下部不再显示loading,会显示‘’暂无更多数据
+          }else {
+            self.searchForm.hasFinish = true
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)
+          }
+        })
+        .finally(() => {
+          self.loading = false
+        })
+    },
+    getJoinList(callback){
+      let self = this
+      self.loading = true
+      let params = {
+        page:self.searchForm.page,
+        page_size:self.searchForm.pageSize
+      }
+
+      self.$axiosUser('get','/api/pro/integral/appeal/list/reviewer',params)
+        .then(res => {
+          if (res.data.code === 1){
+            if (self.searchForm.page === 1){
+              self.list = res.data.data.list
+            }else {
+              self.list = self.list.concat(res.data.data.list)
+            }
+
+            callback && callback()    //将后台获取的数据,复制到vue组件的数据源后,再进行调用done函数。如果在之前调用,会循环调用。如果不调用这个函数,上拉获取数据函数调用不成功
+
+            self.$refs.scroller.finishPullToRefresh()   //停止下拉刷新  loading动画
+
+            self.searchForm.hasFinish = res.data.data.list.length !== self.searchForm.pageSize
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)    //当参数为false时,上拉获取数据可以重新调用。当参数为true,上拉获取数据回调函数停止使用,下拉下部不再显示loading,会显示‘’暂无更多数据
+          }else {
+            self.searchForm.hasFinish = true
+            self.$refs.scroller.finishInfinite(self.searchForm.hasFinish)
+          }
+        })
+        .finally(() => {
+          self.loading = false
+        })
+    },
+    openDetail(appealId){
+      this.appealId = appealId
+      this.showAppealInfo = true
+    },
+    closeDetail(){
+      this.appealId = 0
+      this.showAppealInfo = false
+    },
+
+  },
+  computed:{
+  },
+  watch:{
+    currentTab(v){
+      this.refresh()
+    },
+    'searchForm.status'(){
+      this.refresh()
+    }
+  },
+
+  activated() {
+    this.initData()
+    this.getList()
+  },
+}
+</script>
+
+<style scoped lang="less">
+.popup-container{
+  position: fixed;
+  top: 5rem;
+  right: 0;
+  bottom: 0;
+  left: 0;
+  z-index: 10;
+  overflow: hidden;
+}
+
+/deep/ .van-dropdown-menu__title{
+  position: relative;
+  box-sizing: border-box;
+  max-width: 100%;
+  padding: 0 0.16rem;
+  color: #f8f8f8;
+  font-size: 0.3rem;
+  line-height: 0.44rem;
+}
+
+/deep/ .van-dropdown-menu__bar{
+  height: 0.8rem;
+  background-color: #26A2FF;
+}
+/deep/ .van-dropdown-menu{
+  border-bottom: 0;
+}
+
+.content-list{
+  margin-top: 0.2rem;
+  position: relative;
+  height: calc(100% - 1.5rem);
+}
+
+
+
+</style>

+ 97 - 26
src/point/view/integral/approval_detail.vue

@@ -95,40 +95,64 @@
         <div style="height: 3.5rem;"></div>
       </scroller>
       <!-- 审批者 ||  -->
-      <footer class="flex-box flex-v-ce footer" v-if="detail_info.can_refuse == '1'">
-        <div class="flex-2">撤回后需重新审批</div>
-        <van-button type="info" @click="revoke(1)" class="flex-1">撤回</van-button>
-      </footer>
+<!--      <footer class="flex-box flex-v-ce footer" v-if="detail_info.can_refuse === 1">-->
+<!--        <div class="flex-2">撤回后需重新审批</div>-->
+<!--        <van-button type="info" @click="revoke(1)" class="flex-1">撤回</van-button>-->
+<!--      </footer>-->
       <!-- 申请者 ||  -->
-      <footer class="flex-box flex-v-ce footer" v-if="detail_info.applyor_id==$userInfo().id&&detail_info.can_refuse == '1'&&(detail_info.source_type==2||detail_info.source_type==3)">
-        <div class="flex-2">撤销后数据将不可恢复</div>
-        <van-button type="info" @click="revoke(2)" class="flex-1">撤销</van-button>
+<!--      <footer class="flex-box flex-v-ce footer" v-if="detail_info.applyor_id==$userInfo().id&&detail_info.can_refuse === 1&&(detail_info.source_type===2||detail_info.source_type===3)">-->
+<!--        <div class="flex-2">撤销后数据将不可恢复</div>-->
+<!--        <van-button type="info" @click="revoke(2)" class="flex-1">撤销</van-button>-->
+<!--      </footer>-->
+      <footer class="flex-box flex-v-ce footer" v-if="canRefuse">
+        <van-button type="info" @click="revoke()" :loading="submitting" class="flex-1">撤回审批</van-button>
       </footer>
 
+
       <!-- 驳回弹窗 -->
       <van-popup v-model="show_refuse" position="right" :style="{ height: '100%', width: '100%', 'background-color': 'rgb(245, 245, 245)' }">
         <div :style="'padding-top:' + bar_height + 'px;background-color: #238dfa;'"></div>
-        <van-nav-bar title="确认驳回" left-text="返回" @click-left="show_refuse = false" left-arrow></van-nav-bar>
+        <van-nav-bar title="确认驳回" left-text="返回" @click-left="show_refuse = false" left-arrow></van-nav-bar>`
         <van-cell-group><van-field v-model="refuse_msg" rows="5" autosize type="textarea" maxlength="50" placeholder="请输入审批意见" show-word-limit /></van-cell-group>
-        <div style="padding:0.32rem;"><van-button block type="info" @click="confirm_refuse">确认驳回</van-button></div>
+        <div style="padding:0.32rem;"><van-button block type="info" :loading="submitting" @click="confirm_refuse">确认驳回</van-button></div>
+      </van-popup>
+
+      <van-popup v-model="showRejectRewrite" position="right" :style="{height:'100%',width:'100%', backgroundColor:'rgb(245, 245, 245)'}">
+        <div :style="'padding-top:' + bar_height + 'px;background-color: #238dfa;'"></div>
+        <van-nav-bar title="驳回重填" left-text="返回" @click-left="showRejectRewrite = false" left-arrow></van-nav-bar>`
+        <van-cell-group><van-field v-model="formRejectRewrite.remark" rows="5" autosize type="textarea" maxlength="100" placeholder="原因说明" show-word-limit /></van-cell-group>
+        <div style="padding:0.32rem;"><van-button block type="info" :loading="submitting" @click="rejectRewrite">确认</van-button></div>
       </van-popup>
+
     </div>
 
-    <van-row justify="center" type="flex" v-if="detail_info.can_complete == 1" class="footer">
-      <van-col :span="detail_info.source_type != 4 ? 8 : 0">
-        <div style="padding:0.16rem;">
-          <van-button block type="info" plain :disabled="detail_info.source_type == '4'" v-if="detail_info.source_type != 4" @click="refuse">驳回</van-button>
-        </div>
+<!--    <van-row justify="center" type="flex" v-if="detail_info.can_complete === 1" class="footer">-->
+<!--      <van-col :span="detail_info.source_type !== 4 ? 8 : 0">-->
+<!--        <div style="padding:0.16rem;">-->
+<!--          <van-button block type="info" plain :disabled="detail_info.source_type === 4" v-if="detail_info.source_type !== 4" @click="refuse">拒绝</van-button>-->
+<!--        </div>-->
+<!--      </van-col>-->
+<!--      <van-col :span="detail_info.source_type !== 4 ? 16 : 24">-->
+<!--        <div style="padding:0.16rem; padding-left:0;">-->
+<!--          <van-button block type="info" v-if="detail_info.source_type !== 4" @click="$router.push({ name: 'integralAudit', query: { review_id: detail_info.id } })">-->
+<!--            通过-->
+<!--          </van-button>-->
+<!--          <van-button block type="info" v-else @click="$router.push({ name: 'performanceAudit', query: { review_id: detail_info.id } })">-->
+<!--            通过-->
+<!--          </van-button>-->
+<!--        </div>-->
+<!--      </van-col>-->
+<!--    </van-row>-->
+    <van-row justify="space-around" gutter="10" type="flex" v-if="canComplete" class="footer" >
+      <van-col v-if="canReject" :span="8">
+        <van-button block plain :loading="submitting" @click="refuse" >拒绝</van-button>
       </van-col>
-      <van-col :span="detail_info.source_type != 4 ? 16 : 24">
-        <div style="padding:0.16rem; padding-left:0;">
-          <van-button block type="info" v-if="detail_info.source_type != '4'" @click="$router.push({ name: 'integralAudit', query: { review_id: detail_info.id } })">
-            通过
-          </van-button>
-          <van-button block type="info" v-else @click="$router.push({ name: 'performanceAudit', query: { review_id: detail_info.id } })">
-            通过
-          </van-button>
-        </div>
+      <van-col v-if="canRejectRewrite" :span="8">
+        <van-button block  plain type="warning" :loading="submitting" @click="showRejectRewrite = true" >驳回重填</van-button>
+      </van-col>
+      <van-col :span="canRejectRewrite ? 8 : 16">
+        <van-button block type="info" v-if="detail_info.source_type !== 4" @click="$router.push({ name: 'integralAudit', query: { review_id: detail_info.id } })" :loading="submitting" >通过</van-button>
+        <van-button block type="info" v-else @click="$router.push({ name: 'performanceAudit', query: { review_id: detail_info.id } })" :loading="submitting" ></van-button>
       </van-col>
     </van-row>
 
@@ -139,6 +163,7 @@
 import Vue from 'vue'
 import approvalProcess from '@/point/view/integral/approval_process'
 import { Dialog, Panel, Step, Steps, Overlay, ImagePreview } from 'vant'
+import Footer from "../../../components/footer.vue";
 Vue.use(Dialog)
   .use(Panel)
   .use(Step)
@@ -147,9 +172,10 @@ Vue.use(Dialog)
   .use(ImagePreview)
 export default {
   // 数据
-  components: { approvalProcess },
+  components: {Footer, approvalProcess },
   data () {
     return {
+      userInfo:this.$userInfo(),
       imageSrc: [],
       show: false,
       title: '审批详情',
@@ -177,6 +203,11 @@ export default {
       adopt_two: false,
       types_list: {},
       isHome:false,//微信信息点击进来
+      showRejectRewrite:false,
+      formRejectRewrite:{
+        remark:''
+      },
+      submitting:false,
     }
   },
   watch: {
@@ -320,7 +351,7 @@ export default {
       let self = this
       Dialog.confirm({
         title: '提示',
-        message: '您确定要' + str + '此项吗?'
+        message: '确定要撤回此项吗?'
       })
         .then(() => {
           self.showLoading()
@@ -343,11 +374,33 @@ export default {
         .catch(() => {
           // on cancel
         })
+    },
+    rejectRewrite(){
+      let self = this
+      this.submitting = true
+      self.showLoading()
+      let params = {
+        review_id:self.detail_info.id,
+        remark:self.formRejectRewrite.remark || ''
+      }
+      self.$axiosUser('post','/api/pro/integral/review/reject/rewrite',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.get_info()
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.$toast.clear()
+          self.showRejectRewrite = false
+          self.submitting = false
+        })
     }
   },
   created () {
     this.get_point_types()
-    
+
     if (window.plus) {
       this.bar_height = window.plus.navigator.getStatusbarHeight()
     }
@@ -368,6 +421,24 @@ export default {
       this.isHome = false;
     }
   },
+  computed:{
+    isFirstStep(){
+      return this.detail_info && ((this.detail_info.pid === 0 && this.detail_info.step === 0) || this.detail_info.step === 1)
+    },
+    canComplete(){
+      return this.detail_info && this.detail_info.can_complete === 1
+    },
+    canRefuse(){
+      return this.detail_info && this.detail_info.can_refuse === 1
+    },
+    canRejectRewrite(){
+      return this.canComplete && this.detail_info.source_type === 1
+    },
+    canReject(){
+      return this.canComplete && this.detail_info.source_type !== 4
+    }
+
+  }
 }
 </script>
 <style scoped lang="less">

+ 35 - 14
src/point/view/integral/approval_list.vue

@@ -32,11 +32,10 @@
               <userImage :user_name="item.employee_name" v-if="item.source_type == 1 || item.source_type == 4" width="0.72rem" height="0.72rem" />
               <userImage :user_name="item.employee_name" v-if="item.source_type == 2 || item.source_type == 3" width="0.72rem" height="0.72rem" />
               <div class="task-title__bar">
-                <span class="title" v-show="item.source_type == 1">{{ item.employee_name }}的积分任务</span>
-                <span class="title" v-show="item.source_type == 2">{{ item.employee_name }}的积分申请</span>
-                <span class="title" v-show="item.source_type == 3">{{ item.employee_name }}的积分奖扣</span>
-                <!-- <span class="title" v-show="item.source_type == 4">{{item.employee_name}}的绩效工作</span> -->
-                <!-- <span class="title" v-show="item.source_type == 4">{{item.employee_name}}提交的绩效工作包</span> -->
+                <span class="title">
+                  {{item.employee_name}}
+                  &nbsp;<van-tag type="primary">{{sourceTypeMap[item.source_type] || '--'}}</van-tag>
+                </span>
                 <span v-if="filter.type === 'reviewed' && item.status !== 0 && item.status !== 2">
                   <span class="task-item__point red" v-if="item.review_point >= 0">+{{ item.review_point }}{{ $getTypesName(item.pt_id) }}</span>
                   <span class="task-item__point green" v-else>{{ item.review_point }}{{ $getTypesName(item.pt_id) }}</span>
@@ -45,12 +44,12 @@
             </div>
 
             <div class="task-remark__content">
-              <span>{{ item.remark.customize }}</span>
+              <span class="input-ccc">{{ item.remark.customize }}</span>
             </div>
             <div class="task-item__bottom" v-if="item.status == 0">
               <span class="task-item__date">{{ item.event_time }}</span>
               <span class="task-item__toolbar" v-if="item.status === 0">
-                <span v-show="item.source_type != 4" @click.stop="reject(item)">驳回</span>
+                <span v-show="item.source_type != 4" @click.stop="reject(item)">拒绝</span>
                 <div class="divider"></div>
                 <span v-if="item.source_type == '1'" @click.stop="$router.push({ name: 'integralAudit', query: { review_id: item.id } })">通过</span>
                 <span v-if="item.source_type == '2'" @click.stop="$router.push({ name: 'integralAudit', query: { review_id: item.id } })">通过</span>
@@ -65,8 +64,7 @@
             <div class="task-item__bottom" v-else>
               <span class="task-item__date">{{ item.event_time }}</span>
               <span class="task-item__toolbar">
-                <span class="green" v-if="item.status == 1">审批通过</span>
-                <span class="red" v-if="item.status == 2">审批驳回</span>
+                <van-tag :type="statusType(item.review_status)" mark size="medium" >{{statusMap[item.review_status] || '--'}}</van-tag>
               </span>
             </div>
           </div>
@@ -117,7 +115,7 @@ export default {
       reject_text: '',
 
       // 0411
-      tabsOption: [{ title: '待我审批', value: 'waiting' }, { title: '我已审批', value: 'reviewed' }],
+      tabsOption: [{ title: '待审批', value: 'waiting' }, { title: '参与审批', value: 'reviewed' }],
       screen_list: [
         {
           title: '任务类型',
@@ -130,7 +128,19 @@ export default {
             // {name: '绩效工作', id: '4'}
           ]
         }
-      ]
+      ],
+      statusMap:{
+        0:'待审核',
+        1:'审核通过',
+        2:'拒绝',
+        3:'驳回重填',
+        4:'重填',
+      },
+      sourceTypeMap:{
+        1:'积分任务',
+        2:'积分申请',
+        3:'积分奖扣',
+      }
     };
   },
   components: { TabsList },
@@ -153,7 +163,7 @@ export default {
     }
   },
   activated() {
-  	 this.onRefresh({ pageIndex: 1, isRefresh: true });
+  	this.onRefresh({ pageIndex: 1, isRefresh: true });
   },
   methods: {
     openBatch() {
@@ -271,7 +281,18 @@ export default {
       } else {
         done();
       }
-    }
+    },
+    statusType(status){
+      if (status === -1) return 'info'
+      const map = {
+        0:'warning',
+        1:'success',
+        2:'danger',
+        3:'danger',
+        4:'primary',
+      }
+      return map[status] || 'info'
+    },
   },
 };
 </script>
@@ -349,7 +370,7 @@ export default {
   .task-remark__content {
     display: -webkit-box;
     padding-left: 0.92rem;
-    font-size: 0.32rem;
+    font-size: 0.3rem;
     color: #333;
     text-overflow: ellipsis;
     overflow: hidden;

+ 27 - 5
src/point/view/integral/approval_process.vue

@@ -12,10 +12,12 @@
         <userImage :user_name="item.name" :id="0" :img_url="item.img_url"></userImage>
       </template>
       <template slot="title">
-        <span class="process-item__remark" v-if="item.remark == '申请人'">{{ item.remark }}</span>
-        <span class="process-item__remark" v-else :class="{orange:item.remark == '待审核',green:item.remark == '审核通过',red:item.remark == '审核驳回','color-FF9600': item.remark == '待处理','color-F56C6C':item.remark == '驳回'}">
-          {{ item.remark }}
-        </span>
+        <span v-if="item.step > 0">阶段{{item.step}}</span>
+        <van-tag :type="processStatusType(item.status)" size="medium" mark>{{processStatusMap[item.status] || '--'}}</van-tag>
+<!--        <span class="process-item__remark" v-if="item.remark == '申请人'">{{ item.remark }}</span>-->
+<!--        <span class="process-item__remark" v-else :class="{orange:item.remark == '待审核',green:item.remark == '审核通过',red:item.remark == '审核驳回','color-FF9600': item.remark == '待处理','color-F56C6C':item.remark == '驳回'}">-->
+<!--          {{ item.remark }}-->
+<!--        </span>-->
       </template>
       <template slot="right-icon">
         <span class="red" v-if="item.review_point > 0">+{{ item.review_point }}</span>
@@ -46,7 +48,16 @@ export default {
     }
   },
   data() {
-    return {};
+    return {
+      processStatusMap:{
+        '-1':'发起',
+        0:'待审核',
+        1:'审核通过',
+        2:'拒绝',
+        3:'驳回重填',
+        4:'重填',
+      }
+    };
   },
   methods: {
     getIconText(employeeName) {
@@ -55,6 +66,17 @@ export default {
         return employeeName[len - 2] + employeeName[len - 1];
       }
       return employeeName;
+    },
+    processStatusType(status){
+      if (status === -1) return 'primary'
+      const map = {
+        0:'warning',
+        1:'success',
+        2:'danger',
+        3:'danger',
+        4:'primary',
+      }
+      return map[status] || 'info'
     }
   }
 };

+ 94 - 6
src/point/view/integral/event_detail.vue

@@ -82,12 +82,43 @@
         <div style="height: 1.5rem;"></div>
       </scroller>
 
-      <!-- 奖扣者 ||  -->
-      <footer class="flex-box flex-v-ce footer" v-if="eventInfo.recorder_id == $userInfo().id && eventInfo.process.length == 1 && (eventInfo.event_type == 3 || eventInfo.event_type == 4)">
-        <div class="flex-2">撤销后数据将不可恢复</div>
-        <van-button type="info" @click="revocation()" class="flex-1">撤销</van-button>
+      <footer class="footer">
+        <van-row type="flex" justify="center">
+          <!--    发起申诉    -->
+          <van-col span="24" v-if="appealEnable">
+            <van-button type="info" block @click="showAppeal = true">申诉</van-button>
+          </van-col>
+          <!-- 奖扣者 ||  -->
+          <van-col span="24" v-else-if="eventInfo.recorder_id == $userInfo().id && eventInfo.process.length == 1 && (eventInfo.event_type == 3 || eventInfo.event_type == 4)">
+            <van-button type="info" @click="revocation()" block>撤销</van-button>
+          </van-col>
+        </van-row>
       </footer>
     </div>
+    <van-popup v-model="showAppeal" position="bottom" :style="{height:'100%',width:'100%',backgroundColor:'rgb(245, 245, 245)'}">
+      <div :style="'padding-top:' + barHeight + 'px;background-color: #238dfa;'"></div>
+      <van-nav-bar title="发起申诉" left-text="返回" @click-left="showAppeal = false" left-arrow></van-nav-bar>`
+      <van-cell-group>
+        <EmployeeSelectorCell
+          title="审批人"
+          v-model="appealForm.reviewer"
+          :multi="false"
+          iconType="records"
+          :employee_list="userInfo.employee_detail.superior_list"
+          :is_employee_list="true"
+        />
+        <van-cell>
+          <Mtextarea
+            v-model="appealForm.remark"
+            placeholder="申诉原因"
+          />
+        </van-cell>
+      </van-cell-group>
+      <footer class="flex-box flex-v-ce footer">
+        <van-button type="info" block :loading="submitting" :disabled="!canAppealSubmit" @click="createAppeal">提交</van-button>
+      </footer>
+
+    </van-popup>
   </div>
 </template>
 
@@ -95,6 +126,9 @@
 import approval_process from '@/point/view/integral/approval_process'
 import Vue from 'vue'
 import { Panel, Skeleton, Image, ImagePreview, Dialog } from 'vant'
+import Footer from "../../../components/footer.vue";
+import EmployeeSelectorCell from "../../../components/EmployeeSelectorCell.vue";
+import Mtextarea from "../../../components/Mtextarea2.vue";
 
 Vue.use(Panel)
   .use(Skeleton)
@@ -103,12 +137,21 @@ Vue.use(Panel)
   .use(Dialog)
 export default {
   name: 'event_detail_info',
-  components: {approval_process },
+  components: {Mtextarea, EmployeeSelectorCell, Footer, approval_process },
   data () {
     return {
+      userInfo:this.$userInfo(),
       loading: true,
       eventInfo: { remark: { customize: '' }, process: [] },
       deptName:'',
+      siteAppealEnable: false,
+      showAppeal: false,
+      barHeight:'',
+      appealForm:{
+        reviewer:[],
+        remark:''
+      },
+      submitting:false
     }
   },
   computed: {
@@ -117,15 +160,30 @@ export default {
     },
     hasAttachmentFile () {
       return Array.isArray(this.eventInfo.files) && this.eventInfo.files.length > 0
+    },
+    appealEnable(){
+      return this.eventInfo && this.userInfo && this.siteAppealEnable && this.eventInfo.employee_id === this.userInfo.id
+    },
+    canAppealSubmit(){
+      return this.appealEnable && this.appealForm.reviewer.length === 1 && !this.submitting
     }
   },
   methods: {
+    getConfig(){
+      let self = this
+      self.$axiosUser('get','/api/pro/integral/site/config')
+        .then(res => {
+          if (res.data.code === 1){
+            self.siteAppealEnable = res.data.data.appeal === 1
+          }
+        })
+    },
     // 撤销奖扣
     revocation () {
       var that = this
       Dialog.confirm({
         title: '提示',
-        message: '您确定要撤销此项吗?'
+        message: '撤销后数据将不可恢复,确定要撤销此项吗?'
       }).then(() => {
         let data = { target_id: this.$route.query.id, type: 1}
         this.$axiosUser('post', '/api/pro/integral/review/prize/destroy', data).then(res => {
@@ -165,10 +223,40 @@ export default {
           this.$toast.clear()
           this.loading = false
         })
+    },
+    createAppeal(){
+      let self = this
+      self.submitting = true
+      self.$toast.loading({message:'提交中...'})
+      let params = {
+        reviewer_id:self.appealForm.reviewer[0].id,
+        events:[{id:self.eventInfo.event_id,remark:self.appealForm.remark}]
+      }
+      self.$axiosUser('post','api/pro/integral/appeal/create',params)
+        .then(res => {
+          if (res.data.code === 1){
+            self.appealForm.reviewer = []
+            self.appealForm.remark = ''
+            self.$toast('复议已发起')
+            self.showAppeal = false
+          }else {
+            self.$toast(res.data.msg)
+          }
+        })
+        .finally(() => {
+          self.$toast.clear()
+          self.submitting = false
+        })
+    }
+  },
+  created() {
+    if (window.plus){
+      this.barHeight = window.plus.navigator.getStatusbarHeight()
     }
   },
   mounted () {
     this.getEventDetail()
+    this.getConfig()
   }
 }
 </script>

+ 16 - 4
src/point/view/integral/event_list.vue

@@ -28,7 +28,7 @@
               <span class="event-item__value red" v-if="item.point >= 0">+{{ item.point }}{{ $getTypesName(item.pt_id)}}</span>
               <span class="event-item__value green" v-else>{{ item.point }}{{ $getTypesName(item.pt_id) }}</span>
             </div>
-            <div class="event-content__text">
+            <div class="event-content__text input-ccc">
               <span>{{ item.remark }}</span>
             </div>
             <div class="event-time__text">
@@ -68,6 +68,7 @@ export default {
       dateItemTitle: '本月',
       deptDropdownItemTitle: '全公司',
       eventData: [],
+      hasFinish: false,
       searchParams: {
         dept_ids: null,
         end_day: null,
@@ -151,9 +152,15 @@ export default {
     },
     refresh(done) {
       this.searchParams.page = 1;
+      this.hasFinish = false
       this.getEventData(done);
     },
     infinite(done) {
+      if (this.hasFinish){
+        done()
+        this.$refs.scroller.finishPullToRefresh()
+        return
+      }
       this.searchParams.page++;
       this.getEventData(done);
     },
@@ -232,14 +239,19 @@ export default {
             } else {
               this.eventData = this.eventData.concat(list);
             }
-            scroller.finishInfinite(list.length !== this.searchParams.page_size);
+            callback && callback();
+            scroller.finishPullToRefresh();
+
+            this.hasFinish = list.length !== this.searchParams.page_size
+
+            scroller.finishInfinite(this.hasFinish);
           } else {
-            scroller.finishInfinite(true);
+            this.hasFinish = true
+            scroller.finishInfinite(this.hasFinish);
           }
         })
         .finally(() => {
           this.loading = false;
-          callback && callback();
         });
     }
   },

+ 9 - 1
src/point/view/pointHome.vue

@@ -46,13 +46,18 @@
               <img :src="app.icon" style="-webkit-touch-callout: none;" />
             </template>
           </van-grid-item>
+          <van-grid-item @click="goAppeal" text="申诉">
+            <template #icon>
+              <img src="static/images/caback6.png" style="-webkit-touch-callout: none;"/>
+            </template>
+          </van-grid-item>
           <van-grid-item @click="goDeptRank">
             <template #text>
               <van-loading v-if="!deptRank" type="spinner" size="10px"/>
               <span class="van-grid-item__text" v-else>部门对比</span>
             </template>
             <template #icon>
-              <img src="static/images/daiban.png" style="-webkit-touch-callout: none;"/>
+              <img src="static/images/callback1.png" style="-webkit-touch-callout: none;"/>
             </template>
           </van-grid-item>
 
@@ -715,6 +720,9 @@ export default {
     goDeptRank(){
       if (!this.deptRank) return;
       this.$router.push({ name: 'dept_rank' });
+    },
+    goAppeal(){
+      this.$router.push({name:'appeal'})
     }
   },
   watch: {

+ 3 - 2
src/point/view/task/my_task.vue

@@ -176,13 +176,14 @@ export default {
       activeNames: '2',
       filter: {
         page: 1,
-        status: 'running',
+        status: 'rewrite',
         sort: 'publish',
         source_type: 0,
         pt_id: 0,
         page_size:20,
       },
       tabsOption: [
+        { title: '驳回重做', value: 'rewrite' },
         { title: '待完成', value: 'running' },
         { title: '待审批', value: 'complete' },
         { title: '已审批', value: 'reviewed' }
@@ -251,7 +252,7 @@ export default {
       }
     },
     onRefresh (params) {
-      if(this.filter.status=='running'){
+      if(this.filter.status === 'running'){
         this.getToDay(false,params.done)
       }else{
         this.get_list(false,params.done)

+ 16 - 10
src/point/view/task/taskFile.vue

@@ -34,7 +34,7 @@
             </div>
           </template>
         </van-cell>
-        <van-cell-group :border="false" class="task_detail_group" v-if="info.review_status == 2">
+        <van-cell-group :border="false" class="task_detail_group" v-if="info.review_status === 2">
           <van-cell :border="false">
             <template slot="title">
               <div class="time">
@@ -195,6 +195,7 @@
             </van-slider>
           </div>
         </van-panel>
+
         <div class="task">
           <van-row>
             <van-col span="16">
@@ -204,8 +205,8 @@
               </van-tabs>
             </van-col>
             <van-col span="8" style="background:#fff;border-bottom:0.02rem #efefef solid;">
-              <div v-if="active == 0 && info.employee_id == $userInfo().id && info.status < 3" @click="remberOne" class="rember">+记一条</div>
-              <div v-if="active != 0 && isShowJf" @click="noteone" class="rember">记分</div>
+              <div v-if="active === 0 && canUpdate" @click="remberOne" class="rember">+记一条</div>
+              <div v-if="active !== 0 && isShowJf" @click="noteone" class="rember">记分</div>
             </van-col>
           </van-row>
           <div ref="scoringNotice" style="clear: both;">
@@ -217,7 +218,7 @@
           <van-cell-group
             v-if="info.process !== null && info.process.list !== null"
             v-for="(item, index) in info.process.list"
-            :key="index"
+            :key="'record' + index"
             v-show="active == 0 && item.point == 0"
             :border="false"
           >
@@ -257,7 +258,7 @@
           <van-cell-group
             v-if="info.process !== null && info.process.list !== null"
             v-for="(item, index) in info.process.list"
-            :key="index"
+            :key="'point' + index"
             v-show="info.process.list !== null && active != 0 && item.point != 0"
             :border="false"
           >
@@ -297,7 +298,6 @@
           <van-cell-group style="background: none;" v-show="active != 0 && point_list.length == 0">
             <noTask src="static/images/noTask.png" detail_text="还没有记分记录去记一条吧" />
           </van-cell-group>
-
         </div>
 
         <div v-if="text_list.length != 0 || point_list.length != 0" style="height: 2rem;"></div>
@@ -307,7 +307,7 @@
       <div style="padding:0.32rem;width: 90%;position: fixed;bottom: 0;" v-if="info.reviewer_id == $userInfo().id && info.status == 2&&!isShowSp">
         <van-button block type="info" @click="go_approval">去审批</van-button>
       </div>
-      <div style="padding:0.32rem;width: 90%;position: fixed;bottom: 0;" v-if="info.employee_id == $userInfo().id && info.status == 1&&!isShowSp">
+      <div style="padding:0.4rem;width: 90%;position: fixed;bottom: 0; background-color: white;" v-if="canUpdate&&!isShowSp">
         <van-button block type="info" @click="complete_task(info)">完成</van-button>
       </div>
     </div>
@@ -335,6 +335,7 @@ export default {
   // 数据
   data () {
     return {
+      userInfo:this.$userInfo(),
       The_current_account: false,
       active: 0,
       numberslider: 0,
@@ -550,16 +551,16 @@ export default {
       }
     },
     keepTheScore(data){
-      if(data.status > 2){
+      if(![1,2,6].includes(data.status)){
         return false
       }
-      if(this.$userInfo().id == data.reviewer_id){
+      if(this.userInfo.id === data.reviewer_id){
         return true
       }
       let info=this.$getEmployeeMapItem(data.employee_id)
       if(info){
         return info.employee_detail.superior_list.some(x =>{
-          if(this.$userInfo().id == x.id){
+          if(this.userInfo.id === x.id){
             return true
           }
         })
@@ -632,6 +633,11 @@ export default {
       })
     }
   },
+  computed:{
+    canUpdate(){
+      return this.info.employee_id === this.userInfo.id && [1,6].includes(this.info.status)
+    }
+  },
   mounted () {
     this.getLocalStorage()
   },

+ 7 - 0
src/router/pointRoute.js

@@ -484,6 +484,13 @@ const routes = [
     component: () => import('@/point/view/integral/deptRank'),
     label: '部门排行',
     need_login: true
+  },
+  {
+    path: '/appeal',
+    name: 'appeal',
+    component: () => import('@/point/view/integral/appealList'),
+    label: '申诉列表',
+    need_login: true
   }
 ]
 export default routes

+ 3 - 1
src/utils/validator.js

@@ -15,7 +15,9 @@ Vue.use(VeeValidate, {
   events: 'change',
   dictionary: {
     zh_CN
-  }
+  },
+  errorBagName: 'errorBags',      //解决The computed property "fields" is already defined in data的问题
+  fieldsBagName: 'fieldBags',     //解决The computed property "fields" is already defined in data的问题
 })
 
 const dictionary = {

+ 1 - 1
src/view/user/login.vue

@@ -425,7 +425,7 @@ export default {
                 //     console.log("苹果软件用户没有创建公司");
                 //   }
                 // }
-                console.log(res.data.account_site);
+                // console.log(res.data.account_site);
                 this.openUrl2(
                   res.data.account_site,
                   res.data.invitation_wait_count