From 4c4d13cdd0a056c6d5cb803c240f721642f61970 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sun, 24 Mar 2024 20:35:53 +0800 Subject: [PATCH 01/93] =?UTF-8?q?=E6=94=B9=E9=80=A0=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE.=20=E6=95=B4=E5=90=88=E7=B3=BB=E7=BB=9F?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E4=BB=BB=E5=8A=A1=E7=9A=84=E5=80=99=E9=80=89?= =?UTF-8?q?=E4=BA=BA=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesigner/src/addNode.vue | 39 ++- .../SimpleProcessDesigner/src/consts.ts | 47 +++ .../src/drawer/approverDrawer.vue | 311 ++++++++++++++++++ .../SimpleProcessDesigner/src/nodeWrap.vue | 157 +++++---- .../SimpleProcessDesigner/src/util.ts | 29 ++ src/store/modules/simpleWorkflow.ts | 6 +- src/views/bpm/simpleWorkflow/index.vue | 23 +- 7 files changed, 538 insertions(+), 74 deletions(-) create mode 100644 src/components/SimpleProcessDesigner/src/consts.ts create mode 100644 src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue diff --git a/src/components/SimpleProcessDesigner/src/addNode.vue b/src/components/SimpleProcessDesigner/src/addNode.vue index 6d09ae8a..9686165c 100644 --- a/src/components/SimpleProcessDesigner/src/addNode.vue +++ b/src/components/SimpleProcessDesigner/src/addNode.vue @@ -32,7 +32,7 @@ - + diff --git a/src/components/SimpleProcessDesigner/src/nodeWrap.vue b/src/components/SimpleProcessDesigner/src/nodeWrap.vue index 3c9d5eb1..ecfbdfec 100644 --- a/src/components/SimpleProcessDesigner/src/nodeWrap.vue +++ b/src/components/SimpleProcessDesigner/src/nodeWrap.vue @@ -6,40 +6,48 @@ * @FilePath: /Workflow-Vue3/src/components/nodeWrap.vue --> - + diff --git a/src/components/SimpleProcessDesigner/src/util.ts b/src/components/SimpleProcessDesigner/src/util.ts index f4acd76c..ae72bce0 100644 --- a/src/components/SimpleProcessDesigner/src/util.ts +++ b/src/components/SimpleProcessDesigner/src/util.ts @@ -1,3 +1,6 @@ +// @ts-ignore +import { DictDataVO } from '@/api/system/dict/types' +import { DICT_TYPE, getDictLabel } from '@/utils/dict' /** * todo */ @@ -51,6 +54,32 @@ export const setApproverStr = (nodeConfig: any) => { } } + +export const approveMethods: DictDataVO [] = [ + { label: '单人审批', value: 1 }, + { label: '多人审批(所有人审批通过)', value: 2 } + // TODO 更多的类型 +]; + +export const getApproverShowText = (approveMethod :number, candidateStrategy: number) => { + if(approveMethod && candidateStrategy) { + let appoveMethodText = '' + approveMethods.forEach((item) => { + if (item.value == approveMethod) { + appoveMethodText = item.label + } + }) + const strategyText = getDictLabel( + DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY, + candidateStrategy + ) + return `审批方式:${appoveMethodText}
+ 审批人规则类型:按${strategyText}` + } else { + return '' + } +} + export const copyerStr = (nodeConfig: any) => { if (nodeConfig.nodeUserList.length != 0) { return arrToStr(nodeConfig.nodeUserList) diff --git a/src/store/modules/simpleWorkflow.ts b/src/store/modules/simpleWorkflow.ts index cf98538d..dbeff606 100644 --- a/src/store/modules/simpleWorkflow.ts +++ b/src/store/modules/simpleWorkflow.ts @@ -14,7 +14,8 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', { conditionDrawer: false, conditionsConfig1: { conditionNodes: [] - } + }, + userTaskConfig: {} }), actions: { setTableId(payload) { @@ -46,6 +47,9 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', { }, setConditionsConfig(payload) { this.conditionsConfig1 = payload + }, + setUserTaskConfig(payload) { + this.userTaskConfig = payload } } }) diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index 144615e0..89132787 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -1,6 +1,13 @@ diff --git a/src/components/SimpleProcessDesigner/src/util.ts b/src/components/SimpleProcessDesigner/src/util.ts index ae72bce0..bcd5a7e6 100644 --- a/src/components/SimpleProcessDesigner/src/util.ts +++ b/src/components/SimpleProcessDesigner/src/util.ts @@ -56,14 +56,14 @@ export const setApproverStr = (nodeConfig: any) => { export const approveMethods: DictDataVO [] = [ - { label: '单人审批', value: 1 }, - { label: '多人审批(所有人审批通过)', value: 2 } + { label: '单人审批', value: 1 } + // { label: '多人审批(所有人审批通过)', value: 2 } // TODO 更多的类型 ]; export const getApproverShowText = (approveMethod :number, candidateStrategy: number) => { - if(approveMethod && candidateStrategy) { - let appoveMethodText = '' + let appoveMethodText = '单人审批' + if(candidateStrategy) { approveMethods.forEach((item) => { if (item.value == approveMethod) { appoveMethodText = item.label diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index c1cc111a..1a2702d9 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -1,14 +1,34 @@ \ No newline at end of file + From 4f839136c7c3f18fd9cac951df91ece997b71f65 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 2 Apr 2024 20:56:51 +0800 Subject: [PATCH 04/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=B5=81=E7=A8=8B=EF=BC=9A=E5=A2=9E=E5=8A=A0=E5=8F=91?= =?UTF-8?q?=E8=B5=B7=E4=BA=BA=E3=80=81=E6=9D=A1=E4=BB=B6=E5=88=86=E6=94=AF?= =?UTF-8?q?=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesigner/src/addNode.vue | 59 +++--- .../SimpleProcessDesigner/src/consts.ts | 10 +- .../src/drawer/approverDrawer.vue | 52 +---- .../SimpleProcessDesigner/src/nodeWrap.vue | 182 +++++++++--------- .../SimpleProcessDesigner/src/util.ts | 22 ++- .../SimpleProcessDesigner/theme/workflow.css | 40 +++- src/views/bpm/simpleWorkflow/index.vue | 116 ++++++++--- 7 files changed, 270 insertions(+), 211 deletions(-) diff --git a/src/components/SimpleProcessDesigner/src/addNode.vue b/src/components/SimpleProcessDesigner/src/addNode.vue index d11ead29..7595b670 100644 --- a/src/components/SimpleProcessDesigner/src/addNode.vue +++ b/src/components/SimpleProcessDesigner/src/addNode.vue @@ -24,6 +24,12 @@

条件分支

--> + +
+ +
+

条件分支

+
From f79c29d168d340000539df7cec8db785e9ff824a Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Fri, 5 Apr 2024 13:04:12 +0800 Subject: [PATCH 05/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E6=B5=81=E7=A8=8B=EF=BC=9A=E5=A2=9E=E5=8A=A0=E6=8A=84?= =?UTF-8?q?=E9=80=81=E4=BA=BA=E8=8A=82=E7=82=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesigner/src/addNode.vue | 16 +- .../src/drawer/approverDrawer.vue | 30 +-- .../src/drawer/copyerDrawer.vue | 246 ++++++++++++++++++ .../SimpleProcessDesigner/src/nodeWrap.vue | 115 ++++---- .../SimpleProcessDesigner/src/util.ts | 23 +- .../SimpleProcessDesigner/theme/workflow.css | 49 ++-- src/directives/index.ts | 12 + src/main.ts | 6 +- src/store/modules/simpleWorkflow.ts | 12 +- src/views/bpm/simpleWorkflow/index.vue | 2 + 10 files changed, 391 insertions(+), 120 deletions(-) create mode 100644 src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue diff --git a/src/components/SimpleProcessDesigner/src/addNode.vue b/src/components/SimpleProcessDesigner/src/addNode.vue index 7595b670..d0c7d746 100644 --- a/src/components/SimpleProcessDesigner/src/addNode.vue +++ b/src/components/SimpleProcessDesigner/src/addNode.vue @@ -24,6 +24,12 @@

条件分支

--> + +
+ +
+

抄送人

+
@@ -86,9 +92,13 @@ const addType = (type) => { data = { name: '抄送人', type: 2, - ccSelfSelectFlag: 1, - childNode: props.childNodeP, - nodeUserList: [] + error: true, + // 抄送节点配置 + attributes : { + candidateStrategy: undefined, + candidateParam: undefined + }, + childNode: props.childNodeP } } emits('update:childNodeP', data) diff --git a/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue b/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue index 089a6ac1..cbcec808 100644 --- a/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue +++ b/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue @@ -2,7 +2,6 @@ ([]) // 角色列表 const postOptions = ref([]) // 岗位列表 const userOptions = ref([]) // 用户列表 @@ -183,7 +177,7 @@ const candidateConfig = ref({ }) let approverConfig = ref({}) let store = useWorkFlowStoreWithOut() -let { setApprover, setUserTaskConfig } = store +let { setApproverDrawer, setUserTaskConfig } = store let approverConfig1 = computed(() => store.approverConfig1) let approverDrawer = computed(() => store.approverDrawer) const userTaskConfig = computed(() => store.userTaskConfig) @@ -233,32 +227,16 @@ const saveConfig = () => { // flag: true, // id: approverConfig1.value.id // }) - const showText = getApproverShowText() setUserTaskConfig({ value: rawConfig.value, flag: true, id: userTaskConfig.value.id, - showText }) - console.log('after is userTaskConfig', userTaskConfig.value) closeDrawer() } -const getApproverShowText = () => { - let appoveMethodText = '' - approveMethods.forEach((item) => { - if (item.value == candidateConfig.value.approveMethod) { - appoveMethodText = item.label - } - }) - const strategyText = getDictLabel( - DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY, - candidateConfig.value.candidateStrategy - ) - return `审批方式:${appoveMethodText}
- 审批人规则类型:按${strategyText}` -} + const closeDrawer = () => { - setApprover(false) + setApproverDrawer(false) } const changecandidateStrategy = () => { candidateConfig.value.candidateParam = [] diff --git a/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue b/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue new file mode 100644 index 00000000..d8bd01b6 --- /dev/null +++ b/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue @@ -0,0 +1,246 @@ + + + diff --git a/src/components/SimpleProcessDesigner/src/nodeWrap.vue b/src/components/SimpleProcessDesigner/src/nodeWrap.vue index 034d534b..56112e71 100644 --- a/src/components/SimpleProcessDesigner/src/nodeWrap.vue +++ b/src/components/SimpleProcessDesigner/src/nodeWrap.vue @@ -22,12 +22,13 @@ v-if="isInput" type="text" class="ant-input editable-title-input" - @blur="blurEvent()" - @focus="$event.currentTarget.select()" + @blur="blurEvent(-1)" + @focus="$event.currentTarget?.select()" + v-mountedFoucs v-model="nodeConfig.name" :placeholder="defaultText" /> - {{ nodeConfig.name }} + {{ nodeConfig.name }}
@@ -60,7 +61,8 @@ type="text" class="ant-input editable-title-input" @blur="blurEvent(index)" - @focus="$event.currentTarget.select()" + @focus="$event.currentTarget?.select()" + v-mountedFoucs v-model="item.name" /> {{ @@ -135,9 +137,8 @@ let props = defineProps({ let defaultText = computed(() => { return placeholderList[props.nodeConfig.type] }) - -let isInputList = ref([]) -let isInput = ref(false) +const isInputList = ref([]) +const isInput = ref(false) const resetConditionNodesErr = () => { for (var i = 0; i < props.nodeConfig.conditionNodes.length; i++) { // eslint-disable-next-line vue/no-mutating-props @@ -160,20 +161,20 @@ onMounted(() => { let emits = defineEmits(['update:nodeConfig']) let store = useWorkFlowStoreWithOut() let { - setPromoter, - setApprover, - setCopyer, - setCondition, + setApproverDrawer, + setCopyerDrawer, + // setCondition, setCopyerConfig, - setConditionsConfig, + // setConditionsConfig, setUserTaskConfig } = store +// ??? +const isTried = computed(() => store.isTried) // 审批节点的配置 const userTaskConfig = computed(() => store.userTaskConfig) -let isTried = computed(() => store.isTried) -let approverConfig1 = computed(() => store.approverConfig1) -let copyerConfig1 = computed(() => store.copyerConfig1) -let conditionsConfig1 = computed(() => store.conditionsConfig1) +// 抄送节点的配置 +const copyerConfig = computed(() => store.copyerConfig) +// let conditionsConfig1 = computed(() => store.conditionsConfig1) const showText = computed(() => { if (props.nodeConfig.type == 0) return '发起人' if (props.nodeConfig.type == 1) { @@ -186,42 +187,49 @@ const showText = computed(() => { return '' } } - return copyerStr(props.nodeConfig) + if(props.nodeConfig.type === 2) { + if(props.nodeConfig.attributes) { + return copyerStr( props.nodeConfig.attributes.candidateStrategy) + } else { + return '' + } + + } + return '' }) watch(userTaskConfig, (approver) => { if (approver.flag && approver.id === _uid) { emits('update:nodeConfig', approver.value) } }) -watch(approverConfig1, (approver) => { - if (approver.flag && approver.id === _uid) { - emits('update:nodeConfig', approver.value) - } -}) -watch(copyerConfig1, (copyer) => { +watch(copyerConfig, (copyer) => { + console.log('copyer',copyer) if (copyer.flag && copyer.id === _uid) { + console.log('copyer id is equal',copyer) emits('update:nodeConfig', copyer.value) } }) -watch(conditionsConfig1, (condition) => { - if (condition.flag && condition.id === _uid) { - emits('update:nodeConfig', condition.value) - } -}) + +// watch(conditionsConfig1, (condition) => { +// if (condition.flag && condition.id === _uid) { +// emits('update:nodeConfig', condition.value) +// } +// }) const clickEvent = (index) => { - if (index || index === 0) { + if (index >= 0) { isInputList.value[index] = true } else { isInput.value = true } } + const blurEvent = (index) => { - if (index || index === 0) { + if (index >= 0) { isInputList.value[index] = false // eslint-disable-next-line vue/no-mutating-props props.nodeConfig.conditionNodes[index].name = - props.nodeConfig.conditionNodes[index].name || '条件' + props.nodeConfig.conditionNodes[index].name || '条件' } else { isInput.value = false // eslint-disable-next-line vue/no-mutating-props @@ -278,42 +286,45 @@ const reData = (data, addData) => { } } const setPerson = (priorityLevel) => { - var { type } = props.nodeConfig + console.log('priorityLevel',priorityLevel) + const { type } = props.nodeConfig + console.log('type',type) if (type == 0) { - setPromoter(true) + // setPromoter(true) } else if (type == 1) { - setApprover(true) - let showText = undefined - if (_uid === userTaskConfig.value.id) { - showText = userTaskConfig.value.showText - } + setApproverDrawer(true) + // if (_uid === userTaskConfig.value.id) { + // showText = userTaskConfig.value.showText + // } setUserTaskConfig({ value: { ...JSON.parse(JSON.stringify(props.nodeConfig)), id: 'Activity_' + _uid }, flag: false, - id: _uid, - showText + id: _uid }) } else if (type == 2) { - setCopyer(true) + setCopyerDrawer(true) setCopyerConfig({ - value: JSON.parse(JSON.stringify(props.nodeConfig)), + value: { + ...JSON.parse(JSON.stringify(props.nodeConfig)), + id: 'Activity_' + _uid + }, flag: false, id: _uid }) } else { - setCondition(true) - setConditionsConfig({ - value: { - ...JSON.parse(JSON.stringify(props.nodeConfig)), - id: 'Gateway_' + _uid - }, - priorityLevel, - flag: false, - id: _uid - }) + // setCondition(true) + // setConditionsConfig({ + // value: { + // ...JSON.parse(JSON.stringify(props.nodeConfig)), + // id: 'Gateway_' + _uid + // }, + // priorityLevel, + // flag: false, + // id: _uid + // }) } } // const arrTransfer = (index, type = 1) => { diff --git a/src/components/SimpleProcessDesigner/src/util.ts b/src/components/SimpleProcessDesigner/src/util.ts index f910d56b..3e36ec2b 100644 --- a/src/components/SimpleProcessDesigner/src/util.ts +++ b/src/components/SimpleProcessDesigner/src/util.ts @@ -80,13 +80,24 @@ export const getApproverShowText = (approveMethod :number, candidateStrategy: nu } } -export const copyerStr = (nodeConfig: any) => { - if (nodeConfig.nodeUserList.length != 0) { - return arrToStr(nodeConfig.nodeUserList) +export const copyerStr = ( candidateStrategy: number) => { + // if (nodeConfig.nodeUserList.length != 0) { + // return arrToStr(nodeConfig.nodeUserList) + // } else { + // if (nodeConfig.ccSelfSelectFlag == 1) { + // return '发起人自选' + // } + // } + console.log('candidateStrategy', candidateStrategy); + + if(candidateStrategy) { + const strategyText = getDictLabel( + DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY, + candidateStrategy + ) + return `抄送人类型:按${strategyText}` } else { - if (nodeConfig.ccSelfSelectFlag == 1) { - return '发起人自选' - } + return '' } } export const conditionStr = (nodeConfig, index) => { diff --git a/src/components/SimpleProcessDesigner/theme/workflow.css b/src/components/SimpleProcessDesigner/theme/workflow.css index 19f1cb84..2b9e0daa 100644 --- a/src/components/SimpleProcessDesigner/theme/workflow.css +++ b/src/components/SimpleProcessDesigner/theme/workflow.css @@ -1163,11 +1163,7 @@ html { box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) } -.dingflow-design .auto-judge.active .close, -.dingflow-design .auto-judge:active .close, -.dingflow-design .auto-judge:hover .close { - display: block -} + .dingflow-design .auto-judge.error:after { border: 1px solid #f25643; @@ -1183,6 +1179,7 @@ html { line-height: 24px; width: 258px; } */ + .dingflow-design .title-wrapper { display: flex; justify-content: space-between; @@ -1195,18 +1192,39 @@ html { line-height: 24px; width: 220px; color: #fff; + padding-right: 10px; + padding-left: 10px; } + .dingflow-design .title-wrapper .editable-title { max-width: 120px; - padding-left: 10px; overflow: hidden; white-space: nowrap; text-overflow: ellipsis } -.dingflow-design .title-wrapper .close { - padding-right: 10px; + +.dingflow-design .title-wrapper .close { + display: none; + position: absolute; + right: 10px; + top: 2px; + width: 20px; + height: 20px; + font-size: 14px; + color:#fff; + border-radius: 50%; + text-align: center; + line-height: 20px; + z-index: 2 } +.dingflow-design .title-wrapper:hover .close { + display: block +} +/* .dingflow-design .title-wrapper .close { + padding-right: 2px; +} */ + /* .dingflow-design .title-wrapper .priority-title { display: inline-block; float: right; @@ -1233,21 +1251,6 @@ html { color: #bfbfbf } -.dingflow-design .auto-judge .close { - display: none; - position: absolute; - right: -10px; - top: -10px; - width: 20px; - height: 20px; - font-size: 14px; - color: rgba(0, 0, 0, .25); - border-radius: 50%; - text-align: center; - line-height: 20px; - z-index: 2 -} - .dingflow-design .auto-judge .content { font-size: 14px; color: #191f25; diff --git a/src/directives/index.ts b/src/directives/index.ts index 89cc8ba1..8fb6ff94 100644 --- a/src/directives/index.ts +++ b/src/directives/index.ts @@ -10,4 +10,16 @@ import { hasPermi } from './permission/hasPermi' export const setupAuth = (app: App) => { hasRole(app) hasPermi(app) + +} + +/** + * 导出指令:v-mountedFoucs + */ +export const setupMountedFoucs= (app: App) => { + app.directive('mountedFoucs', { + mounted(el) { + el.focus(); + } + }) } diff --git a/src/main.ts b/src/main.ts index 76c72473..24666be8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -28,8 +28,8 @@ import '@/plugins/animate.css' // 路由 import router, { setupRouter } from '@/router' -// 权限 -import { setupAuth } from '@/directives' +// 其它指令 +import { setupAuth, setupMountedFoucs } from '@/directives' import { createApp } from 'vue' @@ -60,6 +60,8 @@ const setupAll = async () => { setupAuth(app) + setupMountedFoucs(app) + await router.isReady() app.use(VueDOMPurifyHTML) diff --git a/src/store/modules/simpleWorkflow.ts b/src/store/modules/simpleWorkflow.ts index dbeff606..c7c8abd4 100644 --- a/src/store/modules/simpleWorkflow.ts +++ b/src/store/modules/simpleWorkflow.ts @@ -6,11 +6,10 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', { tableId: '', isTried: false, promoterDrawer: false, - flowPermission1: {}, approverDrawer: false, approverConfig1: {}, copyerDrawer: false, - copyerConfig1: {}, + copyerConfig: {}, conditionDrawer: false, conditionsConfig1: { conditionNodes: [] @@ -27,20 +26,17 @@ export const useWorkFlowStore = defineStore('simpleWorkflow', { setPromoter(payload) { this.promoterDrawer = payload }, - setFlowPermission(payload) { - this.flowPermission1 = payload - }, - setApprover(payload) { + setApproverDrawer(payload) { this.approverDrawer = payload }, setApproverConfig(payload) { this.approverConfig1 = payload }, - setCopyer(payload) { + setCopyerDrawer(payload) { this.copyerDrawer = payload }, setCopyerConfig(payload) { - this.copyerConfig1 = payload + this.copyerConfig = payload }, setCondition(payload) { this.conditionDrawer = payload diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index bf298996..5e215c1b 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -24,10 +24,12 @@ + diff --git a/src/components/SimpleProcessDesigner/src/nodeWrap.vue b/src/components/SimpleProcessDesigner/src/nodeWrap.vue index 9f9af39a..b86148ae 100644 --- a/src/components/SimpleProcessDesigner/src/nodeWrap.vue +++ b/src/components/SimpleProcessDesigner/src/nodeWrap.vue @@ -44,7 +44,7 @@ - +
@@ -92,10 +92,10 @@
- + - + - +
@@ -137,10 +137,10 @@
- + - + - +
@@ -186,10 +186,10 @@
- + - + - +
@@ -209,9 +209,9 @@
聚合
- + - + diff --git a/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue b/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue index d8bd01b6..4b074ab8 100644 --- a/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue +++ b/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue @@ -144,7 +144,7 @@ + + diff --git a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue new file mode 100644 index 00000000..855ca63e --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue new file mode 100644 index 00000000..85cf3e66 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -0,0 +1,140 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts new file mode 100644 index 00000000..72450b72 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -0,0 +1,72 @@ +// @ts-ignore +import { DictDataVO } from '@/api/system/dict/types' + +export enum NodeType { + /** + * 发起人节点 + */ + START_EVENT_NODE = 0, + /** + * 结束节点 + */ + END_EVENT_NODE = -2, + + /** + * 审批人节点 + */ + USER_TASK_NODE = 1, + + /** + * 条件节点 + */ + CONDITION_NODE = 3, + /** + * 条件分支节点 + */ + EXCLUSIVE_NODE = 4, + /** + * 并行分支分叉节点 + */ + PARALLEL_NODE_FORK = 5, + /** + * 并行分支聚合 + */ + PARALLEL_NODE_JOIN = 6, + /** + * 包容分支分叉节点 + */ + INCLUSIVE_NODE_FORK = 7, + /** + * 包容分支聚合节点 + */ + INCLUSIVE_NODE_JOIN = 8 +} + +export type SimpleFlowNode = { + id: string, + type: NodeType, + name: string, + showText?: string, + attributes?: any, + // 孩子节点 + childNode?: SimpleFlowNode, + // 条件节点 + conditionNodes?: SimpleFlowNode[] +} + +export const NODE_DEFAULT_TEXT = new Map() +NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置该节点') +NODE_DEFAULT_TEXT.set(NodeType.CONDITION_NODE, '请设置条件') + +export const NODE_DEFAULT_NAME = new Map() +NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人') +NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') + + +export const APPROVE_METHODS: DictDataVO [] = [ + { label: '单人审批', value: 1 }, + { label: '多人会签(需所有审批人同意)', value: 2 }, + { label: '多人或签(一名审批人同意即可)', value: 3 }, + { label: '依次审批(按顺序依次审批)', value: 4 } + // TODO 更多的类型 +] \ No newline at end of file diff --git a/src/components/SimpleProcessDesignerV2/src/index.ts b/src/components/SimpleProcessDesignerV2/src/index.ts new file mode 100644 index 00000000..a53dcf38 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/index.ts @@ -0,0 +1,4 @@ +import SimpleProcessDesigner from './SimpleProcessDesigner.vue' +import '../theme/simple-process-designer.scss' + +export { SimpleProcessDesigner } \ No newline at end of file diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue new file mode 100644 index 00000000..3278e7b8 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/EndEventNode.vue @@ -0,0 +1,13 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue new file mode 100644 index 00000000..7835c959 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue @@ -0,0 +1,35 @@ + + + diff --git a/src/components/SimpleProcessDesignerV2/theme/iconfont.ttf b/src/components/SimpleProcessDesignerV2/theme/iconfont.ttf new file mode 100644 index 0000000000000000000000000000000000000000..c2dcd3f422eda69e3cb3520c32c67528a6f82944 GIT binary patch literal 2908 zcmd^B|8HAY6+h=)$4+eLy<~aMj!WXc_Z-`G+Swf!(gk>Cdq8Ul?16U5UxkoWGH0Rn&rs=#1i>cspJ^_lSF0C+F4a}S(I7^D7~pOF46 z>1VU6nbPPJ`M&`Ot;Ai=zX;%_@n8XH?yR~~g-0Bu(hMlD4sKVjIz#Li&i(T@XQa`8fv4g7UiwE}+^x~> zR2{%RM`|kwb};YB1&{Ggsc_a!KY$&sQsH(t48Rx&M<-|JK+I<<1=wZ#H|&kr2FCny zE<^p>8u@W65`*BhS%(Ag61328UlM*v+}9c{-T(tBQh*jl?8lS`7mqE#n_EKdMm-e+g_rqukk z8#|PpJ9YAG7NnTlKR!Q3Yj2_cD8I8p3z5=5Gk!=-Q2j+&a?>unAlEFuo(qa{JEn>>q3cybypGjL;Ceh;k5(F-*ph z>2XYsp%Fw`#5RoRE_BL%^clmLju6(P7)cT~h?51Fy*M*-@kL(ErcWo6r}MnR%hqH5 zL*3Tt?rwag`;Z^MqX;Y3rdRb?&w0IA^r&7ec!d}2ND8;2b|}T81HaYXZJnV&>tR0+ zJ~B?hJft4ywKm&Ad~NmHTcvf}1JEWY!~QPx<6s+hv2aUg7{7|IS@-|xx2Lw%ckuhx zD|qIO4ePJgudHk6#H_XV${hWVg+7v+&k3!f!o-v#b(c@50@qoL;8Nt2gE8jzsvd*$@;sb z?1=;dIPhR1ax4|>_U-9!uvKNZq6B@LKIwIGA3qp+D3Lrn-G^-QGlvHrjSNf?`?}J-4<(8ruyPK94*{M^if_NKnohObxiS1q`xc&8@;%)CAXgf4NA?=Mh zT&VOX+~X&Yi2GwGw=(P>aC6hX?UaKDXP=!_UPb`pP|joq*pj@j5lJ(l?E=4hjFBJg<|BXq#4HWui` z`mv1}@jth*gYfTc+yXwR+1N?^wvF9z65DO;fe2}G8}XH+VS>SDRLs!mdWW-Uxl2Dz-Z?lAd5SFGWxX@{ zBzc!%jr@3@DqYq%eJb7QHAP;9y62suLJO>+4)?e9`gK#=q%4uDDP@Mo&-+y%H|^`f8glWb^0O mme);3wpiM5E@cV}d9%&DV6(1FiL$?HNA^?f)NJP>_9F7$x_p~i4s9(fLa>J6To%K@>2La zYIs~Q07!vnp*H{kmOBrbObrPl2LgaJ7mPCkVYctjI=v831hsyUqd@GHor0!?L_{+| zZ64%`5?!(pPNzuX)81FN& z%1VNELVIgjG)0}@t7%ez{xNAsKysE$CUJ$rUZL5S36&&OR6KZTHr!4aAcK6$8(up{oB>1yY|&lKI1YI{xp zi2LL9@u|cuy_LMDa>RvSkzX!x28kbPr>CpC==#rChn?zfhasuq&ODof?2w`Q>-FS9ftB$Yo>~VM}Ho97$zzl-}c%`)GrFZK)G;KAZUs#D{y^&C)jDl`(;|K z{z>CIX!s%ijAqdih)e2dP)v%trTC1dx6xxtlTbZW2chL`z1YIDXymZGIFuv z$xo9?gW|$t`;&)`Ykr<)YUy!Ougl^leXsnyLYw>2VDsY0T{1ZqF z{=M7o$JXzg+bh@_gE1B#a318+W)!T?s1i6ci;Xfc{A-xjz%9bOLEI@+DM-(1SVw2E zyk~W{nHLPR)3t@p#v+vI~-t->@d0W+tWHdACHa4$zy*uI%Zp#*~00LT4G(b zk<)D`n5sSxofZYpvg+FeZh?0FWc6y3N!}y`jJ8y&>oy7l=<783oM>L*9k-lO?wQ*>!8Tx>mf*So(1hNy3tK{{XjPx((9`8pWD!(pxQz3p-%Y-w$@J}w> zAiGWbu?nh>dtB8=t;%s4rEXojv4y=ukm-8W?^f4DwrKbrDF%mNiXJTVI^8?(#~V#I zPE0~yMPUgw!RO1n;uY9eC|F!j=94uYmtadUPYhnLri#33nR#n}96UoyELgAEpV1i596Nj=6dGQFZeK1~ddzN}%?KgtS z1`{$Lzdhq-u7TCi!OxgmM%-7#FL!*+t6B^(YA)pgC*}&qRzxa(OM^=fZJSmc8eRXc zHNTg*t8qthHZ#6fV1U(=ZFuwqXHZ6%ohND{7I>03`R|zo%>H%zAGc<|M>Jy?0yImg zE6{3%ZzMty&?r?-UyBfilm?FMm&5!oK5~6psNB{HNLk;=f~eO(0S5&s26z{lL?X2$ zK_HWW7C7}J76{w`-a~vLFQxwYZ!Quw4V+~FL|^Bbu z_|-UlsyR=q2N2byrmi-9I6U5_C%AF2L0HDPxshFiPtd3?O)p{;Zd5X$MoiVn`;<<_ zqQs7>lvuLT!*%8A8JXf%&qZP@?)#Yrw(KT+l)oi+6unZNQVkLXh&LQsWc~_XL@(^;T|={7F0eXzKS|k+fNw4{a+3KVRR?*FK+eSSotZPq*=T zYn+AabwlEkM@;m=$iDn!(;VLcr-1vjN|uv<^OIjd4_*7Ge0<#_o@%0dKW7s%mQD9& zawEEJ8>CHUcCA919Qt1Rw>3X9r{(-3d{YP)-Ng4@r^|DH0(d0Nh~| zL;wI_fdw1@41{?2Z@>TTGc#BI$4r{3MOGJ2&?1EHl|{1m@CNl=E!~DzWmBt=_bHCr zRkeKE`;u#OziE!*6h;w;!{Qhe(Tr#K_tKX_=_MuaDk66klx$84V=#ijf7{nSq5uD0 z)y(4o$-ef`LbB$fIqXv~u?ds_t&Y9G>OBR|si^h=o?)Q6c^iR#OYIule0qHcOSdC7 zux>)o8`QaRyT~G#(GAKBCA8{Vx@!?HRHSF=HSj$D`S_(7GbB|O9A*F2lN5%XH2RgF zdN}!$v`4_@2^BIH9+@c~&pYnQrEFoY=pXx=#bIEuR#JD;@5Ij2u4;Eo_gAk+yD{hv zgTsID2wAOCB%+3jflNN0tm&i}5p*UZGM%T0n(in>MRyFM(EU{=fhOH$Fh+oQNc_jD zg}I|he5kAp8Z>n1;?$G@ljTfpVfO6SENyn{btFyW3`21o!LrFDej9@0D2Bmlx~OoI zG|OMd%?mat%c3n7%O57y3P%a`qA^OfU<5BJ$_GiptZHEqlwXwAoSQA4+k%i!Za|X6 z&8ILA$di|V1b!JtsjHAUEQViuRGCyXb=O!pGNY0&!s^w;V1Yuv7CCYgf`}~`hKNl$ zc>q%z0O0F#L!9Kvb&w&h!aT?qPxS#Fby>)OTNKDmsUimOb&-NqeDWa-FDC4=&`Dak zU?!L&oT0rgVK8<7xZKdHcnrK{$09i2Ee@JxS(h{PGaBH>%`Y<>Z<0Gy(k=M2ZOF3=dvYf*WWs&IpH{1SPExO)0>PQlN#)a7Qu|Do%S@bHfDh)bIB zvLN!6ORA$|YB_O9Q%+Z$6~Z(<{~UJAWU&Jz*OngMG!s0-O-cBCO|*qqOS1Nt;kv?1wP?U3iIB z{RQ_`WCY;mq;0UQyT3D%Xc^9CX|@6Z5kKP5rEO#HO1^av0-Oct4duUi0E{pBJ#S$A z$-_LpHl9D^7sww|_4`=n&c(kMkIUQt+WEgs-{;jYM^K=L7jjkmVQ>V$2IXlXW^scw zWvqQHAZO!jL$Ezrf7rpt-!t4dsYZwuesHQ0H6)D*khP}c3wb_N23QWY)*9%yz{%bN zjNpum(udhz0m4vkkPP+;vY|fkh5QAT(MC`k>L2Zj*9$H^nrX;U>F;s-c6s8A-{<&s&3X~mMFc|c&eU_l(Oi&Eh%AG)8wc@s0;9C3L|QHB*m4kOcPT~ zLQ>1NG<3S2ji@kTAveCLL=sHM*N8cr0>Y9~h1kDJKgeUyFL=8qQsgL6MIBAF`gWK^ ib*iFE6Nz<$sXQ{NqFL&X*rp?Q!RL2r#zj6-iWC5rIkjv6 literal 0 HcmV?d00001 diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss new file mode 100644 index 00000000..6d2b4130 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -0,0 +1,521 @@ +.simple-flow-canvas { + position: absolute; + inset: 0; + z-index: 1; + overflow: auto; + background-color: #fafafa; + user-select: none; + + .simple-flow-container { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .top-area-container { + position: sticky; + inset: 0; + display: flex; + width: 100%; + height: 42px; + z-index: 1; + // padding: 4px 0; + background-color: #fff; + justify-content: flex-end; + align-items: center; + + .top-actions { + display: flex; + margin: 4px; + margin-right: 8px; + align-items: center; + + .canvas-control { + font-size: 16px; + + .control-scale-group { + display: inline-flex; + align-items: center; + margin-right: 8px; + + .control-scale-button { + display: inline-flex; + width: 28px; + height: 28px; + padding: 2px; + text-align: center; + cursor: pointer; + justify-content: center; + align-items: center; + } + + .control-scale-label { + margin: 0 4px; + font-size: 14px; + } + } + } + } + } + + .scale-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 16px; + background-color: #fafafa; + transform-origin: 50% 0 0; + transform: scale(1); + transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + + // 节点容器 定义节点宽度 + .node-container { + width: 200px; + } + // 节点 + .node-box { + position: relative; + display: flex; + min-height: 70px; + padding: 5px 10px 8px; + cursor: pointer; + background-color: #fff; + flex-direction: column; + border: 2px solid transparent; + // border-color: #0089ff; + border-radius: 8px; + // border-color: #0089ff; + box-shadow: 0 1px 4px 0 rgba(10, 30, 65, 0.16); + transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); + + &:hover { + // border-color: #0089ff; + .node-toolbar { + opacity: 1; + } + } + + // 普通节点标题 + .node-title-container { + display: flex; + padding: 4px; + cursor: pointer; + border-radius: 4px 4px 0 0; + align-items: center; + + .node-title-icon { + display: flex; + align-items: center; + } + + .node-title { + margin-left: 4px; + font-size: 14px; + font-weight: 600; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + color: #1f1f1f; + // vertical-align: middle; + } + } + + // 条件节点标题 + .branch-node-title-container { + display: flex; + padding: 4px; + cursor: pointer; + border-radius: 4px 4px 0 0; + align-items: center; + justify-content: space-between; + + .branch-title { + max-width: 120px; + font-size: 13px; + font-weight: 600; + color: #f60; + } + + .branch-priority { + min-width: 50px; + font-size: 13px; + } + } + + .node-content { + display: flex; + min-height: 32px; + padding: 4px 8px; + margin-top: 4px; + line-height: 32px; + justify-content: space-between; + align-items: center; + color: #111f2c; + background: rgba(0, 0, 0, 0.03); + border-radius: 4px; + + .node-text { + display: -webkit-box; + overflow: hidden; + font-size: 14px; + line-height: 24px; + text-overflow: ellipsis; + word-break: break-all; + -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */ + -webkit-box-orient: vertical; + } + } + + .node-toolbar { + opacity: 0; + position: absolute; + top: -26px; + right: 10px; + display: flex; + + .toolbar-icon { + text-align: center; + vertical-align: middle; + color: #000; + border-radius: 4px; + } + } + } + + + .node-config-error { + border-color: #ff5219; + } + // 普通节点包装 + .node-wrapper { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + // 节点连线处理 + .node-handler-wrapper { + position: relative; + display: flex; + height: 70px; + align-items: center; + user-select: none; + justify-content: center; + flex-direction: column; + + &::before { + position: absolute; + top: 0; + right: 0; + left: 0; + // bottom: 5px; + bottom: 0px; + z-index: 0; + width: 2px; + height: 100%; + // height: calc(100% - 5px); + margin: auto; + background-color: #dedede; + content: ''; + } + + .node-handler { + .add-icon { + position: relative; + top: -5px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + width: 25px; + height: 25px; + color: #fff; + background-color: #0089ff; + border-radius: 50%; + + &:hover{ + transform: scale(1.1); + + } + } + + } + + .node-handler-arrow { + position: absolute; + bottom: 0; + left: 50%; + display: flex; + transform: translateX(-50%); + } + } + + + // 条件节点包装 + .branch-node-wrapper { + position: relative; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + margin-top: 16px; + + .branch-node-container { + position: relative; + display: flex; + + &::before { + position: absolute; + height: 100%; + width: 4px; + background-color: #fafafa; + content: ""; + left: 50%; + transform: translate(-50%); + } + + .branch-node-add { + position: absolute; + top: -18px; + left: 50%; + z-index: 1; + height: 36px; + padding: 0 10px; + font-size: 12px; + line-height: 36px; + color: #222; + cursor: pointer; + background: #fff; + border: 2px solid #dedede; + border-radius: 18px; + transform: translateX(-50%); + transform-origin: center center; + transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + } + + .branch-node-item { + position: relative; + display: flex; + flex-direction: column; + align-items: center; + min-width: 280px; + padding: 40px 40px 0; + background: transparent; + border-top: 2px solid #dedede; + border-bottom: 2px solid #dedede; + + &::before { + position: absolute; + width: 2px; + height: 100%; + margin: auto; + inset: 0; + background-color: #dedede; + content: ''; + } + } + // 覆盖条件节点第一个节点左上角的线 + .branch-line-first-top { + position: absolute; + top: -5px; + left: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点第一个节点左下角的线 + .branch-line-first-bottom { + position: absolute; + bottom: -5px; + left: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点最后一个节点右上角的线 + .branch-line-last-top { + position: absolute; + top: -5px; + right: -1px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + // 覆盖条件节点最后一个节点右下角的线 + .branch-line-last-bottom { + position: absolute; + right: -1px; + bottom: -5px; + width: 50%; + height: 7px; + background-color: #fafafa; + content: ''; + } + } + } + + .node-fixed-name { + display: inline-block; + width: auto; + padding: 0 4px; + overflow: hidden; + text-align: center; + text-overflow: ellipsis; + white-space: nowrap; + } + // 开始节点包装 + .start-node-wrapper { + position: relative; + margin-top: 16px; + + .start-node-container { + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + + .start-node-box { + display: flex; + justify-content: center; + align-items: center; + width: 90px; + height: 36px; + padding: 3px 4px; + color: #212121; + cursor: pointer; + // background: #2c2c2c; + background: #fafafa; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08); + box-sizing: border-box; + } + } + } + + // 结束节点包装 + .end-node-wrapper { + margin-bottom: 16px; + + .end-node-box { + display: flex; + justify-content: center; + align-items: center; + width: 80px; + height: 36px; + color: #212121; + // background: #6e6e6e; + background: #fafafa; + border-radius: 30px; + box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08); + box-sizing: border-box; + } + } + + // 可编辑的 title 输入框 + .editable-title-input { + height: 20px; + line-height: 20px; + font-size: 12px; + margin-left: 4px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + border-color: #40a9ff; + outline: 0; + box-shadow: 0 0 0 2px rgba(24, 144, 255, .2) + } + } + } + } + + +} + +// 节点连线气泡卡片样式 +.handler-item-wrapper { + display: flex; + cursor: pointer; + + .handler-item { + margin-right: 8px; + } + + .handler-item-icon { + width: 80px; + height: 80px; + background: #fff; + border: 1px solid #e2e2e2; + border-radius: 50%; + transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + user-select: none; + text-align: center; + + &:hover { + background: #3296fa; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); + } + + .icon-size { + font-size: 35px; + line-height: 80px; + } + } + + .approve { + color: #ff943e; + } + + .handler-item-text { + margin-top: 4px; + width: 80px; + text-align: center; + } + +} + +// iconfont 样式 +@font-face { + font-family: "iconfont"; /* Project id 4495938 */ + src: url('iconfont.woff2?t=1712392083512') format('woff2'), + url('iconfont.woff?t=1712392083512') format('woff'), + url('iconfont.ttf?t=1712392083512') format('truetype'); +} + +.iconfont { + font-family: "iconfont" !important; + font-size: 16px; + font-style: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.icon-Inclusive:before { + content: "\e602"; +} + +.icon-copy:before { + content: "\e7eb"; +} + +.icon-handle:before { + content: "\e61c"; +} + +.icon-exclusive:before { + content: "\e717"; +} + +.icon-approve:before { + content: "\e715"; +} + +.icon-parallel:before { + content: "\e688"; +} \ No newline at end of file diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index 7ac48369..619b9c4a 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -1,169 +1,30 @@ - - diff --git a/src/views/bpm/simpleWorkflow/index1.vue b/src/views/bpm/simpleWorkflow/index1.vue new file mode 100644 index 00000000..6ee5b4e3 --- /dev/null +++ b/src/views/bpm/simpleWorkflow/index1.vue @@ -0,0 +1,169 @@ + + + From 676ed6bd448c444f532a86832fb5bec6c89b8ab2 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 27 Apr 2024 10:45:53 +0800 Subject: [PATCH 13/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=BA=BA=E8=8A=82=E7=82=B9=E6=94=B9=E9=80=A0?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 4 +- .../src/ProcessNodeTree.vue | 16 +- .../src/SimpleProcessDesigner.vue | 47 ++- .../SimpleProcessDesignerV2/src/consts.ts | 37 ++ .../src/nodes-config/UserTaskNodeConfig.vue | 341 ++++++++++++++++++ .../src/nodes/UserTaskNode.vue | 122 +++++++ 6 files changed, 540 insertions(+), 27 deletions(-) create mode 100644 src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue create mode 100644 src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 7ecbacb5..61672c27 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -25,7 +25,7 @@ diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue new file mode 100644 index 00000000..46d0b85c --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue @@ -0,0 +1,122 @@ + + + From ee895d07525ba684e976b72d304e45ae6a59f4d8 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 27 Apr 2024 22:17:04 +0800 Subject: [PATCH 14/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=E6=8A=84=E9=80=81?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E6=94=B9=E9=80=A0.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 27 +- .../src/ProcessNodeTree.vue | 6 +- .../src/SimpleProcessDesigner.vue | 6 + .../SimpleProcessDesignerV2/src/consts.ts | 9 +- .../src/nodes-config/CopyTaskNodeConfig.vue | 302 ++++++++++++++++++ .../src/nodes-config/UserTaskNodeConfig.vue | 10 +- .../src/nodes/CopyTaskNode.vue | 103 ++++++ .../src/nodes/UserTaskNode.vue | 31 +- .../theme/simple-process-designer.scss | 18 +- src/views/bpm/simpleWorkflow/index.vue | 25 ++ 10 files changed, 500 insertions(+), 37 deletions(-) create mode 100644 src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue create mode 100644 src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 61672c27..6824fa1f 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -9,12 +9,12 @@
审批人
- +
抄送
+ diff --git a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue index 39721c6e..e0b01500 100644 --- a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue +++ b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue @@ -5,7 +5,10 @@ - + + @@ -16,6 +19,7 @@ import StartEventNode from './nodes/StartEventNode.vue'; import EndEventNode from './nodes/EndEventNode.vue'; import UserTaskNode from './nodes/UserTaskNode.vue'; +import CopyTaskNode from './nodes/CopyTaskNode.vue'; import { SimpleFlowNode, NodeType } from './consts'; defineOptions({ name: 'ProcessNodeTree' diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 741a786c..24006ad7 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -102,6 +102,12 @@ const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNo } validateNode(node.childNode, errorNodes) } + if (type === NodeType.COPY_TASK_NODE) { + if (!showText) { + errorNodes.push(node) + } + validateNode(node.childNode, errorNodes) + } if (type === NodeType.CONDITION_NODE) { if (!showText) { errorNodes.push(node) diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index e3998079..54af0563 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -15,6 +15,11 @@ export enum NodeType { * 审批人节点 */ USER_TASK_NODE = 1, + + /** + * 抄送人节点 + */ + COPY_TASK_NODE = 2, /** * 条件节点 @@ -92,11 +97,13 @@ export type SimpleFlowNode = { } export const NODE_DEFAULT_TEXT = new Map() -NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置该节点') +NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置审批人') +NODE_DEFAULT_TEXT.set(NodeType.COPY_TASK_NODE, '请配置抄送人') NODE_DEFAULT_TEXT.set(NodeType.CONDITION_NODE, '请设置条件') export const NODE_DEFAULT_NAME = new Map() NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人') +NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人') NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue new file mode 100644 index 00000000..8b07dca2 --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -0,0 +1,302 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 8716fd92..7ddb43fa 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -204,7 +204,7 @@ const saveConfig = () => { emits('update:modelValue', currentNode.value) settingVisible.value = false } -const getShowText = (): string => { +const getShowText = () : string => { let showText = '' // 指定成员 if (currentNode.value.attributes.candidateStrategy === CandidateStrategy.USER) { @@ -290,11 +290,11 @@ const getShowText = (): string => { const open = () => { settingVisible.value = true } -defineExpose({ open }) // 提供 open 方法,用于打开弹窗 +defineExpose({ open }) // 提供 open 方法,用于打开抽屉 const changeCandidateStrategy = () => { candidateParamArray.value = [] currentNode.value.attributes.approveMethod = 1 - if (currentNode.value.attributes.candidateStrategy === 30) { + if (currentNode.value.attributes.candidateStrategy === CandidateStrategy.USER) { notAllowedMultiApprovers.value = true } else { notAllowedMultiApprovers.value = false @@ -302,7 +302,7 @@ const changeCandidateStrategy = () => { } const changedCandidateUsers = () => { - if (candidateParamArray.value?.length <= 1 && currentNode.value.attributes?.candidateStrategy === 30) { + if (candidateParamArray.value?.length <= 1 && currentNode.value.attributes?.candidateStrategy === CandidateStrategy.USER) { currentNode.value.attributes.approveMethod = 1; notAllowedMultiApprovers.value = true } else { @@ -323,7 +323,7 @@ onMounted(async () => { console.log('candidateParam', currentNode.value.attributes?.candidateParam) candidateParamArray.value = currentNode.value.attributes?.candidateParam?.split(',').map(item=> +item) console.log('candidateParamArray.value', candidateParamArray.value) - if (currentNode.value.attributes?.candidateStrategy === 30 && candidateParamArray.value?.length <= 1) { + if (currentNode.value.attributes?.candidateStrategy === CandidateStrategy.USER && candidateParamArray.value?.length <= 1) { notAllowedMultiApprovers.value = true } else { notAllowedMultiApprovers.value = false diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue new file mode 100644 index 00000000..76266e6c --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue @@ -0,0 +1,103 @@ + + + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue index 46d0b85c..630f1809 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue @@ -3,13 +3,12 @@
-
+
-
+
{{ flowNode.showText }}
@@ -32,8 +31,6 @@
- -
@@ -51,7 +48,7 @@ import NodeHandler from '../NodeHandler.vue' import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'; import { generateUUID } from '@/utils' defineOptions({ - name: 'CommonNode' + name: 'UserTaskNode' }) const props = defineProps({ flowNode: { @@ -62,32 +59,27 @@ const props = defineProps({ const emits = defineEmits<{ 'update:modelValue': [node: SimpleFlowNode | undefined] }>() -const nodeSetting = ref() -const commonNodeConfig = () => { - console.log('nodeSetting', nodeSetting) - nodeSetting.value.open() -} const currentNode = ref(props.flowNode) -console.log('current common node is ', currentNode) - -// 不加这个 COPY 会有问题 +const nodeSetting = ref() +// 打开节点配置 +const openNodeConfig = () => { + nodeSetting.value.open() +} watch( () => props.flowNode, (newValue) => { - console.log('new value is ', newValue) currentNode.value = newValue } ) +// 显示节点名称输入框 const showInput = ref(false) +// 节点名称输入框失去焦点 const blurEvent = (event) => { - console.log('blurEvent', event) showInput.value = false currentNode.value.name = currentNode.value.name || NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string } -const focusEvent = (event: FocusEvent) => { - console.log('focusEvent', event) -} +// 点击节点标题进行输入 const clickEvent = () => { showInput.value = true } @@ -115,7 +107,6 @@ const copyNode = () => { childNode: currentNode.value } currentNode.value = newCopyNode - console.log('current node value', currentNode.value) emits('update:modelValue', currentNode.value) } diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss index 6d2b4130..8b6e96e0 100644 --- a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -108,6 +108,13 @@ .node-title-icon { display: flex; align-items: center; + + &.user-task { + color: #ff943e; + } + &.copy-task { + color: #3296fa; + } } .node-title { @@ -118,7 +125,7 @@ overflow: hidden; text-overflow: ellipsis; color: #1f1f1f; - // vertical-align: middle; + line-height: 18px; } } @@ -458,7 +465,7 @@ text-align: center; &:hover { - background: #3296fa; + background: #e2e2e2; box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); } @@ -466,11 +473,14 @@ font-size: 35px; line-height: 80px; } - } + } .approve { color: #ff943e; - } + } + .copy { + color: #3296fa; + } .handler-item-text { margin-top: 4px; diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index 619b9c4a..de5095a0 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -5,6 +5,11 @@ import { SimpleProcessDesigner } from '@/components/SimpleProcessDesignerV2/src/'; import { getModel } from '@/api/bpm/model' import { getForm, FormVO } from '@/api/bpm/form' +import * as RoleApi from '@/api/system/role' +import * as DeptApi from '@/api/system/dept' +import * as PostApi from '@/api/system/post' +import * as UserApi from '@/api/system/user' +import * as UserGroupApi from '@/api/bpm/userGroup' defineOptions({ name: 'SimpleWorkflowDesignEditor' }) @@ -12,8 +17,18 @@ const { query } = useRoute() // 路由的查询 const modelId : string | undefined = query.modelId as string; const formFields = ref([]) const formType = ref(20); +const roleOptions = ref([]) // 角色列表 +const postOptions = ref([]) // 岗位列表 +const userOptions = ref([]) // 用户列表 +const deptOptions = ref([]) // 部门列表 +const userGroupOptions = ref([]) // 用户组列表 provide('formFields', formFields) provide('formType', formType) +provide('roleList', roleOptions) +provide('postList', postOptions) +provide('userList', userOptions) +provide('deptList', deptOptions) +provide('userGroupList', userGroupOptions) onMounted( async () => { const bpmnModel = await getModel(modelId); if (bpmnModel) { @@ -23,6 +38,16 @@ onMounted( async () => { formFields.value = bpmnForm?.fields } } + // 获得角色列表 + roleOptions.value = await RoleApi.getSimpleRoleList() + postOptions.value = await PostApi.getSimplePostList() + // 获得用户列表 + userOptions.value = await UserApi.getSimpleUserList() + // 获得部门列表 + deptOptions.value = await DeptApi.getSimpleDeptList() + console.log('index deptOptions value is' , deptOptions.value) + // 用户组列表 + userGroupOptions.value = await UserGroupApi.getUserGroupSimpleList() }) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue index 1c9e00b6..4647d1ef 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -5,7 +5,6 @@ :show-close="false" :size="550" :before-close="saveConfig" - class="justify-start" >
-
其它条件不满足进入此分支(该分支不可编辑和删除)
+
其它条件不满足进入此分支(该分支不可编辑和删除)
- + @@ -44,13 +44,13 @@ style="width: 100%" /> - 待实现 - + -->
@@ -93,17 +93,17 @@ const closeDrawer = () => { } // 保存配置 const saveConfig = () => { - if (!currentNode.value.attributes.defaultCondition) { + if (!currentNode.value.attributes.defaultFlow) { currentNode.value.showText = getShowText(); } settingVisible.value = false } const getShowText = () : string => { let showText =''; + // if (currentNode.value.attributes.conditionType === 1) { + // showText = '待实现' + // } if (currentNode.value.attributes.conditionType === 1) { - showText = '待实现' - } - if (currentNode.value.attributes.conditionType === 2) { if (currentNode.value.attributes.conditionExpression) { showText = `表达式:${currentNode.value.attributes.conditionExpression}` } diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue index cac1482f..3c64aa44 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue @@ -28,7 +28,7 @@
-
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue index 8e5275f9..3a8f330a 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue @@ -2,11 +2,7 @@
添加条件
-
+
-
+
+type="text" class="input-max-width editable-title-input" @blur="blurEvent(index)" + v-mountedFocus v-model="item.name" />
{{ item.name }}
优先级{{ index + 1 }}
-
-
+
+
{{ item.showText }}
-
+
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
-
-
+
+ +
+
+
+ +
+ +
+
@@ -49,7 +54,7 @@
- +
@@ -74,14 +79,14 @@ const props = defineProps({ }) // 定义事件,更新父组件 const emits = defineEmits<{ - 'update:modelValue': [node : SimpleFlowNode | undefined] + 'update:modelValue': [node: SimpleFlowNode | undefined] }>() const currentNode = ref(props.flowNode) // const conditionNodes = computed(() => currentNode.value.conditionNodes); -watch(() => props.flowNode, (newValue) => { - currentNode.value = newValue; +watch(() => props.flowNode, (newValue) => { + currentNode.value = newValue; }); // TODO 测试后续去掉 // watch(() => conditionNodes, (newValue) => { @@ -90,17 +95,17 @@ watch(() => props.flowNode, (newValue) => { const showInputs = ref([]) // 失去焦点 -const blurEvent = (index:number) => { +const blurEvent = (index: number) => { showInputs.value[index] = false - const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode; - conditionNode.name = conditionNode.name || '条件' + index + const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode; + conditionNode.name = conditionNode.name || '条件' + index } // 点击条件名称 -const clickEvent = (index:number) => { +const clickEvent = (index: number) => { showInputs.value[index] = true } -const conditionNodeConfig = (nodeId:string) => { +const conditionNodeConfig = (nodeId: string) => { console.log('nodeId', nodeId); console.log("proxy.$refs", proxy.$refs); // TODO 测试后续去掉 @@ -109,29 +114,31 @@ const conditionNodeConfig = (nodeId:string) => { conditionNode.open() } +// 新增条件 const addCondition = () => { - const conditionNodes = currentNode.value.conditionNodes; + const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { const len = conditionNodes.length let lastIndex = len - 1 const conditionData: SimpleFlowNode = { - id: generateUUID(), - name: '条件'+len, - showText : '', + id: 'Flow_' + generateUUID(), + name: '条件' + len, + showText: '', type: NodeType.CONDITION_NODE, childNode: undefined, conditionNodes: [], attributes: { conditionType: 1, - defaultCondition: false + defaultFlow: false } } conditionNodes.splice(lastIndex, 0, conditionData) } } -const deleteCondition = (index:number) => { - const conditionNodes = currentNode.value.conditionNodes; +// 删除条件 +const deleteCondition = (index: number) => { + const conditionNodes = currentNode.value.conditionNodes; if (conditionNodes) { conditionNodes.splice(index, 1) if (conditionNodes.length == 1) { @@ -142,6 +149,17 @@ const deleteCondition = (index:number) => { } } +// 移动节点 +const moveNode = (index: number, to: number) => { + // -1 :向左 1: 向右 + if (currentNode.value.conditionNodes) { + currentNode.value.conditionNodes[index] = currentNode.value.conditionNodes.splice(index + to, + 1, currentNode.value.conditionNodes[index])[0] + } + +} + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue index a77012d5..4cba510a 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue @@ -28,7 +28,7 @@
-
+
diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss index 3522fa9d..6cceb074 100644 --- a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -95,6 +95,10 @@ .node-toolbar { opacity: 1; } + + .branch-node-move { + display: flex; + } } // 普通节点标题 @@ -181,24 +185,74 @@ } } + //条件节点内容 + .branch-node-content { + display: flex; + min-height: 32px; + padding: 4px 8px; + margin-top: 4px; + line-height: 32px; + align-items: center; + color: #111f2c; + border-radius: 4px; + + .branch-node-text { + overflow: hidden; + font-size: 14px; + line-height: 24px; + text-overflow: ellipsis; + word-break: break-all; + -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */ + -webkit-box-orient: vertical; + } + } + + // 节点操作 :删除 .node-toolbar { opacity: 0; position: absolute; - top: -5px; - right: -8px; + top: -25px; + right: 0px; display: flex; .toolbar-icon { text-align: center; vertical-align: middle; - color: #6d6c6e; + color: #000; } } + + // 条件节点左右移动 + .branch-node-move { + position: absolute; + width: 10px; + cursor: pointer; + display: none; + align-items: center; + height: 100%; + justify-content: center; + } + + .move-node-left { + left: -2px; + top: 0px; + background: rgba(126, 134, 142, .08); + border-top-left-radius: 8px; + border-bottom-left-radius: 8px; + } + + .move-node-right { + right: -2px; + top: 0px; + background: rgba(126,134,142,.08); + border-top-right-radius: 6px; + border-bottom-right-radius: 6px; + } } .node-config-error { - border-color: #ff5219; + border-color: #ff5219 !important; } // 普通节点包装 .node-wrapper { From 22af2dc2d93174a1815d263a2c96b2cb976d03a6 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 7 May 2024 23:44:01 +0800 Subject: [PATCH 18/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=8A=82=E7=82=B9=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/ConditionNodeConfig.vue | 45 +++++++++++----- .../src/nodes-config/CopyTaskNodeConfig.vue | 41 +++++++++++---- .../src/nodes-config/UserTaskNodeConfig.vue | 46 ++++++++-------- .../src/nodes/CopyTaskNode.vue | 3 +- .../src/nodes/ExclusiveNode.vue | 25 +++++---- .../src/nodes/UserTaskNode.vue | 3 +- .../SimpleProcessDesignerV2/src/utils.ts | 7 +++ .../theme/simple-process-designer.scss | 52 +++++++++++++++++-- 8 files changed, 157 insertions(+), 65 deletions(-) create mode 100644 src/components/SimpleProcessDesignerV2/src/utils.ts diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue index c449af1b..e539604a 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue @@ -7,9 +7,19 @@ :before-close="saveConfig" >
@@ -65,6 +75,7 @@ diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue index 4647d1ef..3acc2822 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -7,9 +7,19 @@ :before-close="saveConfig" > @@ -144,7 +154,7 @@ diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index f793cd68..7893b9f8 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -8,9 +8,19 @@ class="justify-start" > @@ -162,7 +172,7 @@ diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue index 3c64aa44..9e553a13 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue @@ -27,8 +27,7 @@
- -
+
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue index 3a8f330a..b997be09 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue @@ -15,10 +15,13 @@
-
+
+ type="text" + class="input-max-width editable-title-input" + @blur="blurEvent(index)" + v-mountedFocus + v-model="item.name" />
{{ item.name }}
优先级{{ index + 1 }}
@@ -33,7 +36,7 @@ type="text" class="input-max-width editable-title-input" @blur="blurEvent(index)
- +
- +
@@ -65,6 +68,7 @@ type="text" class="input-max-width editable-title-input" @blur="blurEvent(index) import NodeHandler from '../NodeHandler.vue' import ProcessNodeTree from '../ProcessNodeTree.vue' import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts' +import { getDefaultConditionNodeName } from '../utils' import { generateUUID } from '@/utils' import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue' const { proxy } = getCurrentInstance() as any @@ -88,29 +92,24 @@ const currentNode = ref(props.flowNode) watch(() => props.flowNode, (newValue) => { currentNode.value = newValue; }); -// TODO 测试后续去掉 -// watch(() => conditionNodes, (newValue) => { -// console.log('new conditionNodes is ', newValue); -// },{ deep: true }); + const showInputs = ref([]) // 失去焦点 const blurEvent = (index: number) => { showInputs.value[index] = false const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode; - conditionNode.name = conditionNode.name || '条件' + index + conditionNode.name = conditionNode.name || getDefaultConditionNodeName(index, conditionNode.attributes?.defaultFlow) } + // 点击条件名称 const clickEvent = (index: number) => { showInputs.value[index] = true } const conditionNodeConfig = (nodeId: string) => { - console.log('nodeId', nodeId); console.log("proxy.$refs", proxy.$refs); - // TODO 测试后续去掉 const conditionNode = proxy.$refs[nodeId][0]; - console.log("node inf is ", conditionNode.nodeInfo); conditionNode.open() } diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue index 4cba510a..9e7387f5 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue @@ -27,8 +27,7 @@
- -
+
diff --git a/src/components/SimpleProcessDesignerV2/src/utils.ts b/src/components/SimpleProcessDesignerV2/src/utils.ts new file mode 100644 index 00000000..c68635ae --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/utils.ts @@ -0,0 +1,7 @@ +// 获取条件节点默认的名称 +export const getDefaultConditionNodeName = (index:number, defaultFlow: boolean) : string => { + if ( defaultFlow ){ + return "其它情况" + } + return '条件' + (index+1) +} diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss index 6cceb074..8a35345a 100644 --- a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -91,7 +91,7 @@ transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1); &:hover { - // border-color: #0089ff; + border-color: #0089ff; .node-toolbar { opacity: 1; } @@ -130,6 +130,9 @@ text-overflow: ellipsis; color: #1f1f1f; line-height: 18px; + &:hover { + border-bottom: 1px dashed #f60; + } } } @@ -153,6 +156,9 @@ overflow: hidden; text-overflow: ellipsis; color: #f60; + &:hover { + border-bottom: 1px dashed #000; + } } .branch-priority { @@ -211,14 +217,13 @@ .node-toolbar { opacity: 0; position: absolute; - top: -25px; + top: -20px; right: 0px; display: flex; .toolbar-icon { text-align: center; vertical-align: middle; - color: #000; } } @@ -501,10 +506,47 @@ } } } - - } +// 配置节点头部 +.config-header { + display: flex; + flex-direction: column; + + .node-name { + display: flex; + height: 24px; + line-height: 24px; + cursor: pointer; + align-items: center; + } + + .divide-line { + width: 100%; + height: 1px; + margin-top: 16px; + background: #eee; + } + + .config-editable-input { + height: 24px; + max-width: 510px; + font-size: 16px; + line-height: 24px; + border: 1px solid #d9d9d9; + border-radius: 4px; + transition: all 0.3s; + + &:focus { + border-color: #40a9ff; + outline: 0; + box-shadow: 0 0 0 2px rgba(24, 144, 255, .2) + } + } +} + + + // 节点连线气泡卡片样式 .handler-item-wrapper { display: flex; From 672db903f37d6efe5675f851b66c5ead3dc0dde6 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 8 May 2024 20:04:25 +0800 Subject: [PATCH 19/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E8=8A=82=E7=82=B9=EF=BC=8C=E6=8A=84=E9=80=81=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=A1=A8=E5=8D=95=E5=AD=97=E6=AE=B5=E6=9D=83?= =?UTF-8?q?=E9=99=90=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 12 ++- .../src/ProcessNodeTree.vue | 11 ++- .../src/SimpleProcessDesigner.vue | 4 +- .../src/nodes-config/CopyTaskNodeConfig.vue | 62 +++++++++++---- .../src/nodes-config/UserTaskNodeConfig.vue | 72 +++++++++++++----- .../src/nodes/CopyTaskNode.vue | 12 +-- .../src/nodes/ExclusiveNode.vue | 1 - .../src/nodes/StartEventNode.vue | 18 +++-- .../src/nodes/UserTaskNode.vue | 17 ++--- .../SimpleProcessDesignerV2/src/utils.ts | 16 ++++ .../theme/simple-process-designer.scss | 76 +++++++++++++++++++ 11 files changed, 237 insertions(+), 64 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 73183b14..efd7ac41 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -52,11 +52,13 @@ const props = defineProps({ const emits = defineEmits(['update:childNode']) + const addNode = (type: number) => { popoverShow.value = false if (type === NodeType.USER_TASK_NODE) { + const id = 'Activity_'+ generateUUID(); const data: SimpleFlowNode = { - id: 'Activity_'+ generateUUID(), + id: id, name: NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string, showText: '', type: NodeType.USER_TASK_NODE, @@ -64,11 +66,12 @@ const addNode = (type: number) => { attributes: { approveMethod: 1, candidateStrategy: CandidateStrategy.USER, - candidateParam: undefined + candidateParam: undefined, + fieldsPermission: undefined, }, childNode: props.childNode } - emits('update:childNode', data) + emits('update:childNode', data); } if (type === NodeType.COPY_TASK_NODE) { const data: SimpleFlowNode = { @@ -79,7 +82,8 @@ const addNode = (type: number) => { // 审批节点配置 attributes: { candidateStrategy: CandidateStrategy.USER, - candidateParam: undefined + candidateParam: undefined, + fieldsPermission: undefined }, childNode: props.childNode } diff --git a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue index 1d8e612a..a40ebc27 100644 --- a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue +++ b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue @@ -1,6 +1,9 @@ + + From 632bcb9944c4b51cb5f379313c549616566cab52 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 6 Jun 2024 10:05:34 +0800 Subject: [PATCH 29/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E9=80=9A=E8=BF=87?= =?UTF-8?q?=E5=8F=AA=E9=9C=80=E4=B8=80=E4=BA=BA,=E6=8B=92=E7=BB=9D?= =?UTF-8?q?=E9=9C=80=E8=A6=81=E5=85=A8=E5=91=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 2 +- .../SimpleProcessDesignerV2/src/consts.ts | 44 +++++++++--- .../src/nodes-config/UserTaskNodeConfig.vue | 71 +++++++++++++------ 3 files changed, 85 insertions(+), 32 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 40b7a02f..5e1db576 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -84,7 +84,7 @@ const addNode = (type: number) => { enable: false }, rejectHandler: { - type: RejectHandlerType.TERMINATION + type: RejectHandlerType.FINISH_PROCESS } }, childNode: props.childNode diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 70b201f0..a3638415 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -66,11 +66,20 @@ export enum RejectHandlerType { /** * 结束流程 */ - TERMINATION = 1, + FINISH_PROCESS = 1, /** * 驳回到指定节点 */ - RETURN_PRE_USER_TASK = 2 + RETURN_PRE_USER_TASK = 2, + /** + * 按拒绝人数比例终止流程 + */ + FINISH_PROCESS_BY_REJECT_RATIO = 3, + /** + * 结束任务 + */ + FINISH_TASK = 4 + } // 条件配置类型 ( 用于条件节点配置 ) @@ -99,13 +108,22 @@ export enum ApproveMethodType { */ ALL_APPROVE = 2, /** - * 多人或签(一名审批人同意即可) + * 多人会签(按比例投票) */ - ANY_OF_APPROVE = 3, + APPROVE_BY_RATIO = 3, + /** + * 多人会签(通过只需一人,拒绝需要全员) + */ + ANY_APPROVE_ALL_REJECT = 4, + + /** + * 多人或签(一名审批人通过即可) + */ + ANY_APPROVE = 5, /** * 多人依次审批 */ - SEQUENTIAL_APPROVE = 4 + SEQUENTIAL_APPROVE = 6 } @@ -198,10 +216,12 @@ NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人') NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') export const APPROVE_METHODS: DictDataVO [] = [ - { label: '单人审批', value: 1 }, - { label: '多人会签(需所有审批人同意)', value: 2 }, - { label: '多人或签(一名审批人同意即可)', value: 3 }, - { label: '依次审批(按顺序依次审批)', value: 4 } + { label: '单人审批', value: ApproveMethodType.SINGLE_PERSON_APPROVE }, + { label: '多人会签(需所有审批人同意)', value: ApproveMethodType.ALL_APPROVE }, + // { label: '多人会签(按比例投票)', value: ApproveMethodType.APPROVE_BY_RATIO }, + { label: '多人会签(通过只需一人,拒绝需要全员)', value: ApproveMethodType.ANY_APPROVE_ALL_REJECT }, + { label: '多人或签(一名审批人通过即可)', value: ApproveMethodType.ANY_APPROVE }, + { label: '依次审批(按顺序依次审批)', value: ApproveMethodType.SEQUENTIAL_APPROVE } ] export const CONDITION_CONFIG_TYPES: DictDataVO [] = [ @@ -222,8 +242,10 @@ export const TIMEOUT_HANDLER_ACTION_TYPES: DictDataVO [] = [ { label: '自动拒绝', value: 3 }, ] export const REJECT_HANDLER_TYPES: DictDataVO [] = [ - { label: '结束流程', value: RejectHandlerType.TERMINATION }, - { label: '驳回到指定节点', value: RejectHandlerType.RETURN_PRE_USER_TASK } + { label: '终止流程', value: RejectHandlerType.FINISH_PROCESS }, + { label: '驳回到指定节点', value: RejectHandlerType.RETURN_PRE_USER_TASK }, + { label: '按拒绝人数终止流程(用于会签)', value: RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO } + // { label: '结束任务', value: RejectHandlerType.FINISH_TASK } ] // 比较运算符 diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 5815d176..71fb5411 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -144,7 +144,10 @@ /> - +
审批人拒绝时 - - - + + +
+
+ +
+
- + - + { timeUnit.value = convertTimeUnit(parseTimeUnit) } // 查找可以驳回的用户节点 - const matchNodeList = []; - emits('find:returnTaskNodes', matchNodeList); - returnTaskList.value = matchNodeList; + const matchNodeList = [] + emits('find:returnTaskNodes', matchNodeList) + returnTaskList.value = matchNodeList } defineExpose({ open, setCurrentNode }) // 暴露方法给父组件 @@ -517,12 +529,30 @@ const blurEvent = () => { currentNode.value.name = currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) } -const rejectHandlerTypeChange = () => { - if (currentNode.value.attributes?.rejectHandler.type === RejectHandlerType.RETURN_PRE_USER_TASK) { - - console.log('nodeList is {}', returnTaskList.value); +const approveMethodChanged = () => { + const approveMethod = currentNode.value.attributes?.approveMethod + if (approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT || approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { + currentNode.value.attributes.rejectHandler.type =RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO + } else { + currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS } } +const rejectHandlerOptionDisabled = computed(() => { + return (val: number) => { + const approveMethod = currentNode.value.attributes?.approveMethod + if (val === RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO && approveMethod !== ApproveMethodType.APPROVE_BY_RATIO + && approveMethod !== ApproveMethodType.ANY_APPROVE_ALL_REJECT) { + return true + } + if ( approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT && + val === RejectHandlerType.FINISH_PROCESS + ) { + return true + } + + return false + } +}) // 默认 6小时 const timeDuration = ref(6) const timeUnit = ref(TimeUnitType.HOUR) @@ -540,6 +570,7 @@ const isoTimeDuration = computed(() => { } return strTimeDuration }) + // 超时开关改变 const timeoutHandlerChange = () => { if (currentNode.value.attributes.timeoutHandler.enable) { From cab9553235650f73ac878f08721535b946d3699f Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 13 Jun 2024 08:24:54 +0800 Subject: [PATCH 30/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8=20-=E4=BC=9A=E7=AD=BE?= =?UTF-8?q?=E6=8C=89=E9=80=9A=E8=BF=87=E6=AF=94=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/consts.ts | 4 +- .../src/nodes-config/UserTaskNodeConfig.vue | 43 +++++++++++++------ 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index a3638415..575bfa3f 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -108,7 +108,7 @@ export enum ApproveMethodType { */ ALL_APPROVE = 2, /** - * 多人会签(按比例投票) + * 多人会签(按通过比例) */ APPROVE_BY_RATIO = 3, /** @@ -218,7 +218,7 @@ NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') export const APPROVE_METHODS: DictDataVO [] = [ { label: '单人审批', value: ApproveMethodType.SINGLE_PERSON_APPROVE }, { label: '多人会签(需所有审批人同意)', value: ApproveMethodType.ALL_APPROVE }, - // { label: '多人会签(按比例投票)', value: ApproveMethodType.APPROVE_BY_RATIO }, + { label: '多人会签(按通过比例%)', value: ApproveMethodType.APPROVE_BY_RATIO }, { label: '多人会签(通过只需一人,拒绝需要全员)', value: ApproveMethodType.ANY_APPROVE_ALL_REJECT }, { label: '多人或签(一名审批人通过即可)', value: ApproveMethodType.ANY_APPROVE }, { label: '依次审批(按顺序依次审批)', value: ApproveMethodType.SEQUENTIAL_APPROVE } diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 71fb5411..65af2755 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -149,7 +149,7 @@ @change="approveMethodChanged" >
-
+
{{ item.label }} +
@@ -175,6 +183,7 @@ :label="item.label" :disabled="rejectHandlerOptionDisabled(item.value)" /> +
@@ -512,6 +521,7 @@ const changedCandidateUsers = () => { currentNode.value.attributes?.candidateStrategy === CandidateStrategy.USER ) { currentNode.value.attributes.approveMethod = ApproveMethodType.SINGLE_PERSON_APPROVE + currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS notAllowedMultiApprovers.value = true } else { notAllowedMultiApprovers.value = false @@ -530,26 +540,35 @@ const blurEvent = () => { currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) } const approveMethodChanged = () => { - const approveMethod = currentNode.value.attributes?.approveMethod - if (approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT || approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { - currentNode.value.attributes.rejectHandler.type =RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO + const approveMethod = currentNode.value.attributes?.approveMethod + if ( approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT || approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { + currentNode.value.attributes.rejectHandler.type = + RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO } else { currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS } + + if (approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { + currentNode.value.attributes.approveRatio = 50; + } } const rejectHandlerOptionDisabled = computed(() => { return (val: number) => { - const approveMethod = currentNode.value.attributes?.approveMethod - if (val === RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO && approveMethod !== ApproveMethodType.APPROVE_BY_RATIO - && approveMethod !== ApproveMethodType.ANY_APPROVE_ALL_REJECT) { - return true - } - if ( approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT && - val === RejectHandlerType.FINISH_PROCESS + const approveMethod = currentNode.value.attributes?.approveMethod + if ( + val === RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO && + approveMethod !== ApproveMethodType.APPROVE_BY_RATIO && + approveMethod !== ApproveMethodType.ANY_APPROVE_ALL_REJECT ) { return true } - + if ( + approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT && + val === RejectHandlerType.FINISH_PROCESS + ) { + return true + } + return false } }) From d5a7ae186517e1c50474d0d46524e90ff08310fd Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Fri, 14 Jun 2024 11:10:25 +0800 Subject: [PATCH 31/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=A4=9A=E4=BA=BA=E5=AE=A1=E6=89=B9=E6=96=B9=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 2 +- .../SimpleProcessDesignerV2/src/consts.ts | 30 +++++++------------ .../src/nodes-config/UserTaskNodeConfig.vue | 23 +++++++------- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 5e1db576..e28ef7c9 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -75,7 +75,7 @@ const addNode = (type: number) => { type: NodeType.USER_TASK_NODE, // 审批节点配置 attributes: { - approveMethod: ApproveMethodType.SINGLE_PERSON_APPROVE, + approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, candidateStrategy: CandidateStrategy.USER, candidateParam: undefined, fieldsPermission: undefined, diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 575bfa3f..784e3315 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -95,35 +95,27 @@ export enum ConditionConfigType { */ RULE = 2 } -// 审批方式类型 ( 用于审批节点 ) +// 多人审批方式类型 ( 用于审批节点 ) export enum ApproveMethodType { /** - * 单人审批 + * 随机挑选一人审批 */ - SINGLE_PERSON_APPROVE = 1, + RRANDOM_SELECT_ONE_APPROVE = 1, - /** - * 多人会签(需所有审批人同意) - */ - ALL_APPROVE = 2, /** * 多人会签(按通过比例) */ - APPROVE_BY_RATIO = 3, + APPROVE_BY_RATIO = 2, + /** - * 多人会签(通过只需一人,拒绝需要全员) + * 多人或签(通过只需一人,拒绝只需一人) */ - ANY_APPROVE_ALL_REJECT = 4, - - /** - * 多人或签(一名审批人通过即可) - */ - ANY_APPROVE = 5, + ANY_APPROVE = 3, /** * 多人依次审批 */ - SEQUENTIAL_APPROVE = 6 + SEQUENTIAL_APPROVE = 4 } @@ -216,11 +208,9 @@ NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人') NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') export const APPROVE_METHODS: DictDataVO [] = [ - { label: '单人审批', value: ApproveMethodType.SINGLE_PERSON_APPROVE }, - { label: '多人会签(需所有审批人同意)', value: ApproveMethodType.ALL_APPROVE }, + { label: '随机挑选一人审批', value: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE }, { label: '多人会签(按通过比例%)', value: ApproveMethodType.APPROVE_BY_RATIO }, - { label: '多人会签(通过只需一人,拒绝需要全员)', value: ApproveMethodType.ANY_APPROVE_ALL_REJECT }, - { label: '多人或签(一名审批人通过即可)', value: ApproveMethodType.ANY_APPROVE }, + { label: '多人或签(一人通过或拒绝)', value: ApproveMethodType.ANY_APPROVE }, { label: '依次审批(按顺序依次审批)', value: ApproveMethodType.SEQUENTIAL_APPROVE } ] diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 65af2755..4ee0d310 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -143,7 +143,7 @@ style="width: 100%" /> - + @@ -163,7 +163,7 @@ { candidateParamArray.value = [] - currentNode.value.attributes.approveMethod = ApproveMethodType.SINGLE_PERSON_APPROVE + currentNode.value.attributes.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE if ( currentNode.value.attributes.candidateStrategy === CandidateStrategy.START_USER || currentNode.value.attributes.candidateStrategy === CandidateStrategy.USER @@ -520,7 +520,7 @@ const changedCandidateUsers = () => { candidateParamArray.value?.length <= 1 && currentNode.value.attributes?.candidateStrategy === CandidateStrategy.USER ) { - currentNode.value.attributes.approveMethod = ApproveMethodType.SINGLE_PERSON_APPROVE + currentNode.value.attributes.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS notAllowedMultiApprovers.value = true } else { @@ -541,7 +541,7 @@ const blurEvent = () => { } const approveMethodChanged = () => { const approveMethod = currentNode.value.attributes?.approveMethod - if ( approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT || approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { + if ( approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO } else { @@ -549,7 +549,7 @@ const approveMethodChanged = () => { } if (approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { - currentNode.value.attributes.approveRatio = 50; + currentNode.value.attributes.approveRatio = 100; } } const rejectHandlerOptionDisabled = computed(() => { @@ -557,15 +557,12 @@ const rejectHandlerOptionDisabled = computed(() => { const approveMethod = currentNode.value.attributes?.approveMethod if ( val === RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO && - approveMethod !== ApproveMethodType.APPROVE_BY_RATIO && - approveMethod !== ApproveMethodType.ANY_APPROVE_ALL_REJECT + approveMethod !== ApproveMethodType.APPROVE_BY_RATIO ) { return true } - if ( - approveMethod === ApproveMethodType.ANY_APPROVE_ALL_REJECT && - val === RejectHandlerType.FINISH_PROCESS - ) { + if ( approveMethod === ApproveMethodType.APPROVE_BY_RATIO + && val !== RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO) { return true } From 5ee0a7b946a39c9f69009aa52bbf3e0768101d98 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 18 Jun 2024 00:06:52 +0800 Subject: [PATCH 32/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E7=AE=80=E5=8C=96?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E6=8B=92=E7=BB=9D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/bpm/simple/index.ts | 4 +-- .../src/SimpleProcessDesigner.vue | 2 +- .../SimpleProcessDesignerV2/src/consts.ts | 13 ++------- .../src/nodes-config/UserTaskNodeConfig.vue | 28 ++----------------- src/views/bpm/simpleWorkflow/index.vue | 1 - src/views/bpm/simpleWorkflow/index1.vue | 12 +++----- 6 files changed, 11 insertions(+), 49 deletions(-) diff --git a/src/api/bpm/simple/index.ts b/src/api/bpm/simple/index.ts index 28808565..6e1e995a 100644 --- a/src/api/bpm/simple/index.ts +++ b/src/api/bpm/simple/index.ts @@ -8,8 +8,8 @@ export const updateBpmSimpleModel = async (data) => { }) } -export const getBpmSimpleModel = async (modelId) => { +export const getBpmSimpleModel = async (id) => { return await request.get({ - url: '/bpm/model/simple/get?modelId=' + modelId + url: '/bpm/model/simple/get?id=' + id }) } diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 8b7efff4..d3d0b44c 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -82,7 +82,7 @@ const saveSimpleFlowModel = async () => { return; } const data = { - modelId: props.modelId, + id: props.modelId, simpleModel: processNodeTree.value } diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 784e3315..eb897d47 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -70,15 +70,7 @@ export enum RejectHandlerType { /** * 驳回到指定节点 */ - RETURN_PRE_USER_TASK = 2, - /** - * 按拒绝人数比例终止流程 - */ - FINISH_PROCESS_BY_REJECT_RATIO = 3, - /** - * 结束任务 - */ - FINISH_TASK = 4 + RETURN_USER_TASK = 2 } @@ -233,8 +225,7 @@ export const TIMEOUT_HANDLER_ACTION_TYPES: DictDataVO [] = [ ] export const REJECT_HANDLER_TYPES: DictDataVO [] = [ { label: '终止流程', value: RejectHandlerType.FINISH_PROCESS }, - { label: '驳回到指定节点', value: RejectHandlerType.RETURN_PRE_USER_TASK }, - { label: '按拒绝人数终止流程(用于会签)', value: RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO } + { label: '驳回到指定节点', value: RejectHandlerType.RETURN_USER_TASK } // { label: '结束任务', value: RejectHandlerType.FINISH_TASK } ] diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 4ee0d310..7bb245eb 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -181,7 +181,6 @@ :key="item.value" :value="item.value" :label="item.label" - :disabled="rejectHandlerOptionDisabled(item.value)" />
@@ -191,7 +190,7 @@ { currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) } const approveMethodChanged = () => { + currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS const approveMethod = currentNode.value.attributes?.approveMethod - if ( approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { - currentNode.value.attributes.rejectHandler.type = - RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO - } else { - currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS - } - if (approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { currentNode.value.attributes.approveRatio = 100; } } -const rejectHandlerOptionDisabled = computed(() => { - return (val: number) => { - const approveMethod = currentNode.value.attributes?.approveMethod - if ( - val === RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO && - approveMethod !== ApproveMethodType.APPROVE_BY_RATIO - ) { - return true - } - if ( approveMethod === ApproveMethodType.APPROVE_BY_RATIO - && val !== RejectHandlerType.FINISH_PROCESS_BY_REJECT_RATIO) { - return true - } - - return false - } -}) // 默认 6小时 const timeDuration = ref(6) const timeUnit = ref(TimeUnitType.HOUR) diff --git a/src/views/bpm/simpleWorkflow/index.vue b/src/views/bpm/simpleWorkflow/index.vue index 9d5d2144..dac9aa82 100644 --- a/src/views/bpm/simpleWorkflow/index.vue +++ b/src/views/bpm/simpleWorkflow/index.vue @@ -56,5 +56,4 @@ onMounted( async () => { }) diff --git a/src/views/bpm/simpleWorkflow/index1.vue b/src/views/bpm/simpleWorkflow/index1.vue index 04eb8d89..4d612ff0 100644 --- a/src/views/bpm/simpleWorkflow/index1.vue +++ b/src/views/bpm/simpleWorkflow/index1.vue @@ -53,18 +53,14 @@ const test = async () => { message.error('缺少模型 modelId 编号') return } - const test = nodeConfig.value - console.log('test is ', test) + console.log('nodeConfig.value ', nodeConfig.value) - const data1 = { - modelId: modelId, - simpleModelBody: toRaw(nodeConfig.value) - } + const data = { - modelId: modelId, + id: modelId, simpleModelBody: nodeConfig.value } - console.log('request json data1 is ', data1) + const result = await updateBpmSimpleModel(data) console.log('save the result is ', result) if (result) { From 58fc91b8107634ebcea1393431dd3ea0479ab224 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 19 Jun 2024 20:39:16 +0800 Subject: [PATCH 33/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8-=E5=AD=97=E6=AE=B5=E6=9D=83=E9=99=90?= =?UTF-8?q?=E9=A1=BA=E5=BA=8F=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/nodes-config/UserTaskNodeConfig.vue | 26 +++++++++---------- .../SimpleProcessDesignerV2/src/utils.ts | 20 +++++++------- 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 7bb245eb..86ee6717 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -149,7 +149,11 @@ @change="approveMethodChanged" >
-
+
@@ -177,21 +184,14 @@
- - +
@@ -282,8 +282,8 @@
字段名称
- 可编辑 只读 + 可编辑 隐藏
@@ -542,7 +542,7 @@ const approveMethodChanged = () => { currentNode.value.attributes.rejectHandler.type = RejectHandlerType.FINISH_PROCESS const approveMethod = currentNode.value.attributes?.approveMethod if (approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { - currentNode.value.attributes.approveRatio = 100; + currentNode.value.attributes.approveRatio = 100 } } // 默认 6小时 diff --git a/src/components/SimpleProcessDesignerV2/src/utils.ts b/src/components/SimpleProcessDesignerV2/src/utils.ts index 8cc2fb19..55bb1ab4 100644 --- a/src/components/SimpleProcessDesignerV2/src/utils.ts +++ b/src/components/SimpleProcessDesignerV2/src/utils.ts @@ -1,23 +1,23 @@ // 获取条件节点默认的名称 -export const getDefaultConditionNodeName = (index:number, defaultFlow: boolean) : string => { - if ( defaultFlow ){ - return "其它情况" +export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean): string => { + if (defaultFlow) { + return '其它情况' } - return '条件' + (index+1) + return '条件' + (index + 1) } -// 获得默认的表单字段权限. -export const getDefaultFieldsPermission = (formFields: string[] | undefined) =>{ - const defaultFieldsPermission : any[] = []; - if(formFields){ +// 获得默认的表单字段权限. +export const getDefaultFieldsPermission = (formFields: string[] | undefined) => { + const defaultFieldsPermission: any[] = [] + if (formFields) { formFields.forEach((fieldStr: string) => { const { field, title } = JSON.parse(fieldStr) defaultFieldsPermission.push({ field, title, - permission: '2' // 只读 + permission: '1' // 只读 }) }) } - return defaultFieldsPermission; + return defaultFieldsPermission } From ea1e51a6558cbbe6743d41222369e9c07093c08c Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Wed, 19 Jun 2024 23:54:46 +0800 Subject: [PATCH 34/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E8=AE=BE?= =?UTF-8?q?=E8=AE=A1=E5=99=A8-=20=E5=AE=A1=E6=89=B9=E8=8A=82=E7=82=B9?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 71 +++++---- .../SimpleProcessDesignerV2/src/consts.ts | 137 +++++++++++------- .../src/nodes-config/UserTaskNodeConfig.vue | 117 +++++++-------- 3 files changed, 181 insertions(+), 144 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index e28ef7c9..26aed76c 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -42,7 +42,14 @@ + diff --git a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss index 3d633b6d..ecf4250a 100644 --- a/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss +++ b/src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss @@ -241,7 +241,7 @@ .move-node-left { left: -2px; top: 0px; - background: rgba(126, 134, 142, .08); + background: rgba(126, 134, 142, 0.08); border-top-left-radius: 8px; border-bottom-left-radius: 8px; } @@ -249,13 +249,12 @@ .move-node-right { right: -2px; top: 0px; - background: rgba(126,134,142,.08); + background: rgba(126, 134, 142, 0.08); border-top-right-radius: 6px; border-bottom-right-radius: 6px; } } - .node-config-error { border-color: #ff5219 !important; } @@ -306,12 +305,10 @@ background-color: #0089ff; border-radius: 50%; - &:hover{ + &:hover { transform: scale(1.1); - } } - } .node-handler-arrow { @@ -323,7 +320,6 @@ } } - // 条件节点包装 .branch-node-wrapper { position: relative; @@ -341,8 +337,8 @@ position: absolute; height: 100%; width: 4px; - background-color: #fafafa; - content: ""; + background-color: #fafafa; + content: ''; left: 50%; transform: translate(-50%); } @@ -498,10 +494,10 @@ border-radius: 4px; transition: all 0.3s; - &:focus { + &:focus { border-color: #40a9ff; outline: 0; - box-shadow: 0 0 0 2px rgba(24, 144, 255, .2) + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); } } } @@ -537,11 +533,11 @@ border: 1px solid #d9d9d9; border-radius: 4px; transition: all 0.3s; - - &:focus { + + &:focus { border-color: #40a9ff; outline: 0; - box-shadow: 0 0 0 2px rgba(24, 144, 255, .2) + box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2); } } } @@ -550,7 +546,6 @@ .field-setting-pane { display: flex; flex-direction: column; - padding: 16px 0; font-size: 14px; .field-setting-desc { @@ -569,7 +564,7 @@ line-height: 45px; background-color: #f8fafc0a; border: 1px solid #1f38581a; - + .first-title { text-align: left !important; } @@ -588,9 +583,8 @@ color: #000; text-align: center; } - } - + .field-setting-item { align-items: center; display: flex; @@ -632,56 +626,56 @@ margin-right: 8px; } - .handler-item-icon { - width: 80px; - height: 80px; - background: #fff; - border: 1px solid #e2e2e2; - border-radius: 50%; - transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); - user-select: none; - text-align: center; + .handler-item-icon { + width: 80px; + height: 80px; + background: #fff; + border: 1px solid #e2e2e2; + border-radius: 50%; + transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1); + user-select: none; + text-align: center; - &:hover { - background: #e2e2e2; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); - } + &:hover { + background: #e2e2e2; + box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); + } - .icon-size { - font-size: 35px; - line-height: 80px; - } + .icon-size { + font-size: 35px; + line-height: 80px; + } } - .approve { - color: #ff943e; + .approve { + color: #ff943e; } .copy { color: #3296fa; } - + .condition { color: #15bc83; } - .handler-item-text { - margin-top: 4px; - width: 80px; - text-align: center; - } - + .handler-item-text { + margin-top: 4px; + width: 80px; + text-align: center; + } } // iconfont 样式 @font-face { - font-family: "iconfont"; /* Project id 4495938 */ - src: url('iconfont.woff2?t=1712392083512') format('woff2'), - url('iconfont.woff?t=1712392083512') format('woff'), - url('iconfont.ttf?t=1712392083512') format('truetype'); + font-family: 'iconfont'; /* Project id 4495938 */ + src: + url('iconfont.woff2?t=1712392083512') format('woff2'), + url('iconfont.woff?t=1712392083512') format('woff'), + url('iconfont.ttf?t=1712392083512') format('truetype'); } .iconfont { - font-family: "iconfont" !important; + font-family: 'iconfont' !important; font-size: 16px; font-style: normal; -webkit-font-smoothing: antialiased; @@ -689,25 +683,25 @@ } .icon-Inclusive:before { - content: "\e602"; + content: '\e602'; } .icon-copy:before { - content: "\e7eb"; + content: '\e7eb'; } .icon-handle:before { - content: "\e61c"; + content: '\e61c'; } .icon-exclusive:before { - content: "\e717"; + content: '\e717'; } .icon-approve:before { - content: "\e715"; + content: '\e715'; } .icon-parallel:before { - content: "\e688"; -} \ No newline at end of file + content: '\e688'; +} diff --git a/src/views/bpm/processInstance/detail/index.vue b/src/views/bpm/processInstance/detail/index.vue index 94475647..0a9f96a3 100644 --- a/src/views/bpm/processInstance/detail/index.vue +++ b/src/views/bpm/processInstance/detail/index.vue @@ -56,29 +56,71 @@
- + - 通过 + {{ + item.buttonsSetting?.[OpsButtonType.APPROVE]?.displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.APPROVE) + }} - + - 不通过 + {{ + item.buttonsSetting?.[OpsButtonType.REJECT].displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.REJECT) + }} - + - 转办 + {{ + item.buttonsSetting?.[OpsButtonType.TRANSFER]?.displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.TRANSFER) + }} - + - 委派 + {{ + item.buttonsSetting?.[OpsButtonType.DELEGATE]?.displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.DELEGATE) + }} - + - 加签 + {{ + item.buttonsSetting?.[OpsButtonType.ADD_SIGN]?.displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.ADD_SIGN) + }} - + - 回退 + {{ + item.buttonsSetting?.[OpsButtonType.RETURN]?.displayName || + OPERATION_BUTTON_NAME.get(OpsButtonType.RETURN) + }}
@@ -147,6 +189,10 @@ import TaskSignCreateForm from './dialog/TaskSignCreateForm.vue' import { registerComponent } from '@/utils/routerHelper' import { isEmpty } from '@/utils/is' import * as UserApi from '@/api/system/user' +import { + OpsButtonType, + OPERATION_BUTTON_NAME +} from '@/components/SimpleProcessDesignerV2/src/consts' defineOptions({ name: 'BpmProcessInstanceDetail' }) @@ -280,12 +326,16 @@ const getProcessInstance = async () => { // 设置表单信息 const processDefinition = data.processDefinition if (processDefinition.formType === 10) { - setConfAndFields2( - detailForm, - processDefinition.formConf, - processDefinition.formFields, - data.formVariables - ) + if (detailForm.value.rule.length > 0) { + detailForm.value.value = data.formVariables + } else { + setConfAndFields2( + detailForm, + processDefinition.formConf, + processDefinition.formFields, + data.formVariables + ) + } nextTick().then(() => { fApi.value?.btn.show(false) fApi.value?.resetBtn.show(false) From 2c11228f55bacf43f9a9269b898cc40be9558205 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 20 Jul 2024 14:50:05 +0800 Subject: [PATCH 38/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1-=20=20bug=20=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/NodeHandler.vue | 8 +- .../src/ProcessNodeTree.vue | 28 ++- .../src/SimpleProcessDesigner.vue | 58 +++--- .../src/nodes-config/CopyTaskNodeConfig.vue | 42 +++-- .../src/nodes-config/UserTaskNodeConfig.vue | 48 +++-- .../src/nodes/CopyTaskNode.vue | 48 ++--- .../src/nodes/ExclusiveNode.vue | 86 +++++---- .../src/nodes/ParallelNode.vue | 66 ++++--- .../src/nodes/UserTaskNode.vue | 45 ++--- src/views/bpm/simpleWorkflow/index1.vue | 165 ------------------ 10 files changed, 215 insertions(+), 379 deletions(-) delete mode 100644 src/views/bpm/simpleWorkflow/index1.vue diff --git a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue index 3e56e793..b5ba51bf 100644 --- a/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue +++ b/src/components/SimpleProcessDesignerV2/src/NodeHandler.vue @@ -47,8 +47,7 @@ import { NodeType, NODE_DEFAULT_NAME, ApproveMethodType, - RejectHandlerType, - CandidateStrategy + RejectHandlerType } from './consts' import { generateUUID } from '@/utils' defineOptions({ @@ -80,7 +79,6 @@ const addNode = (type: number) => { showText: '', type: NodeType.USER_TASK_NODE, approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, - candidateStrategy: CandidateStrategy.USER, // 超时处理 rejectHandler: { type: RejectHandlerType.FINISH_PROCESS @@ -88,7 +86,6 @@ const addNode = (type: number) => { timeoutHandler: { enable: false }, - childNode: props.childNode } emits('update:childNode', data) @@ -99,9 +96,6 @@ const addNode = (type: number) => { name: NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE) as string, showText: '', type: NodeType.COPY_TASK_NODE, - candidateStrategy: CandidateStrategy.USER, - candidateParam: undefined, - fieldsPermission: undefined, childNode: props.childNode } emits('update:childNode', data) diff --git a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue index c7589089..d11e67cc 100644 --- a/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue +++ b/src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue @@ -3,20 +3,19 @@ - - + @@ -65,11 +64,14 @@ const props = defineProps({ } }) const emits = defineEmits<{ - 'update:flowNode', - 'find:recursiveFindParentNode': [nodeList: SimpleFlowNode[], curentNode: SimpleFlowNode, nodeType: number] + 'update:flowNode': [node: SimpleFlowNode | undefined] + 'find:recursiveFindParentNode': [ + nodeList: SimpleFlowNode[], + curentNode: SimpleFlowNode, + nodeType: number + ] }>() - const currentNode = ref(props.flowNode) // 重要:监控节点变化. 重新绘制节点 @@ -79,16 +81,12 @@ watch( currentNode.value = newValue } ) - +// 用于删除节点 const handleModelValueUpdate = (updateValue) => { - console.log('Process Node Tree handleModelValueUpdate', updateValue) emits('update:flowNode', updateValue) } -const findFromParentNode = ( - nodeList: SimpleFlowNode[], - nodeType: number -) => { +const findFromParentNode = (nodeList: SimpleFlowNode[], nodeType: number) => { emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType) } diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index d3d0b44c..b26c2fea 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -15,25 +15,29 @@
- +
以下节点内容不完善,请修改后保存
-
- {{ item.name }} : {{ NODE_DEFAULT_TEXT.get(item.type) }} +
+ {{ item.name }} : {{ NODE_DEFAULT_TEXT.get(item.type) }}
diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue index ee863c99..b1ee7e1f 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -14,11 +14,11 @@ class="config-editable-input" @blur="blurEvent()" v-mountedFocus - v-model="currentNode.name" - :placeholder="currentNode.name" + v-model="configForm.name" + :placeholder="configForm.name" />
{{ currentNode.name }} + >{{ configForm.name }}
@@ -223,8 +223,15 @@ const props = defineProps({ }) // 是否可见 const settingVisible = ref(false) -// 当前节点信息 +// 当前节点 const currentNode = ref(props.flowNode) +// 监控节点变化 +watch( + () => props.flowNode, + (newValue) => { + currentNode.value = newValue + } +) const roleOptions = inject>('roleList') // 角色列表 const postOptions = inject>('postList') // 岗位列表 const userOptions = inject>('userList') // 用户列表 @@ -247,13 +254,14 @@ const activeTabName = ref('user') const formRef = ref() // 表单 Ref const configForm = ref({ + name: NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE), candidateParamArray: [], candidateStrategy: CandidateStrategy.USER, fieldsPermission: [] }) // 表单校验规则 const formRules = reactive({ - candidateStrategy: [{ required: true }], + candidateStrategy: [{ required: true, message: '抄送人设置不能为空', trigger: 'change' }], candidateParamArray: [{ required: true, message: '选项不能为空', trigger: 'blur' }] }) @@ -269,6 +277,7 @@ const saveConfig = async () => { if (!valid) return false const showText = getShowText() if (!showText) return false + currentNode.value.name = configForm.value.name currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',') currentNode.value.candidateStrategy = configForm.value.candidateStrategy currentNode.value.showText = showText @@ -280,11 +289,10 @@ const saveConfig = async () => { const open = () => { settingVisible.value = true } -// 修改当前编辑的节点, 由父组件传过来 +// 设置抄送节点 const setCurrentNode = (node: SimpleFlowNode) => { - currentNode.value = node - configForm.value.fieldsPermission = - cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value) + configForm.value.name = node.name + // 抄送人设置 configForm.value.candidateStrategy = node.candidateStrategy const strCandidateParam = node?.candidateParam if (node.candidateStrategy === CandidateStrategy.EXPRESSION) { @@ -294,6 +302,9 @@ const setCurrentNode = (node: SimpleFlowNode) => { configForm.value.candidateParamArray = strCandidateParam.split(',').map((item) => +item) } } + // 表单字段权限 + configForm.value.fieldsPermission = + cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value) } defineExpose({ open, setCurrentNode }) // 暴露方法给父组件 @@ -387,16 +398,9 @@ const clickIcon = () => { // 输入框失去焦点 const blurEvent = () => { showInput.value = false - currentNode.value.name = - currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE) as string) + configForm.value.name = + configForm.value.name || (NODE_DEFAULT_NAME.get(NodeType.COPY_TASK_NODE) as string) } - + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 6254ebeb..cb55341e 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -15,11 +15,11 @@ class="config-editable-input" @blur="blurEvent()" v-mountedFocus - v-model="currentNode.name" - :placeholder="currentNode.name" + v-model="configForm.name" + :placeholder="configForm.name" />
{{ currentNode.name }} + >{{ configForm.name }}
@@ -394,8 +394,15 @@ const emits = defineEmits<{ 'find:returnTaskNodes': [nodeList: SimpleFlowNode[]] }>() -const notAllowedMultiApprovers = ref(false) const currentNode = ref(props.flowNode) +// 监控节点变化 +watch( + () => props.flowNode, + (newValue) => { + currentNode.value = newValue + } +) +const notAllowedMultiApprovers = ref(false) const settingVisible = ref(false) const roleOptions = inject>('roleList') // 角色列表 const postOptions = inject>('postList') // 岗位列表 @@ -410,6 +417,7 @@ const returnTaskList = ref([]) const formRef = ref() // 表单 Ref const activeTabName = ref('user') // 激活的 Tab 标签页 const configForm = ref({ + name: NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE), candidateParamArray: [], candidateStrategy: CandidateStrategy.USER, approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, @@ -425,7 +433,7 @@ const configForm = ref({ }) // 表单校验规则 const formRules = reactive({ - candidateStrategy: [{ required: true }], + candidateStrategy: [{ required: true, message: '审批人设置不能为空', trigger: 'change' }], candidateParamArray: [{ required: true, message: '该选项不能为空', trigger: 'change' }], approveMethod: [{ required: true, message: '多人审批方式不能为空', trigger: 'change' }], approveRatio: [{ required: true, message: '通过比例不能为空', trigger: 'blur' }], @@ -447,6 +455,7 @@ const saveConfig = async () => { if (!valid) return false const showText = getShowText() if (!showText) return false + currentNode.value.name = configForm.value.name currentNode.value.candidateStrategy = configForm.value.candidateStrategy currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',') // 设置审批方式 @@ -566,12 +575,10 @@ const getShowText = (): string => { const open = () => { settingVisible.value = true } -// 修改当前编辑的节点, 由父组件传过来 +// 配置审批节点, 由父组件传过来 const setCurrentNode = (node: SimpleFlowNode) => { - currentNode.value = node - configForm.value.fieldsPermission = - cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value) - configForm.value.buttonsSetting = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING + configForm.value.name = node.name + //1.1 审批人设置 configForm.value.candidateStrategy = node.candidateStrategy const strCandidateParam = node?.candidateParam if (node.candidateStrategy === CandidateStrategy.EXPRESSION) { @@ -580,7 +587,6 @@ const setCurrentNode = (node: SimpleFlowNode) => { if (strCandidateParam) { configForm.value.candidateParamArray = strCandidateParam.split(',').map((item) => +item) } - configForm.value.candidateStrategy = node.candidateStrategy } if ( (configForm.value.candidateParamArray?.length <= 1 && @@ -591,13 +597,18 @@ const setCurrentNode = (node: SimpleFlowNode) => { } else { notAllowedMultiApprovers.value = false } - // 设置审批方式 + //1.2 设置审批方式 configForm.value.approveMethod = node.approveMethod if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) { configForm.value.approveRatio = node.approveRatio } + // 1.3 设置审批拒绝处理 configForm.value.rejectHandlerType = node.rejectHandler?.type configForm.value.returnNodeId = node.rejectHandler?.returnNodeId + const matchNodeList = [] + emits('find:returnTaskNodes', matchNodeList) + returnTaskList.value = matchNodeList + // 1.4 设置审批超时处理 configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) { const strTimeDuration = node.timeoutHandler.timeDuration @@ -608,10 +619,11 @@ const setCurrentNode = (node: SimpleFlowNode) => { } configForm.value.timeoutHandlerAction = node.timeoutHandler?.action configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount - // 查找可以驳回的用户节点 - const matchNodeList = [] - emits('find:returnTaskNodes', matchNodeList) - returnTaskList.value = matchNodeList + // 2. 操作按钮设置 + configForm.value.buttonsSetting = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING + // 3. 表单字段权限配置 + configForm.value.fieldsPermission = + cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value) } defineExpose({ open, setCurrentNode }) // 暴露方法给父组件 @@ -650,8 +662,8 @@ const clickIcon = () => { // 节点名称输入框失去焦点 const blurEvent = () => { showInput.value = false - currentNode.value.name = - currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) + configForm.value.name = + configForm.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) } const approveMethodChanged = () => { diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue index ca9ff0ea..9448174d 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue @@ -1,7 +1,7 @@ - - + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue index e2e5a92c..568afa28 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue @@ -2,9 +2,13 @@
添加条件
-
+
@@ -280,7 +278,7 @@
- +
操作按钮
@@ -288,11 +286,7 @@
显示名称
启用
-
+
{{ OPERATION_BUTTON_NAME.get(item.id) }}
{{ item.title }}
@@ -368,19 +362,22 @@ import { TIMEOUT_HANDLER_ACTION_TYPES, TIME_UNIT_TYPES, REJECT_HANDLER_TYPES, - NODE_DEFAULT_NAME, DEFAULT_BUTTON_SETTING, - OPERATION_BUTTON_NAME + OPERATION_BUTTON_NAME, + ButtonSetting } from '../consts' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -import { getDefaultFieldsPermission } from '../utils' +import { + useWatchNode, + useNodeName, + useFormFieldsPermission, + useNodeForm, + UserTaskFormType, + useDrawer +} from '../node' import { defaultProps } from '@/utils/tree' -import * as RoleApi from '@/api/system/role' -import * as DeptApi from '@/api/system/dept' -import * as PostApi from '@/api/system/post' -import * as UserApi from '@/api/system/user' -import * as UserGroupApi from '@/api/bpm/userGroup' import { cloneDeep } from 'lodash-es' +import { convertTimeUnit } from '../utils' defineOptions({ name: 'UserTaskNodeConfig' }) @@ -393,44 +390,22 @@ const props = defineProps({ const emits = defineEmits<{ 'find:returnTaskNodes': [nodeList: SimpleFlowNode[]] }>() +// 监控节点的变化 +const currentNode = useWatchNode(props) +// 抽屉配置 +const { settingVisible, closeDrawer, openDrawer } = useDrawer() +// 节点名称配置 +const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.USER_TASK_NODE) +// 激活的 Tab 标签页 +const activeTabName = ref('user') +// 表单字段权限设置 +const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission() +// 操作按钮设置 +const { buttonsSetting, btnDisplayNameEdit, changeBtnDisplayName, btnDisplayNameBlurEvent } = + useButtonsSetting() -const currentNode = ref(props.flowNode) -// 监控节点变化 -watch( - () => props.flowNode, - (newValue) => { - currentNode.value = newValue - } -) -const notAllowedMultiApprovers = ref(false) -const settingVisible = ref(false) -const roleOptions = inject>('roleList') // 角色列表 -const postOptions = inject>('postList') // 岗位列表 -const userOptions = inject>('userList') // 用户列表 -const deptOptions = inject>('deptList') // 部门列表 -const userGroupOptions = inject>('userGroupList') // 用户组列表 -const deptTreeOptions = inject('deptTree') // 部门树 -const formType = inject('formType') // 表单类型 -const formFields = inject>('formFields') -const returnTaskList = ref([]) - +// 审批人表单设置 const formRef = ref() // 表单 Ref -const activeTabName = ref('user') // 激活的 Tab 标签页 -const configForm = ref({ - name: NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE), - candidateParamArray: [], - candidateStrategy: CandidateStrategy.USER, - approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, - approveRatio: 100, - rejectHandlerType: RejectHandlerType.FINISH_PROCESS, - returnNodeId: '', - timeoutHandlerEnable: false, - timeoutHandlerAction: 1, - timeDuration: 6, // 默认 6小时 - maxRemindCount: 1, // 默认 提醒 1次 - fieldsPermission: [], - buttonsSetting: [] -}) // 表单校验规则 const formRules = reactive({ candidateStrategy: [{ required: true, message: '审批人设置不能为空', trigger: 'change' }], @@ -443,10 +418,66 @@ const formRules = reactive({ timeDuration: [{ required: true, message: '超时时间不能为空', trigger: 'blur' }], maxRemindCount: [{ required: true, message: '提醒次数不能为空', trigger: 'blur' }] }) -// 关闭 -const closeDrawer = () => { - settingVisible.value = false + +const { + configForm: tempConfigForm, + roleOptions, + postOptions, + userOptions, + userGroupOptions, + deptTreeOptions, + getShowText +} = useNodeForm(NodeType.USER_TASK_NODE) +const configForm = tempConfigForm as Ref +// 不允许多人审批 +const notAllowedMultiApprovers = ref(false) +// 改变审批人设置策略 +const changeCandidateStrategy = () => { + configForm.value.candidateParamArray = [] + configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE + if ( + configForm.value.candidateStrategy === CandidateStrategy.START_USER || + configForm.value.candidateStrategy === CandidateStrategy.USER + ) { + notAllowedMultiApprovers.value = true + } else { + notAllowedMultiApprovers.value = false + } } +// 改变审批候选人 +const changedCandidateUsers = () => { + if ( + configForm.value.candidateParamArray?.length <= 1 && + configForm.value.candidateStrategy === CandidateStrategy.USER + ) { + configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE + configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS + notAllowedMultiApprovers.value = true + } else { + notAllowedMultiApprovers.value = false + } +} +// 审批方式改变 +const 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([]) +// 审批人超时未处理设置 +const { + timeoutHandlerChange, + cTimeoutAction, + timeoutActionChanged, + timeUnit, + timeUnitChange, + isoTimeDuration, + cTimeoutMaxRemindCount +} = useTimeoutHandler() + // 保存配置 const saveConfig = async () => { activeTabName.value = 'user' @@ -455,7 +486,7 @@ const saveConfig = async () => { if (!valid) return false const showText = getShowText() if (!showText) return false - currentNode.value.name = configForm.value.name + currentNode.value.name = nodeName.value! currentNode.value.candidateStrategy = configForm.value.candidateStrategy currentNode.value.candidateParam = configForm.value.candidateParamArray?.join(',') // 设置审批方式 @@ -465,121 +496,31 @@ const saveConfig = async () => { } // 设置拒绝处理 currentNode.value.rejectHandler = { - type: configForm.value.rejectHandlerType, + type: configForm.value.rejectHandlerType!, returnNodeId: configForm.value.returnNodeId } // 设置超时处理 currentNode.value.timeoutHandler = { - enable: configForm.value.timeoutHandlerEnable, + enable: configForm.value.timeoutHandlerEnable!, action: cTimeoutAction.value, timeDuration: isoTimeDuration.value, maxRemindCount: cTimeoutMaxRemindCount.value } // 设置表单权限 - currentNode.value.fieldsPermission = configForm.value.fieldsPermission + currentNode.value.fieldsPermission = fieldsPermissionConfig.value // 设置按钮权限 - currentNode.value.buttonsSetting = configForm.value.buttonsSetting + currentNode.value.buttonsSetting = buttonsSetting.value - currentNode.value.showText = getShowText() + currentNode.value.showText = showText settingVisible.value = false return true } -const getShowText = (): string => { - let showText = '' - // 指定成员 - if (configForm.value.candidateStrategy === CandidateStrategy.USER) { - if (configForm.value.candidateParamArray?.length > 0) { - const candidateNames: string[] = [] - userOptions?.value.forEach((item) => { - if (configForm.value.candidateParamArray.includes(item.id)) { - candidateNames.push(item.nickname) - } - }) - showText = `指定成员:${candidateNames.join(',')}` - } - } - // 指定角色 - if (configForm.value.candidateStrategy === CandidateStrategy.ROLE) { - if (configForm.value.candidateParamArray?.length > 0) { - const candidateNames: string[] = [] - roleOptions?.value.forEach((item) => { - if (configForm.value.candidateParamArray.includes(item.id)) { - candidateNames.push(item.name) - } - }) - showText = `指定角色:${candidateNames.join(',')}` - } - } - // 指定部门 - if ( - configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER || - configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER - ) { - if (configForm.value.candidateParamArray?.length > 0) { - const candidateNames: string[] = [] - deptOptions?.value.forEach((item) => { - if (configForm.value.candidateParamArray.includes(item.id)) { - candidateNames.push(item.name) - } - }) - if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) { - showText = `部门成员:${candidateNames.join(',')}` - } else { - showText = `部门的负责人:${candidateNames.join(',')}` - } - } - } - // 指定岗位 - if (configForm.value.candidateStrategy === CandidateStrategy.POST) { - if (configForm.value.candidateParamArray?.length > 0) { - const candidateNames: string[] = [] - postOptions?.value.forEach((item) => { - if (configForm.value.candidateParamArray.includes(item.id)) { - candidateNames.push(item.name) - } - }) - showText = `指定岗位: ${candidateNames.join(',')}` - } - } - // 指定用户组 - if (configForm.value.candidateStrategy === CandidateStrategy.USER_GROUP) { - if (configForm.value.candidateParamArray?.length > 0) { - const candidateNames: string[] = [] - userGroupOptions?.value.forEach((item) => { - if (configForm.value.candidateParamArray.includes(item.id)) { - candidateNames.push(item.name) - } - }) - showText = `指定用户组: ${candidateNames.join(',')}` - } - } - - // 发起人自选 - if (configForm.value.candidateStrategy === CandidateStrategy.START_USER_SELECT) { - showText = `发起人自选` - } - // 发起人自己 - if (configForm.value.candidateStrategy === CandidateStrategy.START_USER) { - showText = `发起人自己` - } - - // 流程表达式 - if (configForm.value.candidateStrategy === CandidateStrategy.EXPRESSION) { - if (configForm.value.candidateParamArray?.length > 0) { - showText = `流程表达式:${configForm.value.candidateParamArray[0]}` - } - } - return showText -} -const open = () => { - settingVisible.value = true -} -// 配置审批节点, 由父组件传过来 -const setCurrentNode = (node: SimpleFlowNode) => { - configForm.value.name = node.name +// 显示审批节点配置, 由父组件传过来 +const showUserTaskNodeConfig = (node: SimpleFlowNode) => { + nodeName.value = node.name //1.1 审批人设置 - configForm.value.candidateStrategy = node.candidateStrategy + configForm.value.candidateStrategy = node.candidateStrategy! const strCandidateParam = node?.candidateParam if (node.candidateStrategy === CandidateStrategy.EXPRESSION) { configForm.value.candidateParamArray[0] = strCandidateParam @@ -598,18 +539,18 @@ const setCurrentNode = (node: SimpleFlowNode) => { notAllowedMultiApprovers.value = false } //1.2 设置审批方式 - configForm.value.approveMethod = node.approveMethod + configForm.value.approveMethod = node.approveMethod! if (node.approveMethod == ApproveMethodType.APPROVE_BY_RATIO) { - configForm.value.approveRatio = node.approveRatio + configForm.value.approveRatio = node.approveRatio! } // 1.3 设置审批拒绝处理 - configForm.value.rejectHandlerType = node.rejectHandler?.type + configForm.value.rejectHandlerType = node.rejectHandler!.type configForm.value.returnNodeId = node.rejectHandler?.returnNodeId const matchNodeList = [] emits('find:returnTaskNodes', matchNodeList) returnTaskList.value = matchNodeList // 1.4 设置审批超时处理 - configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable + configForm.value.timeoutHandlerEnable = node.timeoutHandler!.enable if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) { const strTimeDuration = node.timeoutHandler.timeDuration let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1) @@ -620,152 +561,121 @@ const setCurrentNode = (node: SimpleFlowNode) => { configForm.value.timeoutHandlerAction = node.timeoutHandler?.action configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount // 2. 操作按钮设置 - configForm.value.buttonsSetting = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING + buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING // 3. 表单字段权限配置 - configForm.value.fieldsPermission = - cloneDeep(node.fieldsPermission) || getDefaultFieldsPermission(formFields?.value) + getNodeConfigFormFields(node.fieldsPermission) } -defineExpose({ open, setCurrentNode }) // 暴露方法给父组件 +defineExpose({ openDrawer, showUserTaskNodeConfig }) // 暴露方法给父组件 -const changeCandidateStrategy = () => { - configForm.value.candidateParamArray = [] - configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE - if ( - configForm.value.candidateStrategy === CandidateStrategy.START_USER || - configForm.value.candidateStrategy === CandidateStrategy.USER - ) { - notAllowedMultiApprovers.value = true - } else { - notAllowedMultiApprovers.value = false +/** + * @description 操作按钮设置 + */ +function useButtonsSetting() { + const buttonsSetting = ref() + // 操作按钮显示名称可编辑 + const btnDisplayNameEdit = ref([]) + const changeBtnDisplayName = (index: number) => { + btnDisplayNameEdit.value[index] = true + } + const btnDisplayNameBlurEvent = (index: number) => { + btnDisplayNameEdit.value[index] = false + const buttonItem = buttonsSetting.value![index] + buttonItem.displayName = buttonItem.displayName || OPERATION_BUTTON_NAME.get(buttonItem.id)! + } + return { + buttonsSetting, + btnDisplayNameEdit, + changeBtnDisplayName, + btnDisplayNameBlurEvent } } -const changedCandidateUsers = () => { - if ( - configForm.value.candidateParamArray?.length <= 1 && - configForm.value.candidateStrategy === CandidateStrategy.USER - ) { - configForm.value.approveMethod = ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE - configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS - notAllowedMultiApprovers.value = true - } else { - notAllowedMultiApprovers.value = false - } -} -// 显示名称输入框 -const showInput = ref(false) +/** + * @description 审批人超时未处理配置 + */ +function useTimeoutHandler() { + // 时间单位 + const timeUnit = ref(TimeUnitType.HOUR) -const clickIcon = () => { - showInput.value = true -} -// 节点名称输入框失去焦点 -const blurEvent = () => { - showInput.value = false - configForm.value.name = - configForm.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string) -} + // 超时开关改变 + const timeoutHandlerChange = () => { + if (configForm.value.timeoutHandlerEnable) { + timeUnit.value = 2 + configForm.value.timeDuration = 6 + configForm.value.timeoutHandlerAction = 1 + configForm.value.maxRemindCount = 1 + } + } + // 超时执行的动作 + const cTimeoutAction = computed(() => { + if (!configForm.value.timeoutHandlerEnable) { + return undefined + } + return configForm.value.timeoutHandlerAction + }) -const approveMethodChanged = () => { - configForm.value.rejectHandlerType = RejectHandlerType.FINISH_PROCESS - if (configForm.value.approveMethod === ApproveMethodType.APPROVE_BY_RATIO) { - configForm.value.approveRatio = 100 + // 超时处理动作改变 + const timeoutActionChanged = () => { + if (configForm.value.timeoutHandlerAction === 1) { + configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1 + } } - formRef.value.clearValidate('approveRatio') -} -const timeUnit = ref(TimeUnitType.HOUR) + // 时间单位改变 + const timeUnitChange = () => { + // 分钟,默认是 60 分钟 + if (timeUnit.value === TimeUnitType.MINUTE) { + configForm.value.timeDuration = 60 + } + // 小时,默认是 6 个小时 + if (timeUnit.value === TimeUnitType.HOUR) { + configForm.value.timeDuration = 6 + } + // 天, 默认 1天 + if (timeUnit.value === TimeUnitType.DAY) { + configForm.value.timeDuration = 1 + } + } + // 超时时间的 ISO 表示 + const isoTimeDuration = computed(() => { + if (!configForm.value.timeoutHandlerEnable) { + return undefined + } + let strTimeDuration = 'PT' + if (timeUnit.value === TimeUnitType.MINUTE) { + strTimeDuration += configForm.value.timeDuration + 'M' + } + if (timeUnit.value === TimeUnitType.HOUR) { + strTimeDuration += configForm.value.timeDuration + 'H' + } + if (timeUnit.value === TimeUnitType.DAY) { + strTimeDuration += configForm.value.timeDuration + 'D' + } + return strTimeDuration + }) -// 超时时间的 ISO 表示 -const isoTimeDuration = computed(() => { - if (!configForm.value.timeoutHandlerEnable) { - return undefined - } - let strTimeDuration = 'PT' - if (timeUnit.value === TimeUnitType.MINUTE) { - strTimeDuration += configForm.value.timeDuration + 'M' - } - if (timeUnit.value === TimeUnitType.HOUR) { - strTimeDuration += configForm.value.timeDuration + 'H' - } - if (timeUnit.value === TimeUnitType.DAY) { - strTimeDuration += configForm.value.timeDuration + 'D' - } - return strTimeDuration -}) -// 超时执行的动作 -const cTimeoutAction = computed(() => { - if (!configForm.value.timeoutHandlerEnable) { - return undefined - } - return configForm.value.timeoutHandlerAction -}) -// 超时最大提醒次数 -const cTimeoutMaxRemindCount = computed(() => { - if (!configForm.value.timeoutHandlerEnable) { - return undefined - } - if (configForm.value.timeoutHandlerAction !== 1) { - return undefined - } - return configForm.value.maxRemindCount -}) + // 超时最大提醒次数 + const cTimeoutMaxRemindCount = computed(() => { + if (!configForm.value.timeoutHandlerEnable) { + return undefined + } + if (configForm.value.timeoutHandlerAction !== 1) { + return undefined + } + return configForm.value.maxRemindCount + }) -// 超时开关改变 -const timeoutHandlerChange = () => { - if (configForm.value.timeoutHandlerEnable) { - timeUnit.value = 2 - configForm.value.timeDuration = 6 - configForm.value.timeoutHandlerAction = 1 - configForm.value.maxRemindCount = 1 + return { + timeoutHandlerChange, + cTimeoutAction, + timeoutActionChanged, + timeUnit, + timeUnitChange, + isoTimeDuration, + cTimeoutMaxRemindCount } } -// 超时处理动作改变 -const timeoutActionChanged = () => { - if (configForm.value.timeoutHandlerAction === 1) { - configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1 - } -} - -// 时间单位改变 -const timeUnitChange = () => { - // 分钟,默认是 60 分钟 - if (timeUnit.value === TimeUnitType.MINUTE) { - configForm.value.timeDuration = 60 - } - // 小时,默认是 6 个小时 - if (timeUnit.value === TimeUnitType.HOUR) { - configForm.value.timeDuration = 6 - } - // 天, 默认 1天 - if (timeUnit.value === TimeUnitType.DAY) { - configForm.value.timeDuration = 1 - } -} - -const convertTimeUnit = (strTimeUnit: string) => { - if (strTimeUnit === 'M') { - return TimeUnitType.MINUTE - } - if (strTimeUnit === 'H') { - return TimeUnitType.HOUR - } - if (strTimeUnit === 'D') { - return TimeUnitType.DAY - } - return TimeUnitType.HOUR -} - -// 操作按钮显示名称可编辑 -const btnDisplayNameEdit = ref([]) -const changeBtnDisplayName = (index: number) => { - btnDisplayNameEdit.value[index] = true -} -const btnDisplayNameBlurEvent = (index: number) => { - btnDisplayNameEdit.value[index] = false - const buttonItem = configForm.value.buttonPermission[index] - buttonItem.displayName = buttonItem.displayName || OPERATION_BUTTON_NAME.get(buttonItem.id) -} + From 2dae231afc74952a28cdf79171350b09fd3a91d0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Aug 2024 10:18:50 +0800 Subject: [PATCH 42/93] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E3=80=91=E5=AE=A1=E6=89=B9=E8=8A=82=E7=82=B9=E7=9A=84?= =?UTF-8?q?=E5=AE=A1=E6=89=B9=E4=BA=BA=E4=B8=8E=E5=8F=91=E8=B5=B7=E4=BA=BA?= =?UTF-8?q?=E7=9B=B8=E5=90=8C=E6=97=B6=EF=BC=8C=E5=AF=B9=E5=BA=94=E7=9A=84?= =?UTF-8?q?=E5=A4=84=E7=90=86=E7=B1=BB=E5=9E=8B=E7=9A=84=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/consts.ts | 22 +++++++++++++++++++ .../SimpleProcessDesignerV2/src/node.ts | 6 ++++- .../src/nodes-config/UserTaskNodeConfig.vue | 18 ++++++++++++++- 3 files changed, 44 insertions(+), 2 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 449e193e..9265d8b6 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -77,6 +77,8 @@ export interface SimpleFlowNode { timeoutHandler?: TimeoutHandler // 审批任务拒绝处理 rejectHandler?: RejectHandler + // 审批节点的审批人与发起人相同时,对应的处理类型 + assignStartUserHandlerType?: number } // 候选人策略枚举 ( 用于审批节点。抄送节点 ) export enum CandidateStrategy { @@ -174,6 +176,21 @@ export enum RejectHandlerType { */ RETURN_USER_TASK = 2 } +// 用户任务的审批人与发起人相同时,处理类型枚举 +export enum AssignStartUserHandlerType { + /** + * 由发起人对自己审批 + */ + START_USER_AUDIT = 1, + /** + * 自动跳过【参考飞书】:1)如果当前节点还有其他审批人,则交由其他审批人进行审批;2)如果当前节点没有其他审批人,则该节点自动通过 + */ + SKIP = 2, + /** + * 转交给部门负责人审批 + */ + ASSIGN_DEPT_LEADER +} // 时间单位枚举 export enum TimeUnitType { @@ -309,6 +326,11 @@ export const REJECT_HANDLER_TYPES: DictDataVO[] = [ { label: '驳回到指定节点', value: RejectHandlerType.RETURN_USER_TASK } // { label: '结束任务', value: RejectHandlerType.FINISH_TASK } ] +export const ASSIGN_START_USER_HANDLER_TYPES: DictDataVO[] = [ + { label: '由发起人对自己审批', value: 1 }, + { label: '自动跳过', value: 2 }, + { label: '转交给部门负责人审批', value: 3 } +] // 比较运算符 export const COMPARISON_OPERATORS: DictDataVO = [ diff --git a/src/components/SimpleProcessDesignerV2/src/node.ts b/src/components/SimpleProcessDesignerV2/src/node.ts index e41c9b83..abb3510e 100644 --- a/src/components/SimpleProcessDesignerV2/src/node.ts +++ b/src/components/SimpleProcessDesignerV2/src/node.ts @@ -10,7 +10,9 @@ import { NodeType, ApproveMethodType, RejectHandlerType, - NODE_DEFAULT_NAME + NODE_DEFAULT_NAME, + AssignStartUserHandlerType, + ASSIGN_START_USER_HANDLER_TYPES } from './consts' export function useWatchNode(props: { flowNode: SimpleFlowNode }): Ref { const node = ref(props.flowNode) @@ -97,6 +99,7 @@ export type UserTaskFormType = { returnNodeId?: string timeoutHandlerEnable?: boolean timeoutHandlerAction?: number + assignStartUserHandlerType?: AssignStartUserHandlerType timeDuration?: number maxRemindCount?: number buttonsSetting: any[] @@ -125,6 +128,7 @@ export function useNodeForm(nodeType: NodeType) { approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, approveRatio: 100, rejectHandlerType: RejectHandlerType.FINISH_PROCESS, + assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT, returnNodeId: '', timeoutHandlerEnable: false, timeoutHandlerAction: 1, diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 75af7ba7..77497e7f 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -275,6 +275,17 @@ > + + 审批人与提交人为同一人时 + + +
+
+ +
+
+
+
@@ -364,7 +375,8 @@ import { REJECT_HANDLER_TYPES, DEFAULT_BUTTON_SETTING, OPERATION_BUTTON_NAME, - ButtonSetting + ButtonSetting, + ASSIGN_START_USER_HANDLER_TYPES } from '../consts' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { @@ -506,6 +518,8 @@ const saveConfig = async () => { timeDuration: isoTimeDuration.value, maxRemindCount: cTimeoutMaxRemindCount.value } + // 设置用户任务的审批人与发起人相同时 + currentNode.value.assignStartUserHandlerType = configForm.value.assignStartUserHandlerType // 设置表单权限 currentNode.value.fieldsPermission = fieldsPermissionConfig.value // 设置按钮权限 @@ -560,6 +574,8 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { } configForm.value.timeoutHandlerAction = node.timeoutHandler?.action configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount + // 1.5 设置用户任务的审批人与发起人相同时 + configForm.value.assignStartUserHandlerType = node.assignStartUserHandlerType // 2. 操作按钮设置 buttonsSetting.value = cloneDeep(node.buttonsSetting) || DEFAULT_BUTTON_SETTING // 3. 表单字段权限配置 From 0ce9ececc614a0b5b1fd486f79d72ffa64ddc774 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Aug 2024 12:09:47 +0800 Subject: [PATCH 43/93] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E9=87=8D?= =?UTF-8?q?=E6=9E=84=E3=80=91=E5=B0=86=E5=AE=A1=E6=89=B9=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E7=9A=84=20action=20=E7=BB=9F=E4=B8=80=E6=8D=A2=E6=88=90=20han?= =?UTF-8?q?dlerType=EF=BC=8C=E4=BF=9D=E6=8C=81=E4=B8=80=E8=87=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/consts.ts | 19 ++++++++- .../SimpleProcessDesignerV2/src/node.ts | 4 +- .../src/nodes-config/UserTaskNodeConfig.vue | 41 ++++++++++--------- 3 files changed, 40 insertions(+), 24 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 9265d8b6..17ea37d2 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -159,7 +159,7 @@ export type TimeoutHandler = { //是否开启超时处理 enable: boolean // 超时执行的动作 - action?: number + type?: number // 超时时间设置 timeDuration?: string // 执行动作是自动提醒, 最大提醒次数 @@ -176,6 +176,21 @@ export enum RejectHandlerType { */ RETURN_USER_TASK = 2 } +// 用户任务超时处理类型枚举 +export enum TimeoutHandlerType { + /** + * 自动提醒 + */ + REMINDER = 1, + /** + * 自动同意 + */ + APPROVE = 2, + /** + * 自动拒绝 + */ + REJECT = 3 +} // 用户任务的审批人与发起人相同时,处理类型枚举 export enum AssignStartUserHandlerType { /** @@ -316,7 +331,7 @@ export const TIME_UNIT_TYPES: DictDataVO[] = [ { label: '天', value: TimeUnitType.DAY } ] // 超时处理执行动作类型 -export const TIMEOUT_HANDLER_ACTION_TYPES: DictDataVO[] = [ +export const TIMEOUT_HANDLER_TYPES: DictDataVO[] = [ { label: '自动提醒', value: 1 }, { label: '自动同意', value: 2 }, { label: '自动拒绝', value: 3 } diff --git a/src/components/SimpleProcessDesignerV2/src/node.ts b/src/components/SimpleProcessDesignerV2/src/node.ts index abb3510e..b4b3b37d 100644 --- a/src/components/SimpleProcessDesignerV2/src/node.ts +++ b/src/components/SimpleProcessDesignerV2/src/node.ts @@ -98,7 +98,7 @@ export type UserTaskFormType = { rejectHandlerType?: RejectHandlerType returnNodeId?: string timeoutHandlerEnable?: boolean - timeoutHandlerAction?: number + timeoutHandlerType?: number assignStartUserHandlerType?: AssignStartUserHandlerType timeDuration?: number maxRemindCount?: number @@ -131,7 +131,7 @@ export function useNodeForm(nodeType: NodeType) { assignStartUserHandlerType: AssignStartUserHandlerType.START_USER_AUDIT, returnNodeId: '', timeoutHandlerEnable: false, - timeoutHandlerAction: 1, + timeoutHandlerType: 1, timeDuration: 6, // 默认 6小时 maxRemindCount: 1, // 默认 提醒 1次 buttonsSetting: [] diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 77497e7f..b565fd37 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -227,15 +227,15 @@ @@ -370,13 +370,14 @@ import { ApproveMethodType, TimeUnitType, RejectHandlerType, - TIMEOUT_HANDLER_ACTION_TYPES, + TIMEOUT_HANDLER_TYPES, TIME_UNIT_TYPES, REJECT_HANDLER_TYPES, DEFAULT_BUTTON_SETTING, OPERATION_BUTTON_NAME, ButtonSetting, - ASSIGN_START_USER_HANDLER_TYPES + ASSIGN_START_USER_HANDLER_TYPES, + TimeoutHandlerType } from '../consts' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' import { @@ -426,7 +427,7 @@ const formRules = reactive({ approveRatio: [{ required: true, message: '通过比例不能为空', trigger: 'blur' }], returnNodeId: [{ required: true, message: '驳回节点不能为空', trigger: 'change' }], timeoutHandlerEnable: [{ required: true }], - timeoutHandlerAction: [{ required: true }], + timeoutHandlerType: [{ required: true }], timeDuration: [{ required: true, message: '超时时间不能为空', trigger: 'blur' }], maxRemindCount: [{ required: true, message: '提醒次数不能为空', trigger: 'blur' }] }) @@ -482,8 +483,8 @@ const returnTaskList = ref([]) // 审批人超时未处理设置 const { timeoutHandlerChange, - cTimeoutAction, - timeoutActionChanged, + cTimeoutType, + timeoutHandlerTypeChanged, timeUnit, timeUnitChange, isoTimeDuration, @@ -514,7 +515,7 @@ const saveConfig = async () => { // 设置超时处理 currentNode.value.timeoutHandler = { enable: configForm.value.timeoutHandlerEnable!, - action: cTimeoutAction.value, + type: cTimeoutType.value, timeDuration: isoTimeDuration.value, maxRemindCount: cTimeoutMaxRemindCount.value } @@ -572,7 +573,7 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => { configForm.value.timeDuration = parseInt(parseTime) timeUnit.value = convertTimeUnit(parseTimeUnit) } - configForm.value.timeoutHandlerAction = node.timeoutHandler?.action + configForm.value.timeoutHandlerType = node.timeoutHandler?.type configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount // 1.5 设置用户任务的审批人与发起人相同时 configForm.value.assignStartUserHandlerType = node.assignStartUserHandlerType @@ -619,21 +620,21 @@ function useTimeoutHandler() { if (configForm.value.timeoutHandlerEnable) { timeUnit.value = 2 configForm.value.timeDuration = 6 - configForm.value.timeoutHandlerAction = 1 + configForm.value.timeoutHandlerType = 1 configForm.value.maxRemindCount = 1 } } // 超时执行的动作 - const cTimeoutAction = computed(() => { + const cTimeoutType = computed(() => { if (!configForm.value.timeoutHandlerEnable) { return undefined } - return configForm.value.timeoutHandlerAction + return configForm.value.timeoutHandlerType }) // 超时处理动作改变 - const timeoutActionChanged = () => { - if (configForm.value.timeoutHandlerAction === 1) { + const timeoutHandlerTypeChanged = () => { + if (configForm.value.timeoutHandlerType === TimeoutHandlerType.REMINDER) { configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1 } } @@ -676,7 +677,7 @@ function useTimeoutHandler() { if (!configForm.value.timeoutHandlerEnable) { return undefined } - if (configForm.value.timeoutHandlerAction !== 1) { + if (configForm.value.timeoutHandlerType !== TimeoutHandlerType.REMINDER) { return undefined } return configForm.value.maxRemindCount @@ -684,8 +685,8 @@ function useTimeoutHandler() { return { timeoutHandlerChange, - cTimeoutAction, - timeoutActionChanged, + cTimeoutType, + timeoutHandlerTypeChanged, timeUnit, timeUnitChange, isoTimeDuration, From ab9ce936a36cffbb7bac92855e501eb76af4e624 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sat, 17 Aug 2024 12:19:13 +0800 Subject: [PATCH 44/93] =?UTF-8?q?=E4=BB=BF=E9=92=89=E9=92=89=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E8=AE=BE=E8=AE=A1=E5=99=A8-=20=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E7=AC=AC1=E7=89=88=EF=BC=8C=E6=96=B0=E5=A2=9E=E8=BF=9E?= =?UTF-8?q?=E7=BB=AD=E5=A4=9A=E7=BA=A7=E9=83=A8=E5=88=86=E8=B4=9F=E8=B4=A3?= =?UTF-8?q?=E4=BA=BA=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesigner/src/addNode.vue | 386 ----- .../SimpleProcessDesigner/src/consts.ts | 63 - .../src/drawer/approverDrawer.vue | 434 ------ .../src/drawer/copyerDrawer.vue | 250 --- .../SimpleProcessDesigner/src/nodeWrap.vue | 504 ------ .../SimpleProcessDesigner/src/util.ts | 218 --- .../SimpleProcessDesigner/theme/iconfont.ttf | Bin 2908 -> 0 bytes .../SimpleProcessDesigner/theme/iconfont.woff | Bin 1976 -> 0 bytes .../theme/iconfont.woff2 | Bin 1480 -> 0 bytes .../SimpleProcessDesigner/theme/workflow.css | 1366 ----------------- .../src/SimpleProcessDesigner.vue | 4 +- .../SimpleProcessDesignerV2/src/consts.ts | 48 +- .../SimpleProcessDesignerV2/src/node.ts | 159 +- .../src/nodes-config/CopyTaskNodeConfig.vue | 77 +- .../src/nodes-config/UserTaskNodeConfig.vue | 120 +- 15 files changed, 289 insertions(+), 3340 deletions(-) delete mode 100644 src/components/SimpleProcessDesigner/src/addNode.vue delete mode 100644 src/components/SimpleProcessDesigner/src/consts.ts delete mode 100644 src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue delete mode 100644 src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue delete mode 100644 src/components/SimpleProcessDesigner/src/nodeWrap.vue delete mode 100644 src/components/SimpleProcessDesigner/src/util.ts delete mode 100644 src/components/SimpleProcessDesigner/theme/iconfont.ttf delete mode 100644 src/components/SimpleProcessDesigner/theme/iconfont.woff delete mode 100644 src/components/SimpleProcessDesigner/theme/iconfont.woff2 delete mode 100644 src/components/SimpleProcessDesigner/theme/workflow.css diff --git a/src/components/SimpleProcessDesigner/src/addNode.vue b/src/components/SimpleProcessDesigner/src/addNode.vue deleted file mode 100644 index 1fe66ab5..00000000 --- a/src/components/SimpleProcessDesigner/src/addNode.vue +++ /dev/null @@ -1,386 +0,0 @@ -/* stylelint-disable order/properties-order */ - - - diff --git a/src/components/SimpleProcessDesigner/src/consts.ts b/src/components/SimpleProcessDesigner/src/consts.ts deleted file mode 100644 index 2d9b585e..00000000 --- a/src/components/SimpleProcessDesigner/src/consts.ts +++ /dev/null @@ -1,63 +0,0 @@ -export enum NodeType { - //// -1 根节点流程开始节点 0 发起人 1审批 2抄送 3条件 4路由 - ROOT_NODE = -1, - /** - * 发起人节点 - */ - START_USER_NODE = 0, - /** - * 审批人节点 - */ - APPROVE_USER_NODE = 1, - /** - * 抄送人节点 - */ - CC_USER_NODE = 2, - /** - * 条件节点 - */ - CONDITION_NODE = 3, - /** - * 条件分支节点 - */ - EXCLUSIVE_NODE = 4, - /** - * 并行分支分叉节点 - */ - PARALLEL_NODE_FORK = 5, - /** - * 并行分支聚合 - */ - PARALLEL_NODE_JOIN = 6, - /** - * 包容分支分叉节点 - */ - INCLUSIVE_NODE_FORK = 7, - /** - * 包容分支聚合节点 - */ - INCLUSIVE_NODE_JOIN = 8 -} - -export const NODE_BG_COLOR = new Map() -NODE_BG_COLOR.set(NodeType.START_USER_NODE, '#87, 106, 149') -NODE_BG_COLOR.set(NodeType.APPROVE_USER_NODE, '#255, 148, 62') -NODE_BG_COLOR.set(NodeType.CC_USER_NODE, '#50, 150, 250') - -/** - * 节点的标题 - */ -export const NODE_TITLE = new Map() -NODE_TITLE.set(NodeType.START_USER_NODE, '发起人') -NODE_TITLE.set(NodeType.APPROVE_USER_NODE, '审批人') -NODE_TITLE.set(NodeType.CC_USER_NODE, '抄送人') - -export type WorkFlowNode = { - id: string, - type: NodeType, - name: string, - attributes: any, - // 操作人 - childNode?: WorkFlowNode | undefined, - conditionNodes: WorkFlowNode[] -} \ No newline at end of file diff --git a/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue b/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue deleted file mode 100644 index d6ad5c2c..00000000 --- a/src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue +++ /dev/null @@ -1,434 +0,0 @@ - - - - diff --git a/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue b/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue deleted file mode 100644 index 70b1fc5b..00000000 --- a/src/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue +++ /dev/null @@ -1,250 +0,0 @@ - - - diff --git a/src/components/SimpleProcessDesigner/src/nodeWrap.vue b/src/components/SimpleProcessDesigner/src/nodeWrap.vue deleted file mode 100644 index 18cde05a..00000000 --- a/src/components/SimpleProcessDesigner/src/nodeWrap.vue +++ /dev/null @@ -1,504 +0,0 @@ - - - - - diff --git a/src/components/SimpleProcessDesigner/src/util.ts b/src/components/SimpleProcessDesigner/src/util.ts deleted file mode 100644 index 6b139366..00000000 --- a/src/components/SimpleProcessDesigner/src/util.ts +++ /dev/null @@ -1,218 +0,0 @@ -// @ts-ignore -import { DictDataVO } from '@/api/system/dict/types' -import { DICT_TYPE, getDictLabel } from '@/utils/dict' -/** - * todo - */ -export const arrToStr = (arr?: [{ name: string }]) => { - if (arr) { - return arr - .map((item) => { - return item.name - }) - .toString() - } -} - -export const setApproverStr = (nodeConfig: any) => { - if (nodeConfig.settype == 1) { - if (nodeConfig.nodeUserList.length == 1) { - return nodeConfig.nodeUserList[0].name - } else if (nodeConfig.nodeUserList.length > 1) { - if (nodeConfig.examineMode == 1) { - return arrToStr(nodeConfig.nodeUserList) - } else if (nodeConfig.examineMode == 2) { - return nodeConfig.nodeUserList.length + '人会签' - } - } - } else if (nodeConfig.settype == 2) { - const level = - nodeConfig.directorLevel == 1 ? '直接主管' : '第' + nodeConfig.directorLevel + '级主管' - if (nodeConfig.examineMode == 1) { - return level - } else if (nodeConfig.examineMode == 2) { - return level + '会签' - } - } else if (nodeConfig.settype == 4) { - if (nodeConfig.selectRange == 1) { - return '发起人自选' - } else { - if (nodeConfig.nodeUserList.length > 0) { - if (nodeConfig.selectRange == 2) { - return '发起人自选' - } else { - return '发起人从' + nodeConfig.nodeUserList[0].name + '中自选' - } - } else { - return '' - } - } - } else if (nodeConfig.settype == 5) { - return '发起人自己' - } else if (nodeConfig.settype == 7) { - return '从直接主管到通讯录中级别最高的第' + nodeConfig.examineEndDirectorLevel + '个层级主管' - } -} - - -export const approveMethods: DictDataVO [] = [ - { label: '单人审批', value: 1 } - // { label: '多人审批(所有人审批通过)', value: 2 } - // TODO 更多的类型 -]; - -export const getApproverShowText = (approveMethod :number, candidateStrategy: number) => { - let appoveMethodText = '单人审批' - if(candidateStrategy) { - approveMethods.forEach((item) => { - if (item.value == approveMethod) { - appoveMethodText = item.label - } - }) - const strategyText = getDictLabel( - DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY, - candidateStrategy - ) - return `审批方式:${appoveMethodText}
- 审批人规则类型:按${strategyText}` - } else { - return '' - } -} - -export const copyerStr = ( candidateStrategy: number) => { - // if (nodeConfig.nodeUserList.length != 0) { - // return arrToStr(nodeConfig.nodeUserList) - // } else { - // if (nodeConfig.ccSelfSelectFlag == 1) { - // return '发起人自选' - // } - // } - console.log('candidateStrategy', candidateStrategy); - - if(candidateStrategy) { - const strategyText = getDictLabel( - DICT_TYPE.BPM_TASK_CANDIDATE_STRATEGY, - candidateStrategy - ) - return `抄送人类型:按${strategyText}` - } else { - return '' - } -} -export const conditionStr = (nodeConfig, index) => { - // const { conditionList, nodeUserList } = nodeConfig.conditionNodes[index] - // if (conditionList.length == 0) { - // return index == nodeConfig.conditionNodes.length - 1 && - // nodeConfig.conditionNodes[0].conditionList.length != 0 - // ? '其他条件进入此流程' - // : '请设置条件' - // return index == nodeConfig.conditionNodes.length - 1 && - // nodeConfig.conditionNodes[0].conditionList.length != 0 - // ? '其他条件进入此流程' - // : '请设置条件' - // console.log('index===>', index); - // console.log('nodeConfig.conditionNodes.length===>', nodeConfig.conditionNodes.length); - if( index === nodeConfig.conditionNodes.length - 1) { - return '其它情况将进入该分支' - } else { - return '请设置条件' - } - - // } else { - // let str = '' - // for (let i = 0; i < conditionList.length; i++) { - // const { - // columnId, - // columnType, - // showType, - // showName, - // optType, - // zdy1, - // opt1, - // zdy2, - // opt2, - // fixedDownBoxValue - // } = conditionList[i] - // if (columnId == 0) { - // if (nodeUserList.length != 0) { - // str += '发起人属于:' - // str += - // nodeUserList - // .map((item) => { - // return item.name - // }) - // .join('或') + ' 并且 ' - // } - // } - // if (columnType == 'String' && showType == '3') { - // if (zdy1) { - // str += showName + '属于:' + dealStr(zdy1, JSON.parse(fixedDownBoxValue)) + ' 并且 ' - // } - // } - // if (columnType == 'Double') { - // if (optType != 6 && zdy1) { - // const optTypeStr = ['', '<', '>', '≤', '=', '≥'][optType] - // str += `${showName} ${optTypeStr} ${zdy1} 并且 ` - // } else if (optType == 6 && zdy1 && zdy2) { - // str += `${zdy1} ${opt1} ${showName} ${opt2} ${zdy2} 并且 ` - // } - // } - // } - // str ? str.substring(0, str.length - 4) : - return '请设置条件' - // } -} - -// export const dealStr = (str: string, obj) => { -// const arr = [] -// const list = str.split(',') -// for (const elem in obj) { -// list.map((item) => { -// if (item == elem) { -// arr.push(obj[elem].value) -// } -// }) -// } -// return arr.join('或') -// } - -export const removeEle = (arr, elem, key = 'id') => { - let includesIndex - arr.map((item, index) => { - if (item[key] == elem[key]) { - includesIndex = index - } - }) - arr.splice(includesIndex, 1) -} - -export const bgColors = ['87, 106, 149', '255, 148, 62', '50, 150, 250','50, 150, 250','248, 107, 248','244, 118, 118','23, 148, 46','23, 148, 46'] -export const placeholderList = ['发起人', '审核人', '抄送人'] -export const setTypes = [ - { value: 1, label: '指定成员' }, - { value: 2, label: '主管' }, - { value: 4, label: '发起人自选' }, - { value: 5, label: '发起人自己' }, - { value: 7, label: '连续多级主管' } -] - -export const selectModes = [ - { value: 1, label: '选一个人' }, - { value: 2, label: '选多个人' } -] - -export const selectRanges = [ - { value: 1, label: '全公司' }, - { value: 2, label: '指定成员' }, - { value: 3, label: '指定角色' } -] - -export const optTypes = [ - { value: '1', label: '小于' }, - { value: '2', label: '大于' }, - { value: '3', label: '小于等于' }, - { value: '4', label: '等于' }, - { value: '5', label: '大于等于' }, - { value: '6', label: '介于两个数之间' } -] diff --git a/src/components/SimpleProcessDesigner/theme/iconfont.ttf b/src/components/SimpleProcessDesigner/theme/iconfont.ttf deleted file mode 100644 index c2dcd3f422eda69e3cb3520c32c67528a6f82944..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2908 zcmd^B|8HAY6+h=)$4+eLy<~aMj!WXc_Z-`G+Swf!(gk>Cdq8Ul?16U5UxkoWGH0Rn&rs=#1i>cspJ^_lSF0C+F4a}S(I7^D7~pOF46 z>1VU6nbPPJ`M&`Ot;Ai=zX;%_@n8XH?yR~~g-0Bu(hMlD4sKVjIz#Li&i(T@XQa`8fv4g7UiwE}+^x~> zR2{%RM`|kwb};YB1&{Ggsc_a!KY$&sQsH(t48Rx&M<-|JK+I<<1=wZ#H|&kr2FCny zE<^p>8u@W65`*BhS%(Ag61328UlM*v+}9c{-T(tBQh*jl?8lS`7mqE#n_EKdMm-e+g_rqukk z8#|PpJ9YAG7NnTlKR!Q3Yj2_cD8I8p3z5=5Gk!=-Q2j+&a?>unAlEFuo(qa{JEn>>q3cybypGjL;Ceh;k5(F-*ph z>2XYsp%Fw`#5RoRE_BL%^clmLju6(P7)cT~h?51Fy*M*-@kL(ErcWo6r}MnR%hqH5 zL*3Tt?rwag`;Z^MqX;Y3rdRb?&w0IA^r&7ec!d}2ND8;2b|}T81HaYXZJnV&>tR0+ zJ~B?hJft4ywKm&Ad~NmHTcvf}1JEWY!~QPx<6s+hv2aUg7{7|IS@-|xx2Lw%ckuhx zD|qIO4ePJgudHk6#H_XV${hWVg+7v+&k3!f!o-v#b(c@50@qoL;8Nt2gE8jzsvd*$@;sb z?1=;dIPhR1ax4|>_U-9!uvKNZq6B@LKIwIGA3qp+D3Lrn-G^-QGlvHrjSNf?`?}J-4<(8ruyPK94*{M^if_NKnohObxiS1q`xc&8@;%)CAXgf4NA?=Mh zT&VOX+~X&Yi2GwGw=(P>aC6hX?UaKDXP=!_UPb`pP|joq*pj@j5lJ(l?E=4hjFBJg<|BXq#4HWui` z`mv1}@jth*gYfTc+yXwR+1N?^wvF9z65DO;fe2}G8}XH+VS>SDRLs!mdWW-Uxl2Dz-Z?lAd5SFGWxX@{ zBzc!%jr@3@DqYq%eJb7QHAP;9y62suLJO>+4)?e9`gK#=q%4uDDP@Mo&-+y%H|^`f8glWb^0O mme);3wpiM5E@cV}d9%&DV6(1FiL$?HNA^?f)NJP>_9F7$x_p~i4s9(fLa>J6To%K@>2La zYIs~Q07!vnp*H{kmOBrbObrPl2LgaJ7mPCkVYctjI=v831hsyUqd@GHor0!?L_{+| zZ64%`5?!(pPNzuX)81FN& z%1VNELVIgjG)0}@t7%ez{xNAsKysE$CUJ$rUZL5S36&&OR6KZTHr!4aAcK6$8(up{oB>1yY|&lKI1YI{xp zi2LL9@u|cuy_LMDa>RvSkzX!x28kbPr>CpC==#rChn?zfhasuq&ODof?2w`Q>-FS9ftB$Yo>~VM}Ho97$zzl-}c%`)GrFZK)G;KAZUs#D{y^&C)jDl`(;|K z{z>CIX!s%ijAqdih)e2dP)v%trTC1dx6xxtlTbZW2chL`z1YIDXymZGIFuv z$xo9?gW|$t`;&)`Ykr<)YUy!Ougl^leXsnyLYw>2VDsY0T{1ZqF z{=M7o$JXzg+bh@_gE1B#a318+W)!T?s1i6ci;Xfc{A-xjz%9bOLEI@+DM-(1SVw2E zyk~W{nHLPR)3t@p#v+vI~-t->@d0W+tWHdACHa4$zy*uI%Zp#*~00LT4G(b zk<)D`n5sSxofZYpvg+FeZh?0FWc6y3N!}y`jJ8y&>oy7l=<783oM>L*9k-lO?wQ*>!8Tx>mf*So(1hNy3tK{{XjPx((9`8pWD!(pxQz3p-%Y-w$@J}w> zAiGWbu?nh>dtB8=t;%s4rEXojv4y=ukm-8W?^f4DwrKbrDF%mNiXJTVI^8?(#~V#I zPE0~yMPUgw!RO1n;uY9eC|F!j=94uYmtadUPYhnLri#33nR#n}96UoyELgAEpV1i596Nj=6dGQFZeK1~ddzN}%?KgtS z1`{$Lzdhq-u7TCi!OxgmM%-7#FL!*+t6B^(YA)pgC*}&qRzxa(OM^=fZJSmc8eRXc zHNTg*t8qthHZ#6fV1U(=ZFuwqXHZ6%ohND{7I>03`R|zo%>H%zAGc<|M>Jy?0yImg zE6{3%ZzMty&?r?-UyBfilm?FMm&5!oK5~6psNB{HNLk;=f~eO(0S5&s26z{lL?X2$ zK_HWW7C7}J76{w`-a~vLFQxwYZ!Quw4V+~FL|^Bbu z_|-UlsyR=q2N2byrmi-9I6U5_C%AF2L0HDPxshFiPtd3?O)p{;Zd5X$MoiVn`;<<_ zqQs7>lvuLT!*%8A8JXf%&qZP@?)#Yrw(KT+l)oi+6unZNQVkLXh&LQsWc~_XL@(^;T|={7F0eXzKS|k+fNw4{a+3KVRR?*FK+eSSotZPq*=T zYn+AabwlEkM@;m=$iDn!(;VLcr-1vjN|uv<^OIjd4_*7Ge0<#_o@%0dKW7s%mQD9& zawEEJ8>CHUcCA919Qt1Rw>3X9r{(-3d{YP)-Ng4@r^|DH0(d0Nh~| zL;wI_fdw1@41{?2Z@>TTGc#BI$4r{3MOGJ2&?1EHl|{1m@CNl=E!~DzWmBt=_bHCr zRkeKE`;u#OziE!*6h;w;!{Qhe(Tr#K_tKX_=_MuaDk66klx$84V=#ijf7{nSq5uD0 z)y(4o$-ef`LbB$fIqXv~u?ds_t&Y9G>OBR|si^h=o?)Q6c^iR#OYIule0qHcOSdC7 zux>)o8`QaRyT~G#(GAKBCA8{Vx@!?HRHSF=HSj$D`S_(7GbB|O9A*F2lN5%XH2RgF zdN}!$v`4_@2^BIH9+@c~&pYnQrEFoY=pXx=#bIEuR#JD;@5Ij2u4;Eo_gAk+yD{hv zgTsID2wAOCB%+3jflNN0tm&i}5p*UZGM%T0n(in>MRyFM(EU{=fhOH$Fh+oQNc_jD zg}I|he5kAp8Z>n1;?$G@ljTfpVfO6SENyn{btFyW3`21o!LrFDej9@0D2Bmlx~OoI zG|OMd%?mat%c3n7%O57y3P%a`qA^OfU<5BJ$_GiptZHEqlwXwAoSQA4+k%i!Za|X6 z&8ILA$di|V1b!JtsjHAUEQViuRGCyXb=O!pGNY0&!s^w;V1Yuv7CCYgf`}~`hKNl$ zc>q%z0O0F#L!9Kvb&w&h!aT?qPxS#Fby>)OTNKDmsUimOb&-NqeDWa-FDC4=&`Dak zU?!L&oT0rgVK8<7xZKdHcnrK{$09i2Ee@JxS(h{PGaBH>%`Y<>Z<0Gy(k=M2ZOF3=dvYf*WWs&IpH{1SPExO)0>PQlN#)a7Qu|Do%S@bHfDh)bIB zvLN!6ORA$|YB_O9Q%+Z$6~Z(<{~UJAWU&Jz*OngMG!s0-O-cBCO|*qqOS1Nt;kv?1wP?U3iIB z{RQ_`WCY;mq;0UQyT3D%Xc^9CX|@6Z5kKP5rEO#HO1^av0-Oct4duUi0E{pBJ#S$A z$-_LpHl9D^7sww|_4`=n&c(kMkIUQt+WEgs-{;jYM^K=L7jjkmVQ>V$2IXlXW^scw zWvqQHAZO!jL$Ezrf7rpt-!t4dsYZwuesHQ0H6)D*khP}c3wb_N23QWY)*9%yz{%bN zjNpum(udhz0m4vkkPP+;vY|fkh5QAT(MC`k>L2Zj*9$H^nrX;U>F;s-c6s8A-{<&s&3X~mMFc|c&eU_l(Oi&Eh%AG)8wc@s0;9C3L|QHB*m4kOcPT~ zLQ>1NG<3S2ji@kTAveCLL=sHM*N8cr0>Y9~h1kDJKgeUyFL=8qQsgL6MIBAF`gWK^ ib*iFE6Nz<$sXQ{NqFL&X*rp?Q!RL2r#zj6-iWC5rIkjv6 diff --git a/src/components/SimpleProcessDesigner/theme/workflow.css b/src/components/SimpleProcessDesigner/theme/workflow.css deleted file mode 100644 index ac711bc2..00000000 --- a/src/components/SimpleProcessDesigner/theme/workflow.css +++ /dev/null @@ -1,1366 +0,0 @@ - -.clearfix { - zoom: 1 -} - -.clearfix:after, -.clearfix:before { - content: ""; - display: table -} - -.clearfix:after { - clear: both -} - -@font-face { - font-family: anticon; - font-display: fallback; - src: url("https://at.alicdn.com/t/font_148784_v4ggb6wrjmkotj4i.eot"); - src: url("https://at.alicdn.com/t/font_148784_v4ggb6wrjmkotj4i.woff") format("woff"), url("https://at.alicdn.com/t/font_148784_v4ggb6wrjmkotj4i.ttf") format("truetype"), url("https://at.alicdn.com/t/font_148784_v4ggb6wrjmkotj4i.svg#iconfont") format("svg") -} - -.anticon { - display: inline-block; - font-style: normal; - vertical-align: baseline; - text-align: center; - text-transform: none; - line-height: 1; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale -} - -.anticon:before { - display: block; - font-family: anticon!important -} -.anticon-close:before { - content: "\E633" -} -.anticon-right:before { - content: "\E61F" -} -.anticon-exclamation-circle{ - color: rgb(242, 86, 67) -} -.anticon-exclamation-circle:before { - content: "\E62C" -} - -.anticon-left:before { - content: "\E620" -} - -.anticon-close-circle:before { - content: "\E62E" -} - -.ant-btn { - line-height: 1.5; - display: inline-block; - font-weight: 400; - text-align: center; - touch-action: manipulation; - cursor: pointer; - background-image: none; - border: 1px solid transparent; - white-space: nowrap; - padding: 0 15px; - font-size: 14px; - border-radius: 4px; - height: 32px; - user-select: none; - transition: all .3s cubic-bezier(.645, .045, .355, 1); - position: relative; - color: rgba(0, 0, 0, .65); - background-color: #fff; - border-color: #d9d9d9 -} - -.ant-btn>.anticon { - line-height: 1 -} - -.ant-btn, -.ant-btn:active, -.ant-btn:focus { - outline: 0 -} - -.ant-btn>a:only-child { - color: currentColor -} - -.ant-btn>a:only-child:after { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: transparent -} - -.ant-btn:focus, -.ant-btn:hover { - color: #40a9ff; - background-color: #fff; - border-color: #40a9ff -} - -.ant-btn:focus>a:only-child, -.ant-btn:hover>a:only-child { - color: currentColor -} - -.ant-btn:focus>a:only-child:after, -.ant-btn:hover>a:only-child:after { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: transparent -} - -.ant-btn.active, -.ant-btn:active { - color: #096dd9; - background-color: #fff; - border-color: #096dd9 -} - -.ant-btn.active>a:only-child, -.ant-btn:active>a:only-child { - color: currentColor -} - -.ant-btn.active>a:only-child:after, -.ant-btn:active>a:only-child:after { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 0; - background: transparent -} - -.ant-btn.active, -.ant-btn:active, -.ant-btn:focus, -.ant-btn:hover { - background: #fff; - text-decoration: none -} - -.ant-btn>i, -.ant-btn>span { - pointer-events: none -} - -.ant-btn:before { - position: absolute; - top: -1px; - left: -1px; - bottom: -1px; - right: -1px; - background: #fff; - opacity: .35; - content: ""; - border-radius: inherit; - z-index: 1; - transition: opacity .2s; - pointer-events: none; - display: none -} - -.ant-btn .anticon { - transition: margin-left .3s cubic-bezier(.645, .045, .355, 1) -} - -.ant-btn:active>span, -.ant-btn:focus>span { - position: relative -} - -.ant-btn>.anticon+span, -.ant-btn>span+.anticon { - margin-left: 8px -} - -.ant-input { - font-family: Chinese Quote, -apple-system, BlinkMacSystemFont, Segoe UI, PingFang SC, Hiragino Sans GB, Microsoft YaHei, Helvetica Neue, Helvetica, Arial, sans-serif; - font-variant: tabular-nums; - box-sizing: border-box; - margin: 0; - padding: 0; - list-style: none; - position: relative; - display: inline-block; - padding: 4px 11px; - width: 100%; - height: 32px; - font-size: 14px; - line-height: 1.5; - color: rgba(0, 0, 0, .65); - background-color: #fff; - background-image: none; - border: 1px solid #d9d9d9; - border-radius: 4px; - transition: all .3s -} - -.ant-input::-moz-placeholder { - color: #bfbfbf; - opacity: 1 -} - -.ant-input:-ms-input-placeholder { - color: #bfbfbf -} - -.ant-input::-webkit-input-placeholder { - color: #bfbfbf -} - -.ant-input:focus, -.ant-input:hover { - border-color: #40a9ff; - border-right-width: 1px!important -} - -.ant-input:focus { - outline: 0; - box-shadow: 0 0 0 2px rgba(24, 144, 255, .2) -} - -textarea.ant-input { - max-width: 100%; - height: auto; - vertical-align: bottom; - transition: all .3s, height 0s; - min-height: 32px -} - -a, -abbr, -acronym, -address, -applet, -article, -aside, -audio, -b, -big, -blockquote, -body, -canvas, -caption, -center, -cite, -code, -dd, -del, -details, -dfn, -div, -dl, -dt, -em, -fieldset, -figcaption, -figure, -footer, -form, -h1, -h2, -h3, -h4, -h5, -h6, -header, -hgroup, -html, -i, -iframe, -img, -ins, -kbd, -label, -legend, -li, -mark, -menu, -nav, -object, -ol, -p, -pre, -q, -s, -samp, -section, -small, -span, -strike, -strong, -sub, -summary, -sup, -table, -tbody, -td, -tfoot, -th, -thead, -time, -tr, -tt, -u, -ul, -var, -video { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-size: 100%; - font: inherit; - vertical-align: baseline -} - -*, -:after, -:before { - -webkit-box-sizing: border-box; - -moz-box-sizing: border-box; - box-sizing: border-box -} - -html { - font-family: sans-serif; - -ms-text-size-adjust: 100%; - -webkit-text-size-adjust: 100% -} - -body, -html { - font-size: 14px -} - -body { - font-family: Microsoft Yahei, Lucida Grande, Lucida Sans Unicode, Helvetica, Arial, Verdana, sans-serif; - line-height: 1.6; - background-color: #fff; - position: static!important; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0) -} - -ol, -ul { - list-style-type: none -} - -b, -strong { - font-weight: 700 -} - -img { - border: 0 -} - -button, -input, -select, -textarea { - font-family: inherit; - font-size: 100%; - margin: 0 -} - -textarea { - overflow: auto; - vertical-align: top; - -webkit-appearance: none -} - -button, -input { - line-height: normal -} - -button, -select { - text-transform: none -} - -button, -html input[type=button], -input[type=reset], -input[type=submit] { - -webkit-appearance: button; - cursor: pointer -} - -input[type=search] { - -webkit-appearance: textfield; - -moz-box-sizing: content-box; - -webkit-box-sizing: content-box; - box-sizing: content-box -} - -input[type=search]::-webkit-search-cancel-button, -input[type=search]::-webkit-search-decoration { - -webkit-appearance: none -} - -button::-moz-focus-inner, -input::-moz-focus-inner { - border: 0; - padding: 0 -} - -table { - width: 100%; - border-spacing: 0; - border-collapse: collapse -} - -table, -td, -th { - border: 0 -} - -td, -th { - padding: 0; - vertical-align: top -} - -th { - font-weight: 700; - text-align: left -} - -thead th { - white-space: nowrap -} - -a { - text-decoration: none; - cursor: pointer; - color: #3296fa -} - -a:active, -a:hover { - outline: 0; - color: #3296fa -} - -small { - font-size: 80% -} - -body, -html { - font-size: 12px!important; - color: #191f25!important; - background: #f6f6f6!important -} - -.wrap { - display: -webkit-box; - display: -ms-flexbox; - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - height: 100% -} - -/* @font-face { - font-family: IconFont; - src: url("//at.alicdn.com/t/font_135284_ph2thxxbzgf.eot"); - src: url("//at.alicdn.com/t/font_135284_ph2thxxbzgf.eot?#iefix") format("embedded-opentype"), url("//at.alicdn.com/t/font_135284_ph2thxxbzgf.woff") format("woff"), url("//at.alicdn.com/t/font_135284_ph2thxxbzgf.ttf") format("truetype"), url("//at.alicdn.com/t/font_135284_ph2thxxbzgf.svg#IconFont") format("svg") -} - -.iconfont { - font-family: IconFont!important; - font-size: 16px; - font-style: normal; - -webkit-font-smoothing: antialiased; - -webkit-text-stroke-width: .2px; - -moz-osx-font-smoothing: grayscale -} */ - -@font-face { - font-family: "iconfont"; /* Project id 4495938 */ - src: url('iconfont.woff2?t=1712392083512') format('woff2'), - url('iconfont.woff?t=1712392083512') format('woff'), - url('iconfont.ttf?t=1712392083512') format('truetype'); -} - -.iconfont { - font-family: "iconfont" !important; - font-size: 16px; - font-style: normal; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -.icon-Inclusive:before { - content: "\e602"; -} - -.icon-copy:before { - content: "\e7eb"; -} - -.icon-handle:before { - content: "\e61c"; -} - -.icon-exclusive:before { - content: "\e717"; -} - -.icon-approve:before { - content: "\e715"; -} - -.icon-parallel:before { - content: "\e688"; -} - -.fd-nav { - position: fixed; - top: 0; - left: 0; - right: 0; - z-index: 997; - width: 100%; - height: 60px; - font-size: 14px; - color: #fff; - background: #3296fa; - display: flex; - align-items: center -} - -.fd-nav>* { - flex: 1; - width: 100% -} - -.fd-nav .fd-nav-left { - display: -webkit-box; - display: flex; - align-items: center -} - -.fd-nav .fd-nav-center { - flex: none; - width: 600px; - text-align: center -} - -.fd-nav .fd-nav-right { - display: flex; - align-items: center; - justify-content: flex-end; - text-align: right -} - -.fd-nav .fd-nav-back { - display: inline-block; - width: 60px; - height: 60px; - font-size: 22px; - border-right: 1px solid #1583f2; - text-align: center; - cursor: pointer -} - -.fd-nav .fd-nav-back:hover { - background: #5af -} - -.fd-nav .fd-nav-back:active { - background: #1583f2 -} - -.fd-nav .fd-nav-back .anticon { - line-height: 60px -} - -.fd-nav .fd-nav-title { - width: 0; - flex: 1; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - padding: 0 15px -} - -.fd-nav a { - color: #fff; - margin-left: 12px -} - -.fd-nav .button-publish { - min-width: 80px; - margin-left: 4px; - margin-right: 15px; - color: #3296fa; - border-color: #fff -} - -.fd-nav .button-publish.ant-btn:focus, -.fd-nav .button-publish.ant-btn:hover { - color: #3296fa; - border-color: #fff; - box-shadow: 0 10px 20px 0 rgba(0, 0, 0, .3) -} - -.fd-nav .button-publish.ant-btn:active { - color: #3296fa; - background: #d6eaff; - box-shadow: none -} - -.fd-nav .button-preview { - min-width: 80px; - margin-left: 16px; - margin-right: 4px; - color: #fff; - border-color: #fff; - background: transparent -} - -.fd-nav .button-preview.ant-btn:focus, -.fd-nav .button-preview.ant-btn:hover { - color: #fff; - border-color: #fff; - background: #59acfc -} - -.fd-nav .button-preview.ant-btn:active { - color: #fff; - border-color: #fff; - background: #2186ef -} - -.fd-nav-content { - position: fixed; - top: 60px; - left: 0; - right: 0; - bottom: 0; - z-index: 1; - overflow-x: hidden; - overflow-y: auto; - padding-bottom: 30px -} - -.error-modal-desc { - font-size: 13px; - color: rgba(25, 31, 37, .56); - line-height: 22px; - margin-bottom: 14px -} - -.error-modal-list { - height: 200px; - overflow-y: auto; - margin-right: -25px; - padding-right: 25px -} - -.error-modal-item { - padding: 10px 20px; - line-height: 21px; - background: #f6f6f6; - display: flex; - justify-content: space-between; - align-items: center; - margin-bottom: 8px; - border-radius: 4px -} - -.error-modal-item-label { - flex: none; - font-size: 15px; - color: rgba(25, 31, 37, .56); - padding-right: 10px -} - -.error-modal-item-content { - text-align: right; - flex: 1; - font-size: 13px; - color: #191f25 -} - -#body.blur { - -webkit-filter: blur(3px); - filter: blur(3px) -} - -.zoom { - display: flex; - position: fixed; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -webkit-box-pack: justify; - -ms-flex-pack: justify; - justify-content: space-between; - height: 40px; - width: 125px; - right: 40px; - margin-top: 30px; - z-index: 10 -} - -.zoom .zoom-in, -.zoom .zoom-out { - width: 30px; - height: 30px; - background: #fff; - color: #c1c1cd; - cursor: pointer; - background-size: 100%; - background-repeat: no-repeat -} - -.zoom .zoom-out { - background-image: url(https://gw.alicdn.com/tfs/TB1s0qhBHGYBuNjy0FoXXciBFXa-90-90.png) -} - -.zoom .zoom-out.disabled { - opacity: .5 -} - -.zoom .zoom-in { - background-image: url(https://gw.alicdn.com/tfs/TB1UIgJBTtYBeNjy1XdXXXXyVXa-90-90.png) -} - -.zoom .zoom-in.disabled { - opacity: .5 -} - -.auto-judge:hover .editable-title, -.node-wrap-box:hover .editable-title { - border-bottom: 1px dashed #fff -} - -.auto-judge:hover .editable-title.editing, -.node-wrap-box:hover .editable-title.editing { - text-decoration: none; - border: 1px solid #d9d9d9 -} - -.auto-judge:hover .editable-title { - border-color: #15bc83 -} - -.editable-title { - line-height: 15px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; - border-bottom: 1px dashed transparent -} - -.editable-title:before { - content: ""; - position: absolute; - top: 0; - left: 0; - bottom: 0; - right: 40px -} - -.editable-title:hover { - border-bottom: 1px dashed #fff -} - -.editable-title-input { - flex: none; - height: 18px; - padding-left: 4px; - text-indent: 0; - font-size: 12px; - line-height: 18px; - z-index: 1 -} - -.editable-title-input:hover { - text-decoration: none -} - -.ant-btn { - position: relative -} - -.node-wrap-box { - display: -webkit-inline-box; - display: -ms-inline-flexbox; - display: inline-flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - position: relative; - width: 220px; - min-height: 72px; - -ms-flex-negative: 0; - flex-shrink: 0; - background: #fff; - border-radius: 4px; - cursor: pointer -} - -.node-wrap-box:after { - pointer-events: none; - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 2; - border-radius: 4px; - border: 1px solid transparent; - transition: all .1s cubic-bezier(.645, .045, .355, 1); - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) -} - -.node-wrap-box.active:after, -.node-wrap-box:active:after, -.node-wrap-box:hover:after { - border: 1px solid #3296fa; - box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) -} - -.node-wrap-box.active .close, -.node-wrap-box:active .close, -.node-wrap-box:hover .close { - display: block -} - -.node-wrap-box.error:after { - border: 1px solid #f25643; - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) -} - -.node-wrap-box .title { - position: relative; - display: flex; - align-items: center; - padding-left: 16px; - padding-right: 30px; - width: 100%; - height: 24px; - line-height: 24px; - font-size: 12px; - color: #fff; - text-align: left; - background: #576a95; - border-radius: 4px 4px 0 0 -} - -.node-wrap-box .title .iconfont { - font-size: 12px; - margin-right: 5px -} - -.node-wrap-box .placeholder { - color: #bfbfbf -} - -.node-wrap-box .close { - display: none; - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - width: 20px; - height: 20px; - font-size: 14px; - color: #fff; - border-radius: 50%; - text-align: center; - line-height: 20px -} - -.node-wrap-box .content { - position: relative; - font-size: 14px; - padding: 16px; - padding-right: 30px -} - -.node-wrap-box .content .text { - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical -} - -.node-wrap-box .content .arrow { - position: absolute; - right: 10px; - top: 50%; - transform: translateY(-50%); - width: 20px; - height: 14px; - font-size: 14px; - color: #979797 -} - -.start-node.node-wrap-box .content .text { - display: block; - white-space: nowrap -} - -.node-wrap-box:before { - content: ""; - position: absolute; - top: -12px; - left: 50%; - -webkit-transform: translateX(-50%); - transform: translateX(-50%); - width: 0; - height: 4px; - border-style: solid; - border-width: 8px 6px 4px; - border-color: #cacaca transparent transparent; - background: #f5f5f7 -} - -.node-wrap-box.start-node:before { - content: none -} - -.top-left-cover-line { - left: -1px -} - -.top-left-cover-line, -.top-right-cover-line { - position: absolute; - height: 8px; - width: 50%; - background-color: #f5f5f7; - top: -4px -} - -.top-right-cover-line { - right: -1px -} - -.bottom-left-cover-line { - left: -1px -} - -.bottom-left-cover-line, -.bottom-right-cover-line { - position: absolute; - height: 8px; - width: 50%; - background-color: #f5f5f7; - bottom: -4px -} - -.bottom-right-cover-line { - right: -1px -} - -.dingflow-design { - width: 100%; - background-color: #f5f5f7; - overflow: auto; - position: absolute; - bottom: 0; - left: 0; - right: 0; - top: 0 -} - -.dingflow-design .box-scale { - transform: scale(1); - display: inline-block; - position: relative; - width: 100%; - padding: 54.5px 0; - -webkit-box-align: start; - -ms-flex-align: start; - align-items: flex-start; - -webkit-box-pack: center; - -ms-flex-pack: center; - justify-content: center; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - min-width: -webkit-min-content; - min-width: -moz-min-content; - min-width: min-content; - background-color: #f5f5f7; - transform-origin: 50% 0px 0px; -} - -.dingflow-design .node-wrap { - flex-direction: column; - -webkit-box-pack: start; - -ms-flex-pack: start; - justify-content: flex-start; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-flex: 1; - -ms-flex-positive: 1; - padding: 0 50px; - position: relative -} - -.dingflow-design .branch-wrap, -.dingflow-design .node-wrap { - display: inline-flex; - width: 100% -} - -.dingflow-design .branch-box-wrap { - display: flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - -ms-flex-direction: column; - flex-direction: column; - -ms-flex-wrap: wrap; - flex-wrap: wrap; - -webkit-box-align: center; - -ms-flex-align: center; - align-items: center; - min-height: 270px; - width: 100%; - -ms-flex-negative: 0; - flex-shrink: 0 -} - -.dingflow-design .branch-box { - display: flex; - overflow: visible; - min-height: 180px; - height: auto; - border-bottom: 2px solid #ccc; - border-top: 2px solid #ccc; - position: relative; - margin-top: 15px -} - -.dingflow-design .branch-box .col-box { - background: #f5f5f7 -} - -.dingflow-design .branch-box .col-box:before { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - z-index: 0; - margin: auto; - width: 2px; - height: 100%; - background-color: #cacaca -} - -.dingflow-design .add-branch { - border: none; - outline: none; - user-select: none; - justify-content: center; - font-size: 12px; - padding: 0 10px; - height: 30px; - line-height: 30px; - border-radius: 15px; - color: #3296fa; - background: #fff; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, .1); - position: absolute; - top: -16px; - left: 50%; - transform: translateX(-50%); - transform-origin: center center; - cursor: pointer; - z-index: 1; - display: inline-flex; - align-items: center; - -webkit-transition: all .3s cubic-bezier(.645, .045, .355, 1); - transition: all .3s cubic-bezier(.645, .045, .355, 1) -} - -.dingflow-design .add-branch:hover { - transform: translateX(-50%) scale(1.1); - box-shadow: 0 8px 16px 0 rgba(0, 0, 0, .1) -} - -.dingflow-design .add-branch:active { - transform: translateX(-50%); - box-shadow: none -} - -.dingflow-design .col-box { - display: inline-flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - -webkit-box-align: center; - align-items: center; - position: relative -} - -.dingflow-design .condition-node { - min-height: 220px -} - -.dingflow-design .condition-node, -.dingflow-design .condition-node-box { - display: inline-flex; - -webkit-box-orient: vertical; - -webkit-box-direction: normal; - flex-direction: column; - -webkit-box-flex: 1 -} - -.dingflow-design .condition-node-box { - padding-top: 30px; - padding-right: 50px; - padding-left: 50px; - -webkit-box-pack: center; - justify-content: center; - -webkit-box-align: center; - align-items: center; - flex-grow: 1; - position: relative -} - -.dingflow-design .condition-node-box:before { - content: ""; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - margin: auto; - width: 2px; - height: 100%; - background-color: #cacaca -} - -.dingflow-design .auto-judge { - position: relative; - width: 220px; - min-height: 72px; - background: #fff; - border-radius: 4px; - padding: 14px 19px; - cursor: pointer -} - -.dingflow-design .auto-judge:after { - pointer-events: none; - content: ""; - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - z-index: 2; - border-radius: 4px; - border: 1px solid transparent; - transition: all .1s cubic-bezier(.645, .045, .355, 1); - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) -} - -.dingflow-design .auto-judge.active:after, -.dingflow-design .auto-judge:active:after, -.dingflow-design .auto-judge:hover:after { - border: 1px solid #3296fa; - box-shadow: 0 0 6px 0 rgba(50, 150, 250, .3) -} - - - -.dingflow-design .auto-judge.error:after { - border: 1px solid #f25643; - box-shadow: 0 2px 5px 0 rgba(0, 0, 0, .1) -} - -/* .dingflow-design .auto-judge .title-wrapper { - position: relative; - font-size: 12px; - color: #15bc83; - text-align: left; - height: 24px; - line-height: 24px; - width: 258px; -} */ - -.dingflow-design .title-wrapper { - display: flex; - justify-content: space-between; - align-items: center; - position: relative; - font-size: 12px; - border-radius: 4px 4px 0 0; - text-align: left; - height: 24px; - line-height: 24px; - width: 220px; - color: #fff; - padding-right: 10px; - padding-left: 10px; -} - -.dingflow-design .title-wrapper .editable-title { - max-width: 120px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis -} - -.dingflow-design .title-wrapper .close { - display: none; - position: absolute; - right: 10px; - top: 2px; - width: 20px; - height: 20px; - font-size: 14px; - color:#fff; - border-radius: 50%; - text-align: center; - line-height: 20px; - z-index: 2 -} - -.dingflow-design .title-wrapper:hover .close { - display: block -} -/* .dingflow-design .title-wrapper .close { - padding-right: 2px; -} */ - -/* .dingflow-design .title-wrapper .priority-title { - display: inline-block; - float: right; - margin-right: 10px; - color: rgba(25, 31, 37, .56) -} */ - -/* .dingflow-design .auto-judge .title-wrapper .editable-title { - display: inline-block; - max-width: 120px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis -} - -.dingflow-design .auto-judge .title-wrapper .priority-title { - display: inline-block; - float: right; - margin-right: 10px; - color: rgba(25, 31, 37, .56) -} */ - -.dingflow-design .auto-judge .placeholder { - color: #bfbfbf -} - -.dingflow-design .auto-judge .content { - font-size: 14px; - color: #191f25; - text-align: left; - margin-top: 6px; - overflow: hidden; - text-overflow: ellipsis; - display: -webkit-box; - -webkit-line-clamp: 3; - -webkit-box-orient: vertical -} - -.dingflow-design .auto-judge .sort-left, -.dingflow-design .auto-judge .sort-right { - position: absolute; - top: 0; - bottom: 0; - display: none; - z-index: 1 -} - -.dingflow-design .auto-judge .sort-left { - left: 0; - border-right: 1px solid #f6f6f6 -} - -.dingflow-design .auto-judge .sort-right { - right: 0; - border-left: 1px solid #f6f6f6 -} - -.dingflow-design .auto-judge:hover .sort-left, -.dingflow-design .auto-judge:hover .sort-right { - display: flex; - align-items: center -} - -.dingflow-design .auto-judge .sort-left:hover, -.dingflow-design .auto-judge .sort-right:hover { - background: #efefef -} - -.dingflow-design .end-node { - border-radius: 50%; - font-size: 14px; - color: rgba(25, 31, 37, .4); - text-align: left -} - -.dingflow-design .end-node .end-node-circle { - width: 10px; - height: 10px; - margin: auto; - border-radius: 50%; - background: #dbdcdc -} - -.dingflow-design .end-node .end-node-text { - margin-top: 5px; - text-align: center -} - -.approval-setting { - border-radius: 2px; - margin: 20px 0; - position: relative; - background: #fff -} - -.ant-btn { - position: relative -} - - diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index d112cf5b..a913fdf0 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -146,9 +146,9 @@ onMounted(async () => { processNodeTree.value = { name: '开始', type: NodeType.START_EVENT_NODE, - id: 'StartEvent_1', // TODO @jason:这个我们要不要 StartEvent 哈? + id: 'StartEvent', childNode: { - id: 'EndEvent_1', + id: 'EndEvent', name: '结束', type: NodeType.END_EVENT_NODE } diff --git a/src/components/SimpleProcessDesignerV2/src/consts.ts b/src/components/SimpleProcessDesignerV2/src/consts.ts index 449e193e..6411237d 100644 --- a/src/components/SimpleProcessDesignerV2/src/consts.ts +++ b/src/components/SimpleProcessDesignerV2/src/consts.ts @@ -1,5 +1,6 @@ // @ts-ignore import { DictDataVO } from '@/api/system/dict/types' + /** * 节点类型 */ @@ -85,13 +86,17 @@ export enum CandidateStrategy { */ ROLE = 10, /** - * 指定部门成员 + * 部门成员 */ DEPT_MEMBER = 20, /** * 部门的负责人 */ DEPT_LEADER = 21, + /** + * 连续多级部门的负责人 + */ + MULTI_LEVEL_DEPT_LEADER = 23, /** * 指定岗位 */ @@ -108,6 +113,14 @@ export enum CandidateStrategy { * 发起人自己 */ START_USER = 36, + /** + * 发起人部门负责人 + */ + START_USER_DEPT_LEADER = 37, + /** + * 发起人连续多级部门的负责人 + */ + START_USER_MULTI_LEVEL_DEPT_LEADER = 38, /** * 指定用户组 */ @@ -280,6 +293,21 @@ NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人') NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人') NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件') +// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序 +export const CANDIDATE_STRATEGY: DictDataVO[] = [ + { label: '指定成员', value: CandidateStrategy.USER }, + { label: '指定角色', value: CandidateStrategy.ROLE }, + { label: '部门成员', value: CandidateStrategy.DEPT_MEMBER }, + { label: '部门负责人', value: CandidateStrategy.DEPT_LEADER }, + { label: '连续多级部门负责人', value: CandidateStrategy.MULTI_LEVEL_DEPT_LEADER }, + { label: '发起人自选', value: CandidateStrategy.START_USER_SELECT }, + { label: '发起人本人', value: CandidateStrategy.START_USER }, + { label: '发起人部门负责人', value: CandidateStrategy.START_USER_DEPT_LEADER }, + { label: '发起人连续部门负责人', value: CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER }, + { label: '用户组', value: CandidateStrategy.USER_GROUP }, + { label: '流程表达式', value: CandidateStrategy.EXPRESSION } +] + export const APPROVE_METHODS: DictDataVO[] = [ { label: '随机挑选一人审批', value: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE }, { label: '多人会签(按通过比例%)', value: ApproveMethodType.APPROVE_BY_RATIO }, @@ -355,3 +383,21 @@ export const DEFAULT_BUTTON_SETTING: ButtonSetting[] = [ { id: OpsButtonType.ADD_SIGN, displayName: '加签', enable: false }, { id: OpsButtonType.RETURN, displayName: '回退', enable: false } ] + +export const MULTI_LEVEL_DEPT: DictDataVO = [ + { label: '第1级部门', value: 1 }, + { label: '第2级部门', value: 2 }, + { label: '第3级部门', value: 3 }, + { label: '第4级部门', value: 4 }, + { label: '第5级部门', value: 5 }, + { label: '第6级部门', value: 6 }, + { label: '第7级部门', value: 7 }, + { label: '第8级部门', value: 8 }, + { label: '第9级部门', value: 9 }, + { label: '第10级部门', value: 10 }, + { label: '第11级部门', value: 11 }, + { label: '第12级部门', value: 12 }, + { label: '第13级部门', value: 13 }, + { label: '第14级部门', value: 14 }, + { label: '第15级部门', value: 15 } +] diff --git a/src/components/SimpleProcessDesignerV2/src/node.ts b/src/components/SimpleProcessDesignerV2/src/node.ts index e41c9b83..e9831d81 100644 --- a/src/components/SimpleProcessDesignerV2/src/node.ts +++ b/src/components/SimpleProcessDesignerV2/src/node.ts @@ -89,9 +89,16 @@ export function useFormFieldsPermission() { } export type UserTaskFormType = { - candidateParamArray: any[] + //candidateParamArray: any[] candidateStrategy: CandidateStrategy approveMethod: ApproveMethodType + roleIds?: number[] // 角色 + deptIds?: number[] // 部门 + deptLevel?: number // 部门层级 + userIds?: number[] // 用户 + userGroups?: number[] // 用户组 + postIds?: number[] // 岗位 + expression?: string // 流程表达式 approveRatio?: number rejectHandlerType?: RejectHandlerType returnNodeId?: string @@ -103,8 +110,15 @@ export type UserTaskFormType = { } export type CopyTaskFormType = { - candidateParamArray: any[] + // candidateParamArray: any[] candidateStrategy: CandidateStrategy + roleIds?: number[] // 角色 + deptIds?: number[] // 部门 + deptLevel?: number // 部门层级 + userIds?: number[] // 用户 + userGroups?: number[] // 用户组 + postIds?: number[] // 岗位 + expression?: string // 流程表达式 } /** @@ -120,7 +134,7 @@ export function useNodeForm(nodeType: NodeType) { const configForm = ref() if (nodeType === NodeType.USER_TASK_NODE) { configForm.value = { - candidateParamArray: [], + //candidateParamArray: [], candidateStrategy: CandidateStrategy.USER, approveMethod: ApproveMethodType.RRANDOM_SELECT_ONE_APPROVE, approveRatio: 100, @@ -134,7 +148,7 @@ export function useNodeForm(nodeType: NodeType) { } } else { configForm.value = { - candidateParamArray: [], + //candidateParamArray: [], candidateStrategy: CandidateStrategy.USER } } @@ -143,10 +157,10 @@ export function useNodeForm(nodeType: NodeType) { let showText = '' // 指定成员 if (configForm.value?.candidateStrategy === CandidateStrategy.USER) { - if (configForm.value.candidateParamArray?.length > 0) { + if (configForm.value?.userIds!.length > 0) { const candidateNames: string[] = [] userOptions?.value.forEach((item) => { - if (configForm.value?.candidateParamArray.includes(item.id)) { + if (configForm.value?.userIds!.includes(item.id)) { candidateNames.push(item.nickname) } }) @@ -155,10 +169,10 @@ export function useNodeForm(nodeType: NodeType) { } // 指定角色 if (configForm.value?.candidateStrategy === CandidateStrategy.ROLE) { - if (configForm.value.candidateParamArray?.length > 0) { + if (configForm.value.roleIds!.length > 0) { const candidateNames: string[] = [] roleOptions?.value.forEach((item) => { - if (configForm.value?.candidateParamArray.includes(item.id)) { + if (configForm.value?.roleIds!.includes(item.id)) { candidateNames.push(item.name) } }) @@ -168,29 +182,32 @@ export function useNodeForm(nodeType: NodeType) { // 指定部门 if ( configForm.value?.candidateStrategy === CandidateStrategy.DEPT_MEMBER || - configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER + configForm.value?.candidateStrategy === CandidateStrategy.DEPT_LEADER || + configForm.value?.candidateStrategy === CandidateStrategy.MULTI_LEVEL_DEPT_LEADER ) { - if (configForm.value?.candidateParamArray?.length > 0) { + if (configForm.value?.deptIds!.length > 0) { const candidateNames: string[] = [] deptOptions?.value.forEach((item) => { - if (configForm.value?.candidateParamArray.includes(item.id)) { + if (configForm.value?.deptIds!.includes(item.id!)) { candidateNames.push(item.name) } }) if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_MEMBER) { showText = `部门成员:${candidateNames.join(',')}` - } else { + } else if (configForm.value.candidateStrategy === CandidateStrategy.DEPT_LEADER) { showText = `部门的负责人:${candidateNames.join(',')}` + } else { + showText = `多级部门的负责人:${candidateNames.join(',')}` } } } // 指定岗位 if (configForm.value?.candidateStrategy === CandidateStrategy.POST) { - if (configForm.value.candidateParamArray?.length > 0) { + if (configForm.value.postIds!.length > 0) { const candidateNames: string[] = [] postOptions?.value.forEach((item) => { - if (configForm.value?.candidateParamArray.includes(item.id)) { + if (configForm.value?.postIds!.includes(item.id!)) { candidateNames.push(item.name) } }) @@ -199,10 +216,10 @@ export function useNodeForm(nodeType: NodeType) { } // 指定用户组 if (configForm.value?.candidateStrategy === CandidateStrategy.USER_GROUP) { - if (configForm.value?.candidateParamArray?.length > 0) { + if (configForm.value?.userGroups!.length > 0) { const candidateNames: string[] = [] userGroupOptions?.value.forEach((item) => { - if (configForm.value?.candidateParamArray.includes(item.id)) { + if (configForm.value?.userGroups!.includes(item.id)) { candidateNames.push(item.name) } }) @@ -218,16 +235,116 @@ export function useNodeForm(nodeType: NodeType) { if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER) { showText = `发起人自己` } - + // 发起人的部门负责人 + if (configForm.value?.candidateStrategy === CandidateStrategy.START_USER_DEPT_LEADER) { + showText = `发起人的部门负责人` + } + // 发起人的部门负责人 + if ( + configForm.value?.candidateStrategy === CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER + ) { + showText = `发起人连续部门负责人` + } // 流程表达式 if (configForm.value?.candidateStrategy === CandidateStrategy.EXPRESSION) { - if (configForm.value.candidateParamArray?.length > 0) { - showText = `流程表达式:${configForm.value.candidateParamArray[0]}` - } + showText = `流程表达式:${configForm.value.expression}` } return showText } + /** + * 处理候选人参数的赋值 + */ + const handleCandidateParam = () => { + let candidateParam: undefined | string = undefined + if (!configForm.value) { + return candidateParam + } + switch (configForm.value.candidateStrategy) { + case CandidateStrategy.USER: + candidateParam = configForm.value.userIds!.join(',') + break + case CandidateStrategy.ROLE: + candidateParam = configForm.value.roleIds!.join(',') + break + case CandidateStrategy.POST: + candidateParam = configForm.value.postIds!.join(',') + break + case CandidateStrategy.USER_GROUP: + candidateParam = configForm.value.userGroups!.join(',') + break + case CandidateStrategy.EXPRESSION: + candidateParam = configForm.value.expression! + break + case CandidateStrategy.DEPT_MEMBER: + case CandidateStrategy.DEPT_LEADER: + candidateParam = configForm.value.deptIds!.join(',') + break + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: + candidateParam = configForm.value.deptLevel + '' + break + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // TODO 是否允许选多个部门 + const deptIds = configForm.value.deptIds!.join(',') + candidateParam = deptIds.concat(',' + configForm.value.deptLevel + '') + break + } + default: + break + } + return candidateParam + } + /** + * 解析候选人参数 + */ + const parseCandidateParam = ( + candidateStrategy: CandidateStrategy, + candidateParam: string | undefined + ) => { + if (!configForm.value || !candidateParam) { + return + } + switch (candidateStrategy) { + case CandidateStrategy.USER: { + configForm.value.userIds = candidateParam.split(',').map((item) => +item) + break + } + case CandidateStrategy.ROLE: + configForm.value.roleIds = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.POST: + configForm.value.postIds = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.USER_GROUP: + configForm.value.userGroups = candidateParam.split(',').map((item) => +item) + break + case CandidateStrategy.EXPRESSION: + configForm.value.expression = candidateParam + break + case CandidateStrategy.DEPT_MEMBER: + case CandidateStrategy.DEPT_LEADER: + configForm.value.deptIds = candidateParam.split(',').map((item) => +item) + break + // 发起人部门负责人 + case CandidateStrategy.START_USER_DEPT_LEADER: + case CandidateStrategy.START_USER_MULTI_LEVEL_DEPT_LEADER: + configForm.value.deptLevel = +candidateParam + break + // 指定连续多级部门的负责人 + case CandidateStrategy.MULTI_LEVEL_DEPT_LEADER: { + // 暂时只能选一个部门 + const paramArray = candidateParam.split(',') + configForm.value.deptIds = [+paramArray[0]] + configForm.value.deptLevel = +paramArray[1] + break + } + default: + break + } + } return { configForm, roleOptions, @@ -235,6 +352,8 @@ export function useNodeForm(nodeType: NodeType) { userOptions, userGroupOptions, deptTreeOptions, + handleCandidateParam, + parseCandidateParam, getShowText } } diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue index 807f08b5..aa1bb51b 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue @@ -46,14 +46,9 @@ - + - + - + - + @@ -200,7 +180,7 @@ + + diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue index 01ed75ce..e72b1117 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue @@ -25,7 +25,7 @@
- 审批类型 : + 审批类型 : {{ item.title }}
- +
- +
- +
@@ -435,7 +450,8 @@ import { ASSIGN_START_USER_HANDLER_TYPES, TimeoutHandlerType, ASSIGN_EMPTY_HANDLER_TYPES, - AssignEmptyHandlerType + AssignEmptyHandlerType, + FieldPermissionType } from '../consts' import { @@ -479,7 +495,9 @@ const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.USER_ // 激活的 Tab 标签页 const activeTabName = ref('user') // 表单字段权限设置 -const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission() +const { formType, fieldsPermissionConfig, getNodeConfigFormFields } = useFormFieldsPermission( + FieldPermissionType.READ +) // 操作按钮设置 const { buttonsSetting, btnDisplayNameEdit, changeBtnDisplayName, btnDisplayNameBlurEvent } = useButtonsSetting() diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue deleted file mode 100644 index a26a4935..00000000 --- a/src/components/SimpleProcessDesignerV2/src/nodes/StartEventNode.vue +++ /dev/null @@ -1,43 +0,0 @@ - - - diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue new file mode 100644 index 00000000..23e1dd3e --- /dev/null +++ b/src/components/SimpleProcessDesignerV2/src/nodes/StartUserNode.vue @@ -0,0 +1,79 @@ + + + From e75f9544953a2bcd1638942115ef8b7197fb87df Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 22 Aug 2024 23:23:06 +0800 Subject: [PATCH 50/93] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96,=20b?= =?UTF-8?q?ug=20=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../SimpleProcessDesignerV2/src/node.ts | 68 +++ .../src/nodes-config/ConditionNodeConfig.vue | 429 +++++++++--------- .../src/nodes/CopyTaskNode.vue | 30 +- .../src/nodes/StartUserNode.vue | 22 +- .../src/nodes/UserTaskNode.vue | 24 +- .../theme/iconfont.ttf | Bin 2908 -> 3128 bytes .../theme/iconfont.woff | Bin 1976 -> 2116 bytes .../theme/iconfont.woff2 | Bin 1480 -> 1616 bytes .../theme/simple-process-designer.scss | 15 +- 9 files changed, 318 insertions(+), 270 deletions(-) diff --git a/src/components/SimpleProcessDesignerV2/src/node.ts b/src/components/SimpleProcessDesignerV2/src/node.ts index d0fb0866..282600a3 100644 --- a/src/components/SimpleProcessDesignerV2/src/node.ts +++ b/src/components/SimpleProcessDesignerV2/src/node.ts @@ -90,6 +90,55 @@ export function useFormFieldsPermission(defaultPermission: FieldPermissionType) getNodeConfigFormFields } } +/** + * @description 获取表单的字段 + */ +export function useFormFields() { + // 解析后的表单字段 + const formFields = inject>('formFields') // 流程表单字段 + const parseFormFields = () => { + const parsedFormFields: Array> = [] + if (formFields) { + formFields.value.forEach((fieldStr: string) => { + parseField(JSON.parse(fieldStr), parsedFormFields) + }) + } + return parsedFormFields + } + // 解析字段。 + const parseField = ( + rule: Record, + parsedFormFields: Array>, + parentTitle: string = '' + ) => { + const { field, title: tempTitle, children, type } = rule + if (field && tempTitle) { + let title = tempTitle + if (parentTitle) { + title = `${parentTitle}.${tempTitle}` + } + parsedFormFields.push({ + field, + title, + type + }) + // TODO 子表单 需要处理子表单字段 + // if (type === 'group' && rule.props?.rule && Array.isArray(rule.props.rule)) { + // // 解析子表单的字段 + // rule.props.rule.forEach((item) => { + // parseFieldsSetDefaultPermission(item, fieldsPermission, title) + // }) + // } + } + if (children && Array.isArray(children)) { + children.forEach((rule) => { + parseField(rule, parsedFormFields) + }) + } + } + + return parseFormFields() +} export type UserTaskFormType = { //candidateParamArray: any[] @@ -408,3 +457,22 @@ export function useNodeName(nodeType: NodeType) { blurEvent } } + +export function useNodeName2(node: Ref, nodeType: NodeType) { + // 显示节点名称输入框 + const showInput = ref(false) + // 节点名称输入框失去焦点 + const blurEvent = () => { + showInput.value = false + node.value.name = node.value.name || (NODE_DEFAULT_NAME.get(nodeType) as string) + } + // 点击节点标题进行输入 + const clickTitle = () => { + showInput.value = true + } + return { + showInput, + clickTitle, + blurEvent + } +} diff --git a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue index 679fdbfe..4ffcd4c5 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue @@ -4,9 +4,9 @@ v-model="settingVisible" :show-close="false" :size="588" - :before-close=" handleClose" - > - +
+
其它条件不满足进入此分支(该分支不可编辑和删除)
- - - + + + - - {{ dict.label }} - - - - + {{ dict.label }} + + + + - -
-
-
条件组关系
- -
- -
- - -
- -
- - -
-
- - - -
-
- - - -
-
- -
-
- -
-
- +
+ + +
+ +
+ + +
+
+ + + +
+
+ + + +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+ + +
From b69a784e8631f8b230823b8022ec53d732c50d96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sat, 21 Sep 2024 09:15:27 +0800 Subject: [PATCH 58/93] =?UTF-8?q?=E3=80=90=E6=96=B0=E5=A2=9E=E3=80=91=20IO?= =?UTF-8?q?T=20=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/iot/device/index.ts | 63 ++++++ src/api/iot/product/index.ts | 5 + src/router/modules/remaining.ts | 2 +- src/utils/dict.ts | 3 +- src/views/iot/device/DeviceForm.vue | 121 +++++++++++ src/views/iot/device/index.vue | 276 +++++++++++++++++++++++++ src/views/iot/product/ProductForm.vue | 2 +- src/views/iot/product/detail/index.vue | 2 +- src/views/iot/product/index.vue | 10 +- 9 files changed, 477 insertions(+), 7 deletions(-) create mode 100644 src/api/iot/device/index.ts create mode 100644 src/views/iot/device/DeviceForm.vue create mode 100644 src/views/iot/device/index.vue diff --git a/src/api/iot/device/index.ts b/src/api/iot/device/index.ts new file mode 100644 index 00000000..4ee6d8d9 --- /dev/null +++ b/src/api/iot/device/index.ts @@ -0,0 +1,63 @@ +import request from '@/config/axios' + +// IoT 设备 VO +export interface DeviceVO { + id: number // 设备 ID,主键,自增 + deviceKey: string // 设备唯一标识符,全局唯一,用于识别设备 + deviceName: string // 设备名称,在产品内唯一,用于标识设备 + productId: number // 产品 ID,关联 iot_product 表的 id + productKey: string // 产品 Key,关联 iot_product 表的 product_key + deviceType: number // 设备类型:0 - 直连设备,1 - 网关子设备,2 - 网关设备 + nickname: string // 设备备注名称,供用户自定义备注 + gatewayId: number // 网关设备 ID,子设备需要关联的网关设备 ID + status: number // 设备状态:0 - 未激活,1 - 在线,2 - 离线,3 - 已禁用 + statusLastUpdateTime: Date // 设备状态最后更新时间 + lastOnlineTime: Date // 最后上线时间 + lastOfflineTime: Date // 最后离线时间 + activeTime: Date // 设备激活时间 + ip: string // 设备的 IP 地址 + firmwareVersion: string // 设备的固件版本 + deviceSecret: string // 设备密钥,用于设备认证,需安全存储 + mqttClientId: string // MQTT 客户端 ID + mqttUsername: string // MQTT 用户名 + mqttPassword: string // MQTT 密码 + authType: string // 认证类型(如一机一密、动态注册) + latitude: number // 设备位置的纬度,范围 -90.000000 ~ 90.000000 + longitude: number // 设备位置的经度,范围 -180.000000 ~ 180.000000 + areaId: number // 地区编码,符合国家地区编码标准,关联地区表 + address: string // 设备详细地址 + serialNumber: string // 设备序列号 +} + +// IoT 设备 API +export const DeviceApi = { + // 查询IoT 设备分页 + getDevicePage: async (params: any) => { + return await request.get({ url: `/iot/device/page`, params }) + }, + + // 查询IoT 设备详情 + getDevice: async (id: number) => { + return await request.get({ url: `/iot/device/get?id=` + id }) + }, + + // 新增IoT 设备 + createDevice: async (data: DeviceVO) => { + return await request.post({ url: `/iot/device/create`, data }) + }, + + // 修改IoT 设备 + updateDevice: async (data: DeviceVO) => { + return await request.put({ url: `/iot/device/update`, data }) + }, + + // 删除IoT 设备 + deleteDevice: async (id: number) => { + return await request.delete({ url: `/iot/device/delete?id=` + id }) + }, + + // 导出IoT 设备 Excel + exportDevice: async (params) => { + return await request.download({ url: `/iot/device/export-excel`, params }) + } +} \ No newline at end of file diff --git a/src/api/iot/product/index.ts b/src/api/iot/product/index.ts index 1bc45b9e..d4de1e5b 100644 --- a/src/api/iot/product/index.ts +++ b/src/api/iot/product/index.ts @@ -51,5 +51,10 @@ export const ProductApi = { // 更新产品状态 updateProductStatus: async (id: number, status: number) => { return await request.put({ url: `/iot/product/update-status?id=` + id + `&status=` + status }) + }, + + // 查询产品(精简)列表 + getSimpleProductList() { + return request.get({ url: '/iot/product/list-all-simple' }) } } diff --git a/src/router/modules/remaining.ts b/src/router/modules/remaining.ts index 0a156539..4595d563 100644 --- a/src/router/modules/remaining.ts +++ b/src/router/modules/remaining.ts @@ -614,7 +614,7 @@ const remainingRouter: AppRouteRecordRaw[] = [ children: [ { path: 'product/detail/:id', - name: 'IotProductDetail', + name: 'IoTProductDetail', meta: { title: '产品详情', noCache: true, diff --git a/src/utils/dict.ts b/src/utils/dict.ts index 4a8c017c..82f9218f 100644 --- a/src/utils/dict.ts +++ b/src/utils/dict.ts @@ -234,5 +234,6 @@ export enum DICT_TYPE { IOT_PRODUCT_STATUS = 'iot_product_status', // IOT 产品状态 IOT_PRODUCT_DEVICE_TYPE = 'iot_product_device_type', // IOT 产品设备类型 IOT_DATA_FORMAT = 'iot_data_format', // IOT 数据格式 - IOT_PROTOCOL_TYPE = 'iot_protocol_type' // IOT 接入网关协议 + IOT_PROTOCOL_TYPE = 'iot_protocol_type', // IOT 接入网关协议 + IOT_DEVICE_STATUS = 'iot_device_status' // IOT 设备状态 } diff --git a/src/views/iot/device/DeviceForm.vue b/src/views/iot/device/DeviceForm.vue new file mode 100644 index 00000000..a77045c9 --- /dev/null +++ b/src/views/iot/device/DeviceForm.vue @@ -0,0 +1,121 @@ + + diff --git a/src/views/iot/device/index.vue b/src/views/iot/device/index.vue new file mode 100644 index 00000000..e50819bd --- /dev/null +++ b/src/views/iot/device/index.vue @@ -0,0 +1,276 @@ + + + diff --git a/src/views/iot/product/ProductForm.vue b/src/views/iot/product/ProductForm.vue index 21cee6c3..7d254a03 100644 --- a/src/views/iot/product/ProductForm.vue +++ b/src/views/iot/product/ProductForm.vue @@ -103,7 +103,7 @@ import { ProductApi, ProductVO } from '@/api/iot/product' import { DICT_TYPE, getIntDictOptions } from '@/utils/dict' -defineOptions({ name: 'ProductForm' }) +defineOptions({ name: 'IoTProductForm' }) const { t } = useI18n() const message = useMessage() diff --git a/src/views/iot/product/detail/index.vue b/src/views/iot/product/detail/index.vue index 8652e240..c77fe176 100644 --- a/src/views/iot/product/detail/index.vue +++ b/src/views/iot/product/detail/index.vue @@ -20,7 +20,7 @@ import { ProductApi, ProductVO } from '@/api/iot/product' import ProductDetailsHeader from '@/views/iot/product/detail/ProductDetailsHeader.vue' import ProductDetailsInfo from '@/views/iot/product/detail/ProductDetailsInfo.vue' -defineOptions({ name: 'IotProductDetail' }) +defineOptions({ name: 'IoTProductDetail' }) const route = useRoute() const message = useMessage() diff --git a/src/views/iot/product/index.vue b/src/views/iot/product/index.vue index a1f5ae4a..d3196ac4 100644 --- a/src/views/iot/product/index.vue +++ b/src/views/iot/product/index.vue @@ -44,7 +44,11 @@ - + + +
-
其它条件不满足进入此分支(该分支不可编辑和删除)
+
其它条件不满足进入此分支(该分支不可编辑和删除)
- +
条件组关系
@@ -75,9 +73,6 @@ inactive-text="或" />
-
{ return CONDITION_CONFIG_TYPES.filter((item) => { // 业务表单暂时去掉条件规则选项 if (formType?.value !== 10) { - return item.value === 1 + return item.value === ConditionType.RULE } else { return true } @@ -202,9 +197,9 @@ const props = defineProps({ }) const settingVisible = ref(false) const open = () => { - if (currentNode.value.attributes.conditionType === ConditionConfigType.RULE) { - if (currentNode.value.attributes.conditionGroups) { - conditionGroups.value = currentNode.value.attributes.conditionGroups + if (currentNode.value.conditionType === ConditionType.RULE) { + if (currentNode.value.conditionGroups) { + conditionGroups.value = currentNode.value.conditionGroups } } settingVisible.value = true @@ -227,7 +222,7 @@ const blurEvent = () => { showInput.value = false currentNode.value.name = currentNode.value.name || - getDefaultConditionNodeName(props.nodeIndex, currentNode.value.attributes?.defaultFlow) + getDefaultConditionNodeName(props.nodeIndex, currentNode.value?.defaultFlow) } const currentNode = ref(props.conditionNode) @@ -256,7 +251,7 @@ const formRef = ref() // 表单 Ref // 保存配置 const saveConfig = async () => { - if (!currentNode.value.attributes.defaultFlow) { + if (!currentNode.value.defaultFlow) { // 校验表单 if (!formRef) return false const valid = await formRef.value.validate() @@ -266,12 +261,12 @@ const saveConfig = async () => { return false } currentNode.value.showText = showText - if (currentNode.value.attributes.conditionType === ConditionConfigType.EXPRESSION) { - currentNode.value.attributes.conditionGroups = undefined + if (currentNode.value.conditionType === ConditionType.EXPRESSION) { + currentNode.value.conditionGroups = undefined } - if (currentNode.value.attributes.conditionType === ConditionConfigType.RULE) { - currentNode.value.attributes.conditionExpression = undefined - currentNode.value.attributes.conditionGroups = conditionGroups.value + if (currentNode.value.conditionType === ConditionType.RULE) { + currentNode.value.conditionExpression = undefined + currentNode.value.conditionGroups = conditionGroups.value } } settingVisible.value = false @@ -279,12 +274,12 @@ const saveConfig = async () => { } const getShowText = (): string => { let showText = '' - if (currentNode.value.attributes.conditionType === ConditionConfigType.EXPRESSION) { - if (currentNode.value.attributes.conditionExpression) { - showText = `表达式:${currentNode.value.attributes.conditionExpression}` + if (currentNode.value.conditionType === ConditionType.EXPRESSION) { + if (currentNode.value.conditionExpression) { + showText = `表达式:${currentNode.value.conditionExpression}` } } - if (currentNode.value.attributes.conditionType === ConditionConfigType.RULE) { + if (currentNode.value.conditionType === ConditionType.RULE) { // 条件组是否为与关系 const groupAnd = conditionGroups.value.and let warningMesg: undefined | string = undefined @@ -298,7 +293,7 @@ const getShowText = (): string => { getFieldTitle(rule.leftSide) + ' ' + getOpName(rule.opCode) + ' ' + rule.rightSide ) } else { - // 又一条规则不完善。提示错误 + // 有一条规则不完善。提示错误 warningMesg = '请完善条件规则' return '' } diff --git a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue index 568afa28..385a81ff 100644 --- a/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue +++ b/src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue @@ -130,7 +130,7 @@ const blurEvent = (index: number) => { showInputs.value[index] = false const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode conditionNode.name = - conditionNode.name || getDefaultConditionNodeName(index, conditionNode.attributes?.defaultFlow) + conditionNode.name || getDefaultConditionNodeName(index, conditionNode.defaultFlow) } // 点击条件名称 @@ -156,10 +156,8 @@ const addCondition = () => { type: NodeType.CONDITION_NODE, childNode: undefined, conditionNodes: [], - attributes: { - conditionType: 1, - defaultFlow: false - } + conditionType: 1, + defaultFlow: false } conditionNodes.splice(lastIndex, 0, conditionData) } diff --git a/src/components/SimpleProcessDesignerV2/src/utils.ts b/src/components/SimpleProcessDesignerV2/src/utils.ts index e71f74dc..854d7032 100644 --- a/src/components/SimpleProcessDesignerV2/src/utils.ts +++ b/src/components/SimpleProcessDesignerV2/src/utils.ts @@ -1,7 +1,7 @@ import { TimeUnitType, ApproveType, APPROVE_TYPE } from './consts' // 获取条件节点默认的名称 -export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean): string => { +export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean | undefined): string => { if (defaultFlow) { return '其它情况' } From 63a0e5dc3d3463caffd56eceac5defd854941288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sun, 22 Sep 2024 13:17:12 +0800 Subject: [PATCH 60/93] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91=20IO?= =?UTF-8?q?T=20=E8=AE=BE=E5=A4=87=E7=AE=A1=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/iot/device/index.ts | 28 +++++++--- src/views/iot/device/DeviceForm.vue | 42 +++++++++++++- src/views/iot/device/index.vue | 86 +++++++++++++---------------- 3 files changed, 95 insertions(+), 61 deletions(-) diff --git a/src/api/iot/device/index.ts b/src/api/iot/device/index.ts index 4ee6d8d9..39a2e5a8 100644 --- a/src/api/iot/device/index.ts +++ b/src/api/iot/device/index.ts @@ -1,6 +1,6 @@ import request from '@/config/axios' -// IoT 设备 VO +// 设备 VO export interface DeviceVO { id: number // 设备 ID,主键,自增 deviceKey: string // 设备唯一标识符,全局唯一,用于识别设备 @@ -29,35 +29,45 @@ export interface DeviceVO { serialNumber: string // 设备序列号 } -// IoT 设备 API +export interface DeviceUpdateStatusVO { + id: number // 设备 ID,主键,自增 + status: number // 设备状态:0 - 未激活,1 - 在线,2 - 离线,3 - 已禁用 +} + +// 设备 API export const DeviceApi = { - // 查询IoT 设备分页 + // 查询设备分页 getDevicePage: async (params: any) => { return await request.get({ url: `/iot/device/page`, params }) }, - // 查询IoT 设备详情 + // 查询设备详情 getDevice: async (id: number) => { return await request.get({ url: `/iot/device/get?id=` + id }) }, - // 新增IoT 设备 + // 新增设备 createDevice: async (data: DeviceVO) => { return await request.post({ url: `/iot/device/create`, data }) }, - // 修改IoT 设备 + // 修改设备 updateDevice: async (data: DeviceVO) => { return await request.put({ url: `/iot/device/update`, data }) }, - // 删除IoT 设备 + // 修改设备状态 + updateDeviceStatus: async (data: DeviceUpdateStatusVO) => { + return await request.put({ url: `/iot/device/update-status`, data }) + }, + + // 删除设备 deleteDevice: async (id: number) => { return await request.delete({ url: `/iot/device/delete?id=` + id }) }, - // 导出IoT 设备 Excel + // 导出设备 Excel exportDevice: async (params) => { return await request.download({ url: `/iot/device/export-excel`, params }) } -} \ No newline at end of file +} diff --git a/src/views/iot/device/DeviceForm.vue b/src/views/iot/device/DeviceForm.vue index a77045c9..f926b6d4 100644 --- a/src/views/iot/device/DeviceForm.vue +++ b/src/views/iot/device/DeviceForm.vue @@ -8,7 +8,12 @@ v-loading="formLoading" > - + - + @@ -52,7 +61,34 @@ const formData = ref({ serialNumber: undefined }) const formRules = reactive({ - productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }] + productId: [{ required: true, message: '产品不能为空', trigger: 'blur' }], + deviceName: [ + { + pattern: /^[a-zA-Z0-9_.\-:@]{4,32}$/, + message: + '支持英文字母、数字、下划线(_)、中划线(-)、点号(.)、半角冒号(:)和特殊字符@,长度限制为4~32个字符', + trigger: 'blur' + } + ], + nickname: [ + { + validator: (rule, value, callback) => { + if (value === undefined || value === null) { + callback() + return + } + const length = value.replace(/[\u4e00-\u9fa5\u3040-\u30ff]/g, 'aa').length + if (length < 4 || length > 64) { + callback(new Error('备注名称长度限制为4~64个字符,中文及日文算2个字符')) + } else if (!/^[\u4e00-\u9fa5\u3040-\u30ff_a-zA-Z0-9]+$/.test(value)) { + callback(new Error('备注名称只能包含中文、英文字母、日文、数字和下划线(_)')) + } else { + callback() + } + }, + trigger: 'blur' + } + ] }) const formRef = ref() // 表单 Ref diff --git a/src/views/iot/device/index.vue b/src/views/iot/device/index.vue index e50819bd..bb733250 100644 --- a/src/views/iot/device/index.vue +++ b/src/views/iot/device/index.vue @@ -72,24 +72,22 @@ - 搜索 - 重置 + + + 搜索 + + + + 重置 + - 新增 - - - 导出 + + 新增
@@ -100,9 +98,21 @@ - - - + + + + + + + + + - - -