workflow-bpmn-modeler-andtv-vue3 10.1.2 → 10.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fonts/bpmn.5d33bee4.eot +0 -0
- package/dist/fonts/bpmn.67058807.woff2 +0 -0
- package/dist/fonts/bpmn.b5c9250d.ttf +0 -0
- package/dist/fonts/bpmn.e9e7d076.woff +0 -0
- package/dist/img/bpmn.74eea12b.svg +224 -0
- package/dist/workflow-bpmn-modeler-andtv-vue3.common.js +199 -5
- package/dist/workflow-bpmn-modeler-andtv-vue3.umd.js +199 -5
- package/dist/workflow-bpmn-modeler-andtv-vue3.umd.min.js +199 -5
- package/package/CHANGELOG.md +6 -0
- package/package/LICENSE +21 -0
- package/package/README.md +208 -0
- package/package/components/nodePanel/process.vue +9 -2
- package/package/components/nodePanel/startEnd.vue +6 -2
- package/package/dist/demo.html +9 -0
- package/package/dist/fonts/bpmn.5d33bee4.eot +0 -0
- package/package/dist/fonts/bpmn.67058807.woff2 +0 -0
- package/package/dist/fonts/bpmn.b5c9250d.ttf +0 -0
- package/package/dist/fonts/bpmn.e9e7d076.woff +0 -0
- package/package/dist/img/bpmn.74eea12b.svg +224 -0
- package/package/dist/workflow-bpmn-modeler-andtv-vue3.common.js +5617 -0
- package/package/dist/workflow-bpmn-modeler-andtv-vue3.umd.js +5617 -0
- package/package/dist/workflow-bpmn-modeler-andtv-vue3.umd.min.js +5617 -0
- package/package/index.vue +91 -471
- package/package/package/BpmData.js +68 -0
- package/package/package/PropertyPanel.vue +342 -0
- package/package/package/common/customTranslate.js +20 -0
- package/package/package/common/mixinExecutionListener.js +24 -0
- package/package/package/common/mixinPanel.js +70 -0
- package/package/package/common/mixinXcrud.js +22 -0
- package/package/package/common/parseElement.js +53 -0
- package/package/package/components/custom/customContextPad.vue +24 -0
- package/package/package/components/nodePanel/gateway.vue +165 -0
- package/package/package/components/nodePanel/process.vue +201 -0
- package/package/package/components/nodePanel/property/executionListener.vue +240 -0
- package/package/package/components/nodePanel/property/listenerParam.vue +137 -0
- package/package/package/components/nodePanel/property/multiInstance.vue +177 -0
- package/package/package/components/nodePanel/property/signal.vue +178 -0
- package/package/package/components/nodePanel/property/taskListener.vue +242 -0
- package/package/package/components/nodePanel/sequenceFlow.vue +180 -0
- package/package/package/components/nodePanel/startEnd.vue +174 -0
- package/package/package/components/nodePanel/task.vue +452 -0
- package/package/package/flowable/flowable.json +1218 -0
- package/package/package/flowable/init.js +24 -0
- package/package/package/flowable/showConfig.js +51 -0
- package/package/package/index.js +9 -0
- package/package/package/index.ts +10 -0
- package/package/package/index.vue +730 -0
- package/package/package/lang/zh.js +227 -0
- package/package/package/types/components.d.ts +35 -0
- package/package/package.json +89 -0
- package/package.json +12 -13
- package/package/bpmn-styles.css +0 -40
@@ -0,0 +1,165 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<a-form ref="formRef" :model="formData" layout="horizontal">
|
4
|
+
<a-form-item label="节点 id" name="id" :rules="[{ required: true, message: 'Id 不能为空' }]">
|
5
|
+
<a-input v-model:value="formData.id" />
|
6
|
+
</a-form-item>
|
7
|
+
|
8
|
+
<a-form-item label="节点名称" name="name">
|
9
|
+
<a-input v-model:value="formData.name" />
|
10
|
+
</a-form-item>
|
11
|
+
|
12
|
+
<a-form-item label="节点描述" name="documentation">
|
13
|
+
<a-textarea v-model:value="formData.documentation" />
|
14
|
+
</a-form-item>
|
15
|
+
|
16
|
+
<a-form-item label="执行监听器">
|
17
|
+
<a-badge :count="executionListenerLength">
|
18
|
+
<a-button size="small" @click="dialogName = 'executionListenerDialog'">编辑</a-button>
|
19
|
+
</a-badge>
|
20
|
+
</a-form-item>
|
21
|
+
|
22
|
+
<a-form-item label="异步" name="async">
|
23
|
+
<a-switch v-model:checked="formData.async" checked-children="是" un-checked-children="否" />
|
24
|
+
</a-form-item>
|
25
|
+
</a-form>
|
26
|
+
|
27
|
+
<executionListenerDialog
|
28
|
+
v-if="dialogName === 'executionListenerDialog'"
|
29
|
+
:element="element"
|
30
|
+
:modeler="modeler"
|
31
|
+
@close="finishExecutionListener"
|
32
|
+
/>
|
33
|
+
</div>
|
34
|
+
</template>
|
35
|
+
|
36
|
+
<script setup lang="ts">
|
37
|
+
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
38
|
+
import { FormInstance } from 'ant-design-vue'
|
39
|
+
import executionListenerDialog from './property/executionListener.vue'
|
40
|
+
import { commonParse } from '../../common/parseElement'
|
41
|
+
import showConfigData from '../../flowable/showConfig'
|
42
|
+
import Modeler from 'bpmn-js/lib/Modeler'
|
43
|
+
|
44
|
+
defineOptions({
|
45
|
+
name: 'GatewayPanel'
|
46
|
+
})
|
47
|
+
|
48
|
+
interface Props {
|
49
|
+
modeler: Modeler
|
50
|
+
element: any
|
51
|
+
}
|
52
|
+
|
53
|
+
const props = defineProps<Props>()
|
54
|
+
|
55
|
+
const formRef = ref<FormInstance>()
|
56
|
+
const dialogName = ref('')
|
57
|
+
const executionListenerLength = ref(0)
|
58
|
+
const formData = ref<Record<string, any>>({})
|
59
|
+
|
60
|
+
const elementType = computed(() => {
|
61
|
+
const bizObj = props.element.businessObject
|
62
|
+
return bizObj.eventDefinitions
|
63
|
+
? bizObj.eventDefinitions[0].$type
|
64
|
+
: bizObj.$type
|
65
|
+
})
|
66
|
+
|
67
|
+
const showConfig = computed(() => (showConfigData as any)[elementType.value] || {})
|
68
|
+
|
69
|
+
const updateProperties = (properties: Record<string, any>) => {
|
70
|
+
nextTick(() => {
|
71
|
+
try {
|
72
|
+
const modeling = props.modeler.get('modeling')
|
73
|
+
modeling.updateProperties(props.element, properties)
|
74
|
+
} catch (error) {
|
75
|
+
console.warn('Update properties error:', error)
|
76
|
+
}
|
77
|
+
})
|
78
|
+
}
|
79
|
+
|
80
|
+
const computedExecutionListenerLength = () => {
|
81
|
+
if (props.element?.businessObject?.extensionElements?.values) {
|
82
|
+
executionListenerLength.value = props.element.businessObject.extensionElements.values
|
83
|
+
.filter((item: any) => item.$type === 'flowable:ExecutionListener').length
|
84
|
+
} else {
|
85
|
+
executionListenerLength.value = 0
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
const finishExecutionListener = () => {
|
90
|
+
if (dialogName.value === 'executionListenerDialog') {
|
91
|
+
computedExecutionListenerLength()
|
92
|
+
}
|
93
|
+
dialogName.value = ''
|
94
|
+
}
|
95
|
+
|
96
|
+
// Watch for form data changes
|
97
|
+
watch(() => formData.value.async, (val) => {
|
98
|
+
if (val === '') val = null
|
99
|
+
updateProperties({ 'flowable:async': val })
|
100
|
+
})
|
101
|
+
|
102
|
+
watch(() => formData.value.id, (val) => {
|
103
|
+
updateProperties({ id: val })
|
104
|
+
})
|
105
|
+
|
106
|
+
watch(() => formData.value.name, (val) => {
|
107
|
+
updateProperties({ name: val })
|
108
|
+
})
|
109
|
+
|
110
|
+
watch(() => formData.value.documentation, (val) => {
|
111
|
+
if (!val) {
|
112
|
+
updateProperties({ documentation: [] })
|
113
|
+
return
|
114
|
+
}
|
115
|
+
if (props.modeler?.get('moddle')) {
|
116
|
+
const documentationElement = props.modeler.get('moddle').create('bpmn:Documentation', { text: val })
|
117
|
+
updateProperties({ documentation: [documentationElement] })
|
118
|
+
}
|
119
|
+
})
|
120
|
+
|
121
|
+
onMounted(() => {
|
122
|
+
if (props.element) {
|
123
|
+
formData.value = commonParse(props.element)
|
124
|
+
computedExecutionListenerLength()
|
125
|
+
}
|
126
|
+
})
|
127
|
+
</script>
|
128
|
+
|
129
|
+
<style scoped>
|
130
|
+
.flow-containers {
|
131
|
+
padding: 0;
|
132
|
+
background: transparent;
|
133
|
+
min-height: 100%;
|
134
|
+
}
|
135
|
+
|
136
|
+
.flow-containers :deep(.ant-form-item) {
|
137
|
+
margin-bottom: 16px;
|
138
|
+
}
|
139
|
+
|
140
|
+
.flow-containers :deep(.ant-form-item-label) {
|
141
|
+
font-weight: 500;
|
142
|
+
color: #262626;
|
143
|
+
}
|
144
|
+
|
145
|
+
.flow-containers :deep(.ant-input),
|
146
|
+
.flow-containers :deep(.ant-select),
|
147
|
+
.flow-containers :deep(.ant-textarea) {
|
148
|
+
border-radius: 6px;
|
149
|
+
transition: all 0.3s;
|
150
|
+
}
|
151
|
+
|
152
|
+
.flow-containers :deep(.ant-button) {
|
153
|
+
border-radius: 6px;
|
154
|
+
font-weight: 500;
|
155
|
+
}
|
156
|
+
|
157
|
+
.flow-containers :deep(.ant-badge) {
|
158
|
+
margin-right: 8px;
|
159
|
+
}
|
160
|
+
|
161
|
+
.flow-containers :deep(.ant-badge .ant-badge-count) {
|
162
|
+
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
|
163
|
+
box-shadow: 0 2px 4px rgba(255, 77, 79, 0.3);
|
164
|
+
}
|
165
|
+
</style>
|
@@ -0,0 +1,201 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<a-form ref="formRef" :model="formData" layout="horizontal">
|
4
|
+
<a-form-item label="流程分类" name="processCategory">
|
5
|
+
<a-select v-model:value="formData.processCategory" :options="categoryOptions" />
|
6
|
+
</a-form-item>
|
7
|
+
|
8
|
+
<a-form-item label="流程标识key" name="id" :rules="[{ required: true, message: 'Id 不能为空' }]">
|
9
|
+
<a-input v-model:value="formData.id" />
|
10
|
+
</a-form-item>
|
11
|
+
|
12
|
+
<a-form-item label="流程名称" name="name">
|
13
|
+
<a-input v-model:value="formData.name" />
|
14
|
+
</a-form-item>
|
15
|
+
|
16
|
+
<a-form-item label="节点描述" name="documentation">
|
17
|
+
<a-textarea v-model:value="formData.documentation" />
|
18
|
+
</a-form-item>
|
19
|
+
|
20
|
+
<a-form-item label="执行监听器">
|
21
|
+
<a-badge :count="executionListenerLength">
|
22
|
+
<a-button size="small" @click="dialogName = 'executionListenerDialog'">编辑</a-button>
|
23
|
+
</a-badge>
|
24
|
+
</a-form-item>
|
25
|
+
|
26
|
+
<a-form-item label="信号定义">
|
27
|
+
<a-badge :count="signalLength">
|
28
|
+
<a-button size="small" @click="dialogName = 'signalDialog'">编辑</a-button>
|
29
|
+
</a-badge>
|
30
|
+
</a-form-item>
|
31
|
+
</a-form>
|
32
|
+
|
33
|
+
<executionListenerDialog
|
34
|
+
v-if="dialogName === 'executionListenerDialog'"
|
35
|
+
:element="element"
|
36
|
+
:modeler="modeler"
|
37
|
+
@close="finishExecutionListener"
|
38
|
+
/>
|
39
|
+
<signalDialog
|
40
|
+
v-if="dialogName === 'signalDialog'"
|
41
|
+
:element="element"
|
42
|
+
:modeler="modeler"
|
43
|
+
@close="finishSignal"
|
44
|
+
/>
|
45
|
+
</div>
|
46
|
+
</template>
|
47
|
+
|
48
|
+
<script setup lang="ts">
|
49
|
+
import { ref, computed, watch, onMounted, nextTick } from 'vue'
|
50
|
+
import { FormInstance } from 'ant-design-vue'
|
51
|
+
import executionListenerDialog from './property/executionListener.vue'
|
52
|
+
import signalDialog from './property/signal.vue'
|
53
|
+
import { commonParse } from '../../common/parseElement'
|
54
|
+
import showConfigData from '../../flowable/showConfig'
|
55
|
+
import Modeler from 'bpmn-js/lib/Modeler'
|
56
|
+
|
57
|
+
defineOptions({
|
58
|
+
name: 'ProcessPanel'
|
59
|
+
})
|
60
|
+
|
61
|
+
interface Category {
|
62
|
+
name: string
|
63
|
+
id: string
|
64
|
+
}
|
65
|
+
|
66
|
+
interface Props {
|
67
|
+
categorys: Category[]
|
68
|
+
modeler: Modeler
|
69
|
+
element: any
|
70
|
+
}
|
71
|
+
|
72
|
+
const props = defineProps<Props>()
|
73
|
+
|
74
|
+
const formRef = ref<FormInstance>()
|
75
|
+
const dialogName = ref('')
|
76
|
+
const executionListenerLength = ref(0)
|
77
|
+
const signalLength = ref(0)
|
78
|
+
const formData = ref<Record<string, any>>({})
|
79
|
+
|
80
|
+
const elementType = computed(() => {
|
81
|
+
const bizObj = props.element.businessObject
|
82
|
+
return bizObj.eventDefinitions
|
83
|
+
? bizObj.eventDefinitions[0].$type
|
84
|
+
: bizObj.$type
|
85
|
+
})
|
86
|
+
|
87
|
+
const showConfig = computed(() => (showConfigData as any)[elementType.value] || {})
|
88
|
+
|
89
|
+
const categoryOptions = computed(() =>
|
90
|
+
props.categorys.map(category => ({ label: category.name, value: category.id }))
|
91
|
+
)
|
92
|
+
|
93
|
+
const updateProperties = (properties: Record<string, any>) => {
|
94
|
+
nextTick(() => {
|
95
|
+
try {
|
96
|
+
const modeling = props.modeler.get('modeling')
|
97
|
+
modeling.updateProperties(props.element, properties)
|
98
|
+
} catch (error) {
|
99
|
+
console.warn('Update properties error:', error)
|
100
|
+
}
|
101
|
+
})
|
102
|
+
}
|
103
|
+
|
104
|
+
const computedExecutionListenerLength = () => {
|
105
|
+
if (props.element?.businessObject?.extensionElements?.values) {
|
106
|
+
executionListenerLength.value = props.element.businessObject.extensionElements.values
|
107
|
+
.filter((item: any) => item.$type === 'flowable:ExecutionListener').length
|
108
|
+
} else {
|
109
|
+
executionListenerLength.value = 0
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
const computedSignalLength = () => {
|
114
|
+
signalLength.value = props.element?.businessObject?.extensionElements?.values?.length ?? 0
|
115
|
+
}
|
116
|
+
|
117
|
+
const finishExecutionListener = () => {
|
118
|
+
if (dialogName.value === 'executionListenerDialog') {
|
119
|
+
computedExecutionListenerLength()
|
120
|
+
}
|
121
|
+
dialogName.value = ''
|
122
|
+
}
|
123
|
+
|
124
|
+
const finishSignal = () => {
|
125
|
+
if (dialogName.value === 'signalDialog') {
|
126
|
+
computedSignalLength()
|
127
|
+
}
|
128
|
+
dialogName.value = ''
|
129
|
+
}
|
130
|
+
|
131
|
+
// Watch for form data changes
|
132
|
+
watch(() => formData.value.processCategory, (val) => {
|
133
|
+
if (val === '') val = null
|
134
|
+
updateProperties({ 'flowable:processCategory': val })
|
135
|
+
})
|
136
|
+
|
137
|
+
watch(() => formData.value.id, (val) => {
|
138
|
+
updateProperties({ id: val })
|
139
|
+
})
|
140
|
+
|
141
|
+
watch(() => formData.value.name, (val) => {
|
142
|
+
updateProperties({ name: val })
|
143
|
+
})
|
144
|
+
|
145
|
+
watch(() => formData.value.documentation, (val) => {
|
146
|
+
if (!val) {
|
147
|
+
updateProperties({ documentation: [] })
|
148
|
+
return
|
149
|
+
}
|
150
|
+
if (props.modeler?.get('moddle')) {
|
151
|
+
const documentationElement = props.modeler.get('moddle').create('bpmn:Documentation', { text: val })
|
152
|
+
updateProperties({ documentation: [documentationElement] })
|
153
|
+
}
|
154
|
+
})
|
155
|
+
|
156
|
+
onMounted(() => {
|
157
|
+
if (props.element) {
|
158
|
+
formData.value = commonParse(props.element)
|
159
|
+
computedExecutionListenerLength()
|
160
|
+
computedSignalLength()
|
161
|
+
}
|
162
|
+
})
|
163
|
+
</script>
|
164
|
+
|
165
|
+
<style scoped>
|
166
|
+
.flow-containers {
|
167
|
+
padding: 0;
|
168
|
+
background: transparent;
|
169
|
+
min-height: 100%;
|
170
|
+
}
|
171
|
+
|
172
|
+
.flow-containers :deep(.ant-form-item) {
|
173
|
+
margin-bottom: 16px;
|
174
|
+
}
|
175
|
+
|
176
|
+
.flow-containers :deep(.ant-form-item-label) {
|
177
|
+
font-weight: 500;
|
178
|
+
color: #262626;
|
179
|
+
}
|
180
|
+
|
181
|
+
.flow-containers :deep(.ant-input),
|
182
|
+
.flow-containers :deep(.ant-select),
|
183
|
+
.flow-containers :deep(.ant-textarea) {
|
184
|
+
border-radius: 6px;
|
185
|
+
transition: all 0.3s;
|
186
|
+
}
|
187
|
+
|
188
|
+
.flow-containers :deep(.ant-button) {
|
189
|
+
border-radius: 6px;
|
190
|
+
font-weight: 500;
|
191
|
+
}
|
192
|
+
|
193
|
+
.flow-containers :deep(.ant-badge) {
|
194
|
+
margin-right: 8px;
|
195
|
+
}
|
196
|
+
|
197
|
+
.flow-containers :deep(.ant-badge .ant-badge-count) {
|
198
|
+
background: linear-gradient(135deg, #ff4d4f 0%, #ff7875 100%);
|
199
|
+
box-shadow: 0 2px 4px rgba(255, 77, 79, 0.3);
|
200
|
+
}
|
201
|
+
</style>
|
@@ -0,0 +1,240 @@
|
|
1
|
+
<template>
|
2
|
+
<div>
|
3
|
+
<a-modal
|
4
|
+
v-model:open="dialogVisible"
|
5
|
+
title="执行监听器"
|
6
|
+
width="900px"
|
7
|
+
:mask-closable="false"
|
8
|
+
:keyboard="false"
|
9
|
+
:closable="false"
|
10
|
+
@cancel="$emit('close')"
|
11
|
+
>
|
12
|
+
<a-form ref="formRef" :model="formData" layout="vertical">
|
13
|
+
<a-tabs>
|
14
|
+
<a-tab-pane key="executionListener" tab="执行监听器">
|
15
|
+
<div style="margin-bottom: 16px;">
|
16
|
+
<a-button type="primary" size="small" @click="addExecutionListener">
|
17
|
+
<template #icon><PlusOutlined /></template>
|
18
|
+
添加执行监听器
|
19
|
+
</a-button>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<a-table
|
23
|
+
:columns="columns"
|
24
|
+
:data-source="formData.executionListener"
|
25
|
+
:pagination="false"
|
26
|
+
size="small"
|
27
|
+
>
|
28
|
+
<template #bodyCell="{ column, record, index }">
|
29
|
+
<template v-if="column.key === 'event'">
|
30
|
+
<a-select v-model:value="record.event" size="small" style="width: 100%">
|
31
|
+
<a-select-option value="start">start</a-select-option>
|
32
|
+
<a-select-option value="end">end</a-select-option>
|
33
|
+
<a-select-option value="take">take</a-select-option>
|
34
|
+
</a-select>
|
35
|
+
</template>
|
36
|
+
<template v-if="column.key === 'type'">
|
37
|
+
<a-select v-model:value="record.type" size="small" style="width: 100%">
|
38
|
+
<a-select-option value="class">class</a-select-option>
|
39
|
+
<a-select-option value="expression">expression</a-select-option>
|
40
|
+
<a-select-option value="delegateExpression">delegateExpression</a-select-option>
|
41
|
+
</a-select>
|
42
|
+
</template>
|
43
|
+
<template v-if="column.key === 'className'">
|
44
|
+
<a-input v-model:value="record.className" size="small" placeholder="请输入类名" />
|
45
|
+
</template>
|
46
|
+
<template v-if="column.key === 'params'">
|
47
|
+
<a-badge :count="record.params ? record.params.length : 0">
|
48
|
+
<a-button size="small" @click="configParam(index)">配置</a-button>
|
49
|
+
</a-badge>
|
50
|
+
</template>
|
51
|
+
<template v-if="column.key === 'action'">
|
52
|
+
<a-button type="link" danger size="small" @click="removeExecutionListener(index)">删除</a-button>
|
53
|
+
</template>
|
54
|
+
</template>
|
55
|
+
</a-table>
|
56
|
+
</a-tab-pane>
|
57
|
+
</a-tabs>
|
58
|
+
</a-form>
|
59
|
+
|
60
|
+
<template #footer>
|
61
|
+
<a-button type="primary" @click="closeDialog">确 定</a-button>
|
62
|
+
</template>
|
63
|
+
</a-modal>
|
64
|
+
|
65
|
+
<listenerParam v-if="showParamDialog && nowIndex !== null" :value="formData.executionListener[nowIndex]?.params" @close="finishConfigParam" />
|
66
|
+
</div>
|
67
|
+
</template>
|
68
|
+
|
69
|
+
<script setup lang="ts">
|
70
|
+
import { ref, computed, onMounted, nextTick } from 'vue'
|
71
|
+
import { FormInstance } from 'ant-design-vue'
|
72
|
+
import { PlusOutlined } from '@ant-design/icons-vue'
|
73
|
+
import listenerParam from './listenerParam.vue'
|
74
|
+
import Modeler from 'bpmn-js/lib/Modeler'
|
75
|
+
|
76
|
+
defineOptions({
|
77
|
+
name: 'ExecutionListenerDialog'
|
78
|
+
})
|
79
|
+
|
80
|
+
interface Props {
|
81
|
+
element: any
|
82
|
+
modeler: Modeler
|
83
|
+
}
|
84
|
+
|
85
|
+
const props = defineProps<Props>()
|
86
|
+
const emit = defineEmits<{
|
87
|
+
close: []
|
88
|
+
}>()
|
89
|
+
|
90
|
+
const formRef = ref<FormInstance>()
|
91
|
+
const dialogVisible = ref(true)
|
92
|
+
const showParamDialog = ref(false)
|
93
|
+
const nowIndex = ref<number | null>(null)
|
94
|
+
const formData = ref({
|
95
|
+
executionListener: [] as any[]
|
96
|
+
})
|
97
|
+
|
98
|
+
const columns = [
|
99
|
+
{
|
100
|
+
title: '事件',
|
101
|
+
dataIndex: 'event',
|
102
|
+
key: 'event',
|
103
|
+
width: 120
|
104
|
+
},
|
105
|
+
{
|
106
|
+
title: '类型',
|
107
|
+
dataIndex: 'type',
|
108
|
+
key: 'type',
|
109
|
+
width: 150
|
110
|
+
},
|
111
|
+
{
|
112
|
+
title: 'Java类名',
|
113
|
+
dataIndex: 'className',
|
114
|
+
key: 'className'
|
115
|
+
},
|
116
|
+
{
|
117
|
+
title: '参数',
|
118
|
+
key: 'params',
|
119
|
+
width: 100
|
120
|
+
},
|
121
|
+
{
|
122
|
+
title: '操作',
|
123
|
+
key: 'action',
|
124
|
+
width: 80
|
125
|
+
}
|
126
|
+
]
|
127
|
+
|
128
|
+
const updateProperties = (properties: Record<string, any>) => {
|
129
|
+
nextTick(() => {
|
130
|
+
try {
|
131
|
+
const modeling = props.modeler.get('modeling')
|
132
|
+
modeling.updateProperties(props.element, properties)
|
133
|
+
} catch (error) {
|
134
|
+
}
|
135
|
+
})
|
136
|
+
}
|
137
|
+
|
138
|
+
const addExecutionListener = () => {
|
139
|
+
formData.value.executionListener.push({
|
140
|
+
event: 'start',
|
141
|
+
type: 'class',
|
142
|
+
className: '',
|
143
|
+
params: []
|
144
|
+
})
|
145
|
+
}
|
146
|
+
|
147
|
+
const removeExecutionListener = (index: number) => {
|
148
|
+
formData.value.executionListener.splice(index, 1)
|
149
|
+
}
|
150
|
+
|
151
|
+
const configParam = (index: number) => {
|
152
|
+
nowIndex.value = index
|
153
|
+
const nowObj = formData.value.executionListener[index]
|
154
|
+
if (!nowObj.params) {
|
155
|
+
nowObj.params = []
|
156
|
+
}
|
157
|
+
showParamDialog.value = true
|
158
|
+
}
|
159
|
+
|
160
|
+
const finishConfigParam = (param: any) => {
|
161
|
+
showParamDialog.value = false
|
162
|
+
if (nowIndex.value !== null) {
|
163
|
+
const cache = formData.value.executionListener[nowIndex.value]
|
164
|
+
cache.params = param
|
165
|
+
formData.value.executionListener[nowIndex.value] = { ...cache }
|
166
|
+
}
|
167
|
+
nowIndex.value = null
|
168
|
+
}
|
169
|
+
|
170
|
+
const updateElement = () => {
|
171
|
+
if (formData.value.executionListener?.length) {
|
172
|
+
let extensionElements = props.element.businessObject.get('extensionElements')
|
173
|
+
if (!extensionElements) {
|
174
|
+
extensionElements = props.modeler.get('moddle').create('bpmn:ExtensionElements')
|
175
|
+
}
|
176
|
+
// 清除旧值
|
177
|
+
extensionElements.values = extensionElements.values?.filter((item: any) => item.$type !== 'flowable:ExecutionListener') ?? []
|
178
|
+
formData.value.executionListener.forEach((item: any) => {
|
179
|
+
const executionListener = props.modeler.get('moddle').create('flowable:ExecutionListener')
|
180
|
+
executionListener['event'] = item.event
|
181
|
+
executionListener[item.type] = item.className
|
182
|
+
if (item.params && item.params.length) {
|
183
|
+
item.params.forEach((field: any) => {
|
184
|
+
const fieldElement = props.modeler.get('moddle').create('flowable:Field')
|
185
|
+
fieldElement['name'] = field.name
|
186
|
+
fieldElement[field.type] = field.value
|
187
|
+
executionListener.get('fields').push(fieldElement)
|
188
|
+
})
|
189
|
+
}
|
190
|
+
extensionElements.get('values').push(executionListener)
|
191
|
+
})
|
192
|
+
updateProperties({ extensionElements: extensionElements })
|
193
|
+
} else {
|
194
|
+
const extensionElements = props.element.businessObject[`extensionElements`]
|
195
|
+
if (extensionElements) {
|
196
|
+
extensionElements.values = extensionElements.values?.filter((item: any) => item.$type !== 'flowable:ExecutionListener') ?? []
|
197
|
+
}
|
198
|
+
}
|
199
|
+
}
|
200
|
+
|
201
|
+
const closeDialog = () => {
|
202
|
+
updateElement()
|
203
|
+
dialogVisible.value = false
|
204
|
+
emit('close')
|
205
|
+
}
|
206
|
+
|
207
|
+
onMounted(() => {
|
208
|
+
if (props.element?.businessObject?.extensionElements?.values) {
|
209
|
+
formData.value.executionListener = props.element.businessObject.extensionElements.values
|
210
|
+
.filter((item: any) => item.$type === 'flowable:ExecutionListener')
|
211
|
+
.map((item: any) => {
|
212
|
+
let type
|
213
|
+
if ('class' in item) type = 'class'
|
214
|
+
if ('expression' in item) type = 'expression'
|
215
|
+
if ('delegateExpression' in item) type = 'delegateExpression'
|
216
|
+
return {
|
217
|
+
event: item.event,
|
218
|
+
type: type,
|
219
|
+
className: type ? item[type] : '',
|
220
|
+
params: item.fields?.map((field: any) => {
|
221
|
+
let fieldType
|
222
|
+
if ('stringValue' in field) fieldType = 'stringValue'
|
223
|
+
if ('expression' in field) fieldType = 'expression'
|
224
|
+
return {
|
225
|
+
name: field.name,
|
226
|
+
type: fieldType,
|
227
|
+
value: fieldType ? field[fieldType] : ''
|
228
|
+
}
|
229
|
+
}) ?? []
|
230
|
+
}
|
231
|
+
})
|
232
|
+
}
|
233
|
+
})
|
234
|
+
</script>
|
235
|
+
|
236
|
+
<style scoped>
|
237
|
+
.flow-containers .ant-badge {
|
238
|
+
margin-right: 8px;
|
239
|
+
}
|
240
|
+
</style>
|