Просмотр исходного кода

仿钉钉流程设计- bug 修复

jason 1 год назад
Родитель
Сommit
2c11228f55

+ 1 - 7
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)

+ 13 - 15
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue

@@ -3,20 +3,19 @@
   <StartEventNode
     v-if="currentNode && currentNode.type === NodeType.START_EVENT_NODE"
     :flow-node="currentNode"
-    @update:model-value="handleModelValueUpdate"
   />
   <!-- 审批节点 -->
   <UserTaskNode
     v-if="currentNode && currentNode.type === NodeType.USER_TASK_NODE"
     :flow-node="currentNode"
-    @update:model-value="handleModelValueUpdate"
+    @update:flow-node="handleModelValueUpdate"
     @find:parent-node="findFromParentNode"
   />
   <!-- 抄送节点 -->
   <CopyTaskNode
     v-if="currentNode && currentNode.type === NodeType.COPY_TASK_NODE"
     :flow-node="currentNode"
-    @update:model-value="handleModelValueUpdate"
+    @update:flow-node="handleModelValueUpdate"
   />
   <!-- 条件节点 -->
   <ExclusiveNode
@@ -25,8 +24,8 @@
     @update:model-value="handleModelValueUpdate"
     @find:parent-node="findFromParentNode"
   />
-   <!-- 并行节点 -->
-   <ParallelNode
+  <!-- 并行节点 -->
+  <ParallelNode
     v-if="currentNode && currentNode.type === NodeType.PARALLEL_NODE_FORK"
     :flow-node="currentNode"
     @update:model-value="handleModelValueUpdate"
@@ -36,7 +35,7 @@
   <ProcessNodeTree
     v-if="currentNode && currentNode.childNode"
     v-model:flow-node="currentNode.childNode"
-    :parent-node= "currentNode"
+    :parent-node="currentNode"
     @find:recursive-find-parent-node="recursiveFindParentNode"
   />
 
@@ -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<SimpleFlowNode>(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)
 }
 

+ 24 - 34
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue

@@ -15,25 +15,29 @@
         </div>
       </div>
       <div class="scale-container" :style="`transform: scale(${scaleValue / 100});`">
-        <ProcessNodeTree v-if="processNodeTree"  v-model:flow-node="processNodeTree" />
+        <ProcessNodeTree v-if="processNodeTree" v-model:flow-node="processNodeTree" />
       </div>
     </div>
     <Dialog v-model="errorDialogVisible" title="保存失败" width="400" :fullscreen="false">
       <div class="mb-2">以下节点内容不完善,请修改后保存</div>
-      <div class="mb-3 b-rounded-1 bg-gray-100 p-2 line-height-normal" v-for="(item, index) in errorNodes" :key="index">
-          {{ item.name }} : {{ NODE_DEFAULT_TEXT.get(item.type) }}
+      <div
+        class="mb-3 b-rounded-1 bg-gray-100 p-2 line-height-normal"
+        v-for="(item, index) in errorNodes"
+        :key="index"
+      >
+        {{ item.name }} : {{ NODE_DEFAULT_TEXT.get(item.type) }}
       </div>
       <template #footer>
-        <el-button type="primary" @click="errorDialogVisible = false" >知道了</el-button>
+        <el-button type="primary" @click="errorDialogVisible = false">知道了</el-button>
       </template>
     </Dialog>
   </div>
 </template>
 
 <script setup lang="ts">
-import ProcessNodeTree from './ProcessNodeTree.vue';
+import ProcessNodeTree from './ProcessNodeTree.vue'
 import { updateBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple'
-import { SimpleFlowNode, NodeType,NODE_DEFAULT_TEXT } from './consts'
+import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts'
 
 defineOptions({
   name: 'SimpleProcessDesigner'
@@ -44,33 +48,11 @@ const props = defineProps({
   modelId: String
 })
 const message = useMessage() // 国际化
-const processNodeTree = ref<SimpleFlowNode>({
-  name: '开始',
-  type: NodeType.START_EVENT_NODE,
-  id: 'StartEvent_1',
-  childNode: {
-    id: 'EndEvent_1',
-    name: '结束',
-    type: NodeType.END_EVENT_NODE
-  }
-})
-
-// const rootNode = ref<SimpleFlowNode>({
-//   name: '开始',
-//   type: NodeType.START_EVENT_NODE,
-//   id: 'StartEvent_1'
-// })
-
-// const childNode = ref<SimpleFlowNode>({
-//   id: 'EndEvent_1',
-//   name: '结束',
-//   type: NodeType.END_EVENT_NODE
-// })
+const processNodeTree = ref<SimpleFlowNode | undefined>()
 
 const errorDialogVisible = ref(false)
 let errorNodes: SimpleFlowNode[] = []
 const saveSimpleFlowModel = async () => {
-  console.log('processNodeTree===>', processNodeTree.value)
   if (!props.modelId) {
     message.error('缺少模型 modelId 编号')
     return
@@ -79,7 +61,7 @@ const saveSimpleFlowModel = async () => {
   validateNode(processNodeTree.value, errorNodes)
   if (errorNodes.length > 0) {
     errorDialogVisible.value = true
-    return;
+    return
   }
   const data = {
     id: props.modelId,
@@ -93,7 +75,6 @@ const saveSimpleFlowModel = async () => {
   } else {
     message.alert('修改失败')
   }
-  
 }
 // 校验节点设置。 暂时以 showText 为空 未节点错误配置
 const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
@@ -158,10 +139,19 @@ const zoomIn = () => {
 onMounted(async () => {
   const result = await getBpmSimpleModel(props.modelId)
   if (result) {
-    console.log('the result is ', result)
     processNodeTree.value = result
-    // rootNode.value = result
-    // childNode.value = result.childNode
+  } else {
+    // 初始值
+    processNodeTree.value = {
+      name: '开始',
+      type: NodeType.START_EVENT_NODE,
+      id: 'StartEvent_1',
+      childNode: {
+        id: 'EndEvent_1',
+        name: '结束',
+        type: NodeType.END_EVENT_NODE
+      }
+    }
   }
 })
 </script>

+ 23 - 19
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"
         />
         <div v-else class="node-name"
-          >{{ currentNode.name }}
+          >{{ configForm.name }}
           <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()"
         /></div>
 
@@ -223,8 +223,15 @@ const props = defineProps({
 })
 // 是否可见
 const settingVisible = ref(false)
-// 当前节点信息
+// 当前节点
 const currentNode = ref<SimpleFlowNode>(props.flowNode)
+// 监控节点变化
+watch(
+  () => props.flowNode,
+  (newValue) => {
+    currentNode.value = newValue
+  }
+)
 const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
 const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
 const userOptions = inject<Ref<UserApi.UserVO[]>>('userList') // 用户列表
@@ -247,13 +254,14 @@ const activeTabName = ref('user')
 const formRef = ref() // 表单 Ref
 
 const configForm = ref<any>({
+  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)
 }
 </script>
 
-<style lang="scss" scoped>
-// ::v-deep(.el-divider--horizontal) {
-//   display: block;
-//   height: 1px;
-//   margin: 0;
-//   border-top: 1px var(--el-border-color) var(--el-border-style);
-// }
-</style>
+<style lang="scss" scoped></style>

+ 30 - 18
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"
         />
         <div v-else class="node-name"
-          >{{ currentNode.name }}
+          >{{ configForm.name }}
           <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()"
         /></div>
 
@@ -394,8 +394,15 @@ const emits = defineEmits<{
   'find:returnTaskNodes': [nodeList: SimpleFlowNode[]]
 }>()
 
-const notAllowedMultiApprovers = ref(false)
 const currentNode = ref<SimpleFlowNode>(props.flowNode)
+// 监控节点变化
+watch(
+  () => props.flowNode,
+  (newValue) => {
+    currentNode.value = newValue
+  }
+)
+const notAllowedMultiApprovers = ref(false)
 const settingVisible = ref(false)
 const roleOptions = inject<Ref<RoleApi.RoleVO[]>>('roleList') // 角色列表
 const postOptions = inject<Ref<PostApi.PostVO[]>>('postList') // 岗位列表
@@ -410,6 +417,7 @@ const returnTaskList = ref<SimpleFlowNode[]>([])
 const formRef = ref() // 表单 Ref
 const activeTabName = ref('user') // 激活的 Tab 标签页
 const configForm = ref<any>({
+  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<any>({
 })
 // 表单校验规则
 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 = () => {

+ 14 - 34
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="node-wrapper">
     <div class="node-container">
-      <div class="node-box" :class="{'node-config-error': !currentNode.showText}">
+      <div class="node-box" :class="{ 'node-config-error': !currentNode.showText }">
         <div class="node-title-container">
           <div class="node-title-icon copy-task"><span class="iconfont icon-copy"></span></div>
           <input
@@ -21,30 +21,28 @@
           <div class="node-text" :title="currentNode.showText" v-if="currentNode.showText">
             {{ currentNode.showText }}
           </div>
-          <div class="node-text"  v-else>
+          <div class="node-text" v-else>
             {{ NODE_DEFAULT_TEXT.get(NodeType.COPY_TASK_NODE) }}
           </div>
           <Icon icon="ep:arrow-right-bold" />
         </div>
         <div class="node-toolbar">
-          <div class="toolbar-icon"><Icon  color="#0089ff"  icon="ep:circle-close-filled" :size="18"  @click="deleteNode" /></div>
+          <div class="toolbar-icon"
+            ><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
+          /></div>
         </div>
       </div>
 
       <!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
       <NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
     </div>
-    <CopyTaskNodeConfig
-      v-if="currentNode"
-      ref="nodeSetting"
-      :flow-node="currentNode"
-     />
+    <CopyTaskNodeConfig v-if="currentNode" ref="nodeSetting" :flow-node="currentNode" />
   </div>
 </template>
-<script setup lang='ts'>
+<script setup lang="ts">
 import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT, NODE_DEFAULT_NAME } from '../consts'
 import NodeHandler from '../NodeHandler.vue'
-import CopyTaskNodeConfig from '../nodes-config/CopyTaskNodeConfig.vue';
+import CopyTaskNodeConfig from '../nodes-config/CopyTaskNodeConfig.vue'
 import { generateUUID } from '@/utils'
 defineOptions({
   name: 'CopyTaskNode'
@@ -57,7 +55,7 @@ const props = defineProps({
 })
 // 定义事件,更新父组件。
 const emits = defineEmits<{
-  'update:modelValue': [node: SimpleFlowNode | undefined]
+  'update:flowNode': [node: SimpleFlowNode | undefined]
 }>()
 const currentNode = ref<SimpleFlowNode>(props.flowNode)
 
@@ -73,7 +71,8 @@ const showInput = ref(false)
 // 节点名称输入框失去焦点
 const blurEvent = () => {
   showInput.value = false
-  currentNode.value.name = currentNode.value.name || NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string
+  currentNode.value.name =
+    currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string)
 }
 // 点击节点标题进行输入
 const clickEvent = () => {
@@ -82,33 +81,14 @@ const clickEvent = () => {
 const nodeSetting = ref()
 // 打开节点配置
 const openNodeConfig = () => {
-  nodeSetting.value.setCurrentNode(currentNode.value);
+  nodeSetting.value.setCurrentNode(currentNode.value)
   nodeSetting.value.open()
 }
 
 // 删除节点。更新当前节点为孩子节点
 const deleteNode = () => {
-  emits('update:modelValue', currentNode.value.childNode)
-}
-// 复制节点
-const copyNode = () => {
-  const newCopyNode: SimpleFlowNode = {
-    id: generateUUID(),
-    name: currentNode.value.name,
-    showText: currentNode.value.showText,
-    type: currentNode.value.type,
-    // 抄送节点配置
-    attributes: {
-      candidateStrategy: currentNode.value.attributes?.candidateStrategy,
-      candidateParam: currentNode.value.attributes?.candidateParam
-    },
-    childNode: currentNode.value
-  }
-  currentNode.value = newCopyNode
-  emits('update:modelValue', currentNode.value)
+  emits('update:flowNode', currentNode.value.childNode)
 }
 </script>
 
-<style lang='scss' scoped>
-
-</style>
+<style lang="scss" scoped></style>

+ 54 - 32
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue

@@ -2,9 +2,13 @@
   <div class="branch-node-wrapper">
     <div class="branch-node-container">
       <div class="branch-node-add" @click="addCondition">添加条件</div>
-      <div class="branch-node-item" v-for="(item, index) in currentNode.conditionNodes" :key="index">
+      <div
+        class="branch-node-item"
+        v-for="(item, index) in currentNode.conditionNodes"
+        :key="index"
+      >
         <template v-if="index == 0">
-          <div class="branch-line-first-top"></div>
+          <div class="branch-line-first-top"> </div>
           <div class="branch-line-first-bottom"></div>
         </template>
         <template v-if="index + 1 == currentNode.conditionNodes?.length">
@@ -15,13 +19,14 @@
           <div class="node-container">
             <div class="node-box" :class="{ 'node-config-error': !item.showText }">
               <div class="branch-node-title-container">
-                <div  v-if="showInputs[index]">
+                <div v-if="showInputs[index]">
                   <input
                     type="text"
-                    class="input-max-width editable-title-input" 
+                    class="input-max-width editable-title-input"
                     @blur="blurEvent(index)"
-                    v-mountedFocus 
-                    v-model="item.name" />
+                    v-mountedFocus
+                    v-model="item.name"
+                  />
                 </div>
                 <div v-else class="branch-title" @click="clickEvent(index)"> {{ item.name }} </div>
                 <div class="branch-priority"> 优先级{{ index + 1 }} </div>
@@ -36,19 +41,27 @@
               </div>
               <div class="node-toolbar" v-if="index + 1 !== currentNode.conditionNodes?.length">
                 <div class="toolbar-icon">
-                  <Icon color="#0089ff"  icon="ep:circle-close-filled" :size="18"  @click="deleteCondition(index)" />
+                  <Icon
+                    color="#0089ff"
+                    icon="ep:circle-close-filled"
+                    :size="18"
+                    @click="deleteCondition(index)"
+                  />
                 </div>
               </div>
-              <div 
+              <div
                 class="branch-node-move move-node-left"
-                v-if="index != 0 && index + 1 !== currentNode.conditionNodes?.length" @click="moveNode(index, -1)">
+                v-if="index != 0 && index + 1 !== currentNode.conditionNodes?.length"
+                @click="moveNode(index, -1)"
+              >
                 <Icon icon="ep:arrow-left" />
               </div>
 
-              <div 
+              <div
                 class="branch-node-move move-node-right"
                 v-if="currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
-                @click="moveNode(index, 1)">
+                @click="moveNode(index, 1)"
+              >
                 <Icon icon="ep:arrow-right" />
               </div>
             </div>
@@ -57,11 +70,12 @@
         </div>
         <ConditionNodeConfig :node-index="index" :condition-node="item" :ref="item.id" />
         <!-- 递归显示子节点  -->
-        <ProcessNodeTree 
-            v-if="item && item.childNode" 
-            :parent-node="item" 
-            v-model:flow-node="item.childNode" 
-            @find:recursive-find-parent-node="recursiveFindParentNode"/>
+        <ProcessNodeTree
+          v-if="item && item.childNode"
+          :parent-node="item"
+          v-model:flow-node="item.childNode"
+          @find:recursive-find-parent-node="recursiveFindParentNode"
+        />
       </div>
     </div>
     <NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
@@ -91,25 +105,32 @@ const props = defineProps({
 })
 // 定义事件,更新父组件
 const emits = defineEmits<{
-  'update:modelValue': [node: SimpleFlowNode | undefined],
-  'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number],
-  'find:recursiveFindParentNode': [nodeList: SimpleFlowNode[], curentNode: SimpleFlowNode, nodeType: number]
+  'update:modelValue': [node: SimpleFlowNode | undefined]
+  'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number]
+  'find:recursiveFindParentNode': [
+    nodeList: SimpleFlowNode[],
+    curentNode: SimpleFlowNode,
+    nodeType: number
+  ]
 }>()
 
 const currentNode = ref<SimpleFlowNode>(props.flowNode)
 // const conditionNodes = computed(() => currentNode.value.conditionNodes);
 
-watch(() => props.flowNode, (newValue) => {
-  currentNode.value = newValue;
-});
-
+watch(
+  () => props.flowNode,
+  (newValue) => {
+    currentNode.value = newValue
+  }
+)
 
 const showInputs = ref<boolean[]>([])
 // 失去焦点
 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)
+  const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode
+  conditionNode.name =
+    conditionNode.name || getDefaultConditionNodeName(index, conditionNode.attributes?.defaultFlow)
 }
 
 // 点击条件名称
@@ -118,13 +139,13 @@ const clickEvent = (index: number) => {
 }
 
 const conditionNodeConfig = (nodeId: string) => {
-  const conditionNode = proxy.$refs[nodeId][0];
+  const conditionNode = proxy.$refs[nodeId][0]
   conditionNode.open()
 }
 
 // 新增条件
 const addCondition = () => {
-  const conditionNodes = currentNode.value.conditionNodes;
+  const conditionNodes = currentNode.value.conditionNodes
   if (conditionNodes) {
     const len = conditionNodes.length
     let lastIndex = len - 1
@@ -146,7 +167,7 @@ const addCondition = () => {
 
 // 删除条件
 const deleteCondition = (index: number) => {
-  const conditionNodes = currentNode.value.conditionNodes;
+  const conditionNodes = currentNode.value.conditionNodes
   if (conditionNodes) {
     conditionNodes.splice(index, 1)
     if (conditionNodes.length == 1) {
@@ -161,10 +182,12 @@ 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]
+    currentNode.value.conditionNodes[index] = currentNode.value.conditionNodes.splice(
+      index + to,
+      1,
+      currentNode.value.conditionNodes[index]
+    )[0]
   }
-
 }
 // 递归从父节点中查询匹配的节点
 const recursiveFindParentNode = (
@@ -181,7 +204,6 @@ const recursiveFindParentNode = (
   // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.EXCLUSIVE_NODE) 继续查找
   emits('find:parentNode', nodeList, nodeType)
 }
-
 </script>
 
 <style lang="scss" scoped></style>

+ 41 - 25
src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue

@@ -2,7 +2,11 @@
   <div class="branch-node-wrapper">
     <div class="branch-node-container">
       <div class="branch-node-add" @click="addCondition">添加分支</div>
-      <div class="branch-node-item" v-for="(item, index) in currentNode.conditionNodes" :key="index">
+      <div
+        class="branch-node-item"
+        v-for="(item, index) in currentNode.conditionNodes"
+        :key="index"
+      >
         <template v-if="index == 0">
           <div class="branch-line-first-top"></div>
           <div class="branch-line-first-bottom"></div>
@@ -15,13 +19,14 @@
           <div class="node-container">
             <div class="node-box">
               <div class="branch-node-title-container">
-                <div  v-if="showInputs[index]">
+                <div v-if="showInputs[index]">
                   <input
                     type="text"
-                    class="input-max-width editable-title-input" 
+                    class="input-max-width editable-title-input"
                     @blur="blurEvent(index)"
-                    v-mountedFocus 
-                    v-model="item.name" />
+                    v-mountedFocus
+                    v-model="item.name"
+                  />
                 </div>
                 <div v-else class="branch-title" @click="clickEvent(index)"> {{ item.name }} </div>
                 <div class="branch-priority">无优先级</div>
@@ -36,7 +41,12 @@
               </div>
               <div class="node-toolbar">
                 <div class="toolbar-icon">
-                  <Icon color="#0089ff"  icon="ep:circle-close-filled" :size="18"  @click="deleteCondition(index)" />
+                  <Icon
+                    color="#0089ff"
+                    icon="ep:circle-close-filled"
+                    :size="18"
+                    @click="deleteCondition(index)"
+                  />
                 </div>
               </div>
               <!-- <div 
@@ -56,11 +66,12 @@
           </div>
         </div>
         <!-- 递归显示子节点  -->
-        <ProcessNodeTree 
-            v-if="item && item.childNode" 
-            :parent-node="item" 
-            v-model:flow-node="item.childNode" 
-            @find:recursive-find-parent-node="recursiveFindParentNode"/>
+        <ProcessNodeTree
+          v-if="item && item.childNode"
+          :parent-node="item"
+          v-model:flow-node="item.childNode"
+          @find:recursive-find-parent-node="recursiveFindParentNode"
+        />
       </div>
     </div>
     <NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
@@ -85,24 +96,30 @@ const props = defineProps({
 })
 // 定义事件,更新父组件
 const emits = defineEmits<{
-  'update:modelValue': [node: SimpleFlowNode | undefined],
-  'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number],
-  'find:recursiveFindParentNode': [nodeList: SimpleFlowNode[], curentNode: SimpleFlowNode, nodeType: number]
+  'update:modelValue': [node: SimpleFlowNode | undefined]
+  'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number]
+  'find:recursiveFindParentNode': [
+    nodeList: SimpleFlowNode[],
+    curentNode: SimpleFlowNode,
+    nodeType: number
+  ]
 }>()
 
 const currentNode = ref<SimpleFlowNode>(props.flowNode)
 
-watch(() => props.flowNode, (newValue) => {
-  currentNode.value = newValue;
-});
-
+watch(
+  () => props.flowNode,
+  (newValue) => {
+    currentNode.value = newValue
+  }
+)
 
 const showInputs = ref<boolean[]>([])
 // 失去焦点
 const blurEvent = (index: number) => {
   showInputs.value[index] = false
-  const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode;
-  conditionNode.name = conditionNode.name || `并行${index+1}`
+  const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode
+  conditionNode.name = conditionNode.name || `并行${index + 1}`
 }
 
 // 点击条件名称
@@ -111,13 +128,13 @@ const clickEvent = (index: number) => {
 }
 
 const conditionNodeConfig = (nodeId: string) => {
-  const conditionNode = proxy.$refs[nodeId][0];
+  const conditionNode = proxy.$refs[nodeId][0]
   conditionNode.open()
 }
 
 // 新增条件
 const addCondition = () => {
-  const conditionNodes = currentNode.value.conditionNodes;
+  const conditionNodes = currentNode.value.conditionNodes
   if (conditionNodes) {
     const len = conditionNodes.length
     let lastIndex = len - 1
@@ -127,7 +144,7 @@ const addCondition = () => {
       showText: '无需配置条件同时执行',
       type: NodeType.CONDITION_NODE,
       childNode: undefined,
-      conditionNodes: [],
+      conditionNodes: []
     }
     conditionNodes.splice(lastIndex, 0, conditionData)
   }
@@ -135,7 +152,7 @@ const addCondition = () => {
 
 // 删除条件
 const deleteCondition = (index: number) => {
-  const conditionNodes = currentNode.value.conditionNodes;
+  const conditionNodes = currentNode.value.conditionNodes
   if (conditionNodes) {
     conditionNodes.splice(index, 1)
     if (conditionNodes.length == 1) {
@@ -161,5 +178,4 @@ const recursiveFindParentNode = (
   // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点并行节点(NodeType.PARALLEL_NODE) 继续查找
   emits('find:parentNode', nodeList, nodeType)
 }
-
 </script>

+ 15 - 30
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue

@@ -1,7 +1,7 @@
 <template>
   <div class="node-wrapper">
     <div class="node-container">
-      <div class="node-box" :class="{'node-config-error': !flowNode.showText}">
+      <div class="node-box" :class="{ 'node-config-error': !currentNode.showText }">
         <div class="node-title-container">
           <div class="node-title-icon user-task"><span class="iconfont icon-approve"></span></div>
           <input
@@ -18,16 +18,18 @@
           </div>
         </div>
         <div class="node-content" @click="openNodeConfig">
-          <div class="node-text" :title="flowNode.showText" v-if="flowNode.showText">
-            {{ flowNode.showText }}
+          <div class="node-text" :title="currentNode.showText" v-if="currentNode.showText">
+            {{ currentNode.showText }}
           </div>
-          <div class="node-text"  v-else>
+          <div class="node-text" v-else>
             {{ NODE_DEFAULT_TEXT.get(NodeType.USER_TASK_NODE) }}
           </div>
           <Icon icon="ep:arrow-right-bold" />
         </div>
         <div class="node-toolbar">
-          <div class="toolbar-icon"><Icon color="#0089ff"  icon="ep:circle-close-filled"  :size="18" @click="deleteNode" /></div>
+          <div class="toolbar-icon"
+            ><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
+          /></div>
         </div>
       </div>
       <!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
@@ -44,8 +46,7 @@
 <script setup lang="ts">
 import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT, NODE_DEFAULT_NAME } from '../consts'
 import NodeHandler from '../NodeHandler.vue'
-import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue';
-import { generateUUID } from '@/utils'
+import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'
 defineOptions({
   name: 'UserTaskNode'
 })
@@ -56,7 +57,7 @@ const props = defineProps({
   }
 })
 const emits = defineEmits<{
-  'update:modelValue': [node: SimpleFlowNode | undefined],
+  'update:flowNode': [node: SimpleFlowNode | undefined]
   'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
 }>()
 
@@ -65,7 +66,7 @@ const nodeSetting = ref()
 // 打开节点配置
 const openNodeConfig = () => {
   // 把当前节点传递给配置组件
-  nodeSetting.value.setCurrentNode(currentNode.value);
+  nodeSetting.value.setCurrentNode(currentNode.value)
   nodeSetting.value.open()
 }
 // 监控节点变化
@@ -80,7 +81,8 @@ const showInput = ref(false)
 // 节点名称输入框失去焦点
 const blurEvent = () => {
   showInput.value = false
-  currentNode.value.name = currentNode.value.name || NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string
+  currentNode.value.name =
+    currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string)
 }
 // 点击节点标题进行输入
 const clickEvent = () => {
@@ -88,32 +90,15 @@ const clickEvent = () => {
 }
 
 const deleteNode = () => {
-  emits('update:modelValue', currentNode.value.childNode)
+  emits('update:flowNode', currentNode.value.childNode)
 }
 
-const copyNode = () => {
-  const newCopyNode: SimpleFlowNode = {
-    id: generateUUID(),
-    name: currentNode.value.name,
-    showText: currentNode.value.showText,
-    type: currentNode.value.type,
-    // 审批节点配置
-    attributes: {
-      approveMethod: currentNode.value.attributes?.approveMethod,
-      candidateStrategy: currentNode.value.attributes?.candidateStrategy,
-      candidateParam: currentNode.value.attributes?.candidateParam
-    },
-    childNode: currentNode.value
-  }
-  currentNode.value = newCopyNode
-  emits('update:modelValue', currentNode.value)
-}
 // 查找可以驳回用户节点
 const findReturnTaskNodes = (
-  matchNodeList: SimpleFlowNode[], // 匹配的节点
+  matchNodeList: SimpleFlowNode[] // 匹配的节点
 ) => {
   // 从父节点查找
-  emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE);
+  emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE)
 }
 </script>
 <style lang="scss" scoped></style>

+ 0 - 165
src/views/bpm/simpleWorkflow/index1.vue

@@ -1,165 +0,0 @@
-<template>
-  <div>
-    <section class="dingflow-design">
-      <div class="sticky right-0 top-0 z-10 w-full flex justify-end bg-white p-2 pr-4">
-        <el-button type="primary" size="small" @click="test">保存(测试中,待完善)</el-button>
-      </div>
-      <div class="box-scale">
-        <div class="start-event-node">
-          <div class="start-event-node-circle">开始</div>
-        </div>
-        <div class="start-event-node-line"></div>
-        <nodeWrap v-model:nodeConfig="nodeConfig"/>
-       
-        <div class="end-event">
-          <div class="end-event-circle">结束</div>
-        </div>
-      </div>
-    </section>
-  </div>
-  <approverDrawer/>
-  <copyerDrawer />
-</template>
-<script lang="ts" setup>
-import nodeWrap from '@/components/SimpleProcessDesigner/src/nodeWrap.vue'
-import approverDrawer from '@/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue'
-import copyerDrawer from '@/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue'
-import { WorkFlowNode } from '@/components/SimpleProcessDesigner/src/consts'
-import { ref } from 'vue'
-import { updateBpmSimpleModel, getBpmSimpleModel } from '@/api/bpm/simple'
-import { getModel } from '@/api/bpm/model'
-import { getForm, FormVO } from '@/api/bpm/form'
-defineOptions({ name: 'SimpleWorkflowDesignEditor2' })
-const uid = getCurrentInstance().uid
-const router = useRouter() // 路由
-const { query } = useRoute() // 路由的查询
-const modelId = query.modelId
-const message = useMessage() // 国际化
-const nodeConfig = ref<WorkFlowNode>({
-  name: '发起人',
-  type: 0,
-  id: 'StartEvent_' + uid,
-  childNode: undefined,
-  attributes: undefined,
-  conditionNodes: []
-})
-// 默认的表单字段权限
-const defaultFieldsPermission: any[] = []
-const  formType = ref(20);
-provide('defaultFieldsPermission', defaultFieldsPermission)
-provide('formType', formType)
-const test = async () => {
-  if (!modelId) {
-    message.error('缺少模型 modelId 编号')
-    return
-  }
-
-  console.log('nodeConfig.value ', nodeConfig.value)
-
-  const data = {
-    id: modelId,
-    simpleModelBody: nodeConfig.value
-  }
-
-  const result = await updateBpmSimpleModel(data)
-  console.log('save the result is ', result)
-  if (result) {
-    message.success('修改成功')
-    close()
-  } else {
-    message.alert('修改失败')
-  }
-}
-const close = () => {
-  router.push({ path: '/bpm/manager/model' })
-}
-onMounted(async () => {
-  const bpmnModel = await getModel(modelId)
-  if (bpmnModel) {
-    formType.value = bpmnModel.formType
-    if (formType.value === 10) {
-      const bpmnForm = await getForm(bpmnModel.formId) as unknown as FormVO
-      const formFields = bpmnForm?.fields
-      if (formFields) {
-        formFields.forEach((fieldStr: string) => {
-          const { field, title } = JSON.parse(fieldStr)
-          defaultFieldsPermission.push({
-            field,
-            title,
-            permission: '2'
-          })
-        })
-      }
-      console.log('defaultFieldsPermissions', defaultFieldsPermission);
-    }
-  }
-  console.log('the modelId is ', modelId)
-  const result = await getBpmSimpleModel(modelId)
-  if (result) {
-    console.log('get the result is ', result)
-    nodeConfig.value = result
-  }
-})
-</script>
-<style>
-@import url('@/components/SimpleProcessDesigner/theme/workflow.css');
-
-.end-event {
-  display: flex;
-  direction: columns;
-  justify-content: center;
-  align-items: center;
-}
-
-.end-event-circle {
-  display: flex;
-  width: 40px;
-  height: 40px;
-  font-size: 14px;
-  color: #f8f8fa;
-  background-image: linear-gradient(-30deg, #bbbbc4, #d5d5de), linear-gradient(#bcbcc5, #bcbcc5);
-  border-radius: 50%;
-  justify-content: center;
-  align-items: center;
-}
-
-/* .start-event-node {
-  color: #191f2566;
-  text-align: left;
-  border-radius: 50%;
-} */
-.start-event-node {
-  display: flex;
-  direction: columns;
-  justify-content: center;
-  align-items: center;
-}
-
-.start-event-node-circle {
-  display: flex;
-  width: 40px;
-  height: 40px;
-  align-items: center;
-  justify-content: center;
-  font-size: 14px;
-  color: #f8f8fa;
-  background-image: linear-gradient(90deg, #ff6a00, #f78b3e), linear-gradient(#ff6a00, #ff6a00);
-  border-radius: 50%;
-}
-
-.start-event-node-line::before {
-  position: absolute;
-  inset: 0;
-  z-index: -1;
-  width: 2px;
-  height: 100%;
-  margin: auto;
-  background-color: #cacaca;
-  content: '';
-}
-
-.start-event-node-line {
-  position: relative;
-  padding: 20px 0 32px;
-}
-</style>