潘志宝
6 天以前 ca22cdd5550cfa0defb0f430c538698182cdaec1
提交 | 用户 | 时间
3e359e 1 <template>
H 2   <el-drawer
3     :append-to-body="true"
4     v-model="settingVisible"
5     :show-close="false"
6     :size="550"
7     :before-close="saveConfig"
8     class="justify-start"
9   >
10     <template #header>
11       <div class="config-header">
12         <input
13           v-if="showInput"
14           type="text"
15           class="config-editable-input"
16           @blur="blurEvent()"
17           v-mountedFocus
18           v-model="nodeName"
19           :placeholder="nodeName"
20         />
21         <div v-else class="node-name">
22           {{ nodeName }} <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()" />
23         </div>
24         <div class="divide-line"></div>
25       </div>
26     </template>
27     <div class="flex flex-items-center mb-3">
28       <span class="font-size-16px mr-3">审批类型 :</span>
29       <el-radio-group v-model="approveType">
30         <el-radio
31           v-for="(item, index) in APPROVE_TYPE"
32           :key="index"
33           :value="item.value"
34           :label="item.value"
35         >
36           {{ item.label }}
37         </el-radio>
38       </el-radio-group>
39     </div>
40     <el-tabs type="border-card" v-model="activeTabName" v-if="approveType === ApproveType.USER">
41       <el-tab-pane label="审批人" name="user">
42         <div>
43           <el-form ref="formRef" :model="configForm" label-position="top" :rules="formRules">
44             <el-form-item label="审批人设置" prop="candidateStrategy">
45               <el-radio-group
46                 v-model="configForm.candidateStrategy"
47                 @change="changeCandidateStrategy"
48               >
49                 <el-radio
50                   v-for="(dict, index) in CANDIDATE_STRATEGY"
51                   :key="index"
52                   :value="dict.value"
53                   :label="dict.value"
54                 >
55                   {{ dict.label }}
56                 </el-radio>
57               </el-radio-group>
58             </el-form-item>
59             <el-form-item
60               v-if="configForm.candidateStrategy == CandidateStrategy.ROLE"
61               label="指定角色"
62               prop="roleIds"
63             >
64               <el-select v-model="configForm.roleIds" clearable multiple style="width: 100%">
65                 <el-option
66                   v-for="item in roleOptions"
67                   :key="item.id"
68                   :label="item.name"
69                   :value="item.id"
70                 />
71               </el-select>
72             </el-form-item>
73             <el-form-item
74               v-if="
75                 configForm.candidateStrategy == CandidateStrategy.DEPT_MEMBER ||
76                 configForm.candidateStrategy == CandidateStrategy.DEPT_LEADER ||
77                 configForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
78               "
79               label="指定部门"
80               prop="deptIds"
81               span="24"
82             >
83               <el-tree-select
84                 ref="treeRef"
85                 v-model="configForm.deptIds"
86                 :data="deptTreeOptions"
87                 :props="defaultProps"
88                 empty-text="加载中,请稍后"
89                 multiple
90                 node-key="id"
91                 :check-strictly="true"
92                 style="width: 100%"
93                 show-checkbox
94               />
95             </el-form-item>
96             <el-form-item
97               v-if="configForm.candidateStrategy == CandidateStrategy.POST"
98               label="指定岗位"
99               prop="postIds"
100               span="24"
101             >
102               <el-select v-model="configForm.postIds" clearable multiple style="width: 100%">
103                 <el-option
104                   v-for="item in postOptions"
105                   :key="item.id"
106                   :label="item.name"
107                   :value="item.id!"
108                 />
109               </el-select>
110             </el-form-item>
111             <el-form-item
112               v-if="configForm.candidateStrategy == CandidateStrategy.USER"
113               label="指定用户"
114               prop="userIds"
115               span="24"
116             >
117               <el-select v-model="configForm.userIds" clearable multiple style="width: 100%">
118                 <el-option
119                   v-for="item in userOptions"
120                   :key="item.id"
121                   :label="item.nickname"
122                   :value="item.id"
123                 />
124               </el-select>
125             </el-form-item>
126             <el-form-item
127               v-if="configForm.candidateStrategy === CandidateStrategy.USER_GROUP"
128               label="指定用户组"
129               prop="userGroups"
130             >
131               <el-select v-model="configForm.userGroups" clearable multiple style="width: 100%">
132                 <el-option
133                   v-for="item in userGroupOptions"
134                   :key="item.id"
135                   :label="item.name"
136                   :value="item.id"
137                 />
138               </el-select>
139             </el-form-item>
140             <el-form-item
141               v-if="configForm.candidateStrategy === CandidateStrategy.FORM_USER"
142               label="表单内用户字段"
143               prop="formUser"
144             >
145               <el-select v-model="configForm.formUser" clearable style="width: 100%">
146                 <el-option
147                   v-for="(item, idx) in userFieldOnFormOptions"
148                   :key="idx"
149                   :label="item.title"
150                   :value="item.field"
151                   :disabled ="!item.required"
152                 />
153               </el-select>
154             </el-form-item>
155             <el-form-item
156               v-if="configForm.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER"
157               label="表单内部门字段"
158               prop="formDept"
159             >
160               <el-select v-model="configForm.formDept" clearable style="width: 100%">
161                 <el-option
162                   v-for="(item, idx) in deptFieldOnFormOptions"
163                   :key="idx"
164                   :label="item.title"
165                   :value="item.field"
166                   :disabled ="!item.required"
167                 />
168               </el-select>
169             </el-form-item>
170             <el-form-item
171               v-if="
172                 configForm.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ||
173                 configForm.candidateStrategy == CandidateStrategy.START_USER_DEPT_LEADER ||
174                 configForm.candidateStrategy ==
175                   CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER ||
176                 configForm.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER
177               "
178               :label="deptLevelLabel!"
179               prop="deptLevel"
180               span="24"
181             >
182               <el-select v-model="configForm.deptLevel" clearable>
183                 <el-option
184                   v-for="(item, index) in MULTI_LEVEL_DEPT"
185                   :key="index"
186                   :label="item.label"
187                   :value="item.value"
188                 />
189               </el-select>
190             </el-form-item>
191             <!-- TODO @jason:后续要支持选择已经存好的表达式 -->
192             <el-form-item
193               v-if="configForm.candidateStrategy === CandidateStrategy.EXPRESSION"
194               label="流程表达式"
195               prop="expression"
196             >
197               <el-input
198                 type="textarea"
199                 v-model="configForm.expression"
200                 clearable
201                 style="width: 100%"
202               />
203             </el-form-item>
204             <el-form-item label="多人审批方式" prop="approveMethod">
205               <el-radio-group v-model="configForm.approveMethod" @change="approveMethodChanged">
206                 <div class="flex-col">
207                   <div
208                     v-for="(item, index) in APPROVE_METHODS"
209                     :key="index"
210                     class="flex items-center"
211                   >
212                     <el-radio :value="item.value" :label="item.value">
213                       {{ item.label }}
214                     </el-radio>
215                     <el-form-item prop="approveRatio">
216                       <el-input-number
217                         v-model="configForm.approveRatio"
218                         :min="10"
219                         :max="100"
220                         :step="10"
221                         size="small"
222                         v-if="
223                           item.value === ApproveMethodType.APPROVE_BY_RATIO &&
224                           configForm.approveMethod === ApproveMethodType.APPROVE_BY_RATIO
225                         "
226                       />
227                     </el-form-item>
228                   </div>
229                 </div>
230               </el-radio-group>
231             </el-form-item>
232
233             <el-divider content-position="left">审批人拒绝时</el-divider>
234             <el-form-item prop="rejectHandlerType">
235               <el-radio-group v-model="configForm.rejectHandlerType">
236                 <div class="flex-col">
237                   <div v-for="(item, index) in REJECT_HANDLER_TYPES" :key="index">
238                     <el-radio :key="item.value" :value="item.value" :label="item.label" />
239                   </div>
240                 </div>
241               </el-radio-group>
242             </el-form-item>
243             <el-form-item
244               v-if="configForm.rejectHandlerType == RejectHandlerType.RETURN_USER_TASK"
245               label="驳回节点"
246               prop="returnNodeId"
247             >
248               <el-select v-model="configForm.returnNodeId" clearable style="width: 100%">
249                 <el-option
250                   v-for="item in returnTaskList"
251                   :key="item.id"
252                   :label="item.name"
253                   :value="item.id"
254                 />
255               </el-select>
256             </el-form-item>
257
258             <el-divider content-position="left">审批人超时未处理时</el-divider>
259             <el-form-item label="启用开关" prop="timeoutHandlerEnable">
260               <el-switch
261                 v-model="configForm.timeoutHandlerEnable"
262                 active-text="开启"
263                 inactive-text="关闭"
264                 @change="timeoutHandlerChange"
265               />
266             </el-form-item>
267             <el-form-item
268               label="执行动作"
269               prop="timeoutHandlerType"
270               v-if="configForm.timeoutHandlerEnable"
271             >
272               <el-radio-group
273                 v-model="configForm.timeoutHandlerType"
274                 @change="timeoutHandlerTypeChanged"
275               >
276                 <el-radio-button
277                   v-for="item in TIMEOUT_HANDLER_TYPES"
278                   :key="item.value"
279                   :value="item.value"
280                   :label="item.label"
281                 />
282               </el-radio-group>
283             </el-form-item>
284             <el-form-item label="超时时间设置" v-if="configForm.timeoutHandlerEnable">
285               <span class="mr-2">当超过</span>
286               <el-form-item prop="timeDuration">
287                 <el-input-number
288                   class="mr-2"
289                   :style="{ width: '100px' }"
290                   v-model="configForm.timeDuration"
291                   :min="1"
292                   controls-position="right"
293                 />
294               </el-form-item>
295               <el-select
296                 v-model="timeUnit"
297                 class="mr-2"
298                 :style="{ width: '100px' }"
299                 @change="timeUnitChange"
300               >
301                 <el-option
302                   v-for="item in TIME_UNIT_TYPES"
303                   :key="item.value"
304                   :label="item.label"
305                   :value="item.value"
306                 />
307               </el-select>
308               未处理
309             </el-form-item>
310             <el-form-item
311               label="最大提醒次数"
312               prop="maxRemindCount"
313               v-if="configForm.timeoutHandlerEnable && configForm.timeoutHandlerType === 1"
314             >
315               <el-input-number v-model="configForm.maxRemindCount" :min="1" :max="10" />
316             </el-form-item>
317
318             <el-divider content-position="left">审批人为空时</el-divider>
319             <el-form-item prop="assignEmptyHandlerType">
320               <el-radio-group v-model="configForm.assignEmptyHandlerType">
321                 <div class="flex-col">
322                   <div v-for="(item, index) in ASSIGN_EMPTY_HANDLER_TYPES" :key="index">
323                     <el-radio :key="item.value" :value="item.value" :label="item.label" />
324                   </div>
325                 </div>
326               </el-radio-group>
327             </el-form-item>
328             <el-form-item
329               v-if="configForm.assignEmptyHandlerType == AssignEmptyHandlerType.ASSIGN_USER"
330               label="指定用户"
331               prop="assignEmptyHandlerUserIds"
332               span="24"
333             >
334               <el-select
335                 v-model="configForm.assignEmptyHandlerUserIds"
336                 clearable
337                 multiple
338                 style="width: 100%"
339               >
340                 <el-option
341                   v-for="item in userOptions"
342                   :key="item.id"
343                   :label="item.nickname"
344                   :value="item.id"
345                 />
346               </el-select>
347             </el-form-item>
348
349             <el-divider content-position="left">审批人与提交人为同一人时</el-divider>
350             <el-form-item prop="assignStartUserHandlerType">
351               <el-radio-group v-model="configForm.assignStartUserHandlerType">
352                 <div class="flex-col">
353                   <div v-for="(item, index) in ASSIGN_START_USER_HANDLER_TYPES" :key="index">
354                     <el-radio :key="item.value" :value="item.value" :label="item.label" />
355                   </div>
356                 </div>
357               </el-radio-group>
358             </el-form-item>
359           </el-form>
360         </div>
361       </el-tab-pane>
362       <el-tab-pane label="操作按钮设置" name="buttons">
363         <div class="button-setting-pane">
364           <div class="button-setting-desc">操作按钮</div>
365           <div class="button-setting-title">
366             <div class="button-title-label">操作按钮</div>
367             <div class="pl-4 button-title-label">显示名称</div>
368             <div class="button-title-label">启用</div>
369           </div>
370           <div class="button-setting-item" v-for="(item, index) in buttonsSetting" :key="index">
371             <div class="button-setting-item-label"> {{ OPERATION_BUTTON_NAME.get(item.id) }} </div>
372             <div class="button-setting-item-label">
373               <input
374                 type="text"
375                 class="editable-title-input"
376                 @blur="btnDisplayNameBlurEvent(index)"
377                 v-mountedFocus
378                 v-model="item.displayName"
379                 :placeholder="item.displayName"
380                 v-if="btnDisplayNameEdit[index]"
381               />
382               <el-button v-else text @click="changeBtnDisplayName(index)"
383                 >{{ item.displayName }} &nbsp;<Icon icon="ep:edit"
384               /></el-button>
385             </div>
386             <div class="button-setting-item-label">
387               <el-switch v-model="item.enable" />
388             </div>
389           </div>
390         </div>
391       </el-tab-pane>
392       <el-tab-pane label="表单字段权限" name="fields" v-if="formType === 10">
393         <div class="field-setting-pane">
394           <div class="field-setting-desc">字段权限</div>
395           <div class="field-permit-title">
396             <div class="setting-title-label first-title"> 字段名称 </div>
397             <div class="other-titles">
398               <span class="setting-title-label">只读</span>
399               <span class="setting-title-label">可编辑</span>
400               <span class="setting-title-label">隐藏</span>
401             </div>
402           </div>
403           <div
404             class="field-setting-item"
405             v-for="(item, index) in fieldsPermissionConfig"
406             :key="index"
407           >
408             <div class="field-setting-item-label"> {{ item.title }} </div>
409             <el-radio-group class="field-setting-item-group" v-model="item.permission">
410               <div class="item-radio-wrap">
411                 <el-radio
412                   :value="FieldPermissionType.READ"
413                   size="large"
414                   :label="FieldPermissionType.READ"
415                   ><span></span
416                 ></el-radio>
417               </div>
418               <div class="item-radio-wrap">
419                 <el-radio
420                   :value="FieldPermissionType.WRITE"
421                   size="large"
422                   :label="FieldPermissionType.WRITE"
423                   ><span></span
424                 ></el-radio>
425               </div>
426               <div class="item-radio-wrap">
427                 <el-radio
428                   :value="FieldPermissionType.NONE"
429                   size="large"
430                   :label="FieldPermissionType.NONE"
431                   ><span></span
432                 ></el-radio>
433               </div>
434             </el-radio-group>
435           </div>
436         </div>
437       </el-tab-pane>
438     </el-tabs>
439     <template #footer>
440       <el-divider />
441       <div>
442         <el-button type="primary" @click="saveConfig">确 定</el-button>
443         <el-button @click="closeDrawer">取 消</el-button>
444       </div>
445     </template>
446   </el-drawer>
447 </template>
448
449 <script setup lang="ts">
450 import {
451   SimpleFlowNode,
452   APPROVE_TYPE,
453   ApproveType,
454   APPROVE_METHODS,
455   CandidateStrategy,
456   NodeType,
457   ApproveMethodType,
458   TimeUnitType,
459   RejectHandlerType,
460   TIMEOUT_HANDLER_TYPES,
461   TIME_UNIT_TYPES,
462   REJECT_HANDLER_TYPES,
463   DEFAULT_BUTTON_SETTING,
464   OPERATION_BUTTON_NAME,
465   ButtonSetting,
466   MULTI_LEVEL_DEPT,
467   CANDIDATE_STRATEGY,
468   ASSIGN_START_USER_HANDLER_TYPES,
469   TimeoutHandlerType,
470   ASSIGN_EMPTY_HANDLER_TYPES,
471   AssignEmptyHandlerType,
9259c2 472   FieldPermissionType,
H 473   ProcessVariableEnum
3e359e 474 } from '../consts'
H 475
476 import {
477   useWatchNode,
478   useNodeName,
479   useFormFieldsPermission,
480   useNodeForm,
481   UserTaskFormType,
482   useDrawer
483 } from '../node'
484 import { defaultProps } from '@/utils/tree'
485 import { cloneDeep } from 'lodash-es'
486 import { convertTimeUnit, getApproveTypeText } from '../utils'
487 defineOptions({
488   name: 'UserTaskNodeConfig'
489 })
490 const props = defineProps({
491   flowNode: {
492     type: Object as () => SimpleFlowNode,
493     required: true
494   }
495 })
496 const emits = defineEmits<{
497   'find:returnTaskNodes': [nodeList: SimpleFlowNode[]]
498 }>()
499 const deptLevelLabel = computed(() => {
500   let label = '部门负责人来源'
501   if (configForm.value.candidateStrategy == CandidateStrategy.MULTI_LEVEL_DEPT_LEADER) {
502     label = label + '(指定部门向上)'
503   } else if (configForm.value.candidateStrategy == CandidateStrategy.FORM_DEPT_LEADER) {
504     label = label + '(表单内部门向上)'
505   } else {
506     label = label + '(发起人部门向上)'
507   }
508   return label
509 })
510 // 监控节点的变化
511 const currentNode = useWatchNode(props)
512 // 抽屉配置
513 const { settingVisible, closeDrawer, openDrawer } = useDrawer()
514 // 节点名称配置
515 const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.USER_TASK_NODE)
516 // 激活的 Tab 标签页
517 const activeTabName = ref('user')
518 // 表单字段权限设置
519 const { formType, fieldsPermissionConfig, formFieldOptions, getNodeConfigFormFields } =
520   useFormFieldsPermission(FieldPermissionType.READ)
521 // 表单内用户字段选项, 必须是必填和用户选择器
522 const userFieldOnFormOptions = computed(() => {
9259c2 523   // 固定添加发起人 ID 字段
H 524   formFieldOptions.unshift({
525     field: ProcessVariableEnum.START_USER_ID,
526     title: '发起人',
527     type: 'UserSelect',
528     required: true
529   })
3e359e 530   return formFieldOptions.filter((item) => item.type === 'UserSelect')
H 531 })
532 // 表单内部门字段选项, 必须是必填和部门选择器
533 const deptFieldOnFormOptions = computed(() => {
534   return formFieldOptions.filter((item) => item.type === 'DeptSelect')
535 })
536 // 操作按钮设置
537 const { buttonsSetting, btnDisplayNameEdit, changeBtnDisplayName, btnDisplayNameBlurEvent } =
538   useButtonsSetting()
539 const approveType = ref(ApproveType.USER)
540 // 审批人表单设置
541 const formRef = ref() // 表单 Ref
542 // 表单校验规则
543 const formRules = reactive({
544   candidateStrategy: [{ required: true, message: '审批人设置不能为空', trigger: 'change' }],
545   userIds: [{ required: true, message: '用户不能为空', trigger: 'change' }],
546   roleIds: [{ required: true, message: '角色不能为空', trigger: 'change' }],
547   deptIds: [{ required: true, message: '部门不能为空', trigger: 'change' }],
548   userGroups: [{ required: true, message: '用户组不能为空', trigger: 'change' }],
549   formUser: [{ required: true, message: '表单内用户字段不能为空', trigger: 'change' }],
550   formDept: [{ required: true, message: '表单内部门字段不能为空', trigger: 'change' }],
551   postIds: [{ required: true, message: '岗位不能为空', trigger: 'change' }],
552   expression: [{ required: true, message: '流程表达式不能为空', trigger: 'blur' }],
553   approveMethod: [{ required: true, message: '多人审批方式不能为空', trigger: 'change' }],
554   approveRatio: [{ required: true, message: '通过比例不能为空', trigger: 'blur' }],
555   returnNodeId: [{ required: true, message: '驳回节点不能为空', trigger: 'change' }],
556   timeoutHandlerEnable: [{ required: true }],
557   timeoutHandlerType: [{ required: true }],
558   timeDuration: [{ required: true, message: '超时时间不能为空', trigger: 'blur' }],
559   maxRemindCount: [{ required: true, message: '提醒次数不能为空', trigger: 'blur' }],
560   assignEmptyHandlerType: [{ required: true }],
561   assignEmptyHandlerUserIds: [{ required: true, message: '用户不能为空', trigger: 'change' }],
562   assignStartUserHandlerType: [{ required: true }]
563 })
564
565 const {
566   configForm: tempConfigForm,
567   roleOptions,
568   postOptions,
569   userOptions,
570   userGroupOptions,
571   deptTreeOptions,
572   handleCandidateParam,
573   parseCandidateParam,
574   getShowText
575 } = useNodeForm(NodeType.USER_TASK_NODE)
576 const configForm = tempConfigForm as Ref<UserTaskFormType>
577
578 // 改变审批人设置策略
579 const changeCandidateStrategy = () => {
580   configForm.value.userIds = []
581   configForm.value.deptIds = []
582   configForm.value.roleIds = []
583   configForm.value.postIds = []
584   configForm.value.userGroups = []
585   configForm.value.deptLevel = 1
586   configForm.value.formUser = ''
587   configForm.value.formDept = ''
588   configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE
589 }
590
591 // 审批方式改变
592 const approveMethodChanged = () => {
593   configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS
594   if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) {
595     configForm.value.approveRatio = 100
596   }
597   formRef.value.clearValidate('approveRatio')
598 }
599 // 审批拒绝 可退回的节点
600 const returnTaskList = ref<SimpleFlowNode[]>([])
601 // 审批人超时未处理设置
602 const {
603   timeoutHandlerChange,
604   cTimeoutType,
605   timeoutHandlerTypeChanged,
606   timeUnit,
607   timeUnitChange,
608   isoTimeDuration,
609   cTimeoutMaxRemindCount
610 } = useTimeoutHandler()
611
612 // 保存配置
613 const saveConfig = async () => {
614   activeTabName.value = 'user'
615   // 设置审批节点名称
616   currentNode.value.name = nodeName.value!
617   // 设置审批类型
618   currentNode.value.approveType = approveType.value
619   // 如果不是人工审批。返回
620   if (approveType.value !== ApproveType.USER) {
621     currentNode.value.showText = getApproveTypeText(approveType.value)
622     settingVisible.value = false
623     return true
624   }
625
626   if (!formRef) return false
627   const valid = await formRef.value.validate()
628   if (!valid) return false
629   const showText = getShowText()
630   if (!showText) return false
631
632   currentNode.value.candidateStrategy = configForm.value.candidateStrategy
633   // 处理 candidateParam 参数
634   currentNode.value.candidateParam = handleCandidateParam()
635   // 设置审批方式
636   currentNode.value.approveMethod = configForm.value.approveMethod
637   if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) {
638     currentNode.value.approveRatio = configForm.value.approveRatio
639   }
640   // 设置拒绝处理
641   currentNode.value.rejectHandler = {
642     type: configForm.value.rejectHandlerType!,
643     returnNodeId: configForm.value.returnNodeId
644   }
645   // 设置超时处理
646   currentNode.value.timeoutHandler = {
647     enable: configForm.value.timeoutHandlerEnable!,
648     type: cTimeoutType.value,
649     timeDuration: isoTimeDuration.value,
650     maxRemindCount: cTimeoutMaxRemindCount.value
651   }
652   // 设置审批人为空时
653   currentNode.value.assignEmptyHandler = {
654     type: configForm.value.assignEmptyHandlerType!,
655     userIds:
656       configForm.value.assignEmptyHandlerType === AssignEmptyHandlerType.ASSIGN_USER
657         ? configForm.value.assignEmptyHandlerUserIds
658         : undefined
659   }
660   // 设置审批人与发起人相同时
661   currentNode.value.assignStartUserHandlerType = configForm.value.assignStartUserHandlerType
662   // 设置表单权限
663   currentNode.value.fieldsPermission = fieldsPermissionConfig.value
664   // 设置按钮权限
665   currentNode.value.buttonsSetting = buttonsSetting.value
666
667   currentNode.value.showText = showText
668   settingVisible.value = false
669   return true
670 }
671
672 // 显示审批节点配置, 由父组件传过来
673 const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
674   nodeName.value = node.name
675   // 1 审批类型
676   approveType.value = node.approveType ? node.approveType : ApproveType.USER
677   // 如果审批类型不是人工审批返回
678   if (approveType.value !== ApproveType.USER) {
679     return
680   }
681
682   //2.1 审批人设置
683   configForm.value.candidateStrategy = node.candidateStrategy!
684   // 解析候选人参数
685   parseCandidateParam(node.candidateStrategy!, node?.candidateParam)
686   // 2.2 设置审批方式
687   configForm.value.approveMethod = node.approveMethod!
688   if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) {
689     configForm.value.approveRatio = node.approveRatio!
690   }
691   // 2.3 设置审批拒绝处理
692   configForm.value.rejectHandlerType = node.rejectHandler!.type
693   configForm.value.returnNodeId = node.rejectHandler?.returnNodeId
694   const matchNodeList = []
695   emits('find:returnTaskNodes', matchNodeList)
696   returnTaskList.value = matchNodeList
697   // 2.4 设置审批超时处理
698   configForm.value.timeoutHandlerEnable = node.timeoutHandler!.enable
699   if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) {
700     const strTimeDuration = node.timeoutHandler.timeDuration
701     let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
702     let parseTimeUnit = strTimeDuration.slice(strTimeDuration.length - 1)
703     configForm.value.timeDuration = parseInt(parseTime)
704     timeUnit.value = convertTimeUnit(parseTimeUnit)
705   }
706   configForm.value.timeoutHandlerType = node.timeoutHandler?.type
707   configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount
708   // 2.5 设置审批人为空时
709   configForm.value.assignEmptyHandlerType = node.assignEmptyHandler?.type
710   configForm.value.assignEmptyHandlerUserIds = node.assignEmptyHandler?.userIds
711   // 2.6 设置用户任务的审批人与发起人相同时
712   configForm.value.assignStartUserHandlerType = node.assignStartUserHandlerType
713   // 3. 操作按钮设置
714   buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING
715   // 4. 表单字段权限配置
716   getNodeConfigFormFields(node.fieldsPermission)
717 }
718
719 defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件
720
721 /**
722  * @description 操作按钮设置
723  */
724 function useButtonsSetting() {
725   const buttonsSetting = ref<ButtonSetting[]>()
726   // 操作按钮显示名称可编辑
727   const btnDisplayNameEdit = ref<boolean[]>([])
728   const changeBtnDisplayName = (index: number) => {
729     btnDisplayNameEdit.value[index] = true
730   }
731   const btnDisplayNameBlurEvent = (index: number) => {
732     btnDisplayNameEdit.value[index] = false
733     const buttonItem = buttonsSetting.value![index]
734     buttonItem.displayName = buttonItem.displayName || OPERATION_BUTTON_NAME.get(buttonItem.id)!
735   }
736   return {
737     buttonsSetting,
738     btnDisplayNameEdit,
739     changeBtnDisplayName,
740     btnDisplayNameBlurEvent
741   }
742 }
743
744 /**
745  * @description 审批人超时未处理配置
746  */
747 function useTimeoutHandler() {
748   // 时间单位
749   const timeUnit = ref(TimeUnitType.HOUR)
750
751   // 超时开关改变
752   const timeoutHandlerChange = () => {
753     if (configForm.value.timeoutHandlerEnable) {
754       timeUnit.value = 2
755       configForm.value.timeDuration = 6
756       configForm.value.timeoutHandlerType = 1
757       configForm.value.maxRemindCount = 1
758     }
759   }
760   // 超时执行的动作
761   const cTimeoutType = computed(() => {
762     if (!configForm.value.timeoutHandlerEnable) {
763       return undefined
764     }
765     return configForm.value.timeoutHandlerType
766   })
767
768   // 超时处理动作改变
769   const timeoutHandlerTypeChanged = () => {
770     if (configForm.value.timeoutHandlerType === TimeoutHandlerType.REMINDER) {
771       configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1
772     }
773   }
774
775   // 时间单位改变
776   const timeUnitChange = () => {
777     // 分钟,默认是 60 分钟
778     if (timeUnit.value === TimeUnitType.MINUTE) {
779       configForm.value.timeDuration = 60
780     }
781     // 小时,默认是 6 个小时
782     if (timeUnit.value === TimeUnitType.HOUR) {
783       configForm.value.timeDuration = 6
784     }
785     // 天, 默认 1天
786     if (timeUnit.value === TimeUnitType.DAY) {
787       configForm.value.timeDuration = 1
788     }
789   }
790   // 超时时间的 ISO 表示
791   const isoTimeDuration = computed(() => {
792     if (!configForm.value.timeoutHandlerEnable) {
793       return undefined
794     }
795     let strTimeDuration = 'PT'
796     if (timeUnit.value === TimeUnitType.MINUTE) {
797       strTimeDuration += configForm.value.timeDuration + 'M'
798     }
799     if (timeUnit.value === TimeUnitType.HOUR) {
800       strTimeDuration += configForm.value.timeDuration + 'H'
801     }
802     if (timeUnit.value === TimeUnitType.DAY) {
803       strTimeDuration += configForm.value.timeDuration + 'D'
804     }
805     return strTimeDuration
806   })
807
808   // 超时最大提醒次数
809   const cTimeoutMaxRemindCount = computed(() => {
810     if (!configForm.value.timeoutHandlerEnable) {
811       return undefined
812     }
813     if (configForm.value.timeoutHandlerType !== TimeoutHandlerType.REMINDER) {
814       return undefined
815     }
816     return configForm.value.maxRemindCount
817   })
818
819   return {
820     timeoutHandlerChange,
821     cTimeoutType,
822     timeoutHandlerTypeChanged,
823     timeUnit,
824     timeUnitChange,
825     isoTimeDuration,
826     cTimeoutMaxRemindCount
827   }
828 }
829 </script>
830
831 <style lang="scss" scoped>
832 .button-setting-pane {
833   display: flex;
834   flex-direction: column;
835   font-size: 14px;
836
837   .button-setting-desc {
838     padding-right: 8px;
839     margin-bottom: 16px;
840     font-size: 16px;
841     font-weight: 700;
842   }
843
844   .button-setting-title {
845     display: flex;
846     justify-content: space-between;
847     align-items: center;
848     height: 45px;
849     padding-left: 12px;
850     background-color: #f8fafc0a;
851     border: 1px solid #1f38581a;
852
853     & > :first-child {
854       width: 100px !important;
855       text-align: left !important;
856     }
857
858     & > :last-child {
859       text-align: center !important;
860     }
861
862     .button-title-label {
863       width: 150px;
864       font-size: 13px;
865       font-weight: 700;
866       color: #000;
867       text-align: left;
868     }
869   }
870
871   .button-setting-item {
872     align-items: center;
873     display: flex;
874     justify-content: space-between;
875     height: 38px;
876     padding-left: 12px;
877     border: 1px solid #1f38581a;
878     border-top: 0;
879
880     & > :first-child {
881       width: 100px !important;
882     }
883
884     & > :last-child {
885       text-align: center !important;
886     }
887
888     .button-setting-item-label {
889       width: 150px;
890       overflow: hidden;
891       text-align: left;
892       text-overflow: ellipsis;
893       white-space: nowrap;
894     }
895
896     .editable-title-input {
897       height: 24px;
898       max-width: 130px;
899       margin-left: 4px;
900       line-height: 24px;
901       border: 1px solid #d9d9d9;
902       border-radius: 4px;
903       transition: all 0.3s;
904
905       &:focus {
906         border-color: #40a9ff;
907         outline: 0;
908         box-shadow: 0 0 0 2px rgb(24 144 255 / 20%);
909       }
910     }
911   }
912 }
913 </style>