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
c6f70cce
authored
Feb 09, 2025
by
YunaiV
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/bpm' of
https://gitee.com/yudaocode/yudao-ui-admin-vue3
# Conflicts: # src/views/system/menu/index.vue
parents
f4a83c09
b0d4e39e
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
645 additions
and
102 deletions
+645
-102
src/components/SimpleProcessDesignerV2/src/consts.ts
+30
-14
src/components/SimpleProcessDesignerV2/src/node.ts
+27
-9
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue
+4
-16
src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue
+1
-0
src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue
+202
-9
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
+16
-14
src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
+5
-13
src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestParamSetting.vue
+18
-15
src/router/modules/remaining.ts
+12
-0
src/views/bpm/category/CategoryForm.vue
+5
-0
src/views/bpm/model/CategoryDraggableModel.vue
+20
-0
src/views/bpm/model/form/ExtraSettings.vue
+6
-6
src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue
+10
-0
src/views/bpm/processInstance/report/index.vue
+274
-0
src/views/bpm/task/copy/index.vue
+9
-0
src/views/bpm/task/done/index.vue
+3
-3
src/views/bpm/task/todo/index.vue
+3
-3
No files found.
src/components/SimpleProcessDesignerV2/src/consts.ts
View file @
c6f70cce
...
...
@@ -246,15 +246,15 @@ export type AssignEmptyHandler = {
export
type
ListenerHandler
=
{
enable
:
boolean
path
?:
string
header
?:
Listener
Param
[]
body
?:
Listener
Param
[]
header
?:
HttpRequest
Param
[]
body
?:
HttpRequest
Param
[]
}
export
type
Listener
Param
=
{
export
type
HttpRequest
Param
=
{
key
:
string
type
:
number
value
:
string
}
export
enum
Listener
ParamTypeEnum
{
export
enum
BpmHttpRequest
ParamTypeEnum
{
/**
* 固定值
*/
...
...
@@ -264,7 +264,7 @@ export enum ListenerParamTypeEnum {
*/
FROM_FORM
=
2
}
export
const
LISTENER_MAP
_TYPES
=
[
export
const
BPM_HTTP_REQUEST_PARAM
_TYPES
=
[
{
value
:
1
,
label
:
'固定值'
...
...
@@ -371,13 +371,13 @@ export enum TimeUnitType {
/**
* 条件节点设置结构定义,用于条件节点
*/
export
type
ConditionSetting
=
{
export
type
ConditionSetting
=
{
// 条件类型
conditionType
?:
ConditionType
,
conditionType
?:
ConditionType
// 条件表达式
conditionExpression
?:
string
,
conditionExpression
?:
string
// 条件组
conditionGroups
?:
ConditionGroup
,
conditionGroups
?:
ConditionGroup
// 是否默认的条件
defaultFlow
?:
boolean
}
...
...
@@ -710,13 +710,14 @@ export type RouterSetting = {
conditionGroups
:
ConditionGroup
}
// ==================== 触发器相关定义 ====================
// ==================== 触发器相关定义 ====================
/**
* 触发器节点结构定义
*/
export
type
TriggerSetting
=
{
type
:
TriggerTypeEnum
httpRequestSetting
:
HttpRequestTriggerSetting
httpRequestSetting
?:
HttpRequestTriggerSetting
normalFormSetting
?:
NormalFormTriggerSetting
}
/**
...
...
@@ -727,6 +728,10 @@ export enum TriggerTypeEnum {
* 发送 HTTP 请求触发器
*/
HTTP_REQUEST
=
1
,
/**
* 更新流程表单触发器
*/
UPDATE_NORMAL_FORM
=
2
// TODO @jason:FORM_UPDATE?
}
/**
...
...
@@ -736,11 +741,22 @@ export type HttpRequestTriggerSetting = {
// 请求 URL
url
:
string
// 请求头参数设置
header
?:
ListenerParam
[]
// TODO 需要重命名一下
header
?:
HttpRequestParam
[]
// 请求体参数设置
body
?:
ListenerParam
[]
body
?:
HttpRequestParam
[]
// 请求响应设置
response
?:
Record
<
string
,
string
>
[]
}
/**
* 流程表单触发器配置结构定义
*/
export
type
NormalFormTriggerSetting
=
{
// 更新表单字段
updateFormFields
?:
Record
<
string
,
any
>
}
export
const
TRIGGER_TYPES
:
DictDataVO
[]
=
[
{
label
:
'HTTP 请求'
,
value
:
TriggerTypeEnum
.
HTTP_REQUEST
}
{
label
:
'HTTP 请求'
,
value
:
TriggerTypeEnum
.
HTTP_REQUEST
},
{
label
:
'修改表单数据'
,
value
:
TriggerTypeEnum
.
UPDATE_NORMAL_FORM
}
]
src/components/SimpleProcessDesignerV2/src/node.ts
View file @
c6f70cce
...
...
@@ -14,7 +14,8 @@ import {
AssignStartUserHandlerType
,
AssignEmptyHandlerType
,
FieldPermissionType
,
ListenerParam
HttpRequestParam
,
ProcessVariableEnum
}
from
'./consts'
import
{
parseFormFields
}
from
'@/components/FormCreate/src/utils'
...
...
@@ -105,14 +106,31 @@ export function useFormFieldsPermission(defaultPermission: FieldPermissionType)
getNodeConfigFormFields
}
}
/**
* @description 获取表单的字段
* @description 获取
流程
表单的字段
*/
export
function
useFormFields
()
{
const
formFields
=
inject
<
Ref
<
string
[]
>>
(
'formFields'
,
ref
([]))
// 流程表单字段
return
parseFormCreateFields
(
unref
(
formFields
))
}
// TODO @芋艿:后续需要把各种类似 useFormFieldsPermission 的逻辑,抽成一个通用方法。
/**
* @description 获取流程表单的字段和发起人字段
*/
export
function
useFormFieldsAndStartUser
()
{
const
injectFormFields
=
inject
<
Ref
<
string
[]
>>
(
'formFields'
,
ref
([]))
// 流程表单字段
const
formFields
=
parseFormCreateFields
(
unref
(
injectFormFields
))
// 添加发起人
formFields
.
unshift
({
field
:
ProcessVariableEnum
.
START_USER_ID
,
title
:
'发起人'
,
required
:
true
})
return
formFields
}
export
type
UserTaskFormType
=
{
candidateStrategy
:
CandidateStrategy
approveMethod
:
ApproveMethodType
...
...
@@ -139,20 +157,20 @@ export type UserTaskFormType = {
taskCreateListenerEnable
?:
boolean
taskCreateListenerPath
?:
string
taskCreateListener
?:
{
header
:
ListenerParam
[],
body
:
Listener
Param
[]
header
:
HttpRequestParam
[]
body
:
HttpRequest
Param
[]
}
taskAssignListenerEnable
?:
boolean
taskAssignListenerPath
?:
string
taskAssignListener
?:
{
header
:
ListenerParam
[],
body
:
Listener
Param
[]
header
:
HttpRequestParam
[]
body
:
HttpRequest
Param
[]
}
taskCompleteListenerEnable
?:
boolean
taskCompleteListenerPath
?:
string
taskCompleteListener
?:{
header
:
ListenerParam
[],
body
:
Listener
Param
[]
taskCompleteListener
?:
{
header
:
HttpRequestParam
[]
body
:
HttpRequest
Param
[]
}
signEnable
:
boolean
reasonRequire
:
boolean
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue
View file @
c6f70cce
...
...
@@ -47,10 +47,9 @@ import {
SimpleFlowNode
,
ConditionType
,
COMPARISON_OPERATORS
,
ProcessVariableEnum
}
from
'../consts'
import
{
getDefaultConditionNodeName
}
from
'../utils'
import
{
useFormFields
}
from
'../node'
import
{
useFormFields
AndStartUser
}
from
'../node'
import
Condition
from
'./components/Condition.vue'
const
message
=
useMessage
()
// 消息弹窗
defineOptions
({
...
...
@@ -176,23 +175,12 @@ const getShowText = (): string => {
}
return
showText
}
const
fieldsInfo
=
useFormFields
()
/** 条件规则可选择的表单字段 */
const
fieldOptions
=
computed
(()
=>
{
const
fieldsCopy
=
fieldsInfo
.
slice
()
// 固定添加发起人 ID 字段
fieldsCopy
.
unshift
({
field
:
ProcessVariableEnum
.
START_USER_ID
,
title
:
'发起人'
,
required
:
true
})
return
fieldsCopy
})
// 流程表单字段和发起人字段
const
fieldOptions
=
useFormFieldsAndStartUser
()
/** 获取字段名称 */
const
getFieldTitle
=
(
field
:
string
)
=>
{
const
item
=
fieldOptions
.
value
.
find
((
item
)
=>
item
.
field
===
field
)
const
item
=
fieldOptions
.
find
((
item
)
=>
item
.
field
===
field
)
return
item
?.
title
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue
View file @
c6f70cce
...
...
@@ -124,6 +124,7 @@ const saveConfig = async () => {
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
currentNode
.
value
.
name
=
nodeName
.
value
!
currentNode
.
value
.
showText
=
showText
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_TIME_DURATION
)
{
currentNode
.
value
.
delaySetting
=
{
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue
View file @
c6f70cce
...
...
@@ -35,6 +35,7 @@
/>
</el-select>
</el-form-item>
<!-- HTTP 请求触发器 -->
<div
v-if=
"configForm.type === TriggerTypeEnum.HTTP_REQUEST && configForm.httpRequestSetting"
>
...
...
@@ -46,14 +47,137 @@
:closable=
"false"
/>
</el-form-item>
<!-- 请求地址-->
<el-form-item
label=
"请求地址"
prop=
"httpRequestSetting.url"
>
<el-input
v-model=
"configForm.httpRequestSetting.url"
/>
</el-form-item>
<!-- 请求头,请求体设置-->
<HttpRequestParamSetting
:header=
"configForm.httpRequestSetting.header"
:body=
"configForm.httpRequestSetting.body"
:bind=
"'httpRequestSetting'"
/>
<!-- 返回值设置-->
<el-form-item
label=
"返回值"
>
<el-alert
title=
"通过请求返回值, 可以修改流程表单的值"
type=
"warning"
show-icon
:closable=
"false"
/>
</el-form-item>
<el-form-item>
<div
class=
"flex pt-2"
v-for=
"(item, index) in configForm.httpRequestSetting.response"
:key=
"index"
>
<div
class=
"mr-2"
>
<el-form-item
:prop=
"`httpRequestSetting.response.${index}.key`"
:rules=
"{
required: true,
message: '表单字段不能为空',
trigger: 'blur'
}"
>
<el-select
class=
"w-160px!"
v-model=
"item.key"
placeholder=
"请选择表单字段"
>
<el-option
v-for=
"(field, fIdx) in formFields"
:key=
"fIdx"
:label=
"field.title"
:value=
"field.field"
:disabled=
"!field.required"
/>
</el-select>
</el-form-item>
</div>
<div
class=
"mr-2"
>
<el-form-item
:prop=
"`httpRequestSetting.response.${index}.value`"
:rules=
"{
required: true,
message: '请求返回字段不能为空',
trigger: 'blur'
}"
>
<el-input
class=
"w-160px"
v-model=
"item.value"
placeholder=
"请求返回字段"
/>
</el-form-item>
</div>
<div
class=
"mr-1 pt-1 cursor-pointer"
>
<Icon
icon=
"ep:delete"
:size=
"18"
@
click=
"deleteHttpResponseSetting(configForm.httpRequestSetting.response!, index)"
/>
</div>
</div>
<el-button
type=
"primary"
text
@
click=
"addHttpResponseSetting(configForm.httpRequestSetting.response!)"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
添加一行
</el-button>
</el-form-item>
</div>
<div
v-if=
"
configForm.type === TriggerTypeEnum.UPDATE_NORMAL_FORM && configForm.normalFormSetting
"
>
<el-divider
content-position=
"left"
>
修改表单设置
</el-divider>
<div
class=
"flex items-center"
v-for=
"key in Object.keys(configForm.normalFormSetting.updateFormFields!)"
:key=
"key"
>
<div
class=
"mr-2 flex items-center"
>
<el-form-item>
<el-select
class=
"w-160px!"
:model-value=
"key"
@
update:model-value=
"(newKey) => updateFormFieldKey(key, newKey)"
placeholder=
"请选择表单字段"
:disabled=
"key !== ''"
>
<el-option
v-for=
"(field, fIdx) in optionalUpdateFormFields"
:key=
"fIdx"
:label=
"field.title"
:value=
"field.field"
:disabled=
"field.disabled"
/>
</el-select>
</el-form-item>
</div>
<div
class=
"mx-2"
><el-form-item>
的值设置为
</el-form-item></div>
<div
class=
"mr-2"
>
<el-form-item
:prop=
"`normalFormSetting.updateFormFields.${key}`"
:rules=
"{
required: true,
message: '值不能为空',
trigger: 'blur'
}"
>
<el-input
class=
"w-160px"
v-model=
"configForm.normalFormSetting.updateFormFields![key]"
placeholder=
"请输入"
:disabled=
"!key"
/>
</el-form-item>
</div>
<div
class=
"mr-1 pt-1 cursor-pointer"
>
<el-form-item>
<Icon
icon=
"ep:delete"
:size=
"18"
@
click=
"deleteFormFieldSetting(key)"
/>
</el-form-item>
</div>
</div>
<el-button
type=
"primary"
text
@
click=
"addFormFieldSetting()"
>
<Icon
icon=
"ep:plus"
class=
"mr-5px"
/>
添加修改字段
</el-button>
</div>
</el-form>
</div>
...
...
@@ -68,7 +192,7 @@
</template>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
TriggerSetting
,
TRIGGER_TYPES
,
TriggerTypeEnum
}
from
'../consts'
import
{
useWatchNode
,
useDrawer
,
useNodeName
}
from
'../node'
import
{
useWatchNode
,
useDrawer
,
useNodeName
,
useFormFields
}
from
'../node'
import
HttpRequestParamSetting
from
'./components/HttpRequestParamSetting.vue'
defineOptions
({
...
...
@@ -80,6 +204,7 @@ const props = defineProps({
required
:
true
}
})
const
message
=
useMessage
()
// 消息弹窗
// 抽屉配置
const
{
settingVisible
,
closeDrawer
,
openDrawer
}
=
useDrawer
()
// 当前节点
...
...
@@ -91,9 +216,7 @@ const formRef = ref() // 表单 Ref
// 表单校验规则
const
formRules
=
reactive
({
type
:
[{
required
:
true
,
message
:
'触发器类型不能为空'
,
trigger
:
'change'
}],
httpRequestSetting
:
{
url
:
[{
required
:
true
,
message
:
'请求地址不能为空'
,
trigger
:
'blur'
}]
}
'httpRequestSetting.url'
:
[{
required
:
true
,
message
:
'请求地址不能为空'
,
trigger
:
'blur'
}]
})
// 触发器配置表单数据
const
configForm
=
ref
<
TriggerSetting
>
({
...
...
@@ -101,9 +224,56 @@ const configForm = ref<TriggerSetting>({
httpRequestSetting
:
{
url
:
''
,
header
:
[],
body
:
[]
}
body
:
[],
response
:
[]
},
normalFormSetting
:
{
updateFormFields
:
{}
}
})
// 流程表单字段
const
formFields
=
useFormFields
()
// 可选的修改的表单字段
const
optionalUpdateFormFields
=
computed
(()
=>
{
const
usedFields
=
Object
.
keys
(
configForm
.
value
.
normalFormSetting
?.
updateFormFields
||
{})
return
formFields
.
map
((
field
)
=>
({
title
:
field
.
title
,
field
:
field
.
field
,
disabled
:
usedFields
.
includes
(
field
.
field
)
}))
})
const
updateFormFieldKey
=
(
oldKey
:
string
,
newKey
:
string
)
=>
{
if
(
!
configForm
.
value
.
normalFormSetting
?.
updateFormFields
)
return
const
value
=
configForm
.
value
.
normalFormSetting
.
updateFormFields
[
oldKey
]
delete
configForm
.
value
.
normalFormSetting
.
updateFormFields
[
oldKey
]
configForm
.
value
.
normalFormSetting
.
updateFormFields
[
newKey
]
=
value
}
/** 添加 HTTP 请求返回值设置项*/
const
addHttpResponseSetting
=
(
responseSetting
:
Record
<
string
,
string
>
[])
=>
{
responseSetting
.
push
({
key
:
''
,
value
:
''
})
}
/** 删除 HTTP 请求返回值设置项 */
const
deleteHttpResponseSetting
=
(
responseSetting
:
Record
<
string
,
string
>
[],
index
:
number
)
=>
{
responseSetting
.
splice
(
index
,
1
)
}
/** 添加修改表单设置项 */
const
addFormFieldSetting
=
()
=>
{
if
(
configForm
.
value
.
normalFormSetting
!
.
updateFormFields
===
undefined
)
{
configForm
.
value
.
normalFormSetting
!
.
updateFormFields
=
{}
}
configForm
.
value
.
normalFormSetting
!
.
updateFormFields
[
''
]
=
undefined
}
/** 删除修改表单设置项 */
const
deleteFormFieldSetting
=
(
key
:
string
)
=>
{
if
(
!
configForm
.
value
.
normalFormSetting
?.
updateFormFields
)
return
delete
configForm
.
value
.
normalFormSetting
.
updateFormFields
[
key
]
}
/** 保存配置 */
const
saveConfig
=
async
()
=>
{
...
...
@@ -112,16 +282,31 @@ const saveConfig = async () => {
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
currentNode
.
value
.
name
=
nodeName
.
value
!
currentNode
.
value
.
showText
=
showText
if
(
configForm
.
value
.
type
===
TriggerTypeEnum
.
HTTP_REQUEST
)
{
configForm
.
value
.
normalFormSetting
=
undefined
}
if
(
configForm
.
value
.
type
===
TriggerTypeEnum
.
UPDATE_NORMAL_FORM
)
{
configForm
.
value
.
httpRequestSetting
=
undefined
}
currentNode
.
value
.
triggerSetting
=
configForm
.
value
settingVisible
.
value
=
false
return
true
}
/** 获取节点展示内容 */
const
getShowText
=
():
string
=>
{
let
showText
=
''
if
(
configForm
.
value
.
type
===
TriggerTypeEnum
.
HTTP_REQUEST
)
{
showText
=
`
${
configForm
.
value
.
httpRequestSetting
.
url
}
`
showText
=
`
${
configForm
.
value
.
httpRequestSetting
?.
url
}
`
} else if (configForm.value.type === TriggerTypeEnum.UPDATE_NORMAL_FORM) {
const updatefields = Object.keys(configForm.value.normalFormSetting?.updateFormFields || {})
if (updatefields.length === 0) {
message.warning('请设置修改表单字段')
} else {
showText = '修改表单数据'
}
}
return showText
}
...
...
@@ -130,8 +315,16 @@ const getShowText = (): string => {
const showTriggerNodeConfig = (node: SimpleFlowNode) => {
nodeName.value = node.name
if (node.triggerSetting) {
configForm
.
value
.
type
=
node
.
triggerSetting
.
type
configForm
.
value
.
httpRequestSetting
=
node
.
triggerSetting
.
httpRequestSetting
configForm.value = {
type: node.triggerSetting.type,
httpRequestSetting: node.triggerSetting.httpRequestSetting || {
url: '',
header: [],
body: [],
response: []
},
normalFormSetting: node.triggerSetting.normalFormSetting || { updateFormFields: {} }
}
}
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
View file @
c6f70cce
...
...
@@ -61,7 +61,7 @@
label=
"指定角色"
prop=
"roleIds"
>
<el-select
v-model=
"configForm.roleIds"
clearable
multiple
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.roleIds"
clearable
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in roleOptions"
:key=
"item.id"
...
...
@@ -99,7 +99,7 @@
prop=
"postIds"
span=
"24"
>
<el-select
v-model=
"configForm.postIds"
clearable
multiple
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.postIds"
clearable
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in postOptions"
:key=
"item.id"
...
...
@@ -114,7 +114,7 @@
prop=
"userIds"
span=
"24"
>
<el-select
v-model=
"configForm.userIds"
clearable
multiple
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.userIds"
clearable
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in userOptions"
:key=
"item.id"
...
...
@@ -128,7 +128,7 @@
label=
"指定用户组"
prop=
"userGroups"
>
<el-select
v-model=
"configForm.userGroups"
clearable
multiple
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.userGroups"
clearable
multiple
style=
"width: 100%"
>
<el-option
v-for=
"item in userGroupOptions"
:key=
"item.id"
...
...
@@ -142,7 +142,7 @@
label=
"表单内用户字段"
prop=
"formUser"
>
<el-select
v-model=
"configForm.formUser"
clearable
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.formUser"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"(item, idx) in userFieldOnFormOptions"
:key=
"idx"
...
...
@@ -157,7 +157,7 @@
label=
"表单内部门字段"
prop=
"formDept"
>
<el-select
v-model=
"configForm.formDept"
clearable
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.formDept"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"(item, idx) in deptFieldOnFormOptions"
:key=
"idx"
...
...
@@ -179,7 +179,7 @@
prop=
"deptLevel"
span=
"24"
>
<el-select
v-model=
"configForm.deptLevel"
clearable
>
<el-select
filterable
v-model=
"configForm.deptLevel"
clearable
>
<el-option
v-for=
"(item, index) in MULTI_LEVEL_DEPT"
:key=
"index"
...
...
@@ -245,7 +245,7 @@
label=
"驳回节点"
prop=
"returnNodeId"
>
<el-select
v-model=
"configForm.returnNodeId"
clearable
style=
"width: 100%"
>
<el-select
filterable
v-model=
"configForm.returnNodeId"
clearable
style=
"width: 100%"
>
<el-option
v-for=
"item in returnTaskList"
:key=
"item.id"
...
...
@@ -293,6 +293,7 @@
/>
</el-form-item>
<el-select
filterable
v-model=
"timeUnit"
class=
"mr-2"
:style=
"{ width: '100px' }"
...
...
@@ -332,6 +333,7 @@
span=
"24"
>
<el-select
filterable
v-model=
"configForm.assignEmptyHandlerUserIds"
clearable
multiple
...
...
@@ -758,22 +760,22 @@ const showUserTaskNodeConfig = (node: SimpleFlowNode) => {
getNodeConfigFormFields
(
node
.
fieldsPermission
)
// 5. 监听器
// 5.1 创建任务
configForm
.
value
.
taskCreateListenerEnable
=
node
.
taskCreateListener
!
.
enable
configForm
.
value
.
taskCreateListenerPath
=
node
.
taskCreateListener
!
.
path
configForm
.
value
.
taskCreateListenerEnable
=
node
.
taskCreateListener
?
.
enable
configForm
.
value
.
taskCreateListenerPath
=
node
.
taskCreateListener
?
.
path
configForm
.
value
.
taskCreateListener
=
{
header
:
node
.
taskCreateListener
?.
header
??
[],
body
:
node
.
taskCreateListener
?.
body
??
[]
}
// 5.2 指派任务
configForm
.
value
.
taskAssignListenerEnable
=
node
.
taskAssignListener
!
.
enable
configForm
.
value
.
taskAssignListenerPath
=
node
.
taskAssignListener
!
.
path
configForm
.
value
.
taskAssignListenerEnable
=
node
.
taskAssignListener
?
.
enable
configForm
.
value
.
taskAssignListenerPath
=
node
.
taskAssignListener
?
.
path
configForm
.
value
.
taskAssignListener
=
{
header
:
node
.
taskAssignListener
?.
header
??
[],
body
:
node
.
taskAssignListener
?.
body
??
[]
}
// 5.3 完成任务
configForm
.
value
.
taskCompleteListenerEnable
=
node
.
taskCompleteListener
!
.
enable
configForm
.
value
.
taskCompleteListenerPath
=
node
.
taskCompleteListener
!
.
path
configForm
.
value
.
taskCompleteListenerEnable
=
node
.
taskCompleteListener
?
.
enable
configForm
.
value
.
taskCompleteListenerPath
=
node
.
taskCompleteListener
?
.
path
configForm
.
value
.
taskCompleteListener
=
{
header
:
node
.
taskCompleteListener
?.
header
??
[],
body
:
node
.
taskCompleteListener
?.
body
??
[]
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
View file @
c6f70cce
...
...
@@ -138,11 +138,10 @@ import {
COMPARISON_OPERATORS
,
CONDITION_CONFIG_TYPES
,
ConditionType
,
DEFAULT_CONDITION_GROUP_VALUE
,
ProcessVariableEnum
DEFAULT_CONDITION_GROUP_VALUE
}
from
'../../consts'
import
{
BpmModelFormType
}
from
'@/utils/constants'
import
{
useFormFields
}
from
'../../node'
import
{
useFormFields
AndStartUser
}
from
'../../node'
const
props
=
defineProps
({
modelValue
:
{
...
...
@@ -170,17 +169,10 @@ const conditionConfigTypes = computed(() => {
}
})
})
/** 条件规则可选择的表单字段 */
const
fieldOptions
=
computed
(()
=>
{
const
fieldsCopy
=
useFormFields
().
slice
()
// 固定添加发起人 ID 字段
fieldsCopy
.
unshift
({
field
:
ProcessVariableEnum
.
START_USER_ID
,
title
:
'发起人'
,
required
:
true
})
return
fieldsCopy
})
const
fieldOptions
=
useFormFieldsAndStartUser
()
// 表单校验规则
const
formRules
=
reactive
({
conditionType
:
[{
required
:
true
,
message
:
'配置方式不能为空'
,
trigger
:
'blur'
}],
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/components/HttpRequestParamSetting.vue
View file @
c6f70cce
...
...
@@ -16,7 +16,7 @@
<div
class=
"mr-2"
>
<el-select
class=
"w-100px!"
v-model=
"item.type"
>
<el-option
v-for=
"types in
LISTENER_MAP
_TYPES"
v-for=
"types in
BPM_HTTP_REQUEST_PARAM
_TYPES"
:key=
"types.value"
:label=
"types.label"
:value=
"types.value"
...
...
@@ -33,7 +33,7 @@
}"
>
<el-input
v-if=
"item.type ===
Listener
ParamTypeEnum.FIXED_VALUE"
v-if=
"item.type ===
BpmHttpRequest
ParamTypeEnum.FIXED_VALUE"
class=
"w-160px"
v-model=
"item.value"
/>
...
...
@@ -47,7 +47,7 @@
}"
>
<el-select
v-if=
"item.type ===
Listener
ParamTypeEnum.FROM_FORM"
v-if=
"item.type ===
BpmHttpRequest
ParamTypeEnum.FROM_FORM"
class=
"w-160px!"
v-model=
"item.value"
>
...
...
@@ -86,7 +86,7 @@
<div
class=
"mr-2"
>
<el-select
class=
"w-100px!"
v-model=
"item.type"
>
<el-option
v-for=
"types in
LISTENER_MAP
_TYPES"
v-for=
"types in
BPM_HTTP_REQUEST_PARAM
_TYPES"
:key=
"types.value"
:label=
"types.label"
:value=
"types.value"
...
...
@@ -103,7 +103,7 @@
}"
>
<el-input
v-if=
"item.type ===
Listener
ParamTypeEnum.FIXED_VALUE"
v-if=
"item.type ===
BpmHttpRequest
ParamTypeEnum.FIXED_VALUE"
class=
"w-160px"
v-model=
"item.value"
/>
...
...
@@ -117,7 +117,7 @@
}"
>
<el-select
v-if=
"item.type ===
Listener
ParamTypeEnum.FROM_FORM"
v-if=
"item.type ===
BpmHttpRequest
ParamTypeEnum.FROM_FORM"
class=
"w-160px!"
v-model=
"item.value"
>
...
...
@@ -141,20 +141,20 @@
</el-form-item>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
ListenerParam
,
LISTENER_MAP_TYPES
,
Listener
ParamTypeEnum
}
from
'../../consts'
import
{
useFormFields
}
from
'../../node'
import
{
HttpRequestParam
,
BPM_HTTP_REQUEST_PARAM_TYPES
,
BpmHttpRequest
ParamTypeEnum
}
from
'../../consts'
import
{
useFormFields
AndStartUser
}
from
'../../node'
defineOptions
({
name
:
'HttpRequestParamSetting'
})
const
props
=
defineProps
({
header
:
{
type
:
Array
as
()
=>
Listener
Param
[],
type
:
Array
as
()
=>
HttpRequest
Param
[],
required
:
false
,
default
:
()
=>
[]
},
body
:
{
type
:
Array
as
()
=>
Listener
Param
[],
type
:
Array
as
()
=>
HttpRequest
Param
[],
required
:
false
,
default
:
()
=>
[]
},
...
...
@@ -164,16 +164,19 @@ const props = defineProps({
}
})
const
formFieldOptions
=
useFormFields
()
const
addHttpRequestParam
=
(
arr
:
ListenerParam
[])
=>
{
// 流程表单字段,发起人字段
const
formFieldOptions
=
useFormFieldsAndStartUser
()
/** 添加请求配置项 */
const
addHttpRequestParam
=
(
arr
:
HttpRequestParam
[])
=>
{
arr
.
push
({
key
:
''
,
type
:
Listener
ParamTypeEnum
.
FIXED_VALUE
,
type
:
BpmHttpRequest
ParamTypeEnum
.
FIXED_VALUE
,
value
:
''
})
}
const
deleteHttpRequestParam
=
(
arr
:
ListenerParam
[],
index
:
number
)
=>
{
/** 删除请求配置项 */
const
deleteHttpRequestParam
=
(
arr
:
HttpRequestParam
[],
index
:
number
)
=>
{
arr
.
splice
(
index
,
1
)
}
</
script
>
...
...
src/router/modules/remaining.ts
View file @
c6f70cce
...
...
@@ -308,6 +308,18 @@ const remainingRouter: AppRouteRecordRaw[] = [
})
},
{
path
:
'process-instance/report'
,
component
:
()
=>
import
(
'@/views/bpm/processInstance/report/index.vue'
),
name
:
'BpmProcessInstanceReport'
,
meta
:
{
noCache
:
true
,
hidden
:
true
,
canTo
:
true
,
title
:
'数据报表'
,
activeMenu
:
'/bpm/manager/model'
}
},
{
path
:
'oa/leave/create'
,
component
:
()
=>
import
(
'@/views/bpm/oa/leave/create.vue'
),
name
:
'OALeaveCreate'
,
...
...
src/views/bpm/category/CategoryForm.vue
View file @
c6f70cce
...
...
@@ -13,6 +13,9 @@
<el-form-item
label=
"分类标志"
prop=
"code"
>
<el-input
v-model=
"formData.code"
placeholder=
"请输入分类标志"
/>
</el-form-item>
<el-form-item
label=
"分类描述"
prop=
"description"
>
<el-input
v-model=
"formData.description"
type=
"textarea"
placeholder=
"请输入分类描述"
/>
</el-form-item>
<el-form-item
label=
"分类状态"
prop=
"status"
>
<el-radio-group
v-model=
"formData.status"
>
<el-radio
...
...
@@ -58,6 +61,7 @@ const formData = ref({
id
:
undefined
,
name
:
undefined
,
code
:
undefined
,
description
:
undefined
,
status
:
CommonStatusEnum
.
ENABLE
,
sort
:
undefined
})
...
...
@@ -117,6 +121,7 @@ const resetForm = () => {
id
:
undefined
,
name
:
undefined
,
code
:
undefined
,
description
:
undefined
,
status
:
CommonStatusEnum
.
ENABLE
,
sort
:
undefined
}
...
...
src/views/bpm/model/CategoryDraggableModel.vue
View file @
c6f70cce
...
...
@@ -193,6 +193,16 @@
历史
</el-dropdown-item>
<el-dropdown-item
command=
"handleReport"
v-if=
"
checkPermi(['bpm:process-instance:manager-query']) &&
scope.row.processDefinition
"
:disabled=
"!isManagerUser(scope.row)"
>
报表
</el-dropdown-item>
<el-dropdown-item
command=
"handleChangeState"
v-if=
"hasPermiUpdate && scope.row.processDefinition"
:disabled=
"!isManagerUser(scope.row)"
...
...
@@ -301,6 +311,7 @@ const { t } = useI18n() // 国际化
const
{
push
}
=
useRouter
()
// 路由
const
userStore
=
useUserStoreWithOut
()
// 用户信息缓存
const
isDark
=
computed
(()
=>
useAppStore
().
getIsDark
)
// 是否黑暗模式
const
router
=
useRouter
()
// 路由
const
isModelSorting
=
ref
(
false
)
// 是否正处于排序状态
const
originalData
=
ref
<
ModelInfo
[]
>
([])
// 原始数据
...
...
@@ -349,6 +360,15 @@ const handleModelCommand = (command: string, row: any) => {
case
'handleClean'
:
handleClean
(
row
)
break
case
'handleReport'
:
router
.
push
({
name
:
'BpmProcessInstanceReport'
,
query
:
{
processDefinitionId
:
row
.
processDefinition
.
id
,
processDefinitionKey
:
row
.
key
}
})
break
default
:
break
}
...
...
src/views/bpm/model/form/ExtraSettings.vue
View file @
c6f70cce
...
...
@@ -216,16 +216,16 @@ const formFieldOptions4Title = computed(() => {
})
// 固定添加发起人 ID 字段
cloneFormField
.
unshift
({
label
:
ProcessVariableEnum
.
PROCESS_DEFINITION_NAME
,
value
:
'流程名称'
label
:
'流程名称'
,
value
:
ProcessVariableEnum
.
PROCESS_DEFINITION_NAME
})
cloneFormField
.
unshift
({
label
:
ProcessVariableEnum
.
START_TIME
,
value
:
'发起时间'
label
:
'发起时间'
,
value
:
ProcessVariableEnum
.
START_TIME
})
cloneFormField
.
unshift
({
label
:
ProcessVariableEnum
.
START_USER_ID
,
value
:
'发起人'
label
:
'发起人'
,
value
:
ProcessVariableEnum
.
START_USER_ID
})
return
cloneFormField
})
...
...
src/views/bpm/processInstance/detail/ProcessInstanceSimpleViewer.vue
View file @
c6f70cce
...
...
@@ -114,6 +114,16 @@ const setSimpleModelNodeTaskStatus = (
simpleModel
.
activityStatus
=
TaskStatusEnum
.
NOT_START
}
}
// 触发器节点
if
(
simpleModel
.
type
===
NodeType
.
TRIGGER_NODE
)
{
// 触发器节点,只有通过和未执行状态
if
(
finishedActivityIds
.
includes
(
simpleModel
.
id
))
{
simpleModel
.
activityStatus
=
TaskStatusEnum
.
APPROVE
}
else
{
simpleModel
.
activityStatus
=
TaskStatusEnum
.
NOT_START
}
}
// 条件节点对应 SequenceFlow
if
(
simpleModel
.
type
===
NodeType
.
CONDITION_NODE
)
{
// 条件节点,只有通过和未执行状态
...
...
src/views/bpm/processInstance/report/index.vue
0 → 100644
View file @
c6f70cce
<
template
>
<doc-alert
title=
"工作流手册"
url=
"https://doc.iocoder.cn/bpm/"
/>
<ContentWrap>
<!-- 搜索工作栏 -->
<el-form
class=
"-mb-15px"
:model=
"queryParams"
ref=
"queryFormRef"
:inline=
"true"
label-width=
"68px"
>
<el-form-item
label=
"发起人"
prop=
"startUserId"
>
<el-select
v-model=
"queryParams.startUserId"
placeholder=
"请选择发起人"
class=
"!w-240px"
>
<el-option
v-for=
"user in userList"
:key=
"user.id"
:label=
"user.nickname"
:value=
"user.id"
/>
</el-select>
</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=
"status"
>
<el-select
v-model=
"queryParams.status"
placeholder=
"请选择流程状态"
clearable
class=
"!w-240px"
>
<el-option
v-for=
"dict in getIntDictOptions(DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS)"
:key=
"dict.value"
:label=
"dict.label"
:value=
"dict.value"
/>
</el-select>
</el-form-item>
<el-form-item
label=
"发起时间"
prop=
"createTime"
>
<el-date-picker
v-model=
"queryParams.createTime"
value-format=
"YYYY-MM-DD HH:mm:ss"
type=
"daterange"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
label=
"结束时间"
prop=
"endTime"
>
<el-date-picker
v-model=
"queryParams.endTime"
value-format=
"YYYY-MM-DD HH:mm:ss"
type=
"daterange"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
:default-time=
"[new Date('1 00:00:00'), new Date('1 23:59:59')]"
class=
"!w-240px"
/>
</el-form-item>
<el-form-item
v-for=
"(item, index) in formFields"
:key=
"index"
:label=
"item.title"
:prop=
"item.field"
>
<!-- TODO @lesan:目前只支持input类型的字符串搜索 -->
<el-input
:disabled=
"item.type !== 'input'"
v-model=
"queryParams.formFieldsParams[item.field]"
:placeholder=
"`请输入$
{item.title}`"
clearable
@keyup.enter="handleQuery"
class="!w-240px"
/>
</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-form-item>
</el-form>
</ContentWrap>
<!-- 列表 -->
<ContentWrap>
<el-table
v-loading=
"loading"
border
:data=
"list"
>
<el-table-column
label=
"流程名称"
align=
"center"
prop=
"name"
fixed=
"left"
width=
"200"
/>
<el-table-column
label=
"流程发起人"
align=
"center"
prop=
"startUser.nickname"
width=
"120"
/>
<el-table-column
label=
"流程状态"
prop=
"status"
width=
"120"
>
<template
#
default=
"scope"
>
<dict-tag
:type=
"DICT_TYPE.BPM_PROCESS_INSTANCE_STATUS"
:value=
"scope.row.status"
/>
</
template
>
</el-table-column>
<el-table-column
label=
"发起时间"
align=
"center"
prop=
"startTime"
width=
"180"
:formatter=
"dateFormatter"
/>
<el-table-column
label=
"结束时间"
align=
"center"
prop=
"endTime"
width=
"180"
:formatter=
"dateFormatter"
/>
<el-table-column
v-for=
"(item, index) in formFields"
:key=
"index"
:label=
"item.title"
:prop=
"item.field"
width=
"120"
>
<!-- TODO @lesan:可以根据formField的type进行展示方式的控制,现在全部以字符串 -->
<
template
#
default=
"scope"
>
{{
scope
.
row
.
formVariables
[
item
.
field
]
??
''
}}
</
template
>
</el-table-column>
<el-table-column
label=
"操作"
align=
"center"
fixed=
"right"
width=
"180"
>
<
template
#
default=
"scope"
>
<el-button
link
type=
"primary"
v-hasPermi=
"['bpm:process-instance:cancel']"
@
click=
"handleDetail(scope.row)"
>
详情
</el-button>
<el-button
link
type=
"primary"
v-if=
"scope.row.status === 1"
v-hasPermi=
"['bpm:process-instance:query']"
@
click=
"handleCancel(scope.row)"
>
取消
</el-button>
</
template
>
</el-table-column>
</el-table>
<!-- 分页 -->
<Pagination
:total=
"total"
v-model:page=
"queryParams.pageNo"
v-model:limit=
"queryParams.pageSize"
@
pagination=
"getList"
/>
</ContentWrap>
</template>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
dateFormatter
}
from
'@/utils/formatTime'
import
*
as
ProcessInstanceApi
from
'@/api/bpm/processInstance'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
DefinitionApi
from
'@/api/bpm/definition'
import
{
parseFormFields
}
from
'@/components/FormCreate/src/utils'
import
{
ElMessageBox
}
from
'element-plus'
defineOptions
({
name
:
'BpmProcessInstanceReport'
})
const
router
=
useRouter
()
// 路由
const
{
query
}
=
useRoute
()
const
message
=
useMessage
()
// 消息弹窗
const
{
t
}
=
useI18n
()
// 国际化
const
loading
=
ref
(
true
)
// 列表的加载中
const
total
=
ref
(
0
)
// 列表的总页数
const
list
=
ref
([])
// 列表的数据
const
formFields
=
ref
()
const
processDefinitionId
=
query
.
processDefinitionId
as
string
const
queryParams
=
reactive
({
pageNo
:
1
,
pageSize
:
10
,
startUserId
:
undefined
,
name
:
''
,
processDefinitionKey
:
query
.
processDefinitionKey
,
status
:
undefined
,
createTime
:
[],
endTime
:
[],
formFieldsParams
:
{}
})
const
queryFormRef
=
ref
()
// 搜索的表单
const
userList
=
ref
<
any
[]
>
([])
// 用户列表
/** 查询列表 */
const
getList
=
async
()
=>
{
loading
.
value
=
true
try
{
const
data
=
await
ProcessInstanceApi
.
getProcessInstanceManagerPage
({
...
queryParams
,
formFieldsParams
:
JSON
.
stringify
(
queryParams
.
formFieldsParams
)
})
list
.
value
=
data
.
list
total
.
value
=
data
.
total
}
finally
{
loading
.
value
=
false
}
}
/** 获取流程定义 */
const
getProcessDefinition
=
async
()
=>
{
const
processDefinition
=
await
DefinitionApi
.
getProcessDefinition
(
processDefinitionId
)
formFields
.
value
=
parseFormCreateFields
(
processDefinition
.
formFields
)
}
/** 解析表单字段 */
const
parseFormCreateFields
=
(
formFields
?:
string
[])
=>
{
const
result
:
Array
<
Record
<
string
,
any
>>
=
[]
if
(
formFields
)
{
formFields
.
forEach
((
fieldStr
:
string
)
=>
{
parseFormFields
(
JSON
.
parse
(
fieldStr
),
result
)
})
}
return
result
}
/** 搜索按钮操作 */
const
handleQuery
=
()
=>
{
queryParams
.
pageNo
=
1
getList
()
}
/** 重置按钮操作 */
const
resetQuery
=
()
=>
{
queryFormRef
.
value
.
resetFields
()
queryParams
.
formFieldsParams
=
{}
handleQuery
()
}
/** 查看详情 */
const
handleDetail
=
(
row
)
=>
{
router
.
push
({
name
:
'BpmProcessInstanceDetail'
,
query
:
{
id
:
row
.
id
}
})
}
/** 取消按钮操作 */
const
handleCancel
=
async
(
row
)
=>
{
// 二次确认
const
{
value
}
=
await
ElMessageBox
.
prompt
(
'请输入取消原因'
,
'取消流程'
,
{
confirmButtonText
:
t
(
'common.ok'
),
cancelButtonText
:
t
(
'common.cancel'
),
inputPattern
:
/^
[\s\S]
*.*
\S[\s\S]
*$/
,
// 判断非空,且非空格
inputErrorMessage
:
'取消原因不能为空'
})
// 发起取消
await
ProcessInstanceApi
.
cancelProcessInstanceByAdmin
(
row
.
id
,
value
)
message
.
success
(
'取消成功'
)
// 刷新列表
await
getList
()
}
/** 初始化 **/
onMounted
(
async
()
=>
{
// 获取流程定义,用于 table column 的展示
await
getProcessDefinition
()
// 获取流程列表
await
getList
()
// 获取用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
})
</
script
>
src/views/bpm/task/copy/index.vue
View file @
c6f70cce
...
...
@@ -46,6 +46,15 @@
<el-table
v-loading=
"loading"
:data=
"list"
>
<!-- TODO 芋艿:增加摘要 -->
<el-table-column
align=
"center"
label=
"流程名"
prop=
"processInstanceName"
min-width=
"180"
/>
<el-table-column
label=
"摘要"
prop=
"summary"
min-width=
"180"
>
<template
#
default=
"scope"
>
<div
class=
"flex flex-col"
v-if=
"scope.row.summary && scope.row.summary.length > 0"
>
<div
v-for=
"(item, index) in scope.row.summary"
:key=
"index"
>
<el-text
type=
"info"
>
{{
item
.
key
}}
:
{{
item
.
value
}}
</el-text>
</div>
</div>
</
template
>
</el-table-column>
<el-table-column
align=
"center"
label=
"流程发起人"
...
...
src/views/bpm/task/done/index.vue
View file @
c6f70cce
...
...
@@ -122,10 +122,10 @@
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
align=
"center"
label=
"流程"
prop=
"processInstance.name"
width=
"180"
/>
<el-table-column
label=
"摘要"
prop=
"summary"
min-width=
"180"
>
<el-table-column
label=
"摘要"
prop=
"
processInstance.
summary"
min-width=
"180"
>
<
template
#
default=
"scope"
>
<div
class=
"flex flex-col"
v-if=
"scope.row.
summary && scope.row
.summary.length > 0"
>
<div
v-for=
"(item, index) in scope.row.summary"
:key=
"index"
>
<div
class=
"flex flex-col"
v-if=
"scope.row.
processInstance.summary && scope.row.processInstance
.summary.length > 0"
>
<div
v-for=
"(item, index) in scope.row.
processInstance.
summary"
:key=
"index"
>
<el-text
type=
"info"
>
{{
item
.
key
}}
:
{{
item
.
value
}}
</el-text>
</div>
</div>
...
...
src/views/bpm/task/todo/index.vue
View file @
c6f70cce
...
...
@@ -105,10 +105,10 @@
<ContentWrap>
<el-table
v-loading=
"loading"
:data=
"list"
>
<el-table-column
align=
"center"
label=
"流程"
prop=
"processInstance.name"
width=
"180"
/>
<el-table-column
label=
"摘要"
prop=
"summary"
min-width=
"180"
>
<el-table-column
label=
"摘要"
prop=
"
processInstance.
summary"
min-width=
"180"
>
<
template
#
default=
"scope"
>
<div
class=
"flex flex-col"
v-if=
"scope.row.
summary && scope.row
.summary.length > 0"
>
<div
v-for=
"(item, index) in scope.row.summary"
:key=
"index"
>
<div
class=
"flex flex-col"
v-if=
"scope.row.
processInstance.summary && scope.row.processInstance
.summary.length > 0"
>
<div
v-for=
"(item, index) in scope.row.
processInstance.
summary"
:key=
"index"
>
<el-text
type=
"info"
>
{{
item
.
key
}}
:
{{
item
.
value
}}
</el-text>
</div>
</div>
...
...
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