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
Unverified
Commit
c3ad1ec3
authored
Mar 23, 2025
by
芋道源码
Committed by
GitHub
Mar 23, 2025
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #139 from minivv/master
【Simple设计器】流程模型->基本信息->谁可以发起,支持指定多个部门
parents
80ac4b0d
1b3cbfc8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
280 additions
and
22 deletions
+280
-22
src/components/DeptSelectForm/index.vue
+121
-0
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+6
-0
src/components/SimpleProcessDesignerV2/src/nodes-config/StartUserNodeConfig.vue
+50
-15
src/views/bpm/model/CategoryDraggableModel.vue
+14
-1
src/views/bpm/model/form/BasicInfo.vue
+73
-1
src/views/bpm/model/form/ProcessDesign.vue
+1
-0
src/views/bpm/model/form/index.vue
+13
-5
src/views/bpm/simple/SimpleModelDesign.vue
+2
-0
No files found.
src/components/DeptSelectForm/index.vue
0 → 100644
View file @
c3ad1ec3
<
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
>
\ No newline at end of file
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
c3ad1ec3
...
...
@@ -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 @
c3ad1ec3
...
...
@@ -25,21 +25,38 @@
</
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>
<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 +124,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 +136,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 +167,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/views/bpm/model/CategoryDraggableModel.vue
View file @
c3ad1ec3
...
...
@@ -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 @
c3ad1ec3
...
...
@@ -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/ProcessDesign.vue
View file @
c3ad1ec3
...
...
@@ -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 @
c3ad1ec3
...
...
@@ -62,6 +62,7 @@
v-model=
"formData"
:categoryList=
"categoryList"
:userList=
"userList"
:deptList=
"deptList"
ref=
"basicInfoRef"
/>
</div>
...
...
@@ -92,6 +93,8 @@ 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
{
useUserStoreWithOut
}
from
'@/store/modules/user'
import
*
as
DefinitionApi
from
'@/api/bpm/definition'
import
{
BpmModelFormType
,
BpmModelType
,
BpmAutoApproveType
}
from
'@/utils/constants'
import
BasicInfo
from
'./BasicInfo.vue'
...
...
@@ -153,6 +156,7 @@ const formData: any = ref({
visible
:
true
,
startUserType
:
undefined
,
startUserIds
:
[],
startDeptIds
:
[],
managerUserIds
:
[],
allowCancelRunningProcess
:
true
,
processIdRule
:
{
...
...
@@ -183,6 +187,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 +205,15 @@ 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
// 特殊:复制场景
if
(
actionType
===
'copy'
)
{
formData
.
value
.
startUserType
=
formData
.
value
.
startUserIds
?.
length
>
0
?
1
:
formData
.
value
?.
startDeptIds
?.
length
>
0
?
2
:
0
// 复制场景
if
(
route
.
params
.
type
===
'copy'
)
{
delete
formData
.
value
.
id
formData
.
value
.
name
+=
'副本'
formData
.
value
.
key
+=
'_copy'
...
...
@@ -225,7 +231,9 @@ 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/simple/SimpleModelDesign.vue
View file @
c3ad1ec3
...
...
@@ -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