dengzedong
5 天以前 f9b459a3fefd5fab0ee8e19268adb9d9eadab2a7
提交 | 用户 | 时间
3e359e 1 <template>
H 2   <div class="branch-node-wrapper">
3     <div class="branch-node-container">
4       <div
5         v-if="readonly"
6         class="branch-node-readonly"
7         :class="`${useTaskStatusClass(currentNode?.activityStatus)}`"
8       >
9         <span class="iconfont icon-inclusive icon-size inclusive"></span>
10       </div>
11       <el-button v-else class="branch-node-add" color="#345da2" @click="addCondition" plain
12         >添加条件</el-button
13       >
14       <div
15         class="branch-node-item"
16         v-for="(item, index) in currentNode.conditionNodes"
17         :key="index"
18       >
19         <template v-if="index == 0">
20           <div class="branch-line-first-top"> </div>
21           <div class="branch-line-first-bottom"></div>
22         </template>
23         <template v-if="index + 1 == currentNode.conditionNodes?.length">
24           <div class="branch-line-last-top"></div>
25           <div class="branch-line-last-bottom"></div>
26         </template>
27         <div class="node-wrapper">
28           <div class="node-container">
29             <div
30               class="node-box"
31               :class="[
32                 { 'node-config-error': !item.showText },
33                 `${useTaskStatusClass(item.activityStatus)}`
34               ]"
35             >
36               <div class="branch-node-title-container">
37                 <div v-if="showInputs[index]">
38                   <input
39                     type="text"
40                     class="editable-title-input"
41                     @blur="blurEvent(index)"
42                     v-mountedFocus
43                     v-model="item.name"
44                   />
45                 </div>
46                 <div v-else class="branch-title" @click="clickEvent(index)"> {{ item.name }} </div>
47               </div>
48               <div class="branch-node-content" @click="conditionNodeConfig(item.id)">
49                 <div class="branch-node-text" :title="item.showText" v-if="item.showText">
50                   {{ item.showText }}
51                 </div>
52                 <div class="branch-node-text" v-else>
53                   {{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
54                 </div>
55               </div>
56               <div
57                 class="node-toolbar"
58                 v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length"
59               >
60                 <div class="toolbar-icon">
61                   <Icon
62                     color="#0089ff"
63                     icon="ep:circle-close-filled"
64                     :size="18"
65                     @click="deleteCondition(index)"
66                   />
67                 </div>
68               </div>
69               <div
70                 class="branch-node-move move-node-left"
71                 v-if="!readonly && index != 0 && index + 1 !== currentNode.conditionNodes?.length"
72                 @click="moveNode(index, -1)"
73               >
74                 <Icon icon="ep:arrow-left" />
75               </div>
76
77               <div
78                 class="branch-node-move move-node-right"
79                 v-if="
80                   !readonly &&
81                   currentNode.conditionNodes &&
82                   index < currentNode.conditionNodes.length - 2
83                 "
84                 @click="moveNode(index, 1)"
85               >
86                 <Icon icon="ep:arrow-right" />
87               </div>
88             </div>
89             <NodeHandler v-model:child-node="item.childNode" :current-node="item" />
90           </div>
91         </div>
92         <ConditionNodeConfig :node-index="index" :condition-node="item" :ref="item.id" />
93         <!-- 递归显示子节点  -->
94         <ProcessNodeTree
95           v-if="item && item.childNode"
96           :parent-node="item"
97           v-model:flow-node="item.childNode"
98           @find:recursive-find-parent-node="recursiveFindParentNode"
99         />
100       </div>
101     </div>
102     <NodeHandler
103       v-if="currentNode"
104       v-model:child-node="currentNode.childNode"
105       :current-node="currentNode"
106     />
107   </div>
108 </template>
109
110 <script setup lang="ts">
111 import NodeHandler from '../NodeHandler.vue'
112 import ProcessNodeTree from '../ProcessNodeTree.vue'
113 import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
114 import { useTaskStatusClass } from '../node'
115 import { getDefaultInclusiveConditionNodeName } from '../utils'
116 import { generateUUID } from '@/utils'
117 import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
118 const { proxy } = getCurrentInstance() as any
119 defineOptions({
120   name: 'InclusiveNode'
121 })
122 const props = defineProps({
123   flowNode: {
124     type: Object as () => SimpleFlowNode,
125     required: true
126   }
127 })
128 // 定义事件,更新父组件
129 const emits = defineEmits<{
130   'update:modelValue': [node: SimpleFlowNode | undefined]
131   'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number]
132   'find:recursiveFindParentNode': [
133     nodeList: SimpleFlowNode[],
134     curentNode: SimpleFlowNode,
135     nodeType: number
136   ]
137 }>()
138 // 是否只读
139 const readonly = inject<Boolean>('readonly')
140
141 const currentNode = ref<SimpleFlowNode>(props.flowNode)
142
143 watch(
144   () => props.flowNode,
145   (newValue) => {
146     currentNode.value = newValue
147   }
148 )
149
150 const showInputs = ref<boolean[]>([])
151 // 失去焦点
152 const blurEvent = (index: number) => {
153   showInputs.value[index] = false
154   const conditionNode = currentNode.value.conditionNodes?.at(index) as SimpleFlowNode
155   conditionNode.name =
156     conditionNode.name || getDefaultInclusiveConditionNodeName(index, conditionNode.defaultFlow)
157 }
158
159 // 点击条件名称
160 const clickEvent = (index: number) => {
161   showInputs.value[index] = true
162 }
163
164 const conditionNodeConfig = (nodeId: string) => {
165   if (readonly) {
166     return
167   }
168   const conditionNode = proxy.$refs[nodeId][0]
169   conditionNode.open()
170 }
171
172 // 新增条件
173 const addCondition = () => {
174   const conditionNodes = currentNode.value.conditionNodes
175   if (conditionNodes) {
176     const len = conditionNodes.length
177     let lastIndex = len - 1
178     const conditionData: SimpleFlowNode = {
179       id: 'Flow_' + generateUUID(),
180       name: '包容条件' + len,
181       showText: '',
182       type: NodeType.CONDITION_NODE,
183       childNode: undefined,
184       conditionNodes: [],
185       conditionType: 1,
186       defaultFlow: false
187     }
188     conditionNodes.splice(lastIndex, 0, conditionData)
189   }
190 }
191
192 // 删除条件
193 const deleteCondition = (index: number) => {
194   const conditionNodes = currentNode.value.conditionNodes
195   if (conditionNodes) {
196     conditionNodes.splice(index, 1)
197     if (conditionNodes.length == 1) {
198       const childNode = currentNode.value.childNode
199       // 更新此节点为后续孩子节点
200       emits('update:modelValue', childNode)
201     }
202   }
203 }
204
205 // 移动节点
206 const moveNode = (index: number, to: number) => {
207   // -1 :向左  1: 向右
208   if (currentNode.value.conditionNodes) {
209     currentNode.value.conditionNodes[index] = currentNode.value.conditionNodes.splice(
210       index + to,
211       1,
212       currentNode.value.conditionNodes[index]
213     )[0]
214   }
215 }
216 // 递归从父节点中查询匹配的节点
217 const recursiveFindParentNode = (
218   nodeList: SimpleFlowNode[],
219   node: SimpleFlowNode,
220   nodeType: number
221 ) => {
222   if (!node || node.type === NodeType.START_USER_NODE) {
223     return
224   }
225   if (node.type === nodeType) {
226     nodeList.push(node)
227   }
228   // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.INCLUSIVE_BRANCH_NODE) 继续查找
229   emits('find:parentNode', nodeList, nodeType)
230 }
231 </script>
232
233 <style lang="scss" scoped></style>