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