潘志宝
9 天以前 273cb85713ed1d194eb4cc245daf29cd33be89e7
提交 | 用户 | 时间
820397 1 <template>
H 2   <div class="panel-tab__content">
3     <el-table :data="elementListenersList" size="small" border>
4       <el-table-column label="序号" width="50px" type="index" />
5       <el-table-column label="事件类型" min-width="100px" prop="event" />
6       <el-table-column
7         label="监听器类型"
8         min-width="100px"
9         show-overflow-tooltip
10         :formatter="(row) => listenerTypeObject[row.listenerType]"
11       />
12       <el-table-column label="操作" width="100px">
13         <template #default="scope">
14           <el-button size="small" link @click="openListenerForm(scope.row, scope.$index)"
15             >编辑</el-button
16           >
17           <el-divider direction="vertical" />
18           <el-button size="small" link style="color: #ff4d4f" @click="removeListener(scope.$index)"
19             >移除</el-button
20           >
21         </template>
22       </el-table-column>
23     </el-table>
24     <div class="element-drawer__button">
25       <XButton
26         type="primary"
27         preIcon="ep:plus"
28         title="添加监听器"
29         size="small"
30         @click="openListenerForm(null)"
31       />
32       <XButton
33         type="success"
34         preIcon="ep:select"
35         title="选择监听器"
36         size="small"
37         @click="openProcessListenerDialog"
38       />
39     </div>
40
41     <!-- 监听器 编辑/创建 部分 -->
42     <el-drawer
43       v-model="listenerFormModelVisible"
44       title="执行监听器"
45       :size="`${width}px`"
46       append-to-body
47       destroy-on-close
48     >
49       <el-form :model="listenerForm" label-width="96px" ref="listenerFormRef">
50         <el-form-item
51           label="事件类型"
52           prop="event"
53           :rules="{ required: true, trigger: ['blur', 'change'] }"
54         >
55           <el-select v-model="listenerForm.event">
56             <el-option label="start" value="start" />
57             <el-option label="end" value="end" />
58           </el-select>
59         </el-form-item>
60         <el-form-item
61           label="监听器类型"
62           prop="listenerType"
63           :rules="{ required: true, trigger: ['blur', 'change'] }"
64         >
65           <el-select v-model="listenerForm.listenerType">
66             <el-option
67               v-for="i in Object.keys(listenerTypeObject)"
68               :key="i"
69               :label="listenerTypeObject[i]"
70               :value="i"
71             />
72           </el-select>
73         </el-form-item>
74         <el-form-item
75           v-if="listenerForm.listenerType === 'classListener'"
76           label="Java类"
77           prop="class"
78           key="listener-class"
79           :rules="{ required: true, trigger: ['blur', 'change'] }"
80         >
81           <el-input v-model="listenerForm.class" clearable />
82         </el-form-item>
83         <el-form-item
84           v-if="listenerForm.listenerType === 'expressionListener'"
85           label="表达式"
86           prop="expression"
87           key="listener-expression"
88           :rules="{ required: true, trigger: ['blur', 'change'] }"
89         >
90           <el-input v-model="listenerForm.expression" clearable />
91         </el-form-item>
92         <el-form-item
93           v-if="listenerForm.listenerType === 'delegateExpressionListener'"
94           label="代理表达式"
95           prop="delegateExpression"
96           key="listener-delegate"
97           :rules="{ required: true, trigger: ['blur', 'change'] }"
98         >
99           <el-input v-model="listenerForm.delegateExpression" clearable />
100         </el-form-item>
101         <template v-if="listenerForm.listenerType === 'scriptListener'">
102           <el-form-item
103             label="脚本格式"
104             prop="scriptFormat"
105             key="listener-script-format"
106             :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }"
107           >
108             <el-input v-model="listenerForm.scriptFormat" clearable />
109           </el-form-item>
110           <el-form-item
111             label="脚本类型"
112             prop="scriptType"
113             key="listener-script-type"
114             :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }"
115           >
116             <el-select v-model="listenerForm.scriptType">
117               <el-option label="内联脚本" value="inlineScript" />
118               <el-option label="外部脚本" value="externalScript" />
119             </el-select>
120           </el-form-item>
121           <el-form-item
122             v-if="listenerForm.scriptType === 'inlineScript'"
123             label="脚本内容"
124             prop="value"
125             key="listener-script"
126             :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }"
127           >
128             <el-input v-model="listenerForm.value" clearable />
129           </el-form-item>
130           <el-form-item
131             v-if="listenerForm.scriptType === 'externalScript'"
132             label="资源地址"
133             prop="resource"
134             key="listener-resource"
135             :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }"
136           >
137             <el-input v-model="listenerForm.resource" clearable />
138           </el-form-item>
139         </template>
140       </el-form>
141       <el-divider />
142       <p class="listener-filed__title">
143         <span><Icon icon="ep:menu" />注入字段:</span>
144         <XButton type="primary" @click="openListenerFieldForm(null)" title="添加字段" />
145       </p>
146       <el-table
147         :data="fieldsListOfListener"
148         size="small"
149         max-height="240"
150         fit
151         border
152         style="flex: none"
153       >
154         <el-table-column label="序号" width="50px" type="index" />
155         <el-table-column label="字段名称" min-width="100px" prop="name" />
156         <el-table-column
157           label="字段类型"
158           min-width="80px"
159           show-overflow-tooltip
160           :formatter="(row) => fieldTypeObject[row.fieldType]"
161         />
162         <el-table-column
163           label="字段值/表达式"
164           min-width="100px"
165           show-overflow-tooltip
166           :formatter="(row) => row.string || row.expression"
167         />
168         <el-table-column label="操作" width="130px">
169           <template #default="scope">
170             <el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)"
171               >编辑</el-button
172             >
173             <el-divider direction="vertical" />
174             <el-button
175               size="small"
176               link
177               style="color: #ff4d4f"
178               @click="removeListenerField(scope.$index)"
179               >移除</el-button
180             >
181           </template>
182         </el-table-column>
183       </el-table>
184
185       <div class="element-drawer__button">
186         <el-button @click="listenerFormModelVisible = false">取 消</el-button>
187         <el-button type="primary" @click="saveListenerConfig">保 存</el-button>
188       </div>
189     </el-drawer>
190
191     <!-- 注入西段 编辑/创建 部分 -->
192     <el-dialog
193       title="字段配置"
194       v-model="listenerFieldFormModelVisible"
195       width="600px"
196       append-to-body
197       destroy-on-close
198     >
199       <el-form
200         :model="listenerFieldForm"
201         label-width="96spx"
202         ref="listenerFieldFormRef"
203         style="height: 136px"
204       >
205         <el-form-item
206           label="字段名称:"
207           prop="name"
208           :rules="{ required: true, trigger: ['blur', 'change'] }"
209         >
210           <el-input v-model="listenerFieldForm.name" clearable />
211         </el-form-item>
212         <el-form-item
213           label="字段类型:"
214           prop="fieldType"
215           :rules="{ required: true, trigger: ['blur', 'change'] }"
216         >
217           <el-select v-model="listenerFieldForm.fieldType">
218             <el-option
219               v-for="i in Object.keys(fieldTypeObject)"
220               :key="i"
221               :label="fieldTypeObject[i]"
222               :value="i"
223             />
224           </el-select>
225         </el-form-item>
226         <el-form-item
227           v-if="listenerFieldForm.fieldType === 'string'"
228           label="字段值:"
229           prop="string"
230           key="field-string"
231           :rules="{ required: true, trigger: ['blur', 'change'] }"
232         >
233           <el-input v-model="listenerFieldForm.string" clearable />
234         </el-form-item>
235         <el-form-item
236           v-if="listenerFieldForm.fieldType === 'expression'"
237           label="表达式:"
238           prop="expression"
239           key="field-expression"
240           :rules="{ required: true, trigger: ['blur', 'change'] }"
241         >
242           <el-input v-model="listenerFieldForm.expression" clearable />
243         </el-form-item>
244       </el-form>
245       <template #footer>
246         <el-button size="small" @click="listenerFieldFormModelVisible = false">取 消</el-button>
247         <el-button size="small" type="primary" @click="saveListenerFiled">确 定</el-button>
248       </template>
249     </el-dialog>
250   </div>
251
252   <!-- 选择弹窗 -->
253   <ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
254 </template>
255 <script lang="ts" setup>
256 import { ElMessageBox } from 'element-plus'
257 import { createListenerObject, updateElementExtensions } from '../../utils'
258 import {
259   initListenerType,
260   initListenerForm,
261   listenerType,
262   fieldType,
263   initListenerForm2
264 } from './utilSelf'
265 import ProcessListenerDialog from './ProcessListenerDialog.vue'
266
267 defineOptions({ name: 'ElementListeners' })
268
269 const props = defineProps({
270   id: String,
271   type: String
272 })
273 const prefix = inject('prefix')
274 const width = inject('width')
275 const elementListenersList = ref<any[]>([]) // 监听器列表
276 const listenerForm = ref<any>({}) // 监听器详情表单
277 const listenerFormModelVisible = ref(false) // 监听器 编辑 侧边栏显示状态
278 const fieldsListOfListener = ref<any[]>([])
279 const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单
280 const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态
281 const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增
282 const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增
283 const listenerTypeObject = ref(listenerType)
284 const fieldTypeObject = ref(fieldType)
285 const bpmnElement = ref()
286 const otherExtensionList = ref()
287 const bpmnElementListeners = ref()
288 const listenerFormRef = ref()
289 const listenerFieldFormRef = ref()
290 const bpmnInstances = () => (window as any)?.bpmnInstances
291
292 const resetListenersList = () => {
293   bpmnElement.value = bpmnInstances().bpmnElement
294   otherExtensionList.value = []
295   bpmnElementListeners.value =
296     bpmnElement.value.businessObject?.extensionElements?.values?.filter(
297       (ex) => ex.$type === `${prefix}:ExecutionListener`
298     ) ?? []
299   elementListenersList.value = bpmnElementListeners.value.map((listener) =>
300     initListenerType(listener)
301   )
302 }
303 // 打开 监听器详情 侧边栏
304 const openListenerForm = (listener, index?) => {
305   // debugger
306   if (listener) {
307     listenerForm.value = initListenerForm(listener)
308     editingListenerIndex.value = index
309   } else {
310     listenerForm.value = {}
311     editingListenerIndex.value = -1 // 标记为新增
312   }
313   if (listener && listener.fields) {
314     fieldsListOfListener.value = listener.fields.map((field) => ({
315       ...field,
316       fieldType: field.string ? 'string' : 'expression'
317     }))
318   } else {
319     fieldsListOfListener.value = []
320     listenerForm.value['fields'] = []
321   }
322   // 打开侧边栏并清楚验证状态
323   listenerFormModelVisible.value = true
324   nextTick(() => {
325     if (listenerFormRef.value) {
326       listenerFormRef.value.clearValidate()
327     }
328   })
329 }
330 // 打开监听器字段编辑弹窗
331 const openListenerFieldForm = (field, index?) => {
332   listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
333   editingListenerFieldIndex.value = field ? index : -1
334   listenerFieldFormModelVisible.value = true
335   nextTick(() => {
336     if (listenerFieldFormRef.value) {
337       listenerFieldFormRef.value.clearValidate()
338     }
339   })
340 }
341 // 保存监听器注入字段
342 const saveListenerFiled = async () => {
343   // debugger
344   let validateStatus = await listenerFieldFormRef.value.validate()
345   if (!validateStatus) return // 验证不通过直接返回
346   if (editingListenerFieldIndex.value === -1) {
347     fieldsListOfListener.value.push(listenerFieldForm.value)
348     listenerForm.value.fields.push(listenerFieldForm.value)
349   } else {
350     fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
351     listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
352   }
353   listenerFieldFormModelVisible.value = false
354   nextTick(() => {
355     listenerFieldForm.value = {}
356   })
357 }
358 // 移除监听器字段
359 const removeListenerField = (index) => {
360   // debugger
361   ElMessageBox.confirm('确认移除该字段吗?', '提示', {
362     confirmButtonText: '确 认',
363     cancelButtonText: '取 消'
364   })
365     .then(() => {
366       fieldsListOfListener.value.splice(index, 1)
367       listenerForm.value.fields.splice(index, 1)
368     })
369     .catch(() => console.info('操作取消'))
370 }
371 // 移除监听器
372 const removeListener = (index) => {
3e359e 373   debugger
820397 374   ElMessageBox.confirm('确认移除该监听器吗?', '提示', {
H 375     confirmButtonText: '确 认',
376     cancelButtonText: '取 消'
377   })
378     .then(() => {
379       bpmnElementListeners.value.splice(index, 1)
380       elementListenersList.value.splice(index, 1)
381       updateElementExtensions(
382         bpmnElement.value,
383         otherExtensionList.value.concat(bpmnElementListeners.value)
384       )
385     })
386     .catch(() => console.info('操作取消'))
387 }
388 // 保存监听器配置
389 const saveListenerConfig = async () => {
390   // debugger
391   let validateStatus = await listenerFormRef.value.validate()
392   if (!validateStatus) return // 验证不通过直接返回
393   const listenerObject = createListenerObject(listenerForm.value, false, prefix)
394   if (editingListenerIndex.value === -1) {
395     bpmnElementListeners.value.push(listenerObject)
396     elementListenersList.value.push(listenerForm.value)
397   } else {
398     bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
399     elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
400   }
401   // 保存其他配置
402   otherExtensionList.value =
403     bpmnElement.value.businessObject?.extensionElements?.values?.filter(
404       (ex) => ex.$type !== `${prefix}:ExecutionListener`
405     ) ?? []
406   updateElementExtensions(
407     bpmnElement.value,
408     otherExtensionList.value.concat(bpmnElementListeners.value)
409   )
410   // 4. 隐藏侧边栏
411   listenerFormModelVisible.value = false
412   listenerForm.value = {}
413 }
414
415 // 打开监听器弹窗
416 const processListenerDialogRef = ref()
417 const openProcessListenerDialog = async () => {
418   processListenerDialogRef.value.open('execution')
419 }
420 const selectProcessListener = (listener) => {
421   const listenerForm = initListenerForm2(listener)
422   const listenerObject = createListenerObject(listenerForm, false, prefix)
423   bpmnElementListeners.value.push(listenerObject)
424   elementListenersList.value.push(listenerForm)
425
426   // 保存其他配置
427   otherExtensionList.value =
428     bpmnElement.value.businessObject?.extensionElements?.values?.filter(
429       (ex) => ex.$type !== `${prefix}:ExecutionListener`
430     ) ?? []
431   updateElementExtensions(
432     bpmnElement.value,
433     otherExtensionList.value.concat(bpmnElementListeners.value)
434   )
435 }
436
437 watch(
438   () => props.id,
439   (val) => {
440     val &&
441       val.length &&
442       nextTick(() => {
443         resetListenersList()
444       })
445   },
446   { immediate: true }
447 )
448 </script>