123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742 |
- <template>
- <div v-loading="loading">
- <el-container v-if="appealInfo">
- <el-main class="detail_popup">
- <!-- 基础信息 -->
- <el-card shadow="always" class="appeal_content">
- <template slot="header">
- <userImage
- :user_name="appealInfo.employee_name"
- :img_url="appealInfo.employee_img_url"
- class="fl"
- width="50px"
- height="50px"
- fontSize="15"
- />
- <span style="line-height: 50px; margin-left:10px;margin-right:4px;">{{appealInfo.employee_name}}</span>
- <el-tag :type="appealStatusType(appealInfo.status)">{{appealStatusMap[appealInfo.status] || '--'}}</el-tag>
- </template>
- <div>
- <p><el-tag>{{appealInfo.create_time}}</el-tag> 发起申诉</p>
- <p>共 <el-tag>{{appealInfo.events.length}}</el-tag> 条积分事件</p>
- <div v-if="appealInfo.global_remark">
- <p>申请原因:</p>
- <el-alert
- :title="appealInfo.global_remark"
- type="info"
- :closable="false"
- />
- </div>
- <template v-if="appealInfo.complete_time">
- <p><el-tag>{{appealInfo.complete_time}}</el-tag> 审批结束</p>
- </template>
- </div>
- </el-card>
- <!-- 审批流程 -->
- <div class="process">
- <h5>审批流程</h5>
- <el-steps direction="vertical" :space="50" >
- <el-step v-for="(item, index) in appealInfo.process" :key="index" style="margin-bottom: 5px;">
- <template slot="icon">
- <userImage width="36px" height="36px" :img_url="item.reviewer_img_url" :user_name="item.reviewer_name"></userImage>
- </template>
- <template slot="title">
- 阶段{{item.step}}
- <el-tag :type="processStatusType(item.status)">{{processStatusMap[item.status] || '--'}}</el-tag>
- </template>
- <template slot="description">
- <el-descriptions :column="2" direction="vertical" size="small" :label-style="{width:'80px'}" border>
- <el-descriptions-item label="发起人">{{item.publisher_name}}</el-descriptions-item>
- <el-descriptions-item label="发起时间">{{item.create_time}}</el-descriptions-item>
- <el-descriptions-item label="审批人">{{item.reviewer_name}}</el-descriptions-item>
- <el-descriptions-item label="审批意见" v-if="item.remark" >
- <el-alert
- :closable="false"
- :title="item.remark"
- type="info"
- />
- </el-descriptions-item>
- <el-descriptions-item label="完结时间" v-if="item.complete_time" >{{item.complete_time}}</el-descriptions-item>
- </el-descriptions>
- </template>
- </el-step>
- </el-steps>
- </div>
- <!-- 隐藏信息 -->
- <el-collapse v-model="infoActiveNames">
- <el-collapse-item :title="appealInfo.events.length + '条积分事件'" name="events" >
- <el-descriptions class="detail_row" v-for="(item,index) in appealInfo.events" size="small" :key="index" :column="1" :label-style="{width : '80px'}" border>
- <el-descriptions-item label="积分">
- {{item.point + ' ' + ptName(item.pt_id)}}
- <el-tag :type="pointStatusType(item.status)" v-if="pointStatusMap[item.status]">{{pointStatusMap[item.status]}}</el-tag>
- </el-descriptions-item>
- <el-descriptions-item label="积分备注">
- <el-alert
- :title="item.event_remark"
- :closable="false"
- type="success"
- />
- </el-descriptions-item>
- <el-descriptions-item label="时间">{{item.event_time}}</el-descriptions-item>
- <el-descriptions-item v-if="item.appeal_remark" label="申诉原因">{{item.appeal_remark}}</el-descriptions-item>
- <el-descriptions-item v-if="item.delete_time" label="已删除">{{item.delete_time}}</el-descriptions-item>
- </el-descriptions>
- </el-collapse-item>
- <el-collapse-item :title="appealInfo.logs.length + '条操作日志'" name="logs">
- <el-alert
- v-for="(item,index) in appealInfo.logs"
- :key="index"
- type="info"
- show-icon
- :title="item.create_time + ' ' + item.msg"
- :closable="false"
- />
- </el-collapse-item>
- </el-collapse>
- </el-main>
- <el-footer class="appeal_footer flex-box-end flex-v-ce" height="60" >
- <el-popconfirm
- v-if="appealInfo.can_delete"
- title="删除申诉后将不可恢复,确认提交吗"
- confirm-button-text="提交"
- cancel-button-text="取消"
- icon="el-icon-question"
- icon-color="red"
- @confirm="removeAppeal"
- style="margin: 0 10px"
- >
- <el-button type="danger" size="mini" slot="reference" :loading="submitting || !hasOpen" >删除申诉</el-button>
- </el-popconfirm>
- <el-button type="danger" size="mini" v-if="appealInfo.can_refuse" @click="showReviewRefuse = true" :loading="submitting || !hasOpen">拒绝</el-button>
- <el-button type="warning" size="mini" v-if="appealInfo.can_reject_rewrite" @click="showReviewRejectRewrite = true" :loading="submitting || !hasOpen">驳回重做</el-button>
- <el-popconfirm
- v-if="appealInfo.can_cancel"
- title="审批撤回后可以重新编辑内容重新提交"
- confirm-button-text="提交"
- cancel-button-text="取消"
- icon="el-icon-question"
- icon-color="red"
- @confirm="reviewCancel"
- style="margin: 0 10px"
- >
- <el-button type="info" size="mini" slot="reference" :loading="submitting || !hasOpen">撤回审批</el-button>
- </el-popconfirm>
- <el-popconfirm
- v-if="appealInfo.can_cancel_appeal"
- title="申诉撤回后可以重新编辑内容重新提交"
- confirm-button-text="提交"
- cancel-button-text="取消"
- icon="el-icon-question"
- icon-color="red"
- @confirm="cancelAppeal"
- style="margin: 0 10px"
- >
- <el-button type="info" size="mini" slot="reference" :loading="submitting || !hasOpen" >撤回申诉</el-button>
- </el-popconfirm>
- <el-button type="success" size="mini" v-if="appealInfo.can_rewrite" :loading="submitting || !hasOpen" @click="openRewrite">重新填写</el-button>
- <el-button type="success" size="mini" v-if="appealInfo.can_submit" @click="showReviewSubmit = true" :loading="submitting || !hasOpen">递交审批</el-button>
- <el-button type="primary" size="mini" v-if="appealInfo.can_approval" @click="showReviewApproval = true" :loading="submitting || !hasOpen">通过</el-button>
- </el-footer>
- </el-container>
- <noData class="center" v-else />
- <!-- 拒绝审批 -->
- <el-dialog
- title="拒绝审批"
- :visible.sync="showReviewRefuse"
- :modal="false"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :center="true"
- :show-close="false"
- width="600px"
- >
- <template>
- <el-form v-model="formData">
- <el-form-item >
- <el-input
- type="textarea"
- :rows="3"
- :autosize="true"
- :clearable="true"
- :maxlength="100"
- :show-word-limit="true"
- placeholder="原因说明"
- v-model="formData.remark"
- @input="onFormRemarkInput"
- />
- </el-form-item>
- </el-form>
- </template>
- <template slot="footer">
- <div class="flex-box-end flex-v-ce">
- <el-button type="danger" @click="formData.remark = '',showReviewRefuse = false">关闭</el-button>
- <el-button type="primary" @click="reviewRefuse" :disabled="!canConfirmReviewRefuse" :loading="submitting || !showReviewRefuse || !hasOpen" >确认</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 驳回重做 -->
- <el-dialog
- title="驳回重做"
- :visible.sync="showReviewRejectRewrite"
- :modal="false"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :center="true"
- :show-close="false"
- width="600px"
- >
- <template>
- <el-form v-model="formData">
- <el-form-item >
- <el-input
- type="textarea"
- :rows="3"
- :autosize="true"
- :clearable="true"
- :maxlength="100"
- :show-word-limit="true"
- placeholder="原因说明"
- v-model="formData.remark"
- @input="onFormRemarkInput"
- />
- </el-form-item>
- </el-form>
- </template>
- <template slot="footer">
- <div class="flex-box-end flex-v-ce">
- <el-button type="danger" @click="formData.remark = '',showReviewRejectRewrite = false">关闭</el-button>
- <el-button type="primary" @click="reviewRejectRewrite" :disabled="!canConfirmReviewRejectRewrite" :loading="submitting || !showReviewRejectRewrite || !hasOpen">确认</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 重新填写 -->
- <AppealRewrite
- :visible.sync="showRewrite"
- :id="id"
- @rewriteFinish="onAppRewriteFinish"
- />
- <!-- 递交审批 -->
- <el-dialog
- title="递交审批"
- width="600px"
- :visible.sync="showReviewSubmit"
- :modal="false"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :center="true"
- :show-close="false"
- >
- <template>
- <el-form v-model="formData">
- <el-form-item>
- <el-input class="w250" auto-complete="off" v-model="formData.reviewerName" placeholder="请选择审批人" />
- <div @click="showReviewerSelector = true" style=" position: absolute; top: 0; right: 0; left: 0; bottom: 0; z-index: 9;"></div>
- <EmployeeSelector
- :multi="false"
- :user_employee_list="true"
- :isChecKedAll="false"
- :is_filtration_creator="false"
- :employee_list="superiorList"
- :selected="formData.employeeSelected"
- :visible.sync="showReviewerSelector"
- @confirm="handleReviewerSelector"
- />
- </el-form-item>
- <el-form-item>
- <el-input
- type="textarea"
- :autosize="true"
- :clearable="true"
- :maxlength="100"
- :show-word-limit="true"
- placeholder="请填写原因说明"
- v-model="formData.remark"
- @input="onFormRemarkInput"
- />
- </el-form-item>
- </el-form>
- </template>
- <template slot="footer">
- <div class="flex-box-end flex-v-ce">
- <el-button @click="formData.remark = '',formData.reviewerId = 0,formData.reviewerName = '',formData.employeeSelected = { dept: [], employee: [] },showReviewSubmit = false">关闭</el-button>
- <el-button type="primary" @click="reviewSubmit" :disabled="!canConfirmReviewSubmit" :loading="submitting || !showReviewSubmit || !hasOpen" >确认</el-button>
- </div>
- </template>
- </el-dialog>
- <!-- 通过 -->
- <el-dialog
- title="通过"
- :visible.sync="showReviewApproval"
- :modal="false"
- :close-on-click-modal="false"
- :close-on-press-escape="false"
- :center="true"
- :show-close="false"
- width="600px"
- >
- <template>
- <el-form v-model="formData">
- <el-form-item >
- <el-input
- type="textarea"
- :rows="3"
- :autosize="true"
- :clearable="true"
- :maxlength="100"
- :show-word-limit="true"
- placeholder="原因说明"
- v-model="formData.remark"
- @input="onFormRemarkInput"
- />
- </el-form-item>
- </el-form>
- </template>
- <template slot="footer">
- <div class="flex-box-end flex-v-ce">
- <el-button type="danger" @click="formData.remark = '',showReviewApproval = false">关闭</el-button>
- <el-button type="primary" @click="reviewApproval" :disabled="!canConfirmReviewApproval" :loading="submitting || !showReviewApproval || !hasOpen">确认</el-button>
- </div>
- </template>
- </el-dialog>
- </div>
- </template>
- <script>
- import Template from "../../../examine/components/Template.vue";
- import EmployeeSelector from "../../../components/EmployeeSelector.vue";
- import AppealRewrite from "../../../components/AppealRewrite.vue";
- import {specialFilter} from "../../../utils";
- export default {
- name:'appealPopup',
- components: {AppealRewrite, Template,EmployeeSelector},
- props:{
- id:{
- type: Number,
- default:0
- }
- },
- data() {
- return {
- userInfo: this.$userInfo(),
- hasOpen:false,
- hasSubmit:false, //标识复议记录是否有提交操作,用来通知父组件如果有需要的话
- loading:false,
- appealInfo:null,
- superiorList:[],
- infoActiveNames:[],
- eventSelected:[],
- appealStatusMap:{
- 0:'全部',
- 1:'审批中',
- 2:'审批通过',
- 3:'驳回重做',
- 4:'撤回重填',
- 5:'拒绝'
- },
- pointStatusMap:{
- 1:'正常',
- 2:'已删除',
- 3:'已通过申诉并删除'
- },
- processStatusMap:{
- 1:'待处理',
- 2:'审批通过',
- 3:'递交审批',
- 4:'拒绝',
- 5:'驳回重做',
- 6:'撤回上个节点重填',
- 7:'申诉撤回',
- },
- pts:[],
- formData:{
- reviewerId:0,
- reviewerName:'',
- remark:'',
- employeeSelected: { dept: [], employee: [] },
- },
- rewriteData:{
- events:[],
- globalRemark:'',
- reviewerId:'',
- reviewerName:'',
- employeeSelected: { dept: [], employee: [] },
- },
- showReviewRefuse:false,
- showReviewRejectRewrite:false,
- showReviewApproval:false,
- showReviewerSelector:false,
- showReviewSubmit:false,
- submitting:false,
- showEventSelector:false,
- showRewrite:false,
- }
- },
- watch:{
- },
- computed:{
- canConfirmReviewSubmit(){
- return this.appealInfo && this.appealInfo.can_submit && this.formData.reviewerId && this.showReviewSubmit
- },
- canConfirmReviewApproval(){
- return this.appealInfo && this.appealInfo.can_approval && this.showReviewApproval
- },
- canConfirmReviewRejectRewrite(){
- return this.appealInfo && this.appealInfo.can_reject_rewrite && this.showReviewRejectRewrite
- },
- canConfirmReviewRefuse(){
- return this.appealInfo && this.appealInfo.can_refuse && this.showReviewRefuse
- }
- },
- methods:{
- 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
- })
- },
- initData(){
- this.formData.reviewerId = 0
- this.formData.remark = ''
- this.formData.reviewerName = ''
- this.formData.employeeSelected = { dept: [], employee: [] }
- this.hasSubmit = false
- this.appealInfo = null
- this.infoActiveNames = []
- this.showReviewRefuse = false
- this.showReviewRejectRewrite = false
- this.showReviewApproval = false
- this.showReviewerSelector = false
- this.showReviewSubmit = false
- this.showRewrite = false
- this.showEventSelector = false
- this.submitting = false
- },
- closedHandler(){
- if(this.hasSubmit) this.$emit('update:appeal')
- this.initData()
- },
- closeHandler(){
- this.hasOpen = false
- },
- openedHandler(){
- this.hasOpen = true
- this.initData()
- this.getAppealInfo()
- },
- 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"
- }
- },
- appealStatusType(status){
- const map = {
- 1:'info',
- 2:'success',
- 3:'warning',
- 4:'warning',
- 5:'danger'
- }
- return map[status] || 'info'
- },
- processStatusType(status){
- const map = {
- 1:'info',
- 2:'success',
- 3:'success',
- 4:'danger',
- 5:'warning',
- 6:'warning',
- 7:'info',
- }
- return map[status] || 'info'
- },
- onAppRewriteFinish(){
- this.hasSubmit = true
- this.getAppealInfo()
- },
- 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.$message.info('处理完毕')
- self.hasSubmit = true
- self.getAppealInfo()
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = false
- })
- },
- reviewRefuse(){
- 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.$message.success(res.data.msg)
- self.showReviewRefuse = false
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = false
- })
- },
- reviewRejectRewrite(){
- 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.$message.success(res.data.msg)
- self.showReviewRejectRewrite = false
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = 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()
- self.$message.success(res.data.msg)
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = false
- })
- },
- cancelAppeal(){
- 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()
- self.$message.success(res.data.msg)
- }else {
- this.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = false
- })
- },
- reviewSubmit(){
- if (!this.appealInfo) return
- let self = this
- self.submitting = true
- let params = {
- appeal_id:self.appealInfo.id,
- reviewer_id:self.formData.reviewerId,
- 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.$message.success(res.data.msg)
- self.showReviewSubmit = false
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = 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.$message.success(res.data.msg)
- self.showReviewApproval = false
- }else {
- self.$message.error(res.data.msg)
- }
- })
- .finally(() => {
- self.submitting = false
- })
- },
- handleReviewerSelector(val){
- this.formData.reviewerName = ''
- this.formData.employeeSelected = { dept: [], employee: [] }
- this.formData.reviewerId = 0
- if (val.employee.length > 0){
- this.formData.reviewerName = val.employee[0].name
- this.formData.employeeSelected.employee = [{name:val.employee[0].name,id:val.employee[0].id,img_url:val.employee[0].img_url}]
- this.formData.reviewerId = val.employee[0].id
- }
- },
- openRewrite(){
- 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_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.reviewerId = node.reviewer_id
- this.rewriteData.reviewerName = node.reviewer_name
- }
- this.showRewrite = true
- },
- onFormRemarkInput(val){
- this.formData.remark = specialFilter(val)
- }
- },
- mounted() {
- this.pts = this.$getTyps()
- this.superiorList = this.$store.getters.user_info.employee_detail.superior_list
- }
- }
- </script>
- <style scoped lang="scss">
- .detail_popup {
- padding: 20px;
- overflow-y: auto;
- overflow-x: hidden !important;
- height: calc(100vh - 60px);
- }
- .detail_row {
- padding-bottom: 10px;
- line-height: 50px;
- }
- .appeal_content {
- font-size: 18px;
- }
- .appeal_content p{
- margin-bottom: 10px;
- font-size: 12px;
- color: rgb(144, 147, 153);
- }
- .process{
- position: relative;
- margin: 0 0 20px 0;
- padding-top: 12px;
- font-size: 16px;
- color: #303133;
- line-height: 22px;
- }
- .process:before{
- position: absolute;
- top: 0;
- content: ' ';
- width: 100%;
- border-top: 1px #f8f8f8 solid;
- }
- .appeal_footer{
- border-top: 1px solid #ebebeb;
- padding: 10px 20px;
- font-size: 14px;
- }
- .appeal_action {
- text-align: center;
- }
- .center{
- margin-top: calc(100vh * 0.3);
- }
- .desc-content{
- display: block;
- width: 200px;
- text-align: center;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- }
- </style>
|