Browse Source

feat: 删除设计流程中两个流程设计器的保存模型按钮,并在点击保存/提交按钮时直接获取内部组件xml逻辑

GoldenZqqq 7 months ago
parent
commit
e50cd2231c

+ 22 - 19
src/components/SimpleProcessDesignerV2/src/SimpleProcessModel.vue

@@ -8,15 +8,6 @@
           <el-button size="default" class="w-80px"> {{ scaleValue }}% </el-button>
           <el-button size="default" :plain="true" :icon="ZoomIn" @click="zoomIn()" />
         </el-button-group>
-        <el-button
-          v-if="!readonly"
-          size="default"
-          class="ml-4px"
-          type="primary"
-          :icon="Select"
-          @click="saveSimpleFlowModel"
-          >保存模型</el-button
-        >
       </el-row>
     </div>
     <div class="simple-process-model" :style="`transform: scale(${scaleValue / 100});`">
@@ -42,7 +33,8 @@
 import ProcessNodeTree from './ProcessNodeTree.vue'
 import { SimpleFlowNode, NodeType, NODE_DEFAULT_TEXT } from './consts'
 import { useWatchNode } from './node'
-import { Select, ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
+import { ZoomOut, ZoomIn, ScaleToOriginal } from '@element-plus/icons-vue'
+
 defineOptions({
   name: 'SimpleProcessModel'
 })
@@ -58,6 +50,7 @@ const props = defineProps({
     default: true
   }
 })
+
 const emits = defineEmits<{
   'save': [node: SimpleFlowNode | undefined]
 }>()
@@ -68,6 +61,7 @@ provide('readonly', props.readonly)
 let scaleValue = ref(100)
 const MAX_SCALE_VALUE = 200
 const MIN_SCALE_VALUE = 50
+
 // 放大
 const zoomIn = () => {
   if (scaleValue.value == MAX_SCALE_VALUE) {
@@ -75,6 +69,7 @@ const zoomIn = () => {
   }
   scaleValue.value += 10
 }
+
 // 缩小
 const zoomOut = () => {
   if (scaleValue.value == MIN_SCALE_VALUE) {
@@ -82,21 +77,14 @@ const zoomOut = () => {
   }
   scaleValue.value -= 10
 }
+
 const processReZoom = () => {
   scaleValue.value = 100
 }
 
 const errorDialogVisible = ref(false)
 let errorNodes: SimpleFlowNode[] = []
-const saveSimpleFlowModel = async () => {
-  errorNodes = []
-  validateNode(processNodeTree.value, errorNodes)
-  if (errorNodes.length > 0) {
-    errorDialogVisible.value = true
-    return
-  }
-  emits('save', processNodeTree.value)
-}
+
 // 校验节点设置。 暂时以 showText 为空 未节点错误配置
 const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNode[]) => {
   if (node) {
@@ -135,6 +123,21 @@ const validateNode = (node: SimpleFlowNode | undefined, errorNodes: SimpleFlowNo
     }
   }
 }
+
+/** 获取当前流程数据 */
+const getCurrentFlowData = () => {
+  errorNodes = []
+  validateNode(processNodeTree.value, errorNodes)
+  if (errorNodes.length > 0) {
+    errorDialogVisible.value = true
+    return undefined
+  }
+  return processNodeTree.value
+}
+
+defineExpose({
+  getCurrentFlowData
+})
 </script>
 
 <style lang="scss" scoped></style>

+ 0 - 7
src/components/bpmnProcessDesigner/package/designer/ProcessDesigner.vue

@@ -160,13 +160,6 @@
             <XButton preIcon="ep:refresh" @click="processRestart()" />
           </el-tooltip>
         </ElButtonGroup>
-        <XButton
-          preIcon="ep:plus"
-          title="保存模型"
-          @click="processSave"
-          :type="props.headerButtonType"
-          :disabled="simulationStatus"
-        />
       </template>
       <!-- 用于打开本地文件-->
       <input

+ 43 - 1
src/views/bpm/model/editor/index.vue

@@ -205,11 +205,53 @@ onBeforeUnmount(() => {
     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
+})
 </script>
 <style lang="scss">
 .process-panel__container {
   position: absolute;
-  top: 90px;
+  top: 180px;
   right: 60px;
 }
 </style>

+ 49 - 34
src/views/bpm/model/form/ProcessDesign.vue

@@ -7,6 +7,7 @@
       :model-key="modelData.key"
       :model-name="modelData.name"
       :value="modelData.bpmnXml"
+      ref="bpmnEditorRef"
       @success="handleDesignSuccess"
     />
   </template>
@@ -19,6 +20,7 @@
       :model-key="modelData.key"
       :model-name="modelData.name"
       :value="modelData.bpmnXml"
+      ref="simpleEditorRef"
       @success="handleDesignSuccess"
     />
   </template>
@@ -38,7 +40,8 @@ const props = defineProps({
 
 const emit = defineEmits(['update:modelValue', 'success'])
 
-const xmlString = ref<string>()
+const bpmnEditorRef = ref()
+const simpleEditorRef = ref()
 
 // 创建本地数据副本
 const modelData = computed({
@@ -46,21 +49,56 @@ const modelData = computed({
   set: (val) => emit('update:modelValue', val)
 })
 
-// 监听modelValue变化,确保XML数据同步
-watch(
-  () => props.modelValue,
-  (newVal) => {
-    if (newVal?.bpmnXml) {
-      xmlString.value = newVal.bpmnXml
+/** 表单校验 */
+const validate = async () => {
+  try {
+    // 根据流程类型获取对应的编辑器引用
+    const editorRef =
+      modelData.value.type === BpmModelType.BPMN ? bpmnEditorRef.value : simpleEditorRef.value
+    if (!editorRef) {
+      throw new Error('流程设计器未初始化')
+    }
+
+    // 获取最新的XML数据
+    const bpmnXml = await getXmlString()
+    console.warn(bpmnXml, 'bpmnXml')
+    if (!bpmnXml) {
+      throw new Error('请设计流程')
     }
-  },
-  { immediate: true, deep: true }
-)
+
+    return true
+  } catch (error) {
+    throw error
+  }
+}
+
+/** 获取当前XML字符串 */
+const getXmlString = async () => {
+  try {
+    if (modelData.value.type === BpmModelType.BPMN) {
+      console.warn('bpmnEditorRef.value', bpmnEditorRef.value)
+      // BPMN设计器
+      if (bpmnEditorRef.value) {
+        const { xml } = await bpmnEditorRef.value.saveXML()
+        return xml
+      }
+    } else {
+      // Simple设计器
+      if (simpleEditorRef.value) {
+        const flowData = simpleEditorRef.value.getCurrentFlowData()
+        return flowData ? JSON.stringify(flowData) : undefined
+      }
+    }
+    return undefined
+  } catch (error) {
+    console.error('获取流程数据失败:', error)
+    return undefined
+  }
+}
 
 /** 处理设计器保存成功 */
 const handleDesignSuccess = (bpmnXml?: string) => {
   if (bpmnXml) {
-    xmlString.value = bpmnXml
     modelData.value = {
       ...modelData.value,
       bpmnXml
@@ -69,34 +107,11 @@ const handleDesignSuccess = (bpmnXml?: string) => {
   }
 }
 
-/** 表单校验 */
-const validate = async () => {
-  // 获取最新的XML数据
-  const currentXml = xmlString.value || modelData.value?.bpmnXml
-
-  // 如果是修改场景且有XML数据(无论是新的还是原有的)
-  if (modelData.value.id && currentXml) {
-    return true
-  }
-
-  // 新增场景必须有XML数据
-  if (!currentXml) {
-    throw new Error('请设计流程')
-  }
-
-  return true
-}
-
 /** 是否显示设计器 */
 const showDesigner = computed(() => {
   return Boolean(modelData.value?.key && modelData.value?.name)
 })
 
-/** 获取当前XML字符串 */
-const getXmlString = () => {
-  return xmlString.value || modelData.value?.bpmnXml || ''
-}
-
 defineExpose({
   validate,
   getXmlString

+ 9 - 1
src/views/bpm/model/form/index.vue

@@ -7,7 +7,7 @@
       >
         <!-- 左侧标题 -->
         <div class="w-200px flex items-center overflow-hidden">
-          <Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="router.back()" />
+          <Icon icon="ep:arrow-left" class="cursor-pointer flex-shrink-0" @click="handleBack" />
           <span class="ml-10px text-16px truncate" :title="formData.name || '创建流程'">
             {{ formData.name || '创建流程' }}
           </span>
@@ -322,6 +322,14 @@ const handleDesignSuccess = (bpmnXml?: string) => {
   }
 }
 
+/** 返回列表页 */
+const handleBack = () => {
+  // 先删除当前页签
+  delView(unref(router.currentRoute))
+  // 跳转到列表页
+  router.push({ name: 'BpmModel' })
+}
+
 /** 初始化 */
 onMounted(async () => {
   await initData()