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/listeners/UserTaskListeners.vue |  510 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 510 insertions(+), 0 deletions(-)

diff --git a/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue b/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue
new file mode 100644
index 0000000..cea9f1b
--- /dev/null
+++ b/src/components/bpmnProcessDesigner/package/penal/listeners/UserTaskListeners.vue
@@ -0,0 +1,510 @@
+<template>
+  <div class="panel-tab__content">
+    <el-table :data="elementListenersList" size="small" border>
+      <el-table-column label="搴忓彿" width="50px" type="index" />
+      <el-table-column
+        label="浜嬩欢绫诲瀷"
+        min-width="80px"
+        show-overflow-tooltip
+        :formatter="(row) => listenerEventTypeObject[row.event]"
+      />
+      <el-table-column label="浜嬩欢id" min-width="80px" prop="id" show-overflow-tooltip />
+      <el-table-column
+        label="鐩戝惉鍣ㄧ被鍨�"
+        min-width="80px"
+        show-overflow-tooltip
+        :formatter="(row) => listenerTypeObject[row.listenerType]"
+      />
+      <el-table-column label="鎿嶄綔" width="90px">
+        <template #default="scope">
+          <el-button size="small" link @click="openListenerForm(scope.row, scope.$index)"
+            >缂栬緫</el-button
+          >
+          <el-divider direction="vertical" />
+          <el-button
+            size="small"
+            link
+            style="color: #ff4d4f"
+            @click="removeListener(scope.row, scope.$index)"
+            >绉婚櫎</el-button
+          >
+        </template>
+      </el-table-column>
+    </el-table>
+    <div class="element-drawer__button">
+      <XButton
+        size="small"
+        type="primary"
+        preIcon="ep:plus"
+        title="娣诲姞鐩戝惉鍣�"
+        @click="openListenerForm(null)"
+      />
+      <XButton
+        type="success"
+        preIcon="ep:select"
+        title="閫夋嫨鐩戝惉鍣�"
+        size="small"
+        @click="openProcessListenerDialog"
+      />
+    </div>
+
+    <!-- 鐩戝惉鍣� 缂栬緫/鍒涘缓 閮ㄥ垎 -->
+    <el-drawer
+      v-model="listenerFormModelVisible"
+      title="浠诲姟鐩戝惉鍣�"
+      :size="`${width}px`"
+      append-to-body
+      destroy-on-close
+    >
+      <el-form size="small" :model="listenerForm" label-width="96px" ref="listenerFormRef">
+        <el-form-item
+          label="浜嬩欢绫诲瀷"
+          prop="event"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-select v-model="listenerForm.event">
+            <el-option
+              v-for="i in Object.keys(listenerEventTypeObject)"
+              :key="i"
+              :label="listenerEventTypeObject[i]"
+              :value="i"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          label="鐩戝惉鍣↖D"
+          prop="id"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerForm.id" clearable />
+        </el-form-item>
+        <el-form-item
+          label="鐩戝惉鍣ㄧ被鍨�"
+          prop="listenerType"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-select v-model="listenerForm.listenerType">
+            <el-option
+              v-for="i in Object.keys(listenerTypeObject)"
+              :key="i"
+              :label="listenerTypeObject[i]"
+              :value="i"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          v-if="listenerForm.listenerType === 'classListener'"
+          label="Java绫�"
+          prop="class"
+          key="listener-class"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerForm.class" clearable />
+        </el-form-item>
+        <el-form-item
+          v-if="listenerForm.listenerType === 'expressionListener'"
+          label="琛ㄨ揪寮�"
+          prop="expression"
+          key="listener-expression"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerForm.expression" clearable />
+        </el-form-item>
+        <el-form-item
+          v-if="listenerForm.listenerType === 'delegateExpressionListener'"
+          label="浠g悊琛ㄨ揪寮�"
+          prop="delegateExpression"
+          key="listener-delegate"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerForm.delegateExpression" clearable />
+        </el-form-item>
+        <template v-if="listenerForm.listenerType === 'scriptListener'">
+          <el-form-item
+            label="鑴氭湰鏍煎紡"
+            prop="scriptFormat"
+            key="listener-script-format"
+            :rules="{ required: true, trigger: ['blur', 'change'], message: '璇峰~鍐欒剼鏈牸寮�' }"
+          >
+            <el-input v-model="listenerForm.scriptFormat" clearable />
+          </el-form-item>
+          <el-form-item
+            label="鑴氭湰绫诲瀷"
+            prop="scriptType"
+            key="listener-script-type"
+            :rules="{ required: true, trigger: ['blur', 'change'], message: '璇烽�夋嫨鑴氭湰绫诲瀷' }"
+          >
+            <el-select v-model="listenerForm.scriptType">
+              <el-option label="鍐呰仈鑴氭湰" value="inlineScript" />
+              <el-option label="澶栭儴鑴氭湰" value="externalScript" />
+            </el-select>
+          </el-form-item>
+          <el-form-item
+            v-if="listenerForm.scriptType === 'inlineScript'"
+            label="鑴氭湰鍐呭"
+            prop="value"
+            key="listener-script"
+            :rules="{ required: true, trigger: ['blur', 'change'], message: '璇峰~鍐欒剼鏈唴瀹�' }"
+          >
+            <el-input v-model="listenerForm.value" clearable />
+          </el-form-item>
+          <el-form-item
+            v-if="listenerForm.scriptType === 'externalScript'"
+            label="璧勬簮鍦板潃"
+            prop="resource"
+            key="listener-resource"
+            :rules="{ required: true, trigger: ['blur', 'change'], message: '璇峰~鍐欒祫婧愬湴鍧�' }"
+          >
+            <el-input v-model="listenerForm.resource" clearable />
+          </el-form-item>
+        </template>
+
+        <template v-if="listenerForm.event === 'timeout'">
+          <el-form-item label="瀹氭椂鍣ㄧ被鍨�" prop="eventDefinitionType" key="eventDefinitionType">
+            <el-select v-model="listenerForm.eventDefinitionType">
+              <el-option label="鏃ユ湡" value="date" />
+              <el-option label="鎸佺画鏃堕暱" value="duration" />
+              <el-option label="寰幆" value="cycle" />
+              <el-option label="鏃�" value="null" />
+            </el-select>
+          </el-form-item>
+          <el-form-item
+            v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
+            label="瀹氭椂鍣�"
+            prop="eventTimeDefinitions"
+            key="eventTimeDefinitions"
+            :rules="{ required: true, trigger: ['blur', 'change'], message: '璇峰~鍐欏畾鏃跺櫒閰嶇疆' }"
+          >
+            <el-input v-model="listenerForm.eventTimeDefinitions" clearable />
+          </el-form-item>
+        </template>
+      </el-form>
+
+      <el-divider />
+      <p class="listener-filed__title">
+        <span><Icon icon="ep:menu" />娉ㄥ叆瀛楁锛�</span>
+        <el-button size="small" type="primary" @click="openListenerFieldForm(null)"
+          >娣诲姞瀛楁</el-button
+        >
+      </p>
+      <el-table
+        :data="fieldsListOfListener"
+        size="small"
+        max-height="240"
+        fit
+        border
+        style="flex: none"
+      >
+        <el-table-column label="搴忓彿" width="50px" type="index" />
+        <el-table-column label="瀛楁鍚嶇О" min-width="100px" prop="name" />
+        <el-table-column
+          label="瀛楁绫诲瀷"
+          min-width="80px"
+          show-overflow-tooltip
+          :formatter="(row) => fieldTypeObject[row.fieldType]"
+        />
+        <el-table-column
+          label="瀛楁鍊�/琛ㄨ揪寮�"
+          min-width="100px"
+          show-overflow-tooltip
+          :formatter="(row) => row.string || row.expression"
+        />
+        <el-table-column label="鎿嶄綔" width="100px">
+          <template #default="scope">
+            <el-button size="small" link @click="openListenerFieldForm(scope.row, scope.$index)"
+              >缂栬緫</el-button
+            >
+            <el-divider direction="vertical" />
+            <el-button
+              size="small"
+              link
+              style="color: #ff4d4f"
+              @click="removeListenerField(scope.row, scope.$index)"
+              >绉婚櫎</el-button
+            >
+          </template>
+        </el-table-column>
+      </el-table>
+
+      <div class="element-drawer__button">
+        <el-button size="small" @click="listenerFormModelVisible = false">鍙� 娑�</el-button>
+        <el-button size="small" type="primary" @click="saveListenerConfig">淇� 瀛�</el-button>
+      </div>
+    </el-drawer>
+
+    <!-- 娉ㄥ叆瑗挎 缂栬緫/鍒涘缓 閮ㄥ垎 -->
+    <el-dialog
+      title="瀛楁閰嶇疆"
+      v-model="listenerFieldFormModelVisible"
+      width="600px"
+      append-to-body
+      destroy-on-close
+    >
+      <el-form
+        :model="listenerFieldForm"
+        size="small"
+        label-width="96px"
+        ref="listenerFieldFormRef"
+        style="height: 136px"
+      >
+        <el-form-item
+          label="瀛楁鍚嶇О锛�"
+          prop="name"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerFieldForm.name" clearable />
+        </el-form-item>
+        <el-form-item
+          label="瀛楁绫诲瀷锛�"
+          prop="fieldType"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-select v-model="listenerFieldForm.fieldType">
+            <el-option
+              v-for="i in Object.keys(fieldTypeObject)"
+              :key="i"
+              :label="fieldTypeObject[i]"
+              :value="i"
+            />
+          </el-select>
+        </el-form-item>
+        <el-form-item
+          v-if="listenerFieldForm.fieldType === 'string'"
+          label="瀛楁鍊硷細"
+          prop="string"
+          key="field-string"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerFieldForm.string" clearable />
+        </el-form-item>
+        <el-form-item
+          v-if="listenerFieldForm.fieldType === 'expression'"
+          label="琛ㄨ揪寮忥細"
+          prop="expression"
+          key="field-expression"
+          :rules="{ required: true, trigger: ['blur', 'change'] }"
+        >
+          <el-input v-model="listenerFieldForm.expression" clearable />
+        </el-form-item>
+      </el-form>
+      <template #footer>
+        <el-button size="small" @click="listenerFieldFormModelVisible = false">鍙� 娑�</el-button>
+        <el-button size="small" type="primary" @click="saveListenerFiled">纭� 瀹�</el-button>
+      </template>
+    </el-dialog>
+  </div>
+
+  <!-- 閫夋嫨寮圭獥 -->
+  <ProcessListenerDialog ref="processListenerDialogRef" @select="selectProcessListener" />
+</template>
+<script lang="ts" setup>
+import { ElMessageBox } from 'element-plus'
+import { createListenerObject, updateElementExtensions } from '../../utils'
+import {
+  initListenerForm,
+  initListenerType,
+  eventType,
+  listenerType,
+  fieldType,
+  initListenerForm2
+} from './utilSelf'
+import ProcessListenerDialog from '@/components/bpmnProcessDesigner/package/penal/listeners/ProcessListenerDialog.vue'
+
+defineOptions({ name: 'UserTaskListeners' })
+
+const props = defineProps({
+  id: String,
+  type: String
+})
+const prefix = inject('prefix')
+const width = inject('width')
+const elementListenersList = ref<any[]>([])
+const listenerEventTypeObject = ref(eventType)
+const listenerTypeObject = ref(listenerType)
+const listenerFormModelVisible = ref(false)
+const listenerForm = ref<any>({})
+const fieldTypeObject = ref(fieldType)
+const fieldsListOfListener = ref<any[]>([])
+const listenerFieldFormModelVisible = ref(false) // 鐩戝惉鍣� 娉ㄥ叆瀛楁琛ㄥ崟寮圭獥 鏄剧ず鐘舵��
+const editingListenerIndex = ref(-1) // 鐩戝惉鍣ㄦ墍鍦ㄤ笅鏍囷紝-1 涓烘柊澧�
+const editingListenerFieldIndex = ref(-1) // 瀛楁鎵�鍦ㄤ笅鏍囷紝-1 涓烘柊澧�
+const listenerFieldForm = ref<any>({}) // 鐩戝惉鍣� 娉ㄥ叆瀛楁 璇︽儏琛ㄥ崟
+const bpmnElementListeners = ref()
+const otherExtensionList = ref()
+const listenerFormRef = ref()
+const listenerFieldFormRef = ref()
+const bpmnInstances = () => (window as any)?.bpmnInstances
+
+const resetListenersList = () => {
+  const instances = bpmnInstances()
+  if (!instances || !instances.bpmnElement) return
+
+  // 鐩存帴浣跨敤鍘熷BPMN鍏冪礌锛岄伩鍏峍ue鍝嶅簲寮忎唬鐞嗛棶棰�
+  const bpmnElement = instances.bpmnElement
+  const businessObject = bpmnElement.businessObject
+
+  console.log(bpmnElement, 'bpmnElement - resetListenersList')
+
+  otherExtensionList.value =
+    businessObject?.extensionElements?.values?.filter(
+      (ex) => ex.$type !== `${prefix}:TaskListener`
+    ) ?? [] // 淇濈暀闈炵洃鍚櫒绫诲瀷鐨勬墿灞曞睘鎬э紝閬垮厤绉婚櫎鐩戝惉鍣ㄦ椂娓呯┖鍏朵粬閰嶇疆锛堝瀹℃壒浜虹瓑锛夈�傜浉鍏虫渚嬶細https://gitee.com/yudaocode/yudao-ui-admin-vue3/issues/ICMSYC
+  bpmnElementListeners.value =
+    businessObject?.extensionElements?.values?.filter(
+      (ex) => ex.$type === `${prefix}:TaskListener`
+    ) ?? []
+  elementListenersList.value = bpmnElementListeners.value.map((listener) =>
+    initListenerType(listener)
+  )
+}
+const openListenerForm = (listener, index?) => {
+  if (listener) {
+    listenerForm.value = initListenerForm(listener)
+    editingListenerIndex.value = index
+  } else {
+    listenerForm.value = {}
+    editingListenerIndex.value = -1 // 鏍囪涓烘柊澧�
+  }
+  if (listener && listener.fields) {
+    fieldsListOfListener.value = listener.fields.map((field) => ({
+      ...field,
+      fieldType: field.string ? 'string' : 'expression'
+    }))
+  } else {
+    fieldsListOfListener.value = []
+    listenerForm.value['fields'] = []
+  }
+  // 鎵撳紑渚ц竟鏍忓苟娓呮楠岃瘉鐘舵��
+  listenerFormModelVisible.value = true
+  nextTick(() => {
+    if (listenerFormRef.value) listenerFormRef.value.clearValidate()
+  })
+}
+// 绉婚櫎鐩戝惉鍣�
+const removeListener = (listener, index?) => {
+  console.log(listener, 'listener')
+  ElMessageBox.confirm('纭绉婚櫎璇ョ洃鍚櫒鍚楋紵', '鎻愮ず', {
+    confirmButtonText: '纭� 璁�',
+    cancelButtonText: '鍙� 娑�'
+  })
+    .then(() => {
+      const instances = bpmnInstances()
+      if (!instances || !instances.bpmnElement) return
+
+      bpmnElementListeners.value.splice(index, 1)
+      elementListenersList.value.splice(index, 1)
+      updateElementExtensions(
+        instances.bpmnElement,
+        otherExtensionList.value.concat(bpmnElementListeners.value)
+      )
+    })
+    .catch(() => console.info('鎿嶄綔鍙栨秷'))
+}
+// 淇濆瓨鐩戝惉鍣�
+const saveListenerConfig = async () => {
+  let validateStatus = await listenerFormRef.value.validate()
+  if (!validateStatus) return // 楠岃瘉涓嶉�氳繃鐩存帴杩斿洖
+
+  const instances = bpmnInstances()
+  if (!instances || !instances.bpmnElement) return
+
+  const bpmnElement = instances.bpmnElement
+  const listenerObject = createListenerObject(listenerForm.value, true, prefix)
+
+  if (editingListenerIndex.value === -1) {
+    bpmnElementListeners.value.push(listenerObject)
+    elementListenersList.value.push(listenerForm.value)
+  } else {
+    bpmnElementListeners.value.splice(editingListenerIndex.value, 1, listenerObject)
+    elementListenersList.value.splice(editingListenerIndex.value, 1, listenerForm.value)
+  }
+  // 淇濆瓨鍏朵粬閰嶇疆
+  otherExtensionList.value =
+    bpmnElement.businessObject?.extensionElements?.values?.filter(
+      (ex) => ex.$type !== `${prefix}:TaskListener`
+    ) ?? []
+  updateElementExtensions(
+    bpmnElement,
+    otherExtensionList.value.concat(bpmnElementListeners.value)
+  )
+  // 4. 闅愯棌渚ц竟鏍�
+  listenerFormModelVisible.value = false
+  listenerForm.value = {}
+}
+// 鎵撳紑鐩戝惉鍣ㄥ瓧娈电紪杈戝脊绐�
+const openListenerFieldForm = (field, index?) => {
+  listenerFieldForm.value = field ? JSON.parse(JSON.stringify(field)) : {}
+  editingListenerFieldIndex.value = field ? index : -1
+  listenerFieldFormModelVisible.value = true
+  nextTick(() => {
+    if (listenerFieldFormRef.value) listenerFieldFormRef.value.clearValidate()
+  })
+}
+// 淇濆瓨鐩戝惉鍣ㄦ敞鍏ュ瓧娈�
+const saveListenerFiled = async () => {
+  let validateStatus = await listenerFieldFormRef.value.validate()
+  if (!validateStatus) return // 楠岃瘉涓嶉�氳繃鐩存帴杩斿洖
+  if (editingListenerFieldIndex.value === -1) {
+    fieldsListOfListener.value.push(listenerFieldForm.value)
+    listenerForm.value.fields.push(listenerFieldForm.value)
+  } else {
+    fieldsListOfListener.value.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
+    listenerForm.value.fields.splice(editingListenerFieldIndex.value, 1, listenerFieldForm.value)
+  }
+  listenerFieldFormModelVisible.value = false
+  nextTick(() => {
+    listenerFieldForm.value = {}
+  })
+}
+// 绉婚櫎鐩戝惉鍣ㄥ瓧娈�
+const removeListenerField = (field, index) => {
+  console.log(field, 'field')
+  ElMessageBox.confirm('纭绉婚櫎璇ュ瓧娈靛悧锛�', '鎻愮ず', {
+    confirmButtonText: '纭� 璁�',
+    cancelButtonText: '鍙� 娑�'
+  })
+    .then(() => {
+      fieldsListOfListener.value.splice(index, 1)
+      listenerForm.value.fields.splice(index, 1)
+    })
+    .catch(() => console.info('鎿嶄綔鍙栨秷'))
+}
+
+// 鎵撳紑鐩戝惉鍣ㄥ脊绐�
+const processListenerDialogRef = ref()
+const openProcessListenerDialog = async () => {
+  processListenerDialogRef.value.open('task')
+}
+const selectProcessListener = (listener) => {
+  const instances = bpmnInstances()
+  if (!instances || !instances.bpmnElement) return
+
+  const bpmnElement = instances.bpmnElement
+  const listenerForm = initListenerForm2(listener)
+  const listenerObject = createListenerObject(listenerForm, true, prefix)
+  bpmnElementListeners.value.push(listenerObject)
+  elementListenersList.value.push(listenerForm)
+
+  // 淇濆瓨鍏朵粬閰嶇疆
+  otherExtensionList.value =
+    bpmnElement.businessObject?.extensionElements?.values?.filter(
+      (ex) => ex.$type !== `${prefix}:TaskListener`
+    ) ?? []
+  updateElementExtensions(
+    bpmnElement,
+    otherExtensionList.value.concat(bpmnElementListeners.value)
+  )
+}
+
+watch(
+  () => props.id,
+  (val) => {
+    val &&
+      val.length &&
+      nextTick(() => {
+        resetListenersList()
+      })
+  },
+  { immediate: true }
+)
+</script>

--
Gitblit v1.8.0