init
This commit is contained in:
762
src/views/workflow/process/ProcessTree.vue
Normal file
762
src/views/workflow/process/ProcessTree.vue
Normal file
@@ -0,0 +1,762 @@
|
||||
<script setup>
|
||||
import RootNode from './nodes/RootNode.vue'
|
||||
import END from './nodes/ProcessEndNode.vue'
|
||||
import APPROVAL from './nodes/ApprovalNode.vue'
|
||||
import CcNode from './nodes/CcNode.vue'
|
||||
import ConcurrentNode from './nodes/ConcurrentNode.vue'
|
||||
import ConditionNode from './nodes/ConditionNode.vue'
|
||||
import EmptyNode from './nodes/EmptyNode.vue'
|
||||
import TriggerNode from './nodes/TriggerNode.vue'
|
||||
import MergeNode from './nodes/MergeNode.vue'
|
||||
import DelayNode from './nodes/DelayNode.vue'
|
||||
import AddBranchNode from './nodes/AddBranchNode.vue'
|
||||
|
||||
import {defineExpose, h, render, ref} from 'vue'
|
||||
import DefaultProps from "./DefaultNodeProps"
|
||||
import {ElMessage, ElMessageBox} from 'element-plus'
|
||||
import {useProcessStore} from '@/stores/processStore.js'
|
||||
|
||||
const processStore = useProcessStore()
|
||||
const emit = defineEmits()
|
||||
|
||||
const props = defineProps({
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'design'
|
||||
},
|
||||
idName: {
|
||||
type: String,
|
||||
default: 'processTree'
|
||||
}
|
||||
})
|
||||
|
||||
const valid = ref(true)
|
||||
|
||||
let vNode = {}
|
||||
|
||||
const init = () => {
|
||||
processStore.init()
|
||||
initMapping(processStore.getProcess())
|
||||
// 定义类名(可忽略)
|
||||
let processTrees = getDomTree(h, "admin")
|
||||
vNode = []
|
||||
const dom = document.getElementById(props.idName);
|
||||
vNode = h('div', {class: {'_root': true}}, processTrees);
|
||||
render(vNode, dom)
|
||||
}
|
||||
|
||||
// 初始化map集合,以便数据整理
|
||||
const initMapping = (node) => {
|
||||
console.log("初始化数据", node)
|
||||
node.forEach(nodeItem => {
|
||||
processStore.nodeMap.set(nodeItem.id, nodeItem)
|
||||
processStore.parentMap.set(nodeItem.parentId, nodeItem)
|
||||
})
|
||||
}
|
||||
|
||||
const initHeaderBgc = (node) => {
|
||||
if (node.props && props.mode === 'preview') {
|
||||
let headerBgc = '#ff943e'
|
||||
if (processStore.runningList.value.includes(node.id)) {
|
||||
headerBgc = '#1e90ff'
|
||||
} else if (processStore.endList.value.includes(node.id)) {
|
||||
headerBgc = '#20b2aa'
|
||||
} else if (processStore.noTakeList.value.includes(node.id)) {
|
||||
headerBgc = '#909399'
|
||||
} else if (processStore.refuseList.value.includes(node.id)) {
|
||||
headerBgc = '#f56c6c'
|
||||
} else if (processStore.passList.value.includes(node.id)) {
|
||||
headerBgc = '#ff943e'
|
||||
}
|
||||
node.props.headerBgc = headerBgc
|
||||
}
|
||||
}
|
||||
|
||||
// 获取demo的树形结构
|
||||
const getDomTree = (h, id) => {
|
||||
let node = processStore.parentMap.get(id)
|
||||
if (!(node && node.id)) {
|
||||
return []
|
||||
}
|
||||
initHeaderBgc(node)
|
||||
if (isPrimaryNode(node)) {
|
||||
//普通业务节点
|
||||
let childDoms = getDomTree(h, node.id)
|
||||
decodeAppendDom(h, node, childDoms)
|
||||
return [h('div', {'class': {'primary-node': true}}, childDoms)];
|
||||
} else if (isBranchNode(node)) {
|
||||
let index = 0;
|
||||
//遍历分支节点,包含并行及条件节点
|
||||
let branchItems = node.branchs.map(branchNode => {
|
||||
//处理每个分支内子节点
|
||||
toMapping(branchNode)
|
||||
let childDoms = getDomTree(h, branchNode.id)
|
||||
decodeAppendDom(h, branchNode, childDoms, {level: index + 1, size: node.branchs.length})
|
||||
//插入4条横线,遮挡掉条件节点左右半边线条
|
||||
insertCoverLine(h, index, childDoms, node.branchs)
|
||||
//遍历子分支尾部分支
|
||||
index++;
|
||||
return h('div', {'class': {'branch-node-item': true}}, childDoms);
|
||||
})
|
||||
//插入添加分支/条件的按钮
|
||||
branchItems.unshift(h('div', {'class': {'add-branch-btn': true}}, [
|
||||
h(AddBranchNode, {
|
||||
mode: props.mode,
|
||||
size: 'small', round: true,
|
||||
value: `添加${isConditionNodes(node) ? '条件' : '分支'}`,
|
||||
onAddBranch: () => addBranchNode(node),
|
||||
}, [])
|
||||
]));
|
||||
let bchDom = [h('div', {'class': {'branch-node': true}}, branchItems)]
|
||||
//继续遍历分支后的节点
|
||||
let afterChildDoms = getDomTree(h, node.id)
|
||||
return [h('div', {}, [bchDom, afterChildDoms])]
|
||||
} else if (isMergeNode(node)) {
|
||||
//空节点,存在于分支尾部
|
||||
let childDoms = getDomTree(h, node.id)
|
||||
decodeAppendDom(h, node, childDoms)
|
||||
return [h('div', {'class': {'empty-node': true}}, childDoms)];
|
||||
} else if (isEmptyNode(node)) {
|
||||
//空节点,存在于分支尾部
|
||||
let childDoms = getDomTree(h, node.id)
|
||||
decodeAppendDom(h, node, childDoms)
|
||||
return [h('div', {'class': {'empty-node': true}}, childDoms)];
|
||||
} else if (isEndNode(node)) {
|
||||
let childDoms = getDomTree(h, node.id)
|
||||
decodeAppendEndDom(h, node, childDoms)
|
||||
return [h('div', {class: 'process-end'}, childDoms)];
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const decodeAppendEndDom = (h, node, dom, props = {}) => {
|
||||
props.config = node
|
||||
dom.unshift(h(END, {
|
||||
id: node.id,
|
||||
key: node.id,
|
||||
}, []))
|
||||
}
|
||||
|
||||
//解码渲染的时候插入dom到同级
|
||||
const decodeAppendDom = (h, node, dom, nodeProps = {}) => {
|
||||
nodeProps.config = node
|
||||
dom.unshift(h(getNodeType(node), {
|
||||
mode: props.mode,
|
||||
...nodeProps,
|
||||
id: node.id,
|
||||
key: node.id,
|
||||
//定义事件,插入节点,删除节点,选中节点,复制/移动
|
||||
'onInsertNode': type => insertNode(type, node),
|
||||
'onDelNode': () => delNode(node),
|
||||
'onSelected': () => selectNode(node),
|
||||
'onCopy': () => copyBranch(node),
|
||||
'onLeftMove': () => branchMove(node, -1),
|
||||
'onRightMove': () => branchMove(node, 1)
|
||||
}, []))
|
||||
}
|
||||
|
||||
const getNodeType = (node) => {
|
||||
switch (node.type) {
|
||||
case "ROOT":
|
||||
return RootNode;
|
||||
case "APPROVAL":
|
||||
return APPROVAL;
|
||||
case "CC":
|
||||
return CcNode;
|
||||
case "CONDITION":
|
||||
return ConditionNode;
|
||||
case "CONCURRENT":
|
||||
return ConcurrentNode;
|
||||
case "DELAY":
|
||||
return DelayNode;
|
||||
case "MERGE":
|
||||
return MergeNode;
|
||||
case "EMPTY":
|
||||
return EmptyNode;
|
||||
case "TRIGGER":
|
||||
return TriggerNode;
|
||||
}
|
||||
}
|
||||
|
||||
//id映射到map,用来向上遍历
|
||||
const toMapping = (node) => {
|
||||
if (node && node.id) {
|
||||
let newNode = {
|
||||
...node
|
||||
}
|
||||
newNode.children = []
|
||||
processStore.nodeMap.set(newNode.id, newNode)
|
||||
}
|
||||
}
|
||||
|
||||
// 新增线条
|
||||
const insertCoverLine = (h, index, doms, branchs) => {
|
||||
if (index === 0) {
|
||||
//最左侧分支
|
||||
doms.unshift(h('div', {'class': {'line-top-left': true}}, []))
|
||||
doms.unshift(h('div', {'class': {'line-bot-left': true}}, []))
|
||||
}
|
||||
if (index === branchs.length - 1) {
|
||||
//最右侧分支
|
||||
doms.unshift(h('div', {'class': {'line-top-right': true}}, []))
|
||||
doms.unshift(h('div', {'class': {'line-bot-right': true}}, []))
|
||||
}
|
||||
}
|
||||
|
||||
const copyBranch = (node) => {
|
||||
let parentNode = processStore.nodeMap.get(node.parentId)
|
||||
let branchNode = deepCopy(node)
|
||||
branchNode.name = branchNode.name + '-copy'
|
||||
forEachNode(parentNode, branchNode, (parent, node) => {
|
||||
node.id = getRandomId()
|
||||
node.parentId = parent.id
|
||||
})
|
||||
parentNode.branchs.splice(parentNode.branchs.indexOf(node), 0, branchNode)
|
||||
init()
|
||||
}
|
||||
|
||||
//移动分支节点
|
||||
const branchMove = (node, offset) => {
|
||||
let parentNode = processStore.nodeMap.get(node.parentId)
|
||||
let index = parentNode.branchs.indexOf(node)
|
||||
let branch = parentNode.branchs[index + offset]
|
||||
parentNode.branchs[index + offset] = parentNode.branchs[index]
|
||||
parentNode.branchs[index] = branch
|
||||
init()
|
||||
}
|
||||
|
||||
//判断是否为主要业务节点
|
||||
const isPrimaryNode = (node) => {
|
||||
return node &&
|
||||
(node.type === 'ROOT' || node.type === 'APPROVAL'
|
||||
|| node.type === 'CC' || node.type === 'DELAY'
|
||||
|| node.type === 'TRIGGER');
|
||||
}
|
||||
|
||||
//是否为分支节点
|
||||
const isBranchNode = (node) => {
|
||||
return node && (node.type === 'CONDITIONS' || node.type === 'CONCURRENTS');
|
||||
}
|
||||
|
||||
|
||||
//是否为空节点
|
||||
const isEmptyNode = (node) => {
|
||||
return node && (node.type === 'EMPTY')
|
||||
}
|
||||
const isEndNode = (node) => {
|
||||
return node && (node.type === 'END')
|
||||
}
|
||||
//是否为空节点
|
||||
const isMergeNode = (node) => {
|
||||
return node && (node.type === 'MERGE')
|
||||
}
|
||||
//是分支节点
|
||||
const isConditionNodes = (node) => {
|
||||
return node.type === 'CONDITIONS';
|
||||
}
|
||||
const isConditionNode = (node) => {
|
||||
return node.type === 'CONDITION';
|
||||
}
|
||||
//是分支节点
|
||||
const isBranchSubNode = (node) => {
|
||||
return node && (node.type === 'CONDITION' || node.type === 'CONCURRENT');
|
||||
}
|
||||
//时候并行节点
|
||||
const isConcurrentNodes = (node) => {
|
||||
return node.type === 'CONCURRENTS'
|
||||
}
|
||||
//时候并行节点
|
||||
const isConcurrentNode = (node) => {
|
||||
return node.type === 'CONCURRENT'
|
||||
}
|
||||
|
||||
//新增一个节点id
|
||||
const getRandomId = () => {
|
||||
let d = new Date().getTime()
|
||||
// x 是 0-9 或 a-f 范围内的一个32位十六进制数
|
||||
let id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
let r = (d + Math.random() * 16) % 16 | 0
|
||||
d = Math.floor(d / 16)
|
||||
return (c === 'x' ? r : (r & 0x3 | 0x8)).toString(16)
|
||||
})
|
||||
return 'node_' + id
|
||||
}
|
||||
//选中一个节点
|
||||
const selectNode = (node) => {
|
||||
processStore.setSelectedNode(node)
|
||||
if (!isConcurrentNode(node)) {
|
||||
emit('selectedNode', node)
|
||||
}
|
||||
}
|
||||
|
||||
//处理节点插入逻辑
|
||||
const insertNode = (type, parentNode) => {
|
||||
//插入新节点
|
||||
let id = getRandomId();
|
||||
updateParentId(id, parentNode.id)
|
||||
let children = {
|
||||
id: id,
|
||||
parentId: parentNode.id,
|
||||
type: type,
|
||||
}
|
||||
switch (type) {
|
||||
case 'APPROVAL':
|
||||
insertApprovalNode(children);
|
||||
break;
|
||||
case 'CC':
|
||||
insertCcNode(children);
|
||||
break;
|
||||
case 'DELAY':
|
||||
insertDelayNode(children);
|
||||
break;
|
||||
case 'TRIGGER':
|
||||
insertTriggerNode(children);
|
||||
break;
|
||||
case 'CONDITIONS':
|
||||
insertConditionsNode(children);
|
||||
break;
|
||||
case 'CONCURRENTS':
|
||||
insertConcurrentsNode(children);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
console.log('开始刷新')
|
||||
init()
|
||||
}
|
||||
/**
|
||||
* 更新父id
|
||||
* @param newId
|
||||
* @param oldId
|
||||
*/
|
||||
const updateParentId = (newId, oldId) => {
|
||||
processStore.getProcess().map(node => {
|
||||
if (node.parentId === oldId) {
|
||||
node.parentId = newId
|
||||
}
|
||||
})
|
||||
}
|
||||
/**
|
||||
* 审批人
|
||||
* @param parentNode
|
||||
*/
|
||||
const deepCopy = (obj) => {
|
||||
return JSON.parse(JSON.stringify(obj))
|
||||
}
|
||||
const insertApprovalNode = (parentNode) => {
|
||||
let node = {
|
||||
...parentNode,
|
||||
name: "审批人",
|
||||
props: deepCopy(DefaultProps.APPROVAL_PROPS)
|
||||
}
|
||||
processStore.addProcess(node)
|
||||
}
|
||||
/**
|
||||
* 抄送人
|
||||
* @param node
|
||||
*/
|
||||
const insertCcNode = (node) => {
|
||||
let newNode = {
|
||||
...node,
|
||||
name: "抄送人",
|
||||
props: deepCopy(DefaultProps.CC_PROPS)
|
||||
}
|
||||
processStore.addProcess(newNode)
|
||||
}
|
||||
/**
|
||||
* 延时处理
|
||||
* @param node
|
||||
*/
|
||||
const insertDelayNode = (node) => {
|
||||
let newNode = {
|
||||
...node,
|
||||
name: "延时处理",
|
||||
props: deepCopy(DefaultProps.DELAY_PROPS)
|
||||
}
|
||||
processStore.addProcess(newNode)
|
||||
}
|
||||
/**
|
||||
* 触发器
|
||||
* @param node
|
||||
*/
|
||||
const insertTriggerNode = (node) => {
|
||||
let newNode = {
|
||||
...node,
|
||||
name: "触发器",
|
||||
props: deepCopy(DefaultProps.TRIGGER_PROPS)
|
||||
}
|
||||
processStore.addProcess(newNode)
|
||||
}
|
||||
/**
|
||||
* 新增条件分支F
|
||||
* @param node
|
||||
*/
|
||||
const insertConditionsNode = (node) => {
|
||||
let newNode = {
|
||||
...node,
|
||||
name: "条件分支",
|
||||
branchs: [
|
||||
{
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "CONDITION",
|
||||
props: deepCopy(DefaultProps.CONDITION_PROPS),
|
||||
name: "条件1",
|
||||
children: {}
|
||||
}, {
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "CONDITION",
|
||||
props: deepCopy(DefaultProps.CONDITION_PROPS),
|
||||
name: "条件2",
|
||||
children: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
processStore.addProcess(newNode)
|
||||
let emptyNode = {
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "EMPTY"
|
||||
}
|
||||
updateParentId(emptyNode.id, newNode.id)
|
||||
processStore.addProcess(emptyNode)
|
||||
}
|
||||
/**
|
||||
* 新增同步运行节点
|
||||
* @param node
|
||||
*/
|
||||
const insertConcurrentsNode = (node) => {
|
||||
let newNode = {
|
||||
...node,
|
||||
name: "并行分支",
|
||||
branchs: [
|
||||
{
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "CONCURRENT",
|
||||
props: deepCopy(DefaultProps.CONDITION_PROPS),
|
||||
name: "分支1",
|
||||
children: {}
|
||||
}, {
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "CONCURRENT",
|
||||
props: deepCopy(DefaultProps.CONDITION_PROPS),
|
||||
name: "分支2",
|
||||
children: {}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
processStore.addProcess(newNode)
|
||||
let emptyNode = {
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
type: "MERGE"
|
||||
}
|
||||
updateParentId(emptyNode.id, newNode.id)
|
||||
processStore.addProcess(emptyNode)
|
||||
}
|
||||
|
||||
const addBranchNode = (node) => {
|
||||
if (node.branchs.length < 8) {
|
||||
node.branchs.push({
|
||||
id: getRandomId(),
|
||||
parentId: node.id,
|
||||
name: (isConditionNodes(node) ? '条件' : '分支') + (node.branchs.length + 1),
|
||||
props: isConditionNodes(node) ? deepCopy(DefaultProps.CONDITION_PROPS) : {},
|
||||
type: isConditionNodes(node) ? "CONDITION" : "CONCURRENT",
|
||||
children: {}
|
||||
})
|
||||
init()
|
||||
} else {
|
||||
ElMessage.warning("最多只能添加 8 项😥")
|
||||
}
|
||||
}
|
||||
|
||||
//删除当前节点
|
||||
const delNode = (node) => {
|
||||
//获取该节点的父节点
|
||||
let parentNode = processStore.nodeMap.get(node.parentId)
|
||||
if (parentNode) {
|
||||
if (isBranchNode(parentNode)) {
|
||||
delBranchNode(parentNode, node)
|
||||
} else {
|
||||
delNodeInDomChange(node.id, parentNode.id)
|
||||
}
|
||||
init()
|
||||
} else {
|
||||
ElMessage.warning("出现错误,找不到上级节点😥")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 从dom中删除
|
||||
* @param delId
|
||||
* @param parentId
|
||||
*/
|
||||
const delNodeInDomChange = (delId, parentId) => {
|
||||
updateParentId(parentId, delId)
|
||||
let delNode = processStore.nodeMap.get(delId)
|
||||
processStore.delProcess(delNode)
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
//删除分支
|
||||
const delBranchNode = (parentNode, node) => {
|
||||
let sunNode = processStore.parentMap.get(node.id)
|
||||
//判断当前节点下有没有字节点,有则需要提示
|
||||
if (sunNode) {
|
||||
ElMessageBox.confirm('当前分支下有子节点,是否继续?', '提示', {
|
||||
confirmButtonText: '确 定',
|
||||
cancelButtonText: '取 消',
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
//确认后进行子节点的操作
|
||||
delBranchSunNode(sunNode.id)
|
||||
doDelBranchNode(parentNode, node)
|
||||
})
|
||||
} else {
|
||||
// 没有直接开始删除
|
||||
doDelBranchNode(parentNode, node)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//删除分支节点
|
||||
const doDelBranchNode = (parentNode, node) => {
|
||||
//判断当前分时是否为2
|
||||
if (parentNode.branchs.length === 2) {
|
||||
let nodeList = [...parentNode.branchs]
|
||||
nodeList.splice(nodeList.indexOf(node), 1)
|
||||
//查看另外一个分支上是否有节点
|
||||
let sunNode = processStore.parentMap.get(nodeList[0].id)
|
||||
//有则需要放到主分支上
|
||||
if (sunNode) {
|
||||
//更改分支上第一个节点的父id
|
||||
updateParentId(parentNode.parentId, sunNode.parentId)
|
||||
//找到最后一个节点
|
||||
let lastNode = getLastBranchNode(sunNode.id)
|
||||
let emptyNode = processStore.parentMap.get(parentNode.id)
|
||||
//更新空节点下的第一个节点的id为当前分支最后一个节点
|
||||
updateParentId(lastNode.id, emptyNode.id)
|
||||
//删除分支的主节点
|
||||
delNodeInDom(parentNode)
|
||||
//删除分支的空节点
|
||||
delNodeInDom(emptyNode)
|
||||
} else {
|
||||
//没有则直接删除
|
||||
delEntireBranch(parentNode)
|
||||
}
|
||||
} else {
|
||||
parentNode.branchs.splice(parentNode.branchs.indexOf(node), 1)
|
||||
}
|
||||
}
|
||||
|
||||
//获取最后一个节点
|
||||
const getLastBranchNode = (id) => {
|
||||
let node = processStore.parentMap.get(id)
|
||||
if (node) {
|
||||
return getLastBranchNode(node.id)
|
||||
} else {
|
||||
return processStore.nodeMap.get(id)
|
||||
}
|
||||
}
|
||||
|
||||
const delEntireBranch = (node) => {
|
||||
//删除分支节点和空节点
|
||||
let emptyNode = processStore.parentMap.get(node.id)
|
||||
delNodeInDomChange(node.id, node.parentId)
|
||||
delNodeInDomChange(emptyNode.id, emptyNode.parentId)
|
||||
}
|
||||
|
||||
|
||||
const delNodeInDom = (delNode) => {
|
||||
processStore.delProcess(delNode)
|
||||
init()
|
||||
}
|
||||
|
||||
|
||||
//删除分支的子节点
|
||||
const delBranchSunNode = (id) => {
|
||||
let node = processStore.parentMap.get(id)
|
||||
delNodeInDomChange(id)
|
||||
if (node) {
|
||||
delBranchSunNode(node.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//给定一个起始节点,遍历内部所有节点
|
||||
const forEachNode = (parent, node, callback) => {
|
||||
if (isBranchNode(node)) {
|
||||
callback(parent, node)
|
||||
forEachNode(node, node.children, callback)
|
||||
node.branchs.map(branchNode => {
|
||||
callback(node, branchNode)
|
||||
forEachNode(branchNode, branchNode.children, callback)
|
||||
})
|
||||
} else if (isPrimaryNode(node) || isEmptyNode(node) || isBranchSubNode(node)) {
|
||||
callback(parent, node)
|
||||
forEachNode(node, node.children, callback)
|
||||
}
|
||||
}
|
||||
|
||||
const validateProcess = () => {
|
||||
valid.value = true
|
||||
let err = []
|
||||
validate(err, processStore.getProcess())
|
||||
return err
|
||||
}
|
||||
|
||||
const validateNode = (err, node, nodeMap) => {
|
||||
let component = nodeMap.get(node.id)
|
||||
if (component !== undefined) {
|
||||
valid.value = component.exposed.validate(err)
|
||||
}
|
||||
}
|
||||
|
||||
const validateNodeList = ['APPROVAL', 'CC', 'CONDITION', 'DELAY', 'TRIGGER']
|
||||
|
||||
const analysisNode = (vNode, nodeMap) => {
|
||||
let children = vNode.children
|
||||
if (!children || children.length === 0) {
|
||||
return
|
||||
}
|
||||
for (let child of children) {
|
||||
let node = processStore.nodeMap.get(child.key)
|
||||
if (node !== undefined && node && validateNodeList.includes(node.type)) {
|
||||
nodeMap.set(node.id, child.component)
|
||||
} else {
|
||||
analysisNode(child, nodeMap)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//校验所有节点设置
|
||||
const validate = (err, nodeList) => {
|
||||
const nodeMap = new Map()
|
||||
analysisNode(vNode, nodeMap)
|
||||
nodeList.map(node => {
|
||||
if (isPrimaryNode(node)) {
|
||||
//校验条件节点
|
||||
validateNode(err, node, nodeMap)
|
||||
} else if (isBranchNode(node)) {
|
||||
node.branchs.map(branchNode => {
|
||||
//校验条件节点
|
||||
validateNode(err, branchNode, nodeMap)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
init,
|
||||
validateProcess
|
||||
})
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<style lang="scss">
|
||||
._root {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.process-end {
|
||||
width: 60px;
|
||||
margin: 0 auto;
|
||||
margin-bottom: 20px;
|
||||
border-radius: 15px;
|
||||
text-align: center;
|
||||
padding: 5px 10px;
|
||||
font-size: small;
|
||||
color: #747474;
|
||||
background-color: #f2f2f2;
|
||||
box-shadow: 0 0 10px 0 #bcbcbc;
|
||||
}
|
||||
|
||||
|
||||
.primary-node {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.branch-node {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
/*border-top: 2px solid #cccccc;
|
||||
border-bottom: 2px solid #cccccc;*/
|
||||
}
|
||||
|
||||
.branch-node-item {
|
||||
position: relative;
|
||||
display: flex;
|
||||
//background: #f5f6f6;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
border-top: 2px solid #cccccc;
|
||||
border-bottom: 2px solid #cccccc;
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: calc(50% - 1px);
|
||||
margin: auto;
|
||||
width: 2px;
|
||||
height: 100%;
|
||||
background-color: #CACACA;
|
||||
}
|
||||
|
||||
.line-top-left, .line-top-right, .line-bot-left, .line-bot-right {
|
||||
position: absolute;
|
||||
width: 50%;
|
||||
height: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.line-top-left {
|
||||
top: -2px;
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.line-top-right {
|
||||
top: -2px;
|
||||
right: -1px;
|
||||
}
|
||||
|
||||
.line-bot-left {
|
||||
bottom: -2px;
|
||||
left: -1px;
|
||||
}
|
||||
|
||||
.line-bot-right {
|
||||
bottom: -2px;
|
||||
right: -1px;
|
||||
}
|
||||
}
|
||||
|
||||
.add-branch-btn {
|
||||
position: absolute;
|
||||
width: 80px;
|
||||
|
||||
.add-branch-btn-el {
|
||||
z-index: 999;
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
}
|
||||
}
|
||||
|
||||
.empty-node {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user