Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
phsl
/
admin
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Commit
27d24cd0
authored
Oct 01, 2024
by
jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【工作流】- 流程实例新界面修改
parent
4680a7dc
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
498 additions
and
152 deletions
+498
-152
src/api/bpm/processInstance/index.ts
+35
-1
src/api/bpm/task/index.ts
+46
-0
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+46
-37
src/router/modules/remaining.ts
+1
-1
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue
+4
-2
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
+249
-33
src/views/bpm/processInstance/detail/index_new.vue
+117
-78
No files found.
src/api/bpm/processInstance/index.ts
View file @
27d24cd0
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
import
{
ProcessDefinitionVO
}
from
'@/api/bpm/model'
import
{
ProcessDefinitionVO
}
from
'@/api/bpm/model'
import
{
NodeType
}
from
'@/components/SimpleProcessDesignerV2/src/consts'
export
type
Task
=
{
export
type
Task
=
{
id
:
string
id
:
string
name
:
string
name
:
string
...
@@ -22,6 +22,35 @@ export type ProcessInstanceVO = {
...
@@ -22,6 +22,35 @@ export type ProcessInstanceVO = {
processDefinition
?:
ProcessDefinitionVO
processDefinition
?:
ProcessDefinitionVO
}
}
// 用户信息
export
type
User
=
{
id
:
number
,
nickname
:
string
,
avatar
:
string
}
// 审批任务信息
export
type
ApprovalTaskInfo
=
{
id
:
number
,
ownerUser
:
User
,
assigneeUser
:
User
,
status
:
number
,
reason
:
string
}
// 审批节点信息
export
type
ApprovalNodeInfo
=
{
id
:
number
name
:
string
nodeType
:
NodeType
status
:
number
startTime
?:
Date
endTime
?:
Date
candidateUserList
?:
User
[]
tasks
:
ApprovalTaskInfo
[]
}
export
const
getProcessInstanceMyPage
=
async
(
params
:
any
)
=>
{
export
const
getProcessInstanceMyPage
=
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
'/bpm/process-instance/my-page'
,
params
})
return
await
request
.
get
({
url
:
'/bpm/process-instance/my-page'
,
params
})
}
}
...
@@ -57,3 +86,8 @@ export const getProcessInstance = async (id: string) => {
...
@@ -57,3 +86,8 @@ export const getProcessInstance = async (id: string) => {
export
const
getProcessInstanceCopyPage
=
async
(
params
:
any
)
=>
{
export
const
getProcessInstanceCopyPage
=
async
(
params
:
any
)
=>
{
return
await
request
.
get
({
url
:
'/bpm/process-instance/copy/page'
,
params
})
return
await
request
.
get
({
url
:
'/bpm/process-instance/copy/page'
,
params
})
}
}
export
const
getApprovalDetail
=
async
(
processInstanceId
?:
string
,
processDefinitionId
?:
string
)
=>
{
const
param
=
processInstanceId
?
'?processInstanceId='
+
processInstanceId
:
'?processDefinitionId='
+
processDefinitionId
return
await
request
.
get
({
url
:
'bpm/process-instance/get-approval-detail'
+
param
})
}
src/api/bpm/task/index.ts
View file @
27d24cd0
import
request
from
'@/config/axios'
import
request
from
'@/config/axios'
/**
* 任务状态枚举
*/
export
enum
TaskStatusEnum
{
/**
* 未开始
*/
NOT_START
=
-
1
,
/**
* 待审批
*/
WAIT
=
0
,
/**
* 审批中
*/
RUNNING
=
1
,
/**
* 审批通过
*/
APPROVE
=
2
,
/**
* 审批不通过
*/
REJECT
=
3
,
/**
* 已取消
*/
CANCEL
=
4
,
/**
* 已退回
*/
RETURN
=
5
,
/**
* 委派中
*/
DELEGATE
=
6
,
/**
* 审批通过中
*/
APPROVING
=
7
,
}
export
type
TaskVO
=
{
export
type
TaskVO
=
{
id
:
number
id
:
number
}
}
...
...
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
27d24cd0
<
template
>
<
template
>
<div
class=
"simple-flow-canvas"
>
<div
class=
"simple-flow-canvas"
v-loading=
"loading"
>
<div
class=
"simple-flow-container"
>
<div
class=
"simple-flow-container"
>
<div
class=
"top-area-container"
>
<div
class=
"top-area-container"
>
<div
class=
"top-actions"
>
<div
class=
"top-actions"
>
<div
class=
"canvas-control"
>
<div
class=
"canvas-control"
>
...
@@ -15,7 +15,10 @@
...
@@ -15,7 +15,10 @@
</div>
</div>
</div>
</div>
<div
class=
"scale-container"
:style=
"`transform: scale($
{scaleValue / 100});`">
<div
class=
"scale-container"
:style=
"`transform: scale($
{scaleValue / 100});`">
<ProcessNodeTree
v-if=
"processNodeTree"
v-model:flow-node=
"processNodeTree"
/>
<ProcessNodeTree
v-if=
"processNodeTree"
v-model:flow-node=
"processNodeTree"
/>
</div>
</div>
</div>
</div>
<Dialog
v-model=
"errorDialogVisible"
title=
"保存失败"
width=
"400"
:fullscreen=
"false"
>
<Dialog
v-model=
"errorDialogVisible"
title=
"保存失败"
width=
"400"
:fullscreen=
"false"
>
...
@@ -46,6 +49,7 @@ import * as DeptApi from '@/api/system/dept'
...
@@ -46,6 +49,7 @@ import * as DeptApi from '@/api/system/dept'
import
*
as
PostApi
from
'@/api/system/post'
import
*
as
PostApi
from
'@/api/system/post'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserGroupApi
from
'@/api/bpm/userGroup'
import
*
as
UserGroupApi
from
'@/api/bpm/userGroup'
import
{
fa
}
from
'element-plus/es/locale'
defineOptions
({
defineOptions
({
name
:
'SimpleProcessDesigner'
name
:
'SimpleProcessDesigner'
})
})
...
@@ -56,7 +60,7 @@ const props = defineProps({
...
@@ -56,7 +60,7 @@ const props = defineProps({
required
:
true
required
:
true
}
}
})
})
const
loading
=
ref
(
true
)
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
[]
>
([])
// 角色列表
...
@@ -163,44 +167,49 @@ const zoomIn = () => {
...
@@ -163,44 +167,49 @@ const zoomIn = () => {
}
}
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
// 获取表单字段
try
{
const
bpmnModel
=
await
getModel
(
props
.
modelId
)
loading
.
value
=
true
if
(
bpmnModel
)
{
// 获取表单字段
formType
.
value
=
bpmnModel
.
formType
const
bpmnModel
=
await
getModel
(
props
.
modelId
)
if
(
formType
.
value
===
10
)
{
if
(
bpmnModel
)
{
const
bpmnForm
=
(
await
getForm
(
bpmnModel
.
formId
))
as
unknown
as
FormVO
formType
.
value
=
bpmnModel
.
formType
formFields
.
value
=
bpmnForm
?.
fields
if
(
formType
.
value
===
10
)
{
const
bpmnForm
=
(
await
getForm
(
bpmnModel
.
formId
))
as
unknown
as
FormVO
formFields
.
value
=
bpmnForm
?.
fields
}
}
}
}
// 获得角色列表
// 获得角色列表
roleOptions
.
value
=
await
RoleApi
.
getSimpleRoleList
()
roleOptions
.
value
=
await
RoleApi
.
getSimpleRoleList
()
// 获得岗位列表
// 获得岗位列表
postOptions
.
value
=
await
PostApi
.
getSimplePostList
()
postOptions
.
value
=
await
PostApi
.
getSimplePostList
()
// 获得用户列表
// 获得用户列表
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
// 获得部门列表
// 获得部门列表
deptOptions
.
value
=
await
DeptApi
.
getSimpleDeptList
()
deptOptions
.
value
=
await
DeptApi
.
getSimpleDeptList
()
deptTreeOptions
.
value
=
handleTree
(
deptOptions
.
value
as
DeptApi
.
DeptVO
[],
'id'
)
deptTreeOptions
.
value
=
handleTree
(
deptOptions
.
value
as
DeptApi
.
DeptVO
[],
'id'
)
// 获取用户组列表
// 获取用户组列表
userGroupOptions
.
value
=
await
UserGroupApi
.
getUserGroupSimpleList
()
userGroupOptions
.
value
=
await
UserGroupApi
.
getUserGroupSimpleList
()
// 获取 SIMPLE 设计器模型
// 获取 SIMPLE 设计器模型
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
if
(
result
)
{
if
(
result
)
{
processNodeTree
.
value
=
result
processNodeTree
.
value
=
result
}
else
{
}
else
{
// 初始值
// 初始值
processNodeTree
.
value
=
{
processNodeTree
.
value
=
{
name
:
'发起人'
,
name
:
'发起人'
,
type
:
NodeType
.
START_USER_NODE
,
type
:
NodeType
.
START_USER_NODE
,
id
:
NodeId
.
START_USER_NODE_ID
,
id
:
NodeId
.
START_USER_NODE_ID
,
childNode
:
{
childNode
:
{
id
:
NodeId
.
END_EVENT_NODE_ID
,
id
:
NodeId
.
END_EVENT_NODE_ID
,
name
:
'结束'
,
name
:
'结束'
,
type
:
NodeType
.
END_EVENT_NODE
type
:
NodeType
.
END_EVENT_NODE
}
}
}
}
}
}
finally
{
loading
.
value
=
false
}
}
})
})
</
script
>
</
script
>
src/router/modules/remaining.ts
View file @
27d24cd0
...
@@ -292,7 +292,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -292,7 +292,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
},
},
{
{
path
:
'process-instance/detail'
,
path
:
'process-instance/detail'
,
component
:
()
=>
import
(
'@/views/bpm/processInstance/detail/index.vue'
),
component
:
()
=>
import
(
'@/views/bpm/processInstance/detail/index
_new
.vue'
),
name
:
'BpmProcessInstanceDetail'
,
name
:
'BpmProcessInstanceDetail'
,
meta
:
{
meta
:
{
noCache
:
true
,
noCache
:
true
,
...
...
src/views/bpm/processInstance/detail/ProcessInstanceOperationButton.vue
View file @
27d24cd0
<
template
>
<
template
>
<div
<div
class=
"h-50px
position-fixed
bottom-10 text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
class=
"h-50px bottom-10 text-14px flex items-center color-#32373c dark:color-#fff font-bold btn-container"
>
>
<el-popover
:visible=
"passVisible"
placement=
"top-end"
:width=
"500"
trigger=
"click"
>
<el-popover
:visible=
"passVisible"
placement=
"top-end"
:width=
"500"
trigger=
"click"
>
<template
#
reference
>
<template
#
reference
>
...
@@ -120,6 +120,7 @@
...
@@ -120,6 +120,7 @@
<div
@
click=
"handleSign"
>
<Icon
:size=
"14"
icon=
"ep:plus"
/>
加签
</div>
<div
@
click=
"handleSign"
>
<Icon
:size=
"14"
icon=
"ep:plus"
/>
加签
</div>
<div
@
click=
"handleBack"
>
<Icon
:size=
"14"
icon=
"fa:mail-reply"
/>
退回
</div>
<div
@
click=
"handleBack"
>
<Icon
:size=
"14"
icon=
"fa:mail-reply"
/>
退回
</div>
</div>
</div>
<!-- </div> -->
<!-- 弹窗:转派审批人 -->
<!-- 弹窗:转派审批人 -->
<TaskTransferForm
ref=
"taskTransferFormRef"
@
success=
"getDetail"
/>
<TaskTransferForm
ref=
"taskTransferFormRef"
@
success=
"getDetail"
/>
<!-- 弹窗:回退节点 -->
<!-- 弹窗:回退节点 -->
...
@@ -299,10 +300,11 @@ defineExpose({ loadRunningTask })
...
@@ -299,10 +300,11 @@ defineExpose({ loadRunningTask })
.btn-container
{
.btn-container
{
>
div
{
>
div
{
display
:
flex
;
margin
:
0
15px
;
margin
:
0
15px
;
cursor
:
pointer
;
cursor
:
pointer
;
display
:
flex
;
align-items
:
center
;
align-items
:
center
;
&:hover
{
&:hover
{
color
:
#6db5ff
;
color
:
#6db5ff
;
}
}
...
...
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
View file @
27d24cd0
<
template
>
<
template
>
<el-timeline
class=
"pt-20px"
>
<el-timeline
class=
"pt-20px"
>
<el-timeline-item
v-for=
"(activity, index) in mockData"
:key=
"index"
size=
"large"
>
<el-timeline-item
v-for=
"(activity, index) in approveNodes"
:key=
"index"
size=
"large"
:icon=
"getApprovalNodeIcon(activity.status, activity.nodeType)"
:color=
"getApprovalNodeColor(activity.status)"
>
<div
class=
"flex flex-col items-start"
>
<div
class=
"flex flex-col items-start"
>
<div
class=
"font-bold"
>
{{
activity
.
name
}}
</div>
<div
class=
"font-bold"
>
{{
activity
.
name
}}
</div>
<div
class=
"color-#a1a6ae text-12px mb-10px"
>
{{
activity
.
assigneeUser
.
nickname
}}
</div>
<div
class=
"flex items-center mt-1"
>
<div
v-for=
"(task, idx) in activity.tasks"
:key=
"idx"
class=
"flex items-center"
>
<div
class=
"flex items-center flex-col pr-2"
>
<div
class=
"position-relative"
v-if=
"task.assigneeUser || task.ownerUser"
>
<el-avatar
:size=
"36"
v-if=
"task.assigneeUser && task.assigneeUser.avatar"
:src=
"task.assigneeUser.avatar"
/>
<el-avatar
v-else-if=
"task.assigneeUser && task.assigneeUser.nickname"
>
{{
task
.
assigneeUser
.
nickname
.
substring
(
0
,
1
)
}}
</el-avatar
>
<el-avatar
v-else-if=
"task.ownerUser && task.ownerUser.avatar"
:src=
"task.ownerUser.avatar"
/>
<el-avatar
v-else-if=
"task.ownerUser && task.ownerUser.nickname"
>
{{
task
.
ownerUser
.
nickname
.
substring
(
0
,
1
)
}}
</el-avatar
>
<div
class=
"position-absolute top-26px left-26px bg-#fff rounded-full flex items-center p-2px"
>
<Icon
:size=
"12"
:icon=
"statusIconMap2[task.status]?.icon"
:color=
"statusIconMap2[task.status]?.color"
/>
</div>
</div>
<div
class=
"flex flex-col mt-1"
>
<div
v-if=
"task.assigneeUser && task.assigneeUser.nickname"
class=
"text-10px text-align-center"
>
{{
task
.
assigneeUser
.
nickname
}}
</div
>
<div
v-else-if=
"task.ownerUser && task.ownerUser.nickname"
class=
"text-10px text-align-center"
>
{{
task
.
ownerUser
.
nickname
}}
</div
>
<!--
<div
v-if=
"task.reason"
:title=
"task.reason"
class=
"text-13px text-truncate w-150px mt-1"
>
审批意见:
{{
task
.
reason
}}
</div>
-->
</div>
</div>
</div>
<div
v-for=
"(user, idx1) in activity.candidateUserList"
:key=
"idx1"
class=
"flex items-center"
>
<div
class=
"flex items-center flex-col pr-2"
>
<div
class=
"position-relative"
>
<el-avatar
:size=
"36"
v-if=
"user.avatar"
:src=
"user.avatar"
/>
<el-avatar
v-else-if=
"user.nickname && user.nickname"
>
{{
user
.
nickname
.
substring
(
0
,
1
)
}}
</el-avatar
>
<div
class=
"position-absolute top-26px left-26px bg-#fff rounded-full flex items-center p-2px"
>
<Icon
:size=
"12"
:icon=
"statusIconMap2['-1']?.icon"
:color=
"statusIconMap2['-1']?.color"
/>
</div>
</div>
<div
class=
"flex flex-col mt-1"
>
<div
v-if=
"user.nickname"
class=
"text-10px text-align-center"
>
{{
user
.
nickname
}}
</div>
<!--
<div
v-if=
"task.reason"
:title=
"task.reason"
class=
"text-13px text-truncate w-150px mt-1"
>
审批意见:
{{
task
.
reason
}}
</div>
-->
</div>
</div>
</div>
</div>
<div
v-if=
"activity.status !== TaskStatusEnum.NOT_START"
class=
"text-#a5a5a5 text-13px mt-1"
>
{{
getApprovalNodeTime
(
activity
)
}}
</div>
<!--
<div
class=
"color-#a1a6ae text-12px mb-10px"
>
{{
activity
.
assigneeUser
.
nickname
}}
</div>
<div
v-if=
"activity.opinion"
class=
"text-#a5a5a5 text-12px w-100%"
>
<div
v-if=
"activity.opinion"
class=
"text-#a5a5a5 text-12px w-100%"
>
<div
class=
"mb-5px"
>
审批意见:
</div>
<div
class=
"mb-5px"
>
审批意见:
</div>
<div
<div
...
@@ -14,50 +99,113 @@
...
@@ -14,50 +99,113 @@
</div>
</div>
<div
v-if=
"activity.createTime"
class=
"text-#a5a5a5 text-13px"
>
<div
v-if=
"activity.createTime"
class=
"text-#a5a5a5 text-13px"
>
{{
formatDate
(
activity
.
createTime
)
}}
{{
formatDate
(
activity
.
createTime
)
}}
</div>
</div>
-->
</div>
</div>
<!-- 该节点用户的头像 -->
<template
#
dot
>
<div
class=
"w-35px h-35px position-relative"
>
<img
src=
"@/assets/imgs/avatar.jpg"
class=
"rounded-full w-full h-full position-absolute bottom-6px right-12px"
alt=
""
/>
<div
class=
"position-absolute top-16px left-8px bg-#fff rounded-full flex items-center content-center p-2px"
>
<Icon
:size=
"12"
:icon=
"optIconMap[activity.status]?.icon"
:color=
"optIconMap[activity.status]?.color"
/>
</div>
</div>
</
template
>
</el-timeline-item>
</el-timeline-item>
</el-timeline>
</el-timeline>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
propTypes
}
from
'@/utils/propTypes'
import
*
as
ProcessInstanceApi
from
'@/api/bpm/processInstance'
import
{
TaskStatusEnum
}
from
'@/api/bpm/task'
import
{
NodeType
}
from
'@/components/SimpleProcessDesignerV2/src/consts'
import
{
Check
,
Close
,
Loading
,
Clock
,
Minus
,
Delete
}
from
'@element-plus/icons-vue'
defineOptions
({
name
:
'BpmProcessInstanceTimeline'
})
defineOptions
({
name
:
'BpmProcessInstanceTimeline'
})
defineProps
({
const
props
=
defineProps
({
tasks
:
propTypes
.
array
// 流程任务的数组
// 流程实例编号
processInstanceId
:
{
type
:
String
,
required
:
false
,
default
:
''
},
// 流程定义编号
processDefinitionId
:
{
type
:
String
,
required
:
false
,
default
:
''
}
})
})
const
optIconMap
=
{
// 审批节点
const
approveNodes
=
ref
<
ProcessInstanceApi
.
ApprovalNodeInfo
[]
>
([])
const
statusIconMap2
=
{
// 未开始
'-1'
:
{
color
:
'#e5e7ec'
,
icon
:
'ep-clock'
},
// 待审批
'0'
:
{
color
:
'#e5e7ec'
,
icon
:
'ep:loading'
},
// 审批中
// 审批中
'1'
:
{
'1'
:
{
color
:
'#448ef7'
,
icon
:
'ep:loading'
},
color
:
'#00b32a'
,
icon
:
'fa-solid:clock'
},
// 审批通过
// 审批通过
'2'
:
{
color
:
'#00b32a'
,
icon
:
'
fa-solid:check-circle
'
},
'2'
:
{
color
:
'#00b32a'
,
icon
:
'
ep:circle-check-filled
'
},
// 审批不通过
// 审批不通过
'3'
:
{
color
:
'#f46b6c'
,
icon
:
'fa-solid:times-circle'
}
'3'
:
{
color
:
'#f46b6c'
,
icon
:
'fa-solid:times-circle'
},
// 取消
'4'
:
{
color
:
'#cccccc'
,
icon
:
'ep:delete-filled'
},
// 回退
'5'
:
{
color
:
'#f46b6c'
,
icon
:
'ep:remove-filled'
},
// 委派中
'6'
:
{
color
:
'#448ef7'
,
icon
:
'ep:loading'
},
// 审批通过中
'7'
:
{
color
:
'#00b32a'
,
icon
:
'ep:circle-check-filled'
},
}
const
statusIconMap
=
{
// 审批未开始
'-1'
:
{
color
:
'#e5e7ec'
,
icon
:
Clock
},
'0'
:
{
color
:
'#e5e7ec'
,
icon
:
Clock
},
// 审批中
'1'
:
{
color
:
'#448ef7'
,
icon
:
Loading
},
// 审批通过
'2'
:
{
color
:
'#00b32a'
,
icon
:
Check
},
// 审批不通过
'3'
:
{
color
:
'#f46b6c'
,
icon
:
Close
},
// 已取消
'4'
:
{
color
:
'#cccccc'
,
icon
:
Delete
},
// 回退
'5'
:
{
color
:
'#f46b6c'
,
icon
:
Minus
},
// 委派中
'6'
:
{
color
:
'#448ef7'
,
icon
:
Loading
},
// 审批通过中
'7'
:
{
color
:
'#00b32a'
,
icon
:
Check
},
}
/** 获得审批详情 */
const
getApprovalDetail
=
async
()
=>
{
const
data
=
await
ProcessInstanceApi
.
getApprovalDetail
(
props
.
processInstanceId
,
props
.
processDefinitionId
)
console
.
log
(
'approveNodes is []'
,
data
)
approveNodes
.
value
=
data
.
approveNodes
}
const
getApprovalNodeIcon
=
(
taskStatus
:
number
,
nodeType
:
NodeType
)
=>
{
if
(
taskStatus
==
TaskStatusEnum
.
NOT_START
)
{
return
statusIconMap
[
taskStatus
]?.
icon
}
if
(
nodeType
===
NodeType
.
START_USER_NODE
||
nodeType
===
NodeType
.
USER_TASK_NODE
)
{
return
statusIconMap
[
taskStatus
]?.
icon
}
}
const
getApprovalNodeColor
=
(
taskStatus
:
number
)
=>
{
return
statusIconMap
[
taskStatus
]?.
color
}
const
getApprovalNodeTime
=
(
node
:
ProcessInstanceApi
.
ApprovalNodeInfo
)
=>
{
if
(
node
.
endTime
)
{
return
`结束时间:
${
formatDate
(
node
.
endTime
)}
`
}
if
(
node
.
startTime
)
{
return
`创建时间:
${
formatDate
(
node
.
startTime
)}
`
}
}
}
const
mockData
:
any
=
[
const
mockData
:
any
=
[
...
@@ -156,6 +304,74 @@ const mockData: any = [
...
@@ -156,6 +304,74 @@ const mockData: any = [
formConf
:
null
,
formConf
:
null
,
formFields
:
null
,
formFields
:
null
,
formVariables
:
null
formVariables
:
null
},
{
id
:
'fe1190ee-68c3-11ef-9c7d-00a6181404fd'
,
name
:
'领导审批'
,
createTime
:
1725237646192
,
endTime
:
null
,
durationInMillis
:
null
,
status
:
2
,
reason
:
null
,
ownerUser
:
null
,
assigneeUser
:
{
id
:
104
,
nickname
:
'领导'
,
deptId
:
107
,
deptName
:
'运维部门'
},
taskDefinitionKey
:
'task-01'
,
processInstanceId
:
'fe0c60c6-68c3-11ef-9c7d-00a6181404fd'
,
processInstance
:
{
id
:
'fe0c60c6-68c3-11ef-9c7d-00a6181404fd'
,
name
:
'oa_leave'
,
createTime
:
null
,
processDefinitionId
:
'oa_leave:1:6e5ac269-5f87-11ef-bdb6-00a6181404fd'
,
startUser
:
null
},
parentTaskId
:
null
,
children
:
null
,
formId
:
null
,
formName
:
null
,
formConf
:
null
,
formFields
:
null
,
formVariables
:
null
},
{
id
:
'fe1190ee-68c3-11ef-9c7d-00a6181404fd'
,
name
:
'财务总监审核'
,
createTime
:
1725237646192
,
endTime
:
null
,
durationInMillis
:
null
,
status
:
3
,
reason
:
null
,
ownerUser
:
null
,
assigneeUser
:
{
id
:
104
,
nickname
:
'财务总监'
,
deptId
:
107
,
deptName
:
'运维部门'
},
taskDefinitionKey
:
'task-01'
,
processInstanceId
:
'fe0c60c6-68c3-11ef-9c7d-00a6181404fd'
,
processInstance
:
{
id
:
'fe0c60c6-68c3-11ef-9c7d-00a6181404fd'
,
name
:
'oa_leave'
,
createTime
:
null
,
processDefinitionId
:
'oa_leave:1:6e5ac269-5f87-11ef-bdb6-00a6181404fd'
,
startUser
:
null
},
parentTaskId
:
null
,
children
:
null
,
formId
:
null
,
formName
:
null
,
formConf
:
null
,
formFields
:
null
,
formVariables
:
null
}
}
]
]
onMounted
(
async
()
=>
{
getApprovalDetail
()
})
</
script
>
</
script
>
src/views/bpm/processInstance/detail/index_new.vue
View file @
27d24cd0
<
template
>
<
template
>
<ContentWrap
:bodyStyle=
"
{ padding: '10px 20px' }" class="position-relative">
<ContentWrap
:bodyStyle=
"
{ padding: '10px 20px' }" class="position-relative">
<img
<div
class=
"processInstance-wrap-main"
>
class=
"position-absolute right-20px"
<el-scrollbar>
width=
"150"
<img
:src=
"auditIcons[processInstance.status]"
class=
"position-absolute right-20px"
alt=
""
width=
"150"
/>
:src=
"auditIcons[processInstance.status]"
<div
class=
"text-#878c93"
>
编号:
{{
id
}}
</div>
alt=
""
<el-divider
class=
"!my-8px"
/>
/>
<div
class=
"flex items-center gap-5 mb-10px"
>
<div
class=
"text-#878c93 h-15px"
>
编号:
{{
id
}}
</div>
<div
class=
"text-26px font-bold mb-5px"
>
{{
processInstance
.
name
}}
</div>
<el-divider
class=
"!my-8px"
/>
<dict-tag
:type=
"DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value=
"processInstance.status"
/>
<div
class=
"flex items-center gap-5 mb-10px h-40px"
>
</div>
<div
class=
"text-26px font-bold mb-5px"
>
{{
processInstance
.
name
}}
</div>
<dict-tag
:type=
"DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value=
"processInstance.status"
/>
</div>
<div
class=
"flex items-center gap-5 mb-10px text-13px"
>
<div
class=
"flex items-center gap-5 mb-10px text-13px h-35px"
>
<div
class=
"bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
>
<div
<img
class=
"rounded-full h-28px"
src=
"@/assets/imgs/avatar.jpg"
alt=
""
/>
class=
"bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
{{
processInstance
?.
startUser
?.
nickname
}}
>
</div>
<img
class=
"rounded-full h-28px"
src=
"@/assets/imgs/avatar.jpg"
alt=
""
/>
<div
class=
"text-#878c93"
>
{{
formatDate
(
processInstance
.
startTime
)
}}
提交
</div>
{{
processInstance
?.
startUser
?.
nickname
}}
</div>
</div>
<div
class=
"text-#878c93"
>
{{
formatDate
(
processInstance
.
startTime
)
}}
提交
</div>
</div>
<el-tabs>
<el-tabs
v-model=
"activeTab"
>
<!-- 表单信息 -->
<!-- 表单信息 -->
<el-tab-pane
label=
"表单信息"
>
<el-tab-pane
label=
"表单信息"
name=
"form"
>
<el-row
:gutter=
"10"
>
<div
class=
"form-scoll-area"
>
<el-col
:span=
"18"
class=
"!flex !flex-col formCol"
>
<el-scrollbar>
<!-- 表单信息 -->
<el-row
:gutter=
"10"
>
<div
v-loading=
"processInstanceLoading"
class=
"form-box flex flex-col mb-30px flex-1"
>
<el-col
:span=
"18"
class=
"!flex !flex-col formCol"
>
<!-- 情况一:流程表单 -->
<!-- 表单信息 -->
<el-col
<div
v-if=
"processInstance?.processDefinition?.formType === 10"
v-loading=
"processInstanceLoading"
:offset=
"6"
class=
"form-box flex flex-col mb-30px flex-1"
:span=
"16"
>
>
<!-- 情况一:流程表单 -->
<form-create
<el-col
v-model=
"detailForm.value"
v-if=
"processInstance?.processDefinition?.formType === 10"
v-model:api=
"fApi"
:offset=
"6"
:option=
"detailForm.option"
:span=
"16"
:rule=
"detailForm.rule"
>
/>
<form-create
</el-col>
v-model=
"detailForm.value"
<!-- 情况二:业务表单 -->
v-model:api=
"fApi"
<div
v-if=
"processInstance?.processDefinition?.formType === 20"
>
:option=
"detailForm.option"
<BusinessFormComponent
:id=
"processInstance.businessKey"
/>
:rule=
"detailForm.rule"
</div>
/>
</el-col>
<!-- 情况二:业务表单 -->
<div
v-if=
"processInstance?.processDefinition?.formType === 20"
>
<BusinessFormComponent
:id=
"processInstance.businessKey"
/>
</div>
</div>
</el-col>
<el-col
:span=
"6"
>
<!-- 审批记录时间线 -->
<ProcessInstanceTimeline
:process-instance-id=
"id"
/>
</el-col>
</el-row>
</el-scrollbar>
</div>
</div>
</el-tab-pane>
<!-- 操作栏按钮 -->
<!-- 流程图 -->
<ProcessInstanceOperationButton
<el-tab-pane
label=
"流程图"
name=
"diagram"
>
ref=
"operationButtonRef"
<ProcessInstanceBpmnViewer
:processInstance=
"processInstance"
:id=
"`$
{id}`"
:userOptions=
"userOptions"
:bpmn-xml="bpmnXml"
@
success=
"getDetail"
:loading="processInstanceLoading"
:process-instance="processInstance"
:tasks="tasks"
/>
/>
</el-col>
</el-tab-pane>
<el-col
:span=
"6"
>
<!-- 流转记录 -->
<!-- 审批记录时间线 -->
<el-tab-pane
label=
"流转记录"
name=
"record"
>
<ProcessInstanceTimeline
:process-instance=
"processInstance"
:tasks=
"tasks"
/>
<ProcessInstanceTaskList
</el-col>
:loading=
"tasksLoad"
</el-row>
:process-instance=
"processInstance"
</el-tab-pane>
:tasks=
"tasks"
<!-- 流程图 -->
@
refresh=
"getTaskList"
<el-tab-pane
label=
"流程图"
>
/>
<ProcessInstanceBpmnViewer
</el-tab-pane>
:id=
"`$
{id}`"
<!-- 流转评论 -->
:bpmn-xml="bpmnXml"
<el-tab-pane
label=
"流转评论"
name=
"comment"
>
流转评论
</el-tab-pane>
:loading="processInstanceLoading"
</el-tabs>
:process-instance="processInstance"
:tasks="tasks"
<div
class=
" b-t-solid border-t-1px border-[var(--el-border-color)]"
v-if=
"activeTab === 'form'"
>
/>
<!-- 操作栏按钮 -->
</el-tab-pane>
<ProcessInstanceOperationButton
<!-- 流转记录 -->
ref=
"operationButtonRef"
<el-tab-pane
label=
"流转记录"
>
:processInstance=
"processInstance"
<ProcessInstanceTaskList
:userOptions=
"userOptions"
:loading=
"tasksLoad"
@
success=
"getDetail"
:process-instance=
"processInstance"
/>
:tasks=
"tasks"
</div>
@
refresh=
"getTaskList"
</el-scrollbar>
/>
</div>
</el-tab-pane>
<!-- 流转评论 -->
<el-tab-pane
label=
"流转评论"
>
流转评论
</el-tab-pane>
</el-tabs>
</ContentWrap>
</ContentWrap>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
...
@@ -209,6 +225,9 @@ const getTaskList = async () => {
...
@@ -209,6 +225,9 @@ const getTaskList = async () => {
}
}
}
}
/** 当前的Tab */
const
activeTab
=
ref
(
'form'
)
/** 初始化 */
/** 初始化 */
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
...
@@ -219,9 +238,29 @@ onMounted(async () => {
...
@@ -219,9 +238,29 @@ onMounted(async () => {
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
>
$
wrap-padding-height
:
30px
;
$
wrap-margin-height
:
15px
;
$
button-height
:
51px
;
$
process-header-height
:
194px
;
.processInstance-wrap-main
{
height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
45px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
45px
);
overflow
:
auto
;
.form-scoll-area
{
height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
45px
-
$
process-header-height
-
40px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
45px
-
$
process-header-height
-
40px
);
overflow
:
auto
;
}
}
.form-box
{
.form-box
{
:deep(.el-card)
{
:deep(.el-card)
{
border
:
none
;
border
:
none
;
}
}
}
}
</
style
>
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment