feat: 子流程

This commit is contained in:
Lesan 2025-02-21 16:07:13 +08:00
parent b2ddefe4a0
commit 357955ce24
14 changed files with 571 additions and 23 deletions

View File

@ -0,0 +1 @@
<svg t="1740116978908" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1356" width="200" height="200"><path d="M860.544 633.856c-82.368 0-152.128 69.632-158.464 152h-354.88c-31.616 0-63.296-31.68-63.296-63.296V437.376c12.608 0 25.344 6.4 44.288 6.4h380.16c12.672 69.696 76.032 126.656 152.128 126.656 88.704 0 158.336-69.696 158.336-158.4s-69.632-158.4-158.336-158.4c-76.096 0-139.456 57.024-152.128 126.656h-361.216c-31.616 0-63.296-31.68-63.296-63.296v-133.12h164.736c31.68 0 63.296-22.848 63.296-54.528a55.04 55.04 0 0 0-56-56h-380.16c-31.68 0-70.72 17.984-70.72 56s31.68 54.528 63.36 54.528h133.056v538.624c0 69.696 57.088 126.656 126.72 126.656h386.56c25.344 57.088 82.368 101.376 145.728 101.376a156.8 156.8 0 0 0 158.336-158.4 156.608 156.608 0 0 0-158.208-158.272z m0-316.8c50.624 0 94.912 44.288 94.912 94.976s-44.288 94.976-94.912 94.976c-50.752 0-95.104-44.288-95.104-94.976s44.352-94.976 95.104-94.976z m0 570.24c-50.752 0-95.104-44.352-95.104-95.04s44.352-95.04 95.104-95.04c50.624 0 94.912 44.352 94.912 95.04s-44.288 95.04-94.912 95.04z" p-id="1357" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1 @@
<svg t="1740116949537" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1153" width="200" height="200"><path d="M440.32 296.96h283.30496v145.92h66.56V230.4H440.32V17.92H17.92v424.96H440.32V296.96zM373.76 376.32H84.48v-291.84H373.76v291.84zM586.24 588.8v143.36512H298.66496V586.24h-66.56v212.48512H586.24V1013.76H1008.64v-424.96h-422.4z m355.84 358.4h-289.28v-291.84H942.08v291.84z" p-id="1154" fill="#ffffff"></path></svg>

After

Width:  |  Height:  |  Size: 465 B

View File

@ -63,6 +63,18 @@
</div> </div>
<div class="handler-item-text">触发器</div> <div class="handler-item-text">触发器</div>
</div> </div>
<div class="handler-item" @click="addNode(NodeType.CHILD_PROCESS_NODE)">
<div class="handler-item-icon child-process">
<span class="iconfont icon-size icon-child-process"></span>
</div>
<div class="handler-item-text">子流程</div>
</div>
<div class="handler-item" @click="addNode(NodeType.ASYNC_CHILD_PROCESS_NODE)">
<div class="handler-item-icon async-child-process">
<span class="iconfont icon-size icon-async-child-process"></span>
</div>
<div class="handler-item-text">异步子流程</div>
</div>
</div> </div>
<template #reference> <template #reference>
<div class="add-icon"><Icon icon="ep:plus" /></div> <div class="add-icon"><Icon icon="ep:plus" /></div>
@ -283,6 +295,25 @@ const addNode = (type: number) => {
} }
emits('update:childNode', data) emits('update:childNode', data)
} }
if (type === NodeType.CHILD_PROCESS_NODE) {
const data: SimpleFlowNode = {
id: 'Activity_' + generateUUID(),
name: NODE_DEFAULT_NAME.get(NodeType.CHILD_PROCESS_NODE) as string,
showText: '',
type: NodeType.CHILD_PROCESS_NODE,
childNode: props.childNode,
childProcessSetting: {
calledElement: '',
calledElementName: '',
async: false,
skipStartUserNode: false,
startUserSetting: {
type: 1
}
}
}
emits('update:childNode', data)
}
} }
</script> </script>

View File

@ -54,12 +54,18 @@
:flow-node="currentNode" :flow-node="currentNode"
@update:flow-node="handleModelValueUpdate" @update:flow-node="handleModelValueUpdate"
/> />
<!-- 触发器节点 --> <!-- 触发器节点 -->
<TriggerNode <TriggerNode
v-if="currentNode && currentNode.type === NodeType.TRIGGER_NODE" v-if="currentNode && currentNode.type === NodeType.TRIGGER_NODE"
:flow-node="currentNode" :flow-node="currentNode"
@update:flow-node="handleModelValueUpdate" @update:flow-node="handleModelValueUpdate"
/> />
<!-- 子流程节点 -->
<ChildProcessNode
v-if="currentNode && currentNode.type === NodeType.CHILD_PROCESS_NODE"
:flow-node="currentNode"
@update:flow-node="handleModelValueUpdate"
/>
<!-- 递归显示孩子节点 --> <!-- 递归显示孩子节点 -->
<ProcessNodeTree <ProcessNodeTree
v-if="currentNode && currentNode.childNode" v-if="currentNode && currentNode.childNode"
@ -85,6 +91,7 @@ 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 ChildProcessNode from './nodes/ChildProcessNode.vue'
import { SimpleFlowNode, NodeType } from './consts' import { SimpleFlowNode, NodeType } from './consts'
import { useWatchNode } from './node' import { useWatchNode } from './node'
defineOptions({ defineOptions({

View File

@ -38,6 +38,16 @@ export enum NodeType {
*/ */
TRIGGER_NODE = 15, TRIGGER_NODE = 15,
/**
*
*/
CHILD_PROCESS_NODE = 20,
/**
*
*/
ASYNC_CHILD_PROCESS_NODE = 21,
/** /**
* *
*/ */
@ -128,6 +138,8 @@ export interface SimpleFlowNode {
reasonRequire?: boolean reasonRequire?: boolean
// 触发器设置 // 触发器设置
triggerSetting?: TriggerSetting triggerSetting?: TriggerSetting
// 子流程
childProcessSetting?: ChildProcessSetting
} }
// 候选人策略枚举 用于审批节点。抄送节点 ) // 候选人策略枚举 用于审批节点。抄送节点 )
export enum CandidateStrategy { export enum CandidateStrategy {
@ -512,6 +524,7 @@ NODE_DEFAULT_TEXT.set(NodeType.DELAY_TIMER_NODE, '请设置延迟器')
NODE_DEFAULT_TEXT.set(NodeType.ROUTER_BRANCH_NODE, '请设置路由节点') NODE_DEFAULT_TEXT.set(NodeType.ROUTER_BRANCH_NODE, '请设置路由节点')
NODE_DEFAULT_TEXT.set(NodeType.TRIGGER_NODE, '请设置触发器') NODE_DEFAULT_TEXT.set(NodeType.TRIGGER_NODE, '请设置触发器')
NODE_DEFAULT_TEXT.set(NodeType.TRANSACTOR_NODE, '请设置办理人') NODE_DEFAULT_TEXT.set(NodeType.TRANSACTOR_NODE, '请设置办理人')
NODE_DEFAULT_TEXT.set(NodeType.CHILD_PROCESS_NODE, '请设置子流程')
export const NODE_DEFAULT_NAME = new Map<number, string>() export const NODE_DEFAULT_NAME = new Map<number, string>()
NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人') NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人')
@ -522,6 +535,7 @@ NODE_DEFAULT_NAME.set(NodeType.DELAY_TIMER_NODE, '延迟器')
NODE_DEFAULT_NAME.set(NodeType.ROUTER_BRANCH_NODE, '路由分支') NODE_DEFAULT_NAME.set(NodeType.ROUTER_BRANCH_NODE, '路由分支')
NODE_DEFAULT_NAME.set(NodeType.TRIGGER_NODE, '触发器') NODE_DEFAULT_NAME.set(NodeType.TRIGGER_NODE, '触发器')
NODE_DEFAULT_NAME.set(NodeType.TRANSACTOR_NODE, '办理人') NODE_DEFAULT_NAME.set(NodeType.TRANSACTOR_NODE, '办理人')
NODE_DEFAULT_NAME.set(NodeType.CHILD_PROCESS_NODE, '子流程')
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序 // 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
export const CANDIDATE_STRATEGY: DictDataVO[] = [ export const CANDIDATE_STRATEGY: DictDataVO[] = [
@ -750,7 +764,7 @@ export enum TriggerTypeEnum {
/** /**
* *
*/ */
FORM_UPDATE = 2 FORM_UPDATE = 2
} }
/** /**
@ -785,3 +799,29 @@ export const TRIGGER_TYPES: DictDataVO[] = [
{ label: 'HTTP 请求', value: TriggerTypeEnum.HTTP_REQUEST }, { label: 'HTTP 请求', value: TriggerTypeEnum.HTTP_REQUEST },
{ label: '修改表单数据', value: TriggerTypeEnum.FORM_UPDATE } { label: '修改表单数据', value: TriggerTypeEnum.FORM_UPDATE }
] ]
/**
*
*/
export type ChildProcessSetting = {
calledElement: string
calledElementName: string
async: boolean,
inVariable?: IOParameter[],
outVariable?: IOParameter[],
skipStartUserNode: boolean,
startUserSetting: StartUserSetting,
}
export type IOParameter = {
source: string
sourceExpression: string
target: string
targetExpression: string
}
export type StartUserSetting = {
type: number
formField?: string
emptyHandleType?: number
}

View File

@ -0,0 +1,330 @@
<template>
<el-drawer
:append-to-body="true"
v-model="settingVisible"
:show-close="false"
:size="550"
:before-close="saveConfig"
>
<template #header>
<div class="config-header">
<input
v-if="showInput"
type="text"
class="config-editable-input"
@blur="blurEvent()"
v-mountedFocus
v-model="nodeName"
:placeholder="nodeName"
/>
<div v-else class="node-name">
{{ nodeName }} <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()" />
</div>
<div class="divide-line"></div>
</div>
</template>
<el-tabs type="border-card" v-model="activeTabName">
<el-tab-pane label="子流程" name="child">
<div>
<el-form ref="formRef" :model="configForm" label-position="top" :rules="formRules">
<el-form-item label="选择子流程" prop="calledElement">
<el-select
v-model="configForm.calledElement"
clearable
@change="handleCalledElementChange"
>
<el-option
v-for="(item, index) in childProcessOptions"
:key="index"
:label="item.name"
:value="item.key"
/>
</el-select>
</el-form-item>
<el-form-item label="是否自动跳过子流程发起节点" prop="skipStartUserNode">
<el-switch
v-model="configForm.skipStartUserNode"
active-text="跳过"
inactive-text="不跳过"
/>
</el-form-item>
<el-form-item label="主→子变量传递" prop="inVariable">
<div class="flex pt-2" v-for="(item, index) in configForm.inVariable" :key="index">
<div class="mr-2">
<el-form-item
:prop="`inVariable.${index}.source`"
:rules="{
required: true,
message: '变量不能为空',
trigger: 'blur'
}"
>
<el-select class="w-200px!" v-model="item.source">
<el-option
v-for="(field, fIdx) in formFieldOptions"
:key="fIdx"
:label="field.title"
:value="field.field"
/>
</el-select>
</el-form-item>
</div>
<div class="mr-2">
<el-form-item
:prop="`inVariable.${index}.target`"
:rules="{
required: true,
message: '变量不能为空',
trigger: 'blur'
}"
>
<el-select class="w-200px!" v-model="item.target">
<el-option
v-for="(field, fIdx) in childFormFieldOptions"
:key="fIdx"
:label="field.title"
:value="field.field"
/>
</el-select>
</el-form-item>
</div>
<div class="mr-1 flex items-center">
<Icon
icon="ep:delete"
:size="18"
@click="deleteVariable(configForm.inVariable, index)"
/>
</div>
</div>
<el-button type="primary" text @click="addVariable(configForm.inVariable)">
<Icon icon="ep:plus" class="mr-5px" />添加一行
</el-button>
</el-form-item>
<el-form-item
v-if="currentNode.childProcessSetting?.async === false"
label="子→主变量传递"
prop="outVariable"
>
<div class="flex pt-2" v-for="(item, index) in configForm.outVariable" :key="index">
<div class="mr-2">
<el-form-item
:prop="`outVariable.${index}.source`"
:rules="{
required: true,
message: '变量不能为空',
trigger: 'blur'
}"
>
<el-select class="w-200px!" v-model="item.source">
<el-option
v-for="(field, fIdx) in childFormFieldOptions"
:key="fIdx"
:label="field.title"
:value="field.field"
/>
</el-select>
</el-form-item>
</div>
<div class="mr-2">
<el-form-item
:prop="`outVariable.${index}.target`"
:rules="{
required: true,
message: '变量不能为空',
trigger: 'blur'
}"
>
<el-select class="w-200px!" v-model="item.target">
<el-option
v-for="(field, fIdx) in formFieldOptions"
:key="fIdx"
:label="field.title"
:value="field.field"
/>
</el-select>
</el-form-item>
</div>
<div class="mr-1 flex items-center">
<Icon
icon="ep:delete"
:size="18"
@click="deleteVariable(configForm.outVariable, index)"
/>
</div>
</div>
<el-button type="primary" text @click="addVariable(configForm.outVariable)">
<Icon icon="ep:plus" class="mr-5px" />添加一行
</el-button>
</el-form-item>
<el-form-item label="子流程发起人" prop="startUserType">
<el-radio-group v-model="configForm.startUserType">
<el-radio :value="1">同主流程发起人</el-radio>
<el-radio :value="2">表单</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="configForm.startUserType === 2"
label="当子流程发起人为空时"
prop="startUserType"
>
<el-radio-group v-model="configForm.startUserEmptyType">
<el-radio :value="1">同主流程发起人</el-radio>
<el-radio :value="2">子流程管理员</el-radio>
<el-radio :value="3">主流程管理员</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="configForm.startUserType === 2"
label="发起人表单"
prop="startUserFormField"
>
<el-select class="w-200px!" v-model="configForm.startUserFormField">
<el-option
v-for="(field, fIdx) in formFieldOptions"
:key="fIdx"
:label="field.title"
:value="field.field"
/>
</el-select>
</el-form-item>
</el-form>
</div>
</el-tab-pane>
</el-tabs>
<template #footer>
<el-divider />
<div>
<el-button type="primary" @click="saveConfig"> </el-button>
<el-button @click="closeDrawer"> </el-button>
</div>
</template>
</el-drawer>
</template>
<script setup lang="ts">
import { getModelList } from '@/api/bpm/model'
import { getForm } from '@/api/bpm/form'
import { SimpleFlowNode, NodeType } from '../consts'
import { useWatchNode, useDrawer, useNodeName, useFormFieldsAndStartUser } from '../node'
import { parseFormFields } from '@/components/FormCreate/src/utils'
defineOptions({
name: 'ChildProcessNodeConfig'
})
const props = defineProps({
flowNode: {
type: Object as () => SimpleFlowNode,
required: true
}
})
//
const { settingVisible, closeDrawer, openDrawer } = useDrawer()
//
const currentNode = useWatchNode(props)
//
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.CHILD_PROCESS_NODE)
// Tab
const activeTabName = ref('child')
//
const formRef = ref() // Ref
//
const formRules = reactive({
calledElement: [{ required: true, message: '子流程不能为空', trigger: 'change' }],
skipStartUserNode: [
{ required: true, message: '是否自动跳过子流程发起节点不能为空', trigger: 'change' }
],
startUserType: [{ required: true, message: '子流程发起人不能为空', trigger: 'change' }],
startUserEmptyType: [
{ required: true, message: '当子流程发起人为空时不能为空', trigger: 'change' }
],
startUserFormField: [{ required: true, message: '发起人表单不能为空', trigger: 'change' }]
})
const configForm = ref({
calledElement: '',
skipStartUserNode: false,
inVariable: [],
outVariable: [],
startUserType: 1,
startUserEmptyType: 1,
startUserFormField: ''
})
const childProcessOptions = ref()
const formFieldOptions = useFormFieldsAndStartUser()
const childFormFieldOptions = ref()
//
const saveConfig = async () => {
activeTabName.value = 'child'
if (!formRef) return false
const valid = await formRef.value.validate()
if (!valid) return false
const childInfo = childProcessOptions.value.find(
(option) => option.key === configForm.value.calledElement
)
currentNode.value.name = nodeName.value!
if (currentNode.value.childProcessSetting) {
currentNode.value.childProcessSetting.calledElement = childInfo.key
currentNode.value.childProcessSetting.calledElementName = childInfo.name
currentNode.value.childProcessSetting.skipStartUserNode = configForm.value.skipStartUserNode
currentNode.value.childProcessSetting.inVariable = configForm.value.inVariable
currentNode.value.childProcessSetting.outVariable = configForm.value.outVariable
currentNode.value.childProcessSetting.startUserSetting.type = configForm.value.startUserType
currentNode.value.childProcessSetting.startUserSetting.emptyHandleType =
configForm.value.startUserEmptyType
currentNode.value.childProcessSetting.startUserSetting.formField =
configForm.value.startUserFormField
}
currentNode.value.showText = `调用子流程:${childInfo.name}`
settingVisible.value = false
return true
}
//
const showChildProcessNodeConfig = (node: SimpleFlowNode) => {
nodeName.value = node.name
if (node.childProcessSetting) {
configForm.value.calledElement = node.childProcessSetting.calledElement
configForm.value.skipStartUserNode = node.childProcessSetting.skipStartUserNode
configForm.value.inVariable = node.childProcessSetting.inVariable
configForm.value.outVariable = node.childProcessSetting.outVariable
configForm.value.startUserType = node.childProcessSetting.startUserSetting.type
configForm.value.startUserEmptyType =
node.childProcessSetting.startUserSetting.emptyHandleType ?? 1
configForm.value.startUserFormField = node.childProcessSetting.startUserSetting.formField ?? ''
}
loadFormInfo()
}
defineExpose({ openDrawer, showChildProcessNodeConfig }) //
const addVariable = (arr) => {
arr.push({
source: '',
target: ''
})
}
const deleteVariable = (arr, index: number) => {
arr.splice(index, 1)
}
const handleCalledElementChange = () => {
configForm.value.inVariable = []
configForm.value.outVariable = []
loadFormInfo()
}
const loadFormInfo = async () => {
const childInfo = childProcessOptions.value.find(
(option) => option.key === configForm.value.calledElement
)
const formInfo = await getForm(childInfo.formId)
childFormFieldOptions.value = []
if (formInfo.fields) {
formInfo.fields.forEach((fieldStr: string) => {
parseFormFields(JSON.parse(fieldStr), childFormFieldOptions.value)
})
}
console.log(childFormFieldOptions.value)
}
onMounted(async () => {
childProcessOptions.value = await getModelList(undefined)
})
</script>
<style lang="scss" scoped></style>

View File

@ -0,0 +1,104 @@
<template>
<div class="node-wrapper">
<div class="node-container">
<div
class="node-box"
:class="[
{ 'node-config-error': !currentNode.showText },
`${useTaskStatusClass(currentNode?.activityStatus)}`
]"
>
<div class="node-title-container">
<div
:class="`node-title-icon ${currentNode.childProcessSetting?.async === true ? 'async-child-process' : 'child-process'}`"
>
<span
:class="`iconfont ${currentNode.childProcessSetting?.async === true ? 'icon-async-child-process' : 'icon-child-process'}`"
>
</span>
</div>
<input
v-if="!readonly && showInput"
type="text"
class="editable-title-input"
@blur="blurEvent()"
v-mountedFocus
v-model="currentNode.name"
:placeholder="currentNode.name"
/>
<div v-else class="node-title" @click="clickTitle">
{{ currentNode.name }}
</div>
</div>
<div class="node-content" @click="openNodeConfig">
<div class="node-text" :title="currentNode.showText" v-if="currentNode.showText">
{{ currentNode.showText }}
</div>
<div class="node-text" v-else>
{{ NODE_DEFAULT_TEXT.get(NodeType.CHILD_PROCESS_NODE) }}
</div>
<Icon v-if="!readonly" icon="ep:arrow-right-bold" />
</div>
<div v-if="!readonly" class="node-toolbar">
<div class="toolbar-icon"
><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
/></div>
</div>
</div>
<!-- 传递子节点给添加节点组件会在子节点前面添加节点 -->
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
<ChildProcessNodeConfig
v-if="!readonly && currentNode"
ref="nodeSetting"
:flow-node="currentNode"
/>
</div>
</template>
<script setup lang="ts">
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
import NodeHandler from '../NodeHandler.vue'
import { useNodeName2, useWatchNode, useTaskStatusClass } from '../node'
import ChildProcessNodeConfig from '../nodes-config/ChildProcessNodeConfig.vue'
defineOptions({
name: 'ChildProcessNode'
})
const props = defineProps({
flowNode: {
type: Object as () => SimpleFlowNode,
required: true
}
})
//
const emits = defineEmits<{
'update:flowNode': [node: SimpleFlowNode | undefined]
}>()
//
const readonly = inject<Boolean>('readonly')
//
const currentNode = useWatchNode(props)
//
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.CHILD_PROCESS_NODE)
const nodeSetting = ref()
//
const openNodeConfig = () => {
if (readonly) {
return
}
nodeSetting.value.showChildProcessNodeConfig(currentNode.value)
nodeSetting.value.openDrawer()
}
//
const deleteNode = () => {
emits('update:flowNode', currentNode.value.childNode)
}
</script>
<style scoped></style>

View File

@ -181,6 +181,14 @@
color: #330099; color: #330099;
} }
.child-process {
color: #996633;
}
.async-child-process {
color: #006666;
}
.handler-item-text { .handler-item-text {
margin-top: 4px; margin-top: 4px;
width: 80px; width: 80px;
@ -302,6 +310,14 @@
&.transactor-task { &.transactor-task {
color: #330099; color: #330099;
} }
&.child-process {
color: #996633;
}
&.async-child-process {
color: #006666;
}
} }
.node-title { .node-title {
@ -800,3 +816,11 @@
.icon-parallel:before { .icon-parallel:before {
content: "\e688"; content: "\e688";
} }
.icon-async-child-process:before {
content: "\e6f2";
}
.icon-child-process:before {
content: "\e6c1";
}

View File

@ -157,24 +157,24 @@ const initProcessInfo = async (row: any, formVariables?: any) => {
} }
/** 预测流程节点会因为输入的参数值而产生新的预测结果值,所以需重新预测一次 */ /** 预测流程节点会因为输入的参数值而产生新的预测结果值,所以需重新预测一次 */
watch( // watch(
detailForm.value, // detailForm.value,
(newValue) => { // (newValue) => {
if (newValue && Object.keys(newValue.value).length > 0) { // if (newValue && Object.keys(newValue.value).length > 0) {
// // //
tempStartUserSelectAssignees.value = startUserSelectAssignees.value // tempStartUserSelectAssignees.value = startUserSelectAssignees.value
startUserSelectAssignees.value = {} // startUserSelectAssignees.value = {}
// // //
getApprovalDetail({ // getApprovalDetail({
id: props.selectProcessDefinition.id, // id: props.selectProcessDefinition.id,
processVariablesStr: JSON.stringify(newValue.value) // GET String JSON // processVariablesStr: JSON.stringify(newValue.value) // GET String JSON
}) // })
} // }
}, // },
{ // {
immediate: true // immediate: true
} // }
) // )
/** 获取审批详情 */ /** 获取审批详情 */
const getApprovalDetail = async (row: any) => { const getApprovalDetail = async (row: any) => {

View File

@ -85,7 +85,9 @@ const setSimpleModelNodeTaskStatus = (
if ( if (
simpleModel.type === NodeType.START_USER_NODE || simpleModel.type === NodeType.START_USER_NODE ||
simpleModel.type === NodeType.USER_TASK_NODE || simpleModel.type === NodeType.USER_TASK_NODE ||
simpleModel.type === NodeType.TRANSACTOR_NODE simpleModel.type === NodeType.TRANSACTOR_NODE ||
simpleModel.type === NodeType.CHILD_PROCESS_NODE ||
simpleModel.type === NodeType.ASYNC_CHILD_PROCESS_NODE
) { ) {
simpleModel.activityStatus = TaskStatusEnum.NOT_START simpleModel.activityStatus = TaskStatusEnum.NOT_START
if (rejectedTaskActivityIds.includes(simpleModel.id)) { if (rejectedTaskActivityIds.includes(simpleModel.id)) {

View File

@ -181,6 +181,8 @@ import conditionSvg from '@/assets/svgs/bpm/condition.svg'
import parallelSvg from '@/assets/svgs/bpm/parallel.svg' import parallelSvg from '@/assets/svgs/bpm/parallel.svg'
import finishSvg from '@/assets/svgs/bpm/finish.svg' import finishSvg from '@/assets/svgs/bpm/finish.svg'
import transactorSvg from '@/assets/svgs/bpm/transactor.svg' import transactorSvg from '@/assets/svgs/bpm/transactor.svg'
import childProcessSvg from '@/assets/svgs/bpm/child-process.svg'
import asyncChildProcessSvg from '@/assets/svgs/bpm/async-child-process.svg'
defineOptions({ name: 'BpmProcessInstanceTimeline' }) defineOptions({ name: 'BpmProcessInstanceTimeline' })
withDefaults( withDefaults(
@ -249,7 +251,11 @@ const nodeTypeSvgMap = {
// //
[NodeType.CONDITION_NODE]: { color: '#14bb83', svg: conditionSvg }, [NodeType.CONDITION_NODE]: { color: '#14bb83', svg: conditionSvg },
// //
[NodeType.PARALLEL_BRANCH_NODE]: { color: '#14bb83', svg: parallelSvg } [NodeType.PARALLEL_BRANCH_NODE]: { color: '#14bb83', svg: parallelSvg },
//
[NodeType.CHILD_PROCESS_NODE]: { color: '#14bb83', svg: childProcessSvg },
//
[NodeType.ASYNC_CHILD_PROCESS_NODE]: { color: '#14bb83', svg: asyncChildProcessSvg }
} }
// -101 icon // -101 icon
@ -269,6 +275,8 @@ const getApprovalNodeIcon = (taskStatus: number, nodeType: NodeType) => {
nodeType === NodeType.START_USER_NODE || nodeType === NodeType.START_USER_NODE ||
nodeType === NodeType.USER_TASK_NODE || nodeType === NodeType.USER_TASK_NODE ||
nodeType === NodeType.TRANSACTOR_NODE || nodeType === NodeType.TRANSACTOR_NODE ||
nodeType === NodeType.CHILD_PROCESS_NODE ||
nodeType === NodeType.ASYNC_CHILD_PROCESS_NODE ||
nodeType === NodeType.END_EVENT_NODE nodeType === NodeType.END_EVENT_NODE
) { ) {
return statusIconMap[taskStatus]?.icon return statusIconMap[taskStatus]?.icon