From d7e6523dadb931cda5f3919a6dbcbae993f088e2 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 4 Jan 2025 15:24:38 +0800 Subject: [PATCH 01/86] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E3=80=91=E5=BB=B6=E8=BF=9F=E5=99=A8=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E7=9A=84=E9=AB=98=E4=BA=AE=E6=98=BE=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../detail/ProcessInstanceSimpleViewer.vue | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue b/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue index 0808bec9..0017d3fe 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue @@ -82,7 +82,6 @@ const setSimpleModelNodeTaskStatus = ( } return } - // 审批节点 if ( simpleModel.type === NodeType.START_USER_NODE || @@ -98,26 +97,33 @@ const setSimpleModelNodeTaskStatus = ( } // TODO 是不是还缺一个 cancel 的状态 } - // 抄送节点 if (simpleModel.type === NodeType.COPY_TASK_NODE) { - // 抄送节点 只有通过和未执行状态 + // 抄送节点,只有通过和未执行状态 if (finishedActivityIds.includes(simpleModel.id)) { simpleModel.activityStatus = TaskStatusEnum.APPROVE } else { simpleModel.activityStatus = TaskStatusEnum.NOT_START } } - // 条件节点 对应 SequenceFlow + // 延迟器节点 + if (simpleModel.type === NodeType.DELAY_TIMER_NODE) { + // 延迟器节点,只有通过和未执行状态 + if (finishedActivityIds.includes(simpleModel.id)) { + simpleModel.activityStatus = TaskStatusEnum.APPROVE + } else { + simpleModel.activityStatus = TaskStatusEnum.NOT_START + } + } + // 条件节点对应 SequenceFlow if (simpleModel.type === NodeType.CONDITION_NODE) { - // 条件节点。只有通过和未执行状态 + // 条件节点,只有通过和未执行状态 if (finishedSequenceFlowActivityIds.includes(simpleModel.id)) { simpleModel.activityStatus = TaskStatusEnum.APPROVE } else { simpleModel.activityStatus = TaskStatusEnum.NOT_START } } - // 网关节点 if ( simpleModel.type === NodeType.CONDITION_BRANCH_NODE || @@ -155,13 +161,13 @@ const setSimpleModelNodeTaskStatus = ( diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/RouteNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/RouteNode.vue new file mode 100644 index 00000000..76f7dbe9 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/RouteNode.vue @@ -0,0 +1,98 @@ + + + + From 0a15eca573ea5254a915b41d38384cc0cccf716d Mon Sep 17 00:00:00 2001 From: LesanOuO <1960681385@qq.com> Date: Mon, 6 Jan 2025 12:49:55 +0800 Subject: [PATCH 03/86] =?UTF-8?q?feat:=20=E5=AE=A1=E6=89=B9=E4=BA=BA?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E4=B8=80=E8=A1=8C=E4=B8=89=E4=B8=AA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/UserTaskNodeConfig.vue | 21 +++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index fb5e780e..d4b1101f 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -3,7 +3,7 @@ :append-to-body="true" v-model="settingVisible" :show-close="false" - :size="550" + :size="580" :before-close="saveConfig" class="justify-start" > @@ -46,14 +46,13 @@ v-model="configForm.candidateStrategy" @change="changeCandidateStrategy" > - - {{ dict.label }} - + + + + {{ dict.label }} + + + @@ -163,7 +162,7 @@ :key="idx" :label="item.title" :value="item.field" - :disabled ="!item.required" + :disabled="!item.required" /> From 739a1c29a2eeeb27de96718d534fb63ccc0b846a Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Mon, 6 Jan 2025 17:25:59 +0800 Subject: [PATCH 04/86] =?UTF-8?q?feat:=20Simple=E8=AE=BE=E8=AE=A1=E5=99=A8?= =?UTF-8?q?-=E7=9B=91=E5=90=AC=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 5 +- .../SimpleProcessDesignerV2/src/consts.ts | 27 +++ .../src/nodes-config/UserTaskNodeConfig.vue | 155 +++++++++++++++++- 3 files changed, 184 insertions(+), 3 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 4dfd51ad..13ce4387 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -120,7 +120,10 @@ const addNode = (type: number) => { type: AssignEmptyHandlerType.APPROVE }, assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT, - childNode: props.childNode + childNode: props.childNode, + createTaskListener: { + enable: false + } } emits('update:childNode', data) } diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 10d8a21b..9a20d0f8 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -93,6 +93,8 @@ export interface SimpleFlowNode { assignEmptyHandler?: AssignEmptyHandler // 审批节点的审批人与发起人相同时,对应的处理类型 assignStartUserHandlerType?: number + // 创建任务监听器 + createTaskListener: ListenerHandler // 条件类型 conditionType?: ConditionType // 条件表达式 @@ -222,6 +224,31 @@ export type AssignEmptyHandler = { userIds?: number[] } +/** + * 监听器的结构定义 + */ +export type ListenerHandler = { + enable: boolean + path: string + header: ListenerMap[] + body: ListenerMap[] +} +export type ListenerMap = { + key: string + type: number + value: string +} +export const LISTENER_MAP_TYPES = [ + { + value: 1, + label: '固定值' + }, + { + value: 2, + label: '表单' + } +] + // 审批拒绝类型枚举 export enum RejectHandlerType { /** diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index d4b1101f..82aecbe5 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -434,6 +434,133 @@ + +
+ + + 创建任务 + + + + +
+ + + + + + + +
+
+ +
+
+ + + +
+
+ +
+
+ +
+
+ + 添加一行 + +
+ +
+
+ +
+
+ + + +
+
+ +
+
+ +
+
+ + 添加一行 + +
+
+ + + 指派任务执行人员 + + + + + + + 完成任务 + + + + +
+
+
- + - + @@ -81,7 +81,7 @@ const { settingVisible, closeDrawer, openDrawer } = useDrawer() const currentNode = useWatchNode(props) // 节点名称 const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.ROUTE_BRANCH_NODE) -const routeGroups = ref([]) +const routerGroups = ref([]) const nodeOptions = ref() // 保存配置 @@ -90,26 +90,26 @@ const saveConfig = async () => { if (!showText) return false currentNode.value.name = nodeName.value! currentNode.value.showText = showText - currentNode.value.routeGroups = routeGroups.value + currentNode.value.routerGroups = routerGroups.value settingVisible.value = false return true } // 显示路由分支节点配置, 由父组件传过来 const showRouteNodeConfig = (node: SimpleFlowNode) => { getRoutableNode() - routeGroups.value = [] + routerGroups.value = [] nodeName.value = node.name - if (node.routeGroups) { - routeGroups.value = node.routeGroups + if (node.routerGroups) { + routerGroups.value = node.routerGroups } } const getShowText = () => { - if (!routeGroups.value || !Array.isArray(routeGroups.value) || routeGroups.value.length <= 0) { + if (!routerGroups.value || !Array.isArray(routerGroups.value) || routerGroups.value.length <= 0) { message.warning('请配置路由!') return '' } - for (const route of routeGroups.value) { + for (const route of routerGroups.value) { if (!route.nodeId || !route.conditionType) { message.warning('请完善路由配置项!') return '' @@ -129,11 +129,11 @@ const getShowText = () => { } } } - return `${routeGroups.value.length}条路由分支` + return `${routerGroups.value.length}条路由分支` } const addRouteGroup = () => { - routeGroups.value.push({ + routerGroups.value.push({ nodeId: '', conditionType: ConditionType.RULE, conditionExpression: '', @@ -158,7 +158,7 @@ const addRouteGroup = () => { } const deleteRouteGroup = (index) => { - routeGroups.value.splice(index, 1) + routerGroups.value.splice(index, 1) } const getRoutableNode = () => { diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 962ce9cc..66887a7e 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -482,12 +482,12 @@
@@ -505,7 +505,7 @@ icon="ep:delete" :size="18" @click=" - deleteTaskListenerMap( + deleteTaskListenerParam( configForm[`task${listener.type}ListenerHeader`], index ) @@ -516,7 +516,7 @@ 添加一行 @@ -542,12 +542,12 @@
@@ -565,7 +565,7 @@ icon="ep:delete" :size="18" @click=" - deleteTaskListenerMap( + deleteTaskListenerParam( configForm[`task${listener.type}ListenerBody`], index ) @@ -576,7 +576,7 @@ 添加一行 @@ -623,7 +623,7 @@ import { FieldPermissionType, ProcessVariableEnum, LISTENER_MAP_TYPES, - ListenerMapTypeEnum + ListenerParamTypeEnum } from '../consts' import { @@ -1032,14 +1032,14 @@ function useTimeoutHandler() { } } -const addTaskListenerMap = (arr) => { +const addTaskListenerParam = (arr) => { arr.push({ key: '', type: 1, value: '' }) } -const deleteTaskListenerMap = (arr, index) => { +const deleteTaskListenerParam = (arr, index) => { arr.splice(index, 1) } From 5fa2a78e849558e30c4fdd9b45dbf65b659eb146 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Wed, 8 Jan 2025 15:03:06 +0800 Subject: [PATCH 17/86] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E7=9B=91?= =?UTF-8?q?=E5=90=AC=E5=99=A8=E8=AF=B7=E6=B1=82=E5=9C=B0=E5=9D=80=E9=9D=9E?= =?UTF-8?q?=E7=A9=BA=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/UserTaskNodeConfig.vue | 290 +++++++++--------- 1 file changed, 148 insertions(+), 142 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 66887a7e..3e497b4a 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -436,155 +436,161 @@
-
- -
- - {{ listener.name }} - + +
+ + {{ listener.name }} + + + + +
- -
- - - - - - - -
-
- -
-
- - - -
-
- - - - -
-
- -
+ + + + +
+
+
- - 添加一行 - - - -
-
- -
-
- - - -
-
- + + - - - -
-
- -
+
- - 添加一行 - -
-
+
+ + + + +
+
+ +
+
+ + 添加一行 + +
+ +
+
+ +
+
+ + + +
+
+ + + + +
+
+ +
+
+ + 添加一行 + +
- -
+
+
- + @@ -84,8 +87,17 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.ROUTE const routerGroups = ref([]) const nodeOptions = ref() +const conditionRef = ref([]) // 保存配置 const saveConfig = async () => { + // 校验表单 + let valid = true + for (const item of conditionRef.value) { + if (!(await item.validate())) { + valid = false + } + } + if (!valid) return false const showText = getShowText() if (!showText) return false currentNode.value.name = nodeName.value! diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue index e8fe1d76..85f6e4a0 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue @@ -59,15 +59,24 @@
- - - + + + + +
@@ -80,7 +89,16 @@
- + + +
@@ -122,8 +140,8 @@ import { ConditionType, ProcessVariableEnum } from '../../consts' -import {BpmModelFormType} from '@/utils/constants' -import {useFormFields} from '../../node' +import { BpmModelFormType } from '@/utils/constants' +import { useFormFields } from '../../node' const props = defineProps({ modelValue: { @@ -202,10 +220,10 @@ const addConditionGroup = (conditions) => { const validate = async () => { if (!formRef) return false - return await formRef.value.validate(); + return await formRef.value.validate() } -defineExpose({validate}) +defineExpose({ validate }) diff --git a/src/views/bpm/simple/SimpleModelDesign.vue b/src/views/bpm/simple/SimpleModelDesign.vue index eed00997..e07a04c9 100644 --- a/src/views/bpm/simple/SimpleModelDesign.vue +++ b/src/views/bpm/simple/SimpleModelDesign.vue @@ -23,7 +23,7 @@ const props = defineProps<{ modelId?: string modelKey?: string modelName?: string - value?: string + value?: any startUserIds?: number[] }>() @@ -34,7 +34,6 @@ const currentValue = ref('') // 初始化或更新当前值 const initOrUpdateValue = async () => { - console.log('initOrUpdateValue', props.value) if (props.value) { currentValue.value = props.value // 如果设计器已经初始化,立即加载数据 From 3d8f1290c3c023f34567978d8eebb9985881dc98 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Tue, 14 Jan 2025 08:46:08 +0800 Subject: [PATCH 30/86] =?UTF-8?q?perf:=20bpm=20=E6=B5=81=E7=A8=8B=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E8=A1=A8=E5=8D=95=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= =?UTF-8?q?.=20=E5=8E=BB=E6=8E=89=E5=A4=A7=E9=87=8Fwatch=20=E4=BB=A3?= =?UTF-8?q?=E7=A0=81.=20=E7=94=A8=E4=BE=9D=E8=B5=96=E6=B3=A8=E5=85=A5?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2props=20=E4=BC=A0=E9=80=92=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E6=95=B0=E6=8D=AE.=20=E5=A2=9E=E5=8A=A0=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E5=AF=BC=E5=87=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SimpleProcessDesigner.vue | 118 +---------- .../src/SimpleProcessModel.vue | 63 +++++- .../package/designer/ProcessDesigner.vue | 23 +-- src/views/bpm/model/editor/index.vue | 190 +----------------- src/views/bpm/model/form/BasicInfo.vue | 51 ++--- src/views/bpm/model/form/FormDesign.vue | 11 +- src/views/bpm/model/form/ProcessDesign.vue | 166 +-------------- src/views/bpm/model/form/index.vue | 150 ++++---------- src/views/bpm/simple/SimpleModelDesign.vue | 113 +---------- 9 files changed, 156 insertions(+), 729 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 22e6073f..ad42696b 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -40,7 +40,7 @@ defineOptions({ name: 'SimpleProcessDesigner' }) -const emits = defineEmits(['success', 'init-finished']) // 保存成功事件 +const emits = defineEmits(['success']) // 保存成功事件 const props = defineProps({ modelId: { @@ -59,13 +59,12 @@ const props = defineProps({ startUserIds : { type: Array, required: false - }, - value: { - type: [String, Object], - required: false } }) +const processData = inject('processData') as Ref + + const loading = ref(false) const formFields = ref([]) const formType = ref(20) @@ -76,9 +75,6 @@ const deptOptions = ref([]) // 部门列表 const deptTreeOptions = ref() const userGroupOptions = ref([]) // 用户组列表 -// 添加当前值的引用 -const currentValue = ref() - provide('formFields', formFields) provide('formType', formType) provide('roleList', roleOptions) @@ -88,7 +84,8 @@ provide('deptList', deptOptions) provide('userGroupList', userGroupOptions) provide('deptTree', deptTreeOptions) provide('startUserIds', props.startUserIds) - +provide('tasks', []) +provide('processInstance', {}) const message = useMessage() // 国际化 const processNodeTree = ref() const errorDialogVisible = ref(false) @@ -112,70 +109,14 @@ const updateModel = () => { } } -// 加载流程数据 -const loadProcessData = async (data: any) => { - try { - if (data) { - const parsedData = typeof data === 'string' ? JSON.parse(data) : data - processNodeTree.value = parsedData - currentValue.value = parsedData - // 确保数据加载后刷新视图 - await nextTick() - if (simpleProcessModelRef.value?.refresh) { - await simpleProcessModelRef.value.refresh() - } - } - } catch (error) { - console.error('加载流程数据失败:', error) - } -} - -// 监听属性变化 -watch( - () => props.value, - async (newValue, oldValue) => { - if (newValue && newValue !== oldValue) { - await loadProcessData(newValue) - } - }, - { immediate: true, deep: true } -) - -// 监听流程节点树变化,自动保存 -watch( - () => processNodeTree.value, - async (newValue, oldValue) => { - if (newValue && oldValue && JSON.stringify(newValue) !== JSON.stringify(oldValue)) { - await saveSimpleFlowModel(newValue) - } - }, - { deep: true } -) const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => { if (!simpleModelNode) { return } - // 校验节点 - errorNodes = [] - validateNode(simpleModelNode, errorNodes) - if (errorNodes.length > 0) { - errorDialogVisible.value = true - return - } - try { - if (props.modelId) { - // 编辑模式 - const data = { - id: props.modelId, - simpleModel: simpleModelNode - } - await updateBpmSimpleModel(data) - } - // 无论是编辑还是新建模式,都更新当前值并触发事件 - currentValue.value = simpleModelNode + processData.value = simpleModelNode emits('success', simpleModelNode) } catch (error) { console.error('保存失败:', error) @@ -246,61 +187,20 @@ onMounted(async () => { deptTreeOptions.value = handleTree(deptOptions.value as DeptApi.DeptVO[], 'id') // 获取用户组列表 userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList() - // 加载流程数据 - if (props.modelId) { - // 获取 SIMPLE 设计器模型 - const result = await getBpmSimpleModel(props.modelId) - if (result) { - await loadProcessData(result) - } else { - updateModel() - } - } else if (props.value) { - await loadProcessData(props.value) + if (processData.value) { + processNodeTree.value = processData?.value } else { updateModel() } } finally { loading.value = false - emits('init-finished') } }) const simpleProcessModelRef = ref() -/** 获取当前流程数据 */ -const getCurrentFlowData = async () => { - try { - if (simpleProcessModelRef.value) { - const data = await simpleProcessModelRef.value.getCurrentFlowData() - if (data) { - currentValue.value = data - return data - } - } - return currentValue.value - } catch (error) { - console.error('获取流程数据失败:', error) - return currentValue.value - } -} - -// 刷新方法 -const refresh = async () => { - try { - if (currentValue.value) { - await loadProcessData(currentValue.value) - } - } catch (error) { - console.error('刷新失败:', error) - } -} defineExpose({ - getCurrentFlowData, - updateModel, - loadProcessData, - refresh }) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index ccd1f10d..b9a26475 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -3,11 +3,31 @@
+ 导出 + 导入 + + {{ scaleValue }}% + + + + + + + + +
@@ -33,7 +53,8 @@ import ProcessNodeTree from './ProcessNodeTree.vue' import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts' import { useWatchNode } from './node' -import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' +import { ZoomOut, ZoomIn, ScaleToOriginal, Select } from '@element-plus/icons-vue' +import { isString } from '@/utils/is' defineOptions({ name: 'SimpleProcessModel' @@ -85,6 +106,16 @@ const processReZoom = () => { const errorDialogVisible = ref(false) let errorNodes: SimpleFlowNode[] = [] +const saveSimpleFlowModel = async () => { + errorNodes = [] + validateNode(processNodeTree.value, errorNodes) + if (errorNodes.length > 0) { + errorDialogVisible.value = true + return + } + emits('save', processNodeTree.value) +} + // 校验节点设置。 暂时以 showText 为空 未节点错误配置 const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => { if (node) { @@ -143,6 +174,36 @@ const getCurrentFlowData = async () => { defineExpose({ getCurrentFlowData }) + +const exportJson = () => { + const blob = new Blob([JSON.stringify(processNodeTree.value)]); + const tempLink = document.createElement('a'); // 创建a标签 + const href = window.URL.createObjectURL(blob); // 创建下载的链接 + //filename + const fileName = `model.json`; + tempLink.href = href; + tempLink.target = '_blank'; + tempLink.download = fileName; + document.body.appendChild(tempLink); + tempLink.click(); // 点击下载 + document.body.removeChild(tempLink); // 下载完成移除元素 + window.URL.revokeObjectURL(href); // 释放掉blob对象 +} +const importJson = () => { + refFile.value.click() +} +const refFile = ref() +// 加载本地文件 +const importLocalFile = () => { + const file = refFile.value.files[0] + const reader = new FileReader() + reader.readAsText(file) + reader.onload = function () { + if (isString(this.result)) { + processNodeTree.value = JSON.parse(this.result) + } + } +} diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue index 9d2fa5ba..5b3d14f4 100644 --- a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue @@ -308,28 +308,6 @@ const props = defineProps({ } }) -// 监听value变化,重新加载流程图 -watch( - () => props.value, - (newValue) => { - if (newValue && bpmnModeler) { - createNewDiagram(newValue) - } - }, - { immediate: true } -) - -// 监听processId和processName变化 -watch( - [() => props.processId, () => props.processName], - ([newId, newName]) => { - if (newId && newName && !props.value) { - createNewDiagram(null) - } - }, - { immediate: true } -) - provide('configGlobal', props) let bpmnModeler: any = null const defaultZoom = ref(1) @@ -480,6 +458,7 @@ const initModelListeners = () => { emit('commandStack-changed', event) emit('input', xml) emit('change', xml) + emit('save', xml) } catch (e: any) { console.error(`[Process Designer Warn]: ${e.message || e}`) } diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 37eff739..512eb152 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,6 +3,7 @@ () @@ -51,10 +52,11 @@ const formType = ref(20) provide('formFields', formFields) provide('formType', formType) -const xmlString = ref('') // BPMN XML +//注入 流程数据 +const xmlString = inject('processData') as Ref + const modeler = shallowRef() // BPMN Modeler const processDesigner = ref() -const isModelerReady = ref(false) const controlForm = ref({ simulation: true, labelEditing: false, @@ -65,154 +67,27 @@ const controlForm = ref({ }) const model = ref() // 流程模型的信息 -// 初始化 bpmnInstances -const initBpmnInstances = () => { - if (!modeler.value) return false - try { - const instances = { - modeler: modeler.value, - modeling: modeler.value.get('modeling'), - moddle: modeler.value.get('moddle'), - eventBus: modeler.value.get('eventBus'), - bpmnFactory: modeler.value.get('bpmnFactory'), - elementFactory: modeler.value.get('elementFactory'), - elementRegistry: modeler.value.get('elementRegistry'), - replace: modeler.value.get('replace'), - selection: modeler.value.get('selection') - } - - // 检查所有实例是否都存在 - return Object.values(instances).every((instance) => instance) - } catch (error) { - console.error('初始化 bpmnInstances 失败:', error) - return false - } -} /** 初始化 modeler */ const initModeler = async (item) => { - try { - modeler.value = item - // 等待 modeler 初始化完成 - await nextTick() - - // 确保 modeler 的所有实例都已经准备好 - if (initBpmnInstances()) { - isModelerReady.value = true - emit('init-finished') - - // 初始化完成后,设置初始值 - if (props.modelId) { - // 编辑模式 - const data = await ModelApi.getModel(props.modelId) - model.value = { - ...data, - bpmnXml: undefined // 清空 bpmnXml 属性 - } - xmlString.value = data.bpmnXml || getDefaultBpmnXml(data.key, data.name) - } else if (props.modelKey && props.modelName) { - // 新建模式 - xmlString.value = props.value || getDefaultBpmnXml(props.modelKey, props.modelName) - model.value = { - key: props.modelKey, - name: props.modelName - } as ModelApi.ModelVO - } - - // 导入XML并刷新视图 - await nextTick() - try { - await modeler.value.importXML(xmlString.value) - if (processDesigner.value?.refresh) { - processDesigner.value.refresh() - } - } catch (error) { - console.error('导入XML失败:', error) - } - } else { - console.error('modeler 实例未完全初始化') - } - } catch (error) { - console.error('初始化 modeler 失败:', error) - } + modeler.value = item } -/** 获取默认的BPMN XML */ -const getDefaultBpmnXml = (key: string, name: string) => { - return ` - - - - - -` -} /** 添加/修改模型 */ const save = async (bpmnXml: string) => { try { xmlString.value = bpmnXml - if (props.modelId) { - // 编辑模式 - const data = { - ...model.value, - bpmnXml: bpmnXml - } as unknown as ModelApi.ModelVO - await ModelApi.updateModelBpmn(data) - emit('success') - } else { - // 新建模式,直接返回XML - emit('success', bpmnXml) - } + emit('success', bpmnXml) } catch (error) { console.error('保存失败:', error) message.error('保存失败') } } -// 监听 key、name 和 value 的变化 -watch( - [() => props.modelKey, () => props.modelName, () => props.value], - async ([newKey, newName, newValue]) => { - if (!props.modelId && isModelerReady.value) { - let shouldRefresh = false - - if (newKey && newName) { - const newXml = newValue || getDefaultBpmnXml(newKey, newName) - if (newXml !== xmlString.value) { - xmlString.value = newXml - shouldRefresh = true - } - model.value = { - ...model.value, - key: newKey, - name: newName - } as ModelApi.ModelVO - } else if (newValue && newValue !== xmlString.value) { - xmlString.value = newValue - shouldRefresh = true - } - - if (shouldRefresh) { - // 确保更新后重新渲染 - await nextTick() - if (processDesigner.value?.refresh) { - try { - await modeler.value?.importXML(xmlString.value) - processDesigner.value.refresh() - } catch (error) { - console.error('导入XML失败:', error) - } - } - } - } - }, - { deep: true } -) // 在组件卸载时清理 onBeforeUnmount(() => { - isModelerReady.value = false modeler.value = null // 清理全局实例 const w = window as any @@ -221,54 +96,7 @@ onBeforeUnmount(() => { } }) -/** 获取 XML 字符串 */ -const saveXML = async () => { - if (!modeler.value) { - return { xml: xmlString.value } - } - try { - const result = await modeler.value.saveXML({ format: true }) - xmlString.value = result.xml - return result - } catch (error) { - console.error('获取XML失败:', error) - return { xml: xmlString.value } - } -} -/** 获取SVG字符串 */ -const saveSVG = async () => { - if (!modeler.value) { - return { svg: undefined } - } - try { - return await modeler.value.saveSVG() - } catch (error) { - console.error('获取SVG失败:', error) - return { svg: undefined } - } -} - -/** 刷新视图 */ -const refresh = async () => { - if (processDesigner.value?.refresh && modeler.value) { - try { - await modeler.value.importXML(xmlString.value) - processDesigner.value.refresh() - } catch (error) { - console.error('刷新视图失败:', error) - } - } -} - -// 暴露必要的属性和方法给父组件 -defineExpose({ - modeler, - isModelerReady, - saveXML, - saveSVG, - refresh -}) From 42c1618202242bb193da1768fd0a9548ecee86c7 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Tue, 14 Jan 2025 09:12:53 +0800 Subject: [PATCH 31/86] =?UTF-8?q?fix:=20=E5=88=9B=E5=BB=BAUserTask?= =?UTF-8?q?=E6=97=A0signEnable=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/UserTaskNodeConfig.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 131f7b9e..00ed6cfe 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -990,7 +990,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { configForm.value.taskCompleteListenerHeader = node.taskCompleteListener?.header ?? [] configForm.value.taskCompleteListenerBody = node.taskCompleteListener?.body ?? [] // 6. 签名 - configForm.value.signEnable = node.signEnable ?? false + configForm.value.signEnable = node?.signEnable ?? false } defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件 From 4fe158b2ec5d03bf5ca206c9e04e85bc1aa38bc7 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Tue, 14 Jan 2025 12:00:08 +0800 Subject: [PATCH 32/86] =?UTF-8?q?perf:=20bpm=20=E4=BF=AE=E5=A4=8Dbpmn?= =?UTF-8?q?=E8=AE=BE=E8=AE=A1=E5=99=A8=E4=B8=8D=E6=98=BE=E7=A4=BA=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/editor/index.vue | 1 - 1 file changed, 1 deletion(-) diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 512eb152..101ea1b8 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,7 +3,6 @@ Date: Wed, 15 Jan 2025 14:54:23 +0800 Subject: [PATCH 33/86] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=E5=9C=A8keepAlive=E4=B8=8B=E5=88=B7=E6=96=B0=E4=B8=8D?= =?UTF-8?q?=E8=A7=A6=E5=8F=91onActivated=E9=92=A9=E5=AD=90=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/layout/components/TagsView/src/TagsView.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue index dcbb90fd..3bfb69df 100644 --- a/src/layout/components/TagsView/src/TagsView.vue +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -243,7 +243,7 @@ const move = (to: number) => { start() } -onMounted(() => { +onBeforeMount(() => { initTags() addTags() }) From 8df285aefb5abfbc1573988dc03da5718008738f Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Wed, 15 Jan 2025 14:57:23 +0800 Subject: [PATCH 34/86] =?UTF-8?q?fix:=20bpm=20=E7=94=A8onActivated?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2onMounted=20=E8=A7=A3=E5=86=B3=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=A8=A1=E5=9E=8B=E8=BF=94=E5=9B=9E=E5=90=8E=E4=B8=8D?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E6=96=B0=E7=9A=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/index.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue index c7d94170..8132bf73 100644 --- a/src/views/bpm/model/index.vue +++ b/src/views/bpm/model/index.vue @@ -207,6 +207,8 @@ const getList = async () => { /** 初始化 **/ onMounted(() => { +}) +onActivated(()=>{ getList() }) From b1174313185998677be5a7142a0f716563e0b478 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Wed, 15 Jan 2025 15:04:23 +0800 Subject: [PATCH 35/86] =?UTF-8?q?feat:=20bpm=20=E6=B7=BB=E5=8A=A0=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=A8=A1=E5=9E=8B=E5=A4=8D=E5=88=B6=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/router/modules/remaining.ts | 2 +- src/views/bpm/model/CategoryDraggableModel.vue | 11 ++++++++++- src/views/bpm/model/form/index.vue | 5 ++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 806f954d..34466079 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -344,7 +344,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ } }, { - path: 'manager/model/update/:id', + path: 'manager/model/:type/:id', component: () => import('@/views/bpm/model/form/index.vue'), name: 'BpmModelUpdate', meta: { diff --git a/src/views/bpm/model/CategoryDraggableModel.vue b/src/views/bpm/model/CategoryDraggableModel.vue index f3b5a422..8fe6e14d 100644 --- a/src/views/bpm/model/CategoryDraggableModel.vue +++ b/src/views/bpm/model/CategoryDraggableModel.vue @@ -163,6 +163,15 @@ > 修改 + + 复制 + { } else { push({ name: 'BpmModelUpdate', - params: { id } + params: { id, type } }) } } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 3a45e716..6c5cb21a 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -162,7 +162,10 @@ const initData = async () => { if (modelId) { // 修改场景 formData.value = await ModelApi.getModel(modelId) - + // 复制场景 + if (route.params.type === 'copy') { + delete formData.value.id + } } else { // 新增场景 formData.value.managerUserIds.push(userStore.getUser.id) From 6fba4b722805f742e0e6804827b6f34d8444bdac Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 15 Jan 2025 20:25:07 +0800 Subject: [PATCH 36/86] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91BPM=EF=BC=9A=E6=B5=81=E7=A8=8B=E7=BC=96?= =?UTF-8?q?=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SimpleProcessDesigner.vue | 7 +-- .../src/SimpleProcessModel.vue | 53 +++++++++---------- src/router/modules/remaining.ts | 1 + src/views/bpm/model/editor/index.vue | 8 +-- src/views/bpm/model/form/ProcessDesign.vue | 10 ---- src/views/bpm/model/form/index.vue | 40 +++++++------- src/views/bpm/model/index.vue | 4 +- src/views/bpm/simple/SimpleModelDesign.vue | 14 +---- 8 files changed, 51 insertions(+), 86 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 1125d8e7..70eade33 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -63,8 +63,6 @@ const props = defineProps({ }) const processData = inject('processData') as Ref - - const loading = ref(false) const formFields = ref([]) const formType = ref(20) @@ -110,7 +108,6 @@ const updateModel = () => { } } - const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => { if (!simpleModelNode) { return @@ -201,7 +198,5 @@ onMounted(async () => { const simpleProcessModelRef = ref() - -defineExpose({ -}) +defineExpose({}) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index b9a26475..23f2d791 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -3,10 +3,15 @@
- 导出 - 导入 + + 导出 + + + 导入 + {{ scaleValue }}% - - - - - - - - -
@@ -53,7 +49,7 @@ import ProcessNodeTree from './ProcessNodeTree.vue' import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts' import { useWatchNode } from './node' -import { ZoomOut, ZoomIn, ScaleToOriginal, Select } from '@element-plus/icons-vue' +import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' import { isString } from '@/utils/is' defineOptions({ @@ -73,7 +69,7 @@ const props = defineProps({ }) const emits = defineEmits<{ - 'save': [node: SimpleFlowNode | undefined] + save: [node: SimpleFlowNode | undefined] }>() const processNodeTree = useWatchNode(props) @@ -175,25 +171,28 @@ defineExpose({ getCurrentFlowData }) +/** 导出 JSON */ +// TODO @zws:增加一个 download 里面搞个 json 更好 const exportJson = () => { - const blob = new Blob([JSON.stringify(processNodeTree.value)]); - const tempLink = document.createElement('a'); // 创建a标签 - const href = window.URL.createObjectURL(blob); // 创建下载的链接 - //filename - const fileName = `model.json`; - tempLink.href = href; - tempLink.target = '_blank'; - tempLink.download = fileName; - document.body.appendChild(tempLink); - tempLink.click(); // 点击下载 - document.body.removeChild(tempLink); // 下载完成移除元素 - window.URL.revokeObjectURL(href); // 释放掉blob对象 + const blob = new Blob([JSON.stringify(processNodeTree.value)]) + const tempLink = document.createElement('a') // 创建a标签 + const href = window.URL.createObjectURL(blob) // 创建下载的链接 + // filename + const fileName = `model.json` + tempLink.href = href + tempLink.target = '_blank' + tempLink.download = fileName + document.body.appendChild(tempLink) + tempLink.click() // 点击下载 + document.body.removeChild(tempLink) // 下载完成移除元素 + window.URL.revokeObjectURL(href) // 释放掉 blob 对象 } + +/** 导入 JSON */ +const refFile = ref() const importJson = () => { refFile.value.click() } -const refFile = ref() -// 加载本地文件 const importLocalFile = () => { const file = refFile.value.files[0] const reader = new FileReader() diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 34466079..4b177ae8 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -344,6 +344,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ } }, { + // TODO @zws:1)建议,在加一个路由。然后标题是“复制流程”,这样体验会好点;2)复制出来的数据,在名字前面,加“副本 ”,和钉钉保持一致! path: 'manager/model/:type/:id', component: () => import('@/views/bpm/model/form/index.vue'), name: 'BpmModelUpdate', diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 101ea1b8..b91c250e 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -51,7 +51,7 @@ const formType = ref(20) provide('formFields', formFields) provide('formType', formType) -//注入 流程数据 +// 注入流程数据 const xmlString = inject('processData') as Ref const modeler = shallowRef() // BPMN Modeler @@ -66,13 +66,12 @@ const controlForm = ref({ }) const model = ref() // 流程模型的信息 - /** 初始化 modeler */ +// TODO @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下 const initModeler = async (item) => { modeler.value = item } - /** 添加/修改模型 */ const save = async (bpmnXml: string) => { try { @@ -84,7 +83,6 @@ const save = async (bpmnXml: string) => { } } - // 在组件卸载时清理 onBeforeUnmount(() => { modeler.value = null @@ -94,8 +92,6 @@ onBeforeUnmount(() => { w.bpmnInstances = null } }) - - From 9849a040c00fef3d6214876241a38549b2b881cb Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:20:57 +0800 Subject: [PATCH 37/86] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0download.json()?= =?UTF-8?q?=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/download.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/utils/download.ts b/src/utils/download.ts index 5bbfb9fe..0820136f 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -33,6 +33,10 @@ const download = { markdown: (data: Blob, fileName: string) => { download0(data, fileName, 'text/markdown') }, + // 下载 Json 方法 + json: (data: Blob, fileName: string) => { + download0(data, fileName, 'application/json') + }, // 下载图片(允许跨域) image: ({ url, From 2f7200abdb576ec8bebe0d222f18525c29bea52f Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:26:38 +0800 Subject: [PATCH 38/86] =?UTF-8?q?feat:=20=E4=BB=8Evue-element-plus-admin?= =?UTF-8?q?=E9=A1=B9=E7=9B=AE=20=E5=90=8C=E6=AD=A5TagsView=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=20=E5=AE=9E=E7=8E=B0=E8=AE=BE=E7=BD=AE=E8=B7=AF?= =?UTF-8?q?=E7=94=B1=E6=A0=87=E9=A2=98=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/TagsView/src/TagsView.vue | 107 ++++++++++-------- src/store/modules/tagsView.ts | 26 ++++- 2 files changed, 84 insertions(+), 49 deletions(-) diff --git a/src/layout/components/TagsView/src/TagsView.vue b/src/layout/components/TagsView/src/TagsView.vue index 3bfb69df..ce041b2b 100644 --- a/src/layout/components/TagsView/src/TagsView.vue +++ b/src/layout/components/TagsView/src/TagsView.vue @@ -12,6 +12,11 @@ import { useDesign } from '@/hooks/web/useDesign' import { useTemplateRefsList } from '@vueuse/core' import { ElScrollbar } from 'element-plus' import { useScrollTo } from '@/hooks/event/useScrollTo' +import { useTagsView } from '@/hooks/web/useTagsView' +import { cloneDeep } from 'lodash-es' + + +defineOptions({ name: 'TagsView' }) const { getPrefixCls } = useDesign() @@ -19,7 +24,9 @@ const prefixCls = getPrefixCls('tags-view') const { t } = useI18n() -const { currentRoute, push, replace } = useRouter() +const { currentRoute, push } = useRouter() + +const { closeAll, closeLeft, closeRight, closeOther, closeCurrent, refreshPage } = useTagsView() const permissionStore = usePermissionStore() @@ -31,6 +38,10 @@ const visitedViews = computed(() => tagsViewStore.getVisitedViews) const affixTagArr = ref([]) +const selectedTag = computed(() => tagsViewStore.getSelectedTag) + +const setSelectTag = tagsViewStore.setSelectedTag + const appStore = useAppStore() const tagsViewImmerse = computed(() => appStore.getTagsViewImmerse) @@ -45,66 +56,30 @@ const initTags = () => { for (const tag of unref(affixTagArr)) { // Must have tag name if (tag.name) { - tagsViewStore.addVisitedView(tag) + tagsViewStore.addVisitedView(cloneDeep(tag)) } } } -const selectedTag = ref() - // 新增tag const addTags = () => { const { name } = unref(currentRoute) if (name) { - selectedTag.value = unref(currentRoute) + setSelectTag(unref(currentRoute)) tagsViewStore.addView(unref(currentRoute)) } - return false } // 关闭选中的tag const closeSelectedTag = (view: RouteLocationNormalizedLoaded) => { - if (view?.meta?.affix) return - tagsViewStore.delView(view) - if (isActive(view)) { - toLastView() - } -} - -// 关闭全部 -const closeAllTags = () => { - tagsViewStore.delAllViews() - toLastView() -} - -// 关闭其它 -const closeOthersTags = () => { - tagsViewStore.delOthersViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 重新加载 -const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => { - if (!view) return - tagsViewStore.delCachedView() - const { path, query } = view - await nextTick() - replace({ - path: '/redirect' + path, - query: query + closeCurrent(view, () => { + if (isActive(view)) { + toLastView() + } }) } -// 关闭左侧 -const closeLeftTags = () => { - tagsViewStore.delLeftViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 关闭右侧 -const closeRightTags = () => { - tagsViewStore.delRightViews(unref(selectedTag) as RouteLocationNormalizedLoaded) -} - -// 跳转到最后一个 +// 去最后一个 const toLastView = () => { const visitedViews = tagsViewStore.getVisitedViews const latestView = visitedViews.slice(-1)[0] @@ -118,11 +93,38 @@ const toLastView = () => { addTags() return } - // TODO: You can set another route - push('/') + // You can set another route + push(permissionStore.getAddRouters[0].path) } } +// 关闭全部 +const closeAllTags = () => { + closeAll(() => { + toLastView() + }) +} + +// 关闭其它 +const closeOthersTags = () => { + closeOther() +} + +// 重新加载 +const refreshSelectedTag = async (view?: RouteLocationNormalizedLoaded) => { + refreshPage(view) +} + +// 关闭左侧 +const closeLeftTags = () => { + closeLeft() +} + +// 关闭右侧 +const closeRightTags = () => { + closeRight() +} + // 滚动到选中的tag const moveToCurrentTag = async () => { await nextTick() @@ -209,13 +211,14 @@ const isActive = (route: RouteLocationNormalizedLoaded): boolean => { // 所有右键菜单组件的元素 const itemRefs = useTemplateRefsList>() -// 右键菜单装填改变的时候 +// 右键菜单状态改变的时候 const visibleChange = (visible: boolean, tagItem: RouteLocationNormalizedLoaded) => { if (visible) { for (const v of unref(itemRefs)) { const elDropdownMenuRef = v.elDropdownMenuRef if (tagItem.fullPath !== v.tagItem.fullPath) { elDropdownMenuRef?.handleClose() + setSelectTag(tagItem) } } } @@ -243,6 +246,16 @@ const move = (to: number) => { start() } +const canShowIcon = (item: RouteLocationNormalizedLoaded) => { + if ( + (item?.matched?.[1]?.meta?.icon && unref(tagsViewIcon)) || + (item?.meta?.affix && unref(tagsViewIcon) && item?.meta?.icon) + ) { + return true + } + return false +} + onBeforeMount(() => { initTags() addTags() diff --git a/src/store/modules/tagsView.ts b/src/store/modules/tagsView.ts index 4368efe0..f565ef95 100644 --- a/src/store/modules/tagsView.ts +++ b/src/store/modules/tagsView.ts @@ -4,16 +4,19 @@ import { getRawRoute } from '@/utils/routerHelper' import { defineStore } from 'pinia' import { store } from '../index' import { findIndex } from '@/utils' +import { useUserStoreWithOut } from './user' export interface TagsViewState { visitedViews: RouteLocationNormalizedLoaded[] cachedViews: Set + selectedTag?: RouteLocationNormalizedLoaded } export const useTagsViewStore = defineStore('tagsView', { state: (): TagsViewState => ({ visitedViews: [], - cachedViews: new Set() + cachedViews: new Set(), + selectedTag: undefined }), getters: { getVisitedViews(): RouteLocationNormalizedLoaded[] { @@ -21,6 +24,9 @@ export const useTagsViewStore = defineStore('tagsView', { }, getCachedViews(): string[] { return Array.from(this.cachedViews) + }, + getSelectedTag(): RouteLocationNormalizedLoaded | undefined { + return this.selectedTag } }, actions: { @@ -98,8 +104,12 @@ export const useTagsViewStore = defineStore('tagsView', { }, // 删除所有tag delAllVisitedViews() { + const userStore = useUserStoreWithOut() + // const affixTags = this.visitedViews.filter((tag) => tag.meta.affix) - this.visitedViews = [] + this.visitedViews = userStore.getUser + ? this.visitedViews.filter((tag) => tag?.meta?.affix) + : [] }, // 删除其他 delOthersViews(view: RouteLocationNormalizedLoaded) { @@ -145,6 +155,18 @@ export const useTagsViewStore = defineStore('tagsView', { break } } + }, + // 设置当前选中的tag + setSelectedTag(tag: RouteLocationNormalizedLoaded) { + this.selectedTag = tag + }, + setTitle(title: string, path?: string) { + for (const v of this.visitedViews) { + if (v.path === (path ?? this.selectedTag?.path)) { + v.meta.title = title + break + } + } } }, persist: false From e44f48c0c4bb371913242a00981e96e9f774a0f6 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:27:30 +0800 Subject: [PATCH 39/86] =?UTF-8?q?perf:=20bpm=E6=A8=A1=E5=9E=8B=E5=A4=8D?= =?UTF-8?q?=E5=88=B6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/bpm/model/CategoryDraggableModel.vue | 6 ++++++ src/views/bpm/model/form/index.vue | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/views/bpm/model/CategoryDraggableModel.vue b/src/views/bpm/model/CategoryDraggableModel.vue index 8fe6e14d..9c5b9b13 100644 --- a/src/views/bpm/model/CategoryDraggableModel.vue +++ b/src/views/bpm/model/CategoryDraggableModel.vue @@ -254,6 +254,7 @@ import { checkPermi } from '@/utils/permission' import { useUserStoreWithOut } from '@/store/modules/user' import { useAppStore } from '@/store/modules/app' import { cloneDeep } from 'lodash-es' +import {useTagsView} from "@/hooks/web/useTagsView"; defineOptions({ name: 'BpmModel' }) @@ -474,6 +475,7 @@ const handleDeleteCategory = async () => { } catch {} } +const tagsView = useTagsView(); /** 添加流程模型弹窗 */ const modelFormRef = ref() const openModelForm = (type: string, id?: number) => { @@ -483,6 +485,10 @@ const openModelForm = (type: string, id?: number) => { push({ name: 'BpmModelUpdate', params: { id, type } + }).then((_) => { + if (type === 'copy') { + tagsView.setTitle('复制流程') + } }) } } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 0d20e7ce..37fa6bf0 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -160,6 +160,8 @@ const initData = async () => { // 复制场景 if (route.params.type === 'copy') { delete formData.value.id + formData.value.name += '副本' + formData.value.key += '_copy' } } else { // 新增场景 From 9febee7abe0f9a05714a6e54600a5b9a63111fd6 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:29:11 +0800 Subject: [PATCH 40/86] =?UTF-8?q?perf:=20=E7=94=A8download.json=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=E6=A8=A1=E5=9E=8Bjson=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/SimpleProcessModel.vue | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index 23f2d791..5d3071b4 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -51,6 +51,7 @@ import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts' import { useWatchNode } from './node' import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue' import { isString } from '@/utils/is' +import download from "@/utils/download"; defineOptions({ name: 'SimpleProcessModel' @@ -174,18 +175,7 @@ defineExpose({ /** 导出 JSON */ // TODO @zws:增加一个 download 里面搞个 json 更好 const exportJson = () => { - const blob = new Blob([JSON.stringify(processNodeTree.value)]) - const tempLink = document.createElement('a') // 创建a标签 - const href = window.URL.createObjectURL(blob) // 创建下载的链接 - // filename - const fileName = `model.json` - tempLink.href = href - tempLink.target = '_blank' - tempLink.download = fileName - document.body.appendChild(tempLink) - tempLink.click() // 点击下载 - document.body.removeChild(tempLink) // 下载完成移除元素 - window.URL.revokeObjectURL(href) // 释放掉 blob 对象 + download.json(new Blob([JSON.stringify(processNodeTree.value)]), 'model.json') } /** 导入 JSON */ From 84552a62533f8943f4a5ec8d86aaeacb3dc1edcb Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 09:29:34 +0800 Subject: [PATCH 41/86] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E5=9E=8Bjson=20=E6=95=B0=E6=8D=AE=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/SimpleProcessModel.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue index 5d3071b4..ad0c7b19 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue @@ -190,6 +190,7 @@ const importLocalFile = () => { reader.onload = function () { if (isString(this.result)) { processNodeTree.value = JSON.parse(this.result) + emits('save', processNodeTree.value) } } } From 66d8cf1233504e4a865264a47a368e8f68354df7 Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 10:10:46 +0800 Subject: [PATCH 42/86] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3bpmn=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8=20=E5=88=9D=E6=AC=A1=E5=88=9B=E5=BB=BA?= =?UTF-8?q?=E6=B5=81=E7=A8=8Bkey=E4=B8=8D=E4=B8=80=E8=87=B4=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../package/penal/base/ElementBaseInfo.vue | 3 +++ src/views/bpm/model/editor/index.vue | 6 ++++++ src/views/bpm/model/form/index.vue | 1 + 3 files changed, 10 insertions(+) diff --git a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue index 70ad4f8b..3172338d 100644 --- a/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue +++ b/src/components/bpmnProcessDesigner/package/penal/base/ElementBaseInfo.vue @@ -152,6 +152,9 @@ watch( handleKeyUpdate(props.model.key) handleNameUpdate(props.model.name) } + }, + { + immediate: true } ) diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index b91c250e..1076cf56 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -12,6 +12,8 @@ :additionalModel="controlForm.additionalModel" :model="model" @save="save" + :process-id="modelKey" + :process-name="modelName" /> () // 流程模型的信息 /** 初始化 modeler */ // TODO @zws:需要初始化,不然首次创建后,无法发布!相当于说,key、name 要去赋值下 const initModeler = async (item) => { + //先初始化模型数据 + model.value = modelData.value modeler.value = item } diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index 37fa6bf0..43e5c0a7 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -145,6 +145,7 @@ const formData: any = ref({ const processData = ref() provide('processData', processData) +provide('modelData', formData) // 数据列表 const formList = ref([]) From d52e77913125820fd3f198be5edcc2b3d95ed5cf Mon Sep 17 00:00:00 2001 From: zws <447643445@qq.com> Date: Thu, 16 Jan 2025 10:18:20 +0800 Subject: [PATCH 43/86] =?UTF-8?q?fix:=20=E8=A7=A3=E5=86=B3=E5=AF=BC?= =?UTF-8?q?=E5=85=A5=E6=A8=A1=E5=9E=8Bxml=20=E6=95=B0=E6=8D=AE=E6=B2=A1?= =?UTF-8?q?=E6=9C=89=E4=BF=9D=E5=AD=98=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpmnProcessDesigner/package/designer/ProcessDesigner.vue | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue index 5b3d14f4..83d40fbf 100644 --- a/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue +++ b/src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue @@ -547,6 +547,7 @@ const importLocalFile = () => { reader.onload = function () { let xmlStr = this.result createNewDiagram(xmlStr) + emit('save', xmlStr) } } /* ------------------------------------------------ refs methods ------------------------------------------------------ */ From 8e5271a6d6724e6ad336634fea25d8ed65ec6189 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 16 Jan 2025 13:01:06 +0800 Subject: [PATCH 44/86] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E8=AF=84?= =?UTF-8?q?=E5=AE=A1=E3=80=91Bpm=EF=BC=9A=E5=AE=A1=E6=89=B9=E7=AD=BE?= =?UTF-8?q?=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pnpm-lock.yaml | 103 ++++++----------- src/api/bpm/processInstance/index.ts | 4 +- .../src/nodes-config/RouterNodeConfig.vue | 11 +- .../src/nodes-config/UserTaskNodeConfig.vue | 1 + .../detail/ProcessInstanceOperationButton.vue | 104 ++++++++++-------- .../detail/ProcessInstanceTimeline.vue | 8 +- .../bpm/processInstance/detail/SignDialog.vue | 39 +++---- 7 files changed, 126 insertions(+), 144 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 50e9bf96..ec016eb1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -45,8 +45,8 @@ dependencies: specifier: ^1.1.5 version: 1.1.5 bpmn-js-token-simulation: - specifier: ^0.10.0 - version: 0.10.0 + specifier: ^0.36.0 + version: 0.36.0 camunda-bpmn-moddle: specifier: ^7.0.1 version: 7.0.1 @@ -149,6 +149,9 @@ dependencies: vue-types: specifier: ^5.1.1 version: 5.1.3(vue@3.5.12) + vue3-signature: + specifier: ^0.2.4 + version: 0.2.4(vue@3.5.12) vuedraggable: specifier: ^4.1.0 version: 4.1.0(vue@3.5.12) @@ -4581,12 +4584,14 @@ packages: min-dom: 4.2.1 dev: true - /bpmn-js-token-simulation@0.10.0: - resolution: {integrity: sha512-QuZQ/KVXKt9Vl+XENyOBoTW2Aw+uKjuBlKdCJL6El7AyM7DkJ5bZkSYURshId1SkBDdYg2mJ1flSmsrhGuSfwg==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.10.0.tgz} + /bpmn-js-token-simulation@0.36.0: + resolution: {integrity: sha512-vz+RHlbZCev/6dzk6FhJRz8M0aZ1GL7Xrza0ecWqeg4tHbgPozgyOm3tXTz75XdtOwRVVBzmCjcciXQX7A55wQ==, tarball: https://registry.npmmirror.com/bpmn-js-token-simulation/-/bpmn-js-token-simulation-0.36.0.tgz} + engines: {node: '>= 16'} dependencies: - min-dash: 3.8.1 - min-dom: 0.2.0 - svg.js: 2.7.1 + inherits-browser: 0.1.0 + min-dash: 4.2.2 + min-dom: 4.2.1 + randomcolor: 0.6.2 dev: false /bpmn-js@17.11.1: @@ -4927,51 +4932,13 @@ packages: dot-prop: 5.3.0 dev: true - /component-classes@1.2.6: - resolution: {integrity: sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==, tarball: https://registry.npmmirror.com/component-classes/-/component-classes-1.2.6.tgz} - dependencies: - component-indexof: 0.0.3 - dev: false - - /component-closest@0.1.4: - resolution: {integrity: sha512-NF9hMj6JKGM5sb6wP/dg7GdJOttaIH9PcTsUNdWcrvu7Kw/5R5swQAFpgaYEHlARrNMyn4Wf7O1PlRej+pt76Q==, tarball: https://registry.npmmirror.com/component-closest/-/component-closest-0.1.4.tgz} - dependencies: - component-matches-selector: 0.1.7 - dev: false - - /component-delegate@0.2.4: - resolution: {integrity: sha512-OlpcB/6Fi+kXQPh/TfXnSvvmrU04ghz7vcJh/jgLF0Ni+I+E3WGlKJQbBGDa5X+kVUG8WxOgjP+8iWbz902fPg==, tarball: https://registry.npmmirror.com/component-delegate/-/component-delegate-0.2.4.tgz} - dependencies: - component-closest: 0.1.4 - component-event: 0.1.4 - dev: false - /component-emitter@1.3.1: resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==, tarball: https://registry.npmmirror.com/component-emitter/-/component-emitter-1.3.1.tgz} dev: true - /component-event@0.1.4: - resolution: {integrity: sha512-GMwOG8MnUHP1l8DZx1ztFO0SJTFnIzZnBDkXAj8RM2ntV2A6ALlDxgbMY1Fvxlg6WPQ+5IM/a6vg4PEYbjg/Rw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.1.4.tgz} - dev: false - /component-event@0.2.1: resolution: {integrity: sha512-wGA++isMqiDq1jPYeyv2as/Bt/u+3iLW0rEa+8NQ82jAv3TgqMiCM+B2SaBdn2DfLilLjjq736YcezihRYhfxw==, tarball: https://registry.npmmirror.com/component-event/-/component-event-0.2.1.tgz} - /component-indexof@0.0.3: - resolution: {integrity: sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw==, tarball: https://registry.npmmirror.com/component-indexof/-/component-indexof-0.0.3.tgz} - dev: false - - /component-matches-selector@0.1.7: - resolution: {integrity: sha512-Yb2+pVBvrqkQVpPaDBF0DYXRreBveXJNrpJs9FnFu8PF6/5IIcz5oDZqiH9nB5hbD2/TmFVN5ZCxBzqu7yFFYQ==, tarball: https://registry.npmmirror.com/component-matches-selector/-/component-matches-selector-0.1.7.tgz} - dependencies: - component-query: 0.0.3 - global-object: 1.0.0 - dev: false - - /component-query@0.0.3: - resolution: {integrity: sha512-VgebQseT1hz1Ps7vVp2uaSg+N/gsI5ts3AZUSnN6GMA2M82JH7o+qYifWhmVE/e8w/H48SJuA3nA9uX8zRe95Q==, tarball: https://registry.npmmirror.com/component-query/-/component-query-0.0.3.tgz} - dev: false - /compute-scroll-into-view@1.0.20: resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==, tarball: https://registry.npmmirror.com/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz} dev: false @@ -5521,6 +5488,10 @@ packages: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==, tarball: https://registry.npmmirror.com/deep-is/-/deep-is-0.1.4.tgz} dev: true + /default-passive-events@2.0.0: + resolution: {integrity: sha512-eMtt76GpDVngZQ3ocgvRcNCklUMwID1PaNbCNxfpDXuiOXttSh0HzBbda1HU9SIUsDc02vb7g9+3I5tlqe/qMQ==, tarball: https://registry.npmmirror.com/default-passive-events/-/default-passive-events-2.0.0.tgz} + dev: false + /define-data-property@1.1.4: resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==, tarball: https://registry.npmmirror.com/define-data-property/-/define-data-property-1.1.4.tgz} engines: {node: '>= 0.4'} @@ -6674,10 +6645,6 @@ packages: global-prefix: 3.0.0 dev: true - /global-object@1.0.0: - resolution: {integrity: sha512-mSPSkY6UsHv6hgW0V2dfWBWTS8TnPnLx3ECVNoWp6rBI2Bg66VYoqGoTFlH/l7XhAZ/l+StYlntXlt87BEeCcg==, tarball: https://registry.npmmirror.com/global-object/-/global-object-1.0.0.tgz} - dev: false - /global-prefix@3.0.0: resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==, tarball: https://registry.npmmirror.com/global-prefix/-/global-prefix-3.0.0.tgz} engines: {node: '>=6'} @@ -7899,10 +7866,6 @@ packages: engines: {node: '>=18'} dev: true - /min-dash@3.8.1: - resolution: {integrity: sha512-evumdlmIlg9mbRVPbC4F5FuRhNmcMS5pvuBUbqb1G9v09Ro0ImPEgz5n3khir83lFok1inKqVDjnKEg3GpDxQg==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-3.8.1.tgz} - dev: false - /min-dash@4.2.2: resolution: {integrity: sha512-qbhSYUxk6mBaF096B3JOQSumXbKWHenmT97cSpdNzgkWwGjhjhE/KZODCoDNhI2I4C9Cb6R/Q13S4BYkUSXoXQ==, tarball: https://registry.npmmirror.com/min-dash/-/min-dash-4.2.2.tgz} @@ -7912,18 +7875,6 @@ packages: dom-walk: 0.1.2 dev: false - /min-dom@0.2.0: - resolution: {integrity: sha512-VmxugbnAcVZGqvepjhOA4d4apmrpX8mMaRS+/jo0dI5Yorzrr4Ru9zc9KVALlY/+XakVCb8iQ+PYXljihQcsNw==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-0.2.0.tgz} - dependencies: - component-classes: 1.2.6 - component-closest: 0.1.4 - component-delegate: 0.2.4 - component-event: 0.1.4 - component-matches-selector: 0.1.7 - component-query: 0.0.3 - domify: 1.4.2 - dev: false - /min-dom@4.2.1: resolution: {integrity: sha512-TMoL8SEEIhUWYgkj7XMSgxmwSyGI+4fP2KFFGnN3FbHfbGHVdsLYSz8LoIsgPhz4dWRmLvxWWSMgzZMJW5sZuA==, tarball: https://registry.npmmirror.com/min-dom/-/min-dom-4.2.1.tgz} dependencies: @@ -8714,6 +8665,10 @@ packages: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==, tarball: https://registry.npmmirror.com/queue-microtask/-/queue-microtask-1.2.3.tgz} dev: true + /randomcolor@0.6.2: + resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==, tarball: https://registry.npmmirror.com/randomcolor/-/randomcolor-0.6.2.tgz} + dev: false + /rd@2.0.1: resolution: {integrity: sha512-/XdKU4UazUZTXFmI0dpABt8jSXPWcEyaGdk340KdHnsEOdkTctlX23aAK7ChQDn39YGNlAJr1M5uvaKt4QnpNw==, tarball: https://registry.npmmirror.com/rd/-/rd-2.0.1.tgz} dependencies: @@ -9128,6 +9083,10 @@ packages: engines: {node: '>=14'} dev: true + /signature_pad@3.0.0-beta.4: + resolution: {integrity: sha512-cOf2NhVuTiuNqe2X/ycEmizvCDXk0DoemhsEpnkcGnA4kS5iJYTCqZ9As7tFBbsch45Q1EdX61833+6sjJ8rrw==, tarball: https://registry.npmmirror.com/signature_pad/-/signature_pad-3.0.0-beta.4.tgz} + dev: false + /sirv@2.0.4: resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==, tarball: https://registry.npmmirror.com/sirv/-/sirv-2.0.4.tgz} engines: {node: '>= 10'} @@ -9561,10 +9520,6 @@ packages: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==, tarball: https://registry.npmmirror.com/svg-tags/-/svg-tags-1.0.0.tgz} dev: true - /svg.js@2.7.1: - resolution: {integrity: sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==, tarball: https://registry.npmmirror.com/svg.js/-/svg.js-2.7.1.tgz} - dev: false - /svgo@2.8.0: resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==, tarball: https://registry.npmmirror.com/svgo/-/svgo-2.8.0.tgz} engines: {node: '>=10.13.0'} @@ -10324,6 +10279,16 @@ packages: vue: 3.5.12(typescript@5.3.3) dev: false + /vue3-signature@0.2.4(vue@3.5.12): + resolution: {integrity: sha512-XFwwFVK9OG3F085pKIq2SlNVqx32WdFH+TXbGEWc5FfEKpx8oMmZuAwZZ50K/pH2FgmJSE8IRwU9DDhrLpd6iA==, tarball: https://registry.npmmirror.com/vue3-signature/-/vue3-signature-0.2.4.tgz} + peerDependencies: + vue: ^3.2.0 + dependencies: + default-passive-events: 2.0.0 + signature_pad: 3.0.0-beta.4 + vue: 3.5.12(typescript@5.3.3) + dev: false + /vue@3.5.12(typescript@5.3.3): resolution: {integrity: sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==, tarball: https://registry.npmmirror.com/vue/-/vue-3.5.12.tgz} peerDependencies: diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts index 06dc3f88..a0f263de 100644 --- a/src/api/bpm/processInstance/index.ts +++ b/src/api/bpm/processInstance/index.ts @@ -36,7 +36,7 @@ export type ApprovalTaskInfo = { assigneeUser: User status: number reason: string - sign: string + sign: string // TODO @lesan:字段改成 signPicUrl 签名照片。只有 sign 感觉是签名文本哈。 } // 审批节点信息 @@ -90,7 +90,7 @@ export const getProcessInstanceCopyPage = async (params: any) => { // 获取审批详情 export const getApprovalDetail = async (params: any) => { - return await request.get({ url: 'bpm/process-instance/get-approval-detail' , params }) + return await request.get({ url: 'bpm/process-instance/get-approval-detail', params }) } // 获取表单字段权限 diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue index 442cf337..6748a736 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/RouterNodeConfig.vue @@ -37,9 +37,9 @@ :value="node.value" /> - 删除 + + 删除 +
([]) const nodeOptions = ref() - const conditionRef = ref([]) -// 保存配置 + +/** 保存配置 */ const saveConfig = async () => { // 校验表单 let valid = true diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 00ed6cfe..64acc2c3 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -440,6 +440,7 @@
+
diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue index 7f0696cf..a4ecee65 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue @@ -44,14 +44,26 @@ :rows="4" /> - + 点击签名 - + - + {{ getButtonDisplayName(OperationButtonType.APPROVE) }} 取消 @@ -92,7 +104,11 @@ /> - + {{ getButtonDisplayName(OperationButtonType.REJECT) }} 取消 @@ -478,7 +494,8 @@
- + + - + From 37964e740f8691a58f9a43f976fb9c047e034e28 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Thu, 16 Jan 2025 13:55:15 +0800 Subject: [PATCH 45/86] =?UTF-8?q?feat:=20=E5=AE=A1=E6=89=B9=E7=AD=BE?= =?UTF-8?q?=E5=90=8D=E4=BB=A3=E7=A0=81=E8=AF=84=E5=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bpm/processInstance/index.ts | 2 +- src/utils/download.ts | 27 ++++++++++++++ .../detail/ProcessInstanceOperationButton.vue | 16 ++++----- .../detail/ProcessInstanceTimeline.vue | 6 ++-- .../bpm/processInstance/detail/SignDialog.vue | 35 ++----------------- 5 files changed, 42 insertions(+), 44 deletions(-) diff --git a/src/api/bpm/processInstance/index.ts b/src/api/bpm/processInstance/index.ts index a0f263de..9a99a91e 100644 --- a/src/api/bpm/processInstance/index.ts +++ b/src/api/bpm/processInstance/index.ts @@ -36,7 +36,7 @@ export type ApprovalTaskInfo = { assigneeUser: User status: number reason: string - sign: string // TODO @lesan:字段改成 signPicUrl 签名照片。只有 sign 感觉是签名文本哈。 + signPicUrl: string } // 审批节点信息 diff --git a/src/utils/download.ts b/src/utils/download.ts index 5bbfb9fe..bd58845f 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -65,6 +65,33 @@ const download = { a.download = 'image.png' a.click() } + }, + base64ToFile: (base64, fileName) => { + // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 + const data = base64.split(',') + // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) + const type = data[0].match(/:(.*?);/)[1] + // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) + const suffix = type.split('/')[1] + // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 + const bstr = window.atob(data[1]) + // 获取解码结果字符串的长度 + let n = bstr.length + // 根据解码结果字符串的长度创建一个等长的整形数字数组 + // 但在创建时 所有元素初始值都为 0 + const u8arr = new Uint8Array(n) + // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 + while (n--) { + // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 + u8arr[n] = bstr.charCodeAt(n) + } + // 利用构造函数创建File文件对象 + // new File(bits, name, options) + const file = new File([u8arr], `${fileName}.${suffix}`, { + type: type + }) + // 将File文件对象返回给方法的调用者 + return file } } diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue index a4ecee65..402644e9 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue @@ -47,15 +47,15 @@ 点击签名 @@ -553,11 +553,11 @@ const signRef = ref() const approveSignFormRef = ref() const approveReasonForm = reactive({ reason: '', - sign: '' + signPicUrl: '' }) const approveReasonRule = reactive>({ reason: [{ required: true, message: '审批意见不能为空', trigger: 'blur' }], - sign: [{ required: true, message: '签名不能为空', trigger: 'change' }] + signPicUrl: [{ required: true, message: '签名不能为空', trigger: 'change' }] }) // 拒绝表单 const rejectFormRef = ref() @@ -705,7 +705,7 @@ const handleAudit = async (pass: boolean, formRef: FormInstance | undefined) => } // 签名 if (runningTask.value.signEnable) { - data.sign = approveReasonForm.sign + data.signPicUrl = approveReasonForm.signPicUrl } // 多表单处理,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交 // TODO 芋艿 任务有多表单这里要如何处理,会和可编辑的字段冲突 @@ -1002,7 +1002,7 @@ const getUpdatedProcessInstanceVariables = () => { /** 处理签名完成 */ const handleSignFinish = (url: string) => { - approveReasonForm.sign = url + approveReasonForm.signPicUrl = url approveSignFormRef.value.validate('change') } diff --git a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue index 1fd31dcf..fcd5ec89 100644 --- a/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue +++ b/src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue @@ -124,14 +124,14 @@ 审批意见:{{ task.reason }}
签名:
diff --git a/src/views/bpm/processInstance/detail/SignDialog.vue b/src/views/bpm/processInstance/detail/SignDialog.vue index 211cfcda..744a3556 100644 --- a/src/views/bpm/processInstance/detail/SignDialog.vue +++ b/src/views/bpm/processInstance/detail/SignDialog.vue @@ -2,9 +2,8 @@
- import Vue3Signature from 'vue3-signature' import * as FileApi from '@/api/infra/file' +import download from '@/utils/download' const message = useMessage() // 消息弹窗 const signDialogVisible = ref(false) @@ -40,40 +40,11 @@ const emits = defineEmits(['success']) const submit = async () => { message.success('签名上传中请稍等。。。') const res = await FileApi.updateFile({ - file: base64ToFile(signature.value.save('image/png'), '签名') + file: download.base64ToFile(signature.value.save('image/png'), '签名') }) emits('success', res.data) signDialogVisible.value = false } - -// TODO @lesan:这个要不抽到 download.js 里,让这个组件更简洁干净? -const base64ToFile = (base64, fileName) => { - // 将base64按照 , 进行分割 将前缀 与后续内容分隔开 - let data = base64.split(',') - // 利用正则表达式 从前缀中获取图片的类型信息(image/png、image/jpeg、image/webp等) - let type = data[0].match(/:(.*?);/)[1] - // 从图片的类型信息中 获取具体的文件格式后缀(png、jpeg、webp) - let suffix = type.split('/')[1] - // 使用atob()对base64数据进行解码 结果是一个文件数据流 以字符串的格式输出 - const bstr = window.atob(data[1]) - // 获取解码结果字符串的长度 - let n = bstr.length - // 根据解码结果字符串的长度创建一个等长的整形数字数组 - // 但在创建时 所有元素初始值都为 0 - const u8arr = new Uint8Array(n) - // 将整形数组的每个元素填充为解码结果字符串对应位置字符的UTF-16 编码单元 - while (n--) { - // charCodeAt():获取给定索引处字符对应的 UTF-16 代码单元 - u8arr[n] = bstr.charCodeAt(n) - } - // 利用构造函数创建File文件对象 - // new File(bits, name, options) - const file = new File([u8arr], `${fileName}.${suffix}`, { - type: type - }) - // 将File文件对象返回给方法的调用者 - return file -} From 69ccd83af31c33a92def15100706fe336419d6c0 Mon Sep 17 00:00:00 2001 From: Lesan <1960681385@qq.com> Date: Thu, 16 Jan 2025 14:40:14 +0800 Subject: [PATCH 46/86] =?UTF-8?q?feat:=20bpmn=E8=AE=BE=E8=AE=A1=E5=99=A8?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0UserTask=E7=AD=BE=E5=90=8D=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugins/descriptor/flowableDescriptor.json | 14 ++++++++++++++ .../package/penal/PropertiesPanel.vue | 2 +- .../components/UserTaskCustomConfig.vue | 17 ++++++++++++++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json index 7fe1fa79..e50d3ce3 100644 --- a/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json +++ b/src/components/bpmnProcessDesigner/package/designer/plugins/descriptor/flowableDescriptor.json @@ -1438,6 +1438,20 @@ "isBody": true } ] + }, + { + "name": "SignEnable", + "superClass": ["Element"], + "meta": { + "allowedIn": ["bpmn:UserTask"] + }, + "properties": [ + { + "name": "value", + "type": "Boolean", + "isBody": true + } + ] } ], "emumerations": [] diff --git a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue index e53ad994..ff08dd33 100644 --- a/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue +++ b/src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue @@ -1,5 +1,5 @@
-
未满足其它条件时,将进入此分支(该分支不可编辑和删除)
+
+ 未满足其它条件时,将进入此分支(该分支不可编辑和删除) +
- + - + - +
条件组关系
@@ -194,9 +200,9 @@ const props = defineProps({ }) const settingVisible = ref(false) const open = () => { - if (currentNode.value.conditionType === ConditionType.RULE) { - if (currentNode.value.conditionGroups) { - conditionGroups.value = currentNode.value.conditionGroups + if (currentNode.value.conditionSetting?.conditionType === ConditionType.RULE) { + if (currentNode.value.conditionSetting?.conditionGroups) { + conditionGroups.value = currentNode.value.conditionSetting.conditionGroups } } settingVisible.value = true @@ -219,7 +225,7 @@ const blurEvent = () => { showInput.value = false currentNode.value.name = currentNode.value.name || - getDefaultConditionNodeName(props.nodeIndex, currentNode.value?.defaultFlow) + getDefaultConditionNodeName(props.nodeIndex, currentNode.value?.conditionSetting?.defaultFlow) } const currentNode = ref(props.conditionNode) @@ -248,7 +254,7 @@ const formRef = ref() // 表单 Ref // 保存配置 const saveConfig = async () => { - if (!currentNode.value.defaultFlow) { + if (!currentNode.value.conditionSetting?.defaultFlow) { // 校验表单 if (!formRef) return false const valid = await formRef.value.validate() @@ -258,12 +264,12 @@ const saveConfig = async () => { return false } currentNode.value.showText = showText - if (currentNode.value.conditionType === ConditionType.EXPRESSION) { - currentNode.value.conditionGroups = undefined + if (currentNode.value.conditionSetting?.conditionType === ConditionType.EXPRESSION) { + currentNode.value.conditionSetting.conditionGroups = undefined } - if (currentNode.value.conditionType === ConditionType.RULE) { - currentNode.value.conditionExpression = undefined - currentNode.value.conditionGroups = conditionGroups.value + if (currentNode.value.conditionSetting?.conditionType === ConditionType.RULE) { + currentNode.value.conditionSetting.conditionExpression = undefined + currentNode.value.conditionSetting.conditionGroups = conditionGroups.value } } settingVisible.value = false @@ -271,12 +277,12 @@ const saveConfig = async () => { } const getShowText = (): string => { let showText = '' - if (currentNode.value.conditionType === ConditionType.EXPRESSION) { - if (currentNode.value.conditionExpression) { - showText = `表达式:${currentNode.value.conditionExpression}` + if (currentNode.value.conditionSetting?.conditionType === ConditionType.EXPRESSION) { + if (currentNode.value.conditionSetting.conditionExpression) { + showText = `表达式:${currentNode.value.conditionSetting.conditionExpression}` } } - if (currentNode.value.conditionType === ConditionType.RULE) { + if (currentNode.value.conditionSetting?.conditionType === ConditionType.RULE) { // 条件组是否为与关系 const groupAnd = conditionGroups.value.and let warningMesg: undefined | string = undefined diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue index f1445d83..fb512913 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue @@ -34,7 +34,7 @@ ]" >
-
+
Date: Sun, 19 Jan 2025 22:42:05 +0800 Subject: [PATCH 62/86] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=91=E6=9D=A1=E4=BB=B6=E8=8A=82=E7=82=B9=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 35 +++---------------- .../SimpleProcessDesignerV2/src/consts.ts | 18 ++++++++++ .../src/nodes-config/ConditionNodeConfig.vue | 3 +- .../src/nodes-config/components/Condition.vue | 35 +++++++++++++------ .../src/nodes/ExclusiveNode.vue | 11 +++--- .../src/nodes/InclusiveNode.vue | 11 +++--- 6 files changed, 61 insertions(+), 52 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index e575c36c..c3f68830 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -71,7 +71,8 @@ import { NODE_DEFAULT_NAME, NodeType, RejectHandlerType, - SimpleFlowNode + SimpleFlowNode, + DEFAULT_CONDITION_GROUP_VALUE } from './consts' import {generateUUID} from '@/utils' @@ -167,21 +168,7 @@ const addNode = (type: number) => { conditionSetting: { defaultFlow: false, conditionType: ConditionType.RULE, - conditionGroups: { - and: true, - conditions: [ - { - and: true, - rules: [ - { - opCode: '==', - leftSide: '', - rightSide: '' - } - ] - } - ] - } + conditionGroups: DEFAULT_CONDITION_GROUP_VALUE } }, { @@ -239,21 +226,7 @@ const addNode = (type: number) => { conditionSetting: { defaultFlow: false, conditionType: ConditionType.RULE, - conditionGroups: { - and: true, - conditions: [ - { - and: true, - rules: [ - { - opCode: '==', - leftSide: '', - rightSide: '' - } - ] - } - ] - } + conditionGroups: DEFAULT_CONDITION_GROUP_VALUE } }, { diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 089a6392..1c910c38 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -463,6 +463,24 @@ export type ConditionGroup = { // 条件数组 conditions: Condition[] } +/** + * 条件组默认值 + */ +export const DEFAULT_CONDITION_GROUP_VALUE = { + and: true, + conditions: [ + { + and: true, + rules: [ + { + opCode: '==', + leftSide: '', + rightSide: '' + } + ] + } + ] +} /** * 条件结构定义 diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue index f22168bd..93e3795a 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue @@ -46,7 +46,6 @@ import { SimpleFlowNode, ConditionType, - ConditionSetting, COMPARISON_OPERATORS, ProcessVariableEnum } from '../consts' @@ -69,7 +68,7 @@ const props = defineProps({ }) const settingVisible = ref(false) const currentNode = ref(props.conditionNode) -const condition = ref() +const condition = ref() const open = () => { condition.value = currentNode.value.conditionSetting settingVisible.value = true diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue index 28a7783b..e86ac2da 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue @@ -1,7 +1,7 @@