Skip to content

Commit 49fc9b5

Browse files
committed
2 parents 2a9290c + 5198b2e commit 49fc9b5

File tree

10 files changed

+355
-427
lines changed

10 files changed

+355
-427
lines changed

src/assets/svgs/bpm/delay.svg

Lines changed: 1 addition & 0 deletions
Loading

src/components/SimpleProcessDesignerV2/src/NodeHandler.vue

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,13 @@
3939
</div>
4040
<div class="handler-item-text">包容分支</div>
4141
</div>
42+
<div class="handler-item" @click="addNode(NodeType.DELAY_TIMER_NODE)">
43+
<!-- TODO @芋艿 需要更换一下iconfont的图标 -->
44+
<div class="handler-item-icon copy">
45+
<span class="iconfont icon-size icon-copy"></span>
46+
</div>
47+
<div class="handler-item-text">延迟器</div>
48+
</div>
4249
</div>
4350
<template #reference>
4451
<div class="add-icon"><Icon icon="ep:plus" /></div>
@@ -208,6 +215,16 @@ const addNode = (type: number) => {
208215
}
209216
emits('update:childNode', data)
210217
}
218+
if (type === NodeType.DELAY_TIMER_NODE) {
219+
const data: SimpleFlowNode = {
220+
id: 'Activity_' + generateUUID(),
221+
name: NODE_DEFAULT_NAME.get(NodeType.DELAY_TIMER_NODE) as string,
222+
showText: '',
223+
type: NodeType.DELAY_TIMER_NODE,
224+
childNode: props.childNode
225+
}
226+
emits('update:childNode', data)
227+
}
211228
}
212229
</script>
213230

src/components/SimpleProcessDesignerV2/src/ProcessNodeTree.vue

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@
3838
@update:model-value="handleModelValueUpdate"
3939
@find:parent-node="findFromParentNode"
4040
/>
41+
<!-- 延迟器节点 -->
42+
<DelayTimerNode
43+
v-if="currentNode && currentNode.type === NodeType.DELAY_TIMER_NODE"
44+
:flow-node="currentNode"
45+
@update:flow-node="handleModelValueUpdate"
46+
/>
4147
<!-- 递归显示孩子节点 -->
4248
<ProcessNodeTree
4349
v-if="currentNode && currentNode.childNode"
@@ -60,6 +66,7 @@ import CopyTaskNode from './nodes/CopyTaskNode.vue'
6066
import ExclusiveNode from './nodes/ExclusiveNode.vue'
6167
import ParallelNode from './nodes/ParallelNode.vue'
6268
import InclusiveNode from './nodes/InclusiveNode.vue'
69+
import DelayTimerNode from './nodes/DelayTimerNode.vue'
6370
import { SimpleFlowNode, NodeType } from './consts'
6471
import { useWatchNode } from './node'
6572
defineOptions({

src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ defineOptions({
4040
name: 'SimpleProcessDesigner'
4141
})
4242
43-
const emits = defineEmits(['success']) // 保存成功事件
43+
const emits = defineEmits(['success', 'init-finished']) // 保存成功事件
4444
4545
const props = defineProps({
4646
modelId: {
@@ -263,6 +263,7 @@ onMounted(async () => {
263263
}
264264
} finally {
265265
loading.value = false
266+
emits('init-finished')
266267
}
267268
})
268269

src/components/SimpleProcessDesignerV2/src/consts.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ export enum NodeType {
2323
*/
2424
COPY_TASK_NODE = 12,
2525

26+
/**
27+
* 延迟器节点
28+
*/
29+
DELAY_TIMER_NODE = 14,
30+
2631
/**
2732
* 条件节点
2833
*/
@@ -98,6 +103,8 @@ export interface SimpleFlowNode {
98103
defaultFlow?: boolean
99104
// 活动的状态,用于前端节点状态展示
100105
activityStatus?: TaskStatusEnum
106+
// 延迟设置
107+
delaySetting?: DelaySetting
101108
}
102109
// 候选人策略枚举 ( 用于审批节点。抄送节点 )
103110
export enum CandidateStrategy {
@@ -413,12 +420,14 @@ NODE_DEFAULT_TEXT.set(NodeType.USER_TASK_NODE, '请配置审批人')
413420
NODE_DEFAULT_TEXT.set(NodeType.COPY_TASK_NODE, '请配置抄送人')
414421
NODE_DEFAULT_TEXT.set(NodeType.CONDITION_NODE, '请设置条件')
415422
NODE_DEFAULT_TEXT.set(NodeType.START_USER_NODE, '请设置发起人')
423+
NODE_DEFAULT_TEXT.set(NodeType.DELAY_TIMER_NODE, '请设置延迟器')
416424

417425
export const NODE_DEFAULT_NAME = new Map<number, string>()
418426
NODE_DEFAULT_NAME.set(NodeType.USER_TASK_NODE, '审批人')
419427
NODE_DEFAULT_NAME.set(NodeType.COPY_TASK_NODE, '抄送人')
420428
NODE_DEFAULT_NAME.set(NodeType.CONDITION_NODE, '条件')
421429
NODE_DEFAULT_NAME.set(NodeType.START_USER_NODE, '发起人')
430+
NODE_DEFAULT_NAME.set(NodeType.DELAY_TIMER_NODE, '延迟器')
422431

423432
// 候选人策略。暂时不从字典中取。 后续可能调整。控制显示顺序
424433
export const CANDIDATE_STRATEGY: DictDataVO[] = [
@@ -568,3 +577,30 @@ export enum ProcessVariableEnum {
568577
*/
569578
START_USER_ID = 'PROCESS_START_USER_ID'
570579
}
580+
581+
/**
582+
* 延迟设置
583+
*/
584+
export type DelaySetting = {
585+
// 延迟类型
586+
delayType: number
587+
// 延迟时间表达式
588+
delayTime: string
589+
}
590+
/**
591+
* 延迟类型
592+
*/
593+
export enum DelayTypeEnum {
594+
/**
595+
* 固定时长
596+
*/
597+
FIXED_TIME_DURATION = 1,
598+
/**
599+
* 固定日期时间
600+
*/
601+
FIXED_DATE_TIME = 2
602+
}
603+
export const DELAY_TYPE = [
604+
{ label: '固定时长', value: DelayTypeEnum.FIXED_TIME_DURATION },
605+
{ label: '固定日期', value: DelayTypeEnum.FIXED_DATE_TIME }
606+
]
Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
<template>
2+
<el-drawer
3+
:append-to-body="true"
4+
v-model="settingVisible"
5+
:show-close="false"
6+
:size="550"
7+
:before-close="saveConfig"
8+
>
9+
<template #header>
10+
<div class="config-header">
11+
<input
12+
v-if="showInput"
13+
type="text"
14+
class="config-editable-input"
15+
@blur="blurEvent()"
16+
v-mountedFocus
17+
v-model="nodeName"
18+
:placeholder="nodeName"
19+
/>
20+
<div v-else class="node-name">
21+
{{ nodeName }} <Icon class="ml-1" icon="ep:edit-pen" :size="16" @click="clickIcon()" />
22+
</div>
23+
<div class="divide-line"></div>
24+
</div>
25+
</template>
26+
<div>
27+
<el-form ref="formRef" :model="configForm" label-position="top" :rules="formRules">
28+
<el-form-item label="延迟时间" prop="delayType">
29+
<el-radio-group v-model="configForm.delayType">
30+
<el-radio-button
31+
v-for="item in DELAY_TYPE"
32+
:key="item.value"
33+
:label="item.label"
34+
:value="item.value"
35+
/>
36+
</el-radio-group>
37+
</el-form-item>
38+
<el-form-item v-if="configForm.delayType === DelayTypeEnum.FIXED_TIME_DURATION">
39+
<el-form-item prop="timeDuration">
40+
<el-input-number
41+
class="mr-2"
42+
:style="{ width: '100px' }"
43+
v-model="configForm.timeDuration"
44+
:min="1"
45+
controls-position="right"
46+
/>
47+
</el-form-item>
48+
<el-select v-model="configForm.timeUnit" class="mr-2" :style="{ width: '100px' }">
49+
<el-option
50+
v-for="item in TIME_UNIT_TYPES"
51+
:key="item.value"
52+
:label="item.label"
53+
:value="item.value"
54+
/>
55+
</el-select>
56+
<el-text>后进入下一节点</el-text>
57+
</el-form-item>
58+
<el-form-item v-if="configForm.delayType === DelayTypeEnum.FIXED_DATE_TIME" prop="dateTime">
59+
<el-date-picker
60+
class="mr-2"
61+
v-model="configForm.dateTime"
62+
type="datetime"
63+
placeholder="请选择日期和时间"
64+
value-format="YYYY-MM-DDTHH:mm:ss"
65+
/>
66+
<el-text>后进入下一节点</el-text>
67+
</el-form-item>
68+
</el-form>
69+
</div>
70+
<template #footer>
71+
<el-divider />
72+
<div>
73+
<el-button type="primary" @click="saveConfig">确 定</el-button>
74+
<el-button @click="closeDrawer">取 消</el-button>
75+
</div>
76+
</template>
77+
</el-drawer>
78+
</template>
79+
<script setup lang="ts">
80+
import {
81+
SimpleFlowNode,
82+
NodeType,
83+
TIME_UNIT_TYPES,
84+
TimeUnitType,
85+
DelayTypeEnum,
86+
DELAY_TYPE
87+
} from '../consts'
88+
import { useWatchNode, useDrawer, useNodeName } from '../node'
89+
import { convertTimeUnit } from '../utils'
90+
defineOptions({
91+
name: 'DelayTimerNodeConfig'
92+
})
93+
const props = defineProps({
94+
flowNode: {
95+
type: Object as () => SimpleFlowNode,
96+
required: true
97+
}
98+
})
99+
// 抽屉配置
100+
const { settingVisible, closeDrawer, openDrawer } = useDrawer()
101+
// 当前节点
102+
const currentNode = useWatchNode(props)
103+
// 节点名称
104+
const { nodeName, showInput, clickIcon, blurEvent } = useNodeName(NodeType.DELAY_TIMER_NODE)
105+
// 抄送人表单配置
106+
const formRef = ref() // 表单 Ref
107+
// 表单校验规则
108+
const formRules = reactive({
109+
delayType: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
110+
timeDuration: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }],
111+
dateTime: [{ required: true, message: '延迟时间不能为空', trigger: 'change' }]
112+
})
113+
// 配置表单数据
114+
const configForm = ref({
115+
delayType: DelayTypeEnum.FIXED_TIME_DURATION,
116+
timeDuration: 1,
117+
timeUnit: TimeUnitType.HOUR,
118+
dateTime: ''
119+
})
120+
// 保存配置
121+
const saveConfig = async () => {
122+
if (!formRef) return false
123+
const valid = await formRef.value.validate()
124+
if (!valid) return false
125+
const showText = getShowText()
126+
if (!showText) return false
127+
currentNode.value.showText = showText
128+
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
129+
currentNode.value.delaySetting = {
130+
delayType: configForm.value.delayType,
131+
delayTime: getIsoTimeDuration()
132+
}
133+
}
134+
if (configForm.value.delayType === DelayTypeEnum.FIXED_DATE_TIME) {
135+
currentNode.value.delaySetting = {
136+
delayType: configForm.value.delayType,
137+
delayTime: configForm.value.dateTime
138+
}
139+
}
140+
settingVisible.value = false
141+
return true
142+
}
143+
const getShowText = (): string => {
144+
let showText = ''
145+
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
146+
showText = `延迟${configForm.value.timeDuration}${TIME_UNIT_TYPES.find((item) => item.value === configForm.value.timeUnit).label}`
147+
}
148+
if (configForm.value.delayType === DelayTypeEnum.FIXED_DATE_TIME) {
149+
showText = `延迟至${configForm.value.dateTime.replace('T', ' ')}`
150+
}
151+
return showText
152+
}
153+
const getIsoTimeDuration = () => {
154+
let strTimeDuration = 'PT'
155+
if (configForm.value.timeUnit === TimeUnitType.MINUTE) {
156+
strTimeDuration += configForm.value.timeDuration + 'M'
157+
}
158+
if (configForm.value.timeUnit === TimeUnitType.HOUR) {
159+
strTimeDuration += configForm.value.timeDuration + 'H'
160+
}
161+
if (configForm.value.timeUnit === TimeUnitType.DAY) {
162+
strTimeDuration += configForm.value.timeDuration + 'D'
163+
}
164+
return strTimeDuration
165+
}
166+
// 显示延迟器节点配置, 由父组件传过来
167+
const showDelayTimerNodeConfig = (node: SimpleFlowNode) => {
168+
nodeName.value = node.name
169+
if (node.delaySetting) {
170+
configForm.value.delayType = node.delaySetting.delayType
171+
// 固定时长
172+
if (configForm.value.delayType === DelayTypeEnum.FIXED_TIME_DURATION) {
173+
const strTimeDuration = node.delaySetting.delayTime
174+
let parseTime = strTimeDuration.slice(2, strTimeDuration.length - 1)
175+
let parseTimeUnit = strTimeDuration.slice(strTimeDuration.length - 1)
176+
configForm.value.timeDuration = parseInt(parseTime)
177+
configForm.value.timeUnit = convertTimeUnit(parseTimeUnit)
178+
}
179+
// 固定日期时间
180+
if (configForm.value.delayType === DelayTypeEnum.FIXED_DATE_TIME) {
181+
configForm.value.dateTime = node.delaySetting.delayTime
182+
}
183+
}
184+
}
185+
186+
defineExpose({ openDrawer, showDelayTimerNodeConfig }) // 暴露方法给父组件
187+
</script>
188+
189+
<style lang="scss" scoped></style>

0 commit comments

Comments
 (0)