审批超时延迟器延迟跳转任意指定的节点
parent
b2ddefe4a0
commit
b9ddd1eaa6
|
|
@ -75,6 +75,7 @@
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
// 导入各种流程节点组件
|
||||||
import StartUserNode from './nodes/StartUserNode.vue'
|
import StartUserNode from './nodes/StartUserNode.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'
|
||||||
|
|
@ -85,30 +86,43 @@ import InclusiveNode from './nodes/InclusiveNode.vue'
|
||||||
import DelayTimerNode from './nodes/DelayTimerNode.vue'
|
import DelayTimerNode from './nodes/DelayTimerNode.vue'
|
||||||
import RouterNode from './nodes/RouterNode.vue'
|
import RouterNode from './nodes/RouterNode.vue'
|
||||||
import TriggerNode from './nodes/TriggerNode.vue'
|
import TriggerNode from './nodes/TriggerNode.vue'
|
||||||
|
|
||||||
|
// 导入流程节点相关的类型定义和工具函数
|
||||||
import { SimpleFlowNode, NodeType } from './consts'
|
import { SimpleFlowNode, NodeType } from './consts'
|
||||||
import { useWatchNode } from './node'
|
import { useWatchNode } from './node'
|
||||||
|
|
||||||
|
// 定义组件名称
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'ProcessNodeTree'
|
name: 'ProcessNodeTree'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 定义组件的 props
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
// 父节点对象
|
||||||
parentNode: {
|
parentNode: {
|
||||||
type: Object as () => SimpleFlowNode,
|
type: Object as () => SimpleFlowNode,
|
||||||
default: () => null
|
default: () => null
|
||||||
},
|
},
|
||||||
|
// 当前流程节点对象
|
||||||
flowNode: {
|
flowNode: {
|
||||||
type: Object as () => SimpleFlowNode,
|
type: Object as () => SimpleFlowNode,
|
||||||
default: () => null
|
default: () => null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 定义组件的事件
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
|
// 更新流程节点的事件
|
||||||
'update:flowNode': [node: SimpleFlowNode | undefined]
|
'update:flowNode': [node: SimpleFlowNode | undefined]
|
||||||
|
// 递归查找父节点的事件
|
||||||
'find:recursiveFindParentNode': [
|
'find:recursiveFindParentNode': [
|
||||||
nodeList: SimpleFlowNode[],
|
nodeList: SimpleFlowNode[], // 节点列表
|
||||||
curentNode: SimpleFlowNode,
|
curentNode: SimpleFlowNode, // 当前节点
|
||||||
nodeType: number
|
nodeType: number // 节点类型
|
||||||
]
|
]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
// 使用 useWatchNode hook 监听节点变化
|
||||||
const currentNode = useWatchNode(props)
|
const currentNode = useWatchNode(props)
|
||||||
|
|
||||||
// 用于删除节点
|
// 用于删除节点
|
||||||
|
|
@ -116,27 +130,33 @@ const handleModelValueUpdate = (updateValue) => {
|
||||||
emits('update:flowNode', updateValue)
|
emits('update:flowNode', updateValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从父节点中查找指定类型的节点
|
||||||
const findFromParentNode = (nodeList: SimpleFlowNode[], nodeType: number) => {
|
const findFromParentNode = (nodeList: SimpleFlowNode[], nodeType: number) => {
|
||||||
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归从父节点中查询匹配的节点
|
// 递归查找父节点中匹配指定类型的节点
|
||||||
const recursiveFindParentNode = (
|
const recursiveFindParentNode = (
|
||||||
nodeList: SimpleFlowNode[],
|
nodeList: SimpleFlowNode[], // 存储找到的节点列表
|
||||||
findNode: SimpleFlowNode,
|
findNode: SimpleFlowNode, // 要查找的节点
|
||||||
nodeType: number
|
nodeType: number // 要查找的节点类型
|
||||||
) => {
|
) => {
|
||||||
|
// 如果节点不存在,直接返回
|
||||||
if (!findNode) {
|
if (!findNode) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果是起始用户节点,将其加入列表并返回
|
||||||
if (findNode.type === NodeType.START_USER_NODE) {
|
if (findNode.type === NodeType.START_USER_NODE) {
|
||||||
nodeList.push(findNode)
|
nodeList.push(findNode)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 如果节点类型匹配,将节点加入列表
|
||||||
if (findNode.type === nodeType) {
|
if (findNode.type === nodeType) {
|
||||||
nodeList.push(findNode)
|
nodeList.push(findNode)
|
||||||
}
|
}
|
||||||
|
// 继续向上递归查找
|
||||||
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
emits('find:recursiveFindParentNode', nodeList, props.parentNode, nodeType)
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -233,6 +233,8 @@ export type TimeoutHandler = {
|
||||||
timeDuration?: string
|
timeDuration?: string
|
||||||
// 执行动作是自动提醒, 最大提醒次数
|
// 执行动作是自动提醒, 最大提醒次数
|
||||||
maxRemindCount?: number
|
maxRemindCount?: number
|
||||||
|
// 执行动作是自动跳转时,跳转的节点ID
|
||||||
|
returnNodeId?: string
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -291,6 +293,16 @@ export enum RejectHandlerType {
|
||||||
*/
|
*/
|
||||||
RETURN_USER_TASK = 2
|
RETURN_USER_TASK = 2
|
||||||
}
|
}
|
||||||
|
export enum DelaySettingType {
|
||||||
|
/**
|
||||||
|
* 默认开启
|
||||||
|
*/
|
||||||
|
FINISH_PROCESS = 1,
|
||||||
|
/**
|
||||||
|
* 延迟器指定节点
|
||||||
|
*/
|
||||||
|
RETURN_USER_TASK = 2
|
||||||
|
}
|
||||||
// 用户任务超时处理类型枚举
|
// 用户任务超时处理类型枚举
|
||||||
export enum TimeoutHandlerType {
|
export enum TimeoutHandlerType {
|
||||||
/**
|
/**
|
||||||
|
|
@ -304,7 +316,11 @@ export enum TimeoutHandlerType {
|
||||||
/**
|
/**
|
||||||
* 自动拒绝
|
* 自动拒绝
|
||||||
*/
|
*/
|
||||||
REJECT = 3
|
REJECT = 3,
|
||||||
|
/**
|
||||||
|
* 自动跳转
|
||||||
|
*/
|
||||||
|
AUTO_JUMP = 4
|
||||||
}
|
}
|
||||||
// 用户任务的审批人为空时,处理类型枚举
|
// 用户任务的审批人为空时,处理类型枚举
|
||||||
export enum AssignEmptyHandlerType {
|
export enum AssignEmptyHandlerType {
|
||||||
|
|
@ -570,7 +586,8 @@ export const TIME_UNIT_TYPES: DictDataVO[] = [
|
||||||
export const TIMEOUT_HANDLER_TYPES: DictDataVO[] = [
|
export const TIMEOUT_HANDLER_TYPES: DictDataVO[] = [
|
||||||
{ label: '自动提醒', value: 1 },
|
{ label: '自动提醒', value: 1 },
|
||||||
{ label: '自动同意', value: 2 },
|
{ label: '自动同意', value: 2 },
|
||||||
{ label: '自动拒绝', value: 3 }
|
{ label: '自动拒绝', value: 3 },
|
||||||
|
{ label: '自动跳转', value: 4 }
|
||||||
]
|
]
|
||||||
export const REJECT_HANDLER_TYPES: DictDataVO[] = [
|
export const REJECT_HANDLER_TYPES: DictDataVO[] = [
|
||||||
{ label: '终止流程', value: RejectHandlerType.FINISH_PROCESS },
|
{ label: '终止流程', value: RejectHandlerType.FINISH_PROCESS },
|
||||||
|
|
@ -700,6 +717,8 @@ export type DelaySetting = {
|
||||||
delayType: number
|
delayType: number
|
||||||
// 延迟时间表达式
|
// 延迟时间表达式
|
||||||
delayTime: string
|
delayTime: string
|
||||||
|
autoJumpEnable?: boolean
|
||||||
|
returnNodeId?: string
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 延迟类型
|
* 延迟类型
|
||||||
|
|
|
||||||
|
|
@ -156,6 +156,7 @@ export type UserTaskFormType = {
|
||||||
assignStartUserHandlerType?: AssignStartUserHandlerType
|
assignStartUserHandlerType?: AssignStartUserHandlerType
|
||||||
timeDuration?: number
|
timeDuration?: number
|
||||||
maxRemindCount?: number
|
maxRemindCount?: number
|
||||||
|
timeoutReturnNodeId?: string
|
||||||
buttonsSetting: any[]
|
buttonsSetting: any[]
|
||||||
taskCreateListenerEnable?: boolean
|
taskCreateListenerEnable?: boolean
|
||||||
taskCreateListenerPath?: string
|
taskCreateListenerPath?: string
|
||||||
|
|
|
||||||
|
|
@ -65,6 +65,36 @@
|
||||||
/>
|
/>
|
||||||
<el-text>后进入下一节点</el-text>
|
<el-text>后进入下一节点</el-text>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-divider content-position="left">延迟结束后</el-divider>
|
||||||
|
<el-form-item label="自动跳转" prop="autoJumpEnable">
|
||||||
|
<el-switch
|
||||||
|
v-model="configForm.autoJumpEnable"
|
||||||
|
active-text="开启"
|
||||||
|
inactive-text="关闭"
|
||||||
|
@change="autoJumpChange"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item
|
||||||
|
v-if="!configForm.autoJumpEnable"
|
||||||
|
label="跳转节点"
|
||||||
|
prop="returnNodeId"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
filterable
|
||||||
|
v-model="configForm.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-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
|
|
@ -104,19 +134,44 @@ const currentNode = useWatchNode(props)
|
||||||
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.DELAY_TIMER_NODE)
|
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.DELAY_TIMER_NODE)
|
||||||
// 抄送人表单配置
|
// 抄送人表单配置
|
||||||
const formRef = ref() // 表单 Ref
|
const formRef = ref() // 表单 Ref
|
||||||
|
|
||||||
|
const emits = defineEmits<{
|
||||||
|
'find:return-task-nodes': [nodeList: SimpleFlowNode[]]
|
||||||
|
}>()
|
||||||
|
|
||||||
// 表单校验规则
|
// 表单校验规则
|
||||||
const formRules = reactive({
|
const formRules = reactive({
|
||||||
delayType: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
|
delayType: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
|
||||||
timeDuration: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
|
timeDuration: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
|
||||||
dateTime: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }]
|
dateTime: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
|
||||||
|
returnNodeId: [{ required: true, message: '跳转节点不能为空', trigger: 'change' }]
|
||||||
})
|
})
|
||||||
// 配置表单数据
|
// 配置表单数据
|
||||||
const configForm = ref({
|
const configForm = ref({
|
||||||
delayType: DelayTypeEnum.FIXED_TIME_DURATION,
|
delayType: DelayTypeEnum.FIXED_TIME_DURATION,
|
||||||
timeDuration: 1,
|
timeDuration: 1,
|
||||||
timeUnit: TimeUnitType.HOUR,
|
timeUnit: TimeUnitType.HOUR,
|
||||||
dateTime: ''
|
dateTime: '',
|
||||||
|
autoJumpEnable: true, // 默认开启自动跳转
|
||||||
|
returnNodeId: undefined as string | undefined // Change type to string | undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// 可选的跳转节点列表
|
||||||
|
const returnTaskList = ref<SimpleFlowNode[]>([])
|
||||||
|
|
||||||
|
// 自动跳转开关改变
|
||||||
|
const autoJumpChange = () => {
|
||||||
|
if (!configForm.value.autoJumpEnable) {
|
||||||
|
// 当关闭自动跳转时,获取可跳转的节点列表
|
||||||
|
const matchNodeList: SimpleFlowNode[] = []
|
||||||
|
emits('find:return-task-nodes', matchNodeList)
|
||||||
|
returnTaskList.value = matchNodeList
|
||||||
|
} else {
|
||||||
|
// 当开启自动跳转时,清空跳转节点
|
||||||
|
configForm.value.returnNodeId = undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 保存配置
|
// 保存配置
|
||||||
const saveConfig = async () => {
|
const saveConfig = async () => {
|
||||||
if (!formRef) return false
|
if (!formRef) return false
|
||||||
|
|
@ -129,13 +184,17 @@ const saveConfig = async () => {
|
||||||
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
|
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
|
||||||
currentNode.value.delaySetting = {
|
currentNode.value.delaySetting = {
|
||||||
delayType: configForm.value.delayType,
|
delayType: configForm.value.delayType,
|
||||||
delayTime: getIsoTimeDuration()
|
delayTime: getIsoTimeDuration(),
|
||||||
|
autoJumpEnable: configForm.value.autoJumpEnable,
|
||||||
|
returnNodeId: !configForm.value.autoJumpEnable ? configForm.value.returnNodeId || undefined : undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (configForm.value.delayType === DelayTypeEnum.FIXED_DATE_TIME) {
|
if (configForm.value.delayType === DelayTypeEnum.FIXED_DATE_TIME) {
|
||||||
currentNode.value.delaySetting = {
|
currentNode.value.delaySetting = {
|
||||||
delayType: configForm.value.delayType,
|
delayType: configForm.value.delayType,
|
||||||
delayTime: configForm.value.dateTime
|
delayTime: configForm.value.dateTime,
|
||||||
|
autoJumpEnable: configForm.value.autoJumpEnable,
|
||||||
|
returnNodeId: !configForm.value.autoJumpEnable ? configForm.value.returnNodeId || undefined : undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
settingVisible.value = false
|
settingVisible.value = false
|
||||||
|
|
@ -169,6 +228,16 @@ const showDelayTimerNodeConfig = (node: SimpleFlowNode) => {
|
||||||
nodeName.value = node.name
|
nodeName.value = node.name
|
||||||
if (node.delaySetting) {
|
if (node.delaySetting) {
|
||||||
configForm.value.delayType = node.delaySetting.delayType
|
configForm.value.delayType = node.delaySetting.delayType
|
||||||
|
configForm.value.autoJumpEnable = node.delaySetting.autoJumpEnable ?? true
|
||||||
|
|
||||||
|
// 先获取可跳转节点列表
|
||||||
|
const matchNodeList: SimpleFlowNode[] = []
|
||||||
|
emits('find:return-task-nodes', matchNodeList)
|
||||||
|
returnTaskList.value = matchNodeList
|
||||||
|
|
||||||
|
// 再设置选中的节点
|
||||||
|
configForm.value.returnNodeId = node.delaySetting.returnNodeId
|
||||||
|
|
||||||
// 固定时长
|
// 固定时长
|
||||||
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
|
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
|
||||||
const strTimeDuration = node.delaySetting.delayTime
|
const strTimeDuration = node.delaySetting.delayTime
|
||||||
|
|
|
||||||
|
|
@ -347,6 +347,25 @@
|
||||||
>
|
>
|
||||||
<el-input-number v-model="configForm.maxRemindCount" :min="1" :max="10" />
|
<el-input-number v-model="configForm.maxRemindCount" :min="1" :max="10" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<el-form-item
|
||||||
|
v-if="configForm.timeoutHandlerEnable && configForm.timeoutHandlerType === TimeoutHandlerType.AUTO_JUMP"
|
||||||
|
label="跳转节点"
|
||||||
|
prop="timeoutReturnNodeId"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
filterable
|
||||||
|
v-model="configForm.timeoutReturnNodeId"
|
||||||
|
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>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-divider content-position="left">{{ nodeTypeName }}人为空时</el-divider>
|
<el-divider content-position="left">{{ nodeTypeName }}人为空时</el-divider>
|
||||||
|
|
@ -729,7 +748,9 @@ const saveConfig = async () => {
|
||||||
enable: configForm.value.timeoutHandlerEnable!,
|
enable: configForm.value.timeoutHandlerEnable!,
|
||||||
type: cTimeoutType.value,
|
type: cTimeoutType.value,
|
||||||
timeDuration: isoTimeDuration.value,
|
timeDuration: isoTimeDuration.value,
|
||||||
maxRemindCount: cTimeoutMaxRemindCount.value
|
maxRemindCount: cTimeoutMaxRemindCount.value,
|
||||||
|
returnNodeId: configForm.value.timeoutHandlerType === TimeoutHandlerType.AUTO_JUMP ?
|
||||||
|
configForm.value.timeoutReturnNodeId : undefined
|
||||||
}
|
}
|
||||||
// 设置审批人为空时
|
// 设置审批人为空时
|
||||||
currentNode.value.assignEmptyHandler = {
|
currentNode.value.assignEmptyHandler = {
|
||||||
|
|
@ -803,15 +824,24 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
|
||||||
returnTaskList.value = matchNodeList
|
returnTaskList.value = matchNodeList
|
||||||
// 2.4 设置审批超时处理
|
// 2.4 设置审批超时处理
|
||||||
configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable
|
configForm.value.timeoutHandlerEnable = node.timeoutHandler?.enable
|
||||||
if (node.timeoutHandler?.enable && node.timeoutHandler?.timeDuration) {
|
if (node.timeoutHandler?.enable) {
|
||||||
|
configForm.value.timeoutHandlerType = node.timeoutHandler.type
|
||||||
|
configForm.value.timeoutReturnNodeId = node.timeoutHandler.returnNodeId
|
||||||
|
|
||||||
|
if (node.timeoutHandler.timeDuration) {
|
||||||
const strTimeDuration = node.timeoutHandler.timeDuration
|
const strTimeDuration = node.timeoutHandler.timeDuration
|
||||||
let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
|
let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
|
||||||
let parseTimeUnit = strTimeDuration.slice(strTimeDuration.length - 1)
|
let parseTimeUnit = strTimeDuration.slice(strTimeDuration.length - 1)
|
||||||
configForm.value.timeDuration = parseInt(parseTime)
|
configForm.value.timeDuration = parseInt(parseTime)
|
||||||
timeUnit.value = convertTimeUnit(parseTimeUnit)
|
timeUnit.value = convertTimeUnit(parseTimeUnit)
|
||||||
}
|
}
|
||||||
configForm.value.timeoutHandlerType = node.timeoutHandler?.type
|
|
||||||
configForm.value.maxRemindCount = node.timeoutHandler?.maxRemindCount
|
if (node.timeoutHandler.type === TimeoutHandlerType.AUTO_JUMP) {
|
||||||
|
const matchNodeList: SimpleFlowNode[] = []
|
||||||
|
emits('find:returnTaskNodes', matchNodeList)
|
||||||
|
returnTaskList.value = matchNodeList
|
||||||
|
}
|
||||||
|
}
|
||||||
// 2.5 设置审批人为空时
|
// 2.5 设置审批人为空时
|
||||||
configForm.value.assignEmptyHandlerType = node.assignEmptyHandler?.type
|
configForm.value.assignEmptyHandlerType = node.assignEmptyHandler?.type
|
||||||
configForm.value.assignEmptyHandlerUserIds = node.assignEmptyHandler?.userIds
|
configForm.value.assignEmptyHandlerUserIds = node.assignEmptyHandler?.userIds
|
||||||
|
|
@ -902,6 +932,11 @@ function useTimeoutHandler() {
|
||||||
const timeoutHandlerTypeChanged = () => {
|
const timeoutHandlerTypeChanged = () => {
|
||||||
if (configForm.value.timeoutHandlerType === TimeoutHandlerType.REMINDER) {
|
if (configForm.value.timeoutHandlerType === TimeoutHandlerType.REMINDER) {
|
||||||
configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1
|
configForm.value.maxRemindCount = 1 // 超时提醒次数,默认为1
|
||||||
|
} else if (configForm.value.timeoutHandlerType === TimeoutHandlerType.AUTO_JUMP) {
|
||||||
|
// 获取可跳转节点列表
|
||||||
|
const matchNodeList: SimpleFlowNode[] = []
|
||||||
|
emits('find:returnTaskNodes', matchNodeList)
|
||||||
|
returnTaskList.value = matchNodeList
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@
|
||||||
v-if="!readonly && currentNode"
|
v-if="!readonly && currentNode"
|
||||||
ref="nodeSetting"
|
ref="nodeSetting"
|
||||||
:flow-node="currentNode"
|
:flow-node="currentNode"
|
||||||
|
@find:return-task-nodes="findReturnTaskNodes"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -65,11 +66,16 @@ const props = defineProps({
|
||||||
flowNode: {
|
flowNode: {
|
||||||
type: Object as () => SimpleFlowNode,
|
type: Object as () => SimpleFlowNode,
|
||||||
required: true
|
required: true
|
||||||
|
},
|
||||||
|
parentNode: {
|
||||||
|
type: Object as () => SimpleFlowNode,
|
||||||
|
default: null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
// 定义事件,更新父组件。
|
// 定义事件,更新父组件。
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
'update:flowNode': [node: SimpleFlowNode | undefined]
|
'update:flowNode': [node: SimpleFlowNode | undefined]
|
||||||
|
'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
|
||||||
}>()
|
}>()
|
||||||
// 是否只读
|
// 是否只读
|
||||||
const readonly = inject<Boolean>('readonly')
|
const readonly = inject<Boolean>('readonly')
|
||||||
|
|
@ -92,6 +98,76 @@ const openNodeConfig = () => {
|
||||||
const deleteNode = () => {
|
const deleteNode = () => {
|
||||||
emits('update:flowNode', currentNode.value.childNode)
|
emits('update:flowNode', currentNode.value.childNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查找可跳转节点
|
||||||
|
const findReturnTaskNodes = (matchNodeList: SimpleFlowNode[]) => {
|
||||||
|
// 从父节点查找所有用户任务节点(向上查找)
|
||||||
|
emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE)
|
||||||
|
|
||||||
|
// 从根节点开始查找所有用户任务节点(向下查找)
|
||||||
|
const rootNode = findRootNode(currentNode.value)
|
||||||
|
if (rootNode.type === NodeType.USER_TASK_NODE) {
|
||||||
|
// 如果找到了起始节点,从它的子节点开始查找
|
||||||
|
if (rootNode.childNode) {
|
||||||
|
findAllUserTaskNodes(rootNode.childNode, matchNodeList)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 否则从当前找到的最上层节点开始查找
|
||||||
|
findAllUserTaskNodes(rootNode, matchNodeList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 过滤掉当前节点
|
||||||
|
const currentNodeId = currentNode.value.id
|
||||||
|
const filteredList = matchNodeList.filter(node => node.id !== currentNodeId)
|
||||||
|
matchNodeList.length = 0
|
||||||
|
matchNodeList.push(...filteredList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找根节点
|
||||||
|
const findRootNode = (node: SimpleFlowNode): SimpleFlowNode => {
|
||||||
|
let parent: SimpleFlowNode | null = props.parentNode
|
||||||
|
let current: SimpleFlowNode = node
|
||||||
|
|
||||||
|
while (parent !== null) {
|
||||||
|
current = parent
|
||||||
|
parent = findParentNode(current)
|
||||||
|
}
|
||||||
|
|
||||||
|
return current
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找父节点
|
||||||
|
const findParentNode = (node: SimpleFlowNode): SimpleFlowNode | null => {
|
||||||
|
if (!props.parentNode) return null
|
||||||
|
if (props.parentNode.childNode === node) return props.parentNode
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归查找所有用户任务节点
|
||||||
|
const findAllUserTaskNodes = (node: SimpleFlowNode, matchNodeList: SimpleFlowNode[]) => {
|
||||||
|
if (!node) return
|
||||||
|
|
||||||
|
// 检查当前节点
|
||||||
|
if (node.type === NodeType.USER_TASK_NODE) {
|
||||||
|
if (!matchNodeList.some(n => n.id === node.id)) {
|
||||||
|
matchNodeList.push(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查子节点
|
||||||
|
if (node.childNode) {
|
||||||
|
findAllUserTaskNodes(node.childNode, matchNodeList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查条件分支节点的子节点
|
||||||
|
if (node.type === NodeType.CONDITION_BRANCH_NODE && node.conditionNodes) {
|
||||||
|
node.conditionNodes.forEach(conditionNode => {
|
||||||
|
if (conditionNode.childNode) {
|
||||||
|
findAllUserTaskNodes(conditionNode.childNode, matchNodeList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
||||||
|
|
@ -169,8 +169,42 @@ const deleteNode = () => {
|
||||||
const findReturnTaskNodes = (
|
const findReturnTaskNodes = (
|
||||||
matchNodeList: SimpleFlowNode[] // 匹配的节点
|
matchNodeList: SimpleFlowNode[] // 匹配的节点
|
||||||
) => {
|
) => {
|
||||||
// 从父节点查找
|
// 从父节点查找所有用户任务节点
|
||||||
emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE)
|
emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE)
|
||||||
|
|
||||||
|
// 递归查找当前节点的子节点
|
||||||
|
findChildUserTaskNodes(currentNode.value, matchNodeList)
|
||||||
|
|
||||||
|
// 过滤掉当前节点
|
||||||
|
const currentNodeId = currentNode.value.id
|
||||||
|
const filteredList = matchNodeList.filter(node => node.id !== currentNodeId)
|
||||||
|
matchNodeList.length = 0 // 清空原数组
|
||||||
|
matchNodeList.push(...filteredList) // 将过滤后的节点重新加入数组
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归查找子节点中的用户任务节点
|
||||||
|
const findChildUserTaskNodes = (node: SimpleFlowNode, matchNodeList: SimpleFlowNode[]) => {
|
||||||
|
if (!node) return
|
||||||
|
|
||||||
|
// 检查子节点
|
||||||
|
if (node.childNode) {
|
||||||
|
if (node.childNode.type === NodeType.USER_TASK_NODE) {
|
||||||
|
matchNodeList.push(node.childNode)
|
||||||
|
}
|
||||||
|
findChildUserTaskNodes(node.childNode, matchNodeList)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查条件分支节点的子节点
|
||||||
|
if (node.type === NodeType.CONDITION_BRANCH_NODE && node.conditionNodes) {
|
||||||
|
node.conditionNodes.forEach(conditionNode => {
|
||||||
|
if (conditionNode.childNode && conditionNode.childNode.type === NodeType.USER_TASK_NODE) {
|
||||||
|
matchNodeList.push(conditionNode.childNode)
|
||||||
|
}
|
||||||
|
if (conditionNode.childNode) {
|
||||||
|
findChildUserTaskNodes(conditionNode.childNode, matchNodeList)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 任务的弹窗显示,用于只读模式
|
// 任务的弹窗显示,用于只读模式
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue