【功能新增】 仿钉钉流程模型增加浏览模式
parent
d477b35f83
commit
137b33e7cf
|
@ -6,6 +6,7 @@
|
||||||
v-model:visible="popoverShow"
|
v-model:visible="popoverShow"
|
||||||
placement="right-start"
|
placement="right-start"
|
||||||
width="auto"
|
width="auto"
|
||||||
|
v-if="!readonly"
|
||||||
>
|
>
|
||||||
<div class="handler-item-wrapper">
|
<div class="handler-item-wrapper">
|
||||||
<div class="handler-item" @click="addNode(NodeType.USER_TASK_NODE)">
|
<div class="handler-item" @click="addNode(NodeType.USER_TASK_NODE)">
|
||||||
|
@ -78,6 +79,8 @@ const props = defineProps({
|
||||||
|
|
||||||
const emits = defineEmits(['update:childNode'])
|
const emits = defineEmits(['update:childNode'])
|
||||||
|
|
||||||
|
const readonly = inject<Boolean>('readonly') // 是否只读
|
||||||
|
|
||||||
const addNode = (type: number) => {
|
const addNode = (type: number) => {
|
||||||
popoverShow.value = false
|
popoverShow.value = false
|
||||||
if (type === NodeType.USER_TASK_NODE) {
|
if (type === NodeType.USER_TASK_NODE) {
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 结束节点 -->
|
<!-- 结束节点 -->
|
||||||
<EndEventNode v-if="currentNode && currentNode.type === NodeType.END_EVENT_NODE" />
|
<EndEventNode v-if="currentNode && currentNode.type === NodeType.END_EVENT_NODE" :flow-node="currentNode" />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import StartUserNode from './nodes/StartUserNode.vue'
|
import StartUserNode from './nodes/StartUserNode.vue'
|
||||||
|
|
|
@ -57,7 +57,7 @@ const props = defineProps({
|
||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const loading = ref(true)
|
const loading = ref(false)
|
||||||
const formFields = ref<string[]>([])
|
const formFields = ref<string[]>([])
|
||||||
const formType = ref(20)
|
const formType = ref(20)
|
||||||
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
|
const roleOptions = ref<RoleApi.RoleVO[]>([]) // 角色列表
|
||||||
|
@ -66,6 +66,7 @@ const userOptions = ref<UserApi.UserVO[]>([]) // 用户列表
|
||||||
const deptOptions = ref<DeptApi.DeptVO[]>([]) // 部门列表
|
const deptOptions = ref<DeptApi.DeptVO[]>([]) // 部门列表
|
||||||
const deptTreeOptions = ref()
|
const deptTreeOptions = ref()
|
||||||
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
|
const userGroupOptions = ref<UserGroupApi.UserGroupVO[]>([]) // 用户组列表
|
||||||
|
provide('readonly', false)
|
||||||
provide('formFields', formFields)
|
provide('formFields', formFields)
|
||||||
provide('formType', formType)
|
provide('formType', formType)
|
||||||
provide('roleList', roleOptions)
|
provide('roleList', roleOptions)
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
<template>
|
||||||
|
<div class="simple-flow-canvas" v-loading="loading">
|
||||||
|
<div class="simple-flow-container">
|
||||||
|
<div class="scale-container" :style="`transform: scale(${scaleValue / 100});`">
|
||||||
|
<ProcessNodeTree v-if="processNodeTree" v-model:flow-node="processNodeTree"/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import ProcessNodeTree from './ProcessNodeTree.vue'
|
||||||
|
import { SimpleFlowNode } from './consts'
|
||||||
|
|
||||||
|
defineOptions({
|
||||||
|
name: 'SimpleProcessRender'
|
||||||
|
})
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
flowNode: {
|
||||||
|
type: Object as () => SimpleFlowNode,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
const loading = ref(false)
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.flowNode,
|
||||||
|
(newValue) => {
|
||||||
|
processNodeTree.value = newValue
|
||||||
|
}
|
||||||
|
)
|
||||||
|
const processNodeTree = ref<SimpleFlowNode | undefined>(props.flowNode)
|
||||||
|
provide('readonly', true)
|
||||||
|
let scaleValue = ref(100)
|
||||||
|
const MAX_SCALE_VALUE = 200
|
||||||
|
const MIN_SCALE_VALUE = 50
|
||||||
|
// 放大
|
||||||
|
const zoomOut = () => {
|
||||||
|
if (scaleValue.value == MAX_SCALE_VALUE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scaleValue.value += 10
|
||||||
|
}
|
||||||
|
// 缩小
|
||||||
|
const zoomIn = () => {
|
||||||
|
if (scaleValue.value == MIN_SCALE_VALUE) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scaleValue.value -= 10
|
||||||
|
}
|
||||||
|
|
||||||
|
// onMounted(async () => {
|
||||||
|
// try {
|
||||||
|
// loading.value = true
|
||||||
|
// if (props.view) {
|
||||||
|
// processNodeTree.value = props.view.simpleModel
|
||||||
|
// }
|
||||||
|
// } finally {
|
||||||
|
// loading.value = false
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
</script>
|
|
@ -1,6 +1,6 @@
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import { DictDataVO } from '@/api/system/dict/types'
|
import { DictDataVO } from '@/api/system/dict/types'
|
||||||
|
import { TaskStatusEnum } from '@/api/bpm/task'
|
||||||
/**
|
/**
|
||||||
* 节点类型
|
* 节点类型
|
||||||
*/
|
*/
|
||||||
|
@ -96,6 +96,8 @@ export interface SimpleFlowNode {
|
||||||
conditionGroups?: ConditionGroup
|
conditionGroups?: ConditionGroup
|
||||||
// 是否默认的条件
|
// 是否默认的条件
|
||||||
defaultFlow?: boolean
|
defaultFlow?: boolean
|
||||||
|
// 活动的状态,用于前端节点状态展示
|
||||||
|
activityStatus? : TaskStatusEnum
|
||||||
}
|
}
|
||||||
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
|
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
|
||||||
export enum CandidateStrategy {
|
export enum CandidateStrategy {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import SimpleProcessDesigner from './SimpleProcessDesigner.vue'
|
import SimpleProcessDesigner from './SimpleProcessDesigner.vue'
|
||||||
|
import SimpleProcessViewer from './SimpleProcessViewer.vue'
|
||||||
import '../theme/simple-process-designer.scss'
|
import '../theme/simple-process-designer.scss'
|
||||||
|
|
||||||
export { SimpleProcessDesigner }
|
export { SimpleProcessDesigner, SimpleProcessViewer }
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { cloneDeep } from 'lodash-es'
|
import { cloneDeep } from 'lodash-es'
|
||||||
|
import { TaskStatusEnum } from '@/api/bpm/task'
|
||||||
import * as RoleApi from '@/api/system/role'
|
import * as RoleApi from '@/api/system/role'
|
||||||
import * as DeptApi from '@/api/system/dept'
|
import * as DeptApi from '@/api/system/dept'
|
||||||
import * as PostApi from '@/api/system/post'
|
import * as PostApi from '@/api/system/post'
|
||||||
|
@ -476,3 +477,26 @@ export function useNodeName2(node: Ref<SimpleFlowNode>, nodeType: NodeType) {
|
||||||
blurEvent
|
blurEvent
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @description 根据节点任务状态,获取节点任务状态样式
|
||||||
|
*/
|
||||||
|
export function useTaskStatusClass(taskStatus: TaskStatusEnum | undefined) : string {
|
||||||
|
if (!taskStatus) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
if (taskStatus === TaskStatusEnum.APPROVE ) {
|
||||||
|
return 'status-pass'
|
||||||
|
}
|
||||||
|
if (taskStatus === TaskStatusEnum.RUNNING ) {
|
||||||
|
return 'status-running'
|
||||||
|
}
|
||||||
|
if (taskStatus === TaskStatusEnum.REJECT ) {
|
||||||
|
return 'status-reject'
|
||||||
|
}
|
||||||
|
if (taskStatus === TaskStatusEnum.CANCEL ) {
|
||||||
|
return 'status-cancel'
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<div class="node-title-container">
|
<div class="node-title-container">
|
||||||
<div class="node-title-icon copy-task"><span class="iconfont icon-copy"></span></div>
|
<div class="node-title-icon copy-task"><span class="iconfont icon-copy"></span></div>
|
||||||
<input
|
<input
|
||||||
v-if="showInput"
|
v-if="!readonly && showInput"
|
||||||
type="text"
|
type="text"
|
||||||
class="editable-title-input"
|
class="editable-title-input"
|
||||||
@blur="blurEvent()"
|
@blur="blurEvent()"
|
||||||
|
@ -24,9 +24,9 @@
|
||||||
<div class="node-text" v-else>
|
<div class="node-text" v-else>
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.COPY_TASK_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.COPY_TASK_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
<Icon icon="ep:arrow-right-bold" />
|
<Icon v-if="!readonly" icon="ep:arrow-right-bold" />
|
||||||
</div>
|
</div>
|
||||||
<div class="node-toolbar">
|
<div v-if="!readonly" class="node-toolbar">
|
||||||
<div class="toolbar-icon"
|
<div class="toolbar-icon"
|
||||||
><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
|
><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
|
||||||
/></div>
|
/></div>
|
||||||
|
@ -36,7 +36,7 @@
|
||||||
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
|
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
|
||||||
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
||||||
</div>
|
</div>
|
||||||
<CopyTaskNodeConfig v-if="currentNode" ref="nodeSetting" :flow-node="currentNode" />
|
<CopyTaskNodeConfig v-if="!readonly && currentNode" ref="nodeSetting" :flow-node="currentNode" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
@ -57,7 +57,8 @@ const props = defineProps({
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
'update:flowNode': [node: SimpleFlowNode | undefined]
|
'update:flowNode': [node: SimpleFlowNode | undefined]
|
||||||
}>()
|
}>()
|
||||||
|
// 是否只读
|
||||||
|
const readonly = inject<Boolean>('readonly')
|
||||||
// 监控节点的变化
|
// 监控节点的变化
|
||||||
const currentNode = useWatchNode(props)
|
const currentNode = useWatchNode(props)
|
||||||
// 节点名称编辑
|
// 节点名称编辑
|
||||||
|
@ -66,6 +67,9 @@ const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.
|
||||||
const nodeSetting = ref()
|
const nodeSetting = ref()
|
||||||
// 打开节点配置
|
// 打开节点配置
|
||||||
const openNodeConfig = () => {
|
const openNodeConfig = () => {
|
||||||
|
if (readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
nodeSetting.value.showCopyTaskNodeConfig(currentNode.value)
|
nodeSetting.value.showCopyTaskNodeConfig(currentNode.value)
|
||||||
nodeSetting.value.openDrawer()
|
nodeSetting.value.openDrawer()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="end-node-wrapper">
|
<div class="end-node-wrapper">
|
||||||
<div class="end-node-box">
|
<div class="end-node-box" :class="taskStatusClass">
|
||||||
<span class="node-fixed-name" title="结束">结束</span>
|
<span class="node-fixed-name" title="结束">结束</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
|
import { SimpleFlowNode } from '../consts'
|
||||||
|
import { useWatchNode, useTaskStatusClass } from '../node'
|
||||||
|
|
||||||
defineOptions({
|
defineOptions({
|
||||||
name: 'EndEventNode'
|
name: 'EndEventNode'
|
||||||
})
|
})
|
||||||
|
const props = defineProps({
|
||||||
|
flowNode: {
|
||||||
|
type: Object as () => SimpleFlowNode,
|
||||||
|
default: () => null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// 监控节点变化
|
||||||
|
const currentNode = useWatchNode(props)
|
||||||
|
// 节点任务状态样式
|
||||||
|
const taskStatusClass = useTaskStatusClass(currentNode.value?.activityStatus)
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="branch-node-wrapper">
|
<div class="branch-node-wrapper">
|
||||||
<div class="branch-node-container">
|
<div class="branch-node-container">
|
||||||
<el-button class="branch-node-add" color="#67c23a" @click="addCondition" plain>添加条件</el-button>
|
<div v-if="readonly" class="branch-node-readonly" :class="taskStatusClass">
|
||||||
|
<span class="iconfont icon-exclusive icon-size"></span>
|
||||||
|
</div>
|
||||||
|
<el-button v-else class="branch-node-add" color="#67c23a" @click="addCondition" plain
|
||||||
|
>添加条件</el-button
|
||||||
|
>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="branch-node-item"
|
class="branch-node-item"
|
||||||
v-for="(item, index) in currentNode.conditionNodes"
|
v-for="(item, index) in currentNode.conditionNodes"
|
||||||
|
@ -17,9 +23,9 @@
|
||||||
</template>
|
</template>
|
||||||
<div class="node-wrapper">
|
<div class="node-wrapper">
|
||||||
<div class="node-container">
|
<div class="node-container">
|
||||||
<div class="node-box" :class="{ 'node-config-error': !item.showText }">
|
<div class="node-box" :class="[{ 'node-config-error': !item.showText }, `${useTaskStatusClass(item.activityStatus)}`]">
|
||||||
<div class="branch-node-title-container">
|
<div class="branch-node-title-container">
|
||||||
<div v-if="showInputs[index]">
|
<div v-if="!readonly && showInputs[index]">
|
||||||
<input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
class="input-max-width editable-title-input"
|
class="input-max-width editable-title-input"
|
||||||
|
@ -39,7 +45,10 @@
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="node-toolbar" v-if="index + 1 !== currentNode.conditionNodes?.length">
|
<div
|
||||||
|
class="node-toolbar"
|
||||||
|
v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length"
|
||||||
|
>
|
||||||
<div class="toolbar-icon">
|
<div class="toolbar-icon">
|
||||||
<Icon
|
<Icon
|
||||||
color="#0089ff"
|
color="#0089ff"
|
||||||
|
@ -87,6 +96,7 @@ import NodeHandler from '../NodeHandler.vue'
|
||||||
import ProcessNodeTree from '../ProcessNodeTree.vue'
|
import ProcessNodeTree from '../ProcessNodeTree.vue'
|
||||||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
|
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
|
||||||
import { getDefaultConditionNodeName } from '../utils'
|
import { getDefaultConditionNodeName } from '../utils'
|
||||||
|
import { useTaskStatusClass } from '../node'
|
||||||
import { generateUUID } from '@/utils'
|
import { generateUUID } from '@/utils'
|
||||||
import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
|
import ConditionNodeConfig from '../nodes-config/ConditionNodeConfig.vue'
|
||||||
const { proxy } = getCurrentInstance() as any
|
const { proxy } = getCurrentInstance() as any
|
||||||
|
@ -109,9 +119,11 @@ const emits = defineEmits<{
|
||||||
nodeType: number
|
nodeType: number
|
||||||
]
|
]
|
||||||
}>()
|
}>()
|
||||||
|
// 是否只读
|
||||||
|
const readonly = inject<Boolean>('readonly')
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
// const conditionNodes = computed(() => currentNode.value.conditionNodes);
|
// 节点状态样式
|
||||||
|
const taskStatusClass = useTaskStatusClass(currentNode.value?.activityStatus)
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.flowNode,
|
() => props.flowNode,
|
||||||
|
@ -135,6 +147,9 @@ const clickEvent = (index: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditionNodeConfig = (nodeId: string) => {
|
const conditionNodeConfig = (nodeId: string) => {
|
||||||
|
if (readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const conditionNode = proxy.$refs[nodeId][0]
|
const conditionNode = proxy.$refs[nodeId][0]
|
||||||
conditionNode.open()
|
conditionNode.open()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="branch-node-wrapper">
|
<div class="branch-node-wrapper">
|
||||||
<div class="branch-node-container">
|
<div class="branch-node-container">
|
||||||
<el-button class="branch-node-add" color="#345da2" @click="addCondition" plain>添加条件</el-button>
|
<div v-if="readonly" class="branch-node-readonly">
|
||||||
|
<span class="iconfont icon-inclusive icon-size"></span>
|
||||||
|
</div>
|
||||||
|
<el-button v-else class="branch-node-add" color="#345da2" @click="addCondition" plain>添加条件</el-button>
|
||||||
<div
|
<div
|
||||||
class="branch-node-item"
|
class="branch-node-item"
|
||||||
v-for="(item, index) in currentNode.conditionNodes"
|
v-for="(item, index) in currentNode.conditionNodes"
|
||||||
|
@ -38,7 +41,7 @@
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="node-toolbar" v-if="index + 1 !== currentNode.conditionNodes?.length">
|
<div class="node-toolbar" v-if="!readonly && index + 1 !== currentNode.conditionNodes?.length">
|
||||||
<div class="toolbar-icon">
|
<div class="toolbar-icon">
|
||||||
<Icon
|
<Icon
|
||||||
color="#0089ff"
|
color="#0089ff"
|
||||||
|
@ -50,7 +53,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="branch-node-move move-node-left"
|
class="branch-node-move move-node-left"
|
||||||
v-if="index != 0 && index + 1 !== currentNode.conditionNodes?.length"
|
v-if="!readonly && index != 0 && index + 1 !== currentNode.conditionNodes?.length"
|
||||||
@click="moveNode(index, -1)"
|
@click="moveNode(index, -1)"
|
||||||
>
|
>
|
||||||
<Icon icon="ep:arrow-left" />
|
<Icon icon="ep:arrow-left" />
|
||||||
|
@ -58,7 +61,7 @@
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="branch-node-move move-node-right"
|
class="branch-node-move move-node-right"
|
||||||
v-if="currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
|
v-if="!readonly && currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
|
||||||
@click="moveNode(index, 1)"
|
@click="moveNode(index, 1)"
|
||||||
>
|
>
|
||||||
<Icon icon="ep:arrow-right" />
|
<Icon icon="ep:arrow-right" />
|
||||||
|
@ -108,6 +111,8 @@ const emits = defineEmits<{
|
||||||
nodeType: number
|
nodeType: number
|
||||||
]
|
]
|
||||||
}>()
|
}>()
|
||||||
|
// 是否只读
|
||||||
|
const readonly = inject<Boolean>('readonly')
|
||||||
|
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
|
|
||||||
|
@ -133,6 +138,9 @@ const clickEvent = (index: number) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const conditionNodeConfig = (nodeId: string) => {
|
const conditionNodeConfig = (nodeId: string) => {
|
||||||
|
if (readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const conditionNode = proxy.$refs[nodeId][0]
|
const conditionNode = proxy.$refs[nodeId][0]
|
||||||
conditionNode.open()
|
conditionNode.open()
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="branch-node-wrapper">
|
<div class="branch-node-wrapper">
|
||||||
<div class="branch-node-container">
|
<div class="branch-node-container">
|
||||||
<el-button class="branch-node-add" color="#626aef" @click="addCondition" plain>添加分支</el-button>
|
<div v-if="readonly" class="branch-node-readonly">
|
||||||
|
<span class="iconfont icon-parallel icon-size"></span>
|
||||||
|
</div>
|
||||||
|
<el-button v-else class="branch-node-add" color="#626aef" @click="addCondition" plain>添加分支</el-button>
|
||||||
<div
|
<div
|
||||||
class="branch-node-item"
|
class="branch-node-item"
|
||||||
v-for="(item, index) in currentNode.conditionNodes"
|
v-for="(item, index) in currentNode.conditionNodes"
|
||||||
|
@ -39,7 +42,7 @@
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="node-toolbar">
|
<div v-if="!readonly" class="node-toolbar">
|
||||||
<div class="toolbar-icon">
|
<div class="toolbar-icon">
|
||||||
<Icon
|
<Icon
|
||||||
color="#0089ff"
|
color="#0089ff"
|
||||||
|
@ -49,18 +52,6 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div
|
|
||||||
class="branch-node-move move-node-left"
|
|
||||||
v-if="index != 0 && index + 1 !== currentNode.conditionNodes?.length" @click="moveNode(index, -1)">
|
|
||||||
<Icon icon="ep:arrow-left" />
|
|
||||||
</div> -->
|
|
||||||
|
|
||||||
<!-- <div
|
|
||||||
class="branch-node-move move-node-right"
|
|
||||||
v-if="currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
|
|
||||||
@click="moveNode(index, 1)">
|
|
||||||
<Icon icon="ep:arrow-right" />
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
<NodeHandler v-model:child-node="item.childNode" />
|
<NodeHandler v-model:child-node="item.childNode" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -106,6 +97,8 @@ const emits = defineEmits<{
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
const currentNode = ref<SimpleFlowNode>(props.flowNode)
|
||||||
|
// 是否只读
|
||||||
|
const readonly = inject<Boolean>('readonly')
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => props.flowNode,
|
() => props.flowNode,
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="node-wrapper">
|
<div class="node-wrapper">
|
||||||
<div class="node-container">
|
<div class="node-container">
|
||||||
<div class="node-box" :class="{ 'node-config-error': !currentNode.showText }">
|
<div
|
||||||
|
class="node-box"
|
||||||
|
:class="[{ 'node-config-error': !currentNode.showText }, `${taskStatusClass}`]"
|
||||||
|
>
|
||||||
<div class="node-title-container">
|
<div class="node-title-container">
|
||||||
<div class="node-title-icon start-user"
|
<div class="node-title-icon start-user"
|
||||||
><span class="iconfont icon-start-user"></span
|
><span class="iconfont icon-start-user"></span
|
||||||
|
@ -26,18 +29,18 @@
|
||||||
<div class="node-text" v-else>
|
<div class="node-text" v-else>
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.START_USER_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.START_USER_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
<Icon icon="ep:arrow-right-bold" />
|
<Icon icon="ep:arrow-right-bold" v-if="!readonly" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
|
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
|
||||||
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
<NodeHandler v-if="currentNode" v-model:child-node="currentNode.childNode" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<StartUserNodeConfig v-if="currentNode" ref="nodeSetting" :flow-node="currentNode" />
|
<StartUserNodeConfig v-if="!readonly && currentNode" ref="nodeSetting" :flow-node="currentNode" />
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import NodeHandler from '../NodeHandler.vue'
|
import NodeHandler from '../NodeHandler.vue'
|
||||||
import { useWatchNode, useNodeName2 } from '../node'
|
import { useWatchNode, useNodeName2, useTaskStatusClass } from '../node'
|
||||||
import { SimpleFlowNode, NODE_DEFAULT_TEXT, NodeType } from '../consts'
|
import { SimpleFlowNode, NODE_DEFAULT_TEXT, NodeType } from '../consts'
|
||||||
import StartUserNodeConfig from '../nodes-config/StartUserNodeConfig.vue'
|
import StartUserNodeConfig from '../nodes-config/StartUserNodeConfig.vue'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -49,21 +52,28 @@ const props = defineProps({
|
||||||
default: () => null
|
default: () => null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
const readonly = inject<Boolean>('readonly') // 是否只读
|
||||||
// 定义事件,更新父组件。
|
// 定义事件,更新父组件。
|
||||||
const emits = defineEmits<{
|
const emits = defineEmits<{
|
||||||
'update:modelValue': [node: SimpleFlowNode | undefined]
|
'update:modelValue': [node: SimpleFlowNode | undefined]
|
||||||
}>()
|
}>()
|
||||||
// 监控节点变化
|
// 监控节点变化
|
||||||
const currentNode = useWatchNode(props)
|
const currentNode = useWatchNode(props)
|
||||||
|
// 节点任务状态样式
|
||||||
|
const taskStatusClass = useTaskStatusClass(currentNode.value?.activityStatus)
|
||||||
// 节点名称编辑
|
// 节点名称编辑
|
||||||
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
||||||
|
|
||||||
const nodeSetting = ref()
|
const nodeSetting = ref()
|
||||||
// 打开节点配置
|
// 打开节点配置
|
||||||
const openNodeConfig = () => {
|
const openNodeConfig = () => {
|
||||||
|
if (readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 把当前节点传递给配置组件
|
// 把当前节点传递给配置组件
|
||||||
nodeSetting.value.showStartUserNodeConfig(currentNode.value)
|
nodeSetting.value.showStartUserNodeConfig(currentNode.value)
|
||||||
nodeSetting.value.openDrawer()
|
nodeSetting.value.openDrawer()
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped></style>
|
<style lang="scss" scoped></style>
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="node-wrapper">
|
<div class="node-wrapper">
|
||||||
<div class="node-container">
|
<div class="node-container">
|
||||||
<div class="node-box" :class="{ 'node-config-error': !currentNode.showText }">
|
<div
|
||||||
|
class="node-box"
|
||||||
|
:class="[{ 'node-config-error': !currentNode.showText }, `${taskStatusClass}`]"
|
||||||
|
>
|
||||||
<div class="node-title-container">
|
<div class="node-title-container">
|
||||||
<div class="node-title-icon user-task"><span class="iconfont icon-approve"></span></div>
|
<div class="node-title-icon user-task"><span class="iconfont icon-approve"></span></div>
|
||||||
<input
|
<input
|
||||||
v-if="showInput"
|
v-if="!readonly && showInput"
|
||||||
type="text"
|
type="text"
|
||||||
class="editable-title-input"
|
class="editable-title-input"
|
||||||
@blur="blurEvent()"
|
@blur="blurEvent()"
|
||||||
|
@ -24,9 +27,9 @@
|
||||||
<div class="node-text" v-else>
|
<div class="node-text" v-else>
|
||||||
{{ NODE_DEFAULT_TEXT.get(NodeType.USER_TASK_NODE) }}
|
{{ NODE_DEFAULT_TEXT.get(NodeType.USER_TASK_NODE) }}
|
||||||
</div>
|
</div>
|
||||||
<Icon icon="ep:arrow-right-bold" />
|
<Icon icon="ep:arrow-right-bold" v-if="!readonly" />
|
||||||
</div>
|
</div>
|
||||||
<div class="node-toolbar">
|
<div v-if="!readonly" class="node-toolbar">
|
||||||
<div class="toolbar-icon"
|
<div class="toolbar-icon"
|
||||||
><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
|
><Icon color="#0089ff" icon="ep:circle-close-filled" :size="18" @click="deleteNode"
|
||||||
/></div>
|
/></div>
|
||||||
|
@ -45,7 +48,7 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
|
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
|
||||||
import { useWatchNode, useNodeName2 } from '../node'
|
import { useWatchNode, useNodeName2, useTaskStatusClass } from '../node'
|
||||||
import NodeHandler from '../NodeHandler.vue'
|
import NodeHandler from '../NodeHandler.vue'
|
||||||
import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'
|
import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'
|
||||||
defineOptions({
|
defineOptions({
|
||||||
|
@ -61,13 +64,21 @@ const emits = defineEmits<{
|
||||||
'update:flowNode': [node: SimpleFlowNode | undefined]
|
'update:flowNode': [node: SimpleFlowNode | undefined]
|
||||||
'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
|
'find:parentNode': [nodeList: SimpleFlowNode[], nodeType: NodeType]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
|
// 是否只读
|
||||||
|
const readonly = inject<Boolean>('readonly')
|
||||||
// 监控节点变化
|
// 监控节点变化
|
||||||
const currentNode = useWatchNode(props)
|
const currentNode = useWatchNode(props)
|
||||||
|
// 节点状态样式
|
||||||
|
const taskStatusClass = useTaskStatusClass(currentNode.value?.activityStatus)
|
||||||
// 节点名称编辑
|
// 节点名称编辑
|
||||||
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
||||||
const nodeSetting = ref()
|
const nodeSetting = ref()
|
||||||
// 打开节点配置
|
// 打开节点配置
|
||||||
const openNodeConfig = () => {
|
const openNodeConfig = () => {
|
||||||
|
if (readonly) {
|
||||||
|
return
|
||||||
|
}
|
||||||
// 把当前节点传递给配置组件
|
// 把当前节点传递给配置组件
|
||||||
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
|
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
|
||||||
nodeSetting.value.openDrawer()
|
nodeSetting.value.openDrawer()
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
.simple-flow-canvas {
|
.simple-flow-canvas {
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background-color: #fafafa;
|
background-color: #fafafa;
|
||||||
user-select: none;
|
// user-select: none;
|
||||||
|
|
||||||
.simple-flow-container {
|
.simple-flow-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -84,12 +82,32 @@
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border: 2px solid transparent;
|
border: 2px solid transparent;
|
||||||
// border-color: #0089ff;
|
|
||||||
border-radius: 8px;
|
border-radius: 8px;
|
||||||
// border-color: #0089ff;
|
|
||||||
box-shadow: 0 1px 4px 0 rgba(10, 30, 65, 0.16);
|
box-shadow: 0 1px 4px 0 rgba(10, 30, 65, 0.16);
|
||||||
transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
transition: all 0.1s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||||
|
|
||||||
|
&.status-pass {
|
||||||
|
border-color: #67c23a;
|
||||||
|
background-color: #a9da90;
|
||||||
|
}
|
||||||
|
&.status-pass:hover {
|
||||||
|
border-color: #67c23a;
|
||||||
|
}
|
||||||
|
&.status-running {
|
||||||
|
border-color: #5a9cf8;
|
||||||
|
background-color: #e7f0fe;
|
||||||
|
}
|
||||||
|
&.status-running:hover {
|
||||||
|
border-color: #5a9cf8;
|
||||||
|
}
|
||||||
|
&.status-reject {
|
||||||
|
border-color: #e47470;
|
||||||
|
background-color: #f6e5e5;
|
||||||
|
}
|
||||||
|
&.status-reject:hover {
|
||||||
|
border-color: #e47470;
|
||||||
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: #0089ff;
|
border-color: #0089ff;
|
||||||
.node-toolbar {
|
.node-toolbar {
|
||||||
|
@ -280,15 +298,10 @@
|
||||||
|
|
||||||
&::before {
|
&::before {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top:0;
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
// bottom: 5px;
|
|
||||||
bottom: 0px;
|
|
||||||
z-index: 0;
|
z-index: 0;
|
||||||
width: 2px;
|
width: 2px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
// height: calc(100% - 5px);
|
|
||||||
margin: auto;
|
margin: auto;
|
||||||
background-color: #dedede;
|
background-color: #dedede;
|
||||||
content: '';
|
content: '';
|
||||||
|
@ -361,6 +374,36 @@
|
||||||
transform-origin: center center;
|
transform-origin: center center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.branch-node-readonly {
|
||||||
|
position: absolute;
|
||||||
|
top: -18px;
|
||||||
|
left: 50%;
|
||||||
|
z-index: 1;
|
||||||
|
width: 36px;
|
||||||
|
height: 36px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
border: 2px solid #dedede;
|
||||||
|
background-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
transform-origin: center center;
|
||||||
|
|
||||||
|
&.status-pass {
|
||||||
|
border-color: #6bb63c;
|
||||||
|
background-color: #e9f4e2;
|
||||||
|
}
|
||||||
|
&.status-pass:hover {
|
||||||
|
border-color: #6bb63c;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-size {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #67c23a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.branch-node-item {
|
.branch-node-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -454,7 +497,6 @@
|
||||||
padding: 3px 4px;
|
padding: 3px 4px;
|
||||||
color: #212121;
|
color: #212121;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
// background: #2c2c2c;
|
|
||||||
background: #fafafa;
|
background: #fafafa;
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
||||||
|
@ -473,12 +515,36 @@
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 36px;
|
height: 36px;
|
||||||
|
border: 2px solid #fafafa;
|
||||||
color: #212121;
|
color: #212121;
|
||||||
// background: #6e6e6e;
|
|
||||||
background: #fafafa;
|
|
||||||
border-radius: 30px;
|
border-radius: 30px;
|
||||||
box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
&.status-pass {
|
||||||
|
border-color: #6bb63c;
|
||||||
|
background-color: #a9da90;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-pass:hover {
|
||||||
|
border-color: #6bb63c;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-reject {
|
||||||
|
border-color: #e47470;
|
||||||
|
background-color: #f6e5e5;
|
||||||
|
}
|
||||||
|
&.status-reject:hover {
|
||||||
|
border-color: #e47470;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.status-cancel {
|
||||||
|
border-color: #919398;
|
||||||
|
background-color: #eaeaeb
|
||||||
|
}
|
||||||
|
&.status-cancel:hover {
|
||||||
|
border-color: #919398;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,160 @@
|
||||||
|
<template>
|
||||||
|
<el-card v-loading="loading" class="box-card">
|
||||||
|
<SimpleProcessViewer :flow-node="simpleModel" />
|
||||||
|
</el-card>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { propTypes } from '@/utils/propTypes'
|
||||||
|
import { TaskStatusEnum } from '@/api/bpm/task'
|
||||||
|
import { BpmProcessInstanceStatus } from '@/utils/constants'
|
||||||
|
import { SimpleFlowNode, NodeType } from '@/components/SimpleProcessDesignerV2/src/consts'
|
||||||
|
import { SimpleProcessViewer } from '@/components/SimpleProcessDesignerV2/src/'
|
||||||
|
import * as ProcessInstanceApi from '@/api/bpm/processInstance'
|
||||||
|
|
||||||
|
defineOptions({ name: 'BpmProcessInstanceSimpleViewer' })
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
loading: propTypes.bool.def(false), // 是否加载中
|
||||||
|
id: propTypes.string // 流程实例的编号
|
||||||
|
})
|
||||||
|
|
||||||
|
// const view = ref({
|
||||||
|
// simpleModel: undefined
|
||||||
|
// }) // simple 模型数据
|
||||||
|
|
||||||
|
const simpleModel = ref()
|
||||||
|
|
||||||
|
/** 只有 loading 完成时,才去加载流程列表 */
|
||||||
|
watch(
|
||||||
|
() => props.loading,
|
||||||
|
async (value) => {
|
||||||
|
if (value && props.id) {
|
||||||
|
const modelView = await ProcessInstanceApi.getProcessInstanceBpmnModelView(props.id)
|
||||||
|
if (modelView) {
|
||||||
|
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
||||||
|
const rejectedTaskActivityIds: string[] = modelView.rejectedTaskActivityIds
|
||||||
|
// 进行中的活动节点编号集合, 只包括 UserTask
|
||||||
|
const unfinishedTaskActivityIds: string[] = modelView.unfinishedTaskActivityIds
|
||||||
|
// 已经完成的活动节点编号集合, 包括 UserTask、Gateway 等
|
||||||
|
const finishedActivityIds: string[] = modelView.finishedTaskActivityIds
|
||||||
|
// 已经完成的连线节点编号集合,只包括 SequenceFlow
|
||||||
|
const finishedSequenceFlowActivityIds: string[] = modelView.finishedSequenceFlowActivityIds
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
modelView.simpleModel,
|
||||||
|
modelView.processInstance.status,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds
|
||||||
|
)
|
||||||
|
console.log("modelView.simpleModel==>", modelView.simpleModel)
|
||||||
|
simpleModel.value = modelView.simpleModel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
const setSimpleModelNodeTaskStatus = (
|
||||||
|
simpleModel: SimpleFlowNode | undefined,
|
||||||
|
processStatus: number,
|
||||||
|
rejectedTaskActivityIds: string[],
|
||||||
|
unfinishedTaskActivityIds: string[],
|
||||||
|
finishedActivityIds: string[],
|
||||||
|
finishedSequenceFlowActivityIds: string[],
|
||||||
|
|
||||||
|
) => {
|
||||||
|
if (!simpleModel) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// 结束节点
|
||||||
|
if (simpleModel.type === NodeType.END_EVENT_NODE) {
|
||||||
|
if (finishedActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = processStatus
|
||||||
|
} else {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 审批节点
|
||||||
|
if (
|
||||||
|
simpleModel.type === NodeType.START_USER_NODE ||
|
||||||
|
simpleModel.type === NodeType.USER_TASK_NODE
|
||||||
|
) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||||
|
if (rejectedTaskActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.REJECT
|
||||||
|
} else if(unfinishedTaskActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.RUNNING
|
||||||
|
} else if (finishedActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.APPROVE
|
||||||
|
}
|
||||||
|
// TODO 是不是还缺一个 cancel 的状态
|
||||||
|
}
|
||||||
|
|
||||||
|
// 抄送节点
|
||||||
|
if (simpleModel.type === NodeType.COPY_TASK_NODE) {
|
||||||
|
// 抄送节点 只有通过和未执行状态
|
||||||
|
if (finishedActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.APPROVE
|
||||||
|
} else {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 条件节点 对应 SequenceFlow
|
||||||
|
if (simpleModel.type === NodeType.CONDITION_NODE) {
|
||||||
|
// 条件节点。只有通过和未执行状态
|
||||||
|
if (finishedSequenceFlowActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.APPROVE
|
||||||
|
} else {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 网关节点
|
||||||
|
if (
|
||||||
|
simpleModel.type === NodeType.CONDITION_BRANCH_NODE ||
|
||||||
|
simpleModel.type === NodeType.PARALLEL_BRANCH_NODE ||
|
||||||
|
simpleModel.type === NodeType.INCLUSIVE_BRANCH_NODE
|
||||||
|
) {
|
||||||
|
// 网关节点。只有通过和未执行状态
|
||||||
|
if (finishedActivityIds.includes(simpleModel.id)) {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.APPROVE
|
||||||
|
} else {
|
||||||
|
simpleModel.activityStatus = TaskStatusEnum.NOT_START
|
||||||
|
}
|
||||||
|
simpleModel.conditionNodes?.forEach((node) => {
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
node,
|
||||||
|
processStatus,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
setSimpleModelNodeTaskStatus(
|
||||||
|
simpleModel.childNode,
|
||||||
|
processStatus,
|
||||||
|
rejectedTaskActivityIds,
|
||||||
|
unfinishedTaskActivityIds,
|
||||||
|
finishedActivityIds,
|
||||||
|
finishedSequenceFlowActivityIds
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/** 监听 bpmnXml */
|
||||||
|
// watch(
|
||||||
|
// () => props.bpmnXml,
|
||||||
|
// (value) => {
|
||||||
|
// view.value.bpmnXml = value
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.box-card {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<SimpleProcessDesigner :model-id="modelId" />
|
<ContentWrap :bodyStyle="{ padding: '0px 0px' }" class="position-relative">
|
||||||
|
<SimpleProcessDesigner :model-id="modelId" />
|
||||||
|
</ContentWrap>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { SimpleProcessDesigner } from '@/components/SimpleProcessDesignerV2/src/'
|
import { SimpleProcessDesigner } from '@/components/SimpleProcessDesignerV2/src/'
|
||||||
|
|
Loading…
Reference in New Issue