Quellcode durchsuchen

feat: 修改设计流程切换到第三步自动赋值流程标识与流程名称逻辑

GoldenZqqqq vor 8 Monaten
Ursprung
Commit
21c28c3665

+ 26 - 0
src/components/SimpleProcessDesignerV2/src/SimpleProcessDesigner.vue

@@ -79,6 +79,32 @@ const processNodeTree = ref<SimpleFlowNode | undefined>()
 const errorDialogVisible = ref(false)
 let errorNodes: SimpleFlowNode[] = []
 
+// 添加更新模型的方法
+const updateModel = (key?: string, name?: string) => {
+  if (!processNodeTree.value) {
+    processNodeTree.value = {
+      name: name || '发起人',
+      type: NodeType.START_USER_NODE,
+      id: NodeId.START_USER_NODE_ID,
+      childNode: {
+        id: NodeId.END_EVENT_NODE_ID,
+        name: '结束',
+        type: NodeType.END_EVENT_NODE
+      }
+    }
+  } else if (name) {
+    // 更新现有模型的名称
+    processNodeTree.value.name = name
+  }
+}
+
+// 监听属性变化
+watch([() => props.modelKey, () => props.modelName], ([newKey, newName]) => {
+  if (!props.modelId && newKey && newName) {
+    updateModel(newKey, newName)
+  }
+}, { immediate: true, deep: true })
+
 const saveSimpleFlowModel = async (simpleModelNode: SimpleFlowNode) => {
   if (!simpleModelNode) {
     message.error('模型数据为空')

+ 83 - 39
src/components/bpmnProcessDesigner/package/penal/PropertiesPanel.vue

@@ -1,6 +1,6 @@
 <template>
   <div class="process-panel__container" :style="{ width: `${width}px` }">
-    <el-collapse v-model="activeTab">
+    <el-collapse v-model="activeTab" v-if="isReady">
       <el-collapse-item name="base">
         <!-- class="panel-tab__title" -->
         <template #title>
@@ -108,24 +108,16 @@ const elementBusinessObject = ref<any>({}) // 元素 businessObject 镜像,提
 const conditionFormVisible = ref(false) // 流转条件设置
 const formVisible = ref(false) // 表单配置
 const bpmnElement = ref()
+const isReady = ref(false)
 
 provide('prefix', props.prefix)
 provide('width', props.width)
-const bpmnInstances = () => (window as any)?.bpmnInstances
-
-// 监听 props.bpmnModeler 然后 initModels
-const unwatchBpmn = watch(
-  () => props.bpmnModeler,
-  () => {
-    // 避免加载时 流程图 并未加载完成
-    if (!props.bpmnModeler) {
-      console.log('缺少props.bpmnModeler')
-      return
-    }
 
-    console.log('props.bpmnModeler 有值了!!!')
-    const w = window as any
-    w.bpmnInstances = {
+// 初始化 bpmnInstances
+const initBpmnInstances = () => {
+  if (!props.bpmnModeler) return false
+  try {
+    const instances = {
       modeler: props.bpmnModeler,
       modeling: props.bpmnModeler.get('modeling'),
       moddle: props.bpmnModeler.get('moddle'),
@@ -136,10 +128,46 @@ const unwatchBpmn = watch(
       replace: props.bpmnModeler.get('replace'),
       selection: props.bpmnModeler.get('selection')
     }
+    
+    // 检查所有实例是否都存在
+    const allInstancesExist = Object.values(instances).every(instance => instance)
+    if (allInstancesExist) {
+      const w = window as any
+      w.bpmnInstances = instances
+      return true
+    }
+    return false
+  } catch (error) {
+    console.error('初始化 bpmnInstances 失败:', error)
+    return false
+  }
+}
+
+const bpmnInstances = () => (window as any)?.bpmnInstances
+
+// 监听 props.bpmnModeler 然后 initModels
+const unwatchBpmn = watch(
+  () => props.bpmnModeler,
+  async () => {
+    // 避免加载时 流程图 并未加载完成
+    if (!props.bpmnModeler) {
+      console.log('缺少props.bpmnModeler')
+      return
+    }
 
-    console.log(bpmnInstances(), 'window.bpmnInstances')
-    getActiveElement()
-    unwatchBpmn()
+    try {
+      // 等待 modeler 初始化完成
+      await nextTick()
+      if (initBpmnInstances()) {
+        isReady.value = true
+        await nextTick()
+        getActiveElement()
+      } else {
+        console.error('modeler 实例未完全初始化')
+      }
+    } catch (error) {
+      console.error('初始化失败:', error)
+    }
   },
   {
     immediate: true
@@ -147,6 +175,8 @@ const unwatchBpmn = watch(
 )
 
 const getActiveElement = () => {
+  if (!isReady.value || !props.bpmnModeler) return
+
   // 初始第一个选中元素 bpmn:Process
   initFormOnChanged(null)
   props.bpmnModeler.on('import.done', (e) => {
@@ -164,8 +194,11 @@ const getActiveElement = () => {
     }
   })
 }
+
 // 初始化数据
 const initFormOnChanged = (element) => {
+  if (!isReady.value || !bpmnInstances()) return
+
   let activatedElement = element
   if (!activatedElement) {
     activatedElement =
@@ -173,32 +206,36 @@ const initFormOnChanged = (element) => {
       bpmnInstances().elementRegistry.find((el) => el.type === 'bpmn:Collaboration')
   }
   if (!activatedElement) return
-  console.log(`
-              ----------
-      select element changed:
-                id:  ${activatedElement.id}
-              type:  ${activatedElement.businessObject.$type}
-              ----------
-              `)
-  console.log('businessObject: ', activatedElement.businessObject)
-  bpmnInstances().bpmnElement = activatedElement
-  bpmnElement.value = activatedElement
-  elementId.value = activatedElement.id
-  elementType.value = activatedElement.type.split(':')[1] || ''
-  elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
-  conditionFormVisible.value = !!(
-    elementType.value === 'SequenceFlow' &&
-    activatedElement.source &&
-    activatedElement.source.type.indexOf('StartEvent') === -1
-  )
-  formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
+
+  try {
+    console.log(`
+                ----------
+        select element changed:
+                  id:  ${activatedElement.id}
+                type:  ${activatedElement.businessObject.$type}
+                ----------
+                `)
+    console.log('businessObject: ', activatedElement.businessObject)
+    bpmnInstances().bpmnElement = activatedElement
+    bpmnElement.value = activatedElement
+    elementId.value = activatedElement.id
+    elementType.value = activatedElement.type.split(':')[1] || ''
+    elementBusinessObject.value = JSON.parse(JSON.stringify(activatedElement.businessObject))
+    conditionFormVisible.value = !!(
+      elementType.value === 'SequenceFlow' &&
+      activatedElement.source &&
+      activatedElement.source.type.indexOf('StartEvent') === -1
+    )
+    formVisible.value = elementType.value === 'UserTask' || elementType.value === 'StartEvent'
+  } catch (error) {
+    console.error('初始化表单数据失败:', error)
+  }
 }
 
 onBeforeUnmount(() => {
   const w = window as any
   w.bpmnInstances = null
-  console.log(props, 'props1')
-  console.log(props.bpmnModeler, 'props.bpmnModeler1')
+  isReady.value = false
 })
 
 watch(
@@ -208,3 +245,10 @@ watch(
   }
 )
 </script>
+<style lang="scss">
+.process-panel__container {
+  position: absolute;
+  top: 90px;
+  right: 60px;
+}
+</style>

+ 35 - 6
src/views/bpm/model/CreateUpdate.vue

@@ -274,6 +274,7 @@
       <!-- BPMN设计器 -->
       <template v-if="formData.type === BpmModelType.BPMN">
         <BpmModelEditor
+          v-if="showDesigner"
           :model-id="formData.id"
           :model-key="formData.key"
           :model-name="formData.name"
@@ -284,6 +285,7 @@
       <!-- Simple设计器 -->
       <template v-else>
         <SimpleModelDesign
+          v-if="showDesigner"
           :model-id="formData.id"
           :model-key="formData.key"
           :model-name="formData.name"
@@ -547,16 +549,43 @@ const handleDesignSuccess = (bpmnXml?: string) => {
 // 步骤切换处理
 const handleStepClick = async (index: number) => {
   // 如果是切换到第三步(流程设计),需要校验key和name
-  if (index === 2 && !formData.value.id) {
-    // 新增时才校验
-    if (!formData.value.key || !formData.value.name) {
-      message.warning('请先填写流程标识和流程名称')
-      return
+  if (index === 2) {
+    if (!formData.value.id) {
+      // 新增时才校验
+      try {
+        await formRef.value?.validateField(['key', 'name'])
+        // 确保数据已经准备好
+        await nextTick()
+      } catch (error) {
+        message.warning('请先填写流程标识和流程名称')
+        return
+      }
     }
+    // 确保数据已经准备好再切换
+    await nextTick()
   }
-
   currentStep.value = index
 }
+
+// 添加一个计算属性来判断是否显示设计器
+const showDesigner = computed(() => {
+  return currentStep.value === 2 && Boolean(formData.value.id || (formData.value.key && formData.value.name))
+})
+
+// 监听步骤变化,确保数据准备完成
+watch(() => currentStep.value, async (newStep) => {
+  if (newStep === 2) {
+    await nextTick()
+  }
+}, { immediate: false })
+
+// 在组件卸载时清理
+onBeforeUnmount(() => {
+  const w = window as any
+  if (w.bpmnInstances) {
+    w.bpmnInstances = null
+  }
+})
 </script>
 
 <style lang="scss" scoped>

+ 91 - 27
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"
@@ -16,8 +15,9 @@
     />
     <!-- 流程属性器,负责编辑每个流程节点的属性 -->
     <MyProcessPenal
+      v-if="isModelerReady && modeler"
       key="penal"
-      :bpmnModeler="modeler as any"
+      :bpmnModeler="modeler"
       :prefix="controlForm.prefix"
       class="process-panel"
       :model="model"
@@ -44,8 +44,10 @@ const props = defineProps<{
 const emit = defineEmits(['success'])
 const message = useMessage() // 国际化
 
-const xmlString = ref<string>() // 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,
@@ -56,11 +58,49 @@ const controlForm = ref({
 })
 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
+      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 */
@@ -97,9 +137,9 @@ const save = async (bpmnXml: string) => {
 
 /** 初始化 */
 onMounted(async () => {
-  if (props.modelId) {
-    // 编辑模式
-    try {
+  try {
+    if (props.modelId) {
+      // 编辑模式
       // 查询模型
       const data = await ModelApi.getModel(props.modelId)
       model.value = {
@@ -107,30 +147,54 @@ onMounted(async () => {
         bpmnXml: undefined // 清空 bpmnXml 属性
       }
       xmlString.value = data.bpmnXml || getDefaultBpmnXml(data.key, data.name)
-    } catch (error) {
-      console.error('获取模型失败:', error)
-      message.error('获取模型失败')
+    } else if (props.modelKey && props.modelName) {
+      // 新建模式
+      xmlString.value = getDefaultBpmnXml(props.modelKey, props.modelName)
+      model.value = {
+        key: props.modelKey,
+        name: props.modelName
+      } as ModelApi.ModelVO
     }
-  } else if (props.modelKey && props.modelName) {
-    // 新建模式,使用传入的key和name创建默认XML
-    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('初始化失败')
   }
 })
 
-// 监听key和name的变化
-watch([() => props.modelKey, () => props.modelName], ([newKey, newName]) => {
-  if (!props.modelId && newKey && newName) {
-    xmlString.value = getDefaultBpmnXml(newKey, newName)
+// 更新模型数据
+const updateModelData = async (key?: string, name?: string) => {
+  if (key && name) {
+    xmlString.value = getDefaultBpmnXml(key, name)
     model.value = {
-      key: newKey,
-      name: newName
+      ...model.value,
+      key: key,
+      name: name
     } as ModelApi.ModelVO
+    // 确保更新后重新渲染
+    await nextTick()
+    if (processDesigner.value?.refresh) {
+      processDesigner.value.refresh()
+    }
   }
-}, { immediate: true })
+}
+
+// 监听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
+  }
+})
 </script>
 <style lang="scss">
 .process-panel__container {

+ 10 - 1
src/views/bpm/simple/SimpleModelDesign.vue

@@ -5,6 +5,7 @@
       :model-key="modelKey"
       :model-name="modelName"
       @success="handleSuccess" 
+      ref="designerRef"
     />
   </ContentWrap>
 </template>
@@ -15,13 +16,21 @@ defineOptions({
   name: 'SimpleModelDesign'
 })
 
-defineProps<{
+const props = defineProps<{
   modelId?: string
   modelKey?: string
   modelName?: string
 }>()
 
 const emit = defineEmits(['success'])
+const designerRef = ref()
+
+// 监听属性变化
+watch([() => props.modelKey, () => props.modelName], ([newKey, newName]) => {
+  if (designerRef.value && newKey && newName) {
+    designerRef.value.updateModel(newKey, newName)
+  }
+}, { immediate: true, deep: true })
 
 // 修改成功回调
 const handleSuccess = (data?: any) => {