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
16a98e5a
authored
Mar 30, 2025
by
YunaiV
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'feature/bpm' of
https://gitee.com/yudaocode/yudao-ui-admin-vue3
parents
8d9d9e76
e75dbd67
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
422 additions
and
41 deletions
+422
-41
src/components/DeptSelectForm/index.vue
+122
-0
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
+3
-2
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+6
-0
src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue
+57
-14
src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue
+6
-5
src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
+2
-1
src/components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue
+4
-3
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
+11
-3
src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue
+11
-3
src/views/bpm/model/CategoryDraggableModel.vue
+14
-1
src/views/bpm/model/form/BasicInfo.vue
+73
-1
src/views/bpm/model/form/ExtraSettings.vue
+81
-5
src/views/bpm/model/form/ProcessDesign.vue
+1
-0
src/views/bpm/model/form/index.vue
+12
-3
src/views/bpm/oa/leave/create.vue
+0
-0
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
+17
-0
src/views/bpm/simple/SimpleModelDesign.vue
+2
-0
No files found.
src/components/DeptSelectForm/index.vue
0 → 100644
View file @
16a98e5a
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"部门选择"
width=
"600"
>
<el-row
v-loading=
"formLoading"
>
<el-col
:span=
"24"
>
<ContentWrap
class=
"h-1/1"
>
<el-tree
ref=
"treeRef"
:data=
"deptTree"
:props=
"defaultProps"
show-checkbox
:check-strictly=
"checkStrictly"
check-on-click-node
default-expand-all
highlight-current
node-key=
"id"
@
check=
"handleCheck"
/>
</ContentWrap>
</el-col>
</el-row>
<template
#
footer
>
<el-button
:disabled=
"formLoading || !selectedDeptIds?.length"
type=
"primary"
@
click=
"submitForm"
>
确 定
</el-button>
<el-button
@
click=
"dialogVisible = false"
>
取 消
</el-button>
</
template
>
</Dialog>
</template>
<
script
lang=
"ts"
setup
>
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
import
*
as
DeptApi
from
'@/api/system/dept'
defineOptions
({
name
:
'DeptSelectForm'
})
const
emit
=
defineEmits
<
{
confirm
:
[
deptList
:
any
[]]
}
>
()
const
{
t
}
=
useI18n
()
// 国际化
const
message
=
useMessage
()
// 消息弹窗
const
props
=
defineProps
({
// 是否严格的遵循父子不互相关联
checkStrictly
:
{
type
:
Boolean
,
default
:
false
},
// 是否支持多选
multiple
:
{
type
:
Boolean
,
default
:
true
}
})
const
treeRef
=
ref
()
const
deptTree
=
ref
<
Tree
[]
>
([])
// 部门树形结构
const
selectedDeptIds
=
ref
<
number
[]
>
([])
// 选中的部门 ID 列表
const
dialogVisible
=
ref
(
false
)
// 弹窗的是否展示
const
formLoading
=
ref
(
false
)
// 表单的加载中
/** 打开弹窗 */
const
open
=
async
(
selectedList
?:
DeptApi
.
DeptVO
[])
=>
{
resetForm
()
formLoading
.
value
=
true
try
{
// 加载部门列表
const
deptData
=
await
DeptApi
.
getSimpleDeptList
()
deptTree
.
value
=
handleTree
(
deptData
)
}
finally
{
formLoading
.
value
=
false
}
dialogVisible
.
value
=
true
// 设置已选择的部门
if
(
selectedList
?.
length
)
{
await
nextTick
()
const
selectedIds
=
selectedList
.
map
((
dept
)
=>
dept
.
id
)
.
filter
((
id
):
id
is
number
=>
id
!==
undefined
)
selectedDeptIds
.
value
=
selectedIds
treeRef
.
value
?.
setCheckedKeys
(
selectedIds
)
}
}
/** 处理选中状态变化 */
const
handleCheck
=
(
data
:
any
,
checked
:
any
)
=>
{
selectedDeptIds
.
value
=
treeRef
.
value
.
getCheckedKeys
()
if
(
!
props
.
multiple
&&
selectedDeptIds
.
value
.
length
>
1
)
{
// 单选模式下,只保留最后选择的节点
const
lastSelectedId
=
selectedDeptIds
.
value
[
selectedDeptIds
.
value
.
length
-
1
]
selectedDeptIds
.
value
=
[
lastSelectedId
]
treeRef
.
value
.
setCheckedKeys
([
lastSelectedId
])
}
}
/** 提交选择 */
const
submitForm
=
async
()
=>
{
try
{
// 获取选中的完整部门数据
const
checkedNodes
=
treeRef
.
value
.
getCheckedNodes
()
message
.
success
(
t
(
'common.updateSuccess'
))
dialogVisible
.
value
=
false
emit
(
'confirm'
,
checkedNodes
)
}
finally
{
}
}
/** 重置表单 */
const
resetForm
=
()
=>
{
deptTree
.
value
=
[]
selectedDeptIds
.
value
=
[]
if
(
treeRef
.
value
)
{
treeRef
.
value
.
setCheckedKeys
([])
}
}
defineExpose
({
open
})
// 提供 open 方法,用于打开弹窗
</
script
>
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
View file @
16a98e5a
...
...
@@ -91,6 +91,7 @@ import {
DEFAULT_CONDITION_GROUP_VALUE
}
from
'./consts'
import
{
generateUUID
}
from
'@/utils'
import
{
cloneDeep
}
from
'lodash-es'
defineOptions
({
name
:
'NodeHandler'
...
...
@@ -184,7 +185,7 @@ const addNode = (type: number) => {
conditionSetting
:
{
defaultFlow
:
false
,
conditionType
:
ConditionType
.
RULE
,
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
},
{
...
...
@@ -242,7 +243,7 @@ const addNode = (type: number) => {
conditionSetting
:
{
defaultFlow
:
false
,
conditionType
:
ConditionType
.
RULE
,
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
},
{
...
...
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
16a98e5a
...
...
@@ -59,6 +59,11 @@ const props = defineProps({
startUserIds
:
{
type
:
Array
,
required
:
false
},
// 可发起流程的部门编号
startDeptIds
:
{
type
:
Array
,
required
:
false
}
})
...
...
@@ -82,6 +87,7 @@ provide('deptList', deptOptions)
provide
(
'userGroupList'
,
userGroupOptions
)
provide
(
'deptTree'
,
deptTreeOptions
)
provide
(
'startUserIds'
,
props
.
startUserIds
)
provide
(
'startDeptIds'
,
props
.
startDeptIds
)
provide
(
'tasks'
,
[])
provide
(
'processInstance'
,
{})
const
message
=
useMessage
()
// 国际化
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue
View file @
16a98e5a
...
...
@@ -25,21 +25,46 @@
</
template
>
<el-tabs
type=
"border-card"
v-model=
"activeTabName"
>
<el-tab-pane
label=
"权限"
name=
"user"
>
<el-text
v-if=
"!startUserIds || startUserIds.length === 0"
>
全部成员可以发起流程
</el-text>
<el-text
v-else-if=
"startUserIds.length == 1"
>
{{ getUserNicknames(startUserIds) }} 可发起流程
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"getUserNicknames(startUserIds)"
>
{{ getUserNicknames(startUserIds.slice(0, 2)) }} 等
{{ startUserIds.length }} 人可发起流程
</el-tooltip>
<el-text
v-if=
"
(!startUserIds || startUserIds.length === 0) &&
(!startDeptIds || startDeptIds.length === 0)
"
>
全部成员可以发起流程
</el-text>
<div
v-else-if=
"startUserIds && startUserIds.length > 0"
>
<el-text
v-if=
"startUserIds.length == 1"
>
{{ getUserNicknames(startUserIds) }} 可发起流程
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"getUserNicknames(startUserIds)"
>
{{ getUserNicknames(startUserIds.slice(0, 2)) }} 等
{{ startUserIds.length }} 人可发起流程
</el-tooltip>
</el-text>
</div>
<div
v-else-if=
"startDeptIds && startDeptIds.length > 0"
>
<el-text
v-if=
"startDeptIds.length == 1"
>
{{ getDeptNames(startDeptIds) }} 可发起流程
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"getDeptNames(startDeptIds)"
>
{{ getDeptNames(startDeptIds.slice(0, 2)) }} 等
{{ startDeptIds.length }} 个部门可发起流程
</el-tooltip>
</el-text>
</div>
</el-tab-pane>
<el-tab-pane
label=
"表单字段权限"
name=
"fields"
v-if=
"formType === 10"
>
<div
class=
"field-setting-pane"
>
...
...
@@ -107,6 +132,7 @@
import
{
SimpleFlowNode
,
NodeType
,
FieldPermissionType
,
START_USER_BUTTON_SETTING
}
from
'../consts'
import
{
useWatchNode
,
useDrawer
,
useNodeName
,
useFormFieldsPermission
}
from
'../node'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
DeptApi
from
'@/api/system/dept'
defineOptions
({
name
:
'StartUserNodeConfig'
})
...
...
@@ -118,8 +144,12 @@ const props = defineProps({
})
// 可发起流程的用户编号
const
startUserIds
=
inject
<
Ref
<
any
[]
>>
(
'startUserIds'
)
// 可发起流程的部门编号
const
startDeptIds
=
inject
<
Ref
<
any
[]
>>
(
'startDeptIds'
)
// 用户列表
const
userOptions
=
inject
<
Ref
<
UserApi
.
UserVO
[]
>>
(
'userList'
)
// 部门列表
const
deptOptions
=
inject
<
Ref
<
DeptApi
.
DeptVO
[]
>>
(
'deptList'
)
// 抽屉配置
const
{
settingVisible
,
closeDrawer
,
openDrawer
}
=
useDrawer
()
// 当前节点
...
...
@@ -145,6 +175,19 @@ const getUserNicknames = (userIds: number[]): string => {
})
return
nicknames
.
join
(
','
)
}
const
getDeptNames
=
(
deptIds
:
number
[]):
string
=>
{
if
(
!
deptIds
||
deptIds
.
length
===
0
)
{
return
''
}
const
deptNames
:
string
[]
=
[]
deptIds
.
forEach
((
deptId
)
=>
{
const
found
=
deptOptions
?.
value
.
find
((
item
)
=>
item
.
id
===
deptId
)
if
(
found
&&
found
.
name
)
{
deptNames
.
push
(
found
.
name
)
}
})
return
deptNames
.
join
(
','
)
}
// 保存配置
const
saveConfig
=
async
()
=>
{
activeTabName
.
value
=
'user'
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/TriggerNodeConfig.vue
View file @
16a98e5a
...
...
@@ -254,6 +254,7 @@ import {
import
{
useWatchNode
,
useDrawer
,
useNodeName
,
useFormFields
,
getConditionShowText
}
from
'../node'
import
HttpRequestSetting
from
'./components/HttpRequestSetting.vue'
import
ConditionDialog
from
'./components/ConditionDialog.vue'
import
{
cloneDeep
}
from
'lodash-es'
const
{
proxy
}
=
getCurrentInstance
()
as
any
defineOptions
({
...
...
@@ -290,7 +291,7 @@ const configForm = ref<TriggerSetting>({
},
formSettings
:
[
{
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
,
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
,
updateFormFields
:
{},
deleteFields
:
[]
}
...
...
@@ -346,7 +347,7 @@ const changeTriggerType = () => {
?
originalSetting
.
formSettings
:
[
{
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
,
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
,
updateFormFields
:
{},
deleteFields
:
[]
}
...
...
@@ -361,7 +362,7 @@ const changeTriggerType = () => {
?
originalSetting
.
formSettings
:
[
{
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
,
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
,
updateFormFields
:
undefined
,
deleteFields
:
[]
}
...
...
@@ -374,7 +375,7 @@ const changeTriggerType = () => {
/** 添加新的修改表单设置 */
const
addFormSetting
=
()
=>
{
configForm
.
value
.
formSettings
!
.
push
({
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
,
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
,
updateFormFields
:
{},
deleteFields
:
[]
})
...
...
@@ -509,7 +510,7 @@ const showTriggerNodeConfig = (node: SimpleFlowNode) => {
},
formSettings: node.triggerSetting.formSettings || [
{
conditionGroups:
DEFAULT_CONDITION_GROUP_VALUE
,
conditionGroups:
cloneDeep(DEFAULT_CONDITION_GROUP_VALUE)
,
updateFormFields: {},
deleteFields: []
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/components/Condition.vue
View file @
16a98e5a
...
...
@@ -154,6 +154,7 @@ import {
}
from
'../../consts'
import
{
BpmModelFormType
}
from
'@/utils/constants'
import
{
useFormFieldsAndStartUser
}
from
'../../node'
import
{
cloneDeep
}
from
'lodash-es'
const
props
=
defineProps
({
modelValue
:
{
...
...
@@ -196,7 +197,7 @@ const formRef = ref() // 表单 Ref
const
changeConditionType
=
()
=>
{
if
(
condition
.
value
.
conditionType
===
ConditionType
.
RULE
)
{
if
(
!
condition
.
value
.
conditionGroups
)
{
condition
.
value
.
conditionGroups
=
DEFAULT_CONDITION_GROUP_VALUE
condition
.
value
.
conditionGroups
=
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
}
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes-config/components/ConditionDialog.vue
View file @
16a98e5a
<!-- TODO @jason:有可能,它里面套 Condition 么? -->
<!-- TODO 怕影响其它节点功能,后面看看如何如何复用 Condtion -->
<!-- TODO 怕影响其它节点功能,后面看看如何如何复用 Condtion -->
<
template
>
<Dialog
v-model=
"dialogVisible"
title=
"条件配置"
width=
"600px"
:fullscreen=
"false"
>
<div
class=
"h-410px"
>
...
...
@@ -165,6 +165,7 @@ import {
}
from
'../../consts'
import
{
BpmModelFormType
}
from
'@/utils/constants'
import
{
useFormFieldsAndStartUser
}
from
'../../node'
import
{
cloneDeep
}
from
'lodash-es'
defineOptions
({
name
:
'ConditionDialog'
})
...
...
@@ -175,7 +176,7 @@ const condition = ref<{
conditionGroups
?:
ConditionGroup
}
>
({
conditionType
:
ConditionType
.
RULE
,
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
})
const
emit
=
defineEmits
<
{
...
...
@@ -210,7 +211,7 @@ const formRef = ref() // 表单 Ref
const
changeConditionType
=
()
=>
{
if
(
condition
.
value
.
conditionType
===
ConditionType
.
RULE
)
{
if
(
!
condition
.
value
.
conditionGroups
)
{
condition
.
value
.
conditionGroups
=
DEFAULT_CONDITION_GROUP_VALUE
condition
.
value
.
conditionGroups
=
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
}
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
View file @
16a98e5a
...
...
@@ -108,11 +108,18 @@
<
script
setup
lang=
"ts"
>
import
NodeHandler
from
'../NodeHandler.vue'
import
ProcessNodeTree
from
'../ProcessNodeTree.vue'
import
{
SimpleFlowNode
,
NodeType
,
ConditionType
,
DEFAULT_CONDITION_GROUP_VALUE
,
NODE_DEFAULT_TEXT
}
from
'../consts'
import
{
SimpleFlowNode
,
NodeType
,
ConditionType
,
DEFAULT_CONDITION_GROUP_VALUE
,
NODE_DEFAULT_TEXT
}
from
'../consts'
import
{
getDefaultConditionNodeName
}
from
'../utils'
import
{
useTaskStatusClass
}
from
'../node'
import
{
generateUUID
}
from
'@/utils'
import
ConditionNodeConfig
from
'../nodes-config/ConditionNodeConfig.vue'
import
{
cloneDeep
}
from
'lodash-es'
const
{
proxy
}
=
getCurrentInstance
()
as
any
defineOptions
({
name
:
'ExclusiveNode'
...
...
@@ -149,7 +156,8 @@ const blurEvent = (index: number) => {
showInputs
.
value
[
index
]
=
false
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
conditionNode
.
name
=
conditionNode
.
name
||
getDefaultConditionNodeName
(
index
,
conditionNode
.
conditionSetting
?.
defaultFlow
)
conditionNode
.
name
||
getDefaultConditionNodeName
(
index
,
conditionNode
.
conditionSetting
?.
defaultFlow
)
}
// 点击条件名称
...
...
@@ -181,7 +189,7 @@ const addCondition = () => {
conditionSetting
:
{
defaultFlow
:
false
,
conditionType
:
ConditionType
.
RULE
,
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
}
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
...
...
src/components/SimpleProcessDesignerV2/src/nodes/InclusiveNode.vue
View file @
16a98e5a
...
...
@@ -110,11 +110,18 @@
<
script
setup
lang=
"ts"
>
import
NodeHandler
from
'../NodeHandler.vue'
import
ProcessNodeTree
from
'../ProcessNodeTree.vue'
import
{
SimpleFlowNode
,
NodeType
,
ConditionType
,
DEFAULT_CONDITION_GROUP_VALUE
,
NODE_DEFAULT_TEXT
}
from
'../consts'
import
{
SimpleFlowNode
,
NodeType
,
ConditionType
,
DEFAULT_CONDITION_GROUP_VALUE
,
NODE_DEFAULT_TEXT
}
from
'../consts'
import
{
useTaskStatusClass
}
from
'../node'
import
{
getDefaultInclusiveConditionNodeName
}
from
'../utils'
import
{
generateUUID
}
from
'@/utils'
import
ConditionNodeConfig
from
'../nodes-config/ConditionNodeConfig.vue'
import
{
cloneDeep
}
from
'lodash-es'
const
{
proxy
}
=
getCurrentInstance
()
as
any
defineOptions
({
name
:
'InclusiveNode'
...
...
@@ -153,7 +160,8 @@ const blurEvent = (index: number) => {
showInputs
.
value
[
index
]
=
false
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
conditionNode
.
name
=
conditionNode
.
name
||
getDefaultInclusiveConditionNodeName
(
index
,
conditionNode
.
conditionSetting
?.
defaultFlow
)
conditionNode
.
name
||
getDefaultInclusiveConditionNodeName
(
index
,
conditionNode
.
conditionSetting
?.
defaultFlow
)
}
// 点击条件名称
...
...
@@ -185,7 +193,7 @@ const addCondition = () => {
conditionSetting
:
{
defaultFlow
:
false
,
conditionType
:
ConditionType
.
RULE
,
conditionGroups
:
DEFAULT_CONDITION_GROUP_VALUE
conditionGroups
:
cloneDeep
(
DEFAULT_CONDITION_GROUP_VALUE
)
}
}
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
...
...
src/views/bpm/model/CategoryDraggableModel.vue
View file @
16a98e5a
...
...
@@ -97,10 +97,23 @@
</el-table-column>
<el-table-column
label=
"可见范围"
prop=
"startUserIds"
min-width=
"150"
>
<
template
#
default=
"{ row }"
>
<el-text
v-if=
"!row.startUsers?.length"
>
全部可见
</el-text>
<el-text
v-if=
"!row.startUsers?.length
&& !row.startDepts?.length
"
>
全部可见
</el-text>
<el-text
v-else-if=
"row.startUsers.length === 1"
>
{{
row
.
startUsers
[
0
].
nickname
}}
</el-text>
<el-text
v-else-if=
"row.startDepts?.length === 1"
>
{{
row
.
startDepts
[
0
].
name
}}
</el-text>
<el-text
v-else-if=
"row.startDepts?.length > 1"
>
<el-tooltip
class=
"box-item"
effect=
"dark"
placement=
"top"
:content=
"row.startDepts.map((dept: any) => dept.name).join('、')"
>
{{
row
.
startDepts
[
0
].
name
}}
等
{{
row
.
startDepts
.
length
}}
个部门可见
</el-tooltip>
</el-text>
<el-text
v-else
>
<el-tooltip
class=
"box-item"
...
...
src/views/bpm/model/form/BasicInfo.vue
View file @
16a98e5a
...
...
@@ -77,6 +77,7 @@
>
<el-option
label=
"全员"
:value=
"0"
/>
<el-option
label=
"指定人员"
:value=
"1"
/>
<el-option
label=
"指定部门"
:value=
"2"
/>
</el-select>
<div
v-if=
"modelData.startUserType === 1"
class=
"mt-2 flex flex-wrap gap-2"
>
<div
...
...
@@ -99,6 +100,24 @@
<Icon
icon=
"ep:plus"
/>
选择人员
</el-button>
</div>
<div
v-if=
"modelData.startUserType === 2"
class=
"mt-2 flex flex-wrap gap-2"
>
<div
v-for=
"dept in selectedStartDepts"
:key=
"dept.id"
class=
"bg-gray-100 h-35px rounded-3xl flex items-center pr-8px dark:color-gray-600 position-relative"
>
<Icon
icon=
"ep:office-building"
class=
"!m-5px text-20px"
/>
{{
dept
.
name
}}
<Icon
icon=
"ep:close"
class=
"ml-2 cursor-pointer hover:text-red-500"
@
click=
"handleRemoveStartDept(dept)"
/>
</div>
<el-button
type=
"primary"
link
@
click=
"openStartDeptSelect"
>
<Icon
icon=
"ep:plus"
/>
选择部门
</el-button>
</div>
</el-form-item>
<el-form-item
label=
"流程管理员"
prop=
"managerUserIds"
class=
"mb-20px"
>
<div
class=
"flex flex-wrap gap-2"
>
...
...
@@ -127,11 +146,19 @@
<!-- 用户选择弹窗 -->
<UserSelectForm
ref=
"userSelectFormRef"
@
confirm=
"handleUserSelectConfirm"
/>
<!-- 部门选择弹窗 -->
<DeptSelectForm
ref=
"deptSelectFormRef"
:multiple=
"true"
:check-strictly=
"true"
@
confirm=
"handleDeptSelectConfirm"
/>
</
template
>
<
script
lang=
"ts"
setup
>
import
{
DICT_TYPE
,
getBoolDictOptions
,
getIntDictOptions
}
from
'@/utils/dict'
import
{
UserVO
}
from
'@/api/system/user'
import
{
DeptVO
}
from
'@/api/system/dept'
import
{
CategoryVO
}
from
'@/api/bpm/category'
const
props
=
defineProps
({
...
...
@@ -142,13 +169,19 @@ const props = defineProps({
userList
:
{
type
:
Array
,
required
:
true
},
deptList
:
{
type
:
Array
,
required
:
true
}
})
const
formRef
=
ref
()
const
selectedStartUsers
=
ref
<
UserVO
[]
>
([])
const
selectedStartDepts
=
ref
<
DeptVO
[]
>
([])
const
selectedManagerUsers
=
ref
<
UserVO
[]
>
([])
const
userSelectFormRef
=
ref
()
const
deptSelectFormRef
=
ref
()
const
currentSelectType
=
ref
<
'start'
|
'manager'
>
(
'start'
)
const
rules
=
{
...
...
@@ -174,6 +207,13 @@ watch(
}
else
{
selectedStartUsers
.
value
=
[]
}
if
(
newVal
.
startDeptIds
?.
length
)
{
selectedStartDepts
.
value
=
props
.
deptList
.
filter
((
dept
:
DeptVO
)
=>
newVal
.
startDeptIds
.
includes
(
dept
.
id
)
)
as
DeptVO
[]
}
else
{
selectedStartDepts
.
value
=
[]
}
if
(
newVal
.
managerUserIds
?.
length
)
{
selectedManagerUsers
.
value
=
props
.
userList
.
filter
((
user
:
UserVO
)
=>
newVal
.
managerUserIds
.
includes
(
user
.
id
)
...
...
@@ -193,6 +233,11 @@ const openStartUserSelect = () => {
userSelectFormRef
.
value
.
open
(
0
,
selectedStartUsers
.
value
)
}
/** 打开部门选择 */
const
openStartDeptSelect
=
()
=>
{
deptSelectFormRef
.
value
.
open
(
selectedStartDepts
.
value
)
}
/** 打开管理员选择 */
const
openManagerUserSelect
=
()
=>
{
currentSelectType
.
value
=
'manager'
...
...
@@ -214,9 +259,28 @@ const handleUserSelectConfirm = (_, users: UserVO[]) => {
}
}
/** 处理部门选择确认 */
const
handleDeptSelectConfirm
=
(
depts
:
DeptVO
[])
=>
{
modelData
.
value
=
{
...
modelData
.
value
,
startDeptIds
:
depts
.
map
((
d
)
=>
d
.
id
)
}
}
/** 处理发起人类型变化 */
const
handleStartUserTypeChange
=
(
value
:
number
)
=>
{
if
(
value
!==
1
)
{
if
(
value
===
0
)
{
modelData
.
value
=
{
...
modelData
.
value
,
startUserIds
:
[],
startDeptIds
:
[]
}
}
else
if
(
value
===
1
)
{
modelData
.
value
=
{
...
modelData
.
value
,
startDeptIds
:
[]
}
}
else
if
(
value
===
2
)
{
modelData
.
value
=
{
...
modelData
.
value
,
startUserIds
:
[]
...
...
@@ -232,6 +296,14 @@ const handleRemoveStartUser = (user: UserVO) => {
}
}
/** 移除部门 */
const
handleRemoveStartDept
=
(
dept
:
DeptVO
)
=>
{
modelData
.
value
=
{
...
modelData
.
value
,
startDeptIds
:
modelData
.
value
.
startDeptIds
.
filter
((
id
:
number
)
=>
id
!==
dept
.
id
)
}
}
/** 移除管理员 */
const
handleRemoveManagerUser
=
(
user
:
UserVO
)
=>
{
modelData
.
value
=
{
...
...
src/views/bpm/model/form/ExtraSettings.vue
View file @
16a98e5a
...
...
@@ -148,7 +148,7 @@
<div
class=
"flex"
>
<el-switch
v-model=
"processBeforeTriggerEnable"
@
change=
"handlePr
eProcessNotify
EnableChange"
@
change=
"handlePr
ocessBeforeTrigger
EnableChange"
/>
<div
class=
"ml-80px"
>
流程启动后通知
</div>
</div>
...
...
@@ -168,9 +168,9 @@
<div
class=
"flex"
>
<el-switch
v-model=
"processAfterTriggerEnable"
@
change=
"handleP
ostProcessNotify
EnableChange"
@
change=
"handleP
rocessAfterTrigger
EnableChange"
/>
<div
class=
"ml-80px"
>
流程
启动
后通知
</div>
<div
class=
"ml-80px"
>
流程
结束
后通知
</div>
</div>
<HttpRequestSetting
v-if=
"processAfterTriggerEnable"
...
...
@@ -180,6 +180,46 @@
/>
</div>
</el-form-item>
<el-form-item
class=
"mb-20px"
>
<
template
#
label
>
<el-text
size=
"large"
tag=
"b"
>
任务前置通知
</el-text>
</
template
>
<div
class=
"flex flex-col w-100%"
>
<div
class=
"flex"
>
<el-switch
v-model=
"taskBeforeTriggerEnable"
@
change=
"handleTaskBeforeTriggerEnableChange"
/>
<div
class=
"ml-80px"
>
任务执行时通知
</div>
</div>
<HttpRequestSetting
v-if=
"taskBeforeTriggerEnable"
v-model:setting=
"modelData.taskBeforeTriggerSetting"
:responseEnable=
"true"
:formItemPrefix=
"'taskBeforeTriggerSetting'"
/>
</div>
</el-form-item>
<el-form-item
class=
"mb-20px"
>
<
template
#
label
>
<el-text
size=
"large"
tag=
"b"
>
任务后置通知
</el-text>
</
template
>
<div
class=
"flex flex-col w-100%"
>
<div
class=
"flex"
>
<el-switch
v-model=
"taskAfterTriggerEnable"
@
change=
"handleTaskAfterTriggerEnableChange"
/>
<div
class=
"ml-80px"
>
任务结束后通知
</div>
</div>
<HttpRequestSetting
v-if=
"taskAfterTriggerEnable"
v-model:setting=
"modelData.taskAfterTriggerSetting"
:responseEnable=
"true"
:formItemPrefix=
"'taskAfterTriggerSetting'"
/>
</div>
</el-form-item>
</el-form>
</template>
...
...
@@ -248,7 +288,7 @@ const numberExample = computed(() => {
/** 是否开启流程前置通知 */
const
processBeforeTriggerEnable
=
ref
(
false
)
const
handlePr
eProcessNotify
EnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
const
handlePr
ocessBeforeTrigger
EnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
if
(
val
)
{
modelData
.
value
.
processBeforeTriggerSetting
=
{
url
:
''
,
...
...
@@ -263,7 +303,7 @@ const handlePreProcessNotifyEnableChange = (val: boolean | string | number) => {
/** 是否开启流程后置通知 */
const
processAfterTriggerEnable
=
ref
(
false
)
const
handleP
ostProcessNotify
EnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
const
handleP
rocessAfterTrigger
EnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
if
(
val
)
{
modelData
.
value
.
processAfterTriggerSetting
=
{
url
:
''
,
...
...
@@ -276,6 +316,36 @@ const handlePostProcessNotifyEnableChange = (val: boolean | string | number) =>
}
}
/** 是否开启任务前置通知 */
const
taskBeforeTriggerEnable
=
ref
(
false
)
const
handleTaskBeforeTriggerEnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
if
(
val
)
{
modelData
.
value
.
taskBeforeTriggerSetting
=
{
url
:
''
,
header
:
[],
body
:
[],
response
:
[]
}
}
else
{
modelData
.
value
.
taskBeforeTriggerSetting
=
null
}
}
/** 是否开启任务后置通知 */
const
taskAfterTriggerEnable
=
ref
(
false
)
const
handleTaskAfterTriggerEnableChange
=
(
val
:
boolean
|
string
|
number
)
=>
{
if
(
val
)
{
modelData
.
value
.
taskAfterTriggerSetting
=
{
url
:
''
,
header
:
[],
body
:
[],
response
:
[]
}
}
else
{
modelData
.
value
.
taskAfterTriggerSetting
=
null
}
}
/** 表单选项 */
const
formField
=
ref
<
Array
<
{
field
:
string
;
title
:
string
}
>>
([])
const
formFieldOptions4Title
=
computed
(()
=>
{
...
...
@@ -341,6 +411,12 @@ const initData = () => {
if
(
modelData
.
value
.
processAfterTriggerSetting
)
{
processAfterTriggerEnable
.
value
=
true
}
if
(
modelData
.
value
.
taskBeforeTriggerSetting
)
{
taskBeforeTriggerEnable
.
value
=
true
}
if
(
modelData
.
value
.
taskAfterTriggerSetting
)
{
taskAfterTriggerEnable
.
value
=
true
}
}
defineExpose
({
initData
})
...
...
src/views/bpm/model/form/ProcessDesign.vue
View file @
16a98e5a
...
...
@@ -18,6 +18,7 @@
:model-key=
"modelData.key"
:model-name=
"modelData.name"
:start-user-ids=
"modelData.startUserIds"
:start-dept-ids=
"modelData.startDeptIds"
@
success=
"handleDesignSuccess"
/>
</
template
>
...
...
src/views/bpm/model/form/index.vue
View file @
16a98e5a
...
...
@@ -62,6 +62,7 @@
v-model=
"formData"
:categoryList=
"categoryList"
:userList=
"userList"
:deptList=
"deptList"
ref=
"basicInfoRef"
/>
</div>
...
...
@@ -92,6 +93,7 @@ import * as ModelApi from '@/api/bpm/model'
import
*
as
FormApi
from
'@/api/bpm/form'
import
{
CategoryApi
,
CategoryVO
}
from
'@/api/bpm/category'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
DefinitionApi
from
'@/api/bpm/definition'
import
{
BpmModelFormType
,
BpmModelType
,
BpmAutoApproveType
}
from
'@/utils/constants'
import
BasicInfo
from
'./BasicInfo.vue'
...
...
@@ -153,6 +155,7 @@ const formData: any = ref({
visible
:
true
,
startUserType
:
undefined
,
startUserIds
:
[],
startDeptIds
:
[],
managerUserIds
:
[],
allowCancelRunningProcess
:
true
,
processIdRule
:
{
...
...
@@ -183,6 +186,7 @@ provide('modelData', formData)
const
formList
=
ref
([])
const
categoryList
=
ref
<
CategoryVO
[]
>
([])
const
userList
=
ref
<
UserApi
.
UserVO
[]
>
([])
const
deptList
=
ref
<
DeptApi
.
DeptVO
[]
>
([])
/** 初始化数据 */
const
actionType
=
route
.
params
.
type
as
string
...
...
@@ -200,14 +204,17 @@ const initData = async () => {
data
.
simpleModel
=
JSON
.
parse
(
data
.
simpleModel
)
}
formData
.
value
=
data
formData
.
value
.
startUserType
=
formData
.
value
.
startUserIds
?.
length
>
0
?
1
:
0
formData
.
value
.
startUserType
=
formData
.
value
.
startUserIds
?.
length
>
0
?
1
:
formData
.
value
?.
startDeptIds
?.
length
>
0
?
2
:
0
}
else
if
([
'update'
,
'copy'
].
includes
(
actionType
))
{
// 情况二:修改场景/复制场景
const
modelId
=
route
.
params
.
id
as
string
formData
.
value
=
await
ModelApi
.
getModel
(
modelId
)
formData
.
value
.
startUserType
=
formData
.
value
.
startUserIds
?.
length
>
0
?
1
:
0
formData
.
value
.
startUserType
=
formData
.
value
.
startUserIds
?.
length
>
0
?
1
:
formData
.
value
?.
startDeptIds
?.
length
>
0
?
2
:
0
// 特殊:复制场景
if
(
actionT
ype
===
'copy'
)
{
if
(
route
.
params
.
t
ype
===
'copy'
)
{
delete
formData
.
value
.
id
formData
.
value
.
name
+=
'副本'
formData
.
value
.
key
+=
'_copy'
...
...
@@ -225,6 +232,8 @@ const initData = async () => {
categoryList
.
value
=
await
CategoryApi
.
getCategorySimpleList
()
// 获取用户列表
userList
.
value
=
await
UserApi
.
getSimpleUserList
()
// 获取部门列表
deptList
.
value
=
await
DeptApi
.
getSimpleDeptList
()
// 最终,设置 currentStep 切换到第一步
currentStep
.
value
=
0
...
...
src/views/bpm/oa/leave/create.vue
View file @
16a98e5a
This diff is collapsed.
Click to expand it.
src/views/bpm/processInstance/detail/ProcessInstanceTimeline.vue
View file @
16a98e5a
...
...
@@ -37,6 +37,11 @@
{{ getApprovalNodeTime(activity) }}
</div>
</div>
<div
v-if=
"activity.nodeType === NodeType.CHILD_PROCESS_NODE"
>
<el-button
type=
"primary"
plain
size=
"small"
@
click=
"handleChildProcess(activity)"
>
查看子流程
</el-button>
</div>
<!-- 需要自定义选择审批人 -->
<div
class=
"flex flex-wrap gap2 items-center"
...
...
@@ -194,6 +199,7 @@ withDefaults(
showStatusIcon
:
true
// 默认值为 true
}
)
const
{
push
}
=
useRouter
()
// 路由
// 审批节点
const
statusIconMap2
=
{
...
...
@@ -310,4 +316,15 @@ const handleUserSelectConfirm = (activityId: string, userList: any[]) => {
customApproveUsers
.
value
[
activityId
]
=
userList
||
[]
emit
(
'selectUserConfirm'
,
activityId
,
userList
)
}
/** 跳转子流程 */
const
handleChildProcess
=
(
activity
:
any
)
=>
{
// TODO @lesan:貌似跳不过去?!
push
({
name
:
'BpmProcessInstanceDetail'
,
query
:
{
id
:
activity
.
processInstanceId
}
})
}
</
script
>
src/views/bpm/simple/SimpleModelDesign.vue
View file @
16a98e5a
...
...
@@ -6,6 +6,7 @@
:model-name=
"modelName"
@
success=
"handleSuccess"
:start-user-ids=
"startUserIds"
:start-dept-ids=
"startDeptIds"
ref=
"designerRef"
/>
</ContentWrap>
...
...
@@ -22,6 +23,7 @@ defineProps<{
modelKey
?:
string
modelName
?:
string
startUserIds
?:
number
[]
startDeptIds
?:
number
[]
}
>
()
const
emit
=
defineEmits
([
'success'
])
...
...
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