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
4f839136
authored
Apr 02, 2024
by
jason
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
仿钉钉设计流程:增加发起人、条件分支节点
parent
253d7071
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
179 additions
and
119 deletions
+179
-119
src/components/SimpleProcessDesigner/src/addNode.vue
+30
-27
src/components/SimpleProcessDesigner/src/consts.ts
+6
-5
src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue
+4
-48
src/components/SimpleProcessDesigner/src/nodeWrap.vue
+0
-0
src/components/SimpleProcessDesigner/src/util.ts
+17
-5
src/components/SimpleProcessDesigner/theme/workflow.css
+36
-4
src/views/bpm/simpleWorkflow/index.vue
+86
-30
No files found.
src/components/SimpleProcessDesigner/src/addNode.vue
View file @
4f839136
...
...
@@ -24,6 +24,12 @@
<p>
条件分支
</p>
</a>
-->
<a
class=
"add-node-popover-item condition"
@
click=
"addType(4)"
>
<div
class=
"item-wrapper"
>
<span
class=
"iconfont"
>
</span>
</div>
<p>
条件分支
</p>
</a>
</div>
<template
#
reference
>
<button
class=
"btn"
type=
"button"
>
...
...
@@ -36,6 +42,7 @@
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
}
from
'vue'
import
{
generateUUID
}
from
'@/utils'
let
props
=
defineProps
({
childNodeP
:
{
type
:
Object
,
...
...
@@ -89,7 +96,8 @@ const addType = (type) => {
emits
(
'update:childNodeP'
,
{
name
:
'路由'
,
type
:
4
,
childNode
:
null
,
id
:
'GateWay_'
+
generateUUID
(),
childNode
:
props
.
childNodeP
,
conditionNodes
:
[
{
name
:
'条件1'
,
...
...
@@ -97,15 +105,13 @@ const addType = (type) => {
type
:
3
,
priorityLevel
:
1
,
conditionList
:
[],
nodeUserList
:
[],
// childNode: props.childNodeP
childNode
:
null
},
{
name
:
'
条件2
'
,
name
:
'
其它情况
'
,
type
:
3
,
priorityLevel
:
2
,
conditionList
:
[],
nodeUserList
:
[],
childNode
:
null
}
]
...
...
@@ -115,55 +121,52 @@ const addType = (type) => {
</
script
>
<
style
scoped
lang=
"scss"
>
.add-node-btn-box
{
width
:
240px
;
position
:
relative
;
display
:
inline-flex
;
width
:
240px
;
-ms-flex-negative
:
0
;
flex-shrink
:
0
;
-webkit-box-flex
:
1
;
-ms-flex-positive
:
1
;
position
:
relative
;
&:before
{
content
:
''
;
&::before
{
position
:
absolute
;
top
:
0
;
left
:
0
;
right
:
0
;
bottom
:
0
;
inset
:
0
;
z-index
:
-1
;
margin
:
auto
;
width
:
2px
;
height
:
100%
;
margin
:
auto
;
background-color
:
#cacaca
;
content
:
''
;
}
.add-node-btn
{
user-select
:
none
;
display
:
flex
;
width
:
240px
;
padding
:
20px
0
32px
;
display
:
flex
;
-webkit-box-pack
:
center
;
justify-content
:
center
;
flex-shrink
:
0
;
-webkit-box-flex
:
1
;
-webkit-box-pack
:
center
;
user-select
:
none
;
flex-grow
:
1
;
.btn
{
outline
:
none
;
box-shadow
:
0
2px
4px
0
rgba
(
0
,
0
,
0
,
0.1
);
position
:
relative
;
width
:
30px
;
height
:
30px
;
line-height
:
30px
;
background
:
#3296fa
;
border-radius
:
50%
;
position
:
relative
;
border
:
none
;
line-height
:
30px
;
border-radius
:
50%
;
outline
:
none
;
box-shadow
:
0
2px
4px
0
rgba
(
0
,
0
,
0
,
0.1
);
-webkit-transition
:
all
0.3s
cubic-bezier
(
0.645
,
0.045
,
0.355
,
1
);
transition
:
all
0.3s
cubic-bezier
(
0.645
,
0.045
,
0.355
,
1
);
.iconfont
{
color
:
#fff
;
font-size
:
16px
;
color
:
#fff
;
}
&
:hover
{
...
...
@@ -172,8 +175,8 @@ const addType = (type) => {
}
&
:active
{
transform
:
none
;
background
:
#1e83e9
;
transform
:
none
;
box-shadow
:
0
2px
4px
0
rgba
(
0
,
0
,
0
,
0.1
);
}
}
...
...
@@ -191,7 +194,6 @@ const addType = (type) => {
color
:
#191f25
!important
;
.item-wrapper
{
user-select
:
none
;
display
:
inline-block
;
width
:
80px
;
height
:
80px
;
...
...
@@ -200,6 +202,7 @@ const addType = (type) => {
border
:
1px
solid
#e2e2e2
;
border-radius
:
50%
;
transition
:
all
0.3s
cubic-bezier
(
0.645
,
0.045
,
0.355
,
1
);
user-select
:
none
;
.iconfont
{
font-size
:
35px
;
...
...
@@ -238,8 +241,8 @@ const addType = (type) => {
&
:active
{
.item-wrapper
{
box-shadow
:
none
;
background
:
#eaeaea
;
box-shadow
:
none
;
}
.iconfont
{
...
...
src/components/SimpleProcessDesigner/src/consts.ts
View file @
4f839136
export
enum
NodeType
{
//// 0 发起人 1审批 2抄送 3条件 4路由
//// -1 根节点流程开始节点 0 发起人 1审批 2抄送 3条件 4路由
ROOT_NODE
=
-
1
,
/**
* 发起人节点
*/
...
...
@@ -37,11 +38,10 @@ NODE_TITLE.set(NodeType.CC_USER_NODE, '抄送人')
export
type
WorkFlowNode
=
{
id
:
string
,
parentId
:
string
,
type
:
NodeType
,
name
:
string
,
attributes
:
Map
<
string
,
any
>
,
attributes
:
Object
|
undefined
,
// 操作人
childNode
:
WorkFlowNode
,
conditionNodes
:
WorkFlowNode
[]
childNode
?:
WorkFlowNode
|
undefined
,
conditionNodes
:
WorkFlowNode
[]
|
undefined
}
\ No newline at end of file
src/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue
View file @
4f839136
...
...
@@ -156,7 +156,7 @@
</template>
<
script
lang=
"ts"
setup
>
import
{
ref
,
watch
,
computed
,
toRaw
}
from
'vue'
import
{
approveMethods
,
setApproverStr
}
from
'../util'
import
{
approveMethods
}
from
'../util'
import
{
useWorkFlowStoreWithOut
}
from
'@/store/modules/simpleWorkflow'
import
{
DICT_TYPE
,
getIntDictOptions
,
getDictLabel
}
from
'@/utils/dict'
import
{
defaultProps
,
handleTree
}
from
'@/utils/tree'
...
...
@@ -165,7 +165,7 @@ 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'
let
props
=
defineProps
({
defineProps
({
directorMaxLevel
:
{
type
:
Number
,
default
:
0
...
...
@@ -182,12 +182,8 @@ const candidateConfig = ref({
approveMethod
:
undefined
})
let
approverConfig
=
ref
({})
let
approverVisible
=
ref
(
false
)
let
approverRoleVisible
=
ref
(
false
)
let
checkedRoleList
=
ref
([])
let
checkedList
=
ref
([])
let
store
=
useWorkFlowStoreWithOut
()
let
{
setApprover
Config
,
setApprover
,
setUserTaskConfig
}
=
store
let
{
setApprover
,
setUserTaskConfig
}
=
store
let
approverConfig1
=
computed
(()
=>
store
.
approverConfig1
)
let
approverDrawer
=
computed
(()
=>
store
.
approverDrawer
)
const
userTaskConfig
=
computed
(()
=>
store
.
userTaskConfig
)
...
...
@@ -220,47 +216,7 @@ watch(userTaskConfig, (val) => {
watch
(
approverConfig1
,
(
val
)
=>
{
approverConfig
.
value
=
val
.
value
})
let
changeRange
=
()
=>
{
approverConfig
.
value
.
nodeUserList
=
[]
}
const
changeType
=
(
val
)
=>
{
approverConfig
.
value
.
nodeUserList
=
[]
approverConfig
.
value
.
examineMode
=
1
approverConfig
.
value
.
noHanderAction
=
2
if
(
val
==
2
)
{
approverConfig
.
value
.
directorLevel
=
1
}
else
if
(
val
==
4
)
{
approverConfig
.
value
.
selectMode
=
1
approverConfig
.
value
.
selectRange
=
1
}
else
if
(
val
==
7
)
{
approverConfig
.
value
.
examineEndDirectorLevel
=
1
}
}
const
addApprover
=
()
=>
{
approverVisible
.
value
=
true
checkedList
.
value
=
approverConfig
.
value
.
nodeUserList
}
const
addRoleApprover
=
()
=>
{
approverRoleVisible
.
value
=
true
checkedRoleList
.
value
=
approverConfig
.
value
.
nodeUserList
}
const
sureApprover
=
(
data
)
=>
{
approverConfig
.
value
.
nodeUserList
=
data
approverVisible
.
value
=
false
}
const
sureRoleApprover
=
(
data
)
=>
{
approverConfig
.
value
.
nodeUserList
=
data
approverRoleVisible
.
value
=
false
}
const
saveApprover
=
()
=>
{
approverConfig
.
value
.
error
=
!
setApproverStr
(
approverConfig
.
value
)
setApproverConfig
({
value
:
approverConfig
.
value
,
flag
:
true
,
id
:
approverConfig1
.
value
.
id
})
closeDrawer
()
}
const
saveConfig
=
()
=>
{
const
rawConfig
=
toRaw
(
userTaskConfig
.
value
)
const
{
approveMethod
,
candidateStrategy
,
candidateParam
}
=
toRaw
(
candidateConfig
.
value
);
...
...
src/components/SimpleProcessDesigner/src/nodeWrap.vue
View file @
4f839136
This diff is collapsed.
Click to expand it.
src/components/SimpleProcessDesigner/src/util.ts
View file @
4f839136
...
...
@@ -92,10 +92,22 @@ export const copyerStr = (nodeConfig: any) => {
export
const
conditionStr
=
(
nodeConfig
,
index
)
=>
{
const
{
conditionList
,
nodeUserList
}
=
nodeConfig
.
conditionNodes
[
index
]
if
(
conditionList
.
length
==
0
)
{
return
index
==
nodeConfig
.
conditionNodes
.
length
-
1
&&
nodeConfig
.
conditionNodes
[
0
].
conditionList
.
length
!=
0
?
'其他条件进入此流程'
:
'请设置条件'
// return index == nodeConfig.conditionNodes.length - 1 &&
// nodeConfig.conditionNodes[0].conditionList.length != 0
// ? '其他条件进入此流程'
// : '请设置条件'
// return index == nodeConfig.conditionNodes.length - 1 &&
// nodeConfig.conditionNodes[0].conditionList.length != 0
// ? '其他条件进入此流程'
// : '请设置条件'
console
.
log
(
'index===>'
,
index
);
console
.
log
(
'nodeConfig.conditionNodes.length===>'
,
nodeConfig
.
conditionNodes
.
length
);
if
(
index
===
nodeConfig
.
conditionNodes
.
length
-
1
)
{
return
'其它情况将进入该分支'
}
else
{
return
'请设置条件'
}
}
else
{
let
str
=
''
for
(
let
i
=
0
;
i
<
conditionList
.
length
;
i
++
)
{
...
...
@@ -163,7 +175,7 @@ export const removeEle = (arr, elem, key = 'id') => {
arr
.
splice
(
includesIndex
,
1
)
}
export
const
bgColors
=
[
'87, 106, 149'
,
'255, 148, 62'
,
'50, 150, 250'
]
export
const
bgColors
=
[
'87, 106, 149'
,
'255, 148, 62'
,
'50, 150, 250'
,
'50, 150, 250'
,
'248, 107, 248'
]
export
const
placeholderList
=
[
'发起人'
,
'审核人'
,
'抄送人'
]
export
const
setTypes
=
[
{
value
:
1
,
label
:
'指定成员'
},
...
...
src/components/SimpleProcessDesigner/theme/workflow.css
View file @
4f839136
...
...
@@ -1174,15 +1174,47 @@ html {
box-shadow
:
0
2px
5px
0
rgba
(
0
,
0
,
0
,
.1
)
}
.dingflow-design
.auto-judge
.title-wrapper
{
/*
.dingflow-design .auto-judge .title-wrapper {
position: relative;
font-size: 12px;
color: #15bc83;
text-align: left;
line-height
:
16px
height: 24px;
line-height: 24px;
width: 258px;
} */
.dingflow-design
.title-wrapper
{
display
:
flex
;
justify-content
:
space-between
;
align-items
:
center
;
position
:
relative
;
font-size
:
12px
;
border-radius
:
4px
4px
0
0
;
text-align
:
left
;
height
:
24px
;
line-height
:
24px
;
width
:
220px
;
color
:
#fff
;
}
.dingflow-design
.title-wrapper
.editable-title
{
max-width
:
120px
;
padding-left
:
10px
;
overflow
:
hidden
;
white-space
:
nowrap
;
text-overflow
:
ellipsis
}
.dingflow-design
.title-wrapper
.close
{
padding-right
:
10px
;
}
.dingflow-design
.auto-judge
.title-wrapper
.editable-title
{
/* .dingflow-design .title-wrapper .priority-title {
display: inline-block;
float: right;
margin-right: 10px;
color: rgba(25, 31, 37, .56)
} */
/* .dingflow-design .auto-judge .title-wrapper .editable-title {
display: inline-block;
max-width: 120px;
overflow: hidden;
...
...
@@ -1195,7 +1227,7 @@ html {
float: right;
margin-right: 10px;
color: rgba(25, 31, 37, .56)
}
}
*/
.dingflow-design
.auto-judge
.placeholder
{
color
:
#bfbfbf
...
...
src/views/bpm/simpleWorkflow/index.vue
View file @
4f839136
...
...
@@ -8,31 +8,17 @@
</el-col>
</el-row>
<div
class=
"box-scale"
>
<!--
<div
class=
"start-event-node"
>
<div
class=
"start-event-node-text"
>
流程开始
</div>
<div
class=
"start-event-node-circle"
></div>
<div
class=
"start-event-node-flow"
>
<el-popover
placement=
"right-start"
width=
"auto"
>
<div
class=
"add-node-popover-body"
>
<a
class=
"add-node-popover-item approver"
@
click=
"addType(1)"
>
<div
class=
"item-wrapper"
>
<span
class=
"iconfont"
>
</span>
</div>
<p>
审批人
</p>
</a>
</div>
<template
#
reference
>
<button
class=
"btn"
type=
"button"
>
<span
class=
"iconfont"
>
</span>
</button>
</
template
>
</el-popover>
</div>
</div>
-->
<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-node"
>
<
!--
<
div
class=
"end-node"
>
<div
class=
"end-node-circle"
></div>
<div
class=
"end-node-text"
>
流程结束
</div>
</div>
-->
<div
class=
"end-event"
>
<div
class=
"end-event-circle"
>
结束
</div>
</div>
</div>
</section>
...
...
@@ -41,8 +27,8 @@
</
template
>
<
script
lang=
"ts"
setup
>
import
nodeWrap
from
'@/components/SimpleProcessDesigner/src/nodeWrap.vue'
import
addNode
from
'@/components/SimpleProcessDesigner/src/addNode.vue'
import
approverDrawer
from
'@/components/SimpleProcessDesigner/src/drawer/approverDrawer.vue'
import
{
WorkFlowNode
}
from
'@/components/SimpleProcessDesigner/src/consts'
import
{
ref
}
from
'vue'
import
{
saveBpmSimpleModel
,
getBpmSimpleModel
}
from
'@/api/bpm/simple'
defineOptions
({
name
:
'SimpleWorkflowDesignEditor'
})
...
...
@@ -51,23 +37,34 @@ const router = useRouter() // 路由
const
{
query
}
=
useRoute
()
// 路由的查询
const
modelId
=
query
.
modelId
const
message
=
useMessage
()
// 国际化
const
nodeConfig
=
ref
({
name
:
'流程开始'
,
type
:
-
1
,
id
:
'StartEvent_'
+
uid
,
childNode
:
undefined
})
const
nodeConfig
=
ref
<
WorkFlowNode
>
({
name
:
'发起人'
,
type
:
0
,
id
:
'StartEvent_'
+
uid
,
childNode
:
undefined
,
attributes
:
undefined
,
conditionNodes
:
undefined
}
)
const
test
=
async
()
=>
{
if
(
!
modelId
)
{
message
.
error
(
'缺少模型 modelId 编号'
)
return
}
const
test
=
nodeConfig
.
value
;
console
.
log
(
'test is '
,
test
)
console
.
log
(
'nodeConfig.value '
,
nodeConfig
.
value
)
const
data
=
{
modelId
:
modelId
,
simpleModelBody
:
toRaw
(
nodeConfig
.
value
)
}
const
data1
=
{
modelId
:
modelId
,
simpleModelBody
:
nodeConfig
.
value
}
console
.
log
(
'request json data is '
,
data
)
const
result
=
await
saveBpmSimpleModel
(
data
)
console
.
log
(
'request json data1 is '
,
data1
)
const
result
=
await
saveBpmSimpleModel
(
data1
)
console
.
log
(
'save the result is '
,
result
)
if
(
result
)
{
message
.
success
(
'修改成功'
)
...
...
@@ -91,4 +88,63 @@ onMounted(async () => {
</
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