仿钉钉流程设计器- 审批节点配置新增拒绝处理方式
This commit is contained in:
parent
142b0f7203
commit
0e7dbbb04d
@ -1,37 +1,42 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="node-handler-wrapper">
|
<div class="node-handler-wrapper">
|
||||||
<div class="node-handler" v-if="props.showAdd">
|
<div class="node-handler" v-if="props.showAdd">
|
||||||
<el-popover trigger="hover" v-model:visible="popoverShow" placement="right-start" width="auto">
|
<el-popover
|
||||||
<div class="handler-item-wrapper">
|
trigger="hover"
|
||||||
<div class="handler-item" @click="addNode(NodeType.USER_TASK_NODE)">
|
v-model:visible="popoverShow"
|
||||||
<div class="approve handler-item-icon">
|
placement="right-start"
|
||||||
<span class="iconfont icon-approve icon-size"></span>
|
width="auto"
|
||||||
</div>
|
>
|
||||||
<div class="handler-item-text">审批人</div>
|
<div class="handler-item-wrapper">
|
||||||
</div>
|
<div class="handler-item" @click="addNode(NodeType.USER_TASK_NODE)">
|
||||||
<div class="handler-item" @click="addNode(NodeType.COPY_TASK_NODE)">
|
<div class="approve handler-item-icon">
|
||||||
<div class="handler-item-icon copy">
|
<span class="iconfont icon-approve icon-size"></span>
|
||||||
<span class="iconfont icon-size icon-copy"></span>
|
|
||||||
</div>
|
|
||||||
<div class="handler-item-text">抄送</div>
|
|
||||||
</div>
|
|
||||||
<div class="handler-item" @click="addNode(NodeType.EXCLUSIVE_NODE)">
|
|
||||||
<div class="handler-item-icon condition">
|
|
||||||
<span class="iconfont icon-size icon-exclusive"></span>
|
|
||||||
</div>
|
|
||||||
<div class="handler-item-text">条件分支</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="handler-item-text">审批人</div>
|
||||||
</div>
|
</div>
|
||||||
<template #reference>
|
<div class="handler-item" @click="addNode(NodeType.COPY_TASK_NODE)">
|
||||||
<div class="add-icon"><Icon icon="ep:plus" /></div>
|
<div class="handler-item-icon copy">
|
||||||
</template>
|
<span class="iconfont icon-size icon-copy"></span>
|
||||||
|
</div>
|
||||||
|
<div class="handler-item-text">抄送</div>
|
||||||
|
</div>
|
||||||
|
<div class="handler-item" @click="addNode(NodeType.EXCLUSIVE_NODE)">
|
||||||
|
<div class="handler-item-icon condition">
|
||||||
|
<span class="iconfont icon-size icon-exclusive"></span>
|
||||||
|
</div>
|
||||||
|
<div class="handler-item-text">条件分支</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<template #reference>
|
||||||
|
<div class="add-icon"><Icon icon="ep:plus" /></div>
|
||||||
|
</template>
|
||||||
</el-popover>
|
</el-popover>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_NAME, ApproveMethodType, CandidateStrategy } from './consts'
|
import { SimpleFlowNode, NodeType, NODE_DEFAULT_NAME, ApproveMethodType, RejectHandlerType, CandidateStrategy } from './consts'
|
||||||
import { generateUUID } from '@/utils'
|
import { generateUUID } from '@/utils'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'NodeHandler'
|
name: 'NodeHandler'
|
||||||
@ -71,6 +76,9 @@ const addNode = (type: number) => {
|
|||||||
// 超时处理
|
// 超时处理
|
||||||
timeoutHandler: {
|
timeoutHandler: {
|
||||||
enable: false
|
enable: false
|
||||||
|
},
|
||||||
|
rejectHandler: {
|
||||||
|
type: RejectHandlerType.TERMINATION
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
childNode: props.childNode
|
childNode: props.childNode
|
||||||
|
@ -1,58 +1,103 @@
|
|||||||
<template>
|
<template>
|
||||||
<!-- 开始节点 -->
|
<!-- 开始节点 -->
|
||||||
<StartEventNode
|
<StartEventNode
|
||||||
v-if="currentNode && currentNode.type === NodeType.START_EVENT_NODE"
|
v-if="currentNode && currentNode.type === NodeType.START_EVENT_NODE"
|
||||||
:flow-node ="currentNode"
|
:flow-node="currentNode"
|
||||||
@update:model-value="handleModelValueUpdate" />
|
@update:model-value="handleModelValueUpdate"
|
||||||
|
/>
|
||||||
<!-- 审批节点 -->
|
<!-- 审批节点 -->
|
||||||
<UserTaskNode
|
<UserTaskNode
|
||||||
v-if="currentNode && currentNode.type === NodeType.USER_TASK_NODE"
|
v-if="currentNode && currentNode.type === NodeType.USER_TASK_NODE"
|
||||||
:flow-node ="currentNode" @update:model-value="handleModelValueUpdate"/>
|
:flow-node="currentNode"
|
||||||
|
@update:model-value="handleModelValueUpdate"
|
||||||
|
@find:parent-node="findFromParentNode"
|
||||||
|
/>
|
||||||
<!-- 抄送节点 -->
|
<!-- 抄送节点 -->
|
||||||
<CopyTaskNode
|
<CopyTaskNode
|
||||||
v-if="currentNode && currentNode.type === NodeType.COPY_TASK_NODE"
|
v-if="currentNode && currentNode.type === NodeType.COPY_TASK_NODE"
|
||||||
:flow-node ="currentNode" @update:model-value="handleModelValueUpdate"/>
|
:flow-node="currentNode"
|
||||||
|
@update:model-value="handleModelValueUpdate"
|
||||||
|
/>
|
||||||
<!-- 条件节点 -->
|
<!-- 条件节点 -->
|
||||||
<ExclusiveNode
|
<ExclusiveNode
|
||||||
v-if="currentNode && currentNode.type === NodeType.EXCLUSIVE_NODE"
|
v-if="currentNode && currentNode.type === NodeType.EXCLUSIVE_NODE"
|
||||||
:flow-node ="currentNode" @update:model-value="handleModelValueUpdate"/>
|
:flow-node="currentNode"
|
||||||
|
@update:model-value="handleModelValueUpdate"
|
||||||
|
@find:parent-node="findFromParentNode"
|
||||||
|
/>
|
||||||
<!-- 递归显示孩子节点 -->
|
<!-- 递归显示孩子节点 -->
|
||||||
<ProcessNodeTree v-if="currentNode && currentNode.childNode" v-model:flow-node="currentNode.childNode"/>
|
<ProcessNodeTree
|
||||||
|
v-if="currentNode && currentNode.childNode"
|
||||||
|
v-model:flow-node="currentNode.childNode"
|
||||||
|
:parent-node= "currentNode"
|
||||||
|
@find:recursive-find-parent-node="recursiveFindParentNode"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 结束节点 -->
|
<!-- 结束节点 -->
|
||||||
<EndEventNode v-if="currentNode && currentNode.type === NodeType.END_EVENT_NODE"/>
|
<EndEventNode v-if="currentNode && currentNode.type === NodeType.END_EVENT_NODE" />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang='ts'>
|
<script setup lang="ts">
|
||||||
import StartEventNode from './nodes/StartEventNode.vue';
|
import StartEventNode from './nodes/StartEventNode.vue'
|
||||||
import EndEventNode from './nodes/EndEventNode.vue';
|
import EndEventNode from './nodes/EndEventNode.vue'
|
||||||
import UserTaskNode from './nodes/UserTaskNode.vue';
|
import UserTaskNode from './nodes/UserTaskNode.vue'
|
||||||
import CopyTaskNode from './nodes/CopyTaskNode.vue';
|
import CopyTaskNode from './nodes/CopyTaskNode.vue'
|
||||||
import ExclusiveNode from './nodes/ExclusiveNode.vue';
|
import ExclusiveNode from './nodes/ExclusiveNode.vue'
|
||||||
import { SimpleFlowNode, NodeType } from './consts';
|
import { SimpleFlowNode, NodeType } from './consts'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ProcessNodeTree'
|
name: 'ProcessNodeTree'
|
||||||
})
|
})
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
flowNode : {
|
parentNode: {
|
||||||
|
type: Object as () => SimpleFlowNode,
|
||||||
|
default: () => null
|
||||||
|
},
|
||||||
|
flowNode: {
|
||||||
type: Object as () => SimpleFlowNode,
|
type: Object as () => SimpleFlowNode,
|
||||||
default: () => null
|
default: () => null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emits = defineEmits(['update:flowNode'])
|
const emits = defineEmits<{
|
||||||
|
'update:flowNode',
|
||||||
|
'find:recursiveFindParentNode': [nodeList: SimpleFlowNode[], curentNode: SimpleFlowNode, nodeType: number]
|
||||||
|
}>()
|
||||||
|
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode);
|
|
||||||
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
|
|
||||||
// 重要:监控节点变化. 重新绘制节点
|
// 重要:监控节点变化. 重新绘制节点
|
||||||
watch(() => props.flowNode, (newValue) => {
|
watch(
|
||||||
currentNode.value = newValue;
|
() => props.flowNode,
|
||||||
}
|
(newValue) => {
|
||||||
);
|
currentNode.value = newValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const handleModelValueUpdate = (updateValue) => {
|
const handleModelValueUpdate = (updateValue) => {
|
||||||
console.log('Process Node Tree handleModelValueUpdate', updateValue)
|
console.log('Process Node Tree handleModelValueUpdate', updateValue)
|
||||||
emits('update:flowNode', updateValue);
|
emits('update:flowNode', updateValue)
|
||||||
|
}
|
||||||
|
|
||||||
|
const findFromParentNode = (
|
||||||
|
nodeList: SimpleFlowNode[],
|
||||||
|
nodeType: number
|
||||||
|
) => {
|
||||||
|
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归从父节点中查询匹配的节点
|
||||||
|
const recursiveFindParentNode = (
|
||||||
|
nodeList: SimpleFlowNode[],
|
||||||
|
findNode: SimpleFlowNode,
|
||||||
|
nodeType: number
|
||||||
|
) => {
|
||||||
|
if (!findNode || findNode.type === NodeType.START_EVENT_NODE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (findNode.type === nodeType) {
|
||||||
|
nodeList.push(findNode)
|
||||||
|
}
|
||||||
|
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang='scss' scoped>
|
<style lang="scss" scoped></style>
|
||||||
|
|
||||||
</style>
|
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="scale-container" :style="`transform: scale(${scaleValue / 100});`">
|
<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>
|
||||||
</div>
|
</div>
|
||||||
<Dialog v-model="errorDialogVisible" title="保存失败" width="400" :fullscreen="false">
|
<Dialog v-model="errorDialogVisible" title="保存失败" width="400" :fullscreen="false">
|
||||||
@ -55,6 +55,18 @@ const processNodeTree = ref<SimpleFlowNode>({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 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 errorDialogVisible = ref(false)
|
const errorDialogVisible = ref(false)
|
||||||
let errorNodes: SimpleFlowNode[] = []
|
let errorNodes: SimpleFlowNode[] = []
|
||||||
const saveSimpleFlowModel = async () => {
|
const saveSimpleFlowModel = async () => {
|
||||||
@ -148,6 +160,8 @@ onMounted(async () => {
|
|||||||
if (result) {
|
if (result) {
|
||||||
console.log('the result is ', result)
|
console.log('the result is ', result)
|
||||||
processNodeTree.value = result
|
processNodeTree.value = result
|
||||||
|
// rootNode.value = result
|
||||||
|
// childNode.value = result.childNode
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
</script>
|
</script>
|
||||||
|
@ -62,6 +62,17 @@ export enum TimeUnitType {
|
|||||||
DAY = 3
|
DAY = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum RejectHandlerType {
|
||||||
|
/**
|
||||||
|
* 结束流程
|
||||||
|
*/
|
||||||
|
TERMINATION = 1,
|
||||||
|
/**
|
||||||
|
* 驳回到指定节点
|
||||||
|
*/
|
||||||
|
RETURN_PRE_USER_TASK = 2
|
||||||
|
}
|
||||||
|
|
||||||
// 条件配置类型 ( 用于条件节点配置 )
|
// 条件配置类型 ( 用于条件节点配置 )
|
||||||
export enum ConditionConfigType {
|
export enum ConditionConfigType {
|
||||||
|
|
||||||
@ -186,12 +197,6 @@ NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人')
|
|||||||
NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人')
|
NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人')
|
||||||
NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件')
|
NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件')
|
||||||
|
|
||||||
export const TIME_UNIT_MAP = new Map<number,string>()
|
|
||||||
NODE_DEFAULT_NAME.set(1, 'M')
|
|
||||||
NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人')
|
|
||||||
NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件')
|
|
||||||
|
|
||||||
|
|
||||||
export const APPROVE_METHODS: DictDataVO [] = [
|
export const APPROVE_METHODS: DictDataVO [] = [
|
||||||
{ label: '单人审批', value: 1 },
|
{ label: '单人审批', value: 1 },
|
||||||
{ label: '多人会签(需所有审批人同意)', value: 2 },
|
{ label: '多人会签(需所有审批人同意)', value: 2 },
|
||||||
@ -216,6 +221,10 @@ export const TIMEOUT_HANDLER_ACTION_TYPES: DictDataVO [] = [
|
|||||||
{ label: '自动同意', value: 2 },
|
{ label: '自动同意', value: 2 },
|
||||||
{ label: '自动拒绝', value: 3 },
|
{ label: '自动拒绝', value: 3 },
|
||||||
]
|
]
|
||||||
|
export const REJECT_HANDLER_TYPES: DictDataVO [] = [
|
||||||
|
{ label: '结束流程', value: RejectHandlerType.TERMINATION },
|
||||||
|
{ label: '驳回到指定节点', value: RejectHandlerType.RETURN_PRE_USER_TASK }
|
||||||
|
]
|
||||||
|
|
||||||
// 比较运算符
|
// 比较运算符
|
||||||
export const COMPARISON_OPERATORS : DictDataVO = [
|
export const COMPARISON_OPERATORS : DictDataVO = [
|
||||||
|
@ -131,7 +131,6 @@
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item
|
<el-form-item
|
||||||
v-if="currentNode.attributes.candidateStrategy === CandidateStrategy.EXPRESSION"
|
v-if="currentNode.attributes.candidateStrategy === CandidateStrategy.EXPRESSION"
|
||||||
label="流程表达式"
|
label="流程表达式"
|
||||||
@ -144,7 +143,6 @@
|
|||||||
style="width: 100%"
|
style="width: 100%"
|
||||||
/>
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="审批方式" prop="approveMethod">
|
<el-form-item label="审批方式" prop="approveMethod">
|
||||||
<el-radio-group v-model="currentNode.attributes.approveMethod">
|
<el-radio-group v-model="currentNode.attributes.approveMethod">
|
||||||
<div class="flex-col">
|
<div class="flex-col">
|
||||||
@ -163,8 +161,35 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-divider content-position="left">审批人拒绝时</el-divider>
|
||||||
|
<el-form-item label="处理方式" prop="rejectHandler">
|
||||||
|
<el-radio-group v-model="currentNode.attributes.rejectHandler.type" @change="rejectHandlerTypeChange">
|
||||||
|
<el-radio
|
||||||
|
:border="true"
|
||||||
|
v-for="item in REJECT_HANDLER_TYPES"
|
||||||
|
:key="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="超时处理" prop="timeoutHandlerEnable">
|
<el-form-item
|
||||||
|
v-if="currentNode.attributes.rejectHandler.type == RejectHandlerType.RETURN_PRE_USER_TASK"
|
||||||
|
label="驳回节点"
|
||||||
|
prop="rejectHandlerNode"
|
||||||
|
>
|
||||||
|
<el-select v-model="currentNode.attributes.rejectHandler.returnNodeId" clearable style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item in returnTaskList"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.name"
|
||||||
|
:value="item.id"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-divider content-position="left">审批人超时未处理时</el-divider>
|
||||||
|
<el-form-item label="启用开关" prop="timeoutHandlerEnable">
|
||||||
<el-switch
|
<el-switch
|
||||||
v-model="currentNode.attributes.timeoutHandler.enable"
|
v-model="currentNode.attributes.timeoutHandler.enable"
|
||||||
active-text="开启"
|
active-text="开启"
|
||||||
@ -281,8 +306,10 @@ import {
|
|||||||
NodeType,
|
NodeType,
|
||||||
ApproveMethodType,
|
ApproveMethodType,
|
||||||
TimeUnitType,
|
TimeUnitType,
|
||||||
|
RejectHandlerType,
|
||||||
TIMEOUT_HANDLER_ACTION_TYPES,
|
TIMEOUT_HANDLER_ACTION_TYPES,
|
||||||
TIME_UNIT_TYPES,
|
TIME_UNIT_TYPES,
|
||||||
|
REJECT_HANDLER_TYPES,
|
||||||
NODE_DEFAULT_NAME
|
NODE_DEFAULT_NAME
|
||||||
} from '../consts'
|
} from '../consts'
|
||||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||||
@ -303,6 +330,9 @@ const props = defineProps({
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const emits = defineEmits<{
|
||||||
|
'find:returnTaskNodes': [nodeList: SimpleFlowNode[]]
|
||||||
|
}>()
|
||||||
|
|
||||||
const notAllowedMultiApprovers = ref(false)
|
const notAllowedMultiApprovers = ref(false)
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
@ -316,7 +346,7 @@ const deptTreeOptions = inject('deptTree') // 部门树
|
|||||||
const formType = inject('formType') // 表单类型
|
const formType = inject('formType') // 表单类型
|
||||||
const formFields = inject<Ref<string[]>>('formFields')
|
const formFields = inject<Ref<string[]>>('formFields')
|
||||||
const candidateParamArray = ref<any[]>([])
|
const candidateParamArray = ref<any[]>([])
|
||||||
|
const returnTaskList = ref<SimpleFlowNode[]>([])
|
||||||
const closeDrawer = () => {
|
const closeDrawer = () => {
|
||||||
settingVisible.value = false
|
settingVisible.value = false
|
||||||
}
|
}
|
||||||
@ -443,6 +473,10 @@ const setCurrentNode = (node: SimpleFlowNode) => {
|
|||||||
timeDuration.value = parseInt(parseTime)
|
timeDuration.value = parseInt(parseTime)
|
||||||
timeUnit.value = convertTimeUnit(parseTimeUnit)
|
timeUnit.value = convertTimeUnit(parseTimeUnit)
|
||||||
}
|
}
|
||||||
|
// 查找可以驳回的用户节点
|
||||||
|
const matchNodeList = [];
|
||||||
|
emits('find:returnTaskNodes', matchNodeList);
|
||||||
|
returnTaskList.value = matchNodeList;
|
||||||
}
|
}
|
||||||
|
|
||||||
defineExpose({ open, setCurrentNode }) // 暴露方法给父组件
|
defineExpose({ open, setCurrentNode }) // 暴露方法给父组件
|
||||||
@ -483,6 +517,12 @@ const blurEvent = () => {
|
|||||||
currentNode.value.name =
|
currentNode.value.name =
|
||||||
currentNode.value.name || (NODE_DEFAULT_NAME.get(NodeType.USER_TASK_NODE) as string)
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
// 默认 6小时
|
// 默认 6小时
|
||||||
const timeDuration = ref(6)
|
const timeDuration = ref(6)
|
||||||
const timeUnit = ref(TimeUnitType.HOUR)
|
const timeUnit = ref(TimeUnitType.HOUR)
|
||||||
|
@ -57,7 +57,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<ConditionNodeConfig :node-index="index" :condition-node="item" :ref="item.id" />
|
<ConditionNodeConfig :node-index="index" :condition-node="item" :ref="item.id" />
|
||||||
<!-- 递归显示子节点 -->
|
<!-- 递归显示子节点 -->
|
||||||
<ProcessNodeTree v-if="item && item.childNode" v-model:flow-node="item.childNode" />
|
<ProcessNodeTree
|
||||||
|
v-if="item && item.childNode"
|
||||||
|
:parent-node="item"
|
||||||
|
v-model:flow-node="item.childNode"
|
||||||
|
@find:recursive-find-parent-node="recursiveFindParentNode"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
||||||
@ -76,6 +80,10 @@ defineOptions({
|
|||||||
name: 'ExclusiveNode'
|
name: 'ExclusiveNode'
|
||||||
})
|
})
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
// parentNode : {
|
||||||
|
// type: Object as () => SimpleFlowNode,
|
||||||
|
// required: true
|
||||||
|
// },
|
||||||
flowNode: {
|
flowNode: {
|
||||||
type: Object as () => SimpleFlowNode,
|
type: Object as () => SimpleFlowNode,
|
||||||
required: true
|
required: true
|
||||||
@ -83,7 +91,9 @@ const props = defineProps({
|
|||||||
})
|
})
|
||||||
// 定义事件,更新父组件
|
// 定义事件,更新父组件
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
'update:modelValue': [node: SimpleFlowNode | undefined]
|
'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 currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
@ -156,7 +166,21 @@ const moveNode = (index: number, to: number) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
// 递归从父节点中查询匹配的节点
|
||||||
|
const recursiveFindParentNode = (
|
||||||
|
nodeList: SimpleFlowNode[],
|
||||||
|
node: SimpleFlowNode,
|
||||||
|
nodeType: number
|
||||||
|
) => {
|
||||||
|
if (!node || node.type === NodeType.START_EVENT_NODE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (node.type === nodeType) {
|
||||||
|
nodeList.push(node)
|
||||||
|
}
|
||||||
|
// 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.EXCLUSIVE_NODE) 继续查找
|
||||||
|
emits('find:parentNode', nodeList, nodeType)
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
v-if="currentNode"
|
v-if="currentNode"
|
||||||
ref="nodeSetting"
|
ref="nodeSetting"
|
||||||
:flow-node="currentNode"
|
:flow-node="currentNode"
|
||||||
|
@find:return-task-nodes="findReturnTaskNodes"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
@ -55,7 +56,8 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
'update:modelValue': [node: SimpleFlowNode | undefined]
|
'update:modelValue': [node: SimpleFlowNode | undefined],
|
||||||
|
'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
@ -106,5 +108,12 @@ const copyNode = () => {
|
|||||||
currentNode.value = newCopyNode
|
currentNode.value = newCopyNode
|
||||||
emits('update:modelValue', currentNode.value)
|
emits('update:modelValue', currentNode.value)
|
||||||
}
|
}
|
||||||
|
// 查找可以驳回用户节点
|
||||||
|
const findReturnTaskNodes = (
|
||||||
|
matchNodeList: SimpleFlowNode[], // 匹配的节点
|
||||||
|
) => {
|
||||||
|
// 从父节点查找
|
||||||
|
emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
Loading…
Reference in New Issue
Block a user