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
43b7dff0
authored
Oct 19, 2024
by
YunaiV
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
【功能调整】工作流:工作流程的流转记录,不区分父子任务
parent
dcdce412
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
781 additions
and
1643 deletions
+781
-1643
src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
+10
-8
src/router/modules/remaining.ts
+1
-2
src/views/bpm/model/index.vue
+140
-316
src/views/bpm/model/index_new.vue
+0
-228
src/views/bpm/model/index_old.vue
+404
-0
src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue
+1
-5
src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue
+2
-24
src/views/bpm/processInstance/detail/dialog/TaskDelegateForm.vue
+0
-89
src/views/bpm/processInstance/detail/dialog/TaskReturnForm.vue
+0
-90
src/views/bpm/processInstance/detail/dialog/TaskSignCreateForm.vue
+0
-99
src/views/bpm/processInstance/detail/dialog/TaskSignDeleteForm.vue
+1
-0
src/views/bpm/processInstance/detail/dialog/TaskSignList.vue
+1
-0
src/views/bpm/processInstance/detail/dialog/TaskTransferForm.vue
+0
-89
src/views/bpm/processInstance/detail/index.vue
+221
-352
src/views/bpm/processInstance/detail/index_new.vue
+0
-341
No files found.
src/components/bpmnProcessDesigner/package/designer/ProcessViewer.vue
View file @
43b7dff0
...
@@ -53,11 +53,14 @@
...
@@ -53,11 +53,14 @@
/>
/>
<el-table-column
<el-table-column
label=
"审批人"
label=
"审批人"
prop=
"assigneeUser.nickname"
min-width=
"100"
min-width=
"100"
align=
"center"
align=
"center"
v-if=
"selectActivityType === 'bpmn:UserTask'"
v-if=
"selectActivityType === 'bpmn:UserTask'"
/>
>
<template
#
default=
"scope"
>
{{
scope
.
row
.
assigneeUser
?.
nickname
||
scope
.
row
.
ownerUser
?.
nickname
}}
</
template
>
</el-table-column>
<el-table-column
<el-table-column
label=
"发起人"
label=
"发起人"
prop=
"assigneeUser.nickname"
prop=
"assigneeUser.nickname"
...
@@ -65,12 +68,11 @@
...
@@ -65,12 +68,11 @@
align=
"center"
align=
"center"
v-else
v-else
/>
/>
<el-table-column
<el-table-column
label=
"部门"
min-width=
"100"
align=
"center"
>
label=
"部门"
<
template
#
default=
"scope"
>
prop=
"assigneeUser.deptName"
{{
scope
.
row
.
assigneeUser
?.
deptName
||
scope
.
row
.
ownerUser
?.
deptName
}}
min-width=
"100"
</
template
>
align=
"center"
</el-table-column>
/>
<el-table-column
<el-table-column
:formatter=
"dateFormatter"
:formatter=
"dateFormatter"
align=
"center"
align=
"center"
...
...
src/router/modules/remaining.ts
View file @
43b7dff0
...
@@ -292,8 +292,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
...
@@ -292,8 +292,7 @@ const remainingRouter: AppRouteRecordRaw[] = [
},
},
{
{
path
:
'process-instance/detail'
,
path
:
'process-instance/detail'
,
component
:
()
=>
import
(
'@/views/bpm/processInstance/detail/index_new.vue'
),
component
:
()
=>
import
(
'@/views/bpm/processInstance/detail/index.vue'
),
//component: () => import('@/views/bpm/processInstance/detail/index.vue'),
name
:
'BpmProcessInstanceDetail'
,
name
:
'BpmProcessInstanceDetail'
,
meta
:
{
meta
:
{
noCache
:
true
,
noCache
:
true
,
...
...
src/views/bpm/model/index.vue
View file @
43b7dff0
<
template
>
<
template
>
<doc-alert
title=
"流程设计器(BPMN)"
url=
"https://doc.iocoder.cn/bpm/model-designer-dingding/"
/>
<doc-alert
title=
"流程设计器(钉钉、飞书)"
url=
"https://doc.iocoder.cn/bpm/model-designer-bpmn/"
/>
<doc-alert
title=
"选择审批人、发起人自选"
url=
"https://doc.iocoder.cn/bpm/assignee/"
/>
<doc-alert
title=
"会签、或签、依次审批"
url=
"https://doc.iocoder.cn/bpm/multi-instance/"
/>
<ContentWrap>
<ContentWrap>
<div
class=
"flex justify-between pl-20px items-center"
>
<h3
class=
"font-extrabold"
>
流程模型
</h3>
<!-- 搜索工作栏 -->
<!-- 搜索工作栏 -->
<el-form
<el-form
class=
"-mb-15px"
v-if=
"!isCategorySorting"
class=
"-mb-15px flex mr-10px"
:model=
"queryParams"
:model=
"queryParams"
ref=
"queryFormRef"
ref=
"queryFormRef"
:inline=
"true"
:inline=
"true"
label-width=
"68px"
label-width=
"68px"
@
submit
.
prevent
>
>
<el-form-item
label=
"流程标识"
prop=
"key
"
>
<el-form-item
align=
"right"
prop=
"key"
class=
"ml-auto
"
>
<el-input
<el-input
v-model=
"queryParams.key"
v-model=
"queryParams.key"
placeholder=
"请输入流程标识"
placeholder=
"搜索流程"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"流程名称"
prop=
"name"
>
<el-input
v-model=
"queryParams.name"
placeholder=
"请输入流程名称"
clearable
clearable
@
keyup
.
enter=
"handleQuery"
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"流程分类"
prop=
"category"
>
<el-select
v-model=
"queryParams.category"
placeholder=
"请选择流程分类"
clearable
class=
"!w-240px"
>
>
<el-option
<template
#
prefix
>
v-for=
"category in categoryList"
<Icon
icon=
"ep:search"
class=
"mx-10px"
/>
:key=
"category.code"
</
template
>
:label=
"category.name"
</el-input>
:value=
"category.code"
/>
</el-select>
</el-form-item>
</el-form-item>
<el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
type=
"primary"
@
click=
"openForm('create')"
v-hasPermi=
"['bpm:model:create']"
>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新建模型
<el-button
type=
"primary"
plain
@
click=
"openForm('create')"
v-hasPermi=
"['bpm:model:create']"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新建
</el-button>
</el-button>
</el-form-item>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<el-form-item>
<ContentWrap>
<el-dropdown
@
command=
"(command) => handleCommand(command)"
placement=
"bottom-end"
>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-button
class=
"w-30px"
plain
>
<el-table-column
label=
"流程名称"
align=
"center"
prop=
"name"
min-width=
"200"
/>
<Icon
icon=
"ep:setting"
/>
<el-table-column
label=
"流程图标"
align=
"center"
prop=
"icon"
min-width=
"100"
>
<template
#
default=
"scope"
>
<el-image
:src=
"scope.row.icon"
class=
"h-32px w-32px"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"可见范围"
align=
"center"
prop=
"startUserIds"
min-width=
"100"
>
<
template
#
default=
"scope"
>
<el-text
v-if=
"!scope.row.startUsers || scope.row.startUsers.length === 0"
>
全部可见
</el-text>
<el-text
v-else-if=
"scope.row.startUsers.length == 1"
>
{{
scope
.
row
.
startUsers
[
0
].
nickname
}}
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"scope.row.startUsers.map((user: any) => user.nickname).join('、')"
>
{{
scope
.
row
.
startUsers
[
0
].
nickname
}}
等
{{
scope
.
row
.
startUsers
.
length
}}
人可见
</el-tooltip>
</el-text>
</
template
>
</el-table-column>
<el-table-column
label=
"流程分类"
align=
"center"
prop=
"categoryName"
min-width=
"100"
/>
<el-table-column
label=
"表单信息"
align=
"center"
prop=
"formType"
min-width=
"200"
>
<
template
#
default=
"scope"
>
<el-button
v-if=
"scope.row.formType === 10"
type=
"primary"
link
@
click=
"handleFormDetail(scope.row)"
>
<span>
{{
scope
.
row
.
formName
}}
</span>
</el-button>
<el-button
v-else-if=
"scope.row.formType === 20"
type=
"primary"
link
@
click=
"handleFormDetail(scope.row)"
>
<span>
{{
scope
.
row
.
formCustomCreatePath
}}
</span>
</el-button>
<label
v-else
>
暂无表单
</label>
</
template
>
</el-table-column>
<el-table-column
label=
"最后发布"
align=
"center"
prop=
"deploymentTime"
min-width=
"250"
>
<
template
#
default=
"scope"
>
<span
v-if=
"scope.row.processDefinition"
>
{{
formatDate
(
scope
.
row
.
processDefinition
.
deploymentTime
)
}}
</span>
<el-tag
v-if=
"scope.row.processDefinition"
class=
"ml-10px"
>
v
{{
scope
.
row
.
processDefinition
.
version
}}
</el-tag>
<el-tag
v-else
type=
"warning"
>
未部署
</el-tag>
<el-tag
v-if=
"scope.row.processDefinition?.suspensionState === 2"
type=
"warning"
class=
"ml-10px"
>
已停用
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
width=
"200"
fixed=
"right"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
@
click=
"openForm('update', scope.row.id)"
v-hasPermi=
"['bpm:model:update']"
:disabled=
"!isManagerUser(scope.row)"
>
修改
</el-button>
<el-button
link
class=
"!ml-5px"
type=
"primary"
@
click=
"handleDesign(scope.row)"
v-hasPermi=
"['bpm:model:update']"
:disabled=
"!isManagerUser(scope.row)"
>
设计
</el-button>
<el-button
link
class=
"!ml-5px"
type=
"primary"
@
click=
"handleDeploy(scope.row)"
v-hasPermi=
"['bpm:model:deploy']"
:disabled=
"!isManagerUser(scope.row)"
>
发布
</el-button>
</el-button>
<el-dropdown
class=
"!align-middle ml-5px"
@
command=
"(command) => handleCommand(command, scope.row)"
v-hasPermi=
"['bpm:process-definition:query', 'bpm:model:update', 'bpm:model:delete']"
>
<el-button
type=
"primary"
link
>
更多
</el-button>
<
template
#
dropdown
>
<
template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-menu>
<el-dropdown-item
<el-dropdown-item
command=
"handleAddCategory"
>
command=
"handleDefinitionList"
<Icon
icon=
"ep:circle-plus"
:size=
"13"
class=
"mr-5px"
/>
v-if=
"checkPermi(['bpm:process-definition:query'])"
新建分类
>
历史
</el-dropdown-item>
</el-dropdown-item>
<el-dropdown-item
<el-dropdown-item
command=
"handleSort"
>
command=
"handleChangeState"
<Icon
icon=
"fa:sort-amount-desc"
:size=
"13"
class=
"mr-5px"
/>
v-if=
"checkPermi(['bpm:model:update']) && scope.row.processDefinition"
分类排序
:disabled=
"!isManagerUser(scope.row)"
>
{{
scope
.
row
.
processDefinition
.
suspensionState
===
1
?
'停用'
:
'启用'
}}
</el-dropdown-item>
<el-dropdown-item
type=
"danger"
command=
"handleDelete"
v-if=
"checkPermi(['bpm:model:delete'])"
:disabled=
"!isManagerUser(scope.row)"
>
删除
</el-dropdown-item>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown-menu>
</
template
>
</
template
>
</el-dropdown>
</el-dropdown>
</template>
</el-form-item>
</el-table-column>
</el-form>
</el-table>
<div
class=
"mr-20px"
v-else
>
<!-- 分页 -->
<el-button
@
click=
"cancelSort"
>
取 消
</el-button>
<Pagination
<el-button
type=
"primary"
@
click=
"saveSort"
>
保存排序
</el-button>
:total=
"total"
</div>
v-model:page=
"queryParams.pageNo"
</div>
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
<el-divider
/>
<!-- 分类卡片组 -->
<div
class=
"px-15px"
>
<draggable
:disabled=
"!isCategorySorting"
v-model=
"categoryGroup"
item-key=
"id"
:animation=
"400"
>
<
template
#
item=
"{ element }"
>
<ContentWrap
class=
"rounded-lg transition-all duration-300 ease-in-out hover:shadow-xl"
v-loading=
"loading"
:body-style=
"
{ padding: 0 }"
:key="element.id"
>
<CategoryDraggableModel
ref=
"categoryDraggableModelRef"
:isCategorySorting=
"isCategorySorting"
:categoryInfo=
"element"
@
success=
"getList"
/>
/>
</ContentWrap>
</ContentWrap>
</
template
>
</draggable>
</div>
</ContentWrap>
<!-- 表单弹窗:添加/修改流程 -->
<!-- 表单弹窗:添加/修改流程 -->
<ModelForm
ref=
"formRef"
@
success=
"getList"
/>
<ModelForm
ref=
"formRef"
@
success=
"getList"
/>
<!-- 表单弹窗:添加/修改分类 -->
<CategoryForm
ref=
"categoryFormRef"
@
success=
"getList"
/>
<!-- 弹窗:表单详情 -->
<!-- 弹窗:表单详情 -->
<Dialog
title=
"表单详情"
v-model=
"formDetailVisible"
width=
"800"
>
<Dialog
title=
"表单详情"
v-model=
"formDetailVisible"
width=
"800"
>
<form-create
:rule=
"formDetailPreview.rule"
:option=
"formDetailPreview.option"
/>
<form-create
:rule=
"formDetailPreview.rule"
:option=
"formDetailPreview.option"
/>
...
@@ -218,26 +97,20 @@
...
@@ -218,26 +97,20 @@
</template>
</template>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
formatDate
}
from
'@/utils/formatTime'
import
draggable
from
'vuedraggable'
import
{
CategoryApi
}
from
'@/api/bpm/category'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
*
as
FormApi
from
'@/api/bpm/form'
import
ModelForm
from
'./ModelForm.vue'
import
ModelForm
from
'./ModelForm.vue'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
CategoryForm
from
'../category/CategoryForm.vue'
import
{
CategoryApi
}
from
'@/api/bpm/category'
import
{
groupBy
,
cloneDeep
}
from
'lodash-es'
import
{
BpmModelType
}
from
'@/utils/constants'
import
CategoryDraggableModel
from
'./CategoryDraggableModel.vue'
import
{
checkPermi
}
from
'@/utils/permission'
import
{
useUserStoreWithOut
}
from
'@/store/modules/user'
defineOptions
({
name
:
'BpmModel'
})
defineOptions
({
name
:
'BpmModel'
})
const
message
=
useMessage
()
// 消息弹窗
const
categoryDraggableModelRef
=
ref
()
const
{
t
}
=
useI18n
()
// 国际化
const
categoryFormRef
=
ref
()
const
{
push
}
=
useRouter
()
// 路由
const
userStore
=
useUserStoreWithOut
()
// 用户信息缓存
const
loading
=
ref
(
true
)
// 列表的加载中
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
isCategorySorting
=
ref
(
false
)
// 是否正处于排序状态
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
const
queryParams
=
reactive
({
pageNo
:
1
,
pageNo
:
1
,
pageSize
:
10
,
pageSize
:
10
,
...
@@ -246,18 +119,26 @@ const queryParams = reactive({
...
@@ -246,18 +119,26 @@ const queryParams = reactive({
category
:
undefined
category
:
undefined
})
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
queryFormRef
=
ref
()
// 搜索的表单
const
categoryList
=
ref
([])
// 流程分类列表
const
categoryGroup
:
any
=
ref
([])
// 按照category分组的数据
const
originalData
:
any
=
ref
([])
// 查询所有分类数据
const
getAllCategory
=
async
()
=>
{
// TODO 芋艿:这里需要一个不分页查全部的流程分类接口
const
data
=
await
CategoryApi
.
getCategoryPage
(
queryParams
)
categoryGroup
.
value
=
data
.
list
.
map
((
item
)
=>
({
...
item
,
modelList
:
[]
}))
}
/** 查询列表 */
/** 查询所有流程模型接口 */
const
getList
=
async
()
=>
{
const
getAllModel
=
async
()
=>
{
loading
.
value
=
true
// TODO 芋艿:这里需要一个不分页查全部的流程模型接口
try
{
const
data
=
await
ModelApi
.
getModelPage
(
queryParams
)
const
data
=
await
ModelApi
.
getModelPage
(
queryParams
)
list
.
value
=
data
.
list
const
groupedData
=
groupBy
(
data
.
list
,
'categoryName'
)
total
.
value
=
data
.
total
Object
.
keys
(
groupedData
).
forEach
((
key
)
=>
{
}
finally
{
const
category
=
categoryGroup
.
value
.
find
((
item
)
=>
item
.
name
===
key
)
loading
.
value
=
false
if
(
category
)
{
category
.
modelList
=
groupedData
[
key
]
}
}
})
}
}
/** 搜索按钮操作 */
/** 搜索按钮操作 */
...
@@ -266,139 +147,82 @@ const handleQuery = () => {
...
@@ -266,139 +147,82 @@ const handleQuery = () => {
getList
()
getList
()
}
}
/**
重置按钮
操作 */
/**
添加/修改
操作 */
const
resetQuery
=
()
=>
{
const
formRef
=
ref
()
queryFormRef
.
value
.
resetFields
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
handleQuery
(
)
formRef
.
value
.
open
(
type
,
id
)
}
}
/** 流程表单的详情按钮操作 */
const
formDetailVisible
=
ref
(
false
)
const
formDetailPreview
=
ref
({
rule
:
[],
option
:
{}
})
/**
'更多'操作
按钮 */
/**
右上角设置
按钮 */
const
handleCommand
=
(
command
:
string
,
row
:
any
)
=>
{
const
handleCommand
=
(
command
:
string
)
=>
{
switch
(
command
)
{
switch
(
command
)
{
case
'handleDefinitionList'
:
case
'handleAddCategory'
:
handleDefinitionList
(
row
)
handleAddCategory
()
break
case
'handleDelete'
:
handleDelete
(
row
)
break
break
case
'handle
ChangeState
'
:
case
'handle
Sort
'
:
handle
ChangeState
(
row
)
handle
Sort
(
)
break
break
default
:
default
:
break
break
}
}
}
}
/** 添加/修改操作 */
// 新建分类
const
formRef
=
ref
()
const
handleAddCategory
=
()
=>
{
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
categoryFormRef
.
value
.
open
(
'create'
)
formRef
.
value
.
open
(
type
,
id
)
}
}
// 分类排序
/** 删除按钮操作 */
const
handleSort
=
()
=>
{
const
handleDelete
=
async
(
row
:
any
)
=>
{
// 保存初始数据
try
{
originalData
.
value
=
cloneDeep
(
categoryGroup
.
value
)
// 删除的二次确认
isCategorySorting
.
value
=
true
await
message
.
delConfirm
()
// 发起删除
await
ModelApi
.
deleteModel
(
row
.
id
)
message
.
success
(
t
(
'common.delSuccess'
))
// 刷新列表
await
getList
()
}
catch
{}
}
}
// 取消排序
/** 更新状态操作 */
const
cancelSort
=
()
=>
{
const
handleChangeState
=
async
(
row
:
any
)
=>
{
// 恢复初始数据
const
state
=
row
.
processDefinition
.
suspensionState
categoryGroup
.
value
=
cloneDeep
(
originalData
.
value
)
const
newState
=
state
===
1
?
2
:
1
isCategorySorting
.
value
=
false
try
{
// 修改状态的二次确认
const
id
=
row
.
id
debugger
const
statusState
=
state
===
1
?
'停用'
:
'启用'
const
content
=
'是否确认'
+
statusState
+
'流程名字为"'
+
row
.
name
+
'"的数据项?'
await
message
.
confirm
(
content
)
// 发起修改状态
await
ModelApi
.
updateModelState
(
id
,
newState
)
message
.
success
(
statusState
+
'成功'
)
// 刷新列表
await
getList
()
}
catch
{}
}
}
// 保存排序
/** 设计流程 */
const
saveSort
=
()
=>
{
const
handleDesign
=
(
row
:
any
)
=>
{
// TODO 芋艿:这里需要一个保存分类排序接口
if
(
row
.
type
==
BpmModelType
.
BPMN
)
{
push
({
name
:
'BpmModelEditor'
,
query
:
{
modelId
:
row
.
id
}
})
}
else
{
push
({
name
:
'SimpleWorkflowDesignEditor'
,
query
:
{
modelId
:
row
.
id
}
})
}
}
}
/** 发布流程 */
const
getList
=
async
()
=>
{
const
handleDeploy
=
async
(
row
:
any
)
=>
{
loading
.
value
=
true
try
{
try
{
// 删除的二次确认
await
getAllCategory
()
await
message
.
confirm
(
'是否部署该流程!!'
)
await
getAllModel
()
// 发起部署
}
finally
{
await
ModelApi
.
deployModel
(
row
.
id
)
loading
.
value
=
false
message
.
success
(
t
(
'部署成功'
))
// 刷新列表
await
getList
()
}
catch
{}
}
/** 跳转到指定流程定义列表 */
const
handleDefinitionList
=
(
row
)
=>
{
push
({
name
:
'BpmProcessDefinition'
,
query
:
{
key
:
row
.
key
}
})
}
/** 流程表单的详情按钮操作 */
const
formDetailVisible
=
ref
(
false
)
const
formDetailPreview
=
ref
({
rule
:
[],
option
:
{}
})
const
handleFormDetail
=
async
(
row
:
any
)
=>
{
if
(
row
.
formType
==
10
)
{
// 设置表单
const
data
=
await
FormApi
.
getForm
(
row
.
formId
)
setConfAndFields2
(
formDetailPreview
,
data
.
conf
,
data
.
fields
)
// 弹窗打开
formDetailVisible
.
value
=
true
}
else
{
await
push
({
path
:
row
.
formCustomCreatePath
})
}
}
}
}
/** 判断是否可以操作 */
const
isManagerUser
=
(
row
:
any
)
=>
{
const
userId
=
userStore
.
getUser
.
id
return
row
.
managerUserIds
&&
row
.
managerUserIds
.
includes
(
userId
)
}
/** 初始化 **/
/** 初始化 **/
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
await
getList
()
getList
()
// 查询流程分类列表
categoryList
.
value
=
await
CategoryApi
.
getCategorySimpleList
()
})
})
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
:deep
()
{
.el-table--fit
.
el-table__inner-wrapper
:
before
{
height
:
0
;
}
.el-card
{
border-radius
:
8px
;
}
.el-form--inline
.el-form-item
{
margin-right
:
10px
;
}
.el-divider--horizontal
{
margin-top
:
6px
;
}
}
</
style
>
src/views/bpm/model/index_new.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<ContentWrap>
<div
class=
"flex justify-between pl-20px items-center"
>
<h3
class=
"font-extrabold"
>
流程模型
</h3>
<!-- 搜索工作栏 -->
<el-form
v-if=
"!isCategorySorting"
class=
"-mb-15px flex mr-10px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
@
submit
.
prevent
>
<el-form-item
align=
"right"
prop=
"key"
class=
"ml-auto"
>
<el-input
v-model=
"queryParams.key"
placeholder=
"搜索流程"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
>
<template
#
prefix
>
<Icon
icon=
"ep:search"
class=
"mx-10px"
/>
</
template
>
</el-input>
</el-form-item>
<el-form-item>
<el-button
type=
"primary"
@
click=
"openForm('create')"
v-hasPermi=
"['bpm:model:create']"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新建模型
</el-button>
</el-form-item>
<el-form-item>
<el-dropdown
@
command=
"(command) => handleCommand(command)"
placement=
"bottom-end"
>
<el-button
class=
"w-30px"
plain
>
<Icon
icon=
"ep:setting"
/>
</el-button>
<
template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
command=
"handleAddCategory"
>
<Icon
icon=
"ep:circle-plus"
:size=
"13"
class=
"mr-5px"
/>
新建分类
</el-dropdown-item>
<el-dropdown-item
command=
"handleSort"
>
<Icon
icon=
"fa:sort-amount-desc"
:size=
"13"
class=
"mr-5px"
/>
分类排序
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</el-form-item>
</el-form>
<div
class=
"mr-20px"
v-else
>
<el-button
@
click=
"cancelSort"
>
取 消
</el-button>
<el-button
type=
"primary"
@
click=
"saveSort"
>
保存排序
</el-button>
</div>
</div>
<el-divider
/>
<!-- 分类卡片组 -->
<div
class=
"px-15px"
>
<draggable
:disabled=
"!isCategorySorting"
v-model=
"categoryGroup"
item-key=
"id"
:animation=
"400"
>
<
template
#
item=
"{ element }"
>
<ContentWrap
class=
"rounded-lg transition-all duration-300 ease-in-out hover:shadow-xl"
v-loading=
"loading"
:body-style=
"
{ padding: 0 }"
:key="element.id"
>
<CategoryDraggableModel
ref=
"categoryDraggableModelRef"
:isCategorySorting=
"isCategorySorting"
:categoryInfo=
"element"
@
success=
"getList"
/>
</ContentWrap>
</
template
>
</draggable>
</div>
</ContentWrap>
<!-- 表单弹窗:添加/修改流程 -->
<ModelForm
ref=
"formRef"
@
success=
"getList"
/>
<!-- 表单弹窗:添加/修改分类 -->
<CategoryForm
ref=
"categoryFormRef"
@
success=
"getList"
/>
<!-- 弹窗:表单详情 -->
<Dialog
title=
"表单详情"
v-model=
"formDetailVisible"
width=
"800"
>
<form-create
:rule=
"formDetailPreview.rule"
:option=
"formDetailPreview.option"
/>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
draggable
from
'vuedraggable'
import
{
CategoryApi
}
from
'@/api/bpm/category'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
ModelForm
from
'./ModelForm.vue'
import
CategoryForm
from
'../category/CategoryForm.vue'
import
{
groupBy
,
cloneDeep
}
from
'lodash-es'
import
CategoryDraggableModel
from
'./CategoryDraggableModel.vue'
defineOptions
({
name
:
'BpmModel'
})
const
categoryDraggableModelRef
=
ref
()
const
categoryFormRef
=
ref
()
const
loading
=
ref
(
true
)
// 列表的加载中
const
isCategorySorting
=
ref
(
false
)
// 是否正处于排序状态
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
key
:
undefined
,
name
:
undefined
,
category
:
undefined
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
categoryGroup
:
any
=
ref
([])
// 按照category分组的数据
const
originalData
:
any
=
ref
([])
// 查询所有分类数据
const
getAllCategory
=
async
()
=>
{
// TODO 芋艿:这里需要一个不分页查全部的流程分类接口
const
data
=
await
CategoryApi
.
getCategoryPage
(
queryParams
)
categoryGroup
.
value
=
data
.
list
.
map
((
item
)
=>
({
...
item
,
modelList
:
[]
}))
}
/** 查询所有流程模型接口 */
const
getAllModel
=
async
()
=>
{
// TODO 芋艿:这里需要一个不分页查全部的流程模型接口
const
data
=
await
ModelApi
.
getModelPage
(
queryParams
)
const
groupedData
=
groupBy
(
data
.
list
,
'categoryName'
)
Object
.
keys
(
groupedData
).
forEach
((
key
)
=>
{
const
category
=
categoryGroup
.
value
.
find
((
item
)
=>
item
.
name
===
key
)
if
(
category
)
{
category
.
modelList
=
groupedData
[
key
]
}
})
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 添加/修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
}
/** 流程表单的详情按钮操作 */
const
formDetailVisible
=
ref
(
false
)
const
formDetailPreview
=
ref
({
rule
:
[],
option
:
{}
})
/** 右上角设置按钮 */
const
handleCommand
=
(
command
:
string
)
=>
{
switch
(
command
)
{
case
'handleAddCategory'
:
handleAddCategory
()
break
case
'handleSort'
:
handleSort
()
break
default
:
break
}
}
// 新建分类
const
handleAddCategory
=
()
=>
{
categoryFormRef
.
value
.
open
(
'create'
)
}
// 分类排序
const
handleSort
=
()
=>
{
// 保存初始数据
originalData
.
value
=
cloneDeep
(
categoryGroup
.
value
)
isCategorySorting
.
value
=
true
}
// 取消排序
const
cancelSort
=
()
=>
{
// 恢复初始数据
categoryGroup
.
value
=
cloneDeep
(
originalData
.
value
)
isCategorySorting
.
value
=
false
}
// 保存排序
const
saveSort
=
()
=>
{
// TODO 芋艿:这里需要一个保存分类排序接口
}
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
await
getAllCategory
()
await
getAllModel
()
}
finally
{
loading
.
value
=
false
}
}
/** 初始化 **/
onMounted
(
async
()
=>
{
getList
()
})
</
script
>
<
style
lang=
"scss"
scoped
>
:deep
()
{
.el-table--fit
.
el-table__inner-wrapper
:
before
{
height
:
0
;
}
.el-card
{
border-radius
:
8px
;
}
.el-form--inline
.el-form-item
{
margin-right
:
10px
;
}
.el-divider--horizontal
{
margin-top
:
6px
;
}
}
</
style
>
src/views/bpm/model/index_old.vue
0 → 100644
View file @
43b7dff0
<
template
>
<doc-alert
title=
"流程设计器(BPMN)"
url=
"https://doc.iocoder.cn/bpm/model-designer-dingding/"
/>
<doc-alert
title=
"流程设计器(钉钉、飞书)"
url=
"https://doc.iocoder.cn/bpm/model-designer-bpmn/"
/>
<doc-alert
title=
"选择审批人、发起人自选"
url=
"https://doc.iocoder.cn/bpm/assignee/"
/>
<doc-alert
title=
"会签、或签、依次审批"
url=
"https://doc.iocoder.cn/bpm/multi-instance/"
/>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"流程标识"
prop=
"key"
>
<el-input
v-model=
"queryParams.key"
placeholder=
"请输入流程标识"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"流程名称"
prop=
"name"
>
<el-input
v-model=
"queryParams.name"
placeholder=
"请输入流程名称"
clearable
@
keyup
.
enter=
"handleQuery"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"流程分类"
prop=
"category"
>
<el-select
v-model=
"queryParams.category"
placeholder=
"请选择流程分类"
clearable
class=
"!w-240px"
>
<el-option
v-for=
"category in categoryList"
:key=
"category.code"
:label=
"category.name"
:value=
"category.code"
/>
</el-select>
</el-form-item>
<el-form-item>
<el-button
@
click=
"handleQuery"
><Icon
icon=
"ep:search"
class=
"mr-5px"
/>
搜索
</el-button>
<el-button
@
click=
"resetQuery"
><Icon
icon=
"ep:refresh"
class=
"mr-5px"
/>
重置
</el-button>
<el-button
type=
"primary"
plain
@
click=
"openForm('create')"
v-hasPermi=
"['bpm:model:create']"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
新建
</el-button>
</el-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
label=
"流程名称"
align=
"center"
prop=
"name"
min-width=
"200"
/>
<el-table-column
label=
"流程图标"
align=
"center"
prop=
"icon"
min-width=
"100"
>
<template
#
default=
"scope"
>
<el-image
:src=
"scope.row.icon"
class=
"h-32px w-32px"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"可见范围"
align=
"center"
prop=
"startUserIds"
min-width=
"100"
>
<
template
#
default=
"scope"
>
<el-text
v-if=
"!scope.row.startUsers || scope.row.startUsers.length === 0"
>
全部可见
</el-text>
<el-text
v-else-if=
"scope.row.startUsers.length == 1"
>
{{
scope
.
row
.
startUsers
[
0
].
nickname
}}
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"scope.row.startUsers.map((user: any) => user.nickname).join('、')"
>
{{
scope
.
row
.
startUsers
[
0
].
nickname
}}
等
{{
scope
.
row
.
startUsers
.
length
}}
人可见
</el-tooltip>
</el-text>
</
template
>
</el-table-column>
<el-table-column
label=
"流程分类"
align=
"center"
prop=
"categoryName"
min-width=
"100"
/>
<el-table-column
label=
"表单信息"
align=
"center"
prop=
"formType"
min-width=
"200"
>
<
template
#
default=
"scope"
>
<el-button
v-if=
"scope.row.formType === 10"
type=
"primary"
link
@
click=
"handleFormDetail(scope.row)"
>
<span>
{{
scope
.
row
.
formName
}}
</span>
</el-button>
<el-button
v-else-if=
"scope.row.formType === 20"
type=
"primary"
link
@
click=
"handleFormDetail(scope.row)"
>
<span>
{{
scope
.
row
.
formCustomCreatePath
}}
</span>
</el-button>
<label
v-else
>
暂无表单
</label>
</
template
>
</el-table-column>
<el-table-column
label=
"最后发布"
align=
"center"
prop=
"deploymentTime"
min-width=
"250"
>
<
template
#
default=
"scope"
>
<span
v-if=
"scope.row.processDefinition"
>
{{
formatDate
(
scope
.
row
.
processDefinition
.
deploymentTime
)
}}
</span>
<el-tag
v-if=
"scope.row.processDefinition"
class=
"ml-10px"
>
v
{{
scope
.
row
.
processDefinition
.
version
}}
</el-tag>
<el-tag
v-else
type=
"warning"
>
未部署
</el-tag>
<el-tag
v-if=
"scope.row.processDefinition?.suspensionState === 2"
type=
"warning"
class=
"ml-10px"
>
已停用
</el-tag>
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
width=
"200"
fixed=
"right"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
@
click=
"openForm('update', scope.row.id)"
v-hasPermi=
"['bpm:model:update']"
:disabled=
"!isManagerUser(scope.row)"
>
修改
</el-button>
<el-button
link
class=
"!ml-5px"
type=
"primary"
@
click=
"handleDesign(scope.row)"
v-hasPermi=
"['bpm:model:update']"
:disabled=
"!isManagerUser(scope.row)"
>
设计
</el-button>
<el-button
link
class=
"!ml-5px"
type=
"primary"
@
click=
"handleDeploy(scope.row)"
v-hasPermi=
"['bpm:model:deploy']"
:disabled=
"!isManagerUser(scope.row)"
>
发布
</el-button>
<el-dropdown
class=
"!align-middle ml-5px"
@
command=
"(command) => handleCommand(command, scope.row)"
v-hasPermi=
"['bpm:process-definition:query', 'bpm:model:update', 'bpm:model:delete']"
>
<el-button
type=
"primary"
link
>
更多
</el-button>
<template
#
dropdown
>
<el-dropdown-menu>
<el-dropdown-item
command=
"handleDefinitionList"
v-if=
"checkPermi(['bpm:process-definition:query'])"
>
历史
</el-dropdown-item>
<el-dropdown-item
command=
"handleChangeState"
v-if=
"checkPermi(['bpm:model:update']) && scope.row.processDefinition"
:disabled=
"!isManagerUser(scope.row)"
>
{{
scope
.
row
.
processDefinition
.
suspensionState
===
1
?
'停用'
:
'启用'
}}
</el-dropdown-item>
<el-dropdown-item
type=
"danger"
command=
"handleDelete"
v-if=
"checkPermi(['bpm:model:delete'])"
:disabled=
"!isManagerUser(scope.row)"
>
删除
</el-dropdown-item>
</el-dropdown-menu>
</
template
>
</el-dropdown>
</template>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
<!-- 表单弹窗:添加/修改流程 -->
<ModelForm
ref=
"formRef"
@
success=
"getList"
/>
<!-- 弹窗:表单详情 -->
<Dialog
title=
"表单详情"
v-model=
"formDetailVisible"
width=
"800"
>
<form-create
:rule=
"formDetailPreview.rule"
:option=
"formDetailPreview.option"
/>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
{
formatDate
}
from
'@/utils/formatTime'
import
*
as
ModelApi
from
'@/api/bpm/model'
import
*
as
FormApi
from
'@/api/bpm/form'
import
ModelForm
from
'./ModelForm.vue'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
{
CategoryApi
}
from
'@/api/bpm/category'
import
{
BpmModelType
}
from
'@/utils/constants'
import
{
checkPermi
}
from
'@/utils/permission'
import
{
useUserStoreWithOut
}
from
'@/store/modules/user'
defineOptions
({
name
:
'BpmModel'
})
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
{
push
}
=
useRouter
()
// 路由
const
userStore
=
useUserStoreWithOut
()
// 用户信息缓存
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
key
:
undefined
,
name
:
undefined
,
category
:
undefined
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
categoryList
=
ref
([])
// 流程分类列表
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ModelApi
.
getModelPage
(
queryParams
)
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
.
resetFields
()
handleQuery
()
}
/** '更多'操作按钮 */
const
handleCommand
=
(
command
:
string
,
row
:
any
)
=>
{
switch
(
command
)
{
case
'handleDefinitionList'
:
handleDefinitionList
(
row
)
break
case
'handleDelete'
:
handleDelete
(
row
)
break
case
'handleChangeState'
:
handleChangeState
(
row
)
break
default
:
break
}
}
/** 添加/修改操作 */
const
formRef
=
ref
()
const
openForm
=
(
type
:
string
,
id
?:
number
)
=>
{
formRef
.
value
.
open
(
type
,
id
)
}
/** 删除按钮操作 */
const
handleDelete
=
async
(
row
:
any
)
=>
{
try
{
// 删除的二次确认
await
message
.
delConfirm
()
// 发起删除
await
ModelApi
.
deleteModel
(
row
.
id
)
message
.
success
(
t
(
'common.delSuccess'
))
// 刷新列表
await
getList
()
}
catch
{}
}
/** 更新状态操作 */
const
handleChangeState
=
async
(
row
:
any
)
=>
{
const
state
=
row
.
processDefinition
.
suspensionState
const
newState
=
state
===
1
?
2
:
1
try
{
// 修改状态的二次确认
const
id
=
row
.
id
debugger
const
statusState
=
state
===
1
?
'停用'
:
'启用'
const
content
=
'是否确认'
+
statusState
+
'流程名字为"'
+
row
.
name
+
'"的数据项?'
await
message
.
confirm
(
content
)
// 发起修改状态
await
ModelApi
.
updateModelState
(
id
,
newState
)
message
.
success
(
statusState
+
'成功'
)
// 刷新列表
await
getList
()
}
catch
{}
}
/** 设计流程 */
const
handleDesign
=
(
row
:
any
)
=>
{
if
(
row
.
type
==
BpmModelType
.
BPMN
)
{
push
({
name
:
'BpmModelEditor'
,
query
:
{
modelId
:
row
.
id
}
})
}
else
{
push
({
name
:
'SimpleWorkflowDesignEditor'
,
query
:
{
modelId
:
row
.
id
}
})
}
}
/** 发布流程 */
const
handleDeploy
=
async
(
row
:
any
)
=>
{
try
{
// 删除的二次确认
await
message
.
confirm
(
'是否部署该流程!!'
)
// 发起部署
await
ModelApi
.
deployModel
(
row
.
id
)
message
.
success
(
t
(
'部署成功'
))
// 刷新列表
await
getList
()
}
catch
{}
}
/** 跳转到指定流程定义列表 */
const
handleDefinitionList
=
(
row
)
=>
{
push
({
name
:
'BpmProcessDefinition'
,
query
:
{
key
:
row
.
key
}
})
}
/** 流程表单的详情按钮操作 */
const
formDetailVisible
=
ref
(
false
)
const
formDetailPreview
=
ref
({
rule
:
[],
option
:
{}
})
const
handleFormDetail
=
async
(
row
:
any
)
=>
{
if
(
row
.
formType
==
10
)
{
// 设置表单
const
data
=
await
FormApi
.
getForm
(
row
.
formId
)
setConfAndFields2
(
formDetailPreview
,
data
.
conf
,
data
.
fields
)
// 弹窗打开
formDetailVisible
.
value
=
true
}
else
{
await
push
({
path
:
row
.
formCustomCreatePath
})
}
}
/** 判断是否可以操作 */
const
isManagerUser
=
(
row
:
any
)
=>
{
const
userId
=
userStore
.
getUser
.
id
return
row
.
managerUserIds
&&
row
.
managerUserIds
.
includes
(
userId
)
}
/** 初始化 **/
onMounted
(
async
()
=>
{
await
getList
()
// 查询流程分类列表
categoryList
.
value
=
await
CategoryApi
.
getCategorySimpleList
()
})
</
script
>
src/views/bpm/processInstance/detail/ProcessInstanceBpmnViewer.vue
View file @
43b7dff0
<
template
>
<
template
>
<el-card
v-loading=
"loading"
class=
"box-card"
>
<el-card
v-loading=
"loading"
class=
"box-card"
>
<template
#
header
v-if=
"showHeader"
>
<span
class=
"el-icon-picture-outline"
>
流程图
</span>
</
template
>
<MyProcessViewer
key=
"designer"
:xml=
"view.bpmnXml"
:view=
"view"
class=
"h-700px"
/>
<MyProcessViewer
key=
"designer"
:xml=
"view.bpmnXml"
:view=
"view"
class=
"h-700px"
/>
</el-card>
</el-card>
</
template
>
</
template
>
...
@@ -16,8 +13,7 @@ defineOptions({ name: 'BpmProcessInstanceBpmnViewer' })
...
@@ -16,8 +13,7 @@ defineOptions({ name: 'BpmProcessInstanceBpmnViewer' })
const
props
=
defineProps
({
const
props
=
defineProps
({
loading
:
propTypes
.
bool
.
def
(
false
),
// 是否加载中
loading
:
propTypes
.
bool
.
def
(
false
),
// 是否加载中
id
:
propTypes
.
string
,
// 流程实例的编号
id
:
propTypes
.
string
,
// 流程实例的编号
bpmnXml
:
propTypes
.
string
,
// BPMN XML
bpmnXml
:
propTypes
.
string
// BPMN XML
showHeader
:
propTypes
.
bool
.
def
(
true
),
// 是否显示头
})
})
const
view
=
ref
({
const
view
=
ref
({
...
...
src/views/bpm/processInstance/detail/ProcessInstanceTaskList.vue
View file @
43b7dff0
<
template
>
<
template
>
<el-card
v-loading=
"loading"
class=
"box-card"
>
<el-card
v-loading=
"loading"
class=
"box-card"
>
<template
#
header
v-if=
"showHeader"
>
<el-col>
<span
class=
"el-icon-picture-outline"
>
审批记录
</span>
</
template
>
<el-col
:offset=
"3"
:span=
"17"
>
<div
class=
"block"
>
<div
class=
"block"
>
<el-timeline>
<el-timeline>
<el-timeline-item
<el-timeline-item
...
@@ -28,14 +25,6 @@
...
@@ -28,14 +25,6 @@
<dict-tag
:type=
"DICT_TYPE.BPM_TASK_STATUS"
:value=
"item.status"
/>
<dict-tag
:type=
"DICT_TYPE.BPM_TASK_STATUS"
:value=
"item.status"
/>
<el-button
<el-button
class=
"ml-10px"
class=
"ml-10px"
v-if=
"!isEmpty(item.children)"
@
click=
"openChildrenTask(item)"
size=
"small"
>
<Icon
icon=
"ep:memo"
/>
子任务
</el-button>
<el-button
class=
"ml-10px"
size=
"small"
size=
"small"
v-if=
"item.formId > 0"
v-if=
"item.formId > 0"
@
click=
"handleFormDetail(item)"
@
click=
"handleFormDetail(item)"
...
@@ -78,8 +67,6 @@
...
@@ -78,8 +67,6 @@
</el-col>
</el-col>
</el-card>
</el-card>
<!-- 弹窗:子任务 -->
<TaskSignList
ref=
"taskSignListRef"
@
success=
"refresh"
/>
<!-- 弹窗:表单 -->
<!-- 弹窗:表单 -->
<Dialog
title=
"表单详情"
v-model=
"taskFormVisible"
width=
"600"
>
<Dialog
title=
"表单详情"
v-model=
"taskFormVisible"
width=
"600"
>
<form-create
<form-create
...
@@ -94,8 +81,6 @@
...
@@ -94,8 +81,6 @@
import
{
formatDate
,
formatPast2
}
from
'@/utils/formatTime'
import
{
formatDate
,
formatPast2
}
from
'@/utils/formatTime'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
propTypes
}
from
'@/utils/propTypes'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
isEmpty
}
from
'@/utils/is'
import
TaskSignList
from
'./dialog/TaskSignList.vue'
import
type
{
ApiAttrs
}
from
'@form-create/element-ui/types/config'
import
type
{
ApiAttrs
}
from
'@form-create/element-ui/types/config'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
...
@@ -104,8 +89,7 @@ defineOptions({ name: 'BpmProcessInstanceTaskList' })
...
@@ -104,8 +89,7 @@ defineOptions({ name: 'BpmProcessInstanceTaskList' })
defineProps
({
defineProps
({
loading
:
propTypes
.
bool
,
// 是否加载中
loading
:
propTypes
.
bool
,
// 是否加载中
processInstance
:
propTypes
.
object
,
// 流程实例
processInstance
:
propTypes
.
object
,
// 流程实例
tasks
:
propTypes
.
arrayOf
(
propTypes
.
object
),
// 流程任务的数组
tasks
:
propTypes
.
arrayOf
(
propTypes
.
object
)
// 流程任务的数组
showHeader
:
propTypes
.
bool
.
def
(
true
),
// 是否显示头
})
})
/** 获得流程实例对应的颜色 */
/** 获得流程实例对应的颜色 */
...
@@ -142,12 +126,6 @@ const getTaskTimelineItemType = (item: any) => {
...
@@ -142,12 +126,6 @@ const getTaskTimelineItemType = (item: any) => {
return
''
return
''
}
}
/** 子任务 */
const
taskSignListRef
=
ref
()
const
openChildrenTask
=
(
item
:
any
)
=>
{
taskSignListRef
.
value
.
open
(
item
)
}
/** 查看表单 */
/** 查看表单 */
const
fApi
=
ref
<
ApiAttrs
>
()
// form-create 的 API 操作类
const
fApi
=
ref
<
ApiAttrs
>
()
// form-create 的 API 操作类
const
taskForm
=
ref
({
const
taskForm
=
ref
({
...
...
src/views/bpm/processInstance/detail/dialog/TaskDelegateForm.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"委派任务"
width=
"500"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"formRules"
label-width=
"110px"
>
<el-form-item
label=
"接收人"
prop=
"delegateUserId"
>
<el-select
v-model=
"formData.delegateUserId"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"委派理由"
prop=
"reason"
>
<el-input
v-model=
"formData.reason"
clearable
placeholder=
"请输入委派理由"
/>
</el-form-item>
</el-form>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
TaskApi
from
'@/api/bpm/task'
import
*
as
UserApi
from
'@/api/system/user'
defineOptions
({
name
:
'BpmTaskDelegateForm'
})
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formData
=
ref
({
id
:
''
,
delegateUserId
:
undefined
,
reason
:
''
})
const
formRules
=
ref
({
delegateUserId
:
[{
required
:
true
,
message
:
'接收人不能为空'
,
trigger
:
'change'
}],
reason
:
[{
required
:
true
,
message
:
'委派理由不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
()
// 表单 Ref
const
userList
=
ref
<
any
[]
>
([])
// 用户列表
/** 打开弹窗 */
const
open
=
async
(
id
:
string
)
=>
{
dialogVisible
.
value
=
true
resetForm
()
formData
.
value
.
id
=
id
// 获得用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
}
defineExpose
({
open
})
// 提供 openModal 方法,用于打开弹窗
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
await
TaskApi
.
delegateTask
(
formData
.
value
)
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
''
,
delegateUserId
:
undefined
,
reason
:
''
}
formRef
.
value
?.
resetFields
()
}
</
script
>
src/views/bpm/processInstance/detail/dialog/TaskReturnForm.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"退回任务"
width=
"500"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"formRules"
label-width=
"110px"
>
<el-form-item
label=
"退回节点"
prop=
"targetTaskDefinitionKey"
>
<el-select
v-model=
"formData.targetTaskDefinitionKey"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"item in returnList"
:key=
"item.taskDefinitionKey"
:label=
"item.name"
:value=
"item.taskDefinitionKey"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"退回理由"
prop=
"reason"
>
<el-input
v-model=
"formData.reason"
clearable
placeholder=
"请输入退回理由"
/>
</el-form-item>
</el-form>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
name=
"TaskRollbackDialogForm"
setup
>
import
*
as
TaskApi
from
'@/api/bpm/task'
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formData
=
ref
({
id
:
''
,
targetTaskDefinitionKey
:
undefined
,
reason
:
''
})
const
formRules
=
ref
({
targetTaskDefinitionKey
:
[{
required
:
true
,
message
:
'必须选择退回节点'
,
trigger
:
'change'
}],
reason
:
[{
required
:
true
,
message
:
'退回理由不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
()
// 表单 Ref
const
returnList
=
ref
([]
as
any
)
/** 打开弹窗 */
const
open
=
async
(
id
:
string
)
=>
{
returnList
.
value
=
await
TaskApi
.
getTaskListByReturn
(
id
)
if
(
returnList
.
value
.
length
===
0
)
{
message
.
warning
(
'当前没有可退回的节点'
)
return
false
}
dialogVisible
.
value
=
true
resetForm
()
formData
.
value
.
id
=
id
}
defineExpose
({
open
})
// 提供 openModal 方法,用于打开弹窗
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
await
TaskApi
.
returnTask
(
formData
.
value
)
message
.
success
(
'退回成功'
)
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
''
,
targetTaskDefinitionKey
:
undefined
,
reason
:
''
}
formRef
.
value
?.
resetFields
()
}
</
script
>
src/views/bpm/processInstance/detail/dialog/TaskSignCreateForm.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"加签"
width=
"500"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"formRules"
label-width=
"110px"
>
<el-form-item
label=
"加签处理人"
prop=
"userIds"
>
<el-select
v-model=
"formData.userIds"
multiple
clearable
style=
"width: 100%"
>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"加签理由"
prop=
"reason"
>
<el-input
v-model=
"formData.reason"
clearable
placeholder=
"请输入加签理由"
/>
</el-form-item>
</el-form>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm('before')"
>
向前加签
</el-button>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm('after')"
>
向后加签
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
TaskApi
from
'@/api/bpm/task'
import
*
as
UserApi
from
'@/api/system/user'
defineOptions
({
name
:
'TaskSignCreateForm'
})
const
message
=
useMessage
()
// 消息弹窗
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formData
=
ref
({
id
:
''
,
userIds
:
[],
type
:
''
,
reason
:
''
})
const
formRules
=
ref
({
userIds
:
[{
required
:
true
,
message
:
'加签处理人不能为空'
,
trigger
:
'change'
}],
reason
:
[{
required
:
true
,
message
:
'加签理由不能为空'
,
trigger
:
'change'
}]
})
const
formRef
=
ref
()
// 表单 Ref
const
userList
=
ref
<
any
[]
>
([])
// 用户列表
/** 打开弹窗 */
const
open
=
async
(
id
:
string
)
=>
{
dialogVisible
.
value
=
true
resetForm
()
formData
.
value
.
id
=
id
// 获得用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
}
defineExpose
({
open
})
// 提供 openModal 方法,用于打开弹窗
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
(
type
:
string
)
=>
{
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
formData
.
value
.
type
=
type
try
{
await
TaskApi
.
signCreateTask
(
formData
.
value
)
message
.
success
(
'加签成功'
)
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
''
,
userIds
:
[],
type
:
''
,
reason
:
''
}
formRef
.
value
?.
resetFields
()
}
</
script
>
src/views/bpm/processInstance/detail/dialog/TaskSignDeleteForm.vue
View file @
43b7dff0
...
@@ -86,4 +86,5 @@ const resetForm = () => {
...
@@ -86,4 +86,5 @@ const resetForm = () => {
}
}
formRef
.
value
?.
resetFields
()
formRef
.
value
?.
resetFields
()
}
}
// TODO @jason:新界面搞完,可以删除
</
script
>
</
script
>
src/views/bpm/processInstance/detail/dialog/TaskSignList.vue
View file @
43b7dff0
...
@@ -103,4 +103,5 @@ const handleSignDeleteSuccess = () => {
...
@@ -103,4 +103,5 @@ const handleSignDeleteSuccess = () => {
const
isSignDeleteButtonVisible
=
(
task
:
any
)
=>
{
const
isSignDeleteButtonVisible
=
(
task
:
any
)
=>
{
return
task
&&
task
.
children
&&
!
isEmpty
(
task
.
children
)
return
task
&&
task
.
children
&&
!
isEmpty
(
task
.
children
)
}
}
// TODO @jason:新界面搞完,可以删除
</
script
>
</
script
>
src/views/bpm/processInstance/detail/dialog/TaskTransferForm.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"转派任务"
width=
"500"
>
<el-form
ref=
"formRef"
v-loading=
"formLoading"
:model=
"formData"
:rules=
"formRules"
label-width=
"110px"
>
<el-form-item
label=
"新审批人"
prop=
"assigneeUserId"
>
<el-select
v-model=
"formData.assigneeUserId"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"item in userList"
:key=
"item.id"
:label=
"item.nickname"
:value=
"item.id"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"转派理由"
prop=
"reason"
>
<el-input
v-model=
"formData.reason"
clearable
placeholder=
"请输入转派理由"
/>
</el-form-item>
</el-form>
<template
#
footer
>
<el-button
:disabled=
"formLoading"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
*
as
TaskApi
from
'@/api/bpm/task'
import
*
as
UserApi
from
'@/api/system/user'
defineOptions
({
name
:
'TaskTransferForm'
})
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
const
formData
=
ref
({
id
:
''
,
assigneeUserId
:
undefined
,
reason
:
''
})
const
formRules
=
ref
({
assigneeUserId
:
[{
required
:
true
,
message
:
'新审批人不能为空'
,
trigger
:
'change'
}],
reason
:
[{
required
:
true
,
message
:
'转派理由不能为空'
,
trigger
:
'blur'
}]
})
const
formRef
=
ref
()
// 表单 Ref
const
userList
=
ref
<
any
[]
>
([])
// 用户列表
/** 打开弹窗 */
const
open
=
async
(
id
:
string
)
=>
{
dialogVisible
.
value
=
true
resetForm
()
formData
.
value
.
id
=
id
// 获得用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
}
defineExpose
({
open
})
// 提供 openModal 方法,用于打开弹窗
/** 提交表单 */
const
emit
=
defineEmits
([
'success'
])
// 定义 success 事件,用于操作成功后的回调
const
submitForm
=
async
()
=>
{
// 校验表单
if
(
!
formRef
)
return
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
// 提交请求
formLoading
.
value
=
true
try
{
await
TaskApi
.
transferTask
(
formData
.
value
)
dialogVisible
.
value
=
false
// 发送操作成功的事件
emit
(
'success'
)
}
finally
{
formLoading
.
value
=
false
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
formData
.
value
=
{
id
:
''
,
assigneeUserId
:
undefined
,
reason
:
''
}
formRef
.
value
?.
resetFields
()
}
</
script
>
src/views/bpm/processInstance/detail/index.vue
View file @
43b7dff0
<
template
>
<
template
>
<ContentWrap>
<ContentWrap
:bodyStyle=
"
{ padding: '10px 20px 0' }" class="position-relative">
<!-- 审批信息 -->
<div
class=
"processInstance-wrap-main"
>
<el-card
<el-scrollbar>
v-for=
"(item, index) in runningTasks"
<img
:key=
"index"
class=
"position-absolute right-20px"
v-loading=
"processInstanceLoading"
width=
"150"
class=
"box-card"
:src=
"auditIcons[processInstance.status]"
>
alt=
""
<template
#
header
>
<span
class=
"el-icon-picture-outline"
>
审批任务【
{{
item
.
name
}}
】
</span>
</
template
>
<el-col
:offset=
"6"
:span=
"16"
>
<el-form
:ref=
"'form' + index"
:model=
"auditForms[index]"
:rules=
"auditRule"
label-width=
"100px"
>
<el-form-item
v-if=
"processInstance && processInstance.name"
label=
"流程名"
>
{{ processInstance.name }}
</el-form-item>
<el-form-item
v-if=
"processInstance && processInstance.startUser"
label=
"流程发起人"
>
{{ processInstance?.startUser.nickname }}
<el-tag
size=
"small"
type=
"info"
>
{{ processInstance?.startUser.deptName }}
</el-tag>
</el-form-item>
<el-card
v-if=
"runningTasks[index].formId > 0"
class=
"mb-15px !-mt-10px"
>
<
template
#
header
>
<span
class=
"el-icon-picture-outline"
>
填写表单【
{{
runningTasks
[
index
]?.
formName
}}
】
</span>
</
template
>
<form-create
v-model=
"approveForms[index].value"
v-model:api=
"approveFormFApis[index]"
:option=
"approveForms[index].option"
:rule=
"approveForms[index].rule"
/>
/>
</el-card>
<div
class=
"text-#878c93 h-15px"
>
编号:
{{
id
}}
</div>
<el-form-item
label=
"审批建议"
prop=
"reason"
>
<el-divider
class=
"!my-8px"
/>
<el-input
<div
class=
"flex items-center gap-5 mb-10px h-40px"
>
v-model=
"auditForms[index].reason"
<div
class=
"text-26px font-bold mb-5px"
>
{{
processInstance
.
name
}}
</div>
placeholder=
"请输入审批建议"
<dict-tag
type=
"textarea"
v-if=
"processInstance.status"
:type=
"DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value=
"processInstance.status"
/>
/>
</el-form-item>
</div>
<el-form-item
label=
"抄送人"
prop=
"copyUserIds"
>
<el-select
v-model=
"auditForms[index].copyUserIds"
multiple
placeholder=
"请选择抄送人"
>
<div
class=
"flex items-center gap-5 mb-10px text-13px h-35px"
>
<el-option
<div
v-for=
"itemx in userOptions"
class=
"bg-gray-100 h-35px rounded-3xl flex items-center p-8px gap-2 dark:color-gray-600"
:key=
"itemx.id"
:label=
"itemx.nickname"
:value=
"itemx.id"
/>
</el-select>
</el-form-item>
</el-form>
<div
style=
"margin-bottom: 20px; margin-left: 10%; font-size: 14px"
>
<!-- TODO @jason:建议搞个 if 来判断,替代现有的 !item.buttonsSetting || item.buttonsSetting[OpsButtonType.APPROVE]?.enable -->
<el-button
type=
"success"
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.APPROVE]?.enable"
@
click=
"handleAudit(item, true)"
>
<Icon
icon=
"ep:select"
/>
<!-- TODO @jason:这个也是类似哈,搞个方法来生成名字 -->
{{
item.buttonsSetting?.[OperationButtonType.APPROVE]?.displayName ||
OPERATION_BUTTON_NAME.get(OperationButtonType.APPROVE)
}}
</el-button>
<el-button
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.REJECT]?.enable"
type=
"danger"
@
click=
"handleAudit(item, false)"
>
<Icon
icon=
"ep:close"
/>
{{
item.buttonsSetting?.[OperationButtonType.REJECT].displayName ||
OPERATION_BUTTON_NAME.get(OperationButtonType.REJECT)
}}
</el-button>
<el-button
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.TRANSFER]?.enable"
type=
"primary"
@
click=
"openTaskUpdateAssigneeForm(item.id)"
>
<Icon
icon=
"ep:edit"
/>
{{
item.buttonsSetting?.[OperationButtonType.TRANSFER]?.displayName ||
OPERATION_BUTTON_NAME.get(OperationButtonType.TRANSFER)
}}
</el-button>
<el-button
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.DELEGATE]?.enable"
type=
"primary"
@
click=
"handleDelegate(item)"
>
<Icon
icon=
"ep:position"
/>
{{
item.buttonsSetting?.[OperationButtonType.DELEGATE]?.displayName ||
OPERATION_BUTTON_NAME.get(OperationButtonType.DELEGATE)
}}
</el-button>
<el-button
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.ADD_SIGN]?.enable"
type=
"primary"
@
click=
"handleSign(item)"
>
<Icon
icon=
"ep:plus"
/>
{{
item.buttonsSetting?.[OperationButtonType.ADD_SIGN]?.displayName ||
OPERATION_BUTTON_NAME.get(OperationButtonType.ADD_SIGN)
}}
</el-button>
<el-button
v-if=
"!item.buttonsSetting || item.buttonsSetting[OperationButtonType.RETURN]?.enable"
type=
"warning"
@
click=
"handleBack(item)"
>
>
<Icon
icon=
"ep:back"
/>
<el-avatar
{{
:size=
"28"
item.buttonsSetting?.[OperationButtonType.RETURN]?.displayName ||
v-if=
"processInstance?.startUser?.avatar"
OPERATION_BUTTON_NAME.get(OperationButtonType.RETURN)
:src=
"processInstance?.startUser?.avatar"
}}
/>
</el-button>
<el-avatar
:size=
"28"
v-else-if=
"processInstance?.startUser?.nickname"
>
{{
processInstance
?.
startUser
?.
nickname
.
substring
(
0
,
1
)
}}
</el-avatar>
{{
processInstance
?.
startUser
?.
nickname
}}
</div>
<div
class=
"text-#878c93"
>
{{
formatDate
(
processInstance
.
startTime
)
}}
提交
</div>
</div>
</div>
</el-col>
</el-card>
<!-- 申请信息 -->
<el-tabs
v-model=
"activeTab"
>
<el-card
v-loading=
"processInstanceLoading"
class=
"box-card"
>
<!-- 表单信息 -->
<
template
#
header
>
<el-tab-pane
label=
"审批详情"
name=
"form"
>
<span
class=
"el-icon-document"
>
申请信息【
{{
processInstance
.
name
}}
】
</span>
<div
class=
"form-scroll-area"
>
</
template
>
<el-scrollbar>
<el-row>
<el-col
:span=
"18"
class=
"!flex !flex-col formCol"
>
<!-- 表单信息 -->
<div
v-loading=
"processInstanceLoading"
class=
"form-box flex flex-col mb-30px flex-1"
>
<!-- 情况一:流程表单 -->
<!-- 情况一:流程表单 -->
<el-col
v-if=
"processInstance?.processDefinition?.formType === 10"
:offset=
"6"
:span=
"16
"
>
<el-col
v-if=
"processDefinition?.formType === 10
"
>
<form-create
<form-create
v-model=
"detailForm.value"
v-model=
"detailForm.value"
v-model:api=
"fApi"
v-model:api=
"fApi"
...
@@ -143,74 +58,106 @@
...
@@ -143,74 +58,106 @@
/>
/>
</el-col>
</el-col>
<!-- 情况二:业务表单 -->
<!-- 情况二:业务表单 -->
<div
v-if=
"processInstance?.
processDefinition?.formType === 20"
>
<div
v-if=
"
processDefinition?.formType === 20"
>
<BusinessFormComponent
:id=
"processInstance.businessKey"
/>
<BusinessFormComponent
:id=
"processInstance.businessKey"
/>
</div>
</div>
</el-card>
</div>
</el-col>
<el-col
:span=
"6"
>
<!-- 审批记录时间线 -->
<ProcessInstanceTimeline
ref=
"timelineRef"
:approve-nodes=
"approveNodes"
/>
</el-col>
</el-row>
</el-scrollbar>
</div>
</el-tab-pane>
<!-- 流程图 -->
<el-tab-pane
label=
"流程图"
name=
"diagram"
>
<div
class=
"form-scroll-area"
>
<ProcessInstanceBpmnViewer
:id=
"`$
{id}`"
:loading="processInstanceLoading"
:show-header="false"
/>
</div>
</el-tab-pane>
<!-- 审批记录 -->
<!-- 流转记录 -->
<el-tab-pane
label=
"流转记录"
name=
"record"
>
<div
class=
"form-scroll-area"
>
<el-scrollbar>
<ProcessInstanceTaskList
<ProcessInstanceTaskList
:loading=
"tasksLoad"
:loading=
"tasksLoad"
:process-instance=
"processInstance"
:process-instance=
"processInstance"
:tasks=
"tasks"
:tasks=
"tasks"
@
refresh=
"getTaskList
"
:show-header=
"false
"
/>
/>
</el-scrollbar>
</div>
</el-tab-pane>
<!-- 高亮流程图 -->
<!-- 流转评论 TODO 待开发 -->
<ProcessInstanceBpmnViewer
:id=
"`${id}`"
:loading=
"processInstanceLoading"
/>
<el-tab-pane
label=
"流转评论"
name=
"comment"
v-if=
"false"
>
<div
class=
"form-scroll-area"
>
<el-scrollbar>
流转评论
</el-scrollbar>
</div>
</el-tab-pane>
</el-tabs>
<!-- 弹窗:转派审批人 -->
<div
class=
"b-t-solid border-t-1px border-[var(--el-border-color)]"
>
<TaskTransferForm
ref=
"taskTransferFormRef"
@
success=
"getDetail"
/>
<!-- 操作栏按钮 -->
<!-- 弹窗:退回节点 -->
<ProcessInstanceOperationButton
<TaskReturnForm
ref=
"taskReturnFormRef"
@
success=
"getDetail"
/>
ref=
"operationButtonRef"
<!-- 弹窗:委派,将任务委派给别人处理,处理完成后,会重新回到原审批人手中-->
:process-instance=
"processInstance"
<TaskDelegateForm
ref=
"taskDelegateForm"
@
success=
"getDetail"
/>
:process-definition=
"processDefinition"
<!-- 弹窗:加签,当前任务审批人为A,向前加签选了一个C,则需要C先审批,然后再是A审批,向后加签B,A审批完,需要B再审批完,才算完成这个任务节点 -->
:userOptions=
"userOptions"
<TaskSignCreateForm
ref=
"taskSignCreateFormRef"
@
success=
"getDetail"
/>
@
success=
"refresh"
/>
</div>
</el-scrollbar>
</div>
</ContentWrap>
</ContentWrap>
</
template
>
</
template
>
<
script
lang=
"ts"
setup
>
<
script
lang=
"ts"
setup
>
import
{
useUserStore
}
from
'@/store/modules/user'
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
type
{
ApiAttrs
}
from
'@form-create/element-ui/types/config'
import
type
{
ApiAttrs
}
from
'@form-create/element-ui/types/config'
import
*
as
DefinitionApi
from
'@/api/bpm/definition'
import
*
as
ProcessInstanceApi
from
'@/api/bpm/processInstance'
import
*
as
ProcessInstanceApi
from
'@/api/bpm/processInstance'
import
*
as
TaskApi
from
'@/api/bpm/task'
import
*
as
TaskApi
from
'@/api/bpm/task'
import
ProcessInstanceBpmnViewer
from
'./ProcessInstanceBpmnViewer.vue'
import
ProcessInstanceBpmnViewer
from
'./ProcessInstanceBpmnViewer.vue'
import
ProcessInstanceTaskList
from
'./ProcessInstanceTaskList.vue'
import
ProcessInstanceTaskList
from
'./ProcessInstanceTaskList.vue'
import
TaskReturnForm
from
'./dialog/TaskReturnForm.vue'
import
ProcessInstanceOperationButton
from
'./ProcessInstanceOperationButton.vue'
import
TaskDelegateForm
from
'./dialog/TaskDelegateForm.vue'
import
ProcessInstanceTimeline
from
'./ProcessInstanceTimeline.vue'
import
TaskTransferForm
from
'./dialog/TaskTransferForm.vue'
import
TaskSignCreateForm
from
'./dialog/TaskSignCreateForm.vue'
import
{
registerComponent
}
from
'@/utils/routerHelper'
import
{
isEmpty
}
from
'@/utils/is'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserApi
from
'@/api/system/user'
import
{
import
{
FieldPermissionType
}
from
'@/components/SimpleProcessDesignerV2/src/consts'
OperationButtonType
,
import
audit1
from
'@/assets/svgs/bpm/audit1.svg'
OPERATION_BUTTON_NAME
import
audit2
from
'@/assets/svgs/bpm/audit2.svg'
}
from
'@/components/SimpleProcessDesignerV2/src/consts'
import
audit3
from
'@/assets/svgs/bpm/audit3.svg'
import
audit4
from
'@/assets/svgs/bpm/audit4.svg'
defineOptions
({
name
:
'BpmProcessInstanceDetail'
})
defineOptions
({
name
:
'BpmProcessInstanceDetail'
})
const
props
=
defineProps
<
{
const
{
query
}
=
useRoute
()
// 查询参数
id
:
string
// 流程实例的编号
taskId
?:
string
// 任务编号
activityId
?:
string
//流程活动编号,用于抄送查看
}
>
()
const
message
=
useMessage
()
// 消息弹窗
const
message
=
useMessage
()
// 消息弹窗
const
{
proxy
}
=
getCurrentInstance
()
as
any
const
userId
=
useUserStore
().
getUser
.
id
// 当前登录的编号
const
id
=
query
.
id
as
unknown
as
string
// 流程实例的编号
const
processInstanceLoading
=
ref
(
false
)
// 流程实例的加载中
const
processInstanceLoading
=
ref
(
false
)
// 流程实例的加载中
const
processInstance
=
ref
<
any
>
({})
// 流程实例
const
processInstance
=
ref
<
any
>
({})
// 流程实例
const
bpmnXml
=
ref
(
''
)
// BPMN XML
const
processDefinition
=
ref
<
any
>
({})
// 流程定义
const
timelineRef
=
ref
()
// 操作按钮组件 ref
const
operationButtonRef
=
ref
()
const
tasksLoad
=
ref
(
true
)
// 任务的加载中
const
tasksLoad
=
ref
(
true
)
// 任务的加载中
const
tasks
=
ref
<
any
[]
>
([])
// 任务列表
const
tasks
=
ref
<
any
[]
>
([])
// 任务列表
// ========== 审批信息 ==========
const
auditIcons
=
{
const
runningTasks
=
ref
<
any
[]
>
([])
// 运行中的任务
1
:
audit1
,
const
auditForms
=
ref
<
any
[]
>
([])
// 审批任务的表单
2
:
audit2
,
const
auditRule
=
reactive
({
3
:
audit3
,
reason
:
[{
required
:
true
,
message
:
'审批建议不能为空'
,
trigger
:
'blur'
}]
4
:
audit4
})
}
const
approveForms
=
ref
<
any
[]
>
([])
// 审批通过时,额外的补充信息
const
approveFormFApis
=
ref
<
ApiAttrs
[]
>
([])
// approveForms 的 fAPi
// ========== 申请信息 ==========
// ========== 申请信息 ==========
const
fApi
=
ref
<
ApiAttrs
>
()
//
const
fApi
=
ref
<
ApiAttrs
>
()
//
...
@@ -220,163 +167,106 @@ const detailForm = ref({
...
@@ -220,163 +167,106 @@ const detailForm = ref({
value
:
{}
value
:
{}
})
// 流程实例的表单详情
})
// 流程实例的表单详情
/** 监听 approveFormFApis,实现它对应的 form-create 初始化后,隐藏掉对应的表单提交按钮 */
watch
(
()
=>
approveFormFApis
.
value
,
(
value
)
=>
{
value
?.
forEach
((
api
)
=>
{
api
.
btn
.
show
(
false
)
api
.
resetBtn
.
show
(
false
)
})
},
{
deep
:
true
}
)
/** 处理审批通过和不通过的操作 */
const
handleAudit
=
async
(
task
,
pass
)
=>
{
// 1.1 获得对应表单
const
index
=
runningTasks
.
value
.
indexOf
(
task
)
const
auditFormRef
=
proxy
.
$refs
[
'form'
+
index
][
0
]
// 1.2 校验表单
const
elForm
=
unref
(
auditFormRef
)
if
(
!
elForm
)
return
let
valid
=
await
elForm
.
validate
()
if
(
!
valid
)
return
// 校验申请表单(可编辑字段)
// TODO @jason:之前这里是 if (!fApi.value) return;针对业务表单的情况下,会导致没办法审核,可能要看下。我这里改了点,看看是不是还有别的地方兼容性
if
(
fApi
.
value
)
{
valid
=
await
fApi
.
value
.
validate
()
if
(
!
valid
)
return
}
// 2.1 提交审批
const
data
=
{
id
:
task
.
id
,
reason
:
auditForms
.
value
[
index
].
reason
,
copyUserIds
:
auditForms
.
value
[
index
].
copyUserIds
}
if
(
pass
)
{
// 审批通过,并且有额外的 approveForm 表单,需要校验 + 拼接到 data 表单里提交
const
formCreateApi
=
approveFormFApis
.
value
[
index
]
if
(
formCreateApi
)
{
await
formCreateApi
.
validate
()
data
.
variables
=
approveForms
.
value
[
index
].
value
}
// 获取表单可编辑字段的值
if
(
fApi
.
value
)
{
data
.
variables
=
getWritableValueOfForm
(
task
.
fieldsPermission
)
}
await
TaskApi
.
approveTask
(
data
)
message
.
success
(
'审批通过成功'
)
}
else
{
await
TaskApi
.
rejectTask
(
data
)
message
.
success
(
'审批不通过成功'
)
}
// 2.2 加载最新数据
getDetail
()
}
/** 转派审批人 */
const
taskTransferFormRef
=
ref
()
const
openTaskUpdateAssigneeForm
=
(
id
:
string
)
=>
{
taskTransferFormRef
.
value
.
open
(
id
)
}
/** 处理审批退回的操作 */
const
taskDelegateForm
=
ref
()
const
handleDelegate
=
async
(
task
)
=>
{
taskDelegateForm
.
value
.
open
(
task
.
id
)
}
/** 处理审批退回的操作 */
const
taskReturnFormRef
=
ref
()
const
handleBack
=
async
(
task
:
any
)
=>
{
taskReturnFormRef
.
value
.
open
(
task
.
id
)
}
/** 处理审批加签的操作 */
const
taskSignCreateFormRef
=
ref
()
const
handleSign
=
async
(
task
:
any
)
=>
{
taskSignCreateFormRef
.
value
.
open
(
task
.
id
)
}
/** 获得详情 */
/** 获得详情 */
const
getDetail
=
async
()
=>
{
const
getDetail
=
()
=>
{
// 1. 获
得流程任务列表(审批记录)。 需要先获取任务,表单的权限设置需要根据任务来设置
// 1. 获
取审批详情
await
getTaskList
()
getApprovalDetail
()
// 2. 获得流程
实例相关
// 2. 获得流程
任务列表
get
ProcessInstance
()
get
TaskList
()
}
}
/** 加载流程实例 */
/** 加载流程实例 */
const
BusinessFormComponent
=
ref
(
null
)
// 异步组件
const
BusinessFormComponent
=
ref
<
any
>
(
null
)
// 异步组件
const
getProcessInstance
=
async
()
=>
{
/** 获取审批详情 */
try
{
const
getApprovalDetail
=
async
()
=>
{
processInstanceLoading
.
value
=
true
processInstanceLoading
.
value
=
true
const
data
=
await
ProcessInstanceApi
.
getProcessInstance
(
id
)
try
{
const
param
=
{
processInstanceId
:
props
.
id
,
activityId
:
props
.
activityId
,
taskId
:
props
.
taskId
}
const
data
=
await
ProcessInstanceApi
.
getApprovalDetail
(
param
)
if
(
!
data
)
{
if
(
!
data
)
{
message
.
error
(
'查询不到审批详情信息!'
)
return
}
if
(
!
data
.
processDefinition
||
!
data
.
processInstance
)
{
message
.
error
(
'查询不到流程信息!'
)
message
.
error
(
'查询不到流程信息!'
)
return
return
}
}
processInstance
.
value
=
data
processInstance
.
value
=
data
.
processInstance
processDefinition
.
value
=
data
.
processDefinition
// 设置表单信息
// 设置表单信息
const
processDefinition
=
data
.
processDefinition
if
(
processDefinition
.
value
.
formType
===
10
)
{
if
(
processDefinition
.
formType
===
10
)
{
// 获取表单字段权限
const
formFieldsPermission
=
data
.
formFieldsPermission
if
(
detailForm
.
value
.
rule
.
length
>
0
)
{
if
(
detailForm
.
value
.
rule
.
length
>
0
)
{
detailForm
.
value
.
value
=
data
.
formVariables
// 避免刷新 form-create 显示不了,
detailForm
.
value
.
value
=
processInstance
.
value
.
formVariables
}
else
{
}
else
{
setConfAndFields2
(
setConfAndFields2
(
detailForm
,
detailForm
,
processDefinition
.
formConf
,
processDefinition
.
value
.
formConf
,
processDefinition
.
formFields
,
processDefinition
.
value
.
formFields
,
data
.
formVariables
processInstance
.
value
.
formVariables
)
)
}
}
nextTick
().
then
(()
=>
{
nextTick
().
then
(()
=>
{
fApi
.
value
?.
btn
.
show
(
false
)
fApi
.
value
?.
btn
.
show
(
false
)
fApi
.
value
?.
resetBtn
.
show
(
false
)
fApi
.
value
?.
resetBtn
.
show
(
false
)
//@ts-ignore
fApi
.
value
?.
disabled
(
true
)
fApi
.
value
?.
disabled
(
true
)
// 设置表单权限。后续需要改造成。只处理一个运行中的任务
// 设置表单字段权限
if
(
runningTasks
.
value
.
length
>
0
)
{
if
(
formFieldsPermission
)
{
const
task
=
runningTasks
.
value
.
at
(
0
)
Object
.
keys
(
data
.
formFieldsPermission
).
forEach
((
item
)
=>
{
if
(
task
.
fieldsPermission
)
{
setFieldPermission
(
item
,
formFieldsPermission
[
item
])
Object
.
keys
(
task
.
fieldsPermission
).
forEach
((
item
)
=>
{
setFieldPermission
(
item
,
task
.
fieldsPermission
[
item
])
})
})
}
}
}
})
})
}
else
{
// 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue
BusinessFormComponent
.
value
=
registerComponent
(
data
.
processDefinition
.
formCustomViewPath
)
}
}
// 加载流程图
// 获取审批节点,显示 Timeline 的数据
bpmnXml
.
value
=
(
approveNodes
.
value
=
data
.
approveNodes
await
DefinitionApi
.
getProcessDefinition
(
processDefinition
.
id
as
number
)
)?.
bpmnXml
// 获取待办任务显示操作按钮
operationButtonRef
.
value
?.
loadTodoTask
(
data
.
todoTask
)
}
finally
{
}
finally
{
processInstanceLoading
.
value
=
false
processInstanceLoading
.
value
=
false
}
}
}
}
// 审批节点信息
const
approveNodes
=
ref
<
ProcessInstanceApi
.
ApprovalNodeInfo
[]
>
([])
/**
* 设置表单权限
*/
const
setFieldPermission
=
(
field
:
string
,
permission
:
string
)
=>
{
if
(
permission
===
FieldPermissionType
.
READ
)
{
//@ts-ignore
fApi
.
value
?.
disabled
(
true
,
field
)
}
if
(
permission
===
FieldPermissionType
.
WRITE
)
{
//@ts-ignore
fApi
.
value
?.
disabled
(
false
,
field
)
}
if
(
permission
===
FieldPermissionType
.
NONE
)
{
//@ts-ignore
fApi
.
value
?.
hidden
(
true
,
field
)
}
}
/** 加载任务列表 */
/** 加载任务列表 */
const
getTaskList
=
async
()
=>
{
const
getTaskList
=
async
()
=>
{
runningTasks
.
value
=
[]
auditForms
.
value
=
[]
approveForms
.
value
=
[]
approveFormFApis
.
value
=
[]
try
{
try
{
// 获得未取消的任务
// 获得未取消的任务
tasksLoad
.
value
=
true
tasksLoad
.
value
=
true
const
data
=
await
TaskApi
.
getTaskListByProcessInstanceId
(
id
)
const
data
=
await
TaskApi
.
getTaskListByProcessInstanceId
(
props
.
id
)
tasks
.
value
=
[]
tasks
.
value
=
[]
// 1.1 移除已取消的审批
// 1.1 移除已取消的审批
data
.
forEach
((
task
)
=>
{
data
.
forEach
((
task
:
any
)
=>
{
if
(
task
.
status
!==
4
)
{
if
(
task
.
status
!==
4
)
{
tasks
.
value
.
push
(
task
)
tasks
.
value
.
push
(
task
)
}
}
...
@@ -395,77 +285,21 @@ const getTaskList = async () => {
...
@@ -395,77 +285,21 @@ const getTaskList = async () => {
return
b
.
createTime
-
a
.
createTime
return
b
.
createTime
-
a
.
createTime
}
}
})
})
// 获得需要自己审批的任务
loadRunningTask
(
tasks
.
value
)
}
finally
{
}
finally
{
tasksLoad
.
value
=
false
tasksLoad
.
value
=
false
}
}
}
}
/**
/**
*
设置 runningTasks 中的任务
*
操作成功后刷新
*/
*/
const
loadRunningTask
=
(
tasks
)
=>
{
const
refresh
=
()
=>
{
tasks
.
forEach
((
task
)
=>
{
// 重新获取详情
if
(
!
isEmpty
(
task
.
children
))
{
getDetail
()
loadRunningTask
(
task
.
children
)
}
// 2.1 只有待处理才需要
if
(
task
.
status
!==
1
&&
task
.
status
!==
6
)
{
return
}
// 2.2 自己不是处理人
if
(
!
task
.
assigneeUser
||
task
.
assigneeUser
.
id
!==
userId
)
{
return
}
// 2.3 添加到处理任务
runningTasks
.
value
.
push
({
...
task
})
auditForms
.
value
.
push
({
reason
:
''
,
copyUserIds
:
[]
})
// 2.4 处理 approve 表单
if
(
task
.
formId
&&
task
.
formConf
)
{
const
approveForm
=
{}
setConfAndFields2
(
approveForm
,
task
.
formConf
,
task
.
formFields
,
task
.
formVariables
)
approveForms
.
value
.
push
(
approveForm
)
}
else
{
approveForms
.
value
.
push
({})
// 占位,避免为空
}
})
}
}
/**
/** 当前的Tab */
* 设置表单权限
const
activeTab
=
ref
(
'form'
)
*/
const
setFieldPermission
=
(
field
:
string
,
permission
:
string
)
=>
{
if
(
permission
===
'1'
)
{
fApi
.
value
?.
disabled
(
true
,
field
)
}
if
(
permission
===
'2'
)
{
fApi
.
value
?.
disabled
(
false
,
field
)
}
if
(
permission
===
'3'
)
{
fApi
.
value
?.
hidden
(
true
,
field
)
}
}
/**
* 获取可以编辑字段的值
*/
const
getWritableValueOfForm
=
(
fieldsPermission
:
Object
)
=>
{
const
fieldsValue
=
{}
if
(
fieldsPermission
&&
fApi
.
value
)
{
Object
.
keys
(
fieldsPermission
).
forEach
((
item
)
=>
{
if
(
fieldsPermission
[
item
]
===
'2'
)
{
fieldsValue
[
item
]
=
fApi
.
value
.
getValue
(
item
)
}
})
}
return
fieldsValue
}
/** 初始化 */
/** 初始化 */
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
...
@@ -475,3 +309,38 @@ onMounted(async () => {
...
@@ -475,3 +309,38 @@ onMounted(async () => {
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
})
})
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
$
wrap-padding-height
:
20px
;
$
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
)
-
35px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
);
overflow
:
auto
;
.form-scroll-area
{
height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
-
$
process-header-height
-
40px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
-
$
process-header-height
-
40px
);
overflow
:
auto
;
}
}
.form-box
{
:deep(.el-card)
{
border
:
none
;
}
}
</
style
>
src/views/bpm/processInstance/detail/index_new.vue
deleted
100644 → 0
View file @
dcdce412
<
template
>
<ContentWrap
:bodyStyle=
"
{ padding: '10px 20px 0' }" class="position-relative">
<div
class=
"processInstance-wrap-main"
>
<el-scrollbar>
<img
class=
"position-absolute right-20px"
width=
"150"
:src=
"auditIcons[processInstance.status]"
alt=
""
/>
<div
class=
"text-#878c93 h-15px"
>
编号:
{{
id
}}
</div>
<el-divider
class=
"!my-8px"
/>
<div
class=
"flex items-center gap-5 mb-10px h-40px"
>
<div
class=
"text-26px font-bold mb-5px"
>
{{
processInstance
.
name
}}
</div>
<dict-tag
v-if=
"processInstance.status"
:type=
"DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value=
"processInstance.status"
/>
</div>
<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"
>
<el-avatar
:size=
"28"
v-if=
"processInstance?.startUser?.avatar"
:src=
"processInstance?.startUser?.avatar"
/>
<el-avatar
:size=
"28"
v-else-if=
"processInstance?.startUser?.nickname"
>
{{
processInstance
?.
startUser
?.
nickname
.
substring
(
0
,
1
)
}}
</el-avatar>
{{
processInstance
?.
startUser
?.
nickname
}}
</div>
<div
class=
"text-#878c93"
>
{{
formatDate
(
processInstance
.
startTime
)
}}
提交
</div>
</div>
<el-tabs
v-model=
"activeTab"
>
<!-- 表单信息 -->
<el-tab-pane
label=
"审批详情"
name=
"form"
>
<div
class=
"form-scroll-area"
>
<el-scrollbar>
<el-row>
<el-col
:span=
"18"
class=
"!flex !flex-col formCol"
>
<!-- 表单信息 -->
<div
v-loading=
"processInstanceLoading"
class=
"form-box flex flex-col mb-30px flex-1"
>
<!-- 情况一:流程表单 -->
<el-col
v-if=
"processDefinition?.formType === 10"
>
<form-create
v-model=
"detailForm.value"
v-model:api=
"fApi"
:option=
"detailForm.option"
:rule=
"detailForm.rule"
/>
</el-col>
<!-- 情况二:业务表单 -->
<div
v-if=
"processDefinition?.formType === 20"
>
<BusinessFormComponent
:id=
"processInstance.businessKey"
/>
</div>
</div>
</el-col>
<el-col
:span=
"6"
>
<!-- 审批记录时间线 -->
<ProcessInstanceTimeline
ref=
"timelineRef"
:approve-nodes=
"approveNodes"
/>
</el-col>
</el-row>
</el-scrollbar>
</div>
</el-tab-pane>
<!-- 流程图 -->
<el-tab-pane
label=
"流程图"
name=
"diagram"
>
<div
class=
"form-scroll-area"
>
<ProcessInstanceBpmnViewer
:id=
"`$
{id}`" :loading="processInstanceLoading" :show-header="false"/>
</div>
</el-tab-pane>
<!-- 流转记录 -->
<el-tab-pane
label=
"流转记录"
name=
"record"
>
<div
class=
"form-scroll-area"
>
<el-scrollbar>
<ProcessInstanceTaskList
:loading=
"tasksLoad"
:process-instance=
"processInstance"
:tasks=
"tasks"
:show-header=
"false"
/>
</el-scrollbar>
</div>
</el-tab-pane>
<!-- 流转评论 TODO 待开发 -->
<el-tab-pane
label=
"流转评论"
name=
"comment"
>
<div
class=
"form-scroll-area"
>
<el-scrollbar>
流转评论
</el-scrollbar>
</div>
</el-tab-pane>
</el-tabs>
<div
class=
"b-t-solid border-t-1px border-[var(--el-border-color)]"
>
<!-- 操作栏按钮 -->
<ProcessInstanceOperationButton
ref=
"operationButtonRef"
:process-instance=
"processInstance"
:process-definition=
"processDefinition"
:userOptions=
"userOptions"
@
success=
"refresh"
/>
</div>
</el-scrollbar>
</div>
</ContentWrap>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
formatDate
}
from
'@/utils/formatTime'
import
{
DICT_TYPE
}
from
'@/utils/dict'
import
{
setConfAndFields2
}
from
'@/utils/formCreate'
import
type
{
ApiAttrs
}
from
'@form-create/element-ui/types/config'
import
*
as
ProcessInstanceApi
from
'@/api/bpm/processInstance'
import
*
as
TaskApi
from
'@/api/bpm/task'
import
ProcessInstanceBpmnViewer
from
'./ProcessInstanceBpmnViewer.vue'
import
ProcessInstanceTaskList
from
'./ProcessInstanceTaskList.vue'
import
ProcessInstanceOperationButton
from
'./ProcessInstanceOperationButton.vue'
import
ProcessInstanceTimeline
from
'./ProcessInstanceTimeline.vue'
import
*
as
UserApi
from
'@/api/system/user'
import
{
FieldPermissionType
}
from
'@/components/SimpleProcessDesignerV2/src/consts'
import
audit1
from
'@/assets/svgs/bpm/audit1.svg'
import
audit2
from
'@/assets/svgs/bpm/audit2.svg'
import
audit3
from
'@/assets/svgs/bpm/audit3.svg'
import
audit4
from
'@/assets/svgs/bpm/audit4.svg'
defineOptions
({
name
:
'BpmProcessInstanceDetail'
})
const
props
=
defineProps
<
{
id
:
string
// 流程实例的编号
taskId
?:
string
// 任务编号
activityId
?:
string
//流程活动编号,用于抄送查看
}
>
()
const
message
=
useMessage
()
// 消息弹窗
const
processInstanceLoading
=
ref
(
false
)
// 流程实例的加载中
const
processInstance
=
ref
<
any
>
({})
// 流程实例
const
processDefinition
=
ref
<
any
>
({})
// 流程定义
const
timelineRef
=
ref
()
// 操作按钮组件 ref
const
operationButtonRef
=
ref
()
const
tasksLoad
=
ref
(
true
)
// 任务的加载中
const
tasks
=
ref
<
any
[]
>
([])
// 任务列表
const
auditIcons
=
{
1
:
audit1
,
2
:
audit2
,
3
:
audit3
,
4
:
audit4
}
// ========== 申请信息 ==========
const
fApi
=
ref
<
ApiAttrs
>
()
//
const
detailForm
=
ref
({
rule
:
[],
option
:
{},
value
:
{}
})
// 流程实例的表单详情
/** 获得详情 */
const
getDetail
=
async
()
=>
{
// 1. 获取审批详情
getApprovalDetail
()
// 2. 获得流程任务列表
getTaskList
()
}
/** 加载流程实例 */
const
BusinessFormComponent
=
ref
<
any
>
(
null
)
// 异步组件
/** 获取审批详情 */
const
getApprovalDetail
=
async
()
=>
{
processInstanceLoading
.
value
=
true
try
{
const
param
=
{
processInstanceId
:
props
.
id
,
activityId
:
props
.
activityId
,
taskId
:
props
.
taskId
}
const
data
=
await
ProcessInstanceApi
.
getApprovalDetail
(
param
);
if
(
!
data
)
{
message
.
error
(
'查询不到审批详情信息!'
)
return
}
if
(
!
data
.
processDefinition
||
!
data
.
processInstance
)
{
message
.
error
(
'查询不到流程信息!'
)
return
}
processInstance
.
value
=
data
.
processInstance
processDefinition
.
value
=
data
.
processDefinition
// 设置表单信息
if
(
processDefinition
.
value
.
formType
===
10
)
{
// 获取表单字段权限
const
formFieldsPermission
=
data
.
formFieldsPermission
if
(
detailForm
.
value
.
rule
.
length
>
0
)
{
// 避免刷新 form-create 显示不了,
detailForm
.
value
.
value
=
processInstance
.
value
.
formVariables
}
else
{
setConfAndFields2
(
detailForm
,
processDefinition
.
value
.
formConf
,
processDefinition
.
value
.
formFields
,
processInstance
.
value
.
formVariables
)
}
nextTick
().
then
(()
=>
{
fApi
.
value
?.
btn
.
show
(
false
)
fApi
.
value
?.
resetBtn
.
show
(
false
)
//@ts-ignore
fApi
.
value
?.
disabled
(
true
)
// 设置表单字段权限
if
(
formFieldsPermission
)
{
Object
.
keys
(
data
.
formFieldsPermission
).
forEach
((
item
)
=>
{
setFieldPermission
(
item
,
formFieldsPermission
[
item
])
})
}
})
}
// 获取审批节点,显示 Timeline 的数据
approveNodes
.
value
=
data
.
approveNodes
// 获取待办任务显示操作按钮
operationButtonRef
.
value
?.
loadTodoTask
(
data
.
todoTask
)
}
finally
{
processInstanceLoading
.
value
=
false
}
}
// 审批节点信息
const
approveNodes
=
ref
<
ProcessInstanceApi
.
ApprovalNodeInfo
[]
>
([])
/**
* 设置表单权限
*/
const
setFieldPermission
=
(
field
:
string
,
permission
:
string
)
=>
{
if
(
permission
===
FieldPermissionType
.
READ
)
{
//@ts-ignore
fApi
.
value
?.
disabled
(
true
,
field
)
}
if
(
permission
===
FieldPermissionType
.
WRITE
)
{
//@ts-ignore
fApi
.
value
?.
disabled
(
false
,
field
)
}
if
(
permission
===
FieldPermissionType
.
NONE
)
{
//@ts-ignore
fApi
.
value
?.
hidden
(
true
,
field
)
}
}
/** 加载任务列表 */
const
getTaskList
=
async
()
=>
{
try
{
// 获得未取消的任务
tasksLoad
.
value
=
true
const
data
=
await
TaskApi
.
getTaskListByProcessInstanceId
(
props
.
id
)
tasks
.
value
=
[]
// 1.1 移除已取消的审批
data
.
forEach
((
task
:
any
)
=>
{
if
(
task
.
status
!==
4
)
{
tasks
.
value
.
push
(
task
)
}
})
// 1.2 排序,将未完成的排在前面,已完成的排在后面;
tasks
.
value
.
sort
((
a
,
b
)
=>
{
// 有已完成的情况,按照完成时间倒序
if
(
a
.
endTime
&&
b
.
endTime
)
{
return
b
.
endTime
-
a
.
endTime
}
else
if
(
a
.
endTime
)
{
return
1
}
else
if
(
b
.
endTime
)
{
return
-
1
// 都是未完成,按照创建时间倒序
}
else
{
return
b
.
createTime
-
a
.
createTime
}
})
}
finally
{
tasksLoad
.
value
=
false
}
}
/**
* 操作成功后刷新
*/
const
refresh
=
()
=>
{
// 重新获取详情
getDetail
()
}
/** 当前的Tab */
const
activeTab
=
ref
(
'form'
)
/** 初始化 */
const
userOptions
=
ref
<
UserApi
.
UserVO
[]
>
([])
// 用户列表
onMounted
(
async
()
=>
{
getDetail
()
// 获得用户列表
userOptions
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
<
style
lang=
"scss"
scoped
>
$
wrap-padding-height
:
20px
;
$
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
)
-
35px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
);
overflow
:
auto
;
.form-scroll-area
{
height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
-
$
process-header-height
-
40px
);
max-height
:
calc
(
100vh
-
var
(
--top-tool-height
)
-
var
(
--tags-view-height
)
-
var
(
--app-footer-height
)
-
35px
-
$
process-header-height
-
40px
);
overflow
:
auto
;
}
}
.form-box
{
:deep(.el-card)
{
border
:
none
;
}
}
</
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