From 01713ff22d6a82c3f333563de5ff75d7555d04be Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Tue, 3 Jun 2025 10:11:26 +0800 Subject: [PATCH] =?UTF-8?q?review=EF=BC=9Abpm=20=E6=96=B9=E6=B3=95?= =?UTF-8?q?=E7=BB=9F=E4=B8=80=E4=BD=BF=E7=94=A8=20function=EF=BC=8C?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=A0=B7=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../nodes-config/condition-node-config.vue | 18 ++-- .../nodes-config/copy-task-node-config.vue | 31 +++++-- .../nodes-config/delay-timer-node-config.vue | 20 +++-- .../nodes-config/modules/condition-dialog.vue | 9 +- .../nodes-config/modules/condition.vue | 29 +++--- .../modules/http-request-param-setting.vue | 9 +- .../modules/http-request-setting.vue | 14 +-- .../modules/user-task-listener.vue | 8 +- .../nodes-config/router-node-config.vue | 30 ++++--- .../nodes-config/start-user-node-config.vue | 25 +++--- .../nodes-config/trigger-node-config.vue | 72 ++++++++------- .../nodes-config/user-task-node-config.vue | 37 +++++--- .../components/nodes-config/utils.ts | 20 ++--- .../components/nodes/copy-task-node.vue | 9 +- .../components/nodes/delay-timer-node.vue | 9 +- .../components/nodes/end-event-node.vue | 5 +- .../components/nodes/exclusive-node.vue | 37 ++++---- .../components/nodes/inclusive-node.vue | 35 ++++---- .../components/nodes/node-handler.vue | 7 +- .../components/nodes/parallel-node.vue | 26 +++--- .../components/nodes/router-node.vue | 11 +-- .../components/nodes/start-user-node.vue | 12 +-- .../components/nodes/trigger-node.vue | 11 +-- .../components/nodes/user-task-node.vue | 16 ++-- .../components/process-node-tree.vue | 9 +- .../components/simple-process-designer.vue | 32 ++++--- .../components/simple-process-model.vue | 59 ++++++------- .../simple-process-design/helpers.ts | 88 +++++++++---------- .../form/modules/simple-model-design.vue | 1 - .../detail/modules/operation-button.vue | 1 - 30 files changed, 377 insertions(+), 313 deletions(-) diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/condition-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/condition-node-config.vue index add81c941..ffa494726 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/condition-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/condition-node-config.vue @@ -20,6 +20,7 @@ import Condition from './modules/condition.vue'; defineOptions({ name: 'ConditionNodeConfig', }); + const props = defineProps({ conditionNode: { type: Object as () => SimpleFlowNode, @@ -58,7 +59,7 @@ const conditionRef = ref(); const fieldOptions = useFormFieldsAndStartUser(); // 流程表单字段和发起人字段 /** 保存配置 */ -const saveConfig = async () => { +async function saveConfig() { if (!currentNode.value.conditionSetting?.defaultFlow) { // 校验表单 const valid = await conditionRef.value.validate(); @@ -89,14 +90,14 @@ const saveConfig = async () => { } drawerApi.close(); return true; -}; +} const [Drawer, drawerApi] = useVbenDrawer({ title: currentNode.value.name, onConfirm: saveConfig, }); -const open = () => { +function open() { // 使用三元表达式代替 if-else,解决 linter 警告 condition.value = currentNode.value.conditionSetting ? cloneDeep(currentNode.value.conditionSetting) @@ -121,7 +122,7 @@ const open = () => { }; drawerApi.open(); -}; +} watch( () => props.conditionNode, @@ -130,11 +131,12 @@ watch( }, ); -const clickIcon = () => { +function clickIcon() { showInput.value = true; -}; +} + // 输入框失去焦点 -const blurEvent = () => { +function blurEvent() { showInput.value = false; currentNode.value.name = currentNode.value.name || @@ -142,7 +144,7 @@ const blurEvent = () => { props.nodeIndex, currentNode.value?.conditionSetting?.defaultFlow, ); -}; +} defineExpose({ open }); // 提供 open 方法,用于打开弹窗 diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/copy-task-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/copy-task-node-config.vue index 7e5a015ae..03f454c52 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/copy-task-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/copy-task-node-config.vue @@ -44,12 +44,14 @@ import { } from '../../helpers'; defineOptions({ name: 'CopyTaskNodeConfig' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + const deptLevelLabel = computed(() => { let label = '部门负责人来源'; label = @@ -59,6 +61,7 @@ const deptLevelLabel = computed(() => { : `${label}(发起人部门向上)`; return label; }); + // 抽屉配置 const [Drawer, drawerApi] = useVbenDrawer({ header: true, @@ -68,14 +71,18 @@ const [Drawer, drawerApi] = useVbenDrawer({ saveConfig(); }, }); + // 当前节点 const currentNode = useWatchNode(props); + // 节点名称 const { nodeName, showInput, clickIcon, blurEvent } = useNodeName( NodeType.COPY_TASK_NODE, ); + // 激活的 Tab 标签页 const activeTabName = ref('user'); + // 表单字段权限配置 const { formType, @@ -83,16 +90,20 @@ const { formFieldOptions, getNodeConfigFormFields, } = useFormFieldsPermission(FieldPermissionType.READ); + // 表单内用户字段选项, 必须是必填和用户选择器 const userFieldOnFormOptions = computed(() => { return formFieldOptions.filter((item) => item.type === 'UserSelect'); }); + // 表单内部门字段选项, 必须是必填和部门选择器 const deptFieldOnFormOptions = computed(() => { return formFieldOptions.filter((item) => item.type === 'DeptSelect'); }); + // 抄送人表单配置 const formRef = ref(); // 表单 Ref + // 表单校验规则 const formRules: Record = reactive({ candidateStrategy: [ @@ -127,6 +138,7 @@ const { handleCandidateParam, parseCandidateParam, } = useNodeForm(NodeType.COPY_TASK_NODE); + const configForm = tempConfigForm as Ref; // 抄送人策略, 去掉发起人自选 和 发起人自己 const copyUserStrategies = computed(() => { @@ -134,8 +146,9 @@ const copyUserStrategies = computed(() => { (item) => item.value !== CandidateStrategy.START_USER, ); }); + // 改变抄送人设置策略 -const changeCandidateStrategy = () => { +function changeCandidateStrategy() { configForm.value.userIds = []; configForm.value.deptIds = []; configForm.value.roleIds = []; @@ -144,9 +157,10 @@ const changeCandidateStrategy = () => { configForm.value.deptLevel = 1; configForm.value.formUser = ''; configForm.value.formDept = ''; -}; +} + // 保存配置 -const saveConfig = async () => { +async function saveConfig() { activeTabName.value = 'user'; if (!formRef.value) return false; const valid = await formRef.value.validate(); @@ -160,9 +174,10 @@ const saveConfig = async () => { currentNode.value.fieldsPermission = fieldsPermissionConfig.value; drawerApi.close(); return true; -}; +} + // 显示抄送节点配置, 由父组件传过来 -const showCopyTaskNodeConfig = (node: SimpleFlowNode) => { +function showCopyTaskNodeConfig(node: SimpleFlowNode) { nodeName.value = node.name; // 抄送人设置 configForm.value.candidateStrategy = node.candidateStrategy!; @@ -171,10 +186,10 @@ const showCopyTaskNodeConfig = (node: SimpleFlowNode) => { getNodeConfigFormFields(node.fieldsPermission); drawerApi.open(); -}; +} /** 批量更新权限 */ -const updatePermission = (type: string) => { +function updatePermission(type: string) { fieldsPermissionConfig.value.forEach((field) => { if (type === 'READ') { field.permission = FieldPermissionType.READ; @@ -184,7 +199,7 @@ const updatePermission = (type: string) => { field.permission = FieldPermissionType.NONE; } }); -}; +} // 在组件初始化时对表单字段进行处理 onMounted(() => { diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue index 643e4c9cf..2dca15fba 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/delay-timer-node-config.vue @@ -33,6 +33,7 @@ import { useNodeName, useWatchNode } from '../../helpers'; import { convertTimeUnit } from './utils'; defineOptions({ name: 'DelayTimerNodeConfig' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, @@ -48,6 +49,7 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName( ); // 抄送人表单配置 const formRef = ref(); // 表单 Ref + // 表单校验规则 const formRules: Record = reactive({ delayType: [ @@ -60,6 +62,7 @@ const formRules: Record = reactive({ { required: true, message: '延迟时间不能为空', trigger: 'change' }, ], }); + // 配置表单数据 const configForm = ref({ delayType: DelayTypeEnum.FIXED_TIME_DURATION, @@ -69,7 +72,7 @@ const configForm = ref({ }); // 获取显示文本 -const getShowText = (): string => { +function getShowText(): string { let showText = ''; if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) { showText = `延迟${configForm.value.timeDuration}${TIME_UNIT_TYPES?.find((item) => item.value === configForm.value.timeUnit)?.label}`; @@ -78,10 +81,10 @@ const getShowText = (): string => { showText = `延迟至${configForm.value.dateTime.replace('T', ' ')}`; } return showText; -}; +} // 获取ISO时间格式 -const getIsoTimeDuration = () => { +function getIsoTimeDuration() { let strTimeDuration = 'PT'; if (configForm.value.timeUnit === TimeUnitType.MINUTE) { strTimeDuration += `${configForm.value.timeDuration}M`; @@ -93,10 +96,10 @@ const getIsoTimeDuration = () => { strTimeDuration += `${configForm.value.timeDuration}D`; } return strTimeDuration; -}; +} // 保存配置 -const saveConfig = async () => { +async function saveConfig() { if (!formRef.value) return false; const valid = await formRef.value.validate(); if (!valid) return false; @@ -118,7 +121,7 @@ const saveConfig = async () => { } drawerApi.close(); return true; -}; +} const [Drawer, drawerApi] = useVbenDrawer({ title: nodeName.value, @@ -126,7 +129,7 @@ const [Drawer, drawerApi] = useVbenDrawer({ }); // 显示延迟器节点配置,由父组件调用 -const openDrawer = (node: SimpleFlowNode) => { +function openDrawer(node: SimpleFlowNode) { nodeName.value = node.name; if (node.delaySetting) { configForm.value.delayType = node.delaySetting.delayType; @@ -144,7 +147,7 @@ const openDrawer = (node: SimpleFlowNode) => { } } drawerApi.open(); -}; +} defineExpose({ openDrawer }); // 暴露方法给父组件 @@ -242,4 +245,3 @@ defineExpose({ openDrawer }); // 暴露方法给父组件 - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue index 289811650..f8fea7a2b 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition-dialog.vue @@ -50,15 +50,16 @@ const [Modal, modalApi] = useVbenModal({ }, }); -const open = (conditionObj: any | undefined) => { +// TODO: jason open 在 useVbenModal 中 onOpenChange 方法 +function open(conditionObj: any | undefined) { if (conditionObj) { conditionData.value.conditionType = conditionObj.conditionType; conditionData.value.conditionExpression = conditionObj.conditionExpression; conditionData.value.conditionGroups = conditionObj.conditionGroups; } modalApi.open(); -}; - +} +// TODO: jason 不需要暴露expose,直接使用modalApi.setData(formSetting).open() defineExpose({ open }); - - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition.vue index c0b1738ff..06cb93495 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/condition.vue @@ -38,13 +38,16 @@ import { useFormFieldsAndStartUser } from '../../../helpers'; defineOptions({ name: 'Condition', }); + const props = defineProps({ modelValue: { type: Object, required: true, }, }); + const emit = defineEmits(['update:modelValue']); + const condition = computed({ get() { return props.modelValue; @@ -81,35 +84,37 @@ const formRules: Record = reactive({ }, ], }); + const formRef = ref(); // 表单 Ref /** 切换条件配置方式 */ -const changeConditionType = () => { +function changeConditionType() { if ( condition.value.conditionType === ConditionType.RULE && !condition.value.conditionGroups ) { condition.value.conditionGroups = cloneDeep(DEFAULT_CONDITION_GROUP_VALUE); } -}; -const deleteConditionGroup = (conditions: any, index: number) => { +} + +function deleteConditionGroup(conditions: any, index: number) { conditions.splice(index, 1); -}; +} -const deleteConditionRule = (condition: any, index: number) => { +function deleteConditionRule(condition: any, index: number) { condition.rules.splice(index, 1); -}; +} -const addConditionRule = (condition: any, index: number) => { +function addConditionRule(condition: any, index: number) { const rule = { opCode: '==', leftSide: undefined, rightSide: '', }; condition.rules.splice(index + 1, 0, rule); -}; +} -const addConditionGroup = (conditions: any) => { +function addConditionGroup(conditions: any) { const condition = { and: true, rules: [ @@ -121,12 +126,12 @@ const addConditionGroup = (conditions: any) => { ], }; conditions.push(condition); -}; +} -const validate = async () => { +async function validate() { if (!formRef.value) return false; return await formRef.value.validate(); -}; +} defineExpose({ validate }); diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue index 6f18a06dc..40e859ea9 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-param-setting.vue @@ -42,18 +42,18 @@ const props = defineProps({ const formFieldOptions = useFormFieldsAndStartUser(); /** 添加请求配置项 */ -const addHttpRequestParam = (arr: HttpRequestParam[]) => { +function addHttpRequestParam(arr: HttpRequestParam[]) { arr.push({ key: '', type: BpmHttpRequestParamTypeEnum.FIXED_VALUE, value: '', }); -}; +} /** 删除请求配置项 */ -const deleteHttpRequestParam = (arr: HttpRequestParam[], index: number) => { +function deleteHttpRequestParam(arr: HttpRequestParam[], index: number) { arr.splice(index, 1); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue index 011ae8e19..6f96dc4cd 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/http-request-setting.vue @@ -33,8 +33,11 @@ const props = defineProps({ required: true, }, }); + const emits = defineEmits(['update:setting']); + const { setting } = toRefs(props); + watch( () => setting, (val) => { @@ -46,20 +49,20 @@ watch( const formFields = useFormFields(); /** 添加 HTTP 请求返回值设置项 */ -const addHttpResponseSetting = (responseSetting: Record[]) => { +function addHttpResponseSetting(responseSetting: Record[]) { responseSetting.push({ key: '', value: '', }); -}; +} /** 删除 HTTP 请求返回值设置项 */ -const deleteHttpResponseSetting = ( +function deleteHttpResponseSetting( responseSetting: Record[], index: number, -) => { +) { responseSetting.splice(index, 1); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue index e071c6d82..328d1662b 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/modules/user-task-listener.vue @@ -23,8 +23,11 @@ const props = defineProps({ required: true, }, }); + const emit = defineEmits(['update:modelValue']); + const listenerFormRef = ref(); + const configForm = computed({ get() { return props.modelValue; @@ -33,6 +36,7 @@ const configForm = computed({ emit('update:modelValue', newValue); }, }); + const taskListener = ref([ { name: '创建任务', @@ -48,10 +52,10 @@ const taskListener = ref([ }, ]); -const validate = async () => { +async function validate() { if (!listenerFormRef.value) return false; return await listenerFormRef.value.validate(); -}; +} defineExpose({ validate }); diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/router-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/router-node-config.vue index a1a553487..e42df7d24 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/router-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/router-node-config.vue @@ -26,12 +26,14 @@ import { useNodeName, useWatchNode } from '../../helpers'; import Condition from './modules/condition.vue'; defineOptions({ name: 'RouterNodeConfig' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + const processNodeTree = inject>('processNodeTree'); /** 当前节点 */ @@ -46,7 +48,7 @@ const conditionRef = ref([]); const formRef = ref(); /** 校验节点配置 */ -const validateConfig = async () => { +async function validateConfig() { // 校验路由分支选择 const routeIdValid = await formRef.value.validate().catch(() => false); if (!routeIdValid) { @@ -68,10 +70,10 @@ const validateConfig = async () => { if (!showText) return false; return true; -}; +} /** 保存配置 */ -const saveConfig = async () => { +async function saveConfig() { // 校验配置 if (!(await validateConfig())) { return false; @@ -82,7 +84,7 @@ const saveConfig = async () => { currentNode.value.routerGroups = routerGroups.value; drawerApi.close(); return true; -}; +} const [Drawer, drawerApi] = useVbenDrawer({ title: nodeName.value, @@ -90,7 +92,7 @@ const [Drawer, drawerApi] = useVbenDrawer({ }); /** 打开路由节点配置抽屉,由父组件调用 */ -const openDrawer = (node: SimpleFlowNode) => { +function openDrawer(node: SimpleFlowNode) { nodeOptions.value = []; getRouterNode(processNodeTree?.value); routerGroups.value = []; @@ -99,10 +101,10 @@ const openDrawer = (node: SimpleFlowNode) => { routerGroups.value = node.routerGroups; } drawerApi.open(); -}; +} /** 获取显示文本 */ -const getShowText = () => { +function getShowText() { if ( !routerGroups.value || !Array.isArray(routerGroups.value) || @@ -135,10 +137,10 @@ const getShowText = () => { } } return `${routerGroups.value.length}条路由分支`; -}; +} /** 添加路由分支 */ -const addRouterGroup = () => { +function addRouterGroup() { routerGroups.value.push({ nodeId: undefined, conditionType: ConditionType.RULE, @@ -159,15 +161,15 @@ const addRouterGroup = () => { ], }, }); -}; +} /** 删除路由分支 */ -const deleteRouterGroup = (index: number) => { +function deleteRouterGroup(index: number) { routerGroups.value.splice(index, 1); -}; +} /** 递归获取所有节点 */ -const getRouterNode = (node: any) => { +function getRouterNode(node: any) { // TODO 最好还需要满足以下要求 // 并行分支、包容分支内部节点不能跳转到外部节点 // 条件分支节点可以向上跳转到外部节点 @@ -192,7 +194,7 @@ const getRouterNode = (node: any) => { } node = node.childNode; } -}; +} defineExpose({ openDrawer }); // 暴露方法给父组件 diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/start-user-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/start-user-node-config.vue index f061b0768..bcdb3d9a2 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/start-user-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/start-user-node-config.vue @@ -37,12 +37,14 @@ import { } from '../../helpers'; defineOptions({ name: 'StartUserNodeConfig' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + // 可发起流程的用户编号 const startUserIds = inject>('startUserIds'); // 可发起流程的部门编号 @@ -59,10 +61,12 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName( ); // 激活的 Tab 标签页 const activeTabName = ref('user'); + // 表单字段权限配置 const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission(FieldPermissionType.WRITE); -const getUserNicknames = (userIds: number[]): string => { + +function getUserNicknames(userIds: number[]): string { if (!userIds || userIds.length === 0) { return ''; } @@ -74,9 +78,9 @@ const getUserNicknames = (userIds: number[]): string => { } }); return nicknames.join(','); -}; +} -const getDeptNames = (deptIds: number[]): string => { +function getDeptNames(deptIds: number[]): string { if (!deptIds || deptIds.length === 0) { return ''; } @@ -88,7 +92,7 @@ const getDeptNames = (deptIds: number[]): string => { } }); return deptNames.join(','); -}; +} // 使用 VbenDrawer const [Drawer, drawerApi] = useVbenDrawer({ @@ -103,7 +107,7 @@ const [Drawer, drawerApi] = useVbenDrawer({ }); // 保存配置 -const saveConfig = async () => { +async function saveConfig() { activeTabName.value = 'user'; currentNode.value.name = nodeName.value!; currentNode.value.showText = '已设置'; @@ -113,18 +117,18 @@ const saveConfig = async () => { currentNode.value.buttonsSetting = START_USER_BUTTON_SETTING; drawerApi.setState({ isOpen: false }); return true; -}; +} // 显示发起人节点配置,由父组件传过来 -const showStartUserNodeConfig = (node: SimpleFlowNode) => { +function showStartUserNodeConfig(node: SimpleFlowNode) { nodeName.value = node.name; // 表单字段权限 getNodeConfigFormFields(node.fieldsPermission); drawerApi.open(); -}; +} /** 批量更新权限 */ -const updatePermission = (type: string) => { +function updatePermission(type: string) { fieldsPermissionConfig.value.forEach((field) => { if (type === 'READ') { field.permission = FieldPermissionType.READ; @@ -134,7 +138,7 @@ const updatePermission = (type: string) => { field.permission = FieldPermissionType.NONE; } }); -}; +} /** * 暴露方法给父组件 @@ -289,4 +293,3 @@ defineExpose({ showStartUserNodeConfig }); - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/trigger-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/trigger-node-config.vue index e0431edf3..85b0726aa 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/trigger-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/trigger-node-config.vue @@ -76,6 +76,7 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName( ); // 触发器表单配置 const formRef = ref(); // 表单 Ref + // 表单校验规则 const formRules: Record = reactive({ type: [{ required: true, message: '触发器类型不能为空', trigger: 'change' }], @@ -83,6 +84,7 @@ const formRules: Record = reactive({ { required: true, message: '请求地址不能为空', trigger: 'blur' }, ], }); + // 触发器配置表单数据 const configForm = ref({ type: TriggerTypeEnum.HTTP_REQUEST, @@ -115,7 +117,7 @@ const optionalUpdateFormFields = computed(() => { let originalSetting: TriggerSetting | undefined; /** 触发器类型改变了 */ -const changeTriggerType = () => { +function changeTriggerType() { if (configForm.value.type === TriggerTypeEnum.HTTP_REQUEST) { configForm.value.httpRequestSetting = originalSetting?.type === TriggerTypeEnum.HTTP_REQUEST && @@ -176,44 +178,48 @@ const changeTriggerType = () => { ]; configForm.value.httpRequestSetting = undefined; } -}; +} /** 添加新的修改表单设置 */ -const addFormSetting = () => { +function addFormSetting() { configForm.value.formSettings!.push({ conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE), updateFormFields: {}, deleteFields: [], }); -}; +} /** 删除修改表单设置 */ -const deleteFormSetting = (index: number) => { +function deleteFormSetting(index: number) { configForm.value.formSettings!.splice(index, 1); -}; +} /** 添加条件配置 */ -const addFormSettingCondition = ( +function addFormSettingCondition( index: number, formSetting: FormTriggerSetting, -) => { +) { const conditionDialog = proxy.$refs[`condition-${index}`][0]; + // TODO: jason Modal 使用 useVbenModal 初始化,弹出使用modalApi.setData(formSetting).open() conditionDialog.open(formSetting); -}; +} + /** 删除条件配置 */ -const deleteFormSettingCondition = (formSetting: FormTriggerSetting) => { +function deleteFormSettingCondition(formSetting: FormTriggerSetting) { formSetting.conditionType = undefined; -}; +} + /** 打开条件配置弹窗 */ -const openFormSettingCondition = ( +function openFormSettingCondition( index: number, formSetting: FormTriggerSetting, -) => { +) { const conditionDialog = proxy.$refs[`condition-${index}`][0]; conditionDialog.open(formSetting); -}; +} + /** 处理条件配置保存 */ -const handleConditionUpdate = (index: number, condition: any) => { +function handleConditionUpdate(index: number, condition: any) { if (configForm.value.formSettings![index]) { configForm.value.formSettings![index].conditionType = condition.conditionType; @@ -222,50 +228,48 @@ const handleConditionUpdate = (index: number, condition: any) => { configForm.value.formSettings![index].conditionGroups = condition.conditionGroups; } -}; +} // 包含发起人字段的表单字段 const includeStartUserFormFields = useFormFieldsAndStartUser(); /** 条件配置展示 */ -const showConditionText = (formSetting: FormTriggerSetting) => { +function showConditionText(formSetting: FormTriggerSetting) { return getConditionShowText( formSetting.conditionType, formSetting.conditionExpression, formSetting.conditionGroups, includeStartUserFormFields, ); -}; +} /** 添加修改字段设置项 */ -const addFormFieldSetting = (formSetting: FormTriggerSetting) => { +function addFormFieldSetting(formSetting: FormTriggerSetting) { if (!formSetting) return; if (!formSetting.updateFormFields) { formSetting.updateFormFields = {}; } formSetting.updateFormFields[''] = undefined; -}; +} + /** 更新字段 KEY */ -const updateFormFieldKey = ( +function updateFormFieldKey( formSetting: FormTriggerSetting, oldKey: string, newKey: SelectValue, -) => { +) { if (!formSetting?.updateFormFields || !newKey) return; const value = formSetting.updateFormFields[oldKey]; delete formSetting.updateFormFields[oldKey]; formSetting.updateFormFields[String(newKey)] = value; -}; +} /** 删除修改字段设置项 */ -const deleteFormFieldSetting = ( - formSetting: FormTriggerSetting, - key: string, -) => { +function deleteFormFieldSetting(formSetting: FormTriggerSetting, key: string) { if (!formSetting?.updateFormFields) return; delete formSetting.updateFormFields[key]; -}; +} /** 保存配置 */ -const saveConfig = async () => { +async function saveConfig() { if (!formRef.value) return false; const valid = await formRef.value.validate(); if (!valid) return false; @@ -302,10 +306,10 @@ const saveConfig = async () => { currentNode.value.triggerSetting = configForm.value; drawerApi.close(); return true; -}; +} /** 获取节点展示内容 */ -const getShowText = (): string => { +function getShowText(): string { let showText = ''; switch (configForm.value.type) { case TriggerTypeEnum.FORM_DELETE: { @@ -342,10 +346,10 @@ const getShowText = (): string => { // No default } return showText; -}; +} /** 显示触发器节点配置, 由父组件传过来 */ -const showTriggerNodeConfig = (node: SimpleFlowNode) => { +function showTriggerNodeConfig(node: SimpleFlowNode) { nodeName.value = node.name; originalSetting = node.triggerSetting ? cloneDeep(node.triggerSetting) @@ -369,7 +373,7 @@ const showTriggerNodeConfig = (node: SimpleFlowNode) => { }; } drawerApi.open(); -}; +} // 暴露方法给父组件 defineExpose({ showTriggerNodeConfig }); diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/user-task-node-config.vue b/apps/web-antd/src/components/simple-process-design/components/nodes-config/user-task-node-config.vue index c70ae0a9d..1ee36fb1f 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/user-task-node-config.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/user-task-node-config.vue @@ -70,15 +70,18 @@ import UserTaskListener from './modules/user-task-listener.vue'; import { convertTimeUnit, getApproveTypeText } from './utils'; defineOptions({ name: 'UserTaskNodeConfig' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + const emits = defineEmits<{ findReturnTaskNodes: [nodeList: SimpleFlowNode[]]; }>(); + const deptLevelLabel = computed(() => { let label = '部门负责人来源'; if ( @@ -95,6 +98,7 @@ const deptLevelLabel = computed(() => { } return label; }); + // 监控节点的变化 const currentNode = useWatchNode(props); // 抽屉配置 @@ -106,12 +110,15 @@ const [Drawer, drawerApi] = useVbenDrawer({ saveConfig(); }, }); + // 节点名称配置 const { nodeName, showInput, clickIcon, blurEvent } = useNodeName( NodeType.USER_TASK_NODE, ); + // 激活的 Tab 标签页 const activeTabName = ref('user'); + // 表单字段权限设置 const { formType, @@ -119,10 +126,12 @@ const { formFieldOptions, getNodeConfigFormFields, } = useFormFieldsPermission(FieldPermissionType.READ); + // 表单内用户字段选项, 必须是必填和用户选择器 const userFieldOnFormOptions = computed(() => { return formFieldOptions.filter((item) => item.type === 'UserSelect'); }); + // 表单内部门字段选项, 必须是必填和部门选择器 const deptFieldOnFormOptions = computed(() => { return formFieldOptions.filter((item) => item.type === 'DeptSelect'); @@ -135,7 +144,9 @@ const { changeBtnDisplayName, btnDisplayNameBlurEvent, } = useButtonsSetting(); + const approveType = ref(ApproveType.USER); + // 审批人表单设置 const formRef = ref(); // 表单 Ref // 表单校验规则 @@ -197,7 +208,7 @@ const { const configForm = tempConfigForm as Ref; // 改变审批人设置策略 -const changeCandidateStrategy = () => { +function changeCandidateStrategy() { configForm.value.userIds = []; configForm.value.deptIds = []; configForm.value.roleIds = []; @@ -207,16 +218,16 @@ const changeCandidateStrategy = () => { configForm.value.formUser = ''; configForm.value.formDept = ''; configForm.value.approveMethod = ApproveMethodType.SEQUENTIAL_APPROVE; -}; +} /** 审批方式改变 */ -const approveMethodChanged = () => { +function approveMethodChanged() { configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS; if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { configForm.value.approveRatio = 100; } formRef.value.clearValidate('approveRatio'); -}; +} // 审批拒绝 可退回的节点 const returnTaskList = ref([]); // 审批人超时未处理设置 @@ -238,7 +249,7 @@ const nodeTypeName = computed(() => { }); /** 校验节点配置 */ -const validateConfig = async () => { +async function validateConfig() { if (!formRef.value) return false; if (!userTaskListenerRef.value) return false; @@ -262,9 +273,10 @@ const validateConfig = async () => { if (!showText) return false; return true; -}; +} + /** 保存配置 */ -const saveConfig = async () => { +async function saveConfig() { // 如果不是人工审批,不执行校验,直接返回 if (approveType.value !== ApproveType.USER) { currentNode.value.name = nodeName.value!; @@ -347,10 +359,10 @@ const saveConfig = async () => { currentNode.value.showText = getShowText(); drawerApi.close(); return true; -}; +} /** 显示审批节点配置, 由父组件传过来 */ -const showUserTaskNodeConfig = (node: SimpleFlowNode) => { +function showUserTaskNodeConfig(node: SimpleFlowNode) { nodeName.value = node.name; // 1 审批类型 approveType.value = @@ -429,7 +441,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { configForm.value.reasonRequire = node?.reasonRequire ?? false; drawerApi.open(); -}; +} defineExpose({ showUserTaskNodeConfig }); // 暴露方法给父组件 @@ -541,7 +553,7 @@ function useTimeoutHandler() { } /** 批量更新权限 */ -const updatePermission = (type: string) => { +function updatePermission(type: string) { fieldsPermissionConfig.value.forEach((field) => { if (type === 'READ') { field.permission = FieldPermissionType.READ; @@ -551,7 +563,8 @@ const updatePermission = (type: string) => { field.permission = FieldPermissionType.NONE; } }); -}; +} + // 在组件初始化时记录初始位置 onMounted(() => { // 固定添加发起人ID字段 diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes-config/utils.ts b/apps/web-antd/src/components/simple-process-design/components/nodes-config/utils.ts index c6ab47eca..ee5e06809 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes-config/utils.ts +++ b/apps/web-antd/src/components/simple-process-design/components/nodes-config/utils.ts @@ -1,29 +1,29 @@ import { APPROVE_TYPE, ApproveType, TimeUnitType } from '../../consts'; /** 获取条件节点默认的名称 */ -export const getDefaultConditionNodeName = ( +export function getDefaultConditionNodeName( index: number, defaultFlow: boolean | undefined, -): string => { +): string { if (defaultFlow) { return '其它情况'; } return `条件${index + 1}`; -}; +} /** 获取包容分支条件节点默认的名称 */ -export const getDefaultInclusiveConditionNodeName = ( +export function getDefaultInclusiveConditionNodeName( index: number, defaultFlow: boolean | undefined, -): string => { +): string { if (defaultFlow) { return '其它情况'; } return `包容条件${index + 1}`; -}; +} /** 转换时间单位字符串为枚举值 */ -export const convertTimeUnit = (strTimeUnit: string) => { +export function convertTimeUnit(strTimeUnit: string) { if (strTimeUnit === 'M') { return TimeUnitType.MINUTE; } @@ -34,10 +34,10 @@ export const convertTimeUnit = (strTimeUnit: string) => { return TimeUnitType.DAY; } return TimeUnitType.HOUR; -}; +} /** 根据审批类型获取对应的文本描述 */ -export const getApproveTypeText = (approveType: ApproveType): string => { +export function getApproveTypeText(approveType: ApproveType): string { let approveTypeText = ''; APPROVE_TYPE.forEach((item) => { if (item.value === approveType) { @@ -45,4 +45,4 @@ export const getApproveTypeText = (approveType: ApproveType): string => { } }); return approveTypeText; -}; +} diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/copy-task-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/copy-task-node.vue index a3226a576..c9bd17190 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/copy-task-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/copy-task-node.vue @@ -37,18 +37,18 @@ const { showInput, blurEvent, clickTitle } = useNodeName2( const nodeSetting = ref(); // 打开节点配置 -const openNodeConfig = () => { +function openNodeConfig() { if (readonly) { return; } nodeSetting.value.showCopyTaskNodeConfig(currentNode.value); nodeSetting.value.openDrawer(); -}; +} // 删除节点。更新当前节点为孩子节点 -const deleteNode = () => { +function deleteNode() { emits('update:flowNode', currentNode.value.childNode); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/delay-timer-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/delay-timer-node.vue index 59b887a4b..fa83d4ebe 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/delay-timer-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/delay-timer-node.vue @@ -35,17 +35,17 @@ const { showInput, blurEvent, clickTitle } = useNodeName2( const nodeSetting = ref(); // 打开节点配置 -const openNodeConfig = () => { +function openNodeConfig() { if (readonly) { return; } nodeSetting.value.openDrawer(currentNode.value); -}; +} // 删除节点。更新当前节点为孩子节点 -const deleteNode = () => { +function deleteNode() { emits('update:flowNode', currentNode.value.childNode); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/end-event-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/end-event-node.vue index cccca4dbb..c03fac9c9 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/end-event-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/end-event-node.vue @@ -22,7 +22,7 @@ const processInstance = inject>('processInstance', ref({})); const processInstanceInfos = ref([]); // 流程的审批信息 -const nodeClick = () => { +function nodeClick() { if (readonly && processInstance && processInstance.value) { console.warn( 'TODO 只读模式,弹窗显示审批信息', @@ -30,7 +30,7 @@ const nodeClick = () => { processInstanceInfos.value, ); } -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/exclusive-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/exclusive-node.vue index fb00d2e71..e37edc298 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/exclusive-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/exclusive-node.vue @@ -20,12 +20,14 @@ import ProcessNodeTree from '../process-node-tree.vue'; import NodeHandler from './node-handler.vue'; defineOptions({ name: 'ExclusiveNode' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + // 定义事件,更新父组件 const emits = defineEmits<{ findParentNode: [nodeList: SimpleFlowNode[], nodeType: number]; @@ -36,10 +38,12 @@ const emits = defineEmits<{ ]; 'update:modelValue': [node: SimpleFlowNode | undefined]; }>(); + const { proxy } = getCurrentInstance() as any; // 是否只读 const readonly = inject('readonly'); const currentNode = ref(props.flowNode); + watch( () => props.flowNode, (newValue) => { @@ -48,8 +52,9 @@ watch( ); const showInputs = ref([]); + // 失去焦点 -const blurEvent = (index: number) => { +function blurEvent(index: number) { showInputs.value[index] = false; const conditionNode = currentNode.value.conditionNodes?.at( index, @@ -60,23 +65,23 @@ const blurEvent = (index: number) => { index, conditionNode.conditionSetting?.defaultFlow, ); -}; +} // 点击条件名称 -const clickEvent = (index: number) => { +function clickEvent(index: number) { showInputs.value[index] = true; -}; +} -const conditionNodeConfig = (nodeId: string) => { +function conditionNodeConfig(nodeId: string) { if (readonly) { return; } const conditionNode = proxy.$refs[nodeId][0]; conditionNode.open(); -}; +} // 新增条件 -const addCondition = () => { +function addCondition() { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { const len = conditionNodes.length; @@ -96,10 +101,10 @@ const addCondition = () => { }; conditionNodes.splice(lastIndex, 0, conditionData); } -}; +} // 删除条件 -const deleteCondition = (index: number) => { +function deleteCondition(index: number) { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { conditionNodes.splice(index, 1); @@ -109,10 +114,10 @@ const deleteCondition = (index: number) => { emits('update:modelValue', childNode); } } -}; +} // 移动节点 -const moveNode = (index: number, to: number) => { +function moveNode(index: number, to: number) { // -1 :向左 1: 向右 if ( currentNode.value.conditionNodes && @@ -125,13 +130,14 @@ const moveNode = (index: number, to: number) => { currentNode.value.conditionNodes[index], )[0] as SimpleFlowNode; } -}; +} + // 递归从父节点中查询匹配的节点 -const recursiveFindParentNode = ( +function recursiveFindParentNode( nodeList: SimpleFlowNode[], node: SimpleFlowNode, nodeType: number, -) => { +) { if (!node || node.type === NodeType.START_USER_NODE) { return; } @@ -140,7 +146,7 @@ const recursiveFindParentNode = ( } // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.EXCLUSIVE_NODE) 继续查找 emits('findParentNode', nodeList, nodeType); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/inclusive-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/inclusive-node.vue index 8d613c8ca..cad293d7f 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/inclusive-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/inclusive-node.vue @@ -25,12 +25,14 @@ import NodeHandler from './node-handler.vue'; defineOptions({ name: 'InclusiveNode', }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + // 定义事件,更新父组件 const emits = defineEmits<{ findParentNode: [nodeList: SimpleFlowNode[], nodeType: number]; @@ -41,6 +43,7 @@ const emits = defineEmits<{ ]; 'update:modelValue': [node: SimpleFlowNode | undefined]; }>(); + const { proxy } = getCurrentInstance() as any; // 是否只读 const readonly = inject('readonly'); @@ -56,7 +59,7 @@ watch( const showInputs = ref([]); // 失去焦点 -const blurEvent = (index: number) => { +function blurEvent(index: number) { showInputs.value[index] = false; const conditionNode = currentNode.value.conditionNodes?.at( index, @@ -67,23 +70,23 @@ const blurEvent = (index: number) => { index, conditionNode.conditionSetting?.defaultFlow, ); -}; +} // 点击条件名称 -const clickEvent = (index: number) => { +function clickEvent(index: number) { showInputs.value[index] = true; -}; +} -const conditionNodeConfig = (nodeId: string) => { +function conditionNodeConfig(nodeId: string) { if (readonly) { return; } const conditionNode = proxy.$refs[nodeId][0]; conditionNode.open(); -}; +} // 新增条件 -const addCondition = () => { +function addCondition() { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { const len = conditionNodes.length; @@ -103,10 +106,10 @@ const addCondition = () => { }; conditionNodes.splice(lastIndex, 0, conditionData); } -}; +} // 删除条件 -const deleteCondition = (index: number) => { +function deleteCondition(index: number) { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { conditionNodes.splice(index, 1); @@ -116,10 +119,10 @@ const deleteCondition = (index: number) => { emits('update:modelValue', childNode); } } -}; +} // 移动节点 -const moveNode = (index: number, to: number) => { +function moveNode(index: number, to: number) { // -1 :向左 1: 向右 if ( currentNode.value.conditionNodes && @@ -132,13 +135,14 @@ const moveNode = (index: number, to: number) => { currentNode.value.conditionNodes[index], )[0] as SimpleFlowNode; } -}; +} + // 递归从父节点中查询匹配的节点 -const recursiveFindParentNode = ( +function recursiveFindParentNode( nodeList: SimpleFlowNode[], node: SimpleFlowNode, nodeType: number, -) => { +) { if (!node || node.type === NodeType.START_USER_NODE) { return; } @@ -147,7 +151,7 @@ const recursiveFindParentNode = ( } // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.INCLUSIVE_BRANCH_NODE) 继续查找 emits('findParentNode', nodeList, nodeType); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/node-handler.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/node-handler.vue index 01ab889dc..dee4e6985 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/node-handler.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/node-handler.vue @@ -33,11 +33,12 @@ const props = defineProps({ required: true, }, }); + const emits = defineEmits(['update:childNode']); const popoverShow = ref(false); const readonly = inject('readonly'); // 是否只读 -const addNode = (type: number) => { +function addNode(type: number) { // 校验:条件分支、包容分支后面,不允许直接添加并行分支 if ( type === NodeType.PARALLEL_BRANCH_NODE && @@ -238,7 +239,7 @@ const addNode = (type: number) => { }; emits('update:childNode', data); } -}; +} - - diff --git a/apps/web-antd/src/components/simple-process-design/components/nodes/parallel-node.vue b/apps/web-antd/src/components/simple-process-design/components/nodes/parallel-node.vue index f2424ca92..977de0955 100644 --- a/apps/web-antd/src/components/simple-process-design/components/nodes/parallel-node.vue +++ b/apps/web-antd/src/components/simple-process-design/components/nodes/parallel-node.vue @@ -14,12 +14,14 @@ import ProcessNodeTree from '../process-node-tree.vue'; import NodeHandler from './node-handler.vue'; defineOptions({ name: 'ParallelNode' }); + const props = defineProps({ flowNode: { type: Object as () => SimpleFlowNode, required: true, }, }); + // 定义事件,更新父组件 const emits = defineEmits<{ findParnetNode: [nodeList: SimpleFlowNode[], nodeType: number]; @@ -30,6 +32,7 @@ const emits = defineEmits<{ ]; 'update:modelValue': [node: SimpleFlowNode | undefined]; }>(); + const currentNode = ref(props.flowNode); // 是否只读 const readonly = inject('readonly'); @@ -42,22 +45,23 @@ watch( ); const showInputs = ref([]); + // 失去焦点 -const blurEvent = (index: number) => { +function blurEvent(index: number) { showInputs.value[index] = false; const conditionNode = currentNode.value.conditionNodes?.at( index, ) as SimpleFlowNode; conditionNode.name = conditionNode.name || `并行${index + 1}`; -}; +} // 点击条件名称 -const clickEvent = (index: number) => { +function clickEvent(index: number) { showInputs.value[index] = true; -}; +} // 新增条件 -const addCondition = () => { +function addCondition() { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { const len = conditionNodes.length; @@ -72,10 +76,10 @@ const addCondition = () => { }; conditionNodes.splice(lastIndex, 0, conditionData); } -}; +} // 删除条件 -const deleteCondition = (index: number) => { +function deleteCondition(index: number) { const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { conditionNodes.splice(index, 1); @@ -85,14 +89,14 @@ const deleteCondition = (index: number) => { emits('update:modelValue', childNode); } } -}; +} // 递归从父节点中查询匹配的节点 -const recursiveFindParentNode = ( +function recursiveFindParentNode( nodeList: SimpleFlowNode[], node: SimpleFlowNode, nodeType: number, -) => { +) { if (!node || node.type === NodeType.START_USER_NODE) { return; } @@ -101,7 +105,7 @@ const recursiveFindParentNode = ( } // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点并行节点(NodeType.PARALLEL_NODE) 继续查找 emits('findParnetNode', nodeList, nodeType); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/process-node-tree.vue b/apps/web-antd/src/components/simple-process-design/components/process-node-tree.vue index 25516b7f7..1efbce306 100644 --- a/apps/web-antd/src/components/simple-process-design/components/process-node-tree.vue +++ b/apps/web-antd/src/components/simple-process-design/components/process-node-tree.vue @@ -15,6 +15,7 @@ import TriggerNode from './nodes/trigger-node.vue'; import UserTaskNode from './nodes/user-task-node.vue'; defineOptions({ name: 'ProcessNodeTree' }); + const props = defineProps({ parentNode: { type: Object as () => SimpleFlowNode, @@ -25,6 +26,7 @@ const props = defineProps({ default: () => null, }, }); + const emits = defineEmits<{ recursiveFindParentNode: [ nodeList: SimpleFlowNode[], @@ -47,11 +49,11 @@ const findParentNode = (nodeList: SimpleFlowNode[], nodeType: number) => { }; // 递归从父节点中查询匹配的节点 -const recursiveFindParentNode = ( +function recursiveFindParentNode( nodeList: SimpleFlowNode[], findNode: SimpleFlowNode, nodeType: number, -) => { +) { if (!findNode) { return; } @@ -64,7 +66,7 @@ const recursiveFindParentNode = ( nodeList.push(findNode); } emits('recursiveFindParentNode', nodeList, props.parentNode, nodeType); -}; +} - diff --git a/apps/web-antd/src/components/simple-process-design/components/simple-process-designer.vue b/apps/web-antd/src/components/simple-process-design/components/simple-process-designer.vue index 7f2762ca1..c189e129a 100644 --- a/apps/web-antd/src/components/simple-process-design/components/simple-process-designer.vue +++ b/apps/web-antd/src/components/simple-process-design/components/simple-process-designer.vue @@ -116,7 +116,7 @@ const errorDialogVisible = ref(false); const errorNodes: SimpleFlowNode[] = []; // 添加更新模型的方法 -const updateModel = () => { +function updateModel() { if (!processNodeTree.value) { processNodeTree.value = { name: '发起人', @@ -131,11 +131,11 @@ const updateModel = () => { // 初始化时也触发一次保存 saveSimpleFlowModel(processNodeTree.value); } -}; +} -const saveSimpleFlowModel = async ( +async function saveSimpleFlowModel( simpleModelNode: SimpleFlowNode | undefined, -) => { +) { if (!simpleModelNode) { return; } @@ -146,16 +146,15 @@ const saveSimpleFlowModel = async ( } catch (error) { console.error('保存失败:', error); } -}; +} /** * 校验节点设置。 暂时以 showText 为空 未节点错误配置 */ -// eslint-disable-next-line unused-imports/no-unused-vars, no-unused-vars -const validateNode = ( +function validateNode( node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[], -) => { +) { if (node) { const { type, showText, conditionNodes } = node; if (type === NodeType.END_EVENT_NODE) { @@ -163,7 +162,7 @@ const validateNode = ( } if (type === NodeType.START_USER_NODE) { // 发起人节点暂时不用校验,直接校验孩子节点 - validateNode(node.childNode, errorNodes); + useValidateNode(node.childNode, errorNodes); } if ( @@ -174,7 +173,7 @@ const validateNode = ( if (!showText) { errorNodes.push(node); } - validateNode(node.childNode, errorNodes); + useValidateNode(node.childNode, errorNodes); } if ( @@ -185,13 +184,20 @@ const validateNode = ( // 分支节点 // 1. 先校验各个分支 conditionNodes?.forEach((item) => { - validateNode(item, errorNodes); + useValidateNode(item, errorNodes); }); // 2. 校验孩子节点 - validateNode(node.childNode, errorNodes); + useValidateNode(node.childNode, errorNodes); } } -}; +} + +function useValidateNode( + node: SimpleFlowNode | undefined, + errorNodes: SimpleFlowNode[], +) { + validateNode(node, errorNodes); +} onMounted(async () => { try { diff --git a/apps/web-antd/src/components/simple-process-design/components/simple-process-model.vue b/apps/web-antd/src/components/simple-process-design/components/simple-process-model.vue index cfd2e6a84..b09c4e079 100644 --- a/apps/web-antd/src/components/simple-process-design/components/simple-process-model.vue +++ b/apps/web-antd/src/components/simple-process-design/components/simple-process-model.vue @@ -49,22 +49,22 @@ const currentY = ref(0); const initialX = ref(0); const initialY = ref(0); -const setGrabCursor = () => { +function setGrabCursor() { document.body.style.cursor = 'grab'; -}; +} -const resetCursor = () => { +function resetCursor() { document.body.style.cursor = 'default'; -}; +} -const startDrag = (e: MouseEvent) => { +function startDrag(e: MouseEvent) { isDragging.value = true; startX.value = e.clientX - currentX.value; startY.value = e.clientY - currentY.value; setGrabCursor(); // 设置小手光标 -}; +} -const onDrag = (e: MouseEvent) => { +function onDrag(e: MouseEvent) { if (!isDragging.value) return; e.preventDefault(); // 禁用文本选择 @@ -73,44 +73,44 @@ const onDrag = (e: MouseEvent) => { currentX.value = e.clientX - startX.value; currentY.value = e.clientY - startY.value; }); -}; +} -const stopDrag = () => { +function stopDrag() { isDragging.value = false; resetCursor(); // 重置光标 -}; +} -const zoomIn = () => { +function zoomIn() { if (scaleValue.value === MAX_SCALE_VALUE) { return; } scaleValue.value += 10; -}; +} -const zoomOut = () => { +function zoomOut() { if (scaleValue.value === MIN_SCALE_VALUE) { return; } scaleValue.value -= 10; -}; +} -const processReZoom = () => { +function processReZoom() { scaleValue.value = 100; -}; +} -const resetPosition = () => { +function resetPosition() { currentX.value = initialX.value; currentY.value = initialY.value; -}; +} /** 校验节点设置 */ const errorDialogVisible = ref(false); let errorNodes: SimpleFlowNode[] = []; -const validateNode = ( +function validateNode( node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[], -) => { +) { if (node) { const { type, showText, conditionNodes } = node; if (type === NodeType.END_EVENT_NODE) { @@ -146,10 +146,10 @@ const validateNode = ( validateNode(node.childNode, errorNodes); } } -}; +} /** 获取当前流程数据 */ -const getCurrentFlowData = async () => { +async function getCurrentFlowData() { try { errorNodes = []; validateNode(processNodeTree.value, errorNodes); @@ -162,26 +162,26 @@ const getCurrentFlowData = async () => { console.error('获取流程数据失败:', error); return undefined; } -}; +} defineExpose({ getCurrentFlowData, }); /** 导出 JSON */ -const exportJson = () => { +function exportJson() { downloadFileFromBlob({ fileName: 'model.json', source: new Blob([JSON.stringify(processNodeTree.value)]), }); -}; +} /** 导入 JSON */ const refFile = ref(); -const importJson = () => { +function importJson() { refFile.value.click(); -}; -const importLocalFile = () => { +} +function importLocalFile() { const file = refFile.value.files[0]; file.text().then((result: any) => { if (isString(result)) { @@ -189,7 +189,7 @@ const importLocalFile = () => { emits('save', processNodeTree.value); } }); -}; +} // 在组件初始化时记录初始位置 onMounted(() => { @@ -267,4 +267,3 @@ onMounted(() => { - diff --git a/apps/web-antd/src/components/simple-process-design/helpers.ts b/apps/web-antd/src/components/simple-process-design/helpers.ts index 9fddcb13c..6423111a8 100644 --- a/apps/web-antd/src/components/simple-process-design/helpers.ts +++ b/apps/web-antd/src/components/simple-process-design/helpers.ts @@ -43,7 +43,7 @@ export function useWatchNode(props: { } // 解析 formCreate 所有表单字段, 并返回 -const parseFormCreateFields = (formFields?: string[]) => { +function parseFormCreateFields(formFields?: string[]) { const result: Array> = []; if (formFields) { formFields.forEach((fieldStr: string) => { @@ -51,7 +51,7 @@ const parseFormCreateFields = (formFields?: string[]) => { }); } return result; -}; +} /** * 解析表单组件的 field, title 等字段(递归,如果组件包含子组件) @@ -109,20 +109,20 @@ export function useFormFieldsPermission( const formFields = inject>('formFields', ref([])); // 流程表单字段 - const getNodeConfigFormFields = ( + function getNodeConfigFormFields( nodeFormFields?: Array>, - ) => { + ) { nodeFormFields = toRaw(nodeFormFields); fieldsPermissionConfig.value = !nodeFormFields || nodeFormFields.length === 0 ? getDefaultFieldsPermission(unref(formFields)) : mergeFieldsPermission(nodeFormFields, unref(formFields)); - }; + } // 合并已经设置的表单字段权限,当前流程表单字段 (可能新增,或删除了字段) - const mergeFieldsPermission = ( + function mergeFieldsPermission( formFieldsPermisson: Array>, formFields?: string[], - ) => { + ) { let mergedFieldsPermission: Array> = []; if (formFields) { mergedFieldsPermission = parseFormCreateFields(formFields).map((item) => { @@ -137,10 +137,10 @@ export function useFormFieldsPermission( }); } return mergedFieldsPermission; - }; + } // 默认的表单权限: 获取表单的所有字段,设置字段默认权限为只读 - const getDefaultFieldsPermission = (formFields?: string[]) => { + function getDefaultFieldsPermission(formFields?: string[]) { let defaultFieldsPermission: Array> = []; if (formFields) { defaultFieldsPermission = parseFormCreateFields(formFields).map( @@ -154,7 +154,7 @@ export function useFormFieldsPermission( ); } return defaultFieldsPermission; - }; + } // 获取表单的所有字段,作为下拉框选项 const formFieldOptions = parseFormCreateFields(unref(formFields)); @@ -268,7 +268,6 @@ export function useNodeForm(nodeType: NodeType) { const formFields = inject>('formFields', ref([])); // 流程表单字段 const configForm = ref(); - // eslint-disable-next-line unicorn/prefer-ternary if ( nodeType === NodeType.USER_TASK_NODE || nodeType === NodeType.TRANSACTOR_NODE @@ -286,13 +285,12 @@ export function useNodeForm(nodeType: NodeType) { maxRemindCount: 1, // 默认 提醒 1次 buttonsSetting: [], }; - } else { - configForm.value = { - candidateStrategy: CandidateStrategy.USER, - }; } + configForm.value = { + candidateStrategy: CandidateStrategy.USER, + }; - const getShowText = (): string => { + function getShowText(): string { let showText = ''; // 指定成员 if ( @@ -428,12 +426,12 @@ export function useNodeForm(nodeType: NodeType) { showText = `流程表达式:${configForm.value.expression}`; } return showText; - }; + } /** * 处理候选人参数的赋值 */ - const handleCandidateParam = () => { + function handleCandidateParam() { let candidateParam: string | undefined; if (!configForm.value) { return candidateParam; @@ -495,14 +493,14 @@ export function useNodeForm(nodeType: NodeType) { } } return candidateParam; - }; + } /** * 解析候选人参数 */ - const parseCandidateParam = ( + function parseCandidateParam( candidateStrategy: CandidateStrategy, candidateParam: string | undefined, - ) => { + ) { if (!configForm.value || !candidateParam) { return; } @@ -578,7 +576,7 @@ export function useNodeForm(nodeType: NodeType) { break; } } - }; + } return { configForm, roleOptions, @@ -599,13 +597,13 @@ export function useDrawer() { // 抽屉配置是否可见 const settingVisible = ref(false); // 关闭配置抽屉 - const closeDrawer = () => { + function closeDrawer() { settingVisible.value = false; - }; + } // 打开配置抽屉 - const openDrawer = () => { + function openDrawer() { settingVisible.value = true; - }; + } return { settingVisible, closeDrawer, @@ -622,15 +620,15 @@ export function useNodeName(nodeType: NodeType) { // 节点名称输入框 const showInput = ref(false); // 点击节点名称编辑图标 - const clickIcon = () => { + function clickIcon() { showInput.value = true; - }; + } // 节点名称输入框失去焦点 - const blurEvent = () => { + function blurEvent() { showInput.value = false; nodeName.value = nodeName.value || (NODE_DEFAULT_NAME.get(nodeType) as string); - }; + } return { nodeName, showInput, @@ -643,15 +641,15 @@ export function useNodeName2(node: Ref, nodeType: NodeType) { // 显示节点名称输入框 const showInput = ref(false); // 节点名称输入框失去焦点 - const blurEvent = () => { + function blurEvent() { showInput.value = false; node.value.name = node.value.name || (NODE_DEFAULT_NAME.get(nodeType) as string); - }; + } // 点击节点标题进行输入 - const clickTitle = () => { + function clickTitle() { showInput.value = true; - }; + } return { showInput, clickTitle, @@ -722,40 +720,40 @@ export function getConditionShowText( } /** 获取表单字段名称*/ -const getFormFieldTitle = ( +function getFormFieldTitle( fieldOptions: Array>, field: string, -) => { +) { const item = fieldOptions.find((item) => item.field === field); return item?.title; -}; +} /** 获取操作符名称 */ -const getOpName = (opCode: string): string | undefined => { +function getOpName(opCode: string): string | undefined { const opName = COMPARISON_OPERATORS.find( (item: any) => item.value === opCode, ); return opName?.label; -}; +} /** 获取条件节点默认的名称 */ -export const getDefaultConditionNodeName = ( +export function getDefaultConditionNodeName( index: number, defaultFlow: boolean | undefined, -): string => { +): string { if (defaultFlow) { return '其它情况'; } return `条件${index + 1}`; -}; +} /** 获取包容分支条件节点默认的名称 */ -export const getDefaultInclusiveConditionNodeName = ( +export function getDefaultInclusiveConditionNodeName( index: number, defaultFlow: boolean | undefined, -): string => { +): string { if (defaultFlow) { return '其它情况'; } return `包容条件${index + 1}`; -}; +} diff --git a/apps/web-antd/src/views/bpm/model/form/modules/simple-model-design.vue b/apps/web-antd/src/views/bpm/model/form/modules/simple-model-design.vue index d503f2de6..0401157a4 100644 --- a/apps/web-antd/src/views/bpm/model/form/modules/simple-model-design.vue +++ b/apps/web-antd/src/views/bpm/model/form/modules/simple-model-design.vue @@ -37,4 +37,3 @@ const handleSuccess = (data?: any) => { /> - diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue b/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue index f00c58ab1..57265935a 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue @@ -1389,4 +1389,3 @@ defineExpose({ loadTodoTask }); -