diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index 6b5ff997..bdea492a 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -1,6 +1,7 @@ + + diff --git a/src/views/bpm/model/editor/index.vue b/src/views/bpm/model/editor/index.vue index 1a41a50c..6e71d01c 100644 --- a/src/views/bpm/model/editor/index.vue +++ b/src/views/bpm/model/editor/index.vue @@ -3,7 +3,6 @@ () + +const emit = defineEmits(['success']) const message = useMessage() // 国际化 // 表单信息 @@ -45,8 +50,10 @@ const formType = ref(20) provide('formFields', formFields) provide('formType', formType) -const xmlString = ref(undefined) // BPMN XML -const modeler = ref(null) // BPMN Modeler +const xmlString = ref('') // BPMN XML +const modeler = shallowRef() // BPMN Modeler +const processDesigner = ref() +const isModelerReady = ref(false) const controlForm = ref({ simulation: true, labelEditing: false, @@ -57,73 +64,194 @@ const controlForm = ref({ }) const model = ref() // 流程模型的信息 +// 初始化 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 + if (!props.modelId && props.modelKey && props.modelName) { + await updateModelData(props.modelKey, props.modelName) + } + } else { + console.error('modeler 实例未完全初始化') + } + } catch (error) { + console.error('初始化 modeler 失败:', error) + } +} + +/** 获取默认的BPMN XML */ +const getDefaultBpmnXml = (key: string, name: string) => { + return ` + + + + + +` } /** 添加/修改模型 */ 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 { + 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' }) } /** 初始化 */ onMounted(async () => { - const modelId = query.modelId as unknown as number - if (!modelId) { - message.error('缺少模型 modelId 编号') - return - } - // 查询模型 - const data = await ModelApi.getModel(modelId) - if (!data.bpmnXml) { - // 首次创建的 Model 模型,它是没有 bpmnXml,此时需要给它一个默认的 - data.bpmnXml = ` - - - - - -` + try { + 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 = getDefaultBpmnXml(props.modelKey, props.modelName) + model.value = { + key: props.modelKey, + name: props.modelName + } as ModelApi.ModelVO + } + } catch (error) { + console.error('初始化失败:', error) + message.error('初始化失败') } +}) - formType.value = data.formType - if (data.formType === 10) { - const bpmnForm = (await getForm(data.formId)) as unknown as FormVO - formFields.value = bpmnForm?.fields +/** 更新模型数据 */ +const updateModelData = async (key?: string, name?: string) => { + if (key && name) { + xmlString.value = getDefaultBpmnXml(key, name) + model.value = { + ...model.value, + key: key, + name: name + } as ModelApi.ModelVO + // 确保更新后重新渲染 + await nextTick() + if (processDesigner.value?.refresh) { + processDesigner.value.refresh() + } } +} - model.value = { - ...data, - bpmnXml: undefined // 清空 bpmnXml 属性 +// 监听 key 和 name 的变化 +watch( + [() => props.modelKey, () => props.modelName], + async ([newKey, newName]) => { + if (!props.modelId && newKey && newName && modeler.value) { + await updateModelData(newKey, newName) + } + }, + { immediate: true, deep: true } +) + +// 在组件卸载时清理 +onBeforeUnmount(() => { + isModelerReady.value = false + modeler.value = null + // 清理全局实例 + const w = window as any + if (w.bpmnInstances) { + w.bpmnInstances = null } - xmlString.value = data.bpmnXml +}) + +/** 获取 XML 字符串 */ +const saveXML = async () => { + if (!modeler.value) { + return { xml: undefined } + } + try { + return await modeler.value.saveXML({ format: true }) + } catch (error) { + console.error('获取XML失败:', error) + return { xml: undefined } + } +} + +/** 获取SVG字符串 */ +const saveSVG = async () => { + if (!modeler.value) { + return { svg: undefined } + } + try { + return await modeler.value.saveSVG() + } catch (error) { + console.error('获取SVG失败:', error) + return { svg: undefined } + } +} + +/** 刷新视图 */ +const refresh = () => { + if (processDesigner.value?.refresh) { + processDesigner.value.refresh() + } +} + +// 暴露必要的属性和方法给父组件 +defineExpose({ + modeler, + isModelerReady, + saveXML, + saveSVG, + refresh }) diff --git a/src/views/bpm/model/form/BasicInfo.vue b/src/views/bpm/model/form/BasicInfo.vue new file mode 100644 index 00000000..0359ea89 --- /dev/null +++ b/src/views/bpm/model/form/BasicInfo.vue @@ -0,0 +1,301 @@ + + + + + diff --git a/src/views/bpm/model/form/FormDesign.vue b/src/views/bpm/model/form/FormDesign.vue new file mode 100644 index 00000000..98aee6d2 --- /dev/null +++ b/src/views/bpm/model/form/FormDesign.vue @@ -0,0 +1,137 @@ + + + diff --git a/src/views/bpm/model/form/ProcessDesign.vue b/src/views/bpm/model/form/ProcessDesign.vue new file mode 100644 index 00000000..c6d787ba --- /dev/null +++ b/src/views/bpm/model/form/ProcessDesign.vue @@ -0,0 +1,130 @@ + + + diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue new file mode 100644 index 00000000..ac628e0a --- /dev/null +++ b/src/views/bpm/model/form/index.vue @@ -0,0 +1,392 @@ + + + + + diff --git a/src/views/bpm/model/index.vue b/src/views/bpm/model/index.vue index bf43d292..c7d94170 100644 --- a/src/views/bpm/model/index.vue +++ b/src/views/bpm/model/index.vue @@ -106,6 +106,7 @@ import CategoryDraggableModel from './CategoryDraggableModel.vue' defineOptions({ name: 'BpmModel' }) +const { push } = useRouter() const message = useMessage() // 消息弹窗 const loading = ref(true) // 列表的加载中 const isCategorySorting = ref(false) // 是否 category 正处于排序状态 @@ -124,7 +125,14 @@ const handleQuery = () => { /** 添加/修改操作 */ const formRef = ref() const openForm = (type: string, id?: number) => { - formRef.value.open(type, id) + if (type === 'create') { + push({ name: 'BpmModelCreate' }) + } else { + push({ + name: 'BpmModelUpdate', + params: { id } + }) + } } /** 流程表单的详情按钮操作 */ diff --git a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue index 3800f191..64d072ce 100644 --- a/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue +++ b/src/views/bpm/processInstance/create/ProcessDefinitionDetail.vue @@ -8,7 +8,7 @@ - +
@@ -75,7 +75,11 @@