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
3a5c93fa
authored
Jul 23, 2024
by
jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
仿钉钉流程设计器- 代码优化
parent
2c11228f
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
467 additions
and
305 deletions
+467
-305
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
+2
-8
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+1
-0
src/components/SimpleProcessDesignerV2/src/consts.ts
+132
-112
src/components/SimpleProcessDesignerV2/src/node.ts
+260
-0
src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue
+52
-159
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
+0
-0
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
+2
-3
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
+6
-10
src/components/SimpleProcessDesignerV2/src/utils.ts
+12
-13
No files found.
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
View file @
3a5c93fa
...
...
@@ -50,6 +50,7 @@ import CopyTaskNode from './nodes/CopyTaskNode.vue'
import
ExclusiveNode
from
'./nodes/ExclusiveNode.vue'
import
ParallelNode
from
'./nodes/ParallelNode.vue'
import
{
SimpleFlowNode
,
NodeType
}
from
'./consts'
import
{
useWatchNode
}
from
'./node'
defineOptions
({
name
:
'ProcessNodeTree'
})
...
...
@@ -72,15 +73,8 @@ const emits = defineEmits<{
]
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
useWatchNode
(
props
)
// 重要:监控节点变化. 重新绘制节点
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
// 用于删除节点
const
handleModelValueUpdate
=
(
updateValue
)
=>
{
emits
(
'update:flowNode'
,
updateValue
)
...
...
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
3a5c93fa
...
...
@@ -138,6 +138,7 @@ const zoomIn = () => {
onMounted
(
async
()
=>
{
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
console
.
log
(
'the result is :'
,
result
)
if
(
result
)
{
processNodeTree
.
value
=
result
}
else
{
...
...
src/components/SimpleProcessDesignerV2/src/consts.ts
View file @
3a5c93fa
// @ts-ignore
import
{
DictDataVO
}
from
'@/api/system/dict/types'
/**
* 节点类型
*/
export
enum
NodeType
{
/**
* 发起人节点
...
...
@@ -46,68 +48,37 @@ export enum NodeType {
*/
INCLUSIVE_NODE_JOIN
=
8
}
// 时间单位枚举
export
enum
TimeUnitType
{
/**
* 分钟
*/
MINUTE
=
1
,
/**
* 小时
*/
HOUR
=
2
,
/**
* 天
*/
DAY
=
3
}
export
enum
RejectHandlerType
{
/**
* 结束流程
*/
FINISH_PROCESS
=
1
,
/**
* 驳回到指定节点
*/
RETURN_USER_TASK
=
2
}
// 条件配置类型 ( 用于条件节点配置 )
export
enum
ConditionConfigType
{
/**
* 条件表达式
*/
EXPRESSION
=
1
,
/**
* 条件规则
*/
RULE
=
2
}
// 多人审批方式类型 ( 用于审批节点 )
export
enum
ApproveMethodType
{
/**
* 随机挑选一人审批
*/
RRANDOM_SELECT_ONE_APPROVE
=
1
,
/**
* 多人会签(按通过比例)
*/
APPROVE_BY_RATIO
=
2
,
/**
* 多人或签(通过只需一人,拒绝只需一人)
/**
* 节点结构定义
*/
ANY_APPROVE
=
3
,
/**
* 多人依次审批
*/
SEQUENTIAL_APPROVE
=
4
export
interface
SimpleFlowNode
{
id
:
string
type
:
NodeType
name
:
string
showText
?:
string
attributes
?:
any
// 孩子节点
childNode
?:
SimpleFlowNode
// 条件节点
conditionNodes
?:
SimpleFlowNode
[]
// 候选人策略
candidateStrategy
?:
number
// 候选人参数
candidateParam
?:
string
// 多人审批方式
approveMethod
?:
ApproveMethodType
//通过比例
approveRatio
?:
number
// 审批按钮设置
buttonsSetting
?:
any
[]
// 表单权限
fieldsPermission
?:
Array
<
Record
<
string
,
string
>>
// 审批任务超时处理
timeoutHandler
?:
TimeoutHandler
// 审批任务拒绝处理
rejectHandler
?:
RejectHandler
}
// 候选人策略 ( 用于审批节点。抄送节点 )
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
export
enum
CandidateStrategy
{
/**
* 指定角色
...
...
@@ -147,12 +118,41 @@ export enum CandidateStrategy {
EXPRESSION
=
60
}
// 多人审批方式类型枚举 ( 用于审批节点 )
export
enum
ApproveMethodType
{
/**
* 随机挑选一人审批
*/
RRANDOM_SELECT_ONE_APPROVE
=
1
,
/**
* 多人会签(按通过比例)
*/
APPROVE_BY_RATIO
=
2
,
/**
* 多人或签(通过只需一人,拒绝只需一人)
*/
ANY_APPROVE
=
3
,
/**
* 多人依次审批
*/
SEQUENTIAL_APPROVE
=
4
}
/**
* 审批拒绝结构定义
*/
export
type
RejectHandler
=
{
// 审批拒绝类型
type
:
RejectHandlerType
// 回退节点 Id
returnNodeId
?:
string
}
/**
* 审批超时结构定义
*/
export
type
TimeoutHandler
=
{
//是否开启超时处理
enable
:
boolean
...
...
@@ -163,60 +163,57 @@ export type TimeoutHandler = {
// 执行动作是自动提醒, 最大提醒次数
maxRemindCount
?:
number
}
export
type
SimpleFlowNode
=
{
id
:
string
type
:
NodeType
name
:
string
showText
?:
string
attributes
?:
any
// 孩子节点
childNode
?:
SimpleFlowNode
// 条件节点
conditionNodes
?:
SimpleFlowNode
[]
// 候选人策略
candidateStrategy
?:
number
// 候选人参数
candidateParam
?:
string
// 多人审批方式
approveMethod
?:
ApproveMethodType
//通过比例
approveRatio
?:
number
// 审批按钮设置
buttonsSetting
?:
any
[]
// 表单权限
fieldsPermission
?:
any
[]
// 审批任务超时处理
timeoutHandler
?:
TimeoutHandler
// 审批任务拒绝处理
rejectHandler
?:
RejectHandler
// 审批拒绝类型枚举
export
enum
RejectHandlerType
{
/**
* 结束流程
*/
FINISH_PROCESS
=
1
,
/**
* 驳回到指定节点
*/
RETURN_USER_TASK
=
2
}
// 条件组
export
type
ConditionGroup
=
{
// 条件组的逻辑关系是否为且
and
:
boolean
// 条件数组
conditions
:
Condition
[]
// 时间单位枚举
export
enum
TimeUnitType
{
/**
* 分钟
*/
MINUTE
=
1
,
/**
* 小时
*/
HOUR
=
2
,
/**
* 天
*/
DAY
=
3
}
// 条件
export
type
Condition
=
{
// 条件规则的逻辑关系是否为且
and
:
boolean
rules
:
ConditionRule
[]
// 条件配置类型 ( 用于条件节点配置 )
export
enum
ConditionConfigType
{
/**
* 条件表达式
*/
EXPRESSION
=
1
,
/**
* 条件规则
*/
RULE
=
2
}
/
/ 条件规则
export
type
ConditionRule
=
{
type
:
number
opName
:
string
opCode
:
string
leftSid
e
:
string
rightSide
:
string
/
**
* 操作按钮权限结构定义
*/
export
type
ButtonSetting
=
{
id
:
OpsButtonType
displayNam
e
:
string
enable
:
boolean
}
//
审批操作按钮类型
//
操作按钮类型枚举 (用于审批节点)
export
enum
OpsButtonType
{
/**
* 通过
...
...
@@ -243,11 +240,34 @@ export enum OpsButtonType {
*/
RETURN
=
6
}
/**
* 条件规则结构定义
*/
export
type
ConditionRule
=
{
type
:
number
opName
:
string
opCode
:
string
leftSide
:
string
rightSide
:
string
}
export
type
ButtonSetting
=
{
id
:
OpsButtonType
displayName
:
string
enable
:
boolean
/**
* 条件组结构定义
*/
export
type
ConditionGroup
=
{
// 条件组的逻辑关系是否为且
and
:
boolean
// 条件数组
conditions
:
Condition
[]
}
/**
* 条件结构定义
*/
export
type
Condition
=
{
// 条件规则的逻辑关系是否为且
and
:
boolean
rules
:
ConditionRule
[]
}
export
const
NODE_DEFAULT_TEXT
=
new
Map
<
number
,
string
>
()
...
...
src/components/SimpleProcessDesignerV2/src/node.ts
0 → 100644
View file @
3a5c93fa
import
{
cloneDeep
}
from
'lodash-es'
import
*
as
RoleApi
from
'@/api/system/role'
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
PostApi
from
'@/api/system/post'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserGroupApi
from
'@/api/bpm/userGroup'
import
{
SimpleFlowNode
,
CandidateStrategy
,
NodeType
,
ApproveMethodType
,
RejectHandlerType
,
NODE_DEFAULT_NAME
}
from
'./consts'
export
function
useWatchNode
(
props
:
{
flowNode
:
SimpleFlowNode
}):
Ref
<
SimpleFlowNode
>
{
const
node
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
node
.
value
=
newValue
}
)
return
node
}
/**
* @description 表单数据权限配置,用于审批节点、抄送节点
*/
export
function
useFormFieldsPermission
()
{
// 字段权限配置. 需要有 field, title, permissioin 属性
const
fieldsPermissionConfig
=
ref
<
Array
<
Record
<
string
,
string
>>>
([])
const
formType
=
inject
<
Ref
<
number
>>
(
'formType'
)
// 表单类型
const
formFields
=
inject
<
Ref
<
string
[]
>>
(
'formFields'
)
// 流程表单字段
const
getNodeConfigFormFields
=
(
nodeFormFields
?:
Array
<
Record
<
string
,
string
>>
)
=>
{
nodeFormFields
=
toRaw
(
nodeFormFields
)
fieldsPermissionConfig
.
value
=
cloneDeep
(
nodeFormFields
)
||
getDefaultFieldsPermission
(
unref
(
formFields
))
}
// 获取默认的表单权限。 所有字段只读
const
getDefaultFieldsPermission
=
(
formFields
?:
string
[])
=>
{
const
defaultFieldsPermission
:
Array
<
Record
<
string
,
string
>>
=
[]
if
(
formFields
)
{
formFields
.
forEach
((
fieldStr
:
string
)
=>
{
const
{
field
,
title
}
=
JSON
.
parse
(
fieldStr
)
defaultFieldsPermission
.
push
({
field
,
title
,
permission
:
'1'
// 只读
})
})
}
return
defaultFieldsPermission
}
return
{
formType
,
fieldsPermissionConfig
,
getNodeConfigFormFields
}
}
export
type
UserTaskFormType
=
{
candidateParamArray
:
any
[]
candidateStrategy
:
CandidateStrategy
approveMethod
:
ApproveMethodType
approveRatio
?:
number
rejectHandlerType
?:
RejectHandlerType
returnNodeId
?:
string
timeoutHandlerEnable
?:
boolean
timeoutHandlerAction
?:
number
timeDuration
?:
number
maxRemindCount
?:
number
buttonsSetting
:
any
[]
}
export
type
CopyTaskFormType
=
{
candidateParamArray
:
any
[]
candidateStrategy
:
CandidateStrategy
}
/**
* @description 节点表单数据。 用于审批节点、抄送节点
*/
export
function
useNodeForm
(
nodeType
:
NodeType
)
{
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
const
userOptions
=
inject
<
Ref
<
UserApi
.
UserVO
[]
>>
(
'userList'
)
// 用户列表
const
deptOptions
=
inject
<
Ref
<
DeptApi
.
DeptVO
[]
>>
(
'deptList'
)
// 部门列表
const
userGroupOptions
=
inject
<
Ref
<
UserGroupApi
.
UserGroupVO
[]
>>
(
'userGroupList'
)
// 用户组列表
const
deptTreeOptions
=
inject
(
'deptTree'
)
// 部门树
const
configForm
=
ref
<
UserTaskFormType
|
CopyTaskFormType
>
()
if
(
nodeType
===
NodeType
.
USER_TASK_NODE
)
{
configForm
.
value
=
{
candidateParamArray
:
[],
candidateStrategy
:
CandidateStrategy
.
USER
,
approveMethod
:
ApproveMethodType
.
RRANDOM_SELECT_ONE_APPROVE
,
approveRatio
:
100
,
rejectHandlerType
:
RejectHandlerType
.
FINISH_PROCESS
,
returnNodeId
:
''
,
timeoutHandlerEnable
:
false
,
timeoutHandlerAction
:
1
,
timeDuration
:
6
,
// 默认 6小时
maxRemindCount
:
1
,
// 默认 提醒 1次
buttonsSetting
:
[]
}
}
else
{
configForm
.
value
=
{
candidateParamArray
:
[],
candidateStrategy
:
CandidateStrategy
.
USER
}
}
const
getShowText
=
():
string
=>
{
let
showText
=
''
// 指定成员
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
USER
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
userOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
?.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
nickname
)
}
})
showText
=
`指定成员:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定角色
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
ROLE
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
roleOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
?.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定角色:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定部门
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
DEPT_MEMBER
||
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
DEPT_LEADER
)
{
if
(
configForm
.
value
?.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
deptOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
?.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
DEPT_MEMBER
)
{
showText
=
`部门成员:
${
candidateNames
.
join
(
','
)}
`
}
else
{
showText
=
`部门的负责人:
${
candidateNames
.
join
(
','
)}
`
}
}
}
// 指定岗位
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
POST
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
postOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
?.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定岗位:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定用户组
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
USER_GROUP
)
{
if
(
configForm
.
value
?.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
userGroupOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
?.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定用户组:
${
candidateNames
.
join
(
','
)}
`
}
}
// 发起人自选
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
START_USER_SELECT
)
{
showText
=
`发起人自选`
}
// 发起人自己
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
START_USER
)
{
showText
=
`发起人自己`
}
// 流程表达式
if
(
configForm
.
value
?.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
showText
=
`流程表达式:
${
configForm
.
value
.
candidateParamArray
[
0
]}
`
}
}
return
showText
}
return
{
configForm
,
roleOptions
,
postOptions
,
userOptions
,
userGroupOptions
,
deptTreeOptions
,
getShowText
}
}
/**
* @description 抽屉配置
*/
export
function
useDrawer
()
{
// 抽屉配置是否可见
const
settingVisible
=
ref
(
false
)
// 关闭配置抽屉
const
closeDrawer
=
()
=>
{
settingVisible
.
value
=
false
}
// 打开配置抽屉
const
openDrawer
=
()
=>
{
settingVisible
.
value
=
true
}
return
{
settingVisible
,
closeDrawer
,
openDrawer
}
}
/**
* @description 节点名称配置
*/
export
function
useNodeName
(
nodeType
:
NodeType
)
{
// 节点名称
const
nodeName
=
ref
<
string
>
()
// 节点名称输入框
const
showInput
=
ref
(
false
)
// 点击节点名称编辑图标
const
clickIcon
=
()
=>
{
showInput
.
value
=
true
}
// 节点名称输入框失去焦点
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
nodeName
.
value
=
nodeName
.
value
||
(
NODE_DEFAULT_NAME
.
get
(
nodeType
)
as
string
)
}
return
{
nodeName
,
showInput
,
clickIcon
,
blurEvent
}
}
src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue
View file @
3a5c93fa
...
...
@@ -14,14 +14,12 @@
class=
"config-editable-input"
@
blur=
"blurEvent()"
v-mountedFocus
v-model=
"
configForm.n
ame"
:placeholder=
"
configForm.n
ame"
v-model=
"
nodeN
ame"
:placeholder=
"
nodeN
ame"
/>
<div
v-else
class=
"node-name"
>
{{
configForm
.
name
}}
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
/></div>
<div
v-else
class=
"node-name"
>
{{
nodeName
}}
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
/>
</div>
<div
class=
"divide-line"
></div>
</div>
</
template
>
...
...
@@ -173,7 +171,7 @@
</div>
<div
class=
"field-setting-item"
v-for=
"(item, index) in
configForm.fieldsPermission
"
v-for=
"(item, index) in
fieldsPermissionConfig
"
:key=
"index"
>
<div
class=
"field-setting-item-label"
>
{{ item.title }}
</div>
...
...
@@ -202,16 +200,17 @@
</el-drawer>
</template>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
CandidateStrategy
,
NodeType
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
{
getDefaultFieldsPermission
}
from
'../utils'
import
{
SimpleFlowNode
,
CandidateStrategy
,
NodeType
}
from
'../consts'
import
{
DICT_TYPE
,
getIntDictOptions
}
from
'@/utils/dict'
import
*
as
RoleApi
from
'@/api/system/role'
import
*
as
DeptApi
from
'@/api/system/dept'
import
*
as
PostApi
from
'@/api/system/post'
import
*
as
UserApi
from
'@/api/system/user'
import
*
as
UserGroupApi
from
'@/api/bpm/userGroup'
import
{
useWatchNode
,
useDrawer
,
useNodeName
,
useFormFieldsPermission
,
useNodeForm
,
CopyTaskFormType
}
from
'../node'
import
{
defaultProps
}
from
'@/utils/tree'
import
{
cloneDeep
}
from
'lodash-es'
defineOptions
({
name
:
'CopyTaskNodeConfig'
})
...
...
@@ -221,53 +220,45 @@ const props = defineProps({
required
:
true
}
})
//
是否可见
const
settingVisible
=
ref
(
false
)
//
抽屉配置
const
{
settingVisible
,
closeDrawer
,
openDrawer
}
=
useDrawer
(
)
// 当前节点
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
// 监控节点变化
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
const
userOptions
=
inject
<
Ref
<
UserApi
.
UserVO
[]
>>
(
'userList'
)
// 用户列表
const
deptOptions
=
inject
<
Ref
<
DeptApi
.
DeptVO
[]
>>
(
'deptList'
)
// 部门列表
const
userGroupOptions
=
inject
<
Ref
<
UserGroupApi
.
UserGroupVO
[]
>>
(
'userGroupList'
)
// 用户组列表
const
deptTreeOptions
=
inject
(
'deptTree'
)
// 部门树
const
formType
=
inject
(
'formType'
)
// 表单类型
const
formFields
=
inject
<
Ref
<
string
[]
>>
(
'formFields'
)
// 抄送人策略, 去掉发起人自选 和 发起人自己
const
copyUserStrategies
=
computed
(()
=>
{
return
getIntDictOptions
(
DICT_TYPE
.
BPM_TASK_CANDIDATE_STRATEGY
).
filter
(
(
item
)
=>
item
.
value
!==
CandidateStrategy
.
START_USER_SELECT
&&
item
.
value
!==
CandidateStrategy
.
START_USER
)
})
const
currentNode
=
useWatchNode
(
props
)
// 节点名称
const
{
nodeName
,
showInput
,
clickIcon
,
blurEvent
}
=
useNodeName
(
NodeType
.
COPY_TASK_NODE
)
// 激活的 Tab 标签页
const
activeTabName
=
ref
(
'user'
)
// 表单字段权限配置
const
{
formType
,
fieldsPermissionConfig
,
getNodeConfigFormFields
}
=
useFormFieldsPermission
()
// 抄送人表单配置
const
formRef
=
ref
()
// 表单 Ref
const
configForm
=
ref
<
any
>
({
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
),
candidateParamArray
:
[],
candidateStrategy
:
CandidateStrategy
.
USER
,
fieldsPermission
:
[]
})
// 表单校验规则
const
formRules
=
reactive
({
candidateStrategy
:
[{
required
:
true
,
message
:
'抄送人设置不能为空'
,
trigger
:
'change'
}],
candidateParamArray
:
[{
required
:
true
,
message
:
'选项不能为空'
,
trigger
:
'blur'
}]
})
// 关闭
const
closeDrawer
=
()
=>
{
settingVisible
.
value
=
false
const
{
configForm
:
tempConfigForm
,
roleOptions
,
postOptions
,
userOptions
,
userGroupOptions
,
deptTreeOptions
,
getShowText
}
=
useNodeForm
(
NodeType
.
COPY_TASK_NODE
)
const
configForm
=
tempConfigForm
as
Ref
<
CopyTaskFormType
>
// 抄送人策略, 去掉发起人自选 和 发起人自己
const
copyUserStrategies
=
computed
(()
=>
{
return
getIntDictOptions
(
DICT_TYPE
.
BPM_TASK_CANDIDATE_STRATEGY
).
filter
(
(
item
)
=>
item
.
value
!==
CandidateStrategy
.
START_USER_SELECT
&&
item
.
value
!==
CandidateStrategy
.
START_USER
)
})
// 改变抄送人设置策略
const
changeCandidateStrategy
=
()
=>
{
configForm
.
value
.
candidateParamArray
=
[]
}
// 保存配置
const
saveConfig
=
async
()
=>
{
...
...
@@ -277,23 +268,19 @@ const saveConfig = async () => {
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
currentNode
.
value
.
name
=
configForm
.
value
.
name
currentNode
.
value
.
name
=
nodeName
.
value
!
currentNode
.
value
.
candidateParam
=
configForm
.
value
.
candidateParamArray
?.
join
(
','
)
currentNode
.
value
.
candidateStrategy
=
configForm
.
value
.
candidateStrategy
currentNode
.
value
.
showText
=
showText
currentNode
.
value
.
fieldsPermission
=
configForm
.
value
.
fieldsPermission
currentNode
.
value
.
fieldsPermission
=
fieldsPermissionConfig
.
value
settingVisible
.
value
=
false
return
true
}
const
open
=
()
=>
{
settingVisible
.
value
=
true
}
// 设置抄送节点
const
setCurrentNode
=
(
node
:
SimpleFlowNode
)
=>
{
configForm
.
value
.
name
=
node
.
name
// 显示抄送节点配置, 由父组件传过来
const
showCopyTaskNodeConfig
=
(
node
:
SimpleFlowNode
)
=>
{
nodeName
.
value
=
node
.
name
// 抄送人设置
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
!
const
strCandidateParam
=
node
?.
candidateParam
if
(
node
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
configForm
.
value
.
candidateParamArray
[
0
]
=
strCandidateParam
...
...
@@ -303,104 +290,10 @@ const setCurrentNode = (node: SimpleFlowNode) => {
}
}
// 表单字段权限
configForm
.
value
.
fieldsPermission
=
cloneDeep
(
node
.
fieldsPermission
)
||
getDefaultFieldsPermission
(
formFields
?.
value
)
getNodeConfigFormFields
(
node
.
fieldsPermission
)
}
defineExpose
({
open
,
setCurrentNode
})
// 暴露方法给父组件
const
changeCandidateStrategy
=
()
=>
{
configForm
.
value
.
candidateParamArray
=
[]
}
// TODO 貌似可以和 UserTaskNodeConfig 重复了, 如何共用??
const
getShowText
=
():
string
=>
{
let
showText
=
''
// 指定成员
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
USER
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
userOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
nickname
)
}
})
showText
=
`指定成员:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定角色
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
ROLE
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
roleOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定角色:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定部门
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
DEPT_MEMBER
||
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
DEPT_LEADER
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
deptOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
if
(
currentNode
.
value
.
candidateStrategy
===
CandidateStrategy
.
DEPT_MEMBER
)
{
showText
=
`部门成员:
${
candidateNames
.
join
(
','
)}
`
}
else
{
showText
=
`部门的负责人:
${
candidateNames
.
join
(
','
)}
`
}
}
}
// 指定岗位
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
POST
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
postOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定岗位:
${
candidateNames
.
join
(
','
)}
`
}
}
// 指定用户组
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
USER_GROUP
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
const
candidateNames
:
string
[]
=
[]
userGroupOptions
?.
value
.
forEach
((
item
)
=>
{
if
(
configForm
.
value
.
candidateParamArray
.
includes
(
item
.
id
))
{
candidateNames
.
push
(
item
.
name
)
}
})
showText
=
`指定用户组:
${
candidateNames
.
join
(
','
)}
`
}
}
// 流程表达式
if
(
configForm
.
value
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
if
(
configForm
.
value
.
candidateParamArray
?.
length
>
0
)
{
showText
=
`流程表达式:
${
configForm
.
value
.
candidateParamArray
[
0
]}
`
}
}
return
showText
}
// 显示名称输入框
const
showInput
=
ref
(
false
)
const
clickIcon
=
()
=>
{
showInput
.
value
=
true
}
// 输入框失去焦点
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
configForm
.
value
.
name
=
configForm
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
)
as
string
)
}
defineExpose
({
openDrawer
,
showCopyTaskNodeConfig
})
// 暴露方法给父组件
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
View file @
3a5c93fa
This diff is collapsed.
Click to expand it.
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
View file @
3a5c93fa
...
...
@@ -43,7 +43,6 @@
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
NodeHandler
from
'../NodeHandler.vue'
import
CopyTaskNodeConfig
from
'../nodes-config/CopyTaskNodeConfig.vue'
import
{
generateUUID
}
from
'@/utils'
defineOptions
({
name
:
'CopyTaskNode'
})
...
...
@@ -81,8 +80,8 @@ const clickEvent = () => {
const
nodeSetting
=
ref
()
// 打开节点配置
const
openNodeConfig
=
()
=>
{
nodeSetting
.
value
.
s
etCurrentNode
(
currentNode
.
value
)
nodeSetting
.
value
.
open
()
nodeSetting
.
value
.
s
howCopyTaskNodeConfig
(
currentNode
.
value
)
nodeSetting
.
value
.
open
Drawer
()
}
// 删除节点。更新当前节点为孩子节点
...
...
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
View file @
3a5c93fa
...
...
@@ -45,6 +45,7 @@
</
template
>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
{
useWatchNode
}
from
'../node'
import
NodeHandler
from
'../NodeHandler.vue'
import
UserTaskNodeConfig
from
'../nodes-config/UserTaskNodeConfig.vue'
defineOptions
({
...
...
@@ -61,21 +62,16 @@ const emits = defineEmits<{
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
NodeType
]
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
useWatchNode
(
props
)
const
nodeSetting
=
ref
()
// 打开节点配置
const
openNodeConfig
=
()
=>
{
// 把当前节点传递给配置组件
nodeSetting
.
value
.
s
etCurrentNode
(
currentNode
.
value
)
nodeSetting
.
value
.
open
()
nodeSetting
.
value
.
s
howUserTaskNodeConfig
(
currentNode
.
value
)
nodeSetting
.
value
.
open
Drawer
()
}
// 监控节点变化
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
// 显示节点名称输入框
const
showInput
=
ref
(
false
)
// 节点名称输入框失去焦点
...
...
src/components/SimpleProcessDesignerV2/src/utils.ts
View file @
3a5c93fa
import
{
TimeUnitType
}
from
'./consts'
// 获取条件节点默认的名称
export
const
getDefaultConditionNodeName
=
(
index
:
number
,
defaultFlow
:
boolean
):
string
=>
{
if
(
defaultFlow
)
{
...
...
@@ -6,18 +8,15 @@ export const getDefaultConditionNodeName = (index: number, defaultFlow: boolean)
return
'条件'
+
(
index
+
1
)
}
// 获得默认的表单字段权限.
export
const
getDefaultFieldsPermission
=
(
formFields
:
string
[]
|
undefined
)
=>
{
const
defaultFieldsPermission
:
any
[]
=
[]
if
(
formFields
)
{
formFields
.
forEach
((
fieldStr
:
string
)
=>
{
const
{
field
,
title
}
=
JSON
.
parse
(
fieldStr
)
defaultFieldsPermission
.
push
({
field
,
title
,
permission
:
'1'
// 只读
})
})
export
const
convertTimeUnit
=
(
strTimeUnit
:
string
)
=>
{
if
(
strTimeUnit
===
'M'
)
{
return
TimeUnitType
.
MINUTE
}
if
(
strTimeUnit
===
'H'
)
{
return
TimeUnitType
.
HOUR
}
if
(
strTimeUnit
===
'D'
)
{
return
TimeUnitType
.
DAY
}
return
defaultFieldsPermission
return
TimeUnitType
.
HOUR
}
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