123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- <template>
- <div class="branch-node-wrapper">
- <div class="branch-node-container">
- <div
- v-if="readonly"
- class="branch-node-readonly"
- :class="`${useTaskStatusClass(currentNode?.activityStatus)}`"
- >
- <span class="iconfont icon-inclusive icon-size inclusive"></span>
- </div>
- <el-button v-else class="branch-node-add" color="#345da2" @click="addCondition" plain
- >添加条件</el-button
- >
- <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>
- </template>
- <template v-if="index + 1 == currentNode.conditionNodes?.length">
- <div class="branch-line-last-top"></div>
- <div class="branch-line-last-bottom"></div>
- </template>
- <div class="node-wrapper">
- <div class="node-container">
- <div
- class="node-box"
- :class="[
- { 'node-config-error': !item.showText },
- `${useTaskStatusClass(item.activityStatus)}`
- ]"
- >
- <div class="branch-node-title-container">
- <div v-if="!readonly && showInputs[index]">
- <input
- type="text"
- class="editable-title-input"
- @blur="blurEvent(index)"
- v-mountedFocus
- v-model="item.name"
- />
- </div>
- <div v-else class="branch-title" @click="clickEvent(index)"> {{ item.name }} </div>
- </div>
- <div class="branch-node-content" @click="conditionNodeConfig(item.id)">
- <div class="branch-node-text" :title="item.showText" v-if="item.showText">
- {{ item.showText }}
- </div>
- <div class="branch-node-text" v-else>
- {{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
- </div>
- </div>
- <div
- class="node-toolbar"
- v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length"
- >
- <div class="toolbar-icon">
- <Icon
- color="#0089ff"
- icon="ep:circle-close-filled"
- :size="18"
- @click="deleteCondition(index)"
- />
- </div>
- </div>
- <div
- class="branch-node-move move-node-left"
- v-if="!readonly && index != 0 && index + 1 !== currentNode.conditionNodes?.length"
- @click="moveNode(index, -1)"
- >
- <Icon icon="ep:arrow-left" />
- </div>
- <div
- class="branch-node-move move-node-right"
- v-if="
- !readonly &&
- currentNode.conditionNodes &&
- index < currentNode.conditionNodes.length - 2
- "
- @click="moveNode(index, 1)"
- >
- <Icon icon="ep:arrow-right" />
- </div>
- </div>
- <NodeHandler v-model:child-node="item.childNode" :current-node="item" />
- </div>
- </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"
- />
- </div>
- </div>
- <NodeHandler
- v-if="currentNode"
- v-model:child-node="currentNode.childNode"
- :current-node="currentNode"
- />
- </div>
- </template>
- <script setup lang="ts">
- import NodeHandler from '../NodeHandler.vue'
- import ProcessNodeTree from '../ProcessNodeTree.vue'
- import {
- SimpleFlowNode,
- NodeType,
- ConditionType,
- DEFAULT_CONDITION_GROUP_VALUE,
- NODE_DEFAULT_TEXT
- } from '../consts'
- import { useTaskStatusClass } from '../node'
- import { getDefaultInclusiveConditionNodeName } from '../utils'
- import { generateUUID } from '@/utils'
- import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
- import { cloneDeep } from 'lodash-es'
- const { proxy } = getCurrentInstance() as any
- defineOptions({
- name: 'InclusiveNode'
- })
- const props = defineProps({
- flowNode: {
- type: Object as () => SimpleFlowNode,
- required: true
- }
- })
- // 定义事件,更新父组件
- const emits = defineEmits<{
- 'update:modelValue': [node: SimpleFlowNode | undefined]
- 'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: number]
- 'find:recursiveFindParentNode': [
- nodeList: SimpleFlowNode[],
- curentNode: SimpleFlowNode,
- nodeType: number
- ]
- }>()
- // 是否只读
- const readonly = inject<Boolean>('readonly')
- const currentNode = ref<SimpleFlowNode>(props.flowNode)
- 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 ||
- getDefaultInclusiveConditionNodeName(index, conditionNode.conditionSetting?.defaultFlow)
- }
- // 点击条件名称
- const clickEvent = (index: number) => {
- showInputs.value[index] = true
- }
- const conditionNodeConfig = (nodeId: string) => {
- if (readonly) {
- return
- }
- const conditionNode = proxy.$refs[nodeId][0]
- conditionNode.open()
- }
- // 新增条件
- const addCondition = () => {
- const conditionNodes = currentNode.value.conditionNodes
- if (conditionNodes) {
- const len = conditionNodes.length
- let lastIndex = len - 1
- const conditionData: SimpleFlowNode = {
- id: 'Flow_' + generateUUID(),
- name: '包容条件' + len,
- showText: '',
- type: NodeType.CONDITION_NODE,
- childNode: undefined,
- conditionNodes: [],
- conditionSetting: {
- defaultFlow: false,
- conditionType: ConditionType.RULE,
- conditionGroups: cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
- }
- }
- conditionNodes.splice(lastIndex, 0, conditionData)
- }
- }
- // 删除条件
- const deleteCondition = (index: number) => {
- const conditionNodes = currentNode.value.conditionNodes
- if (conditionNodes) {
- conditionNodes.splice(index, 1)
- if (conditionNodes.length == 1) {
- const childNode = currentNode.value.childNode
- // 更新此节点为后续孩子节点
- emits('update:modelValue', childNode)
- }
- }
- }
- // 移动节点
- 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]
- }
- }
- // 递归从父节点中查询匹配的节点
- const recursiveFindParentNode = (
- nodeList: SimpleFlowNode[],
- node: SimpleFlowNode,
- nodeType: number
- ) => {
- if (!node || node.type === NodeType.START_USER_NODE) {
- return
- }
- if (node.type === nodeType) {
- nodeList.push(node)
- }
- // 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.INCLUSIVE_BRANCH_NODE) 继续查找
- emits('find:parentNode', nodeList, nodeType)
- }
- </script>
- <style lang="scss" scoped></style>
|