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
2c11228f
authored
Jul 20, 2024
by
jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
仿钉钉流程设计- bug 修复
parent
538ad86b
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
193 additions
and
357 deletions
+193
-357
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
+1
-7
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
+11
-13
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
+22
-32
src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue
+23
-19
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
+30
-18
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
+13
-33
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
+45
-23
src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue
+34
-18
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
+14
-29
src/views/bpm/simpleWorkflow/index1.vue
+0
-165
No files found.
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
View file @
2c11228f
...
@@ -47,8 +47,7 @@ import {
...
@@ -47,8 +47,7 @@ import {
NodeType
,
NodeType
,
NODE_DEFAULT_NAME
,
NODE_DEFAULT_NAME
,
ApproveMethodType
,
ApproveMethodType
,
RejectHandlerType
,
RejectHandlerType
CandidateStrategy
}
from
'./consts'
}
from
'./consts'
import
{
generateUUID
}
from
'@/utils'
import
{
generateUUID
}
from
'@/utils'
defineOptions
({
defineOptions
({
...
@@ -80,7 +79,6 @@ const addNode = (type: number) => {
...
@@ -80,7 +79,6 @@ const addNode = (type: number) => {
showText
:
''
,
showText
:
''
,
type
:
NodeType
.
USER_TASK_NODE
,
type
:
NodeType
.
USER_TASK_NODE
,
approveMethod
:
ApproveMethodType
.
RRANDOM_SELECT_ONE_APPROVE
,
approveMethod
:
ApproveMethodType
.
RRANDOM_SELECT_ONE_APPROVE
,
candidateStrategy
:
CandidateStrategy
.
USER
,
// 超时处理
// 超时处理
rejectHandler
:
{
rejectHandler
:
{
type
:
RejectHandlerType
.
FINISH_PROCESS
type
:
RejectHandlerType
.
FINISH_PROCESS
...
@@ -88,7 +86,6 @@ const addNode = (type: number) => {
...
@@ -88,7 +86,6 @@ const addNode = (type: number) => {
timeoutHandler
:
{
timeoutHandler
:
{
enable
:
false
enable
:
false
},
},
childNode
:
props
.
childNode
childNode
:
props
.
childNode
}
}
emits
(
'update:childNode'
,
data
)
emits
(
'update:childNode'
,
data
)
...
@@ -99,9 +96,6 @@ const addNode = (type: number) => {
...
@@ -99,9 +96,6 @@ const addNode = (type: number) => {
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
)
as
string
,
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
)
as
string
,
showText
:
''
,
showText
:
''
,
type
:
NodeType
.
COPY_TASK_NODE
,
type
:
NodeType
.
COPY_TASK_NODE
,
candidateStrategy
:
CandidateStrategy
.
USER
,
candidateParam
:
undefined
,
fieldsPermission
:
undefined
,
childNode
:
props
.
childNode
childNode
:
props
.
childNode
}
}
emits
(
'update:childNode'
,
data
)
emits
(
'update:childNode'
,
data
)
...
...
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
View file @
2c11228f
...
@@ -3,20 +3,19 @@
...
@@ -3,20 +3,19 @@
<StartEventNode
<StartEventNode
v-if=
"currentNode && currentNode.type === NodeType.START_EVENT_NODE"
v-if=
"currentNode && currentNode.type === NodeType.START_EVENT_NODE"
:flow-node=
"currentNode"
:flow-node=
"currentNode"
@
update:model-value=
"handleModelValueUpdate"
/>
/>
<!-- 审批节点 -->
<!-- 审批节点 -->
<UserTaskNode
<UserTaskNode
v-if=
"currentNode && currentNode.type === NodeType.USER_TASK_NODE"
v-if=
"currentNode && currentNode.type === NodeType.USER_TASK_NODE"
:flow-node=
"currentNode"
:flow-node=
"currentNode"
@
update:
model-valu
e=
"handleModelValueUpdate"
@
update:
flow-nod
e=
"handleModelValueUpdate"
@
find:parent-node=
"findFromParentNode"
@
find:parent-node=
"findFromParentNode"
/>
/>
<!-- 抄送节点 -->
<!-- 抄送节点 -->
<CopyTaskNode
<CopyTaskNode
v-if=
"currentNode && currentNode.type === NodeType.COPY_TASK_NODE"
v-if=
"currentNode && currentNode.type === NodeType.COPY_TASK_NODE"
:flow-node=
"currentNode"
:flow-node=
"currentNode"
@
update:
model-valu
e=
"handleModelValueUpdate"
@
update:
flow-nod
e=
"handleModelValueUpdate"
/>
/>
<!-- 条件节点 -->
<!-- 条件节点 -->
<ExclusiveNode
<ExclusiveNode
...
@@ -36,7 +35,7 @@
...
@@ -36,7 +35,7 @@
<ProcessNodeTree
<ProcessNodeTree
v-if=
"currentNode && currentNode.childNode"
v-if=
"currentNode && currentNode.childNode"
v-model:flow-node=
"currentNode.childNode"
v-model:flow-node=
"currentNode.childNode"
:parent-node=
"currentNode"
:parent-node=
"currentNode"
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
/>
/>
...
@@ -65,11 +64,14 @@ const props = defineProps({
...
@@ -65,11 +64,14 @@ const props = defineProps({
}
}
})
})
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:flowNode'
,
'update:flowNode'
:
[
node
:
SimpleFlowNode
|
undefined
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
}
>
()
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
// 重要:监控节点变化. 重新绘制节点
// 重要:监控节点变化. 重新绘制节点
...
@@ -79,16 +81,12 @@ watch(
...
@@ -79,16 +81,12 @@ watch(
currentNode
.
value
=
newValue
currentNode
.
value
=
newValue
}
}
)
)
// 用于删除节点
const
handleModelValueUpdate
=
(
updateValue
)
=>
{
const
handleModelValueUpdate
=
(
updateValue
)
=>
{
console
.
log
(
'Process Node Tree handleModelValueUpdate'
,
updateValue
)
emits
(
'update:flowNode'
,
updateValue
)
emits
(
'update:flowNode'
,
updateValue
)
}
}
const
findFromParentNode
=
(
const
findFromParentNode
=
(
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
)
=>
{
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
)
=>
{
emits
(
'find:recursiveFindParentNode'
,
nodeList
,
props
.
parentNode
,
nodeType
)
emits
(
'find:recursiveFindParentNode'
,
nodeList
,
props
.
parentNode
,
nodeType
)
}
}
...
...
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue
View file @
2c11228f
...
@@ -20,20 +20,24 @@
...
@@ -20,20 +20,24 @@
</div>
</div>
<Dialog
v-model=
"errorDialogVisible"
title=
"保存失败"
width=
"400"
:fullscreen=
"false"
>
<Dialog
v-model=
"errorDialogVisible"
title=
"保存失败"
width=
"400"
:fullscreen=
"false"
>
<div
class=
"mb-2"
>
以下节点内容不完善,请修改后保存
</div>
<div
class=
"mb-2"
>
以下节点内容不完善,请修改后保存
</div>
<div
class=
"mb-3 b-rounded-1 bg-gray-100 p-2 line-height-normal"
v-for=
"(item, index) in errorNodes"
:key=
"index"
>
<div
class=
"mb-3 b-rounded-1 bg-gray-100 p-2 line-height-normal"
v-for=
"(item, index) in errorNodes"
:key=
"index"
>
{{
item
.
name
}}
:
{{
NODE_DEFAULT_TEXT
.
get
(
item
.
type
)
}}
{{
item
.
name
}}
:
{{
NODE_DEFAULT_TEXT
.
get
(
item
.
type
)
}}
</div>
</div>
<template
#
footer
>
<template
#
footer
>
<el-button
type=
"primary"
@
click=
"errorDialogVisible = false"
>
知道了
</el-button>
<el-button
type=
"primary"
@
click=
"errorDialogVisible = false"
>
知道了
</el-button>
</
template
>
</
template
>
</Dialog>
</Dialog>
</div>
</div>
</template>
</template>
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
ProcessNodeTree
from
'./ProcessNodeTree.vue'
;
import
ProcessNodeTree
from
'./ProcessNodeTree.vue'
import
{
updateBpmSimpleModel
,
getBpmSimpleModel
}
from
'@/api/bpm/simple'
import
{
updateBpmSimpleModel
,
getBpmSimpleModel
}
from
'@/api/bpm/simple'
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
}
from
'./consts'
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
}
from
'./consts'
defineOptions
({
defineOptions
({
name
:
'SimpleProcessDesigner'
name
:
'SimpleProcessDesigner'
...
@@ -44,33 +48,11 @@ const props = defineProps({
...
@@ -44,33 +48,11 @@ const props = defineProps({
modelId
:
String
modelId
:
String
})
})
const
message
=
useMessage
()
// 国际化
const
message
=
useMessage
()
// 国际化
const
processNodeTree
=
ref
<
SimpleFlowNode
>
({
const
processNodeTree
=
ref
<
SimpleFlowNode
|
undefined
>
()
name
:
'开始'
,
type
:
NodeType
.
START_EVENT_NODE
,
id
:
'StartEvent_1'
,
childNode
:
{
id
:
'EndEvent_1'
,
name
:
'结束'
,
type
:
NodeType
.
END_EVENT_NODE
}
})
// const rootNode = ref
<
SimpleFlowNode
>
({
// name: '开始',
// type: NodeType.START_EVENT_NODE,
// id: 'StartEvent_1'
// })
// const childNode = ref
<
SimpleFlowNode
>
({
// id: 'EndEvent_1',
// name: '结束',
// type: NodeType.END_EVENT_NODE
// })
const
errorDialogVisible
=
ref
(
false
)
const
errorDialogVisible
=
ref
(
false
)
let
errorNodes
:
SimpleFlowNode
[]
=
[]
let
errorNodes
:
SimpleFlowNode
[]
=
[]
const
saveSimpleFlowModel
=
async
()
=>
{
const
saveSimpleFlowModel
=
async
()
=>
{
console
.
log
(
'processNodeTree===>'
,
processNodeTree
.
value
)
if
(
!
props
.
modelId
)
{
if
(
!
props
.
modelId
)
{
message
.
error
(
'缺少模型 modelId 编号'
)
message
.
error
(
'缺少模型 modelId 编号'
)
return
return
...
@@ -79,7 +61,7 @@ const saveSimpleFlowModel = async () => {
...
@@ -79,7 +61,7 @@ const saveSimpleFlowModel = async () => {
validateNode
(
processNodeTree
.
value
,
errorNodes
)
validateNode
(
processNodeTree
.
value
,
errorNodes
)
if
(
errorNodes
.
length
>
0
)
{
if
(
errorNodes
.
length
>
0
)
{
errorDialogVisible
.
value
=
true
errorDialogVisible
.
value
=
true
return
;
return
}
}
const
data
=
{
const
data
=
{
id
:
props
.
modelId
,
id
:
props
.
modelId
,
...
@@ -93,7 +75,6 @@ const saveSimpleFlowModel = async () => {
...
@@ -93,7 +75,6 @@ const saveSimpleFlowModel = async () => {
}
else
{
}
else
{
message
.
alert
(
'修改失败'
)
message
.
alert
(
'修改失败'
)
}
}
}
}
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
// 校验节点设置。 暂时以 showText 为空 未节点错误配置
const
validateNode
=
(
node
:
SimpleFlowNode
|
undefined
,
errorNodes
:
SimpleFlowNode
[])
=>
{
const
validateNode
=
(
node
:
SimpleFlowNode
|
undefined
,
errorNodes
:
SimpleFlowNode
[])
=>
{
...
@@ -158,10 +139,19 @@ const zoomIn = () => {
...
@@ -158,10 +139,19 @@ const zoomIn = () => {
onMounted
(
async
()
=>
{
onMounted
(
async
()
=>
{
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
const
result
=
await
getBpmSimpleModel
(
props
.
modelId
)
if
(
result
)
{
if
(
result
)
{
console
.
log
(
'the result is '
,
result
)
processNodeTree
.
value
=
result
processNodeTree
.
value
=
result
// rootNode.value = result
}
else
{
// childNode.value = result.childNode
// 初始值
processNodeTree
.
value
=
{
name
:
'开始'
,
type
:
NodeType
.
START_EVENT_NODE
,
id
:
'StartEvent_1'
,
childNode
:
{
id
:
'EndEvent_1'
,
name
:
'结束'
,
type
:
NodeType
.
END_EVENT_NODE
}
}
}
}
})
})
</
script
>
</
script
>
src/components/SimpleProcessDesignerV2/src/nodes-config/CopyTaskNodeConfig.vue
View file @
2c11228f
...
@@ -14,11 +14,11 @@
...
@@ -14,11 +14,11 @@
class=
"config-editable-input"
class=
"config-editable-input"
@
blur=
"blurEvent()"
@
blur=
"blurEvent()"
v-mountedFocus
v-mountedFocus
v-model=
"c
urrentNode
.name"
v-model=
"c
onfigForm
.name"
:placeholder=
"c
urrentNode
.name"
:placeholder=
"c
onfigForm
.name"
/>
/>
<div
v-else
class=
"node-name"
<div
v-else
class=
"node-name"
>
{{
c
urrentNode
.
name
}}
>
{{
c
onfigForm
.
name
}}
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
/></div>
/></div>
...
@@ -223,8 +223,15 @@ const props = defineProps({
...
@@ -223,8 +223,15 @@ const props = defineProps({
})
})
// 是否可见
// 是否可见
const
settingVisible
=
ref
(
false
)
const
settingVisible
=
ref
(
false
)
// 当前节点
信息
// 当前节点
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
// 监控节点变化
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
const
userOptions
=
inject
<
Ref
<
UserApi
.
UserVO
[]
>>
(
'userList'
)
// 用户列表
const
userOptions
=
inject
<
Ref
<
UserApi
.
UserVO
[]
>>
(
'userList'
)
// 用户列表
...
@@ -247,13 +254,14 @@ const activeTabName = ref('user')
...
@@ -247,13 +254,14 @@ const activeTabName = ref('user')
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
configForm
=
ref
<
any
>
({
const
configForm
=
ref
<
any
>
({
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
),
candidateParamArray
:
[],
candidateParamArray
:
[],
candidateStrategy
:
CandidateStrategy
.
USER
,
candidateStrategy
:
CandidateStrategy
.
USER
,
fieldsPermission
:
[]
fieldsPermission
:
[]
})
})
// 表单校验规则
// 表单校验规则
const
formRules
=
reactive
({
const
formRules
=
reactive
({
candidateStrategy
:
[{
required
:
true
}],
candidateStrategy
:
[{
required
:
true
,
message
:
'抄送人设置不能为空'
,
trigger
:
'change'
}],
candidateParamArray
:
[{
required
:
true
,
message
:
'选项不能为空'
,
trigger
:
'blur'
}]
candidateParamArray
:
[{
required
:
true
,
message
:
'选项不能为空'
,
trigger
:
'blur'
}]
})
})
...
@@ -269,6 +277,7 @@ const saveConfig = async () => {
...
@@ -269,6 +277,7 @@ const saveConfig = async () => {
if
(
!
valid
)
return
false
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
if
(
!
showText
)
return
false
currentNode
.
value
.
name
=
configForm
.
value
.
name
currentNode
.
value
.
candidateParam
=
configForm
.
value
.
candidateParamArray
?.
join
(
','
)
currentNode
.
value
.
candidateParam
=
configForm
.
value
.
candidateParamArray
?.
join
(
','
)
currentNode
.
value
.
candidateStrategy
=
configForm
.
value
.
candidateStrategy
currentNode
.
value
.
candidateStrategy
=
configForm
.
value
.
candidateStrategy
currentNode
.
value
.
showText
=
showText
currentNode
.
value
.
showText
=
showText
...
@@ -280,11 +289,10 @@ const saveConfig = async () => {
...
@@ -280,11 +289,10 @@ const saveConfig = async () => {
const
open
=
()
=>
{
const
open
=
()
=>
{
settingVisible
.
value
=
true
settingVisible
.
value
=
true
}
}
//
修改当前编辑的节点, 由父组件传过来
//
设置抄送节点
const
setCurrentNode
=
(
node
:
SimpleFlowNode
)
=>
{
const
setCurrentNode
=
(
node
:
SimpleFlowNode
)
=>
{
currentNode
.
value
=
node
configForm
.
value
.
name
=
node
.
name
configForm
.
value
.
fieldsPermission
=
// 抄送人设置
cloneDeep
(
node
.
fieldsPermission
)
||
getDefaultFieldsPermission
(
formFields
?.
value
)
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
const
strCandidateParam
=
node
?.
candidateParam
const
strCandidateParam
=
node
?.
candidateParam
if
(
node
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
if
(
node
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
...
@@ -294,6 +302,9 @@ const setCurrentNode = (node: SimpleFlowNode) => {
...
@@ -294,6 +302,9 @@ const setCurrentNode = (node: SimpleFlowNode) => {
configForm
.
value
.
candidateParamArray
=
strCandidateParam
.
split
(
','
).
map
((
item
)
=>
+
item
)
configForm
.
value
.
candidateParamArray
=
strCandidateParam
.
split
(
','
).
map
((
item
)
=>
+
item
)
}
}
}
}
// 表单字段权限
configForm
.
value
.
fieldsPermission
=
cloneDeep
(
node
.
fieldsPermission
)
||
getDefaultFieldsPermission
(
formFields
?.
value
)
}
}
defineExpose
({
open
,
setCurrentNode
})
// 暴露方法给父组件
defineExpose
({
open
,
setCurrentNode
})
// 暴露方法给父组件
...
@@ -387,16 +398,9 @@ const clickIcon = () => {
...
@@ -387,16 +398,9 @@ const clickIcon = () => {
// 输入框失去焦点
// 输入框失去焦点
const
blurEvent
=
()
=>
{
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
showInput
.
value
=
false
c
urrentNode
.
value
.
name
=
c
onfigForm
.
value
.
name
=
c
urrentNode
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
)
as
string
)
c
onfigForm
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
COPY_TASK_NODE
)
as
string
)
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
>
<
style
lang=
"scss"
scoped
></
style
>
//
::v-deep
(
.el-divider--horizontal
)
{
//
display
:
block
;
//
height
:
1px
;
//
margin
:
0
;
//
border-top
:
1px
var
(
--el-border-color
)
var
(
--el-border-style
);
//
}
</
style
>
src/components/SimpleProcessDesignerV2/src/nodes-config/UserTaskNodeConfig.vue
View file @
2c11228f
...
@@ -15,11 +15,11 @@
...
@@ -15,11 +15,11 @@
class=
"config-editable-input"
class=
"config-editable-input"
@
blur=
"blurEvent()"
@
blur=
"blurEvent()"
v-mountedFocus
v-mountedFocus
v-model=
"c
urrentNode
.name"
v-model=
"c
onfigForm
.name"
:placeholder=
"c
urrentNode
.name"
:placeholder=
"c
onfigForm
.name"
/>
/>
<div
v-else
class=
"node-name"
<div
v-else
class=
"node-name"
>
{{
c
urrentNode
.
name
}}
>
{{
c
onfigForm
.
name
}}
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
<Icon
class=
"ml-1"
icon=
"ep:edit-pen"
:size=
"16"
@
click=
"clickIcon()"
/></div>
/></div>
...
@@ -394,8 +394,15 @@ const emits = defineEmits<{
...
@@ -394,8 +394,15 @@ const emits = defineEmits<{
'find:returnTaskNodes'
:
[
nodeList
:
SimpleFlowNode
[]]
'find:returnTaskNodes'
:
[
nodeList
:
SimpleFlowNode
[]]
}
>
()
}
>
()
const
notAllowedMultiApprovers
=
ref
(
false
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
// 监控节点变化
watch
(
()
=>
props
.
flowNode
,
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
const
notAllowedMultiApprovers
=
ref
(
false
)
const
settingVisible
=
ref
(
false
)
const
settingVisible
=
ref
(
false
)
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
roleOptions
=
inject
<
Ref
<
RoleApi
.
RoleVO
[]
>>
(
'roleList'
)
// 角色列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
const
postOptions
=
inject
<
Ref
<
PostApi
.
PostVO
[]
>>
(
'postList'
)
// 岗位列表
...
@@ -410,6 +417,7 @@ const returnTaskList = ref<SimpleFlowNode[]>([])
...
@@ -410,6 +417,7 @@ const returnTaskList = ref<SimpleFlowNode[]>([])
const
formRef
=
ref
()
// 表单 Ref
const
formRef
=
ref
()
// 表单 Ref
const
activeTabName
=
ref
(
'user'
)
// 激活的 Tab 标签页
const
activeTabName
=
ref
(
'user'
)
// 激活的 Tab 标签页
const
configForm
=
ref
<
any
>
({
const
configForm
=
ref
<
any
>
({
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
),
candidateParamArray
:
[],
candidateParamArray
:
[],
candidateStrategy
:
CandidateStrategy
.
USER
,
candidateStrategy
:
CandidateStrategy
.
USER
,
approveMethod
:
ApproveMethodType
.
RRANDOM_SELECT_ONE_APPROVE
,
approveMethod
:
ApproveMethodType
.
RRANDOM_SELECT_ONE_APPROVE
,
...
@@ -425,7 +433,7 @@ const configForm = ref<any>({
...
@@ -425,7 +433,7 @@ const configForm = ref<any>({
})
})
// 表单校验规则
// 表单校验规则
const
formRules
=
reactive
({
const
formRules
=
reactive
({
candidateStrategy
:
[{
required
:
true
}],
candidateStrategy
:
[{
required
:
true
,
message
:
'审批人设置不能为空'
,
trigger
:
'change'
}],
candidateParamArray
:
[{
required
:
true
,
message
:
'该选项不能为空'
,
trigger
:
'change'
}],
candidateParamArray
:
[{
required
:
true
,
message
:
'该选项不能为空'
,
trigger
:
'change'
}],
approveMethod
:
[{
required
:
true
,
message
:
'多人审批方式不能为空'
,
trigger
:
'change'
}],
approveMethod
:
[{
required
:
true
,
message
:
'多人审批方式不能为空'
,
trigger
:
'change'
}],
approveRatio
:
[{
required
:
true
,
message
:
'通过比例不能为空'
,
trigger
:
'blur'
}],
approveRatio
:
[{
required
:
true
,
message
:
'通过比例不能为空'
,
trigger
:
'blur'
}],
...
@@ -447,6 +455,7 @@ const saveConfig = async () => {
...
@@ -447,6 +455,7 @@ const saveConfig = async () => {
if
(
!
valid
)
return
false
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
if
(
!
showText
)
return
false
currentNode
.
value
.
name
=
configForm
.
value
.
name
currentNode
.
value
.
candidateStrategy
=
configForm
.
value
.
candidateStrategy
currentNode
.
value
.
candidateStrategy
=
configForm
.
value
.
candidateStrategy
currentNode
.
value
.
candidateParam
=
configForm
.
value
.
candidateParamArray
?.
join
(
','
)
currentNode
.
value
.
candidateParam
=
configForm
.
value
.
candidateParamArray
?.
join
(
','
)
// 设置审批方式
// 设置审批方式
...
@@ -566,12 +575,10 @@ const getShowText = (): string => {
...
@@ -566,12 +575,10 @@ const getShowText = (): string => {
const
open
=
()
=>
{
const
open
=
()
=>
{
settingVisible
.
value
=
true
settingVisible
.
value
=
true
}
}
//
修改当前编辑的
节点, 由父组件传过来
//
配置审批
节点, 由父组件传过来
const
setCurrentNode
=
(
node
:
SimpleFlowNode
)
=>
{
const
setCurrentNode
=
(
node
:
SimpleFlowNode
)
=>
{
currentNode
.
value
=
node
configForm
.
value
.
name
=
node
.
name
configForm
.
value
.
fieldsPermission
=
//1.1 审批人设置
cloneDeep
(
node
.
fieldsPermission
)
||
getDefaultFieldsPermission
(
formFields
?.
value
)
configForm
.
value
.
buttonsSetting
=
cloneDeep
(
node
.
buttonsSetting
)
||
DEFAULT_BUTTON_SETTING
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
const
strCandidateParam
=
node
?.
candidateParam
const
strCandidateParam
=
node
?.
candidateParam
if
(
node
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
if
(
node
.
candidateStrategy
===
CandidateStrategy
.
EXPRESSION
)
{
...
@@ -580,7 +587,6 @@ const setCurrentNode = (node: SimpleFlowNode) => {
...
@@ -580,7 +587,6 @@ const setCurrentNode = (node: SimpleFlowNode) => {
if
(
strCandidateParam
)
{
if
(
strCandidateParam
)
{
configForm
.
value
.
candidateParamArray
=
strCandidateParam
.
split
(
','
).
map
((
item
)
=>
+
item
)
configForm
.
value
.
candidateParamArray
=
strCandidateParam
.
split
(
','
).
map
((
item
)
=>
+
item
)
}
}
configForm
.
value
.
candidateStrategy
=
node
.
candidateStrategy
}
}
if
(
if
(
(
configForm
.
value
.
candidateParamArray
?.
length
<=
1
&&
(
configForm
.
value
.
candidateParamArray
?.
length
<=
1
&&
...
@@ -591,13 +597,18 @@ const setCurrentNode = (node: SimpleFlowNode) => {
...
@@ -591,13 +597,18 @@ const setCurrentNode = (node: SimpleFlowNode) => {
}
else
{
}
else
{
notAllowedMultiApprovers
.
value
=
false
notAllowedMultiApprovers
.
value
=
false
}
}
// 设置审批方式
//
1.2
设置审批方式
configForm
.
value
.
approveMethod
=
node
.
approveMethod
configForm
.
value
.
approveMethod
=
node
.
approveMethod
if
(
node
.
approveMethod
==
ApproveMethodType
.
APPROVE_BY_RATIO
)
{
if
(
node
.
approveMethod
==
ApproveMethodType
.
APPROVE_BY_RATIO
)
{
configForm
.
value
.
approveRatio
=
node
.
approveRatio
configForm
.
value
.
approveRatio
=
node
.
approveRatio
}
}
// 1.3 设置审批拒绝处理
configForm
.
value
.
rejectHandlerType
=
node
.
rejectHandler
?.
type
configForm
.
value
.
rejectHandlerType
=
node
.
rejectHandler
?.
type
configForm
.
value
.
returnNodeId
=
node
.
rejectHandler
?.
returnNodeId
configForm
.
value
.
returnNodeId
=
node
.
rejectHandler
?.
returnNodeId
const
matchNodeList
=
[]
emits
(
'find:returnTaskNodes'
,
matchNodeList
)
returnTaskList
.
value
=
matchNodeList
// 1.4 设置审批超时处理
configForm
.
value
.
timeoutHandlerEnable
=
node
.
timeoutHandler
?.
enable
configForm
.
value
.
timeoutHandlerEnable
=
node
.
timeoutHandler
?.
enable
if
(
node
.
timeoutHandler
?.
enable
&&
node
.
timeoutHandler
?.
timeDuration
)
{
if
(
node
.
timeoutHandler
?.
enable
&&
node
.
timeoutHandler
?.
timeDuration
)
{
const
strTimeDuration
=
node
.
timeoutHandler
.
timeDuration
const
strTimeDuration
=
node
.
timeoutHandler
.
timeDuration
...
@@ -608,10 +619,11 @@ const setCurrentNode = (node: SimpleFlowNode) => {
...
@@ -608,10 +619,11 @@ const setCurrentNode = (node: SimpleFlowNode) => {
}
}
configForm
.
value
.
timeoutHandlerAction
=
node
.
timeoutHandler
?.
action
configForm
.
value
.
timeoutHandlerAction
=
node
.
timeoutHandler
?.
action
configForm
.
value
.
maxRemindCount
=
node
.
timeoutHandler
?.
maxRemindCount
configForm
.
value
.
maxRemindCount
=
node
.
timeoutHandler
?.
maxRemindCount
// 查找可以驳回的用户节点
// 2. 操作按钮设置
const
matchNodeList
=
[]
configForm
.
value
.
buttonsSetting
=
cloneDeep
(
node
.
buttonsSetting
)
||
DEFAULT_BUTTON_SETTING
emits
(
'find:returnTaskNodes'
,
matchNodeList
)
// 3. 表单字段权限配置
returnTaskList
.
value
=
matchNodeList
configForm
.
value
.
fieldsPermission
=
cloneDeep
(
node
.
fieldsPermission
)
||
getDefaultFieldsPermission
(
formFields
?.
value
)
}
}
defineExpose
({
open
,
setCurrentNode
})
// 暴露方法给父组件
defineExpose
({
open
,
setCurrentNode
})
// 暴露方法给父组件
...
@@ -650,8 +662,8 @@ const clickIcon = () => {
...
@@ -650,8 +662,8 @@ const clickIcon = () => {
// 节点名称输入框失去焦点
// 节点名称输入框失去焦点
const
blurEvent
=
()
=>
{
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
showInput
.
value
=
false
c
urrentNode
.
value
.
name
=
c
onfigForm
.
value
.
name
=
c
urrentNode
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
)
c
onfigForm
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
)
}
}
const
approveMethodChanged
=
()
=>
{
const
approveMethodChanged
=
()
=>
{
...
...
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
View file @
2c11228f
<
template
>
<
template
>
<div
class=
"node-wrapper"
>
<div
class=
"node-wrapper"
>
<div
class=
"node-container"
>
<div
class=
"node-container"
>
<div
class=
"node-box"
:class=
"
{
'node-config-error': !currentNode.showText
}">
<div
class=
"node-box"
:class=
"
{
'node-config-error': !currentNode.showText
}">
<div
class=
"node-title-container"
>
<div
class=
"node-title-container"
>
<div
class=
"node-title-icon copy-task"
><span
class=
"iconfont icon-copy"
></span></div>
<div
class=
"node-title-icon copy-task"
><span
class=
"iconfont icon-copy"
></span></div>
<input
<input
...
@@ -27,24 +27,22 @@
...
@@ -27,24 +27,22 @@
<Icon
icon=
"ep:arrow-right-bold"
/>
<Icon
icon=
"ep:arrow-right-bold"
/>
</div>
</div>
<div
class=
"node-toolbar"
>
<div
class=
"node-toolbar"
>
<div
class=
"toolbar-icon"
><Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteNode"
/></div>
<div
class=
"toolbar-icon"
><Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteNode"
/></div>
</div>
</div>
</div>
</div>
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
</div>
</div>
<CopyTaskNodeConfig
<CopyTaskNodeConfig
v-if=
"currentNode"
ref=
"nodeSetting"
:flow-node=
"currentNode"
/>
v-if=
"currentNode"
ref=
"nodeSetting"
:flow-node=
"currentNode"
/>
</div>
</div>
</
template
>
</
template
>
<
script
setup
lang=
'ts'
>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
NodeHandler
from
'../NodeHandler.vue'
import
NodeHandler
from
'../NodeHandler.vue'
import
CopyTaskNodeConfig
from
'../nodes-config/CopyTaskNodeConfig.vue'
;
import
CopyTaskNodeConfig
from
'../nodes-config/CopyTaskNodeConfig.vue'
import
{
generateUUID
}
from
'@/utils'
import
{
generateUUID
}
from
'@/utils'
defineOptions
({
defineOptions
({
name
:
'CopyTaskNode'
name
:
'CopyTaskNode'
...
@@ -57,7 +55,7 @@ const props = defineProps({
...
@@ -57,7 +55,7 @@ const props = defineProps({
})
})
// 定义事件,更新父组件。
// 定义事件,更新父组件。
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:
modelValu
e'
:
[
node
:
SimpleFlowNode
|
undefined
]
'update:
flowNod
e'
:
[
node
:
SimpleFlowNode
|
undefined
]
}
>
()
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
...
@@ -73,7 +71,8 @@ const showInput = ref(false)
...
@@ -73,7 +71,8 @@ const showInput = ref(false)
// 节点名称输入框失去焦点
// 节点名称输入框失去焦点
const
blurEvent
=
()
=>
{
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
showInput
.
value
=
false
currentNode
.
value
.
name
=
currentNode
.
value
.
name
||
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
currentNode
.
value
.
name
=
currentNode
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
)
}
}
// 点击节点标题进行输入
// 点击节点标题进行输入
const
clickEvent
=
()
=>
{
const
clickEvent
=
()
=>
{
...
@@ -82,33 +81,14 @@ const clickEvent = () => {
...
@@ -82,33 +81,14 @@ const clickEvent = () => {
const
nodeSetting
=
ref
()
const
nodeSetting
=
ref
()
// 打开节点配置
// 打开节点配置
const
openNodeConfig
=
()
=>
{
const
openNodeConfig
=
()
=>
{
nodeSetting
.
value
.
setCurrentNode
(
currentNode
.
value
)
;
nodeSetting
.
value
.
setCurrentNode
(
currentNode
.
value
)
nodeSetting
.
value
.
open
()
nodeSetting
.
value
.
open
()
}
}
// 删除节点。更新当前节点为孩子节点
// 删除节点。更新当前节点为孩子节点
const
deleteNode
=
()
=>
{
const
deleteNode
=
()
=>
{
emits
(
'update:modelValue'
,
currentNode
.
value
.
childNode
)
emits
(
'update:flowNode'
,
currentNode
.
value
.
childNode
)
}
// 复制节点
const
copyNode
=
()
=>
{
const
newCopyNode
:
SimpleFlowNode
=
{
id
:
generateUUID
(),
name
:
currentNode
.
value
.
name
,
showText
:
currentNode
.
value
.
showText
,
type
:
currentNode
.
value
.
type
,
// 抄送节点配置
attributes
:
{
candidateStrategy
:
currentNode
.
value
.
attributes
?.
candidateStrategy
,
candidateParam
:
currentNode
.
value
.
attributes
?.
candidateParam
},
childNode
:
currentNode
.
value
}
currentNode
.
value
=
newCopyNode
emits
(
'update:modelValue'
,
currentNode
.
value
)
}
}
</
script
>
</
script
>
<
style
lang=
'scss'
scoped
>
<
style
lang=
"scss"
scoped
></
style
>
</
style
>
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
View file @
2c11228f
...
@@ -2,9 +2,13 @@
...
@@ -2,9 +2,13 @@
<div
class=
"branch-node-wrapper"
>
<div
class=
"branch-node-wrapper"
>
<div
class=
"branch-node-container"
>
<div
class=
"branch-node-container"
>
<div
class=
"branch-node-add"
@
click=
"addCondition"
>
添加条件
</div>
<div
class=
"branch-node-add"
@
click=
"addCondition"
>
添加条件
</div>
<div
class=
"branch-node-item"
v-for=
"(item, index) in currentNode.conditionNodes"
:key=
"index"
>
<div
class=
"branch-node-item"
v-for=
"(item, index) in currentNode.conditionNodes"
:key=
"index"
>
<template
v-if=
"index == 0"
>
<template
v-if=
"index == 0"
>
<div
class=
"branch-line-first-top"
></div>
<div
class=
"branch-line-first-top"
>
</div>
<div
class=
"branch-line-first-bottom"
></div>
<div
class=
"branch-line-first-bottom"
></div>
</
template
>
</
template
>
<
template
v-if=
"index + 1 == currentNode.conditionNodes?.length"
>
<
template
v-if=
"index + 1 == currentNode.conditionNodes?.length"
>
...
@@ -21,7 +25,8 @@
...
@@ -21,7 +25,8 @@
class=
"input-max-width editable-title-input"
class=
"input-max-width editable-title-input"
@
blur=
"blurEvent(index)"
@
blur=
"blurEvent(index)"
v-mountedFocus
v-mountedFocus
v-model=
"item.name"
/>
v-model=
"item.name"
/>
</div>
</div>
<div
v-else
class=
"branch-title"
@
click=
"clickEvent(index)"
>
{{ item.name }}
</div>
<div
v-else
class=
"branch-title"
@
click=
"clickEvent(index)"
>
{{ item.name }}
</div>
<div
class=
"branch-priority"
>
优先级{{ index + 1 }}
</div>
<div
class=
"branch-priority"
>
优先级{{ index + 1 }}
</div>
...
@@ -36,19 +41,27 @@
...
@@ -36,19 +41,27 @@
</div>
</div>
<div
class=
"node-toolbar"
v-if=
"index + 1 !== currentNode.conditionNodes?.length"
>
<div
class=
"node-toolbar"
v-if=
"index + 1 !== currentNode.conditionNodes?.length"
>
<div
class=
"toolbar-icon"
>
<div
class=
"toolbar-icon"
>
<Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteCondition(index)"
/>
<Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteCondition(index)"
/>
</div>
</div>
</div>
</div>
<div
<div
class=
"branch-node-move move-node-left"
class=
"branch-node-move move-node-left"
v-if=
"index != 0 && index + 1 !== currentNode.conditionNodes?.length"
@
click=
"moveNode(index, -1)"
>
v-if=
"index != 0 && index + 1 !== currentNode.conditionNodes?.length"
@
click=
"moveNode(index, -1)"
>
<Icon
icon=
"ep:arrow-left"
/>
<Icon
icon=
"ep:arrow-left"
/>
</div>
</div>
<div
<div
class=
"branch-node-move move-node-right"
class=
"branch-node-move move-node-right"
v-if=
"currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
v-if=
"currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
@
click=
"moveNode(index, 1)"
>
@
click=
"moveNode(index, 1)"
>
<Icon
icon=
"ep:arrow-right"
/>
<Icon
icon=
"ep:arrow-right"
/>
</div>
</div>
</div>
</div>
...
@@ -61,7 +74,8 @@
...
@@ -61,7 +74,8 @@
v-if=
"item && item.childNode"
v-if=
"item && item.childNode"
:parent-node=
"item"
:parent-node=
"item"
v-model:flow-node=
"item.childNode"
v-model:flow-node=
"item.childNode"
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
/>
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
/>
</div>
</div>
</div>
</div>
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
...
@@ -91,25 +105,32 @@ const props = defineProps({
...
@@ -91,25 +105,32 @@ const props = defineProps({
})
})
// 定义事件,更新父组件
// 定义事件,更新父组件
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
],
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
]
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
],
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
}
>
()
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
// const conditionNodes = computed(() => currentNode.value.conditionNodes);
// const conditionNodes = computed(() => currentNode.value.conditionNodes);
watch
(()
=>
props
.
flowNode
,
(
newValue
)
=>
{
watch
(
currentNode
.
value
=
newValue
;
()
=>
props
.
flowNode
,
});
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
const
showInputs
=
ref
<
boolean
[]
>
([])
const
showInputs
=
ref
<
boolean
[]
>
([])
// 失去焦点
// 失去焦点
const
blurEvent
=
(
index
:
number
)
=>
{
const
blurEvent
=
(
index
:
number
)
=>
{
showInputs
.
value
[
index
]
=
false
showInputs
.
value
[
index
]
=
false
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
;
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
conditionNode
.
name
=
conditionNode
.
name
||
getDefaultConditionNodeName
(
index
,
conditionNode
.
attributes
?.
defaultFlow
)
conditionNode
.
name
=
conditionNode
.
name
||
getDefaultConditionNodeName
(
index
,
conditionNode
.
attributes
?.
defaultFlow
)
}
}
// 点击条件名称
// 点击条件名称
...
@@ -118,13 +139,13 @@ const clickEvent = (index: number) => {
...
@@ -118,13 +139,13 @@ const clickEvent = (index: number) => {
}
}
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
const
conditionNode
=
proxy
.
$refs
[
nodeId
][
0
]
;
const
conditionNode
=
proxy
.
$refs
[
nodeId
][
0
]
conditionNode
.
open
()
conditionNode
.
open
()
}
}
// 新增条件
// 新增条件
const
addCondition
=
()
=>
{
const
addCondition
=
()
=>
{
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
;
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
if
(
conditionNodes
)
{
if
(
conditionNodes
)
{
const
len
=
conditionNodes
.
length
const
len
=
conditionNodes
.
length
let
lastIndex
=
len
-
1
let
lastIndex
=
len
-
1
...
@@ -146,7 +167,7 @@ const addCondition = () => {
...
@@ -146,7 +167,7 @@ const addCondition = () => {
// 删除条件
// 删除条件
const
deleteCondition
=
(
index
:
number
)
=>
{
const
deleteCondition
=
(
index
:
number
)
=>
{
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
;
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
if
(
conditionNodes
)
{
if
(
conditionNodes
)
{
conditionNodes
.
splice
(
index
,
1
)
conditionNodes
.
splice
(
index
,
1
)
if
(
conditionNodes
.
length
==
1
)
{
if
(
conditionNodes
.
length
==
1
)
{
...
@@ -161,10 +182,12 @@ const deleteCondition = (index: number) => {
...
@@ -161,10 +182,12 @@ const deleteCondition = (index: number) => {
const
moveNode
=
(
index
:
number
,
to
:
number
)
=>
{
const
moveNode
=
(
index
:
number
,
to
:
number
)
=>
{
// -1 :向左 1: 向右
// -1 :向左 1: 向右
if
(
currentNode
.
value
.
conditionNodes
)
{
if
(
currentNode
.
value
.
conditionNodes
)
{
currentNode
.
value
.
conditionNodes
[
index
]
=
currentNode
.
value
.
conditionNodes
.
splice
(
index
+
to
,
currentNode
.
value
.
conditionNodes
[
index
]
=
currentNode
.
value
.
conditionNodes
.
splice
(
1
,
currentNode
.
value
.
conditionNodes
[
index
])[
0
]
index
+
to
,
1
,
currentNode
.
value
.
conditionNodes
[
index
]
)[
0
]
}
}
}
}
// 递归从父节点中查询匹配的节点
// 递归从父节点中查询匹配的节点
const
recursiveFindParentNode
=
(
const
recursiveFindParentNode
=
(
...
@@ -181,7 +204,6 @@ const recursiveFindParentNode = (
...
@@ -181,7 +204,6 @@ const recursiveFindParentNode = (
// 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.EXCLUSIVE_NODE) 继续查找
// 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点条件分支节点(NodeType.EXCLUSIVE_NODE) 继续查找
emits
(
'find:parentNode'
,
nodeList
,
nodeType
)
emits
(
'find:parentNode'
,
nodeList
,
nodeType
)
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/SimpleProcessDesignerV2/src/nodes/ParallelNode.vue
View file @
2c11228f
...
@@ -2,7 +2,11 @@
...
@@ -2,7 +2,11 @@
<div
class=
"branch-node-wrapper"
>
<div
class=
"branch-node-wrapper"
>
<div
class=
"branch-node-container"
>
<div
class=
"branch-node-container"
>
<div
class=
"branch-node-add"
@
click=
"addCondition"
>
添加分支
</div>
<div
class=
"branch-node-add"
@
click=
"addCondition"
>
添加分支
</div>
<div
class=
"branch-node-item"
v-for=
"(item, index) in currentNode.conditionNodes"
:key=
"index"
>
<div
class=
"branch-node-item"
v-for=
"(item, index) in currentNode.conditionNodes"
:key=
"index"
>
<template
v-if=
"index == 0"
>
<template
v-if=
"index == 0"
>
<div
class=
"branch-line-first-top"
></div>
<div
class=
"branch-line-first-top"
></div>
<div
class=
"branch-line-first-bottom"
></div>
<div
class=
"branch-line-first-bottom"
></div>
...
@@ -21,7 +25,8 @@
...
@@ -21,7 +25,8 @@
class=
"input-max-width editable-title-input"
class=
"input-max-width editable-title-input"
@
blur=
"blurEvent(index)"
@
blur=
"blurEvent(index)"
v-mountedFocus
v-mountedFocus
v-model=
"item.name"
/>
v-model=
"item.name"
/>
</div>
</div>
<div
v-else
class=
"branch-title"
@
click=
"clickEvent(index)"
>
{{ item.name }}
</div>
<div
v-else
class=
"branch-title"
@
click=
"clickEvent(index)"
>
{{ item.name }}
</div>
<div
class=
"branch-priority"
>
无优先级
</div>
<div
class=
"branch-priority"
>
无优先级
</div>
...
@@ -36,7 +41,12 @@
...
@@ -36,7 +41,12 @@
</div>
</div>
<div
class=
"node-toolbar"
>
<div
class=
"node-toolbar"
>
<div
class=
"toolbar-icon"
>
<div
class=
"toolbar-icon"
>
<Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteCondition(index)"
/>
<Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteCondition(index)"
/>
</div>
</div>
</div>
</div>
<!-- <div
<!-- <div
...
@@ -60,7 +70,8 @@
...
@@ -60,7 +70,8 @@
v-if=
"item && item.childNode"
v-if=
"item && item.childNode"
:parent-node=
"item"
:parent-node=
"item"
v-model:flow-node=
"item.childNode"
v-model:flow-node=
"item.childNode"
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
/>
@
find:recursive-find-parent-node=
"recursiveFindParentNode"
/>
</div>
</div>
</div>
</div>
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
/>
...
@@ -85,24 +96,30 @@ const props = defineProps({
...
@@ -85,24 +96,30 @@ const props = defineProps({
})
})
// 定义事件,更新父组件
// 定义事件,更新父组件
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
],
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
]
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
],
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
number
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
'find:recursiveFindParentNode'
:
[
nodeList
:
SimpleFlowNode
[],
curentNode
:
SimpleFlowNode
,
nodeType
:
number
]
}
>
()
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
watch
(()
=>
props
.
flowNode
,
(
newValue
)
=>
{
watch
(
currentNode
.
value
=
newValue
;
()
=>
props
.
flowNode
,
});
(
newValue
)
=>
{
currentNode
.
value
=
newValue
}
)
const
showInputs
=
ref
<
boolean
[]
>
([])
const
showInputs
=
ref
<
boolean
[]
>
([])
// 失去焦点
// 失去焦点
const
blurEvent
=
(
index
:
number
)
=>
{
const
blurEvent
=
(
index
:
number
)
=>
{
showInputs
.
value
[
index
]
=
false
showInputs
.
value
[
index
]
=
false
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
;
const
conditionNode
=
currentNode
.
value
.
conditionNodes
?.
at
(
index
)
as
SimpleFlowNode
conditionNode
.
name
=
conditionNode
.
name
||
`并行
${
index
+
1
}
`
conditionNode
.
name
=
conditionNode
.
name
||
`并行
${
index
+
1
}
`
}
}
// 点击条件名称
// 点击条件名称
...
@@ -111,13 +128,13 @@ const clickEvent = (index: number) => {
...
@@ -111,13 +128,13 @@ const clickEvent = (index: number) => {
}
}
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
const
conditionNode
=
proxy
.
$refs
[
nodeId
][
0
]
;
const
conditionNode
=
proxy
.
$refs
[
nodeId
][
0
]
conditionNode
.
open
()
conditionNode
.
open
()
}
}
// 新增条件
// 新增条件
const
addCondition
=
()
=>
{
const
addCondition
=
()
=>
{
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
;
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
if
(
conditionNodes
)
{
if
(
conditionNodes
)
{
const
len
=
conditionNodes
.
length
const
len
=
conditionNodes
.
length
let
lastIndex
=
len
-
1
let
lastIndex
=
len
-
1
...
@@ -127,7 +144,7 @@ const addCondition = () => {
...
@@ -127,7 +144,7 @@ const addCondition = () => {
showText
:
'无需配置条件同时执行'
,
showText
:
'无需配置条件同时执行'
,
type
:
NodeType
.
CONDITION_NODE
,
type
:
NodeType
.
CONDITION_NODE
,
childNode
:
undefined
,
childNode
:
undefined
,
conditionNodes
:
[]
,
conditionNodes
:
[]
}
}
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
}
}
...
@@ -135,7 +152,7 @@ const addCondition = () => {
...
@@ -135,7 +152,7 @@ const addCondition = () => {
// 删除条件
// 删除条件
const
deleteCondition
=
(
index
:
number
)
=>
{
const
deleteCondition
=
(
index
:
number
)
=>
{
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
;
const
conditionNodes
=
currentNode
.
value
.
conditionNodes
if
(
conditionNodes
)
{
if
(
conditionNodes
)
{
conditionNodes
.
splice
(
index
,
1
)
conditionNodes
.
splice
(
index
,
1
)
if
(
conditionNodes
.
length
==
1
)
{
if
(
conditionNodes
.
length
==
1
)
{
...
@@ -161,5 +178,4 @@ const recursiveFindParentNode = (
...
@@ -161,5 +178,4 @@ const recursiveFindParentNode = (
// 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点并行节点(NodeType.PARALLEL_NODE) 继续查找
// 条件节点 (NodeType.CONDITION_NODE) 比较特殊。需要调用其父节点并行节点(NodeType.PARALLEL_NODE) 继续查找
emits
(
'find:parentNode'
,
nodeList
,
nodeType
)
emits
(
'find:parentNode'
,
nodeList
,
nodeType
)
}
}
</
script
>
</
script
>
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
View file @
2c11228f
<
template
>
<
template
>
<div
class=
"node-wrapper"
>
<div
class=
"node-wrapper"
>
<div
class=
"node-container"
>
<div
class=
"node-container"
>
<div
class=
"node-box"
:class=
"
{
'node-config-error': !flowNode.showText
}">
<div
class=
"node-box"
:class=
"
{
'node-config-error': !currentNode.showText
}">
<div
class=
"node-title-container"
>
<div
class=
"node-title-container"
>
<div
class=
"node-title-icon user-task"
><span
class=
"iconfont icon-approve"
></span></div>
<div
class=
"node-title-icon user-task"
><span
class=
"iconfont icon-approve"
></span></div>
<input
<input
...
@@ -18,8 +18,8 @@
...
@@ -18,8 +18,8 @@
</div>
</div>
</div>
</div>
<div
class=
"node-content"
@
click=
"openNodeConfig"
>
<div
class=
"node-content"
@
click=
"openNodeConfig"
>
<div
class=
"node-text"
:title=
"
flowNode.showText"
v-if=
"flow
Node.showText"
>
<div
class=
"node-text"
:title=
"
currentNode.showText"
v-if=
"current
Node.showText"
>
{{
flow
Node
.
showText
}}
{{
current
Node
.
showText
}}
</div>
</div>
<div
class=
"node-text"
v-else
>
<div
class=
"node-text"
v-else
>
{{
NODE_DEFAULT_TEXT
.
get
(
NodeType
.
USER_TASK_NODE
)
}}
{{
NODE_DEFAULT_TEXT
.
get
(
NodeType
.
USER_TASK_NODE
)
}}
...
@@ -27,7 +27,9 @@
...
@@ -27,7 +27,9 @@
<Icon
icon=
"ep:arrow-right-bold"
/>
<Icon
icon=
"ep:arrow-right-bold"
/>
</div>
</div>
<div
class=
"node-toolbar"
>
<div
class=
"node-toolbar"
>
<div
class=
"toolbar-icon"
><Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteNode"
/></div>
<div
class=
"toolbar-icon"
><Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteNode"
/></div>
</div>
</div>
</div>
</div>
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
...
@@ -44,8 +46,7 @@
...
@@ -44,8 +46,7 @@
<
script
setup
lang=
"ts"
>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
,
NODE_DEFAULT_NAME
}
from
'../consts'
import
NodeHandler
from
'../NodeHandler.vue'
import
NodeHandler
from
'../NodeHandler.vue'
import
UserTaskNodeConfig
from
'../nodes-config/UserTaskNodeConfig.vue'
;
import
UserTaskNodeConfig
from
'../nodes-config/UserTaskNodeConfig.vue'
import
{
generateUUID
}
from
'@/utils'
defineOptions
({
defineOptions
({
name
:
'UserTaskNode'
name
:
'UserTaskNode'
})
})
...
@@ -56,7 +57,7 @@ const props = defineProps({
...
@@ -56,7 +57,7 @@ const props = defineProps({
}
}
})
})
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:
modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
],
'update:
flowNode'
:
[
node
:
SimpleFlowNode
|
undefined
]
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
NodeType
]
'find:parentNode'
:
[
nodeList
:
SimpleFlowNode
[],
nodeType
:
NodeType
]
}
>
()
}
>
()
...
@@ -65,7 +66,7 @@ const nodeSetting = ref()
...
@@ -65,7 +66,7 @@ const nodeSetting = ref()
// 打开节点配置
// 打开节点配置
const
openNodeConfig
=
()
=>
{
const
openNodeConfig
=
()
=>
{
// 把当前节点传递给配置组件
// 把当前节点传递给配置组件
nodeSetting
.
value
.
setCurrentNode
(
currentNode
.
value
)
;
nodeSetting
.
value
.
setCurrentNode
(
currentNode
.
value
)
nodeSetting
.
value
.
open
()
nodeSetting
.
value
.
open
()
}
}
// 监控节点变化
// 监控节点变化
...
@@ -80,7 +81,8 @@ const showInput = ref(false)
...
@@ -80,7 +81,8 @@ const showInput = ref(false)
// 节点名称输入框失去焦点
// 节点名称输入框失去焦点
const
blurEvent
=
()
=>
{
const
blurEvent
=
()
=>
{
showInput
.
value
=
false
showInput
.
value
=
false
currentNode
.
value
.
name
=
currentNode
.
value
.
name
||
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
currentNode
.
value
.
name
=
currentNode
.
value
.
name
||
(
NODE_DEFAULT_NAME
.
get
(
NodeType
.
USER_TASK_NODE
)
as
string
)
}
}
// 点击节点标题进行输入
// 点击节点标题进行输入
const
clickEvent
=
()
=>
{
const
clickEvent
=
()
=>
{
...
@@ -88,32 +90,15 @@ const clickEvent = () => {
...
@@ -88,32 +90,15 @@ const clickEvent = () => {
}
}
const
deleteNode
=
()
=>
{
const
deleteNode
=
()
=>
{
emits
(
'update:
modelValu
e'
,
currentNode
.
value
.
childNode
)
emits
(
'update:
flowNod
e'
,
currentNode
.
value
.
childNode
)
}
}
const
copyNode
=
()
=>
{
const
newCopyNode
:
SimpleFlowNode
=
{
id
:
generateUUID
(),
name
:
currentNode
.
value
.
name
,
showText
:
currentNode
.
value
.
showText
,
type
:
currentNode
.
value
.
type
,
// 审批节点配置
attributes
:
{
approveMethod
:
currentNode
.
value
.
attributes
?.
approveMethod
,
candidateStrategy
:
currentNode
.
value
.
attributes
?.
candidateStrategy
,
candidateParam
:
currentNode
.
value
.
attributes
?.
candidateParam
},
childNode
:
currentNode
.
value
}
currentNode
.
value
=
newCopyNode
emits
(
'update:modelValue'
,
currentNode
.
value
)
}
// 查找可以驳回用户节点
// 查找可以驳回用户节点
const
findReturnTaskNodes
=
(
const
findReturnTaskNodes
=
(
matchNodeList
:
SimpleFlowNode
[]
,
// 匹配的节点
matchNodeList
:
SimpleFlowNode
[]
// 匹配的节点
)
=>
{
)
=>
{
// 从父节点查找
// 从父节点查找
emits
(
'find:parentNode'
,
matchNodeList
,
NodeType
.
USER_TASK_NODE
)
;
emits
(
'find:parentNode'
,
matchNodeList
,
NodeType
.
USER_TASK_NODE
)
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
src/views/bpm/simpleWorkflow/index1.vue
deleted
100644 → 0
View file @
538ad86b
<
template
>
<div>
<section
class=
"dingflow-design"
>
<div
class=
"sticky right-0 top-0 z-10 w-full flex justify-end bg-white p-2 pr-4"
>
<el-button
type=
"primary"
size=
"small"
@
click=
"test"
>
保存(测试中,待完善)
</el-button>
</div>
<div
class=
"box-scale"
>
<div
class=
"start-event-node"
>
<div
class=
"start-event-node-circle"
>
开始
</div>
</div>
<div
class=
"start-event-node-line"
></div>
<nodeWrap
v-model:nodeConfig=
"nodeConfig"
/>
<div
class=
"end-event"
>
<div
class=
"end-event-circle"
>
结束
</div>
</div>
</div>
</section>
</div>
<approverDrawer/>
<copyerDrawer
/>
</
template
>
<
script
lang=
"ts"
setup
>
import
nodeWrap
from
'@/components/SimpleProcessDesigner/src/nodeWrap.vue'
import
approverDrawer
from
'@/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue'
import
copyerDrawer
from
'@/components/SimpleProcessDesigner/src/drawer/copyerDrawer.vue'
import
{
WorkFlowNode
}
from
'@/components/SimpleProcessDesigner/src/consts'
import
{
ref
}
from
'vue'
import
{
updateBpmSimpleModel
,
getBpmSimpleModel
}
from
'@/api/bpm/simple'
import
{
getModel
}
from
'@/api/bpm/model'
import
{
getForm
,
FormVO
}
from
'@/api/bpm/form'
defineOptions
({
name
:
'SimpleWorkflowDesignEditor2'
})
const
uid
=
getCurrentInstance
().
uid
const
router
=
useRouter
()
// 路由
const
{
query
}
=
useRoute
()
// 路由的查询
const
modelId
=
query
.
modelId
const
message
=
useMessage
()
// 国际化
const
nodeConfig
=
ref
<
WorkFlowNode
>
({
name
:
'发起人'
,
type
:
0
,
id
:
'StartEvent_'
+
uid
,
childNode
:
undefined
,
attributes
:
undefined
,
conditionNodes
:
[]
})
// 默认的表单字段权限
const
defaultFieldsPermission
:
any
[]
=
[]
const
formType
=
ref
(
20
);
provide
(
'defaultFieldsPermission'
,
defaultFieldsPermission
)
provide
(
'formType'
,
formType
)
const
test
=
async
()
=>
{
if
(
!
modelId
)
{
message
.
error
(
'缺少模型 modelId 编号'
)
return
}
console
.
log
(
'nodeConfig.value '
,
nodeConfig
.
value
)
const
data
=
{
id
:
modelId
,
simpleModelBody
:
nodeConfig
.
value
}
const
result
=
await
updateBpmSimpleModel
(
data
)
console
.
log
(
'save the result is '
,
result
)
if
(
result
)
{
message
.
success
(
'修改成功'
)
close
()
}
else
{
message
.
alert
(
'修改失败'
)
}
}
const
close
=
()
=>
{
router
.
push
({
path
:
'/bpm/manager/model'
})
}
onMounted
(
async
()
=>
{
const
bpmnModel
=
await
getModel
(
modelId
)
if
(
bpmnModel
)
{
formType
.
value
=
bpmnModel
.
formType
if
(
formType
.
value
===
10
)
{
const
bpmnForm
=
await
getForm
(
bpmnModel
.
formId
)
as
unknown
as
FormVO
const
formFields
=
bpmnForm
?.
fields
if
(
formFields
)
{
formFields
.
forEach
((
fieldStr
:
string
)
=>
{
const
{
field
,
title
}
=
JSON
.
parse
(
fieldStr
)
defaultFieldsPermission
.
push
({
field
,
title
,
permission
:
'2'
})
})
}
console
.
log
(
'defaultFieldsPermissions'
,
defaultFieldsPermission
);
}
}
console
.
log
(
'the modelId is '
,
modelId
)
const
result
=
await
getBpmSimpleModel
(
modelId
)
if
(
result
)
{
console
.
log
(
'get the result is '
,
result
)
nodeConfig
.
value
=
result
}
})
</
script
>
<
style
>
@import
url('@/components/SimpleProcessDesigner/theme/workflow.css')
;
.end-event
{
display
:
flex
;
direction
:
columns
;
justify-content
:
center
;
align-items
:
center
;
}
.end-event-circle
{
display
:
flex
;
width
:
40px
;
height
:
40px
;
font-size
:
14px
;
color
:
#f8f8fa
;
background-image
:
linear-gradient
(
-30deg
,
#bbbbc4
,
#d5d5de
),
linear-gradient
(
#bcbcc5
,
#bcbcc5
);
border-radius
:
50%
;
justify-content
:
center
;
align-items
:
center
;
}
/* .start-event-node {
color: #191f2566;
text-align: left;
border-radius: 50%;
} */
.start-event-node
{
display
:
flex
;
direction
:
columns
;
justify-content
:
center
;
align-items
:
center
;
}
.start-event-node-circle
{
display
:
flex
;
width
:
40px
;
height
:
40px
;
align-items
:
center
;
justify-content
:
center
;
font-size
:
14px
;
color
:
#f8f8fa
;
background-image
:
linear-gradient
(
90deg
,
#ff6a00
,
#f78b3e
),
linear-gradient
(
#ff6a00
,
#ff6a00
);
border-radius
:
50%
;
}
.start-event-node-line
::before
{
position
:
absolute
;
inset
:
0
;
z-index
:
-1
;
width
:
2px
;
height
:
100%
;
margin
:
auto
;
background-color
:
#cacaca
;
content
:
''
;
}
.start-event-node-line
{
position
:
relative
;
padding
:
20px
0
32px
;
}
</
style
>
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment