From c9a6f7cbb5209415e626df29c7572cf40fe92b66 Mon Sep 17 00:00:00 2001 From: houzhongjian <houzhongyi@126.com> Date: 星期一, 06 一月 2025 11:44:50 +0800 Subject: [PATCH] 1、工作流程功能优化,解决流程图模拟功能simulation不生效的bug 2、system menu等页面修改 3、Footer copyright年份修改为动态 --- src/views/bpm/model/editor/index.vue | 258 ++++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 204 insertions(+), 54 deletions(-) diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 1a41a50..37eff73 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,7 +3,6 @@ <!-- 流程设计器,负责绘制流程等 --> <MyProcessDesigner key="designer" - v-if="xmlString !== undefined" v-model="xmlString" :value="xmlString" v-bind="controlForm" @@ -11,12 +10,14 @@ ref="processDesigner" @init-finished="initModeler" :additionalModel="controlForm.additionalModel" + :model="model" @save="save" /> <!-- 流程属性器,负责编辑每个流程节点的属性 --> <MyProcessPenal + v-if="isModelerReady && modeler" key="penal" - :bpmnModeler="modeler as any" + :bpmnModeler="modeler" :prefix="controlForm.prefix" class="process-panel" :model="model" @@ -31,12 +32,17 @@ // 自定义左侧菜单(修改 默认任务 为 用户任务) import CustomPaletteProvider from '@/components/bpmnProcessDesigner/package/designer/plugins/palette' import * as ModelApi from '@/api/bpm/model' -import { getForm, FormVO } from '@/api/bpm/form' defineOptions({ name: 'BpmModelEditor' }) -const router = useRouter() // 路由 -const { query } = useRoute() // 路由的查询 +const props = defineProps<{ + modelId?: string + modelKey?: string + modelName?: string + value?: string +}>() + +const emit = defineEmits(['success', 'init-finished']) const message = useMessage() // 国际化 // 表单信息 @@ -45,8 +51,10 @@ provide('formFields', formFields) provide('formType', formType) -const xmlString = ref(undefined) // BPMN XML -const modeler = ref(null) // BPMN Modeler +const xmlString = ref<string>('') // BPMN XML +const modeler = shallowRef() // BPMN Modeler +const processDesigner = ref() +const isModelerReady = ref(false) const controlForm = ref({ simulation: true, labelEditing: false, @@ -57,73 +65,215 @@ }) const model = ref<ModelApi.ModelVO>() // 流程模型的信息 +// 初始化 bpmnInstances +const initBpmnInstances = () => { + if (!modeler.value) return false + try { + const instances = { + modeler: modeler.value, + modeling: modeler.value.get('modeling'), + moddle: modeler.value.get('moddle'), + eventBus: modeler.value.get('eventBus'), + bpmnFactory: modeler.value.get('bpmnFactory'), + elementFactory: modeler.value.get('elementFactory'), + elementRegistry: modeler.value.get('elementRegistry'), + replace: modeler.value.get('replace'), + selection: modeler.value.get('selection') + } + + // 检查所有实例是否都存在 + return Object.values(instances).every((instance) => instance) + } catch (error) { + console.error('初始化 bpmnInstances 失败:', error) + return false + } +} + /** 初始化 modeler */ -const initModeler = (item) => { - setTimeout(() => { +const initModeler = async (item) => { + try { modeler.value = item - }, 10) + // 等待 modeler 初始化完成 + await nextTick() + + // 确保 modeler 的所有实例都已经准备好 + if (initBpmnInstances()) { + isModelerReady.value = true + emit('init-finished') + + // 初始化完成后,设置初始值 + if (props.modelId) { + // 编辑模式 + const data = await ModelApi.getModel(props.modelId) + model.value = { + ...data, + bpmnXml: undefined // 清空 bpmnXml 属性 + } + xmlString.value = data.bpmnXml || getDefaultBpmnXml(data.key, data.name) + } else if (props.modelKey && props.modelName) { + // 新建模式 + xmlString.value = props.value || getDefaultBpmnXml(props.modelKey, props.modelName) + model.value = { + key: props.modelKey, + name: props.modelName + } as ModelApi.ModelVO + } + + // 导入XML并刷新视图 + await nextTick() + try { + await modeler.value.importXML(xmlString.value) + if (processDesigner.value?.refresh) { + processDesigner.value.refresh() + } + } catch (error) { + console.error('导入XML失败:', error) + } + } else { + console.error('modeler 实例未完全初始化') + } + } catch (error) { + console.error('初始化 modeler 失败:', error) + } +} + +/** 获取默认的BPMN XML */ +const getDefaultBpmnXml = (key: string, name: string) => { + return `<?xml version="1.0" encoding="UTF-8"?> +<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.activiti.org/processdef"> + <process id="${key}" name="${name}" isExecutable="true" /> + <bpmndi:BPMNDiagram id="BPMNDiagram"> + <bpmndi:BPMNPlane id="${key}_di" bpmnElement="${key}" /> + </bpmndi:BPMNDiagram> +</definitions>` } /** 添加/修改模型 */ const save = async (bpmnXml: string) => { - const data = { - ...model.value, - bpmnXml: bpmnXml // bpmnXml 只是初始化流程图,后续修改无法通过它获得 - } as unknown as ModelApi.ModelVO - // 提交 - if (data.id) { - await ModelApi.updateModelBpmn(data) - message.success('修改成功') - } else { - await ModelApi.updateModelBpmn(data) - message.success('新增成功') + try { + xmlString.value = bpmnXml + if (props.modelId) { + // 编辑模式 + const data = { + ...model.value, + bpmnXml: bpmnXml + } as unknown as ModelApi.ModelVO + await ModelApi.updateModelBpmn(data) + emit('success') + } else { + // 新建模式,直接返回XML + emit('success', bpmnXml) + } + } catch (error) { + console.error('保存失败:', error) + message.error('保存失败') } - // 跳转回去 - close() } -/** 关闭按钮 */ -const close = () => { - router.push({ path: '/bpm/manager/model' }) +// 监听 key、name 和 value 的变化 +watch( + [() => props.modelKey, () => props.modelName, () => props.value], + async ([newKey, newName, newValue]) => { + if (!props.modelId && isModelerReady.value) { + let shouldRefresh = false + + if (newKey && newName) { + const newXml = newValue || getDefaultBpmnXml(newKey, newName) + if (newXml !== xmlString.value) { + xmlString.value = newXml + shouldRefresh = true + } + model.value = { + ...model.value, + key: newKey, + name: newName + } as ModelApi.ModelVO + } else if (newValue && newValue !== xmlString.value) { + xmlString.value = newValue + shouldRefresh = true + } + + if (shouldRefresh) { + // 确保更新后重新渲染 + await nextTick() + if (processDesigner.value?.refresh) { + try { + await modeler.value?.importXML(xmlString.value) + processDesigner.value.refresh() + } catch (error) { + console.error('导入XML失败:', error) + } + } + } + } + }, + { deep: true } +) + +// 在组件卸载时清理 +onBeforeUnmount(() => { + isModelerReady.value = false + modeler.value = null + // 清理全局实例 + const w = window as any + if (w.bpmnInstances) { + w.bpmnInstances = null + } +}) + +/** 获取 XML 字符串 */ +const saveXML = async () => { + if (!modeler.value) { + return { xml: xmlString.value } + } + try { + const result = await modeler.value.saveXML({ format: true }) + xmlString.value = result.xml + return result + } catch (error) { + console.error('获取XML失败:', error) + return { xml: xmlString.value } + } } -/** 初始化 */ -onMounted(async () => { - const modelId = query.modelId as unknown as number - if (!modelId) { - message.error('缺少模型 modelId 编号') - return +/** 获取SVG字符串 */ +const saveSVG = async () => { + if (!modeler.value) { + return { svg: undefined } } - // 查询模型 - const data = await ModelApi.getModel(modelId) - if (!data.bpmnXml) { - // 首次创建的 Model 模型,它是没有 bpmnXml,此时需要给它一个默认的 - data.bpmnXml = ` <?xml version="1.0" encoding="UTF-8"?> -<definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.activiti.org/processdef"> - <process id="${data.key}" name="${data.name}" isExecutable="true" /> - <bpmndi:BPMNDiagram id="BPMNDiagram"> - <bpmndi:BPMNPlane id="${data.key}_di" bpmnElement="${data.key}" /> - </bpmndi:BPMNDiagram> -</definitions>` + try { + return await modeler.value.saveSVG() + } catch (error) { + console.error('获取SVG失败:', error) + return { svg: undefined } } +} - formType.value = data.formType - if (data.formType === 10) { - const bpmnForm = (await getForm(data.formId)) as unknown as FormVO - formFields.value = bpmnForm?.fields +/** 刷新视图 */ +const refresh = async () => { + if (processDesigner.value?.refresh && modeler.value) { + try { + await modeler.value.importXML(xmlString.value) + processDesigner.value.refresh() + } catch (error) { + console.error('刷新视图失败:', error) + } } +} - model.value = { - ...data, - bpmnXml: undefined // 清空 bpmnXml 属性 - } - xmlString.value = data.bpmnXml +// 暴露必要的属性和方法给父组件 +defineExpose({ + modeler, + isModelerReady, + saveXML, + saveSVG, + refresh }) </script> <style lang="scss"> .process-panel__container { position: absolute; - top: 90px; - right: 60px; + top: 172px; + right: 70px; } </style> -- Gitblit v1.9.3