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
e8193a0a
authored
Apr 30, 2024
by
jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
仿钉钉流程设计器- 完善条件分支节点
parent
9a2dcf20
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
116 additions
and
45 deletions
+116
-45
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
+2
-2
src/components/SimpleProcessDesignerV2/src/consts.ts
+1
-2
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue
+9
-9
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
+1
-1
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
+44
-26
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
+1
-1
src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss
+58
-4
No files found.
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
View file @
e8193a0a
...
@@ -100,7 +100,7 @@ const addNode = (type: number) => {
...
@@ -100,7 +100,7 @@ const addNode = (type: number) => {
childNode
:
undefined
,
childNode
:
undefined
,
attributes
:
{
attributes
:
{
conditionType
:
1
,
conditionType
:
1
,
default
Condition
:
false
default
Flow
:
false
}
}
},
},
{
{
...
@@ -111,7 +111,7 @@ const addNode = (type: number) => {
...
@@ -111,7 +111,7 @@ const addNode = (type: number) => {
childNode
:
undefined
,
childNode
:
undefined
,
attributes
:
{
attributes
:
{
conditionType
:
undefined
,
conditionType
:
undefined
,
default
Condition
:
true
default
Flow
:
true
}
}
}
}
]
]
...
...
src/components/SimpleProcessDesignerV2/src/consts.ts
View file @
e8193a0a
...
@@ -115,6 +115,5 @@ export const APPROVE_METHODS: DictDataVO [] = [
...
@@ -115,6 +115,5 @@ export const APPROVE_METHODS: DictDataVO [] = [
]
]
export
const
CONDITION_CONFIG_TYPES
:
DictDataVO
[]
=
[
export
const
CONDITION_CONFIG_TYPES
:
DictDataVO
[]
=
[
{
label
:
'条件规则'
,
value
:
1
},
{
label
:
'自定义条件表达式'
,
value
:
1
}
{
label
:
'条件表达式'
,
value
:
2
}
]
]
src/components/SimpleProcessDesignerV2/src/nodes-config/ConditionNodeConfig.vue
View file @
e8193a0a
...
@@ -13,10 +13,10 @@
...
@@ -13,10 +13,10 @@
</div>
</div>
</
template
>
</
template
>
<div>
<div>
<div
class=
"mb-3 text-size-sm"
v-if=
"currentNode.attributes.default
Condition
"
>
其它条件不满足进入此分支(该分支不可编辑和删除)
</div>
<div
class=
"mb-3 text-size-sm"
v-if=
"currentNode.attributes.default
Flow
"
>
其它条件不满足进入此分支(该分支不可编辑和删除)
</div>
<div
v-else
>
<div
v-else
>
<el-form
label-position=
"top"
>
<el-form
label-position=
"top"
>
<el-form-item
label=
"
配置方式
"
prop=
"conditionType"
>
<el-form-item
label=
"
条件类型
"
prop=
"conditionType"
>
<el-radio-group
<el-radio-group
v-model=
"currentNode.attributes.conditionType"
v-model=
"currentNode.attributes.conditionType"
@
change=
"changeConditionType"
@
change=
"changeConditionType"
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
</el-form-item>
</el-form-item>
<el-form-item
<el-form-item
v-if=
"currentNode.attributes.conditionType ===
2
"
v-if=
"currentNode.attributes.conditionType ===
1
"
label=
"条件表达式"
label=
"条件表达式"
prop=
"conditionExpression"
prop=
"conditionExpression"
>
>
...
@@ -44,13 +44,13 @@
...
@@ -44,13 +44,13 @@
style=
"width: 100%"
style=
"width: 100%"
/>
/>
</el-form-item>
</el-form-item>
<el-form-item
<
!-- <
el-form-item
v-if="currentNode.attributes.conditionType === 1"
v-if="currentNode.attributes.conditionType === 1"
label="条件规则"
label="条件规则"
prop="conditionExpression"
prop="conditionExpression"
>
>
<span class="text-red-400">待实现</span>
<span class="text-red-400">待实现</span>
</el-form-item>
</el-form-item>
-->
</el-form>
</el-form>
</div>
</div>
</div>
</div>
...
@@ -93,17 +93,17 @@ const closeDrawer = () => {
...
@@ -93,17 +93,17 @@ const closeDrawer = () => {
}
}
// 保存配置
// 保存配置
const
saveConfig
=
()
=>
{
const
saveConfig
=
()
=>
{
if
(
!
currentNode
.
value
.
attributes
.
default
Condition
)
{
if
(
!
currentNode
.
value
.
attributes
.
default
Flow
)
{
currentNode
.
value
.
showText
=
getShowText
();
currentNode
.
value
.
showText
=
getShowText
();
}
}
settingVisible
.
value
=
false
settingVisible
.
value
=
false
}
}
const
getShowText
=
()
:
string
=>
{
const
getShowText
=
()
:
string
=>
{
let
showText
=
''
;
let
showText
=
''
;
// if (currentNode.value.attributes.conditionType === 1) {
// showText = '待实现'
// }
if
(
currentNode
.
value
.
attributes
.
conditionType
===
1
)
{
if
(
currentNode
.
value
.
attributes
.
conditionType
===
1
)
{
showText
=
'待实现'
}
if
(
currentNode
.
value
.
attributes
.
conditionType
===
2
)
{
if
(
currentNode
.
value
.
attributes
.
conditionExpression
)
{
if
(
currentNode
.
value
.
attributes
.
conditionExpression
)
{
showText
=
`表达式:
${
currentNode
.
value
.
attributes
.
conditionExpression
}
`
showText
=
`表达式:
${
currentNode
.
value
.
attributes
.
conditionExpression
}
`
}
}
...
...
src/components/SimpleProcessDesignerV2/src/nodes/CopyTaskNode.vue
View file @
e8193a0a
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
</div>
</div>
<div
class=
"node-toolbar"
>
<div
class=
"node-toolbar"
>
<!--
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:document-copy"
@
click=
"copyNode"
/></div>
-->
<!--
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:document-copy"
@
click=
"copyNode"
/></div>
-->
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:
circle-close"
:size=
"18
"
@
click=
"deleteNode"
/></div>
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:
delete"
:size=
"16
"
@
click=
"deleteNode"
/></div>
</div>
</div>
</div>
</div>
...
...
src/components/SimpleProcessDesignerV2/src/nodes/ExclusiveNode.vue
View file @
e8193a0a
...
@@ -2,11 +2,7 @@
...
@@ -2,11 +2,7 @@
<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
<div
class=
"branch-node-item"
v-for=
"(item, index) in currentNode.conditionNodes"
:key=
"index"
>
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>
...
@@ -17,31 +13,40 @@
...
@@ -17,31 +13,40 @@
</
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': !item.showText
}"
>
<div
class=
"node-box"
:class=
"{
'node-config-error': !item.showText
}"
>
<div
class=
"branch-node-title-container"
>
<div
class=
"branch-node-title-container"
>
<div
class=
"branch-title"
v-if=
"showInputs[index]"
>
<div
class=
"branch-title"
v-if=
"showInputs[index]"
>
<input
<input
type=
"text"
type=
"text"
class=
"input-max-width editable-title-input"
@
blur=
"blurEvent(index)"
class=
"input-max-width editable-title-input"
v-mountedFocus
v-model=
"item.name"
/>
@
blur=
"blurEvent(index)"
v-mountedFocus
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>
</div>
</div>
<div
class=
"node-content"
@
click=
"conditionNodeConfig(item.id)"
>
<div
class=
"
branch-
node-content"
@
click=
"conditionNodeConfig(item.id)"
>
<div
class=
"
node-text"
:title=
"item.showText"
v-if
=
"item.showText"
>
<div
class=
"
branch-node-text"
:title=
"item.showText"
v-if
=
"item.showText"
>
{{ item.showText }}
{{ item.showText }}
</div>
</div>
<div
class=
"
node-text"
v-else
>
<div
class=
"
branch-node-text"
v-else
>
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
{{ NODE_DEFAULT_TEXT.get(NodeType.CONDITION_NODE) }}
</div>
</div>
<Icon
icon=
"ep:arrow-right-bold"
/>
</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"
><Icon
icon=
"ep:circle-close"
@
click=
"deleteCondition(index)"
/></div>
<div
class=
"toolbar-icon"
>
<Icon
icon=
"ep:delete"
:size=
"16"
@
click=
"deleteCondition(index)"
/>
</div>
</div>
<div
class=
"branch-node-move move-node-left"
v-if=
"index != 0 && index + 1 !== currentNode.conditionNodes?.length"
@
click=
"moveNode(index, -1)"
>
<Icon
icon=
"ep:arrow-left"
/>
</div>
<div
class=
"branch-node-move move-node-right"
v-if=
"currentNode.conditionNodes && index < currentNode.conditionNodes.length - 2"
@
click=
"moveNode(index, 1)"
>
<Icon
icon=
"ep:arrow-right"
/>
</div>
</div>
</div>
</div>
<NodeHandler
v-model:child-node=
"item.childNode"
/>
<NodeHandler
v-model:child-node=
"item.childNode"
/>
...
@@ -74,7 +79,7 @@ const props = defineProps({
...
@@ -74,7 +79,7 @@ const props = defineProps({
})
})
// 定义事件,更新父组件
// 定义事件,更新父组件
const
emits
=
defineEmits
<
{
const
emits
=
defineEmits
<
{
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
]
'update:modelValue'
:
[
node
:
SimpleFlowNode
|
undefined
]
}
>
()
}
>
()
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
const
currentNode
=
ref
<
SimpleFlowNode
>
(
props
.
flowNode
)
...
@@ -90,17 +95,17 @@ watch(() => props.flowNode, (newValue) => {
...
@@ -90,17 +95,17 @@ watch(() => props.flowNode, (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
conditionNode
.
name
=
conditionNode
.
name
||
'条件'
+
index
}
}
// 点击条件名称
// 点击条件名称
const
clickEvent
=
(
index
:
number
)
=>
{
const
clickEvent
=
(
index
:
number
)
=>
{
showInputs
.
value
[
index
]
=
true
showInputs
.
value
[
index
]
=
true
}
}
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
const
conditionNodeConfig
=
(
nodeId
:
string
)
=>
{
console
.
log
(
'nodeId'
,
nodeId
);
console
.
log
(
'nodeId'
,
nodeId
);
console
.
log
(
"proxy.$refs"
,
proxy
.
$refs
);
console
.
log
(
"proxy.$refs"
,
proxy
.
$refs
);
// TODO 测试后续去掉
// TODO 测试后续去掉
...
@@ -109,28 +114,30 @@ const conditionNodeConfig = (nodeId:string) => {
...
@@ -109,28 +114,30 @@ const conditionNodeConfig = (nodeId:string) => {
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
const
conditionData
:
SimpleFlowNode
=
{
const
conditionData
:
SimpleFlowNode
=
{
id
:
generateUUID
(),
id
:
'Flow_'
+
generateUUID
(),
name
:
'条件'
+
len
,
name
:
'条件'
+
len
,
showText
:
''
,
showText
:
''
,
type
:
NodeType
.
CONDITION_NODE
,
type
:
NodeType
.
CONDITION_NODE
,
childNode
:
undefined
,
childNode
:
undefined
,
conditionNodes
:
[],
conditionNodes
:
[],
attributes
:
{
attributes
:
{
conditionType
:
1
,
conditionType
:
1
,
default
Condition
:
false
default
Flow
:
false
}
}
}
}
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
conditionNodes
.
splice
(
lastIndex
,
0
,
conditionData
)
}
}
}
}
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
)
...
@@ -142,6 +149,17 @@ const deleteCondition = (index:number) => {
...
@@ -142,6 +149,17 @@ const deleteCondition = (index:number) => {
}
}
}
}
// 移动节点
const
moveNode
=
(
index
:
number
,
to
:
number
)
=>
{
// -1 :向左 1: 向右
if
(
currentNode
.
value
.
conditionNodes
)
{
currentNode
.
value
.
conditionNodes
[
index
]
=
currentNode
.
value
.
conditionNodes
.
splice
(
index
+
to
,
1
,
currentNode
.
value
.
conditionNodes
[
index
])[
0
]
}
}
</
script
>
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/SimpleProcessDesignerV2/src/nodes/UserTaskNode.vue
View file @
e8193a0a
...
@@ -28,7 +28,7 @@
...
@@ -28,7 +28,7 @@
</div>
</div>
<div
class=
"node-toolbar"
>
<div
class=
"node-toolbar"
>
<!--
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:document-copy"
@
click=
"copyNode"
/></div>
-->
<!--
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:document-copy"
@
click=
"copyNode"
/></div>
-->
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:
circle-clos
e"
:size=
"18"
@
click=
"deleteNode"
/></div>
<div
class=
"toolbar-icon"
><Icon
icon=
"ep:
delet
e"
:size=
"18"
@
click=
"deleteNode"
/></div>
</div>
</div>
</div>
</div>
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
...
...
src/components/SimpleProcessDesignerV2/theme/simple-process-designer.scss
View file @
e8193a0a
...
@@ -95,6 +95,10 @@
...
@@ -95,6 +95,10 @@
.node-toolbar
{
.node-toolbar
{
opacity
:
1
;
opacity
:
1
;
}
}
.branch-node-move
{
display
:
flex
;
}
}
}
// 普通节点标题
// 普通节点标题
...
@@ -181,24 +185,74 @@
...
@@ -181,24 +185,74 @@
}
}
}
}
//条件节点内容
.branch-node-content
{
display
:
flex
;
min-height
:
32px
;
padding
:
4px
8px
;
margin-top
:
4px
;
line-height
:
32px
;
align-items
:
center
;
color
:
#111f2c
;
border-radius
:
4px
;
.branch-node-text
{
overflow
:
hidden
;
font-size
:
14px
;
line-height
:
24px
;
text-overflow
:
ellipsis
;
word-break
:
break-all
;
-webkit-line-clamp
:
2
;
/* 这将限制文本显示为两行 */
-webkit-box-orient
:
vertical
;
}
}
// 节点操作 :删除
.node-toolbar
{
.node-toolbar
{
opacity
:
0
;
opacity
:
0
;
position
:
absolute
;
position
:
absolute
;
top
:
-5px
;
top
:
-
2
5px
;
right
:
-8
px
;
right
:
0
px
;
display
:
flex
;
display
:
flex
;
.toolbar-icon
{
.toolbar-icon
{
text-align
:
center
;
text-align
:
center
;
vertical-align
:
middle
;
vertical-align
:
middle
;
color
:
#6d6c6e
;
color
:
#000
;
}
}
}
// 条件节点左右移动
.branch-node-move
{
position
:
absolute
;
width
:
10px
;
cursor
:
pointer
;
display
:
none
;
align-items
:
center
;
height
:
100%
;
justify-content
:
center
;
}
.move-node-left
{
left
:
-2px
;
top
:
0px
;
background
:
rgba
(
126
,
134
,
142
,
.08
);
border-top-left-radius
:
8px
;
border-bottom-left-radius
:
8px
;
}
.move-node-right
{
right
:
-2px
;
top
:
0px
;
background
:
rgba
(
126
,
134
,
142
,.
08
);
border-top-right-radius
:
6px
;
border-bottom-right-radius
:
6px
;
}
}
}
}
.node-config-error
{
.node-config-error
{
border-color
:
#ff5219
;
border-color
:
#ff5219
!
important
;
}
}
// 普通节点包装
// 普通节点包装
.node-wrapper
{
.node-wrapper
{
...
...
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