更多ruoyi-nbcio功能请看演示系统
gitee源代码地址
前后端代码: https://gitee.com/nbacheng/ruoyi-nbcio
演示地址:RuoYi-Nbcio后台管理系统 http://218.75.87.38:9666/
更多nbcio-boot功能请看演示系统
gitee源代码地址
后端代码: https://gitee.com/nbacheng/nbcio-boot
前端代码:https://gitee.com/nbacheng/nbcio-vue.git
在线演示(包括H5) : http://218.75.87.38:9888
1、执行监听器的vue2代码如下:
<template> <div class="panel-tab__content"> <el-table :data="elementListenersList" size="small" border> <el-table-column label="序号" width="50px" type="index" /> <el-table-column label="事件类型" min-width="100px" prop="event" /> <el-table-column label="监听器类型" min-width="100px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" /> <el-table-column label="操作" width="90px"> <template v-slot="{ row, $index }"> <el-button link type="" @click="openListenerForm(row, $index)">编辑</el-button> <el-divider direction="vertical" /> <el-button link type="" style="color: #ff4d4f" @click="removeListener(row, $index)">移除</el-button> </template> </el-table-column> </el-table> <div class="element-drawer__button"> <el-button size="small" type="primary" :icon="Plus" @click="openListenerForm(null)">添加监听器</el-button> </div> <!-- 监听器 编辑/创建 部分 --> <el-drawer v-model="listenerFormModelVisible" title="执行监听器" :size="`${width}px`" append-to-body destroy-on-close> <el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.prevent> <el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerForm.event"> <el-option label="start" value="start" /> <el-option label="end" value="end" /> </el-select> </el-form-item> <el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerForm.listenerType"> <el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" /> </el-select> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'classListener'" label="Java类" prop="class" key="listener-class" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.class" clearable /> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'expressionListener'" label="表达式" prop="expression" key="listener-expression" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.expression" clearable /> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'delegateExpressionListener'" label="代理表达式" prop="delegateExpression" key="listener-delegate" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.delegateExpression" clearable /> </el-form-item> <template v-if="listenerForm.listenerType === 'scriptListener'"> <el-form-item label="脚本格式" prop="scriptFormat" key="listener-script-format" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }" > <el-input v-model="listenerForm.scriptFormat" clearable /> </el-form-item> <el-form-item label="脚本类型" prop="scriptType" key="listener-script-type" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }" > <el-select v-model="listenerForm.scriptType"> <el-option label="内联脚本" value="inlineScript" /> <el-option label="外部脚本" value="externalScript" /> </el-select> </el-form-item> <el-form-item v-if="listenerForm.scriptType === 'inlineScript'" label="脚本内容" prop="value" key="listener-script" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }" > <el-input v-model="listenerForm.value" clearable /> </el-form-item> <el-form-item v-if="listenerForm.scriptType === 'externalScript'" label="资源地址" prop="resource" key="listener-resource" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }" > <el-input v-model="listenerForm.resource" clearable /> </el-form-item> </template> </el-form> <el-divider /> <p class="listener-filed__title"> <span><el-icon><Menu /></el-icon>注入字段:</span> <el-button size="small" type="primary" @click="openListenerFieldForm(null)">添加字段</el-button> </p> <el-table :data="fieldsListOfListener" size="small" max-height="240" border fit style="flex: none"> <el-table-column label="序号" width="50px" type="index" /> <el-table-column label="字段名称" min-width="100px" prop="name" /> <el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" /> <el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" /> <el-table-column label="操作" width="100px"> <template v-slot="{ row, $index }"> <el-button link type="" @click="openListenerFieldForm(row, $index)">编辑</el-button> <el-divider direction="vertical" /> <el-button link type="" style="color: #ff4d4f" @click="removeListenerField(row, $index)">移除</el-button> </template> </el-table-column> </el-table> <div class="element-drawer__button"> <el-button size="small" @click="listenerFormModelVisible = false">取 消</el-button> <el-button size="small" type="primary" @click="saveListenerConfig">保 存</el-button> </div> </el-drawer> <!-- 注入西段 编辑/创建 部分 --> <el-dialog title="字段配置" v-model="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close> <el-form :model="listenerFieldForm" size="small" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.prevent> <el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-input v-model="listenerFieldForm.name" clearable /> </el-form-item> <el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerFieldForm.fieldType"> <el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" /> </el-select> </el-form-item> <el-form-item v-if="listenerFieldForm.fieldType === 'string'" label="字段值:" prop="string" key="field-string" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerFieldForm.string" clearable /> </el-form-item> <el-form-item v-if="listenerFieldForm.fieldType === 'expression'" label="表达式:" prop="expression" key="field-expression" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerFieldForm.expression" clearable /> </el-form-item> </el-form> <template v-slot:footer> <el-button size="small" @click="listenerFieldFormModelVisible = false">取 消</el-button> <el-button size="small" type="primary" @click="saveListenerFiled">确 定</el-button> </template> </el-dialog> </div> </template> <script> import { createListenerObject, updateElementExtensions } from "../../utils"; import { initListenerType, initListenerForm, listenerType, fieldType } from "./utilSelf"; import { Plus } from '@element-plus/icons-vue' export default { name: "ElementListeners", setup() { return { Plus } }, props: { id: String, type: String }, inject: { prefix: "prefix", width: "width" }, data() { return { elementListenersList: [], // 监听器列表 listenerForm: {}, // 监听器详情表单 listenerFormModelVisible: false, // 监听器 编辑 侧边栏显示状态 fieldsListOfListener: [], listenerFieldForm: {}, // 监听器 注入字段 详情表单 listenerFieldFormModelVisible: false, // 监听器 注入字段表单弹窗 显示状态 editingListenerIndex: -1, // 监听器所在下标,-1 为新增 editingListenerFieldIndex: -1, // 字段所在下标,-1 为新增 listenerTypeObject: listenerType, fieldTypeObject: fieldType }; }, watch: { id: { immediate: true, handler(val) { val && val.length && this.$nextTick(() => this.resetListenersList()); } } }, methods: { resetListenersList() { this.bpmnElement = window.bpmnInstances.bpmnElement; this.otherExtensionList = []; this.bpmnElementListeners = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type === `${this.prefix}:ExecutionListener`) ?? []; this.elementListenersList = this.bpmnElementListeners.map(listener => initListenerType(listener)); }, // 打开 监听器详情 侧边栏 openListenerForm(listener, index) { if (listener) { this.listenerForm = initListenerForm(listener); this.editingListenerIndex = index; } else { this.listenerForm = {}; this.editingListenerIndex = -1; // 标记为新增 } if (listener && listener.fields) { this.fieldsListOfListener = listener.fields.map(field => ({ ...field, fieldType: field.string ? "string" : "expression" })); } else { this.fieldsListOfListener = []; this.listenerForm["fields"] = [] } // 打开侧边栏并清楚验证状态 this.listenerFormModelVisible = true; this.$nextTick(() => { if (this.$refs["listenerFormRef"]) this.$refs["listenerFormRef"].clearValidate(); }); }, // 打开监听器字段编辑弹窗 openListenerFieldForm(field, index) { this.listenerFieldForm = field ? JSON.parse(JSON.stringify(field)) : {}; this.editingListenerFieldIndex = field ? index : -1; this.listenerFieldFormModelVisible = true; this.$nextTick(() => { if (this.$refs["listenerFieldFormRef"]) this.$refs["listenerFieldFormRef"].clearValidate(); }); }, // 保存监听器注入字段 async saveListenerFiled() { let validateStatus = await this.$refs["listenerFieldFormRef"].validate(); if (!validateStatus) return; // 验证不通过直接返回 if (this.editingListenerFieldIndex === -1) { this.fieldsListOfListener.push(this.listenerFieldForm); this.listenerForm.fields.push(this.listenerFieldForm); } else { this.fieldsListOfListener.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm); this.listenerForm.fields.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm); } this.listenerFieldFormModelVisible = false; this.$nextTick(() => (this.listenerFieldForm = {})); }, // 移除监听器字段 removeListenerField(field, index) { this.$confirm("确认移除该字段吗?", "提示", { confirmButtonText: "确 认", cancelButtonText: "取 消" }) .then(() => { this.fieldsListOfListener.splice(index, 1); this.listenerForm.fields.splice(index, 1); }) .catch(() => console.info("操作取消")); }, // 移除监听器 removeListener(listener, index) { this.$confirm("确认移除该监听器吗?", "提示", { confirmButtonText: "确 认", cancelButtonText: "取 消" }) .then(() => { this.bpmnElementListeners.splice(index, 1); this.elementListenersList.splice(index, 1); updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners)); }) .catch(() => console.info("操作取消")); }, // 保存监听器配置 async saveListenerConfig() { let validateStatus = await this.$refs["listenerFormRef"].validate(); if (!validateStatus) return; // 验证不通过直接返回 const listenerObject = createListenerObject(this.listenerForm, false, this.prefix); if (this.editingListenerIndex === -1) { this.bpmnElementListeners.push(listenerObject); this.elementListenersList.push(this.listenerForm); } else { this.bpmnElementListeners.splice(this.editingListenerIndex, 1, listenerObject); this.elementListenersList.splice(this.editingListenerIndex, 1, this.listenerForm); } // 保存其他配置 this.otherExtensionList = this.bpmnElement.businessObject?.extensionElements?.values?.filter(ex => ex.$type !== `${this.prefix}:ExecutionListener`) ?? []; updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners)); // 4. 隐藏侧边栏 this.listenerFormModelVisible = false; this.listenerForm = {}; } } }; </script>
2、修改后的vue3代码如下:
<template> <div class="panel-tab__content"> <el-table :data="elementListenersList" size="small" border> <el-table-column label="序号" width="50px" type="index" /> <el-table-column label="事件类型" min-width="100px" prop="event" /> <el-table-column label="监听器类型" min-width="100px" show-overflow-tooltip :formatter="row => listenerTypeObject[row.listenerType]" /> <el-table-column label="操作" width="90px"> <template #default="scope"> <el-button link type="" @click="openListenerForm(scope.row, scope.$index)">编辑</el-button> <el-divider direction="vertical" /> <el-button link type="" style="color: #ff4d4f" @click="removeListener(scope.row, scope.$index)">移除</el-button> </template> </el-table-column> </el-table> <div class="element-drawer__button"> <el-button size="small" type="primary" :icon="Plus" @click="openListenerForm(null)">添加监听器</el-button> </div> <!-- 监听器 编辑/创建 部分 --> <el-drawer v-model="listenerFormModelVisible" title="执行监听器" :size="`${width}px`" append-to-body destroy-on-close> <el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef" @submit.prevent> <el-form-item label="事件类型" prop="event" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerForm.event"> <el-option label="start" value="start" /> <el-option label="end" value="end" /> </el-select> </el-form-item> <el-form-item label="监听器类型" prop="listenerType" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerForm.listenerType"> <el-option v-for="i in Object.keys(listenerTypeObject)" :key="i" :label="listenerTypeObject[i]" :value="i" /> </el-select> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'classListener'" label="Java类" prop="class" key="listener-class" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.class" clearable /> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'expressionListener'" label="表达式" prop="expression" key="listener-expression" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.expression" clearable /> </el-form-item> <el-form-item v-if="listenerForm.listenerType === 'delegateExpressionListener'" label="代理表达式" prop="delegateExpression" key="listener-delegate" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerForm.delegateExpression" clearable /> </el-form-item> <template v-if="listenerForm.listenerType === 'scriptListener'"> <el-form-item label="脚本格式" prop="scriptFormat" key="listener-script-format" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本格式' }" > <el-input v-model="listenerForm.scriptFormat" clearable /> </el-form-item> <el-form-item label="脚本类型" prop="scriptType" key="listener-script-type" :rules="{ required: true, trigger: ['blur', 'change'], message: '请选择脚本类型' }" > <el-select v-model="listenerForm.scriptType"> <el-option label="内联脚本" value="inlineScript" /> <el-option label="外部脚本" value="externalScript" /> </el-select> </el-form-item> <el-form-item v-if="listenerForm.scriptType === 'inlineScript'" label="脚本内容" prop="value" key="listener-script" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写脚本内容' }" > <el-input v-model="listenerForm.value" clearable /> </el-form-item> <el-form-item v-if="listenerForm.scriptType === 'externalScript'" label="资源地址" prop="resource" key="listener-resource" :rules="{ required: true, trigger: ['blur', 'change'], message: '请填写资源地址' }" > <el-input v-model="listenerForm.resource" clearable /> </el-form-item> </template> </el-form> <el-divider /> <p class="listener-filed__title"> <span><el-icon><Menu /></el-icon>注入字段:</span> <el-button size="small" type="primary" @click="openListenerFieldForm(null)">添加字段</el-button> </p> <el-table :data="fieldsListOfListener" size="small" max-height="240" border fit style="flex: none"> <el-table-column label="序号" width="50px" type="index" /> <el-table-column label="字段名称" min-width="100px" prop="name" /> <el-table-column label="字段类型" min-width="80px" show-overflow-tooltip :formatter="row => fieldTypeObject[row.fieldType]" /> <el-table-column label="字段值/表达式" min-width="100px" show-overflow-tooltip :formatter="row => row.string || row.expression" /> <el-table-column label="操作" width="100px"> <template #default="scope"> <el-button link type="" @click="openListenerFieldForm(scope.row, scope.$index)">编辑</el-button> <el-divider direction="vertical" /> <el-button link type="" style="color: #ff4d4f" @click="removeListenerField(scope.row, scope.$index)">移除</el-button> </template> </el-table-column> </el-table> <div class="element-drawer__button"> <el-button size="small" @click="listenerFormModelVisible = false">取 消</el-button> <el-button size="small" type="primary" @click="saveListenerConfig">保 存</el-button> </div> </el-drawer> <!-- 注入西段 编辑/创建 部分 --> <el-dialog title="字段配置" v-model="listenerFieldFormModelVisible" width="600px" append-to-body destroy-on-close> <el-form :model="listenerFieldForm" size="small" label-width="96px" ref="listenerFieldFormRef" style="height: 136px" @submit.prevent> <el-form-item label="字段名称:" prop="name" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-input v-model="listenerFieldForm.name" clearable /> </el-form-item> <el-form-item label="字段类型:" prop="fieldType" :rules="{ required: true, trigger: ['blur', 'change'] }"> <el-select v-model="listenerFieldForm.fieldType"> <el-option v-for="i in Object.keys(fieldTypeObject)" :key="i" :label="fieldTypeObject[i]" :value="i" /> </el-select> </el-form-item> <el-form-item v-if="listenerFieldForm.fieldType === 'string'" label="字段值:" prop="string" key="field-string" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerFieldForm.string" clearable /> </el-form-item> <el-form-item v-if="listenerFieldForm.fieldType === 'expression'" label="表达式:" prop="expression" key="field-expression" :rules="{ required: true, trigger: ['blur', 'change'] }" > <el-input v-model="listenerFieldForm.expression" clearable /> </el-form-item> </el-form> <template #footer> <el-button size="small" @click="listenerFieldFormModelVisible = false">取 消</el-button> <el-button size="small" type="primary" @click="saveListenerFiled">确 定</el-button> </template> </el-dialog> </div> </template> <script lang="ts" setup> import { ElMessageBox } from 'element-plus' import { createListenerObject, updateElementExtensions } from "../../utils"; import { initListenerType, initListenerForm, listenerType, fieldType } from "./utilSelf"; import { Plus } from '@element-plus/icons-vue' defineOptions({ name: 'ElementListeners' }) const props = defineProps({ id: String, type: String }) const prefix = inject('prefix') const width = inject('width') const elementListenersList = ref<any[]>([]) // 监听器列表 const listenerForm = ref<any>({}) // 监听器详情表单 const listenerFormModelVisible = ref(false) // 监听器 编辑 侧边栏显示状态 const fieldsListOfListener = ref<any[]>([]) const listenerFieldForm = ref<any>({}) // 监听器 注入字段 详情表单 const listenerFieldFormModelVisible = ref(false) // 监听器 注入字段表单弹窗 显示状态 const editingListenerIndex = ref(-1) // 监听器所在下标,-1 为新增 const editingListenerFieldIndex = ref(-1) // 字段所在下标,-1 为新增 const listenerTypeObject = ref(listenerType) const fieldTypeObject = ref(fieldType) const bpmnElement = ref() const otherExtensionList = ref() const bpmnElementListeners = ref() const listenerFormRef = ref() const listenerFieldFormRef = ref() const bpmnInstances = () => (window as any)?.bpmnInstances watch( () => props.id, (val) => { val && val.length && nextTick(() => { resetListenersList() }) }, { immediate: true } ) const resetListenersList = () => { bpmnElement.value = bpmnInstances().bpmnElement otherExtensionList.value = [] bpmnElementListeners.value = bpmnElement.value.businessObject?.extensionElements?.values?.filter( (ex) => ex.$type === `${prefix}:ExecutionListener` ) ?? [] elementListenersList.value = bpmnElementListeners.value.map((listener) => initListenerType(listener) ) } // 打开 监听器详情 侧边栏 const openListenerForm = (listener, index?) => { if (listener) { listenerForm.value = initListenerForm(listener) editingListenerIndex.value = index } else { listenerForm.value = {} editingListenerIndex.value = -1 // 标记为新增 } if (listener && listener.fields) { fieldsListOfListener.value = listener.fields.map((field) => ({ ...field, fieldType: field.string ? 'string' : 'expression' })) } else { fieldsListOfListener.value = [] listenerForm.value['fields'] = [] } // 打开侧边栏并清楚验证状态 listenerFormModelVisible.value = true nextTick(() => { if (listenerFormRef.value) { listenerFormRef.value.clearValidate() } }) } // 打开监听器字段编辑弹窗 const openListenerFieldForm = (field, index?) => { listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {} editingListenerFieldIndex.value = field ? index : -1 listenerFieldFormModelVisible.value = true nextTick(() => { if (listenerFieldFormRef.value) { listenerFieldFormRef.value.clearValidate() } }) } // 保存监听器注入字段 const saveListenerFiled = async () => { let validateStatus = await listenerFieldFormRef.value.validate() if (!validateStatus) return // 验证不通过直接返回 if (editingListenerFieldIndex.value === -1) { fieldsListOfListener.value.push(listenerFieldForm.value) listenerForm.value.fields.push(listenerFieldForm.value) } else { fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value) listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value) } listenerFieldFormModelVisible.value = false nextTick(() => { listenerFieldForm.value = {} }) } // 移除监听器字段 const removeListenerField = (index) => { ElMessageBox.confirm('确认移除该字段吗?', '提示', { confirmButtonText: '确 认', cancelButtonText: '取 消' }) .then(() => { fieldsListOfListener.value.splice(index, 1) listenerForm.value.fields.splice(index, 1) }) .catch(() => console.info('操作取消')) } // 移除监听器 const removeListener = (index) => { ElMessageBox.confirm('确认移除该监听器吗?', '提示', { confirmButtonText: '确 认', cancelButtonText: '取 消' }) .then(() => { bpmnElementListeners.value.splice(index, 1) elementListenersList.value.splice(index, 1) updateElementExtensions( bpmnElement.value, otherExtensionList.value.concat(bpmnElementListeners.value) ) }) .catch(() => console.info('操作取消')) } // 保存监听器配置 const saveListenerConfig = async () => { let validateStatus = await listenerFormRef.value.validate() if (!validateStatus) return // 验证不通过直接返回 const listenerObject = createListenerObject(listenerForm.value, false, prefix) if (editingListenerIndex.value === -1) { bpmnElementListeners.value.push(listenerObject) elementListenersList.value.push(listenerForm.value) } else { bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject) elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value) } // 保存其他配置 otherExtensionList.value = bpmnElement.value.businessObject?.extensionElements?.values?.filter( (ex) => ex.$type !== `${prefix}:ExecutionListener` ) ?? [] updateElementExtensions( bpmnElement.value, otherExtensionList.value.concat(bpmnElementListeners.value) ) // 4. 隐藏侧边栏 listenerFormModelVisible.value = false listenerForm.value = {} } </script>
3、效果图如下: