Skip to content

Commit a6f325b

Browse files
authored
Merge pull request #96 from GoldenZqqq/feature/bpm
工作流审批页面-时间线组件样式布局重构与展示逻辑调整
2 parents cd9cefa + c7ecb0a commit a6f325b

File tree

7 files changed

+132
-98
lines changed

7 files changed

+132
-98
lines changed

src/assets/svgs/bpm/auditor.svg

Lines changed: 1 addition & 0 deletions
Loading

src/assets/svgs/bpm/condition.svg

Lines changed: 1 addition & 0 deletions
Loading

src/assets/svgs/bpm/copy.svg

Lines changed: 1 addition & 0 deletions
Loading

src/assets/svgs/bpm/parallel.svg

Lines changed: 1 addition & 0 deletions
Loading

src/assets/svgs/bpm/starter.svg

Lines changed: 1 addition & 0 deletions
Loading

src/views/bpm/model/CategoryDraggableModel.vue

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
<Icon icon="fa:sort-amount-desc" class="mr-5px" />
3636
排序
3737
</el-button>
38-
<el-button v-else link type="info" class="mr-20px" @click.stop="handleAddModel('create')">
38+
<el-button v-else link type="info" class="mr-20px" @click.stop="openModelForm('create')">
3939
<Icon icon="fa:plus" class="mr-5px" />
4040
新建
4141
</el-button>
@@ -150,7 +150,7 @@
150150
<el-button
151151
link
152152
type="primary"
153-
@click="openForm('update', scope.row.id)"
153+
@click="openModelForm('update', scope.row.id)"
154154
v-hasPermi="['bpm:model:update']"
155155
:disabled="!isManagerUser(scope.row)"
156156
>
@@ -299,12 +299,6 @@ const handleCategoryCommand = (command: string) => {
299299
}
300300
}
301301
302-
/** 添加/修改操作 */
303-
const formRef = ref()
304-
const openForm = (type: string, id?: number) => {
305-
formRef.value.open(type, id)
306-
}
307-
308302
/** 删除按钮操作 */
309303
const handleDelete = async (row: any) => {
310304
try {
@@ -481,8 +475,8 @@ const handleDeleteGroup = async () => {
481475
482476
// 添加流程模型弹窗
483477
const modelFormRef = ref()
484-
const handleAddModel = (type: string) => {
485-
modelFormRef.value.open(type)
478+
const openModelForm = (type: string, id?: number) => {
479+
modelFormRef.value.open(type, id)
486480
}
487481
488482
watch(() => props.categoryInfo.modelList, updateTableData, { immediate: true })

src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue

Lines changed: 123 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -9,103 +9,112 @@
99
:icon="getApprovalNodeIcon(activity.status, activity.nodeType)"
1010
:color="getApprovalNodeColor(activity.status)"
1111
>
12+
<template #dot>
13+
<div
14+
class="position-absolute left--10px top--6px rounded-full border border-solid border-#dedede w-30px h-30px flex justify-center items-center bg-#3f73f7 p-5px"
15+
>
16+
<img class="w-full h-full" :src="getApprovalNodeImg(activity.nodeType)" alt="" />
17+
<div
18+
class="position-absolute top-17px left-17px bg-#fff rounded-full flex items-center p-2px"
19+
>
20+
<el-icon :size="12" :color="getApprovalNodeColor(activity.status)">
21+
<component :is="getApprovalNodeIcon(activity.status, activity.nodeType)" />
22+
</el-icon>
23+
</div>
24+
</div>
25+
</template>
1226
<div class="flex flex-col items-start">
13-
<div class="font-bold"> {{ activity.name }}</div>
27+
<!-- 第一行:节点名称、时间 -->
28+
<div class="flex w-full">
29+
<div class="font-bold"> {{ activity.name }}</div>
30+
<!-- 信息:时间 -->
31+
<div
32+
v-if="activity.status !== TaskStatusEnum.NOT_START"
33+
class="text-#a5a5a5 text-13px mt-1 ml-auto"
34+
>
35+
{{ getApprovalNodeTime(activity) }}
36+
</div>
37+
</div>
1438
<div class="flex items-center flex-wrap mt-1">
1539
<!-- 情况一:遍历每个审批节点下的【进行中】task 任务 -->
1640
<div v-for="(task, idx) in activity.tasks" :key="idx" class="flex items-center">
17-
<div class="flex flex-col pr-2">
18-
<div class="position-relative" v-if="task.assigneeUser || task.ownerUser">
19-
<!-- 信息:头像 -->
20-
<el-avatar
21-
v-if="task.assigneeUser && task.assigneeUser.avatar"
22-
:size="36"
23-
:src="task.assigneeUser.avatar"
24-
/>
25-
<el-avatar v-else-if="task.assigneeUser && task.assigneeUser.nickname">
26-
{{ task.assigneeUser.nickname.substring(0, 1) }}
27-
</el-avatar>
28-
<el-avatar
29-
v-else-if="task.ownerUser && task.ownerUser.avatar"
30-
:src="task.ownerUser.avatar"
31-
/>
32-
<el-avatar v-else-if="task.ownerUser && task.ownerUser.nickname">
33-
{{ task.ownerUser.nickname.substring(0, 1) }}
34-
</el-avatar>
35-
<!-- 信息:任务 ICON -->
41+
<div class="flex flex-col pr-2 gap2">
42+
<div
43+
class="position-relative flex flex-wrap gap2"
44+
v-if="task.assigneeUser || task.ownerUser"
45+
>
46+
<!-- 信息:头像昵称 -->
3647
<div
37-
class="position-absolute top-26px left-26px bg-#fff rounded-full flex items-center p-2px"
48+
class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600 position-relative"
3849
>
39-
<Icon
40-
:size="12"
41-
:icon="statusIconMap2[task.status]?.icon"
42-
:color="statusIconMap2[task.status]?.color"
43-
/>
44-
</div>
45-
</div>
46-
<div class="flex flex-col mt-1">
47-
<!-- 信息:昵称 -->
48-
<div
49-
v-if="task.assigneeUser && task.assigneeUser.nickname"
50-
class="text-12px text-align-center"
51-
>
52-
{{ task.assigneeUser.nickname }}
53-
</div>
54-
<div
55-
v-else-if="task.ownerUser && task.ownerUser.nickname"
56-
class="text-10px text-align-center"
57-
>
58-
{{ task.ownerUser.nickname }}
50+
<template v-if="task.assigneeUser?.avatar || task.assigneeUser?.nickname">
51+
<el-avatar
52+
:size="28"
53+
v-if="task.assigneeUser?.avatar"
54+
:src="task.assigneeUser?.avatar"
55+
/>
56+
<el-avatar :size="28" v-else>
57+
{{ task.assigneeUser?.nickname.substring(0, 1) }}
58+
</el-avatar>
59+
{{ task.assigneeUser?.nickname }}
60+
</template>
61+
<template v-else-if="task.ownerUser?.avatar || task.ownerUser?.nickname">
62+
<el-avatar
63+
:size="28"
64+
v-if="task.ownerUser?.avatar"
65+
:src="task.ownerUser?.avatar"
66+
/>
67+
<el-avatar :size="28" v-else>
68+
{{ task.ownerUser?.nickname.substring(0, 1) }}
69+
</el-avatar>
70+
{{ task.ownerUser?.nickname }}
71+
</template>
72+
<!-- 信息:任务 ICON -->
73+
<div
74+
v-if="onlyStatusIconShow.includes(task.status)"
75+
class="position-absolute top-22px left-26px bg-#fff rounded-full flex items-center p-2px"
76+
>
77+
<Icon
78+
:size="12"
79+
:icon="statusIconMap2[task.status]?.icon"
80+
:color="statusIconMap2[task.status]?.color"
81+
/>
82+
</div>
5983
</div>
84+
<!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
6085
<div
61-
v-if="task.reason && activity.nodeType === NodeType.USER_TASK_NODE"
62-
class="text-#a5a5a5 text-13px mt-1"
86+
v-for="(user, idx1) in activity.candidateUsers"
87+
:key="idx1"
88+
class="bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600 position-relative"
6389
>
64-
审批意见:{{ task.reason }}
65-
</div>
66-
</div>
67-
</div>
68-
</div>
69-
<!-- 情况二:遍历每个审批节点下的【候选的】task 任务。例如说,1)依次审批,2)未来的审批任务等 -->
70-
<div
71-
v-for="(user, idx1) in activity.candidateUsers"
72-
:key="idx1"
73-
class="flex items-center"
74-
>
75-
<div class="flex items-center flex-col pr-2">
76-
<div class="position-relative">
77-
<!-- 信息:头像 -->
78-
<el-avatar :size="36" v-if="user.avatar" :src="user.avatar" />
79-
<el-avatar v-else-if="user.nickname && user.nickname">
80-
{{ user.nickname.substring(0, 1) }}
81-
</el-avatar>
82-
<!-- 信息:任务 ICON -->
83-
<div
84-
class="position-absolute top-26px left-26px bg-#fff rounded-full flex items-center p-2px"
85-
>
86-
<Icon
87-
:size="12"
88-
:icon="statusIconMap2['-1']?.icon"
89-
:color="statusIconMap2['-1']?.color"
90-
/>
91-
</div>
92-
</div>
93-
<div class="flex flex-col mt-1">
94-
<!-- 信息:昵称 -->
95-
<div v-if="user.nickname" class="text-10px text-align-center">
90+
<el-avatar :size="28" v-if="user.avatar" :src="user.avatar" />
91+
<el-avatar :size="28" v-else>
92+
{{ user.nickname.substring(0, 1) }}
93+
</el-avatar>
9694
{{ user.nickname }}
95+
96+
<!-- 信息:任务 ICON -->
97+
<div
98+
v-if="onlyStatusIconShow.includes(task.status)"
99+
class="position-absolute top-22px left-26px bg-#fff rounded-full flex items-center p-2px"
100+
>
101+
<Icon
102+
:size="12"
103+
:icon="statusIconMap2['-1']?.icon"
104+
:color="statusIconMap2['-1']?.color"
105+
/>
106+
</div>
97107
</div>
98108
</div>
109+
<div
110+
v-if="task.reason && activity.nodeType === NodeType.USER_TASK_NODE"
111+
class="text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
112+
>
113+
审批意见:{{ task.reason }}
114+
</div>
99115
</div>
100116
</div>
101117
</div>
102-
<!-- 信息:时间 -->
103-
<div
104-
v-if="activity.status !== TaskStatusEnum.NOT_START"
105-
class="text-#a5a5a5 text-13px mt-1"
106-
>
107-
{{ getApprovalNodeTime(activity) }}
108-
</div>
109118
</div>
110119
</el-timeline-item>
111120
</el-timeline>
@@ -117,16 +126,21 @@ import * as ProcessInstanceApi from '@/api/bpm/processInstance'
117126
import { TaskStatusEnum } from '@/api/bpm/task'
118127
import { NodeType } from '@/components/SimpleProcessDesignerV2/src/consts'
119128
import { Check, Close, Loading, Clock, Minus, Delete } from '@element-plus/icons-vue'
129+
import starterSvg from '@/assets/svgs/bpm/starter.svg'
130+
import auditorSvg from '@/assets/svgs/bpm/auditor.svg'
131+
import copySvg from '@/assets/svgs/bpm/copy.svg'
132+
import conditionSvg from '@/assets/svgs/bpm/condition.svg'
133+
import parallelSvg from '@/assets/svgs/bpm/parallel.svg'
134+
120135
defineOptions({ name: 'BpmProcessInstanceTimeline' })
121136
defineProps<{
122137
approveNodes: ProcessInstanceApi.ApprovalNodeInfo[] // 审批节点信息
123138
}>()
124139
125140
// 审批节点
126-
127141
const statusIconMap2 = {
128142
// 未开始
129-
'-1': { color: '#e5e7ec', icon: 'ep-clock' },
143+
'-1': { color: '#909398', icon: 'ep-clock' },
130144
// 待审批
131145
'0': { color: '#e5e7ec', icon: 'ep:loading' },
132146
// 审批中
@@ -147,7 +161,7 @@ const statusIconMap2 = {
147161
148162
const statusIconMap = {
149163
// 审批未开始
150-
'-1': { color: '#e5e7ec', icon: Clock },
164+
'-1': { color: '#909398', icon: Clock },
151165
'0': { color: '#e5e7ec', icon: Clock },
152166
// 审批中
153167
'1': { color: '#448ef7', icon: Loading },
@@ -165,6 +179,27 @@ const statusIconMap = {
165179
'7': { color: '#00b32a', icon: Check }
166180
}
167181
182+
const nodeTypeSvgMap = {
183+
// 发起人节点
184+
[NodeType.START_USER_NODE]: { color: '#ffffff', svg: starterSvg },
185+
// 审批人节点
186+
[NodeType.USER_TASK_NODE]: { color: '#ff943e', svg: auditorSvg },
187+
// 抄送人节点
188+
[NodeType.COPY_TASK_NODE]: { color: '#3296fb', svg: copySvg },
189+
// 条件分支节点
190+
[NodeType.CONDITION_NODE]: { color: '#14bb83', svg: conditionSvg },
191+
// 并行分支节点
192+
[NodeType.PARALLEL_BRANCH_NODE]: { color: '#14bb83', svg: parallelSvg }
193+
}
194+
195+
// 只有只有状态是 -1、0、1 才展示头像右小角状态小icon
196+
const onlyStatusIconShow = [-1, 0, 1]
197+
198+
// timeline时间线上icon图标
199+
const getApprovalNodeImg = (nodeType: NodeType) => {
200+
return nodeTypeSvgMap[nodeType]?.svg
201+
}
202+
168203
const getApprovalNodeIcon = (taskStatus: number, nodeType: NodeType) => {
169204
if (taskStatus == TaskStatusEnum.NOT_START) {
170205
return statusIconMap[taskStatus]?.icon
@@ -181,13 +216,13 @@ const getApprovalNodeColor = (taskStatus: number) => {
181216
182217
const getApprovalNodeTime = (node: ProcessInstanceApi.ApprovalNodeInfo) => {
183218
if (node.nodeType === NodeType.START_USER_NODE && node.startTime) {
184-
return `发起时间:${formatDate(node.startTime)}`
219+
return `${formatDate(node.startTime)}`
185220
}
186221
if (node.endTime) {
187-
return `审批时间:${formatDate(node.endTime)}`
222+
return `${formatDate(node.endTime)}`
188223
}
189224
if (node.startTime) {
190-
return `创建时间:${formatDate(node.startTime)}`
225+
return `${formatDate(node.startTime)}`
191226
}
192227
}
193228
</script>

0 commit comments

Comments
 (0)