From a1d7e81859f554f3a53680cc35f0f49bf1f77098 Mon Sep 17 00:00:00 2001
From: wwf <1971391498@qq.com>
Date: 星期四, 14 五月 2026 14:37:02 +0800
Subject: [PATCH] 导入项目

---
 src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue |  421 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 421 insertions(+), 0 deletions(-)

diff --git a/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue b/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue
new file mode 100644
index 0000000..99ee6f8
--- /dev/null
+++ b/src/components/bpmnProcessDesigner/package/penal/multi-instance/ElementMultiInstance.vue
@@ -0,0 +1,421 @@
+<template>
+  <div class="panel-tab__content">
+    <el-radio-group
+      v-if="type === 'UserTask'"
+      v-model="approveMethod"
+      @change="onApproveMethodChange"
+    >
+      <div class="flex-col">
+        <div v-for="(item, index) in APPROVE_METHODS" :key="index">
+          <el-radio :value="item.value" :label="item.value">
+            {{ item.label }}
+          </el-radio>
+          <el-form-item prop="approveRatio">
+            <el-input-number
+              v-model="approveRatio"
+              :min="10"
+              :max="100"
+              :step="10"
+              size="small"
+              v-if="
+                item.value === ApproveMethodType.APPROVE_BY_RATIO &&
+                approveMethod === ApproveMethodType.APPROVE_BY_RATIO
+              "
+              @change="onApproveRatioChange"
+            />
+          </el-form-item>
+        </div>
+      </div>
+    </el-radio-group>
+    <div v-else>
+      闄や簡UserTask浠ュ鑺傜偣鐨勫瀹炰緥寰呭疄鐜�
+    </div>
+    <!-- 涓嶴imple璁捐鍣ㄩ厤缃悎骞讹紝淇濈暀浠ュ墠鐨勪唬鐮� -->
+    <el-form label-width="90px" style="display: none">
+      <el-form-item label="蹇嵎閰嶇疆">
+        <el-button size="small" @click="changeConfig('渚濇瀹℃壒')">渚濇瀹℃壒</el-button>
+        <el-button size="small" @click="changeConfig('浼氱')">浼氱</el-button>
+        <el-button size="small" @click="changeConfig('鎴栫')">鎴栫</el-button>
+      </el-form-item>
+      <el-form-item label="浼氱绫诲瀷">
+        <el-select v-model="loopCharacteristics" @change="changeLoopCharacteristicsType">
+          <el-option label="骞惰澶氶噸浜嬩欢" value="ParallelMultiInstance" />
+          <el-option label="鏃跺簭澶氶噸浜嬩欢" value="SequentialMultiInstance" />
+          <el-option label="鏃�" value="Null" />
+        </el-select>
+      </el-form-item>
+      <template
+        v-if="
+          loopCharacteristics === 'ParallelMultiInstance' ||
+          loopCharacteristics === 'SequentialMultiInstance'
+        "
+      >
+        <el-form-item label="寰幆鏁伴噺" key="loopCardinality">
+          <el-input
+            v-model="loopInstanceForm.loopCardinality"
+            clearable
+            @change="updateLoopCardinality"
+          />
+        </el-form-item>
+        <el-form-item label="闆嗗悎" key="collection" v-show="false">
+          <el-input v-model="loopInstanceForm.collection" clearable @change="updateLoopBase" />
+        </el-form-item>
+        <!-- add by 鑺嬭壙锛氱敱浜庛�屽厓绱犲彉閲忋�嶆殏鏃剁敤涓嶅埌锛屾墍浠ヨ繖閲� display 涓� none -->
+        <el-form-item label="鍏冪礌鍙橀噺" key="elementVariable" style="display: none">
+          <el-input v-model="loopInstanceForm.elementVariable" clearable @change="updateLoopBase" />
+        </el-form-item>
+        <el-form-item label="瀹屾垚鏉′欢" key="completionCondition">
+          <el-input
+            v-model="loopInstanceForm.completionCondition"
+            clearable
+            @change="updateLoopCondition"
+          />
+        </el-form-item>
+        <!-- add by 鑺嬭壙锛氱敱浜庛�屽紓姝ョ姸鎬併�嶆殏鏃剁敤涓嶅埌锛屾墍浠ヨ繖閲� display 涓� none -->
+        <el-form-item label="寮傛鐘舵��" key="async" style="display: none">
+          <el-checkbox
+            v-model="loopInstanceForm.asyncBefore"
+            label="寮傛鍓�"
+            value="寮傛鍓�"
+            @change="updateLoopAsync('asyncBefore')"
+          />
+          <el-checkbox
+            v-model="loopInstanceForm.asyncAfter"
+            label="寮傛鍚�"
+            value="寮傛鍚�"
+            @change="updateLoopAsync('asyncAfter')"
+          />
+          <el-checkbox
+            v-model="loopInstanceForm.exclusive"
+            v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
+            label="鎺掗櫎"
+            value="鎺掗櫎"
+            @change="updateLoopAsync('exclusive')"
+          />
+        </el-form-item>
+        <el-form-item
+          label="閲嶈瘯鍛ㄦ湡"
+          prop="timeCycle"
+          v-if="loopInstanceForm.asyncAfter || loopInstanceForm.asyncBefore"
+          key="timeCycle"
+        >
+          <el-input v-model="loopInstanceForm.timeCycle" clearable @change="updateLoopTimeCycle" />
+        </el-form-item>
+      </template>
+    </el-form>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ApproveMethodType, APPROVE_METHODS } from '@/components/SimpleProcessDesignerV2/src/consts'
+
+defineOptions({ name: 'ElementMultiInstance' })
+
+const props = defineProps({
+  businessObject: Object,
+  type: String,
+  id: String
+})
+const prefix = inject('prefix')
+const loopCharacteristics = ref('')
+//榛樿閰嶇疆锛岀敤鏉ヨ鐩栧師濮嬩笉瀛樺湪鐨勯�夐」锛岄伩鍏嶆姤閿�
+const defaultLoopInstanceForm = ref({
+  completionCondition: '',
+  loopCardinality: '',
+  extensionElements: [],
+  asyncAfter: false,
+  asyncBefore: false,
+  exclusive: false
+})
+const loopInstanceForm = ref<any>({})
+const bpmnElement = ref(null)
+const multiLoopInstance = ref(null)
+const bpmnInstances = () => (window as any)?.bpmnInstances
+
+const getElementLoop = (businessObject) => {
+  if (!businessObject.loopCharacteristics) {
+    loopCharacteristics.value = 'Null'
+    loopInstanceForm.value = {}
+    return
+  }
+  if (businessObject.loopCharacteristics.$type === 'bpmn:StandardLoopCharacteristics') {
+    loopCharacteristics.value = 'StandardLoop'
+    loopInstanceForm.value = {}
+    return
+  }
+  if (businessObject.loopCharacteristics.isSequential) {
+    loopCharacteristics.value = 'SequentialMultiInstance'
+  } else {
+    loopCharacteristics.value = 'ParallelMultiInstance'
+  }
+  // 鍚堝苟閰嶇疆
+  loopInstanceForm.value = {
+    ...defaultLoopInstanceForm.value,
+    ...businessObject.loopCharacteristics,
+    completionCondition: businessObject.loopCharacteristics?.completionCondition?.body ?? '',
+    loopCardinality: businessObject.loopCharacteristics?.loopCardinality?.body ?? ''
+  }
+  // 淇濈暀褰撳墠鍏冪礌 businessObject 涓婄殑 loopCharacteristics 瀹炰緥
+  multiLoopInstance.value = bpmnInstances().bpmnElement.businessObject.loopCharacteristics
+  // 鏇存柊琛ㄥ崟
+  if (
+    businessObject.loopCharacteristics.extensionElements &&
+    businessObject.loopCharacteristics.extensionElements.values &&
+    businessObject.loopCharacteristics.extensionElements.values.length
+  ) {
+    loopInstanceForm.value['timeCycle'] =
+      businessObject.loopCharacteristics.extensionElements.values[0].body
+  }
+}
+
+const changeLoopCharacteristicsType = (type) => {
+  // this.loopInstanceForm = { ...this.defaultLoopInstanceForm }; // 鍒囨崲绫诲瀷鍙栨秷鍘熻〃鍗曢厤缃�
+  // 鍙栨秷澶氬疄渚嬮厤缃�
+  if (type === 'Null') {
+    bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+      loopCharacteristics: null
+    })
+    return
+  }
+  // 閰嶇疆寰幆
+  if (type === 'StandardLoop') {
+    const loopCharacteristicsObject = bpmnInstances().moddle.create(
+      'bpmn:StandardLoopCharacteristics'
+    )
+    bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+      loopCharacteristics: loopCharacteristicsObject
+    })
+    multiLoopInstance.value = null
+    return
+  }
+  // 鏃跺簭
+  if (type === 'SequentialMultiInstance') {
+    multiLoopInstance.value = bpmnInstances().moddle.create(
+      'bpmn:MultiInstanceLoopCharacteristics',
+      { isSequential: true }
+    )
+  } else {
+    multiLoopInstance.value = bpmnInstances().moddle.create(
+      'bpmn:MultiInstanceLoopCharacteristics',
+      { collection: '${coll_userList}' }
+    )
+  }
+  bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+    loopCharacteristics: toRaw(multiLoopInstance.value)
+  })
+}
+
+// 寰幆鍩烘暟
+const updateLoopCardinality = (cardinality) => {
+  let loopCardinality = null
+  if (cardinality && cardinality.length) {
+    loopCardinality = bpmnInstances().moddle.create('bpmn:FormalExpression', {
+      body: cardinality
+    })
+  }
+  bpmnInstances().modeling.updateModdleProperties(
+    toRaw(bpmnElement.value),
+    multiLoopInstance.value,
+    {
+      loopCardinality
+    }
+  )
+}
+
+// 瀹屾垚鏉′欢
+const updateLoopCondition = (condition) => {
+  let completionCondition = null
+  if (condition && condition.length) {
+    completionCondition = bpmnInstances().moddle.create('bpmn:FormalExpression', {
+      body: condition
+    })
+  }
+  bpmnInstances().modeling.updateModdleProperties(
+    toRaw(bpmnElement.value),
+    multiLoopInstance.value,
+    {
+      completionCondition
+    }
+  )
+}
+
+// 閲嶈瘯鍛ㄦ湡
+const updateLoopTimeCycle = (timeCycle) => {
+  const extensionElements = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
+    values: [
+      bpmnInstances().moddle.create(`${prefix}:FailedJobRetryTimeCycle`, {
+        body: timeCycle
+      })
+    ]
+  })
+  bpmnInstances().modeling.updateModdleProperties(
+    toRaw(bpmnElement.value),
+    multiLoopInstance.value,
+    {
+      extensionElements
+    }
+  )
+}
+
+// 鐩存帴鏇存柊鐨勫熀纭�淇℃伅
+const updateLoopBase = () => {
+  bpmnInstances().modeling.updateModdleProperties(
+    toRaw(bpmnElement.value),
+    multiLoopInstance.value,
+    {
+      collection: loopInstanceForm.value.collection || null,
+      elementVariable: loopInstanceForm.value.elementVariable || null
+    }
+  )
+}
+
+// 鍚勫紓姝ョ姸鎬�
+const updateLoopAsync = (key) => {
+  const { asyncBefore, asyncAfter } = loopInstanceForm.value
+  let asyncAttr = Object.create(null)
+  if (!asyncBefore && !asyncAfter) {
+    // this.$set(this.loopInstanceForm, "exclusive", false);
+    loopInstanceForm.value['exclusive'] = false
+    asyncAttr = { asyncBefore: false, asyncAfter: false, exclusive: false, extensionElements: null }
+  } else {
+    asyncAttr[key] = loopInstanceForm.value[key]
+  }
+  bpmnInstances().modeling.updateModdleProperties(
+    toRaw(bpmnElement.value),
+    multiLoopInstance.value,
+    asyncAttr
+  )
+}
+
+const changeConfig = (config) => {
+  if (config === '渚濇瀹℃壒') {
+    changeLoopCharacteristicsType('SequentialMultiInstance')
+    updateLoopCardinality('1')
+    updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
+  } else if (config === '浼氱') {
+    changeLoopCharacteristicsType('ParallelMultiInstance')
+    updateLoopCondition('${ nrOfCompletedInstances >= nrOfInstances }')
+  } else if (config === '鎴栫') {
+    changeLoopCharacteristicsType('ParallelMultiInstance')
+    updateLoopCondition('${ nrOfCompletedInstances > 0 }')
+  }
+}
+
+/**
+ * -----鏂扮増鏈瀹炰緥-----
+ */
+const approveMethod = ref()
+const approveRatio = ref(100)
+const otherExtensions = ref()
+const getElementLoopNew = () => {
+  if (props.type === 'UserTask') {
+    const extensionElements =
+      bpmnElement.value.businessObject?.extensionElements ??
+      bpmnInstances().moddle.create('bpmn:ExtensionElements', { values: [] })
+    approveMethod.value = extensionElements.values.filter(
+      (ex) => ex.$type === `${prefix}:ApproveMethod`
+    )?.[0]?.value
+
+    otherExtensions.value =
+      extensionElements.values.filter((ex) => ex.$type !== `${prefix}:ApproveMethod`) ?? []
+
+    if (!approveMethod.value) {
+      approveMethod.value = ApproveMethodType.SEQUENTIAL_APPROVE
+      updateLoopCharacteristics()
+    }
+  }
+}
+const onApproveMethodChange = () => {
+  approveRatio.value = 100
+  updateLoopCharacteristics()
+}
+const onApproveRatioChange = () => {
+  updateLoopCharacteristics()
+}
+const updateLoopCharacteristics = () => {
+  // 鏍规嵁ApproveMethod鐢熸垚multiInstanceLoopCharacteristics鑺傜偣
+  if (approveMethod.value === ApproveMethodType.RANDOM_SELECT_ONE_APPROVE) {
+    bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+      loopCharacteristics: null
+    })
+  } else {
+    if (approveMethod.value === ApproveMethodType.APPROVE_BY_RATIO) {
+      multiLoopInstance.value = bpmnInstances().moddle.create(
+        'bpmn:MultiInstanceLoopCharacteristics',
+        { isSequential: false, collection: '${coll_userList}' }
+      )
+      multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
+        'bpmn:FormalExpression',
+        {
+          body: '${ nrOfCompletedInstances/nrOfInstances >= ' + approveRatio.value / 100 + '}'
+        }
+      )
+    }
+    if (approveMethod.value === ApproveMethodType.ANY_APPROVE) {
+      multiLoopInstance.value = bpmnInstances().moddle.create(
+        'bpmn:MultiInstanceLoopCharacteristics',
+        { isSequential: false, collection: '${coll_userList}' }
+      )
+      multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
+        'bpmn:FormalExpression',
+        {
+          body: '${ nrOfCompletedInstances > 0 }'
+        }
+      )
+    }
+    if (approveMethod.value === ApproveMethodType.SEQUENTIAL_APPROVE) {
+      multiLoopInstance.value = bpmnInstances().moddle.create(
+        'bpmn:MultiInstanceLoopCharacteristics',
+        { isSequential: true, collection: '${coll_userList}' }
+      )
+      multiLoopInstance.value.loopCardinality = bpmnInstances().moddle.create(
+        'bpmn:FormalExpression',
+        {
+          body: '1'
+        }
+      )
+      multiLoopInstance.value.completionCondition = bpmnInstances().moddle.create(
+        'bpmn:FormalExpression',
+        {
+          body: '${ nrOfCompletedInstances >= nrOfInstances }'
+        }
+      )
+    }
+    bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+      loopCharacteristics: toRaw(multiLoopInstance.value)
+    })
+  }
+
+  // 娣诲姞ApproveMethod鍒癊xtensionElements
+  const extensions = bpmnInstances().moddle.create('bpmn:ExtensionElements', {
+    values: [
+      ...otherExtensions.value,
+      bpmnInstances().moddle.create(`${prefix}:ApproveMethod`, {
+        value: approveMethod.value
+      })
+    ]
+  })
+  bpmnInstances().modeling.updateProperties(toRaw(bpmnElement.value), {
+    extensionElements: extensions
+  })
+}
+
+onBeforeUnmount(() => {
+  multiLoopInstance.value = null
+  bpmnElement.value = null
+})
+
+watch(
+  () => props.id,
+  (val) => {
+    if (val) {
+      nextTick(() => {
+        bpmnElement.value = bpmnInstances().bpmnElement
+        // getElementLoop(val)
+        getElementLoopNew()
+      })
+    }
+  },
+  { immediate: true }
+)
+</script>

--
Gitblit v1.8.0