【功能完善】仿钉钉流程模型浏览,增加弹窗显示用户任务信息
parent
7044bcee60
commit
8465f8fada
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<SimpleProcessModel :flow-node="simpleModel" :readonly="true"/>
|
||||
<SimpleProcessModel :flow-node="simpleModel" :readonly="true" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
|
@ -16,10 +16,33 @@ const props = defineProps({
|
|||
required: true
|
||||
},
|
||||
// 流程任务
|
||||
tasks : {
|
||||
type : Array,
|
||||
tasks: {
|
||||
type: Array,
|
||||
default: () => [] as any[]
|
||||
},
|
||||
// 流程实例
|
||||
processInstance: {
|
||||
type: Object,
|
||||
default: () => undefined
|
||||
}
|
||||
})
|
||||
const approveTasks = ref<any[]>(props.tasks)
|
||||
const currentProcessInstance = ref(props.processInstance)
|
||||
const simpleModel = useWatchNode(props)
|
||||
watch(
|
||||
() => props.tasks,
|
||||
(newValue) => {
|
||||
approveTasks.value = newValue
|
||||
}
|
||||
)
|
||||
watch(
|
||||
() => props.processInstance,
|
||||
(newValue) => {
|
||||
currentProcessInstance.value = newValue
|
||||
}
|
||||
)
|
||||
|
||||
provide('tasks', approveTasks)
|
||||
provide('processInstance', currentProcessInstance)
|
||||
</script>
|
||||
p
|
||||
|
|
|
@ -1,14 +1,69 @@
|
|||
<template>
|
||||
<div class="end-node-wrapper">
|
||||
<div class="end-node-box" :class="`${useTaskStatusClass(currentNode?.activityStatus)}`">
|
||||
<div class="end-node-box cursor-pointer" :class="`${useTaskStatusClass(currentNode?.activityStatus)}`" @click="nodeClick">
|
||||
<span class="node-fixed-name" title="结束">结束</span>
|
||||
</div>
|
||||
</div>
|
||||
<el-dialog title="审批信息" v-model="dialogVisible" width="1000px" append-to-body>
|
||||
<el-row>
|
||||
<el-table
|
||||
:data="processInstanceInfos"
|
||||
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="发起人"
|
||||
prop="assigneeUser.nickname"
|
||||
min-width="100"
|
||||
align="center"
|
||||
/>
|
||||
<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_PROCESS_INSTANCE_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<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">
|
||||
import { SimpleFlowNode } from '../consts'
|
||||
import { useWatchNode, useTaskStatusClass } from '../node'
|
||||
|
||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
defineOptions({
|
||||
name: 'EndEventNode'
|
||||
})
|
||||
|
@ -20,6 +75,28 @@ const props = defineProps({
|
|||
})
|
||||
// 监控节点变化
|
||||
const currentNode = useWatchNode(props)
|
||||
// 是否只读
|
||||
const readonly = inject<Boolean>('readonly')
|
||||
const processInstance = inject<Ref<any>>('processInstance')
|
||||
// 审批信息的弹窗显示,用于只读模式
|
||||
const dialogVisible = ref(false) // 弹窗可见性
|
||||
const processInstanceInfos = ref<any[]>([]) // 流程的审批信息
|
||||
|
||||
const nodeClick = () => {
|
||||
if (readonly) {
|
||||
if(processInstance && processInstance.value){
|
||||
processInstanceInfos.value = [
|
||||
{
|
||||
assigneeUser: processInstance.value.startUser,
|
||||
createTime: processInstance.value.startTime,
|
||||
endTime: processInstance.value.endTime,
|
||||
status: processInstance.value.status,
|
||||
durationInMillis: processInstance.value.durationInMillis
|
||||
}
|
||||
]
|
||||
dialogVisible.value = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
{{ currentNode.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="node-content" @click="openNodeConfig">
|
||||
<div class="node-content" @click="nodeClick">
|
||||
<div class="node-text" :title="currentNode.showText" v-if="currentNode.showText">
|
||||
{{ currentNode.showText }}
|
||||
</div>
|
||||
|
@ -37,12 +37,78 @@
|
|||
</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>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import NodeHandler from '../NodeHandler.vue'
|
||||
import { useWatchNode, useNodeName2, useTaskStatusClass } from '../node'
|
||||
import { SimpleFlowNode, NODE_DEFAULT_TEXT, NodeType } from '../consts'
|
||||
import StartUserNodeConfig from '../nodes-config/StartUserNodeConfig.vue'
|
||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
defineOptions({
|
||||
name: 'StartEventNode'
|
||||
})
|
||||
|
@ -53,6 +119,7 @@ const props = defineProps({
|
|||
}
|
||||
})
|
||||
const readonly = inject<Boolean>('readonly') // 是否只读
|
||||
const tasks = inject<Ref<any[]>>('tasks')
|
||||
// 定义事件,更新父组件。
|
||||
const emits = defineEmits<{
|
||||
'update:modelValue': [node: SimpleFlowNode | undefined]
|
||||
|
@ -63,15 +130,27 @@ const currentNode = useWatchNode(props)
|
|||
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
||||
|
||||
const nodeSetting = ref()
|
||||
// 打开节点配置
|
||||
const openNodeConfig = () => {
|
||||
//
|
||||
const nodeClick = () => {
|
||||
if (readonly) {
|
||||
return
|
||||
// 只读模式,弹窗显示任务信息
|
||||
if(tasks && tasks.value){
|
||||
dialogTitle.value = currentNode.value.name
|
||||
selectTasks.value = tasks.value.filter((item: any) => item?.taskDefinitionKey === currentNode.value.id)
|
||||
dialogVisible.value = true
|
||||
}
|
||||
} else {
|
||||
// 编辑模式,打开节点配置、把当前节点传递给配置组件
|
||||
nodeSetting.value.showStartUserNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
}
|
||||
// 把当前节点传递给配置组件
|
||||
nodeSetting.value.showStartUserNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
|
||||
}
|
||||
|
||||
// 任务的弹窗显示,用于只读模式
|
||||
const dialogVisible = ref(false) // 弹窗可见性
|
||||
const dialogTitle = ref<string | undefined>(undefined) // 弹窗标题
|
||||
const selectTasks = ref<any[]|undefined>([]) // 选中的任务数组
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
{{ currentNode.name }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="node-content" @click="openNodeConfig">
|
||||
<div class="node-content" @click="nodeClick">
|
||||
<div class="node-text" :title="currentNode.showText" v-if="currentNode.showText">
|
||||
{{ currentNode.showText }}
|
||||
</div>
|
||||
|
@ -45,12 +45,78 @@
|
|||
:flow-node="currentNode"
|
||||
@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>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from '../consts'
|
||||
import { useWatchNode, useNodeName2, useTaskStatusClass } from '../node'
|
||||
import NodeHandler from '../NodeHandler.vue'
|
||||
import UserTaskNodeConfig from '../nodes-config/UserTaskNodeConfig.vue'
|
||||
import { dateFormatter, formatPast2 } from '@/utils/formatTime'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
defineOptions({
|
||||
name: 'UserTaskNode'
|
||||
})
|
||||
|
@ -67,26 +133,32 @@ const emits = defineEmits<{
|
|||
|
||||
// 是否只读
|
||||
const readonly = inject<Boolean>('readonly')
|
||||
const tasks = inject<Ref<any[]>>('tasks')
|
||||
// 监控节点变化
|
||||
const currentNode = useWatchNode(props)
|
||||
|
||||
// 节点名称编辑
|
||||
const { showInput, blurEvent, clickTitle } = useNodeName2(currentNode, NodeType.START_USER_NODE)
|
||||
const nodeSetting = ref()
|
||||
// 打开节点配置
|
||||
const openNodeConfig = () => {
|
||||
if (readonly) {
|
||||
return
|
||||
|
||||
|
||||
const nodeClick = () => {
|
||||
if (readonly) {
|
||||
if(tasks && tasks.value){
|
||||
dialogTitle.value = currentNode.value.name
|
||||
// 只读模式,弹窗显示任务信息
|
||||
selectTasks.value = tasks.value.filter((item: any) => item?.taskDefinitionKey === currentNode.value.id)
|
||||
dialogVisible.value = true
|
||||
}
|
||||
} else {
|
||||
// 编辑模式,打开节点配置、把当前节点传递给配置组件
|
||||
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
}
|
||||
// 把当前节点传递给配置组件
|
||||
nodeSetting.value.showUserTaskNodeConfig(currentNode.value)
|
||||
nodeSetting.value.openDrawer()
|
||||
}
|
||||
|
||||
const deleteNode = () => {
|
||||
emits('update:flowNode', currentNode.value.childNode)
|
||||
}
|
||||
|
||||
// 查找可以驳回用户节点
|
||||
const findReturnTaskNodes = (
|
||||
matchNodeList: SimpleFlowNode[] // 匹配的节点
|
||||
|
@ -94,5 +166,11 @@ const findReturnTaskNodes = (
|
|||
// 从父节点查找
|
||||
emits('find:parentNode', matchNodeList, NodeType.USER_TASK_NODE)
|
||||
}
|
||||
|
||||
// 任务的弹窗显示,用于只读模式
|
||||
const dialogVisible = ref(false) // 弹窗可见性
|
||||
const dialogTitle = ref<string | undefined>(undefined) // 弹窗标题
|
||||
const selectTasks = ref<any[]|undefined>([]) // 选中的任务数组
|
||||
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
|
|
|
@ -1,573 +1,3 @@
|
|||
// .simple-flow-canvas {
|
||||
// z-index: 1;
|
||||
// overflow: auto;
|
||||
// background-color: #fafafa;
|
||||
// // user-select: none;
|
||||
|
||||
// .simple-flow-container {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
|
||||
// .top-area-container {
|
||||
// position: sticky;
|
||||
// inset: 0;
|
||||
// display: flex;
|
||||
// width: 100%;
|
||||
// height: 42px;
|
||||
// z-index: 1;
|
||||
// // padding: 4px 0;
|
||||
// background-color: #fff;
|
||||
// justify-content: flex-end;
|
||||
// align-items: center;
|
||||
|
||||
// .top-actions {
|
||||
// display: flex;
|
||||
// margin: 4px;
|
||||
// margin-right: 8px;
|
||||
// align-items: center;
|
||||
|
||||
// .canvas-control {
|
||||
// font-size: 16px;
|
||||
|
||||
// .control-scale-group {
|
||||
// display: inline-flex;
|
||||
// align-items: center;
|
||||
// margin-right: 8px;
|
||||
|
||||
// .control-scale-button {
|
||||
// display: inline-flex;
|
||||
// width: 28px;
|
||||
// height: 28px;
|
||||
// padding: 2px;
|
||||
// text-align: center;
|
||||
// cursor: pointer;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// }
|
||||
|
||||
// .control-scale-label {
|
||||
// margin: 0 4px;
|
||||
// font-size: 14px;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// .scale-container {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// margin-top: 16px;
|
||||
// background-color: #fafafa;
|
||||
// transform-origin: 50% 0 0;
|
||||
// transform: scale(1);
|
||||
// transition: transform 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
|
||||
|
||||
// // 节点容器 定义节点宽度
|
||||
// .node-container {
|
||||
// width: 200px;
|
||||
// }
|
||||
// // 节点
|
||||
// .node-box {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// min-height: 70px;
|
||||
// padding: 5px 10px 8px;
|
||||
// cursor: pointer;
|
||||
// background-color: #fff;
|
||||
// flex-direction: column;
|
||||
// border: 2px solid transparent;
|
||||
// border-radius: 8px;
|
||||
// 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);
|
||||
|
||||
// &.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 {
|
||||
// border-color: #0089ff;
|
||||
// .node-toolbar {
|
||||
// opacity: 1;
|
||||
// }
|
||||
|
||||
// .branch-node-move {
|
||||
// display: flex;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 普通节点标题
|
||||
// .node-title-container {
|
||||
// display: flex;
|
||||
// padding: 4px;
|
||||
// cursor: pointer;
|
||||
// border-radius: 4px 4px 0 0;
|
||||
// align-items: center;
|
||||
|
||||
// .node-title-icon {
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
|
||||
// &.user-task {
|
||||
// color: #ff943e;
|
||||
// }
|
||||
// &.copy-task {
|
||||
// color: #3296fa;
|
||||
// }
|
||||
// &.start-user {
|
||||
// color: #676565;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .node-title {
|
||||
// margin-left: 4px;
|
||||
// font-size: 14px;
|
||||
// font-weight: 600;
|
||||
// white-space: nowrap;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// color: #1f1f1f;
|
||||
// line-height: 18px;
|
||||
// &:hover {
|
||||
// border-bottom: 1px dashed #f60;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 条件节点标题
|
||||
// .branch-node-title-container {
|
||||
// display: flex;
|
||||
// padding: 4px 0;
|
||||
// cursor: pointer;
|
||||
// border-radius: 4px 4px 0 0;
|
||||
// align-items: center;
|
||||
// justify-content: space-between;
|
||||
|
||||
// .input-max-width {
|
||||
// max-width: 115px !important;
|
||||
// }
|
||||
|
||||
// .branch-title {
|
||||
// font-size: 13px;
|
||||
// font-weight: 600;
|
||||
// white-space: nowrap;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// color: #f60;
|
||||
// &:hover {
|
||||
// border-bottom: 1px dashed #000;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .branch-priority {
|
||||
// min-width: 50px;
|
||||
// font-size: 12px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .node-content {
|
||||
// display: flex;
|
||||
// min-height: 32px;
|
||||
// padding: 4px 8px;
|
||||
// margin-top: 4px;
|
||||
// line-height: 32px;
|
||||
// justify-content: space-between;
|
||||
// align-items: center;
|
||||
// color: #111f2c;
|
||||
// background: rgba(0, 0, 0, 0.03);
|
||||
// border-radius: 4px;
|
||||
|
||||
// .node-text {
|
||||
// display: -webkit-box;
|
||||
// overflow: hidden;
|
||||
// font-size: 14px;
|
||||
// line-height: 24px;
|
||||
// text-overflow: ellipsis;
|
||||
// word-break: break-all;
|
||||
// -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */
|
||||
// -webkit-box-orient: vertical;
|
||||
// }
|
||||
// }
|
||||
|
||||
// //条件节点内容
|
||||
// .branch-node-content {
|
||||
// display: flex;
|
||||
// min-height: 32px;
|
||||
// padding: 4px 0;
|
||||
// margin-top: 4px;
|
||||
// line-height: 32px;
|
||||
// align-items: center;
|
||||
// color: #111f2c;
|
||||
// border-radius: 4px;
|
||||
|
||||
// .branch-node-text {
|
||||
// overflow: hidden;
|
||||
// font-size: 12px;
|
||||
// line-height: 24px;
|
||||
// text-overflow: ellipsis;
|
||||
// word-break: break-all;
|
||||
// -webkit-line-clamp: 2; /* 这将限制文本显示为两行 */
|
||||
// -webkit-box-orient: vertical;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 节点操作 :删除
|
||||
// .node-toolbar {
|
||||
// opacity: 0;
|
||||
// position: absolute;
|
||||
// top: -20px;
|
||||
// right: 0px;
|
||||
// display: flex;
|
||||
|
||||
// .toolbar-icon {
|
||||
// text-align: center;
|
||||
// vertical-align: middle;
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 条件节点左右移动
|
||||
// .branch-node-move {
|
||||
// position: absolute;
|
||||
// width: 10px;
|
||||
// cursor: pointer;
|
||||
// display: none;
|
||||
// align-items: center;
|
||||
// height: 100%;
|
||||
// justify-content: center;
|
||||
// }
|
||||
|
||||
// .move-node-left {
|
||||
// left: -2px;
|
||||
// top: 0px;
|
||||
// background: rgba(126, 134, 142, 0.08);
|
||||
// border-top-left-radius: 8px;
|
||||
// border-bottom-left-radius: 8px;
|
||||
// }
|
||||
|
||||
// .move-node-right {
|
||||
// right: -2px;
|
||||
// top: 0px;
|
||||
// background: rgba(126, 134, 142, 0.08);
|
||||
// border-top-right-radius: 6px;
|
||||
// border-bottom-right-radius: 6px;
|
||||
// }
|
||||
// }
|
||||
|
||||
// .node-config-error {
|
||||
// border-color: #ff5219 !important;
|
||||
// }
|
||||
// // 普通节点包装
|
||||
// .node-wrapper {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// }
|
||||
// // 节点连线处理
|
||||
// .node-handler-wrapper {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// height: 70px;
|
||||
// align-items: center;
|
||||
// user-select: none;
|
||||
// justify-content: center;
|
||||
// flex-direction: column;
|
||||
|
||||
// &::before {
|
||||
// position: absolute;
|
||||
// top: 0;
|
||||
// z-index: 0;
|
||||
// width: 2px;
|
||||
// height: 100%;
|
||||
// margin: auto;
|
||||
// background-color: #dedede;
|
||||
// content: '';
|
||||
// }
|
||||
|
||||
// .node-handler {
|
||||
// .add-icon {
|
||||
// position: relative;
|
||||
// top: -5px;
|
||||
// display: flex;
|
||||
// align-items: center;
|
||||
// justify-content: center;
|
||||
// cursor: pointer;
|
||||
// width: 25px;
|
||||
// height: 25px;
|
||||
// color: #fff;
|
||||
// background-color: #0089ff;
|
||||
// border-radius: 50%;
|
||||
|
||||
// &:hover {
|
||||
// transform: scale(1.1);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// .node-handler-arrow {
|
||||
// position: absolute;
|
||||
// bottom: 0;
|
||||
// left: 50%;
|
||||
// display: flex;
|
||||
// transform: translateX(-50%);
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 条件节点包装
|
||||
// .branch-node-wrapper {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// margin-top: 16px;
|
||||
|
||||
// .branch-node-container {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
|
||||
// &::before {
|
||||
// position: absolute;
|
||||
// height: 100%;
|
||||
// width: 4px;
|
||||
// background-color: #fafafa;
|
||||
// content: '';
|
||||
// left: 50%;
|
||||
// transform: translate(-50%);
|
||||
// }
|
||||
|
||||
// .branch-node-add {
|
||||
// position: absolute;
|
||||
// top: -18px;
|
||||
// left: 50%;
|
||||
// z-index: 1;
|
||||
// height: 36px;
|
||||
// padding: 0 10px;
|
||||
// font-size: 12px;
|
||||
// line-height: 36px;
|
||||
// border: 2px solid #dedede;
|
||||
// border-radius: 18px;
|
||||
// transform: translateX(-50%);
|
||||
// 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 {
|
||||
// position: relative;
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// align-items: center;
|
||||
// min-width: 280px;
|
||||
// padding: 40px 40px 0;
|
||||
// background: transparent;
|
||||
// border-top: 2px solid #dedede;
|
||||
// border-bottom: 2px solid #dedede;
|
||||
|
||||
// &::before {
|
||||
// position: absolute;
|
||||
// width: 2px;
|
||||
// height: 100%;
|
||||
// margin: auto;
|
||||
// inset: 0;
|
||||
// background-color: #dedede;
|
||||
// content: '';
|
||||
// }
|
||||
// }
|
||||
// // 覆盖条件节点第一个节点左上角的线
|
||||
// .branch-line-first-top {
|
||||
// position: absolute;
|
||||
// top: -5px;
|
||||
// left: -1px;
|
||||
// width: 50%;
|
||||
// height: 7px;
|
||||
// background-color: #fafafa;
|
||||
// content: '';
|
||||
// }
|
||||
// // 覆盖条件节点第一个节点左下角的线
|
||||
// .branch-line-first-bottom {
|
||||
// position: absolute;
|
||||
// bottom: -5px;
|
||||
// left: -1px;
|
||||
// width: 50%;
|
||||
// height: 7px;
|
||||
// background-color: #fafafa;
|
||||
// content: '';
|
||||
// }
|
||||
// // 覆盖条件节点最后一个节点右上角的线
|
||||
// .branch-line-last-top {
|
||||
// position: absolute;
|
||||
// top: -5px;
|
||||
// right: -1px;
|
||||
// width: 50%;
|
||||
// height: 7px;
|
||||
// background-color: #fafafa;
|
||||
// content: '';
|
||||
// }
|
||||
// // 覆盖条件节点最后一个节点右下角的线
|
||||
// .branch-line-last-bottom {
|
||||
// position: absolute;
|
||||
// right: -1px;
|
||||
// bottom: -5px;
|
||||
// width: 50%;
|
||||
// height: 7px;
|
||||
// background-color: #fafafa;
|
||||
// content: '';
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// .node-fixed-name {
|
||||
// display: inline-block;
|
||||
// width: auto;
|
||||
// padding: 0 4px;
|
||||
// overflow: hidden;
|
||||
// text-align: center;
|
||||
// text-overflow: ellipsis;
|
||||
// white-space: nowrap;
|
||||
// }
|
||||
// // 开始节点包装
|
||||
// .start-node-wrapper {
|
||||
// position: relative;
|
||||
// margin-top: 16px;
|
||||
|
||||
// .start-node-container {
|
||||
// display: flex;
|
||||
// flex-direction: column;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
|
||||
// .start-node-box {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// width: 90px;
|
||||
// height: 36px;
|
||||
// padding: 3px 4px;
|
||||
// color: #212121;
|
||||
// cursor: pointer;
|
||||
// background: #fafafa;
|
||||
// border-radius: 30px;
|
||||
// box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
||||
// box-sizing: border-box;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 结束节点包装
|
||||
// .end-node-wrapper {
|
||||
// margin-bottom: 16px;
|
||||
|
||||
// .end-node-box {
|
||||
// display: flex;
|
||||
// justify-content: center;
|
||||
// align-items: center;
|
||||
// width: 80px;
|
||||
// height: 36px;
|
||||
// border: 2px solid #fafafa;
|
||||
// color: #212121;
|
||||
// border-radius: 30px;
|
||||
// box-shadow: 0 1px 5px 0 rgba(10, 30, 65, 0.08);
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 可编辑的 title 输入框
|
||||
// .editable-title-input {
|
||||
// height: 20px;
|
||||
// max-width: 145px;
|
||||
// line-height: 20px;
|
||||
// font-size: 12px;
|
||||
// margin-left: 4px;
|
||||
// border: 1px solid #d9d9d9;
|
||||
// border-radius: 4px;
|
||||
// transition: all 0.3s;
|
||||
|
||||
// &:focus {
|
||||
// border-color: #40a9ff;
|
||||
// outline: 0;
|
||||
// box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// 配置节点头部
|
||||
.config-header {
|
||||
|
@ -739,7 +169,7 @@
|
|||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
// Simple 流程模型样式
|
||||
.simple-process-model-container {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div v-loading="loading" class="mb-20px">
|
||||
<SimpleProcessViewer :flow-node="simpleModel" :tasks="tasks"/>
|
||||
<SimpleProcessViewer :flow-node="simpleModel" :tasks="tasks" :process-instance="processInstance"/>
|
||||
</div>
|
||||
</template>
|
||||
<script lang="ts" setup>
|
||||
|
@ -16,10 +16,11 @@ const props = defineProps({
|
|||
loading: propTypes.bool.def(false), // 是否加载中
|
||||
id: propTypes.string // 流程实例的编号
|
||||
})
|
||||
|
||||
const tasks = ref([])
|
||||
const simpleModel = ref()
|
||||
|
||||
// 用户任务
|
||||
const tasks = ref([])
|
||||
// 流程实例
|
||||
const processInstance = ref()
|
||||
/** 只有 loading 完成时,才去加载流程列表 */
|
||||
watch(
|
||||
() => props.loading,
|
||||
|
@ -27,7 +28,8 @@ watch(
|
|||
if (value && props.id) {
|
||||
const modelView = await ProcessInstanceApi.getProcessInstanceBpmnModelView(props.id)
|
||||
if (modelView) {
|
||||
tasks.value = modelView.tasks;
|
||||
tasks.value = modelView.tasks
|
||||
processInstance.value = modelView.processInstance
|
||||
// 已经拒绝的活动节点编号集合,只包括 UserTask
|
||||
const rejectedTaskActivityIds: string[] = modelView.rejectedTaskActivityIds
|
||||
// 进行中的活动节点编号集合, 只包括 UserTask
|
||||
|
@ -44,7 +46,6 @@ watch(
|
|||
finishedActivityIds,
|
||||
finishedSequenceFlowActivityIds
|
||||
)
|
||||
console.log('modelView.simpleModel==>', modelView.simpleModel)
|
||||
simpleModel.value = modelView.simpleModel
|
||||
}
|
||||
}
|
||||
|
@ -140,11 +141,4 @@ const setSimpleModelNodeTaskStatus = (
|
|||
finishedSequenceFlowActivityIds
|
||||
)
|
||||
}
|
||||
/** 监听 bpmnXml */
|
||||
// watch(
|
||||
// () => props.bpmnXml,
|
||||
// (value) => {
|
||||
// view.value.bpmnXml = value
|
||||
// }
|
||||
// )
|
||||
</script>
|
||||
|
|
Loading…
Reference in New Issue