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/time-event-config/TimeEventConfig.vue |  312 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 312 insertions(+), 0 deletions(-)

diff --git a/src/components/bpmnProcessDesigner/package/penal/time-event-config/TimeEventConfig.vue b/src/components/bpmnProcessDesigner/package/penal/time-event-config/TimeEventConfig.vue
new file mode 100644
index 0000000..3ec31f9
--- /dev/null
+++ b/src/components/bpmnProcessDesigner/package/penal/time-event-config/TimeEventConfig.vue
@@ -0,0 +1,312 @@
+<template>
+  <div class="panel-tab__content">
+    <div style="margin-top: 10px">
+      <span>绫诲瀷锛�</span>
+      <el-button-group>
+        <el-button size="mini" :type="type === 'time' ? 'primary' : ''" @click="setType('time')"
+          >鏃堕棿</el-button
+        >
+        <el-button
+          size="mini"
+          :type="type === 'duration' ? 'primary' : ''"
+          @click="setType('duration')"
+          >鎸佺画</el-button
+        >
+        <el-button size="mini" :type="type === 'cycle' ? 'primary' : ''" @click="setType('cycle')"
+          >寰幆</el-button
+        >
+      </el-button-group>
+      <el-icon v-if="valid" color="green" style="margin-left: 8px"><CircleCheckFilled /></el-icon>
+    </div>
+    <div style="margin-top: 10px; display: flex; align-items: center">
+      <span>鏉′欢锛�</span>
+      <el-input
+        v-model="condition"
+        :placeholder="placeholder"
+        style="width: calc(100% - 100px)"
+        :readonly="type !== 'duration' && type !== 'cycle'"
+        @focus="handleInputFocus"
+        @blur="updateNode"
+      >
+        <template #suffix>
+          <el-tooltip v-if="!valid" content="鏍煎紡閿欒" placement="top">
+            <el-icon color="orange"><WarningFilled /></el-icon>
+          </el-tooltip>
+          <el-tooltip :content="helpText" placement="top">
+            <el-icon color="#409EFF" style="cursor: pointer" @click="showHelp = true"
+              ><QuestionFilled
+            /></el-icon>
+          </el-tooltip>
+          <el-button
+            v-if="type === 'time'"
+            @click="showDatePicker = true"
+            style="margin-left: 4px"
+            circle
+            size="small"
+          >
+            <Icon icon="ep:calendar" />
+          </el-button>
+          <el-button
+            v-if="type === 'duration'"
+            @click="showDurationDialog = true"
+            style="margin-left: 4px"
+            circle
+            size="small"
+          >
+            <Icon icon="ep:timer" />
+          </el-button>
+          <el-button
+            v-if="type === 'cycle'"
+            @click="showCycleDialog = true"
+            style="margin-left: 4px"
+            circle
+            size="small"
+          >
+            <Icon icon="ep:setting" />
+          </el-button>
+        </template>
+      </el-input>
+    </div>
+    <!-- 鏃堕棿閫夋嫨鍣� -->
+    <el-dialog
+      v-model="showDatePicker"
+      title="閫夋嫨鏃堕棿"
+      width="400px"
+      @close="showDatePicker = false"
+    >
+      <el-date-picker
+        v-model="dateValue"
+        type="datetime"
+        placeholder="閫夋嫨鏃ユ湡鏃堕棿"
+        style="width: 100%"
+        @change="onDateChange"
+      />
+      <template #footer>
+        <el-button @click="showDatePicker = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="onDateConfirm">纭畾</el-button>
+      </template>
+    </el-dialog>
+    <!-- 鎸佺画鏃堕暱閫夋嫨鍣� -->
+    <el-dialog
+      v-model="showDurationDialog"
+      title="鏃堕棿閰嶇疆"
+      width="600px"
+      @close="showDurationDialog = false"
+    >
+      <DurationConfig :value="condition" @change="onDurationChange" />
+      <template #footer>
+        <el-button @click="showDurationDialog = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="onDurationConfirm">纭畾</el-button>
+      </template>
+    </el-dialog>
+    <!-- 寰幆閰嶇疆鍣� -->
+    <el-dialog
+      v-model="showCycleDialog"
+      title="鏃堕棿閰嶇疆"
+      width="800px"
+      @close="showCycleDialog = false"
+    >
+      <CycleConfig :value="condition" @change="onCycleChange" />
+      <template #footer>
+        <el-button @click="showCycleDialog = false">鍙栨秷</el-button>
+        <el-button type="primary" @click="onCycleConfirm">纭畾</el-button>
+      </template>
+    </el-dialog>
+    <!-- 甯姪璇存槑 -->
+    <el-dialog v-model="showHelp" title="鏍煎紡璇存槑" width="600px" @close="showHelp = false">
+      <div v-html="helpHtml"></div>
+      <template #footer>
+        <el-button @click="showHelp = false">鍏抽棴</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script lang="ts" setup>
+import { ref, computed, watch, onMounted } from 'vue'
+import { CircleCheckFilled, WarningFilled, QuestionFilled } from '@element-plus/icons-vue'
+import DurationConfig from './DurationConfig.vue'
+import CycleConfig from './CycleConfig.vue'
+import { createListenerObject, updateElementExtensions } from '../../utils'
+const bpmnInstances = () => (window as any).bpmnInstances
+const props = defineProps({ businessObject: Object })
+const type = ref('time')
+const condition = ref('')
+const valid = ref(true)
+const showDatePicker = ref(false)
+const showDurationDialog = ref(false)
+const showCycleDialog = ref(false)
+const showHelp = ref(false)
+const dateValue = ref(null)
+const bpmnElement = ref(null)
+
+const placeholder = computed(() => {
+  if (type.value === 'time') return '璇疯緭鍏ユ椂闂�'
+  if (type.value === 'duration') return '璇疯緭鍏ユ寔缁椂闀�'
+  if (type.value === 'cycle') return '璇疯緭鍏ュ惊鐜〃杈惧紡'
+  return ''
+})
+const helpText = computed(() => {
+  if (type.value === 'time') return '閫夋嫨鍏蜂綋鏃堕棿'
+  if (type.value === 'duration') return 'ISO 8601鏍煎紡锛屽PT1H'
+  if (type.value === 'cycle') return 'CRON琛ㄨ揪寮忔垨ISO 8601鍛ㄦ湡'
+  return ''
+})
+const helpHtml = computed(() => {
+  if (type.value === 'duration') {
+    return `鎸囧畾瀹氭椂鍣ㄤ箣鍓嶈绛夊緟澶氶暱鏃堕棿銆係琛ㄧず绉掞紝M琛ㄧず鍒嗭紝D琛ㄧず澶╋紱P琛ㄧず鏃堕棿娈碉紝T琛ㄧず绮剧‘鍒版椂闂寸殑鏃堕棿娈点��<br>
+    鏃堕棿鏍煎紡渚濈劧涓篒SO 8601鏍煎紡锛屼竴骞翠袱涓湀涓夊ぉ鍥涘皬鏃朵簲鍒嗗叚绉掑唴锛屽彲浠ュ啓鎴怭1Y2M3DT4H5M6S銆�<br>
+    P鏄紑濮嬫爣璁帮紝T鏄椂闂村拰鏃ユ湡鍒嗗壊鏍囪锛屾病鏈夋棩鏈熷彧鏈夋椂闂碩鏄笉鑳界渷鍘荤殑锛屾瘮濡�1灏忔椂鎵ц涓�娆″簲鍐欐垚PT1H銆俙
+  }
+  if (type.value === 'cycle') {
+    return `鏀寔CRON琛ㄨ揪寮忥紙濡�0 0/30 * * * ?锛夋垨ISO 8601鍛ㄦ湡锛堝R3/PT10M锛夈�俙
+  }
+  return ''
+})
+
+// 鍒濆鍖栧拰鐩戝惉
+function syncFromBusinessObject() {
+  if (props.businessObject) {
+    const timerDef = (props.businessObject.eventDefinitions || [])[0]
+    if (timerDef) {
+      if (timerDef.timeDate) {
+        type.value = 'time'
+        condition.value = timerDef.timeDate.body
+      } else if (timerDef.timeDuration) {
+        type.value = 'duration'
+        condition.value = timerDef.timeDuration.body
+      } else if (timerDef.timeCycle) {
+        type.value = 'cycle'
+        condition.value = timerDef.timeCycle.body
+      }
+    }
+  }
+}
+onMounted(syncFromBusinessObject)
+
+// 鍒囨崲绫诲瀷
+function setType(t) {
+  type.value = t
+  condition.value = ''
+  updateNode()
+}
+
+// 杈撳叆鏍¢獙
+watch([type, condition], () => {
+  valid.value = validate()
+  // updateNode() // 鍙互娉ㄩ噴鎺夛紝閬垮厤棰戠箒瑙﹀彂
+})
+
+function validate() {
+  if (type.value === 'time') {
+    return !!condition.value && !isNaN(Date.parse(condition.value))
+  }
+  if (type.value === 'duration') {
+    return /^P.*$/.test(condition.value)
+  }
+  if (type.value === 'cycle') {
+    return /^([0-9*\/?, ]+|R\d*\/P.*)$/.test(condition.value)
+  }
+  return true
+}
+
+// 閫夋嫨鏃堕棿
+function onDateChange(val) {
+  dateValue.value = val
+}
+function onDateConfirm() {
+  if (dateValue.value) {
+    condition.value = new Date(dateValue.value).toISOString()
+    showDatePicker.value = false
+    updateNode()
+  }
+}
+
+// 鎸佺画鏃堕暱
+function onDurationChange(val) {
+  condition.value = val
+}
+function onDurationConfirm() {
+  showDurationDialog.value = false
+  updateNode()
+}
+
+// 寰幆
+function onCycleChange(val) {
+  condition.value = val
+}
+function onCycleConfirm() {
+  showCycleDialog.value = false
+  updateNode()
+}
+
+// 杈撳叆妗嗚仛鐒︽椂寮圭獥锛堝彲閫夛級
+function handleInputFocus() {
+  if (type.value === 'time') showDatePicker.value = true
+  if (type.value === 'duration') showDurationDialog.value = true
+  if (type.value === 'cycle') showCycleDialog.value = true
+}
+
+// 鍚屾鍒拌妭鐐�
+function updateNode() {
+  const moddle = window.bpmnInstances?.moddle
+  const modeling = window.bpmnInstances?.modeling
+  const elementRegistry = window.bpmnInstances?.elementRegistry
+  if (!moddle || !modeling || !elementRegistry) return
+
+  // 鑾峰彇鍏冪礌
+  if (!props.businessObject || !props.businessObject.id) return
+  const element = elementRegistry.get(props.businessObject.id)
+  if (!element) return
+
+  // 1. 澶嶇敤鍘熸湁 timerDef锛屾垨鏂板缓
+  let timerDef =
+    element.businessObject.eventDefinitions && element.businessObject.eventDefinitions[0]
+  if (!timerDef) {
+    timerDef = bpmnInstances().bpmnFactory.create('bpmn:TimerEventDefinition', {})
+    modeling.updateProperties(element, {
+      eventDefinitions: [timerDef]
+    })
+  }
+
+  // 2. 娓呯┖鍘熸湁
+  delete timerDef.timeDate
+  delete timerDef.timeDuration
+  delete timerDef.timeCycle
+
+  // 3. 璁剧疆鏂扮殑
+  if (type.value === 'time' && condition.value) {
+    timerDef.timeDate = bpmnInstances().bpmnFactory.create('bpmn:FormalExpression', {
+      body: condition.value
+    })
+  } else if (type.value === 'duration' && condition.value) {
+    timerDef.timeDuration = bpmnInstances().bpmnFactory.create('bpmn:FormalExpression', {
+      body: condition.value
+    })
+  } else if (type.value === 'cycle' && condition.value) {
+    timerDef.timeCycle = bpmnInstances().bpmnFactory.create('bpmn:FormalExpression', {
+      body: condition.value
+    })
+  }
+
+  bpmnInstances().modeling.updateProperties(toRaw(element), {
+    eventDefinitions: [timerDef]
+  })
+}
+
+watch(
+  () => props.businessObject,
+  (val) => {
+    if (val) {
+      nextTick(() => {
+        syncFromBusinessObject()
+      })
+    }
+  },
+  { immediate: true }
+)
+</script>
+
+<style scoped>
+/* 鐩稿叧鏍峰紡 */
+</style>

--
Gitblit v1.8.0