提交 | 用户 | 时间
3e359e 1 <template>
H 2   <div
3     class="h-50px bottom-10 text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
4   >
5     <!-- 【通过】按钮 -->
6     <el-popover
7       :visible="popOverVisible.approve"
8       placement="top-end"
9       :width="420"
10       trigger="click"
11       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.APPROVE)"
12     >
13       <template #reference>
14         <el-button plain type="success" @click="openPopover('approve')">
15           <Icon icon="ep:select" />&nbsp; {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
16         </el-button>
17       </template>
18       <!-- 审批表单 -->
19       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
20         <el-form
21           label-position="top"
22           class="mb-auto"
9259c2 23           ref="approveFormRef"
H 24           :model="approveReasonForm"
25           :rules="approveReasonRule"
3e359e 26           label-width="100px"
H 27         >
28           <el-card v-if="runningTask?.formId > 0" class="mb-15px !-mt-10px">
29             <template #header>
30               <span class="el-icon-picture-outline"> 填写表单【{{ runningTask?.formName }}】 </span>
31             </template>
32             <form-create
33               v-model="approveForm.value"
34               v-model:api="approveFormFApi"
35               :option="approveForm.option"
36               :rule="approveForm.rule"
37             />
38           </el-card>
39           <el-form-item label="审批意见" prop="reason">
40             <el-input
9259c2 41               v-model="approveReasonForm.reason"
3e359e 42               placeholder="请输入审批意见"
H 43               type="textarea"
44               :rows="4"
45             />
46           </el-form-item>
47           <el-form-item>
9259c2 48             <el-button :disabled="formLoading" type="success" @click="handleAudit(true, approveFormRef)">
3e359e 49               {{ getButtonDisplayName(OperationButtonType.APPROVE) }}
H 50             </el-button>
9259c2 51             <el-button @click="closePropover('approve', approveFormRef)"> 取消 </el-button>
3e359e 52           </el-form-item>
H 53         </el-form>
54       </div>
55     </el-popover>
56
57     <!-- 【拒绝】按钮 -->
58     <el-popover
59       :visible="popOverVisible.reject"
60       placement="top-end"
61       :width="420"
62       trigger="click"
63       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.REJECT)"
64     >
65       <template #reference>
66         <el-button class="mr-20px" plain type="danger" @click="openPopover('reject')">
67           <Icon icon="ep:close" />&nbsp; {{ getButtonDisplayName(OperationButtonType.REJECT) }}
68         </el-button>
69       </template>
70       <!-- 审批表单 -->
71       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
72         <el-form
73           label-position="top"
74           class="mb-auto"
9259c2 75           ref="rejectFormRef"
H 76           :model="rejectReasonForm"
77           :rules="rejectReasonRule"
3e359e 78           label-width="100px"
H 79         >
80           <el-form-item label="审批意见" prop="reason">
81             <el-input
9259c2 82               v-model="rejectReasonForm.reason"
3e359e 83               placeholder="请输入审批意见"
H 84               type="textarea"
85               :rows="4"
86             />
87           </el-form-item>
88           <el-form-item>
9259c2 89             <el-button :disabled="formLoading" type="danger" @click="handleAudit(false,rejectFormRef)">
3e359e 90               {{ getButtonDisplayName(OperationButtonType.REJECT) }}
H 91             </el-button>
9259c2 92             <el-button @click="closePropover('reject', rejectFormRef)"> 取消 </el-button>
3e359e 93           </el-form-item>
H 94         </el-form>
95       </div>
96     </el-popover>
97
98     <!-- 【抄送】按钮 -->
99     <el-popover
100       :visible="popOverVisible.copy"
101       placement="top-start"
102       :width="420"
103       trigger="click"
104       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.COPY)"
105     >
106       <template #reference>
107         <div @click="openPopover('copy')" class="hover-bg-gray-100 rounded-xl p-6px">
108           <Icon :size="14" icon="svg-icon:send" />&nbsp;
109           {{ getButtonDisplayName(OperationButtonType.COPY) }}
110         </div>
111       </template>
112       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
113         <el-form
114           label-position="top"
115           class="mb-auto"
9259c2 116           ref="copyFormRef"
H 117           :model="copyForm"
118           :rules="copyFormRule"
3e359e 119           label-width="100px"
H 120         >
121           <el-form-item label="抄送人" prop="copyUserIds">
122             <el-select
9259c2 123               v-model="copyForm.copyUserIds"
3e359e 124               clearable
H 125               style="width: 100%"
126               multiple
127               placeholder="请选择抄送人"
128             >
129               <el-option
130                 v-for="item in userOptions"
131                 :key="item.id"
132                 :label="item.nickname"
133                 :value="item.id"
134               />
135             </el-select>
136           </el-form-item>
137           <el-form-item label="抄送意见" prop="copyReason">
138             <el-input
9259c2 139               v-model="copyForm.copyReason"
3e359e 140               clearable
H 141               placeholder="请输入抄送意见"
142               type="textarea"
143               :rows="3"
144             />
145           </el-form-item>
146           <el-form-item>
147             <el-button :disabled="formLoading" type="primary" @click="handleCopy">
148               {{ getButtonDisplayName(OperationButtonType.COPY) }}
149             </el-button>
9259c2 150             <el-button @click="closePropover('copy', copyFormRef)"> 取消 </el-button>
3e359e 151           </el-form-item>
H 152         </el-form>
153       </div>
154     </el-popover>
155
9259c2 156     <!-- 【转办】按钮 -->
3e359e 157     <el-popover
H 158       :visible="popOverVisible.transfer"
159       placement="top-start"
160       :width="420"
161       trigger="click"
162       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.TRANSFER)"
163     >
164       <template #reference>
165         <div @click="openPopover('transfer')" class="hover-bg-gray-100 rounded-xl p-6px">
166           <Icon :size="14" icon="fa:share-square-o" />&nbsp;
167           {{ getButtonDisplayName(OperationButtonType.TRANSFER) }}
168         </div>
169       </template>
170       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
171         <el-form
172           label-position="top"
173           class="mb-auto"
9259c2 174           ref="transferFormRef"
H 175           :model="transferForm"
176           :rules="transferFormRule"
3e359e 177           label-width="100px"
H 178         >
179           <el-form-item label="新审批人" prop="assigneeUserId">
9259c2 180             <el-select v-model="transferForm.assigneeUserId" clearable style="width: 100%">
3e359e 181               <el-option
H 182                 v-for="item in userOptions"
183                 :key="item.id"
184                 :label="item.nickname"
185                 :value="item.id"
186               />
187             </el-select>
188           </el-form-item>
189           <el-form-item label="审批意见" prop="reason">
190             <el-input
9259c2 191               v-model="transferForm.reason"
3e359e 192               clearable
H 193               placeholder="请输入审批意见"
194               type="textarea"
195               :rows="3"
196             />
197           </el-form-item>
198           <el-form-item>
199             <el-button :disabled="formLoading" type="primary" @click="handleTransfer()">
200               {{ getButtonDisplayName(OperationButtonType.TRANSFER) }}
201             </el-button>
9259c2 202             <el-button @click="closePropover('transfer', transferFormRef)"> 取消 </el-button>
3e359e 203           </el-form-item>
H 204         </el-form>
205       </div>
206     </el-popover>
207
208     <!-- 【委派】按钮 -->
209     <el-popover
210       :visible="popOverVisible.delegate"
211       placement="top-start"
212       :width="420"
213       trigger="click"
214       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.DELEGATE)"
215     >
216       <template #reference>
217         <div @click="openPopover('delegate')" class="hover-bg-gray-100 rounded-xl p-6px">
218           <Icon :size="14" icon="ep:position" />&nbsp;
219           {{ getButtonDisplayName(OperationButtonType.DELEGATE) }}
220         </div>
221       </template>
222       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
223         <el-form
224           label-position="top"
225           class="mb-auto"
9259c2 226           ref="delegateFormRef"
H 227           :model="delegateForm"
228           :rules="delegateFormRule"
3e359e 229           label-width="100px"
H 230         >
231           <el-form-item label="接收人" prop="delegateUserId">
9259c2 232             <el-select v-model="delegateForm.delegateUserId" clearable style="width: 100%">
3e359e 233               <el-option
H 234                 v-for="item in userOptions"
235                 :key="item.id"
236                 :label="item.nickname"
237                 :value="item.id"
238               />
239             </el-select>
240           </el-form-item>
241           <el-form-item label="审批意见" prop="reason">
242             <el-input
9259c2 243               v-model="delegateForm.reason"
3e359e 244               clearable
H 245               placeholder="请输入审批意见"
246               type="textarea"
247               :rows="3"
248             />
249           </el-form-item>
250           <el-form-item>
251             <el-button :disabled="formLoading" type="primary" @click="handleDelegate()">
252               {{ getButtonDisplayName(OperationButtonType.DELEGATE) }}
253             </el-button>
9259c2 254             <el-button @click="closePropover('delegate', delegateFormRef)"> 取消 </el-button>
3e359e 255           </el-form-item>
H 256         </el-form>
257       </div>
258     </el-popover>
259
260     <!-- 【加签】按钮 当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
261     <el-popover
262       :visible="popOverVisible.addSign"
263       placement="top-start"
264       :width="420"
265       trigger="click"
266       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.ADD_SIGN)"
267     >
268       <template #reference>
269         <div @click="openPopover('addSign')" class="hover-bg-gray-100 rounded-xl p-6px">
270           <Icon :size="14" icon="ep:plus" />&nbsp;
271           {{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
272         </div>
273       </template>
274       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
275         <el-form
276           label-position="top"
277           class="mb-auto"
9259c2 278           ref="addSignFormRef"
H 279           :model="addSignForm"
280           :rules="addSignFormRule"
3e359e 281           label-width="100px"
H 282         >
283           <el-form-item label="加签处理人" prop="addSignUserIds">
9259c2 284             <el-select v-model="addSignForm.addSignUserIds" multiple clearable style="width: 100%">
3e359e 285               <el-option
H 286                 v-for="item in userOptions"
287                 :key="item.id"
288                 :label="item.nickname"
289                 :value="item.id"
290               />
291             </el-select>
292           </el-form-item>
293           <el-form-item label="审批意见" prop="reason">
294             <el-input
9259c2 295               v-model="addSignForm.reason"
3e359e 296               clearable
H 297               placeholder="请输入审批意见"
298               type="textarea"
299               :rows="3"
300             />
301           </el-form-item>
302           <el-form-item>
303             <el-button :disabled="formLoading" type="primary" @click="handlerAddSign('before')">
304               向前{{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
305             </el-button>
306             <el-button :disabled="formLoading" type="primary" @click="handlerAddSign('after')">
307               向后{{ getButtonDisplayName(OperationButtonType.ADD_SIGN) }}
308             </el-button>
9259c2 309             <el-button @click="closePropover('addSign', addSignFormRef)"> 取消 </el-button>
3e359e 310           </el-form-item>
H 311         </el-form>
312       </div>
313     </el-popover>
314
315     <!-- 【减签】按钮 -->
316     <el-popover
317       :visible="popOverVisible.deleteSign"
318       placement="top-start"
319       :width="420"
320       trigger="click"
321       v-if="runningTask?.children.length > 0"
322     >
323       <template #reference>
324         <div @click="openPopover('deleteSign')" class="hover-bg-gray-100 rounded-xl p-6px">
325           <Icon :size="14" icon="ep:semi-select" />&nbsp; 减签
326         </div>
327       </template>
328       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
329         <el-form
330           label-position="top"
331           class="mb-auto"
9259c2 332           ref="deleteSignFormRef"
H 333           :model="deleteSignForm"
334           :rules="deleteSignFormRule"
3e359e 335           label-width="100px"
H 336         >
337           <el-form-item label="减签人员" prop="deleteSignTaskId">
9259c2 338             <el-select v-model="deleteSignForm.deleteSignTaskId" clearable style="width: 100%">
3e359e 339               <el-option
H 340                 v-for="item in runningTask.children"
341                 :key="item.id"
342                 :label="getDeleteSignUserLabel(item)"
343                 :value="item.id"
344               />
345             </el-select>
346           </el-form-item>
347           <el-form-item label="审批意见" prop="reason">
348             <el-input
9259c2 349               v-model="deleteSignForm.reason"
3e359e 350               clearable
H 351               placeholder="请输入审批意见"
352               type="textarea"
353               :rows="3"
354             />
355           </el-form-item>
356           <el-form-item>
357             <el-button :disabled="formLoading" type="primary" @click="handlerDeleteSign()">
358               减签
359             </el-button>
9259c2 360             <el-button @click="closePropover('deleteSign', deleteSignFormRef)"> 取消 </el-button>
3e359e 361           </el-form-item>
H 362         </el-form>
363       </div>
364     </el-popover>
365
366     <!-- 【退回】按钮 -->
367     <el-popover
368       :visible="popOverVisible.return"
369       placement="top-start"
370       :width="420"
371       trigger="click"
372       v-if="runningTask && isHandleTaskStatus() && isShowButton(OperationButtonType.RETURN)"
373     >
374       <template #reference>
9259c2 375         <div @click="openPopover('return')" class="hover-bg-gray-100 rounded-xl p-6px">
3e359e 376           <Icon :size="14" icon="ep:back" />&nbsp;
H 377           {{ getButtonDisplayName(OperationButtonType.RETURN) }}
378         </div>
379       </template>
380       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
381         <el-form
382           label-position="top"
383           class="mb-auto"
9259c2 384           ref="returnFormRef"
H 385           :model="returnForm"
386           :rules="returnFormRule"
3e359e 387           label-width="100px"
H 388         >
389           <el-form-item label="退回节点" prop="targetTaskDefinitionKey">
9259c2 390             <el-select v-model="returnForm.targetTaskDefinitionKey" clearable style="width: 100%">
3e359e 391               <el-option
H 392                 v-for="item in returnList"
393                 :key="item.taskDefinitionKey"
394                 :label="item.name"
395                 :value="item.taskDefinitionKey"
396               />
397             </el-select>
398           </el-form-item>
399           <el-form-item label="退回理由" prop="returnReason">
400             <el-input
9259c2 401               v-model="returnForm.returnReason"
3e359e 402               clearable
H 403               placeholder="请输入退回理由"
404               type="textarea"
405               :rows="3"
406             />
407           </el-form-item>
408           <el-form-item>
409             <el-button :disabled="formLoading" type="primary" @click="handleReturn()">
410               {{ getButtonDisplayName(OperationButtonType.RETURN) }}
411             </el-button>
9259c2 412             <el-button @click="closePropover('return', returnFormRef)"> 取消 </el-button>
3e359e 413           </el-form-item>
H 414         </el-form>
415       </div>
416     </el-popover>
417
418     <!--【取消】按钮 这个对应发起人的取消, 只有发起人可以取消 -->
419     <el-popover
420       :visible="popOverVisible.cancel"
421       placement="top-start"
422       :width="420"
423       trigger="click"
424       v-if="
425         userId === processInstance?.startUser?.id && !isEndProcessStatus(processInstance?.status)
426       "
427     >
428       <template #reference>
429         <div @click="openPopover('cancel')" class="hover-bg-gray-100 rounded-xl p-6px">
430           <Icon :size="14" icon="fa:mail-reply" />&nbsp; 取消
431         </div>
432       </template>
433       <div class="flex flex-col flex-1 pt-20px px-20px" v-loading="formLoading">
434         <el-form
435           label-position="top"
436           class="mb-auto"
9259c2 437           ref="cancelFormRef"
H 438           :model="cancelForm"
439           :rules="cancelFormRule"
3e359e 440           label-width="100px"
H 441         >
442           <el-form-item label="取消理由" prop="cancelReason">
443             <span class="text-#878c93 text-12px">&nbsp; 取消后,该审批流程将自动结束</span>
444             <el-input
9259c2 445               v-model="cancelForm.cancelReason"
3e359e 446               clearable
H 447               placeholder="请输入取消理由"
448               type="textarea"
449               :rows="3"
450             />
451           </el-form-item>
452           <el-form-item>
453             <el-button :disabled="formLoading" type="primary" @click="handleCancel()">
9259c2 454               确认
3e359e 455             </el-button>
9259c2 456             <el-button @click="closePropover('cancel', cancelFormRef)"> 取消 </el-button>
3e359e 457           </el-form-item>
H 458         </el-form>
459       </div>
460     </el-popover>
461     <!-- 【再次提交】 按钮-->
462     <div
463       @click="handleReCreate()"
464       class="hover-bg-gray-100 rounded-xl p-6px"
465       v-if="
466         userId === processInstance?.startUser?.id &&
467         isEndProcessStatus(processInstance?.status) &&
468         processDefinition?.formType === 10
469       "
470     >
471       <Icon :size="14" icon="ep:refresh" />&nbsp; 再次提交
472     </div>
473   </div>
474 </template>
475 <script lang="ts" setup>
476 import { useUserStoreWithOut } from '@/store/modules/user'
477 import { setConfAndFields2 } from '@/utils/formCreate'
478 import * as TaskApi from '@/api/bpm/task'
479 import * as ProcessInstanceApi from '@/api/bpm/processInstance'
9259c2 480 import * as UserApi from '@/api/system/user'
3e359e 481 import {
H 482   OperationButtonType,
483   OPERATION_BUTTON_NAME
484 } from '@/components/SimpleProcessDesignerV2/src/consts'
9259c2 485 import { BpmProcessInstanceStatus, BpmModelFormType } from '@/utils/constants'
H 486 import type { FormInstance, FormRules } from 'element-plus'
3e359e 487 defineOptions({ name: 'ProcessInstanceBtnContainer' })
H 488
489 const router = useRouter() // 路由
490 const message = useMessage() // 消息弹窗
491
492 const userId = useUserStoreWithOut().getUser.id // 当前登录的编号
493 const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
9259c2 494
H 495 const props = defineProps< {
496   processInstance: any,  // 流程实例信息
497   processDefinition: any,  // 流程定义信息
498   userOptions: UserApi.UserVO[],
499   normalForm: any, // 流程表单 formCreate
500   normalFormApi: any, // 流程表单 formCreate Api
501   writableFields: string[] // 流程表单可以编辑的字段
502 }>()
3e359e 503
H 504 const formLoading = ref(false) // 表单加载中
505 const popOverVisible = ref({
506   approve: false,
507   reject: false,
508   transfer: false,
509   delegate: false,
510   addSign: false,
511   return: false,
512   copy: false,
513   cancel: false,
514   deleteSign: false
515 }) // 气泡卡是否展示
516 const returnList = ref([] as any) // 退回节点
517
518 // ========== 审批信息 ==========
519 const runningTask = ref<any>() // 运行中的任务
520 const approveForm = ref<any>({}) // 审批通过时,额外的补充信息
521 const approveFormFApi = ref<any>({}) // approveForms 的 fAPi
9259c2 522
H 523 // 审批通过意见表单
524 const approveFormRef = ref<FormInstance>()
525 const approveReasonForm = reactive({
526   reason: ''
527 })
528 const approveReasonRule = reactive<FormRules<typeof approveReasonForm>>({
3e359e 529   reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
9259c2 530 })
H 531 // 拒绝表单
532 const rejectFormRef = ref<FormInstance>()
533 const rejectReasonForm = reactive({
534   reason: ''
535 })
536 const rejectReasonRule = reactive<FormRules<typeof rejectReasonForm>>({
537   reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
538 })
539
540 // 抄送表单
541 const copyFormRef = ref<FormInstance>()
542 const copyForm = reactive({
543   copyUserIds: [],
544   copyReason: ''
545 })
546 const copyFormRule = reactive<FormRules<typeof copyForm>>({
547   copyUserIds: [{ required: true, message: '抄送人不能为空', trigger: 'change' }]
548 })
549
550 // 转办表单
551 const transferFormRef = ref<FormInstance>()
552 const transferForm = reactive({
553   assigneeUserId: undefined,
554   reason: ''
555 })
556 const transferFormRule = reactive<FormRules<typeof transferForm>>({
3e359e 557   assigneeUserId: [{ required: true, message: '新审批人不能为空', trigger: 'change' }],
9259c2 558   reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
H 559 })
560
561 // 委派表单
562 const delegateFormRef = ref<FormInstance>()
563 const delegateForm = reactive({
564   delegateUserId: undefined,
565   reason: ''
566 })
567 const delegateFormRule = reactive<FormRules<typeof delegateForm>>({
3e359e 568   delegateUserId: [{ required: true, message: '接收人不能为空', trigger: 'change' }],
9259c2 569   reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
H 570 })
571
572 // 加签表单
573 const addSignFormRef = ref<FormInstance>()
574 const addSignForm = reactive({
575   addSignUserIds: undefined,
576   reason: ''
577 })
578 const addSignFormRule = reactive<FormRules<typeof addSignForm>>({
3e359e 579   addSignUserIds: [{ required: true, message: '加签处理人不能为空', trigger: 'change' }],
9259c2 580   reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
H 581 })
582
583 // 减签表单
584 const deleteSignFormRef = ref<FormInstance>()
585 const deleteSignForm = reactive({
586   deleteSignTaskId: undefined,
587   reason: ''
588 })
589 const deleteSignFormRule = reactive<FormRules<typeof deleteSignForm>>({
3e359e 590   deleteSignTaskId: [{ required: true, message: '减签人员不能为空', trigger: 'change' }],
9259c2 591  reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }],
H 592 })
593
594 // 退回表单
595 const returnFormRef = ref<FormInstance>()
596 const returnForm = reactive({
597   targetTaskDefinitionKey: undefined,
598   returnReason: ''
599 })
600 const returnFormRule = reactive<FormRules<typeof returnForm>>({
601   targetTaskDefinitionKey: [{ required: true, message: '退回节点不能为空', trigger: 'change' }],
602   returnReason: [{ required: true, message: '退回理由不能为空', trigger: 'blur' }]
603 })
604
605 // 取消表单
606 const cancelFormRef = ref<FormInstance>()
607 const cancelForm = reactive({
608   cancelReason: ''
609 })
610 const cancelFormRule = reactive<FormRules<typeof cancelForm>>({
611   cancelReason: [{ required: true, message: '取消理由不能为空', trigger: 'blur' }],
612 })
3e359e 613
H 614 /** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
615 watch(
616   () => approveFormFApi.value,
617   (val) => {
618     val?.btn?.show(false)
619     val?.resetBtn?.show(false)
620   },
621   {
622     deep: true
623   }
624 )
625
626 /** 弹出气泡卡 */
627 const openPopover = async (type: string) => {
9259c2 628   if (type === 'approve') {
H 629     // 校验流程表单
630      const valid = await validateNormalForm();
631      if (!valid) {
632       message.warning('表单校验不通过,请先完善表单!!')
633       return;
634      }
635   }
636   if (type === 'return') {
637     // 获取退回节点
638     returnList.value = await TaskApi.getTaskListByReturn(runningTask.value.id)
639     if (returnList.value.length === 0) {
640       message.warning('当前没有可退回的节点')
641       return
642     }
643   }
3e359e 644   Object.keys(popOverVisible.value).forEach((item) => {
H 645     popOverVisible.value[item] = item === type
646   })
9259c2 647   // await nextTick()
H 648   // formRef.value.resetFields()
649 }
650
651 /** 关闭气泡卡 */
652 const closePropover = (type: string, formRef: FormInstance | undefined) => {
653   if (formRef) {
654     formRef.resetFields()
655   } 
656   popOverVisible.value[type] = false
3e359e 657 }
H 658
659 /** 处理审批通过和不通过的操作 */
9259c2 660 const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) => {
3e359e 661   formLoading.value = true
H 662   try {
9259c2 663     // 校验表单
H 664     if (!formRef) return
665     await formRef.validate()
3e359e 666     if (pass) {
9259c2 667        // 获取修改的流程变量, 暂时只支持流程表单
H 668        const variables = getUpdatedProcessInstanceVaiables();
669       // 审批通过数据
670       const data = {
671         id: runningTask.value.id,
672         reason: approveReasonForm.reason,
673         variables // 审批通过, 把修改的字段值赋于流程实例变量
674       }
675       // 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
676       // TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突
3e359e 677       const formCreateApi = approveFormFApi.value
H 678       if (Object.keys(formCreateApi)?.length > 0) {
679         await formCreateApi.validate()
680         // @ts-ignore
681         data.variables = approveForm.value.value
682       }
683       await TaskApi.approveTask(data)
684       popOverVisible.value.approve = false
685       message.success('审批通过成功')
686     } else {
9259c2 687        // 审批不通过数据
H 688        const data = {
689         id: runningTask.value.id,
690         reason: rejectReasonForm.reason,
691       }
3e359e 692       await TaskApi.rejectTask(data)
H 693       popOverVisible.value.reject = false
694       message.success('审批不通过成功')
695     }
9259c2 696     // 重置表单
H 697     formRef.resetFields()
698     // 加载最新数据
3e359e 699     reload()
H 700   } finally {
701     formLoading.value = false
702   }
703 }
704
705 /** 处理抄送 */
706 const handleCopy = async () => {
707   formLoading.value = true
708   try {
709     // 1. 校验表单
9259c2 710     if (!copyFormRef.value) return
H 711     await copyFormRef.value.validate()
3e359e 712     // 2. 提交抄送
H 713     const data = {
714       id: runningTask.value.id,
9259c2 715       reason: copyForm.copyReason,
H 716       copyUserIds:copyForm.copyUserIds
3e359e 717     }
H 718     await TaskApi.copyTask(data)
9259c2 719     copyFormRef.value.resetFields()
3e359e 720     popOverVisible.value.copy = false
H 721     message.success('操作成功')
722   } finally {
723     formLoading.value = false
724   }
725 }
726
727 /** 处理转交 */
728 const handleTransfer = async () => {
729   formLoading.value = true
730   try {
731     // 1.1 校验表单
9259c2 732     if (!transferFormRef.value) return
H 733     await transferFormRef.value.validate()
3e359e 734     // 1.2 提交转交
H 735     const data = {
736       id: runningTask.value.id,
9259c2 737       reason: transferForm.reason,
H 738       assigneeUserId: transferForm.assigneeUserId
3e359e 739     }
H 740     await TaskApi.transferTask(data)
9259c2 741     transferFormRef.value.resetFields()
3e359e 742     popOverVisible.value.transfer = false
H 743     message.success('操作成功')
744     // 2. 加载最新数据
745     reload()
746   } finally {
747     formLoading.value = false
748   }
749 }
750
751 /** 处理委派 */
752 const handleDelegate = async () => {
753   formLoading.value = true
754   try {
9259c2 755  
3e359e 756     // 1.1 校验表单
9259c2 757     if (!delegateFormRef.value) return
H 758     await delegateFormRef.value.validate()
3e359e 759     // 1.2 处理委派
H 760     const data = {
761       id: runningTask.value.id,
9259c2 762       reason: delegateForm.reason,
H 763       delegateUserId: delegateForm.delegateUserId
3e359e 764     }
H 765
766     await TaskApi.delegateTask(data)
767     popOverVisible.value.delegate = false
9259c2 768     delegateFormRef.value.resetFields()
3e359e 769     message.success('操作成功')
H 770     // 2. 加载最新数据
771     reload()
772   } finally {
773     formLoading.value = false
774   }
775 }
776
777 /** 处理加签 */
778 const handlerAddSign = async (type: string) => {
779   formLoading.value = true
780   try {
781     // 1.1 校验表单
9259c2 782     if (!addSignFormRef.value) return
H 783     await addSignFormRef.value.validate()
3e359e 784     // 1.2 提交加签
H 785     const data = {
786       id: runningTask.value.id,
787       type,
9259c2 788       reason: addSignForm.reason,
H 789       userIds: addSignForm.addSignUserIds
3e359e 790     }
H 791     await TaskApi.signCreateTask(data)
792     message.success('操作成功')
9259c2 793     addSignFormRef.value.resetFields()
3e359e 794     popOverVisible.value.addSign = false
H 795     // 2 加载最新数据
796     reload()
797   } finally {
798     formLoading.value = false
799   }
800 }
801
802 /** 处理退回 */
803 const handleReturn = async () => {
804   formLoading.value = true
805   try {
806     // 1.1 校验表单
9259c2 807     if (!returnFormRef.value) return
H 808     await returnFormRef.value.validate()
3e359e 809     // 1.2 提交退回
H 810     const data = {
811       id: runningTask.value.id,
9259c2 812       reason: returnForm.returnReason,
H 813       targetTaskDefinitionKey: returnForm.targetTaskDefinitionKey
3e359e 814     }
H 815
816     await TaskApi.returnTask(data)
817     popOverVisible.value.return = false
9259c2 818     returnFormRef.value.resetFields()
3e359e 819     message.success('操作成功')
H 820     // 2 重新加载数据
821     reload()
822   } finally {
823     formLoading.value = false
824   }
825 }
826
827 /** 处理取消 */
828 const handleCancel = async () => {
829   formLoading.value = true
830   try {
831     // 1.1 校验表单
9259c2 832     if (!cancelFormRef.value) return
H 833     await cancelFormRef.value.validate()
3e359e 834     // 1.2 提交取消
H 835     await ProcessInstanceApi.cancelProcessInstanceByStartUser(
836       props.processInstance.id,
9259c2 837       cancelForm.cancelReason
3e359e 838     )
H 839     popOverVisible.value.return = false
840     message.success('操作成功')
9259c2 841     cancelFormRef.value.resetFields()
3e359e 842     // 2 重新加载数据
H 843     reload()
844   } finally {
845     formLoading.value = false
846   }
847 }
848
849 /** 处理再次提交 */
850 const handleReCreate = async () => {
851   // 跳转发起流程界面
852   await router.push({
853     name: 'BpmProcessInstanceCreate',
854     query: { processInstanceId: props.processInstance?.id }
855   })
856 }
857
858 /** 获取减签人员标签 */
859 const getDeleteSignUserLabel = (task: any): string => {
860   const deptName = task?.assigneeUser?.deptName || task?.ownerUser?.deptName
861   const nickname = task?.assigneeUser?.nickname || task?.ownerUser?.nickname
862   return `${nickname} ( 所属部门:${deptName} )`
863 }
864 /** 处理减签 */
865 const handlerDeleteSign = async () => {
866   formLoading.value = true
867   try {
868     // 1.1 校验表单
9259c2 869     if (!deleteSignFormRef.value) return
H 870     await deleteSignFormRef.value.validate()
3e359e 871     // 1.2 提交减签
H 872     const data = {
9259c2 873       id: deleteSignForm.deleteSignTaskId,
H 874       reason: deleteSignForm.reason
3e359e 875     }
H 876     await TaskApi.signDeleteTask(data)
877     message.success('减签成功')
9259c2 878     deleteSignFormRef.value.resetFields()
3e359e 879     popOverVisible.value.deleteSign = false
H 880     // 2 加载最新数据
881     reload()
882   } finally {
883     formLoading.value = false
884   }
885 }
886 /** 重新加载数据 */
887 const reload = () => {
888   emit('success')
889 }
890
891 /** 任务是否为处理中状态 */
892 const isHandleTaskStatus = () => {
893   let canHandle = false
894   if (TaskApi.TaskStatusEnum.RUNNING === runningTask.value?.status) {
895     canHandle = true
896   }
897   return canHandle
898 }
899
900 /** 流程状态是否为结束状态 */
901 const isEndProcessStatus = (status: number) => {
902   let isEndStatus = false
903   if (
904     BpmProcessInstanceStatus.APPROVE === status ||
905     BpmProcessInstanceStatus.REJECT === status ||
906     BpmProcessInstanceStatus.CANCEL === status
907   ) {
908     isEndStatus = true
909   }
910   return isEndStatus
911 }
912
913 /** 是否显示按钮 */
914 const isShowButton = (btnType: OperationButtonType): boolean => {
915   let isShow = true
916   if (runningTask.value?.buttonsSetting && runningTask.value?.buttonsSetting[btnType]) {
917     isShow = runningTask.value.buttonsSetting[btnType].enable
918   }
919   return isShow
920 }
921
922 /** 获取按钮的显示名称 */
923 const getButtonDisplayName = (btnType: OperationButtonType) => {
924   let displayName = OPERATION_BUTTON_NAME.get(btnType)
925   if (runningTask.value?.buttonsSetting && runningTask.value?.buttonsSetting[btnType]) {
926     displayName = runningTask.value.buttonsSetting[btnType].displayName
927   }
928   return displayName
929 }
930
931 const loadTodoTask = (task: any) => {
932   approveForm.value = {}
933   approveFormFApi.value = {}
934   runningTask.value = task
935   // 处理 approve 表单.
936   if (task && task.formId && task.formConf) {
937     const tempApproveForm = {}
938     setConfAndFields2(tempApproveForm, task.formConf, task.formFields, task.formVariables)
939     approveForm.value = tempApproveForm
940   } else {
941     approveForm.value = {} // 占位,避免为空
942   }
943 }
944
9259c2 945 /** 校验流程表单 */
H 946 const validateNormalForm = async () => {
947   if (props.processDefinition?.formType === BpmModelFormType.NORMAL) {
948     let valid = true
949     try {
950       await props.normalFormApi?.validate()
951     } catch {
952       valid = false;
953     }
954     return valid;
955   } else {
956     return true;
957   }
958 }
959 /** 从可以编辑的流程表单字段,获取需要修改的流程实例的变量 */
960 const getUpdatedProcessInstanceVaiables = ()=> {
961   const variables = {}
962   props.writableFields.forEach( (field) => {
963     const fieldValue = props.normalFormApi.getValue(field)
964     variables[field] = fieldValue;
965   })
966   return variables
967 }
968
3e359e 969 defineExpose({ loadTodoTask })
H 970 </script>
971
972 <style lang="scss" scoped>
973 :deep(.el-affix--fixed) {
974   background-color: var(--el-bg-color);
975 }
976
977 .btn-container {
978   > div {
979     display: flex;
980     margin: 0 8px;
981     cursor: pointer;
982     align-items: center;
983
984     &:hover {
985       color: #6db5ff;
986     }
987   }
988 }
989 </style>