dengzedong
5 天以前 3357b5f0f0919f7a52cd32a6d6de0acb14e0daaf
提交 | 用户 | 时间
3e359e 1 import { cloneDeep } from 'lodash-es'
H 2 import { TaskStatusEnum } from '@/api/bpm/task'
3 import * as RoleApi from '@/api/system/role'
4 import * as DeptApi from '@/api/system/dept'
5 import * as PostApi from '@/api/system/post'
6 import * as UserApi from '@/api/system/user'
7 import * as UserGroupApi from '@/api/bpm/userGroup'
8 import {
9   SimpleFlowNode,
10   CandidateStrategy,
11   NodeType,
12   ApproveMethodType,
13   RejectHandlerType,
14   NODE_DEFAULT_NAME,
15   AssignStartUserHandlerType,
16   AssignEmptyHandlerType,
17   FieldPermissionType,
18   ProcessVariableEnum
19 } from './consts'
20 import { parseFormFields } from '@/components/FormCreate/src/utils/index'
21 export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref<SimpleFlowNode> {
22   const node = ref<SimpleFlowNode>(props.flowNode)
23   watch(
24     () => props.flowNode,
25     (newValue) => {
26       node.value = newValue
27     }
28   )
29   return node
30 }
31
32 // 解析 formCreate 所有表单字段, 并返回
33 const parseFormCreateFields = (formFields?: string[]) => {
34   const result: Array<Record<string, any>> = []
35   if (formFields) {
36     formFields.forEach((fieldStr: string) => {
37       parseFormFields(JSON.parse(fieldStr), result)
38     })
39   }
40   // 固定添加发起人 ID 字段
41   result.unshift({
42     field: ProcessVariableEnum.START_USER_ID,
43     title: '发起人',
44     type: 'UserSelect',
45     required: true
46   })
47   return result
48 }
49
50 /**
51  * @description 表单数据权限配置,用于发起人节点 、审批节点、抄送节点
52  */
53 export function useFormFieldsPermission(defaultPermission: FieldPermissionType) {
54   // 字段权限配置. 需要有 field, title,  permissioin 属性
55   const fieldsPermissionConfig = ref<Array<Record<string, any>>>([])
56
57   const formType = inject<Ref<number>>('formType') // 表单类型
58
59   const formFields = inject<Ref<string[]>>('formFields') // 流程表单字段
60
61   const getNodeConfigFormFields = (nodeFormFields?: Array<Record<string, string>>) => {
62     nodeFormFields = toRaw(nodeFormFields)
63     fieldsPermissionConfig.value =
64       cloneDeep(nodeFormFields) || getDefaultFieldsPermission(unref(formFields))
65   }
66   // 默认的表单权限: 获取表单的所有字段,设置字段默认权限为只读
67   const getDefaultFieldsPermission = (formFields?: string[]) => {
68     let defaultFieldsPermission: Array<Record<string, any>> = []
69     if (formFields) {
70       defaultFieldsPermission = parseFormCreateFields(formFields).map((item) => {
71         return {
72           field: item.field,
73           title: item.title,
74           permission: defaultPermission
75         }
76       })
77     }
78     return defaultFieldsPermission
79   }
80
81   // 获取表单的所有字段,作为下拉框选项
82   const formFieldOptions = parseFormCreateFields(unref(formFields))
83
84   return {
85     formType,
86     fieldsPermissionConfig,
87     formFieldOptions,
88     getNodeConfigFormFields
89   }
90 }
91 /**
92  * @description 获取表单的字段
93  */
94 export function useFormFields() {
95   const formFields = inject<Ref<string[]>>('formFields') // 流程表单字段
96   return parseFormCreateFields(unref(formFields))
97 }
98
99 export type UserTaskFormType = {
100   //candidateParamArray: any[]
101   candidateStrategy: CandidateStrategy
102   approveMethod: ApproveMethodType
103   roleIds?: number[] // 角色
104   deptIds?: number[] // 部门
105   deptLevel?: number // 部门层级
106   userIds?: number[] // 用户
107   userGroups?: number[] // 用户组
108   postIds?: number[] // 岗位
109   expression?: string // 流程表达式
110   formUser?: string // 表单内用户字段
111   formDept?: string // 表单内部门字段
112   approveRatio?: number
113   rejectHandlerType?: RejectHandlerType
114   returnNodeId?: string
115   timeoutHandlerEnable?: boolean
116   timeoutHandlerType?: number
117   assignEmptyHandlerType?: AssignEmptyHandlerType
118   assignEmptyHandlerUserIds?: number[]
119   assignStartUserHandlerType?: AssignStartUserHandlerType
120   timeDuration?: number
121   maxRemindCount?: number
122   buttonsSetting: any[]
123 }
124
125 export type CopyTaskFormType = {
126   // candidateParamArray: any[]
127   candidateStrategy: CandidateStrategy
128   roleIds?: number[] // 角色
129   deptIds?: number[] // 部门
130   deptLevel?: number // 部门层级
131   userIds?: number[] // 用户
132   userGroups?: number[] // 用户组
133   postIds?: number[] // 岗位
134   formUser?: string // 表单内用户字段
135   formDept?: string // 表单内部门字段
136   expression?: string // 流程表达式
137 }
138
139 /**
140  * @description 节点表单数据。 用于审批节点、抄送节点
141  */
142 export function useNodeForm(nodeType: NodeType) {
143   const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
144   const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
145   const userOptions = inject<Ref<UserApi.UserVO[]>>('userList') // 用户列表
146   const deptOptions = inject<Ref<DeptApi.DeptVO[]>>('deptList') // 部门列表
147   const userGroupOptions = inject<Ref<UserGroupApi.UserGroupVO[]>>('userGroupList') // 用户组列表
148   const deptTreeOptions = inject('deptTree') // 部门树
149   const formFields = inject<Ref<string[]>>('formFields') // 流程表单字段
150   const configForm = ref<UserTaskFormType | CopyTaskFormType>()
151   if (nodeType === NodeType.USER_TASK_NODE) {
152     configForm.value = {
153       candidateStrategy: CandidateStrategy.USER,
154       approveMethod: ApproveMethodType.SEQUENTIAL_APPROVE,
155       approveRatio: 100,
156       rejectHandlerType: RejectHandlerType.FINISH_PROCESS,
157       assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT,
158       returnNodeId: '',
159       timeoutHandlerEnable: false,
160       timeoutHandlerType: 1,
161       timeDuration: 6, // 默认 6小时
162       maxRemindCount: 1, // 默认 提醒 1次
163       buttonsSetting: []
164     }
165   } else {
166     configForm.value = {
167       candidateStrategy: CandidateStrategy.USER
168     }
169   }
170
171   const getShowText = (): string => {
172     let showText = ''
173     // 指定成员
174     if (configForm.value?.candidateStrategy === CandidateStrategy.USER) {
175       if (configForm.value?.userIds!.length > 0) {
176         const candidateNames: string[] = []
177         userOptions?.value.forEach((item) => {
178           if (configForm.value?.userIds!.includes(item.id)) {
179             candidateNames.push(item.nickname)
180           }
181         })
182         showText = `指定成员:${candidateNames.join(',')}`
183       }
184     }
185     // 指定角色
186     if (configForm.value?.candidateStrategy === CandidateStrategy.ROLE) {
187       if (configForm.value.roleIds!.length > 0) {
188         const candidateNames: string[] = []
189         roleOptions?.value.forEach((item) => {
190           if (configForm.value?.roleIds!.includes(item.id)) {
191             candidateNames.push(item.name)
192           }
193         })
194         showText = `指定角色:${candidateNames.join(',')}`
195       }
196     }
197     // 指定部门
198     if (
199       configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER ||
200       configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER ||
201       configForm.value?.candidateStrategy === CandidateStrategy.MULTI_LEVEL_DEPT_LEADER
202     ) {
203       if (configForm.value?.deptIds!.length > 0) {
204         const candidateNames: string[] = []
205         deptOptions?.value.forEach((item) => {
206           if (configForm.value?.deptIds!.includes(item.id!)) {
207             candidateNames.push(item.name)
208           }
209         })
210         if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) {
211           showText = `部门成员:${candidateNames.join(',')}`
212         } else if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER) {
213           showText = `部门的负责人:${candidateNames.join(',')}`
214         } else {
215           showText = `多级部门的负责人:${candidateNames.join(',')}`
216         }
217       }
218     }
219
220     // 指定岗位
221     if (configForm.value?.candidateStrategy === CandidateStrategy.POST) {
222       if (configForm.value.postIds!.length > 0) {
223         const candidateNames: string[] = []
224         postOptions?.value.forEach((item) => {
225           if (configForm.value?.postIds!.includes(item.id!)) {
226             candidateNames.push(item.name)
227           }
228         })
229         showText = `指定岗位: ${candidateNames.join(',')}`
230       }
231     }
232     // 指定用户组
233     if (configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP) {
234       if (configForm.value?.userGroups!.length > 0) {
235         const candidateNames: string[] = []
236         userGroupOptions?.value.forEach((item) => {
237           if (configForm.value?.userGroups!.includes(item.id)) {
238             candidateNames.push(item.name)
239           }
240         })
241         showText = `指定用户组: ${candidateNames.join(',')}`
242       }
243     }
244
245     // 表单内用户字段
246     if (configForm.value?.candidateStrategy === CandidateStrategy.FORM_USER) {
247       const formFieldOptions = parseFormCreateFields(unref(formFields))
248       const item = formFieldOptions.find((item) => item.field === configForm.value?.formUser)
249       showText = `表单用户:${item?.title}`
250     }
251
252     // 表单内部门负责人
253     if (configForm.value?.candidateStrategy === CandidateStrategy.FORM_DEPT_LEADER) {
254       showText = `表单内部门负责人`
255     }
256
257     // 发起人自选
258     if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_SELECT) {
259       showText = `发起人自选`
260     }
261     // 发起人自己
262     if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) {
263       showText = `发起人自己`
264     }
265     // 发起人的部门负责人
266     if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_DEPT_LEADER) {
267       showText = `发起人的部门负责人`
268     }
269     // 发起人的部门负责人
270     if (
271       configForm.value?.candidateStrategy === CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER
272     ) {
273       showText = `发起人连续部门负责人`
274     }
275     // 流程表达式
276     if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) {
277       showText = `流程表达式:${configForm.value.expression}`
278     }
279     return showText
280   }
281
282   /**
283    *  处理候选人参数的赋值
284    */
285   const handleCandidateParam = () => {
286     let candidateParam: undefined | string = undefined
287     if (!configForm.value) {
288       return candidateParam
289     }
290     switch (configForm.value.candidateStrategy) {
291       case CandidateStrategy.USER:
292         candidateParam = configForm.value.userIds!.join(',')
293         break
294       case CandidateStrategy.ROLE:
295         candidateParam = configForm.value.roleIds!.join(',')
296         break
297       case CandidateStrategy.POST:
298         candidateParam = configForm.value.postIds!.join(',')
299         break
300       case CandidateStrategy.USER_GROUP:
301         candidateParam = configForm.value.userGroups!.join(',')
302         break
303       case CandidateStrategy.FORM_USER:
304         candidateParam = configForm.value.formUser!
305         break
306       case CandidateStrategy.EXPRESSION:
307         candidateParam = configForm.value.expression!
308         break
309       case CandidateStrategy.DEPT_MEMBER:
310       case CandidateStrategy.DEPT_LEADER:
311         candidateParam = configForm.value.deptIds!.join(',')
312         break
313       // 发起人部门负责人
314       case CandidateStrategy.START_USER_DEPT_LEADER:
315       case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER:
316         candidateParam = configForm.value.deptLevel + ''
317         break
318       // 指定连续多级部门的负责人
319       case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: {
320         // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级
321         const deptIds = configForm.value.deptIds!.join(',')
322         candidateParam = deptIds.concat('|' + configForm.value.deptLevel + '')
323         break
324       }
325       // 表单内部门的负责人
326       case CandidateStrategy.FORM_DEPT_LEADER: {
327         // 候选人参数格式: | 分隔 。左边为表单内部门字段。 右边为部门层级
328         const deptFieldOnForm = configForm.value.formDept!
329         candidateParam = deptFieldOnForm.concat('|' + configForm.value.deptLevel + '')
330         break
331       }
332       default:
333         break
334     }
335     return candidateParam
336   }
337   /**
338    *  解析候选人参数
339    */
340   const parseCandidateParam = (
341     candidateStrategy: CandidateStrategy,
342     candidateParam: string | undefined
343   ) => {
344     if (!configForm.value || !candidateParam) {
345       return
346     }
347     switch (candidateStrategy) {
348       case CandidateStrategy.USER: {
349         configForm.value.userIds = candidateParam.split(',').map((item) => +item)
350         break
351       }
352       case CandidateStrategy.ROLE:
353         configForm.value.roleIds = candidateParam.split(',').map((item) => +item)
354         break
355       case CandidateStrategy.POST:
356         configForm.value.postIds = candidateParam.split(',').map((item) => +item)
357         break
358       case CandidateStrategy.USER_GROUP:
359         configForm.value.userGroups = candidateParam.split(',').map((item) => +item)
360         break
361       case CandidateStrategy.FORM_USER:
362         configForm.value.formUser = candidateParam
363         break
364       case CandidateStrategy.EXPRESSION:
365         configForm.value.expression = candidateParam
366         break
367       case CandidateStrategy.DEPT_MEMBER:
368       case CandidateStrategy.DEPT_LEADER:
369         configForm.value.deptIds = candidateParam.split(',').map((item) => +item)
370         break
371       // 发起人部门负责人
372       case CandidateStrategy.START_USER_DEPT_LEADER:
373       case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER:
374         configForm.value.deptLevel = +candidateParam
375         break
376       // 指定连续多级部门的负责人
377       case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: {
378         // 候选人参数格式: | 分隔 。左边为部门(多个部门用 , 分隔)。 右边为部门层级
379         const paramArray = candidateParam.split('|')
380         configForm.value.deptIds = paramArray[0].split(',').map((item) => +item)
381         configForm.value.deptLevel = +paramArray[1]
382         break
383       }
384       // 表单内的部门负责人
385       case CandidateStrategy.FORM_DEPT_LEADER: {
386         // 候选人参数格式: | 分隔 。左边为表单内的部门字段。 右边为部门层级
387         const paramArray = candidateParam.split('|')
388         configForm.value.formDept = paramArray[0]
389         configForm.value.deptLevel = +paramArray[1]
390         break
391       }
392       default:
393         break
394     }
395   }
396   return {
397     configForm,
398     roleOptions,
399     postOptions,
400     userOptions,
401     userGroupOptions,
402     deptTreeOptions,
403     handleCandidateParam,
404     parseCandidateParam,
405     getShowText
406   }
407 }
408
409 /**
410  * @description 抽屉配置
411  */
412 export function useDrawer() {
413   // 抽屉配置是否可见
414   const settingVisible = ref(false)
415   // 关闭配置抽屉
416   const closeDrawer = () => {
417     settingVisible.value = false
418   }
419   // 打开配置抽屉
420   const openDrawer = () => {
421     settingVisible.value = true
422   }
423   return {
424     settingVisible,
425     closeDrawer,
426     openDrawer
427   }
428 }
429
430 /**
431  * @description 节点名称配置
432  */
433 export function useNodeName(nodeType: NodeType) {
434   // 节点名称
435   const nodeName = ref<string>()
436   // 节点名称输入框
437   const showInput = ref(false)
438   // 点击节点名称编辑图标
439   const clickIcon = () => {
440     showInput.value = true
441   }
442   // 节点名称输入框失去焦点
443   const blurEvent = () => {
444     showInput.value = false
445     nodeName.value = nodeName.value || (NODE_DEFAULT_NAME.get(nodeType) as string)
446   }
447   return {
448     nodeName,
449     showInput,
450     clickIcon,
451     blurEvent
452   }
453 }
454
455 export function useNodeName2(node: Ref<SimpleFlowNode>, nodeType: NodeType) {
456   // 显示节点名称输入框
457   const showInput = ref(false)
458   // 节点名称输入框失去焦点
459   const blurEvent = () => {
460     showInput.value = false
461     node.value.name = node.value.name || (NODE_DEFAULT_NAME.get(nodeType) as string)
462   }
463   // 点击节点标题进行输入
464   const clickTitle = () => {
465     showInput.value = true
466   }
467   return {
468     showInput,
469     clickTitle,
470     blurEvent
471   }
472 }
473
474 /**
475  * @description 根据节点任务状态,获取节点任务状态样式
476  */
477 export function useTaskStatusClass(taskStatus: TaskStatusEnum | undefined): string {
478   if (!taskStatus) {
479     return ''
480   }
481   if (taskStatus === TaskStatusEnum.APPROVE) {
482     return 'status-pass'
483   }
484   if (taskStatus === TaskStatusEnum.RUNNING) {
485     return 'status-running'
486   }
487   if (taskStatus === TaskStatusEnum.REJECT) {
488     return 'status-reject'
489   }
490   if (taskStatus === TaskStatusEnum.CANCEL) {
491     return 'status-cancel'
492   }
493
494   return ''
495 }