diff --git a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue index bc952d74..bdea492a 100644 --- a/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue +++ b/src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue @@ -1,6 +1,7 @@ { w.bpmnInstances = null } }) + +/** 获取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 index 532ec786..0359ea89 100644 --- a/src/views/bpm/model/form/BasicInfo.vue +++ b/src/views/bpm/model/form/BasicInfo.vue @@ -1,15 +1,9 @@ @@ -19,6 +20,7 @@ :model-key="modelData.key" :model-name="modelData.name" :value="modelData.bpmnXml" + ref="simpleEditorRef" @success="handleDesignSuccess" /> @@ -38,7 +40,8 @@ const props = defineProps({ const emit = defineEmits(['update:modelValue', 'success']) -const xmlString = ref() +const bpmnEditorRef = ref() +const simpleEditorRef = ref() // 创建本地数据副本 const modelData = computed({ @@ -46,45 +49,73 @@ const modelData = computed({ set: (val) => emit('update:modelValue', val) }) -// 监听modelValue变化,确保XML数据同步 -watch( - () => props.modelValue, - (newVal) => { - if (newVal?.bpmnXml) { - xmlString.value = newVal.bpmnXml +/** 获取当前流程数据 */ +const getProcessData = async () => { + try { + if (modelData.value.type === BpmModelType.BPMN) { + // BPMN设计器 + if (bpmnEditorRef.value) { + const { xml } = await bpmnEditorRef.value.saveXML() + if (xml) { + return xml + } + } + } else { + // Simple设计器 + if (simpleEditorRef.value) { + const flowData = await simpleEditorRef.value.getCurrentFlowData() + if (flowData) { + return flowData // 直接返回流程数据对象,不需要转换为字符串 + } + } } - }, - { immediate: true, deep: true } -) - -/** 处理设计器保存成功 */ -const handleDesignSuccess = (bpmnXml?: string) => { - if (bpmnXml) { - xmlString.value = bpmnXml - modelData.value = { - ...modelData.value, - bpmnXml - } - emit('success', bpmnXml) + return undefined + } catch (error) { + console.error('获取流程数据失败:', error) + return undefined } } /** 表单校验 */ const validate = async () => { - // 获取最新的XML数据 - const currentXml = xmlString.value || modelData.value?.bpmnXml + try { + // 根据流程类型获取对应的编辑器引用 + const editorRef = + modelData.value.type === BpmModelType.BPMN ? bpmnEditorRef.value : simpleEditorRef.value + if (!editorRef) { + throw new Error('流程设计器未初始化') + } + + // 获取最新的流程数据 + const processData = await getProcessData() + if (!processData) { + throw new Error('请设计流程') + } - // 如果是修改场景且有XML数据(无论是新的还是原有的) - if (modelData.value.id && currentXml) { return true + } catch (error) { + throw error } +} - // 新增场景必须有XML数据 - if (!currentXml) { - throw new Error('请设计流程') +/** 处理设计器保存成功 */ +const handleDesignSuccess = (data?: any) => { + if (data) { + if (modelData.value.type === BpmModelType.BPMN) { + modelData.value = { + ...modelData.value, + bpmnXml: data, + simpleModel: null + } + } else { + modelData.value = { + ...modelData.value, + bpmnXml: null, + simpleModel: data + } + } + emit('success', data) } - - return true } /** 是否显示设计器 */ @@ -92,13 +123,8 @@ const showDesigner = computed(() => { return Boolean(modelData.value?.key && modelData.value?.name) }) -/** 获取当前XML字符串 */ -const getXmlString = () => { - return xmlString.value || modelData.value?.bpmnXml || '' -} - defineExpose({ validate, - getXmlString + getProcessData }) diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue index f6c2ef2a..4e807a26 100644 --- a/src/views/bpm/model/form/index.vue +++ b/src/views/bpm/model/form/index.vue @@ -7,7 +7,7 @@ >
- + {{ formData.name || '创建流程' }} @@ -44,15 +44,15 @@
- 保 存 - 发 布 + 发 布 + 保 存
-
+
-
+
@@ -90,8 +90,10 @@ import { BpmModelType, BpmModelFormType } from '@/utils/constants' import BasicInfo from './BasicInfo.vue' import FormDesign from './FormDesign.vue' import ProcessDesign from './ProcessDesign.vue' +import { useTagsViewStore } from '@/store/modules/tagsView' const router = useRouter() +const { delView } = useTagsViewStore() // 视图操作 const route = useRoute() const message = useMessage() const userStore = useUserStoreWithOut() @@ -102,24 +104,24 @@ const formDesignRef = ref() const processDesignRef = ref() /** 步骤校验函数 */ -const validateStep1 = async () => { +const validateBasic = async () => { await basicInfoRef.value?.validate() } -const validateStep2 = async () => { +const validateForm = async () => { await formDesignRef.value?.validate() } -const validateStep3 = async () => { +const validateProcess = async () => { await processDesignRef.value?.validate() } // 步骤控制 const currentStep = ref(0) const steps = [ - { title: '基本信息', validator: validateStep1 }, - { title: '表单设计', validator: validateStep2 }, - { title: '流程设计', validator: validateStep3 } + { title: '基本信息', validator: validateBasic }, + { title: '表单设计', validator: validateForm }, + { title: '流程设计', validator: validateProcess } ] // 表单数据 @@ -166,71 +168,154 @@ const initData = async () => { userList.value = await UserApi.getSimpleUserList() } +/** 校验所有步骤数据是否完整 */ +const validateAllSteps = async () => { + try { + // 基本信息校验 + await basicInfoRef.value?.validate() + if (!formData.value.key || !formData.value.name || !formData.value.category) { + currentStep.value = 0 + throw new Error('请完善基本信息') + } + + // 表单设计校验 + await formDesignRef.value?.validate() + if (formData.value.formType === 10 && !formData.value.formId) { + currentStep.value = 1 + throw new Error('请选择流程表单') + } + if ( + formData.value.formType === 20 && + (!formData.value.formCustomCreatePath || !formData.value.formCustomViewPath) + ) { + currentStep.value = 1 + throw new Error('请完善自定义表单信息') + } + + // 流程设计校验 + await processDesignRef.value?.validate() + const processData = await processDesignRef.value?.getProcessData() + if (!processData) { + currentStep.value = 2 + throw new Error('请设计流程') + } + + return true + } catch (error) { + throw error + } +} + /** 保存操作 */ const handleSave = async () => { try { - // 保存前确保所有步骤的数据都已经验证通过 - for (const step of steps) { - if (step.validator) { - await step.validator() - } + // 保存前校验所有步骤的数据 + await validateAllSteps() + + // 获取最新的流程设计数据 + const processData = await processDesignRef.value?.getProcessData() + if (!processData) { + throw new Error('获取流程数据失败') } - // 如果是在第三步,需要先获取最新的流程设计数据 - if (currentStep.value === 2) { - await nextTick() - const bpmnXml = processDesignRef.value?.getXmlString() - // 确保有XML数据 - if (!bpmnXml) { - throw new Error('请设计流程') - } - formData.value.bpmnXml = bpmnXml + // 更新表单数据 + const modelData = { + ...formData.value } - - if (formData.value.id) { - await ModelApi.updateModel(formData.value) - message.success('修改成功') + if (formData.value.type === BpmModelType.BPMN) { + modelData.bpmnXml = processData + modelData.simpleModel = null } else { - const result = await ModelApi.createModel(formData.value) - formData.value.id = result.id - message.success('新增成功') + modelData.bpmnXml = null + modelData.simpleModel = processData // 直接使用流程数据对象 } - } catch (error) { + + if (formData.value.id) { + // 修改场景 + await ModelApi.updateModel(modelData) + message.success('修改成功') + // 询问是否发布流程 + try { + await message.confirm('修改流程成功,是否发布流程?') + // 用户点击确认,执行发布 + await handleDeploy() + } catch { + // 用户点击取消,停留在当前页面 + } + } else { + // 新增场景 + const result = await ModelApi.createModel(modelData) + formData.value.id = result + message.success('新增成功') + try { + await message.confirm('创建流程成功,是否继续编辑?') + // 用户点击继续编辑,跳转到编辑页面 + await nextTick() + // 先删除当前页签 + delView(unref(router.currentRoute)) + // 跳转到编辑页面 + await router.push({ + name: 'BpmModelUpdate', + params: { id: formData.value.id } + }) + } catch { + // 先删除当前页签 + delView(unref(router.currentRoute)) + // 用户点击返回列表 + await router.push({ name: 'BpmModel' }) + } + } + } catch (error: any) { console.error('保存失败:', error) - message.error(error.message || '保存失败') - throw error + message.warning(error.message || '请完善所有步骤的必填信息') } } /** 发布操作 */ const handleDeploy = async () => { try { - await message.confirm('是否确认发布该流程?') + // 修改场景下直接发布,新增场景下需要先确认 + if (!formData.value.id) { + await message.confirm('是否确认发布该流程?') + } + + // 校验所有步骤 + await validateAllSteps() + + // 获取最新的流程设计数据 + const processData = await processDesignRef.value?.getProcessData() + if (!processData) { + throw new Error('获取流程数据失败') + } + + // 更新表单数据 + const modelData = { + ...formData.value + } + if (formData.value.type === BpmModelType.BPMN) { + modelData.bpmnXml = processData + modelData.simpleModel = null + } else { + modelData.bpmnXml = null + modelData.simpleModel = processData // 直接使用流程数据对象 + } + // 先保存所有数据 - await handleSave() + if (formData.value.id) { + await ModelApi.updateModel(modelData) + } else { + const result = await ModelApi.createModel(modelData) + formData.value.id = result.id + } + // 发布 await ModelApi.deployModel(formData.value.id) message.success('发布成功') + // 返回列表页 router.push({ name: 'BpmModel' }) - } catch (error) { + } catch (error: any) { console.error('发布失败:', error) - if (error instanceof Error) { - // 校验失败时,跳转到对应步骤 - const failedStep = steps.findIndex((step) => { - try { - step.validator && step.validator() - return false - } catch { - return true - } - }) - if (failedStep !== -1) { - currentStep.value = failedStep - message.warning('请完善必填信息') - } else { - message.error(error.message || '发布失败') - } - } + message.warning(error.message || '发布失败') } } @@ -243,7 +328,7 @@ const handleStepClick = async (index: number) => { return } } - + // 只有在向后切换时才进行校验 if (index > currentStep.value) { try { @@ -267,10 +352,26 @@ const handleDesignSuccess = (bpmnXml?: string) => { } } +/** 返回列表页 */ +const handleBack = () => { + // 先删除当前页签 + delView(unref(router.currentRoute)) + // 跳转到列表页 + router.push({ name: 'BpmModel' }) +} + /** 初始化 */ onMounted(async () => { await initData() }) + +// 添加组件卸载前的清理代码 +onBeforeUnmount(() => { + // 清理所有的引用 + basicInfoRef.value = null + formDesignRef.value = null + processDesignRef.value = null +})