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