【功能优化】条件分支、包容分支后面不允许直接添加并行分支

This commit is contained in:
YunaiV 2024-11-02 09:11:19 +08:00
parent e504be7d42
commit a097560f81
7 changed files with 227 additions and 171 deletions

View File

@ -27,14 +27,7 @@
</div>
<div class="handler-item-text">条件分支</div>
</div>
<div
class="handler-item"
@click="addNode(NodeType.PARALLEL_BRANCH_NODE)"
v-if="
NodeType.CONDITION_BRANCH_NODE !== currentNode?.type &&
NodeType.INCLUSIVE_BRANCH_NODE !== currentNode?.type
"
>
<div class="handler-item" @click="addNode(NodeType.PARALLEL_BRANCH_NODE)">
<div class="handler-item-icon parallel">
<span class="iconfont icon-size icon-parallel"></span>
</div>
@ -70,8 +63,10 @@ import { generateUUID } from '@/utils'
defineOptions({
name: 'NodeHandler'
})
const popoverShow = ref(false)
const message = useMessage() //
const popoverShow = ref(false)
const props = defineProps({
childNode: {
type: Object as () => SimpleFlowNode,
@ -87,6 +82,17 @@ const emits = defineEmits(['update:childNode'])
const readonly = inject<Boolean>('readonly') //
const addNode = (type: number) => {
//
if (
type === NodeType.PARALLEL_BRANCH_NODE &&
[NodeType.CONDITION_BRANCH_NODE, NodeType.INCLUSIVE_BRANCH_NODE].includes(
props.currentNode?.type
)
) {
message.error('条件分支、包容分支后面,不允许直接添加并行分支')
return
}
popoverShow.value = false
if (type === NodeType.USER_TASK_NODE) {
const id = 'Activity_' + generateUUID()

View File

@ -3,7 +3,10 @@
<div class="node-container">
<div
class="node-box"
:class="[{ 'node-config-error': !currentNode.showText }, `${useTaskStatusClass(currentNode?.activityStatus)}`]"
:class="[
{ 'node-config-error': !currentNode.showText },
`${useTaskStatusClass(currentNode?.activityStatus)}`
]"
>
<div class="node-title-container">
<div class="node-title-icon copy-task"><span class="iconfont icon-copy"></span></div>
@ -37,7 +40,11 @@
</div>
<!-- 传递子节点给添加节点组件会在子节点前面添加节点 -->
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode"/>
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
<CopyTaskNodeConfig
v-if="!readonly && currentNode"

View File

@ -1,7 +1,11 @@
<template>
<div class="branch-node-wrapper">
<div class="branch-node-container">
<div v-if="readonly" class="branch-node-readonly" :class="`${useTaskStatusClass(currentNode?.activityStatus)}`">
<div
v-if="readonly"
class="branch-node-readonly"
:class="`${useTaskStatusClass(currentNode?.activityStatus)}`"
>
<span class="iconfont icon-exclusive icon-size condition"></span>
</div>
<el-button v-else class="branch-node-add" color="#67c23a" @click="addCondition" plain
@ -23,7 +27,13 @@
</template>
<div class="node-wrapper">
<div class="node-container">
<div class="node-box" :class="[{ 'node-config-error': !item.showText }, `${useTaskStatusClass(item.activityStatus)}`]">
<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
@ -87,7 +97,11 @@
/>
</div>
</div>
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode" />
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
</template>
@ -120,7 +134,7 @@ const emits = defineEmits<{
]
}>()
//
const readonly = inject<Boolean>('readonly')
const readonly = inject<Boolean>('readonly')
const currentNode = ref<SimpleFlowNode>(props.flowNode)
watch(
() => props.flowNode,

View File

@ -1,10 +1,16 @@
<template>
<div class="branch-node-wrapper">
<div class="branch-node-container">
<div v-if="readonly" class="branch-node-readonly" :class="`${useTaskStatusClass(currentNode?.activityStatus)}`" >
<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>
<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"
@ -20,7 +26,13 @@
</template>
<div class="node-wrapper">
<div class="node-container">
<div class="node-box" :class="[{ 'node-config-error': !item.showText }, `${useTaskStatusClass(item.activityStatus)}`]">
<div
class="node-box"
:class="[
{ 'node-config-error': !item.showText },
`${useTaskStatusClass(item.activityStatus)}`
]"
>
<div class="branch-node-title-container">
<div v-if="showInputs[index]">
<input
@ -41,7 +53,10 @@
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
</div>
</div>
<div class="node-toolbar" v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length">
<div
class="node-toolbar"
v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length"
>
<div class="toolbar-icon">
<Icon
color="#0089ff"
@ -61,13 +76,17 @@
<div
class="branch-node-move move-node-right"
v-if="!readonly && currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
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"/>
<NodeHandler v-model:child-node="item.childNode" :current-node="item" />
</div>
</div>
<ConditionNodeConfig :node-index="index" :condition-node="item" :ref="item.id" />
@ -80,7 +99,11 @@
/>
</div>
</div>
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode"/>
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
</template>

View File

@ -1,10 +1,16 @@
<template>
<div class="branch-node-wrapper">
<div class="branch-node-container">
<div v-if="readonly" class="branch-node-readonly" :class="`${useTaskStatusClass(currentNode?.activityStatus)}`">
<div
v-if="readonly"
class="branch-node-readonly"
:class="`${useTaskStatusClass(currentNode?.activityStatus)}`"
>
<span class="iconfont icon-parallel icon-size parallel"></span>
</div>
<el-button v-else class="branch-node-add" color="#626aef" @click="addCondition" plain>添加分支</el-button>
<el-button v-else class="branch-node-add" color="#626aef" @click="addCondition" plain
>添加分支</el-button
>
<div
class="branch-node-item"
v-for="(item, index) in currentNode.conditionNodes"
@ -42,7 +48,7 @@
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
</div>
</div>
<div v-if="!readonly" class="node-toolbar">
<div v-if="!readonly" class="node-toolbar">
<div class="toolbar-icon">
<Icon
color="#0089ff"
@ -53,7 +59,7 @@
</div>
</div>
</div>
<NodeHandler v-model:child-node="item.childNode" :current-node="item"/>
<NodeHandler v-model:child-node="item.childNode" :current-node="item" />
</div>
</div>
<!-- 递归显示子节点 -->
@ -65,7 +71,11 @@
/>
</div>
</div>
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode" />
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
</template>
@ -98,7 +108,7 @@ const emits = defineEmits<{
const currentNode = ref<SimpleFlowNode>(props.flowNode)
//
const readonly = inject<Boolean>('readonly')
const readonly = inject<Boolean>('readonly')
watch(
() => props.flowNode,

View File

@ -3,7 +3,10 @@
<div class="node-container">
<div
class="node-box"
:class="[{ 'node-config-error': !currentNode.showText }, `${useTaskStatusClass(currentNode?.activityStatus)}`]"
:class="[
{ 'node-config-error': !currentNode.showText },
`${useTaskStatusClass(currentNode?.activityStatus)}`
]"
>
<div class="node-title-container">
<div class="node-title-icon start-user"
@ -33,73 +36,68 @@
</div>
</div>
<!-- 传递子节点给添加节点组件会在子节点前面添加节点 -->
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode" />
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
</div>
<StartUserNodeConfig v-if="!readonly && currentNode" ref="nodeSetting" :flow-node="currentNode" />
<!-- 审批记录 -->
<el-dialog :title="dialogTitle || '审批记录'" v-model="dialogVisible" width="1000px" append-to-body>
<el-row>
<el-table
:data="selectTasks"
size="small"
border
header-cell-class-name="table-header-gray"
>
<el-table-column
label="序号"
header-align="center"
align="center"
type="index"
width="50"
/>
<el-table-column
label="审批人"
min-width="100"
align="center"
>
<template #default="scope">
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
</template>
</el-table-column>
<el-table-column label="部门" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
</template>
</el-table-column>
<el-table-column
:formatter="dateFormatter"
align="center"
label="开始时间"
prop="createTime"
min-width="140"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
min-width="140"
/>
<el-table-column align="center" label="审批状态" prop="status" min-width="90">
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
align="center"
label="审批建议"
prop="reason"
min-width="120"
/>
<el-table-column align="center" label="耗时" prop="durationInMillis" width="100">
<template #default="scope">
{{ formatPast2(scope.row.durationInMillis) }}
</template>
</el-table-column>
</el-table>
</el-row>
<!-- 审批记录 -->
<el-dialog
:title="dialogTitle || '审批记录'"
v-model="dialogVisible"
width="1000px"
append-to-body
>
<el-row>
<el-table :data="selectTasks" size="small" border header-cell-class-name="table-header-gray">
<el-table-column
label="序号"
header-align="center"
align="center"
type="index"
width="50"
/>
<el-table-column label="审批人" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
</template>
</el-table-column>
<el-table-column label="部门" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
</template>
</el-table-column>
<el-table-column
:formatter="dateFormatter"
align="center"
label="开始时间"
prop="createTime"
min-width="140"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
min-width="140"
/>
<el-table-column align="center" label="审批状态" prop="status" min-width="90">
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column align="center" label="审批建议" prop="reason" min-width="120" />
<el-table-column align="center" label="耗时" prop="durationInMillis" width="100">
<template #default="scope">
{{ formatPast2(scope.row.durationInMillis) }}
</template>
</el-table-column>
</el-table>
</el-row>
</el-dialog>
</template>
<script setup lang="ts">
@ -130,13 +128,15 @@ const currentNode = useWatchNode(props)
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
const nodeSetting = ref()
//
//
const nodeClick = () => {
if (readonly) {
//
if(tasks && tasks.value){
if (tasks && tasks.value) {
dialogTitle.value = currentNode.value.name
selectTasks.value = tasks.value.filter((item: any) => item?.taskDefinitionKey === currentNode.value.id)
selectTasks.value = tasks.value.filter(
(item: any) => item?.taskDefinitionKey === currentNode.value.id
)
dialogVisible.value = true
}
} else {
@ -144,13 +144,11 @@ const nodeClick = () => {
nodeSetting.value.showStartUserNodeConfig(currentNode.value)
nodeSetting.value.openDrawer()
}
}
//
const dialogVisible = ref(false) //
const dialogTitle = ref<string | undefined>(undefined) //
const selectTasks = ref<any[]|undefined>([]) //
const selectTasks = ref<any[] | undefined>([]) //
</script>
<style lang="scss" scoped></style>

View File

@ -3,7 +3,10 @@
<div class="node-container">
<div
class="node-box"
:class="[{ 'node-config-error': !currentNode.showText }, `${useTaskStatusClass(currentNode?.activityStatus)}`]"
:class="[
{ 'node-config-error': !currentNode.showText },
`${useTaskStatusClass(currentNode?.activityStatus)}`
]"
>
<div class="node-title-container">
<div class="node-title-icon user-task"><span class="iconfont icon-approve"></span></div>
@ -36,7 +39,11 @@
</div>
</div>
<!-- 传递子节点给添加节点组件会在子节点前面添加节点 -->
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" :current-node="currentNode" />
<NodeHandler
v-if="currentNode"
v-model:child-node="currentNode.childNode"
:current-node="currentNode"
/>
</div>
</div>
<UserTaskNodeConfig
@ -46,68 +53,59 @@
@find:return-task-nodes="findReturnTaskNodes"
/>
<!-- 审批记录 -->
<el-dialog :title="dialogTitle || '审批记录'" v-model="dialogVisible" width="1000px" append-to-body>
<el-row>
<el-table
:data="selectTasks"
size="small"
border
header-cell-class-name="table-header-gray"
>
<el-table-column
label="序号"
header-align="center"
align="center"
type="index"
width="50"
/>
<el-table-column
label="审批人"
min-width="100"
align="center"
>
<template #default="scope">
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
</template>
</el-table-column>
<el-table-column label="部门" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
</template>
</el-table-column>
<el-table-column
:formatter="dateFormatter"
align="center"
label="开始时间"
prop="createTime"
min-width="140"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
min-width="140"
/>
<el-table-column align="center" label="审批状态" prop="status" min-width="90">
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column
align="center"
label="审批建议"
prop="reason"
min-width="120"
/>
<el-table-column align="center" label="耗时" prop="durationInMillis" width="100">
<template #default="scope">
{{ formatPast2(scope.row.durationInMillis) }}
</template>
</el-table-column>
</el-table>
</el-row>
<el-dialog
:title="dialogTitle || '审批记录'"
v-model="dialogVisible"
width="1000px"
append-to-body
>
<el-row>
<el-table :data="selectTasks" size="small" border header-cell-class-name="table-header-gray">
<el-table-column
label="序号"
header-align="center"
align="center"
type="index"
width="50"
/>
<el-table-column label="审批人" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.nickname || scope.row.ownerUser?.nickname }}
</template>
</el-table-column>
<el-table-column label="部门" min-width="100" align="center">
<template #default="scope">
{{ scope.row.assigneeUser?.deptName || scope.row.ownerUser?.deptName }}
</template>
</el-table-column>
<el-table-column
:formatter="dateFormatter"
align="center"
label="开始时间"
prop="createTime"
min-width="140"
/>
<el-table-column
:formatter="dateFormatter"
align="center"
label="结束时间"
prop="endTime"
min-width="140"
/>
<el-table-column align="center" label="审批状态" prop="status" min-width="90">
<template #default="scope">
<dict-tag :type="DICT_TYPE.BPM_TASK_STATUS" :value="scope.row.status" />
</template>
</el-table-column>
<el-table-column align="center" label="审批建议" prop="reason" min-width="120" />
<el-table-column align="center" label="耗时" prop="durationInMillis" width="100">
<template #default="scope">
{{ formatPast2(scope.row.durationInMillis) }}
</template>
</el-table-column>
</el-table>
</el-row>
</el-dialog>
</template>
<script setup lang="ts">
@ -140,17 +138,18 @@ const currentNode = useWatchNode(props)
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
const nodeSetting = ref()
const nodeClick = () => {
if (readonly) {
if(tasks && tasks.value){
if (readonly) {
if (tasks && tasks.value) {
dialogTitle.value = currentNode.value.name
//
selectTasks.value = tasks.value.filter((item: any) => item?.taskDefinitionKey === currentNode.value.id)
selectTasks.value = tasks.value.filter(
(item: any) => item?.taskDefinitionKey === currentNode.value.id
)
dialogVisible.value = true
}
} else {
//
} else {
//
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
nodeSetting.value.openDrawer()
}
@ -170,7 +169,6 @@ const findReturnTaskNodes = (
//
const dialogVisible = ref(false) //
const dialogTitle = ref<string | undefined>(undefined) //
const selectTasks = ref<any[]|undefined>([]) //
const selectTasks = ref<any[] | undefined>([]) //
</script>
<style lang="scss" scoped></style>