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
f470e0d6
authored
Jan 03, 2025
by
Lesan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: Simple设计器-延时器
parent
c144439e
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
347 additions
and
0 deletions
+347
-0
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
+17
-0
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
+7
-0
src/components/SimpleProcessDesignerV2/src/consts.ts
+36
-0
src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue
+189
-0
src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue
+98
-0
No files found.
src/components/SimpleProcessDesignerV2/src/NodeHandler.vue
View file @
f470e0d6
...
@@ -39,6 +39,13 @@
...
@@ -39,6 +39,13 @@
</div>
</div>
<div
class=
"handler-item-text"
>
包容分支
</div>
<div
class=
"handler-item-text"
>
包容分支
</div>
</div>
</div>
<div
class=
"handler-item"
@
click=
"addNode(NodeType.DELAY_TIMER_NODE)"
>
<!-- TODO @芋艿 需要更换一下iconfont的图标 -->
<div
class=
"handler-item-icon copy"
>
<span
class=
"iconfont icon-size icon-copy"
></span>
</div>
<div
class=
"handler-item-text"
>
延迟器
</div>
</div>
</div>
</div>
<template
#
reference
>
<template
#
reference
>
<div
class=
"add-icon"
><Icon
icon=
"ep:plus"
/></div>
<div
class=
"add-icon"
><Icon
icon=
"ep:plus"
/></div>
...
@@ -208,6 +215,16 @@ const addNode = (type: number) => {
...
@@ -208,6 +215,16 @@ const addNode = (type: number) => {
}
}
emits
(
'update:childNode'
,
data
)
emits
(
'update:childNode'
,
data
)
}
}
if
(
type
===
NodeType
.
DELAY_TIMER_NODE
)
{
const
data
:
SimpleFlowNode
=
{
id
:
'Activity_'
+
generateUUID
(),
name
:
NODE_DEFAULT_NAME
.
get
(
NodeType
.
DELAY_TIMER_NODE
)
as
string
,
showText
:
''
,
type
:
NodeType
.
DELAY_TIMER_NODE
,
childNode
:
props
.
childNode
}
emits
(
'update:childNode'
,
data
)
}
}
}
</
script
>
</
script
>
...
...
src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue
View file @
f470e0d6
...
@@ -38,6 +38,12 @@
...
@@ -38,6 +38,12 @@
@
update:model-value=
"handleModelValueUpdate"
@
update:model-value=
"handleModelValueUpdate"
@
find:parent-node=
"findFromParentNode"
@
find:parent-node=
"findFromParentNode"
/>
/>
<!-- 延迟器节点 -->
<DelayTimerNode
v-if=
"currentNode && currentNode.type === NodeType.DELAY_TIMER_NODE"
:flow-node=
"currentNode"
@
update:flow-node=
"handleModelValueUpdate"
/>
<!-- 递归显示孩子节点 -->
<!-- 递归显示孩子节点 -->
<ProcessNodeTree
<ProcessNodeTree
v-if=
"currentNode && currentNode.childNode"
v-if=
"currentNode && currentNode.childNode"
...
@@ -60,6 +66,7 @@ import CopyTaskNode from './nodes/CopyTaskNode.vue'
...
@@ -60,6 +66,7 @@ import CopyTaskNode from './nodes/CopyTaskNode.vue'
import
ExclusiveNode
from
'./nodes/ExclusiveNode.vue'
import
ExclusiveNode
from
'./nodes/ExclusiveNode.vue'
import
ParallelNode
from
'./nodes/ParallelNode.vue'
import
ParallelNode
from
'./nodes/ParallelNode.vue'
import
InclusiveNode
from
'./nodes/InclusiveNode.vue'
import
InclusiveNode
from
'./nodes/InclusiveNode.vue'
import
DelayTimerNode
from
'./nodes/DelayTimerNode.vue'
import
{
SimpleFlowNode
,
NodeType
}
from
'./consts'
import
{
SimpleFlowNode
,
NodeType
}
from
'./consts'
import
{
useWatchNode
}
from
'./node'
import
{
useWatchNode
}
from
'./node'
defineOptions
({
defineOptions
({
...
...
src/components/SimpleProcessDesignerV2/src/consts.ts
View file @
f470e0d6
...
@@ -24,6 +24,11 @@ export enum NodeType {
...
@@ -24,6 +24,11 @@ export enum NodeType {
COPY_TASK_NODE
=
12
,
COPY_TASK_NODE
=
12
,
/**
/**
* 延迟器节点
*/
DELAY_TIMER_NODE
=
13
,
/**
* 条件节点
* 条件节点
*/
*/
CONDITION_NODE
=
50
,
CONDITION_NODE
=
50
,
...
@@ -98,6 +103,8 @@ export interface SimpleFlowNode {
...
@@ -98,6 +103,8 @@ export interface SimpleFlowNode {
defaultFlow
?:
boolean
defaultFlow
?:
boolean
// 活动的状态,用于前端节点状态展示
// 活动的状态,用于前端节点状态展示
activityStatus
?:
TaskStatusEnum
activityStatus
?:
TaskStatusEnum
// 延迟设置
delaySetting
?:
DelaySetting
}
}
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
export
enum
CandidateStrategy
{
export
enum
CandidateStrategy
{
...
@@ -413,12 +420,14 @@ NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置审批人')
...
@@ -413,12 +420,14 @@ NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置审批人')
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
COPY_TASK_NODE
,
'请配置抄送人'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
COPY_TASK_NODE
,
'请配置抄送人'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
CONDITION_NODE
,
'请设置条件'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
CONDITION_NODE
,
'请设置条件'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
START_USER_NODE
,
'请设置发起人'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
START_USER_NODE
,
'请设置发起人'
)
NODE_DEFAULT_TEXT
.
set
(
NodeType
.
DELAY_TIMER_NODE
,
'请设置延迟器'
)
export
const
NODE_DEFAULT_NAME
=
new
Map
<
number
,
string
>
()
export
const
NODE_DEFAULT_NAME
=
new
Map
<
number
,
string
>
()
NODE_DEFAULT_NAME
.
set
(
NodeType
.
USER_TASK_NODE
,
'审批人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
USER_TASK_NODE
,
'审批人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
COPY_TASK_NODE
,
'抄送人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
COPY_TASK_NODE
,
'抄送人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
CONDITION_NODE
,
'条件'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
CONDITION_NODE
,
'条件'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
START_USER_NODE
,
'发起人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
START_USER_NODE
,
'发起人'
)
NODE_DEFAULT_NAME
.
set
(
NodeType
.
DELAY_TIMER_NODE
,
'延迟器'
)
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
export
const
CANDIDATE_STRATEGY
:
DictDataVO
[]
=
[
export
const
CANDIDATE_STRATEGY
:
DictDataVO
[]
=
[
...
@@ -568,3 +577,30 @@ export enum ProcessVariableEnum {
...
@@ -568,3 +577,30 @@ export enum ProcessVariableEnum {
*/
*/
START_USER_ID
=
'PROCESS_START_USER_ID'
START_USER_ID
=
'PROCESS_START_USER_ID'
}
}
/**
* 延迟设置
*/
export
type
DelaySetting
=
{
// 延迟类型
delayType
:
number
// 延迟时间表达式
delayTime
:
string
}
/**
* 延迟类型
*/
export
enum
DelayTypeEnum
{
/**
* 固定时长
*/
FIXED_TIME_DURATION
=
1
,
/**
* 固定日期时间
*/
FIXED_DATE_TIME
=
2
}
export
const
DELAY_TYPE
=
[
{
label
:
'固定时长'
,
value
:
DelayTypeEnum
.
FIXED_TIME_DURATION
},
{
label
:
'固定日期时间'
,
value
:
DelayTypeEnum
.
FIXED_DATE_TIME
}
]
src/components/SimpleProcessDesignerV2/src/nodes-config/DelayTimerNodeConfig.vue
0 → 100644
View file @
f470e0d6
<
template
>
<el-drawer
:append-to-body=
"true"
v-model=
"settingVisible"
:show-close=
"false"
:size=
"550"
:before-close=
"saveConfig"
>
<template
#
header
>
<div
class=
"config-header"
>
<input
v-if=
"showInput"
type=
"text"
class=
"config-editable-input"
@
blur=
"blurEvent()"
v-mountedFocus
v-model=
"nodeName"
:placeholder=
"nodeName"
/>
<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
>
<div>
<el-form
ref=
"formRef"
:model=
"configForm"
label-position=
"top"
:rules=
"formRules"
>
<el-form-item
label=
"延迟时间"
prop=
"delayType"
>
<el-radio-group
v-model=
"configForm.delayType"
>
<el-radio-button
v-for=
"item in DELAY_TYPE"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-radio-group>
</el-form-item>
<el-form-item
v-if=
"configForm.delayType === DelayTypeEnum.FIXED_TIME_DURATION"
>
<el-form-item
prop=
"timeDuration"
>
<el-input-number
class=
"mr-2"
:style=
"{ width: '100px' }"
v-model=
"configForm.timeDuration"
:min=
"1"
controls-position=
"right"
/>
</el-form-item>
<el-select
v-model=
"configForm.timeUnit"
class=
"mr-2"
:style=
"{ width: '100px' }"
>
<el-option
v-for=
"item in TIME_UNIT_TYPES"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
<el-text>
后进入下一节点
</el-text>
</el-form-item>
<el-form-item
v-if=
"configForm.delayType === DelayTypeEnum.FIXED_DATE_TIME"
prop=
"dateTime"
>
<el-date-picker
class=
"mr-2"
v-model=
"configForm.dateTime"
type=
"datetime"
placeholder=
"请选择日期和时间"
value-format=
"YYYY-MM-DDTHH:mm:ss"
/>
<el-text>
后进入下一节点
</el-text>
</el-form-item>
</el-form>
</div>
<
template
#
footer
>
<el-divider
/>
<div>
<el-button
type=
"primary"
@
click=
"saveConfig"
>
确 定
</el-button>
<el-button
@
click=
"closeDrawer"
>
取 消
</el-button>
</div>
</
template
>
</el-drawer>
</template>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
TIME_UNIT_TYPES
,
TimeUnitType
,
DelayTypeEnum
,
DELAY_TYPE
}
from
'../consts'
import
{
useWatchNode
,
useDrawer
,
useNodeName
}
from
'../node'
import
{
convertTimeUnit
}
from
'../utils'
defineOptions
({
name
:
'DelayTimerNodeConfig'
})
const
props
=
defineProps
({
flowNode
:
{
type
:
Object
as
()
=>
SimpleFlowNode
,
required
:
true
}
})
// 抽屉配置
const
{
settingVisible
,
closeDrawer
,
openDrawer
}
=
useDrawer
()
// 当前节点
const
currentNode
=
useWatchNode
(
props
)
// 节点名称
const
{
nodeName
,
showInput
,
clickIcon
,
blurEvent
}
=
useNodeName
(
NodeType
.
DELAY_TIMER_NODE
)
// 抄送人表单配置
const
formRef
=
ref
()
// 表单 Ref
// 表单校验规则
const
formRules
=
reactive
({
delayType
:
[{
required
:
true
,
message
:
'延迟时间不能为空'
,
trigger
:
'change'
}],
timeDuration
:
[{
required
:
true
,
message
:
'延迟时间不能为空'
,
trigger
:
'change'
}],
dateTime
:
[{
required
:
true
,
message
:
'延迟时间不能为空'
,
trigger
:
'change'
}]
})
// 配置表单数据
const
configForm
=
ref
({
delayType
:
DelayTypeEnum
.
FIXED_TIME_DURATION
,
timeDuration
:
1
,
timeUnit
:
TimeUnitType
.
HOUR
,
dateTime
:
''
})
// 保存配置
const
saveConfig
=
async
()
=>
{
if
(
!
formRef
)
return
false
const
valid
=
await
formRef
.
value
.
validate
()
if
(
!
valid
)
return
false
const
showText
=
getShowText
()
if
(
!
showText
)
return
false
currentNode
.
value
.
showText
=
showText
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_TIME_DURATION
)
{
currentNode
.
value
.
delaySetting
=
{
delayType
:
configForm
.
value
.
delayType
,
delayTime
:
getIsoTimeDuration
()
}
}
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_DATE_TIME
)
{
currentNode
.
value
.
delaySetting
=
{
delayType
:
configForm
.
value
.
delayType
,
delayTime
:
configForm
.
value
.
dateTime
}
}
settingVisible
.
value
=
false
return
true
}
const
getShowText
=
():
string
=>
{
let
showText
=
''
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_TIME_DURATION
)
{
showText
=
`延迟
${
configForm
.
value
.
timeDuration
}${
TIME_UNIT_TYPES
.
find
((
item
)
=>
item
.
value
===
configForm
.
value
.
timeUnit
).
label
}
`
}
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_DATE_TIME
)
{
showText
=
`延迟至
${
configForm
.
value
.
dateTime
.
replace
(
'T'
,
' '
)}
`
}
return
showText
}
const
getIsoTimeDuration
=
()
=>
{
let
strTimeDuration
=
'PT'
if
(
configForm
.
value
.
timeUnit
===
TimeUnitType
.
MINUTE
)
{
strTimeDuration
+=
configForm
.
value
.
timeDuration
+
'M'
}
if
(
configForm
.
value
.
timeUnit
===
TimeUnitType
.
HOUR
)
{
strTimeDuration
+=
configForm
.
value
.
timeDuration
+
'H'
}
if
(
configForm
.
value
.
timeUnit
===
TimeUnitType
.
DAY
)
{
strTimeDuration
+=
configForm
.
value
.
timeDuration
+
'D'
}
return
strTimeDuration
}
// 显示延迟器节点配置, 由父组件传过来
const
showDelayTimerNodeConfig
=
(
node
:
SimpleFlowNode
)
=>
{
nodeName
.
value
=
node
.
name
if
(
node
.
delaySetting
)
{
configForm
.
value
.
delayType
=
node
.
delaySetting
.
delayType
// 固定时长
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_TIME_DURATION
)
{
const
strTimeDuration
=
node
.
delaySetting
.
delayTime
let
parseTime
=
strTimeDuration
.
slice
(
2
,
strTimeDuration
.
length
-
1
)
let
parseTimeUnit
=
strTimeDuration
.
slice
(
strTimeDuration
.
length
-
1
)
configForm
.
value
.
timeDuration
=
parseInt
(
parseTime
)
configForm
.
value
.
timeUnit
=
convertTimeUnit
(
parseTimeUnit
)
}
// 固定日期时间
if
(
configForm
.
value
.
delayType
===
DelayTypeEnum
.
FIXED_DATE_TIME
)
{
configForm
.
value
.
dateTime
=
node
.
delaySetting
.
delayTime
}
}
}
defineExpose
({
openDrawer
,
showDelayTimerNodeConfig
})
// 暴露方法给父组件
</
script
>
<
style
lang=
"scss"
scoped
></
style
>
src/components/SimpleProcessDesignerV2/src/nodes/DelayTimerNode.vue
0 → 100644
View file @
f470e0d6
<
template
>
<div
class=
"node-wrapper"
>
<div
class=
"node-container"
>
<div
class=
"node-box"
:class=
"[
{ 'node-config-error': !currentNode.showText },
`${useTaskStatusClass(currentNode?.activityStatus)}`
]"
>
<div
class=
"node-title-container"
>
<!-- TODO @芋艿 需要更换图标 -->
<div
class=
"node-title-icon copy-task"
><span
class=
"iconfont icon-copy"
></span></div>
<input
v-if=
"!readonly && showInput"
type=
"text"
class=
"editable-title-input"
@
blur=
"blurEvent()"
v-mountedFocus
v-model=
"currentNode.name"
:placeholder=
"currentNode.name"
/>
<div
v-else
class=
"node-title"
@
click=
"clickTitle"
>
{{
currentNode
.
name
}}
</div>
</div>
<div
class=
"node-content"
@
click=
"openNodeConfig"
>
<div
class=
"node-text"
:title=
"currentNode.showText"
v-if=
"currentNode.showText"
>
{{
currentNode
.
showText
}}
</div>
<div
class=
"node-text"
v-else
>
{{
NODE_DEFAULT_TEXT
.
get
(
NodeType
.
DELAY_TIMER_NODE
)
}}
</div>
<Icon
v-if=
"!readonly"
icon=
"ep:arrow-right-bold"
/>
</div>
<div
v-if=
"!readonly"
class=
"node-toolbar"
>
<div
class=
"toolbar-icon"
><Icon
color=
"#0089ff"
icon=
"ep:circle-close-filled"
:size=
"18"
@
click=
"deleteNode"
/></div>
</div>
</div>
<!-- 传递子节点给添加节点组件。会在子节点前面添加节点 -->
<NodeHandler
v-if=
"currentNode"
v-model:child-node=
"currentNode.childNode"
:current-node=
"currentNode"
/>
</div>
<DelayTimerNodeConfig
v-if=
"!readonly && currentNode"
ref=
"nodeSetting"
:flow-node=
"currentNode"
/>
</div>
</
template
>
<
script
setup
lang=
"ts"
>
import
{
SimpleFlowNode
,
NodeType
,
NODE_DEFAULT_TEXT
}
from
'../consts'
import
NodeHandler
from
'../NodeHandler.vue'
import
{
useNodeName2
,
useWatchNode
,
useTaskStatusClass
}
from
'../node'
import
DelayTimerNodeConfig
from
'../nodes-config/DelayTimerNodeConfig.vue'
defineOptions
({
name
:
'DelayTimerNode'
})
const
props
=
defineProps
({
flowNode
:
{
type
:
Object
as
()
=>
SimpleFlowNode
,
required
:
true
}
})
// 定义事件,更新父组件。
const
emits
=
defineEmits
<
{
'update:flowNode'
:
[
node
:
SimpleFlowNode
|
undefined
]
}
>
()
// 是否只读
const
readonly
=
inject
<
Boolean
>
(
'readonly'
)
// 监控节点的变化
const
currentNode
=
useWatchNode
(
props
)
// 节点名称编辑
const
{
showInput
,
blurEvent
,
clickTitle
}
=
useNodeName2
(
currentNode
,
NodeType
.
DELAY_TIMER_NODE
)
const
nodeSetting
=
ref
()
// 打开节点配置
const
openNodeConfig
=
()
=>
{
if
(
readonly
)
{
return
}
nodeSetting
.
value
.
showDelayTimerNodeConfig
(
currentNode
.
value
)
nodeSetting
.
value
.
openDrawer
()
}
// 删除节点。更新当前节点为孩子节点
const
deleteNode
=
()
=>
{
emits
(
'update:flowNode'
,
currentNode
.
value
.
childNode
)
}
</
script
>
<
style
lang=
"scss"
scoped
></
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