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

---
 src/views/bpm/model/form/index.vue |  456 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 456 insertions(+), 0 deletions(-)

diff --git a/src/views/bpm/model/form/index.vue b/src/views/bpm/model/form/index.vue
new file mode 100644
index 0000000..9974f08
--- /dev/null
+++ b/src/views/bpm/model/form/index.vue
@@ -0,0 +1,456 @@
+<template>
+  <ContentWrap>
+    <div class="mx-auto">
+      <!-- 澶撮儴瀵艰埅鏍� -->
+      <div
+        class="absolute top-0 left-0 right-0 h-50px bg-white border-bottom z-10 flex items-center px-20px"
+      >
+        <!-- 宸︿晶鏍囬 -->
+        <div class="w-200px flex items-center overflow-hidden">
+          <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>
+        </div>
+
+        <!-- 姝ラ鏉� -->
+        <div class="flex-1 flex items-center justify-center h-full">
+          <div class="w-400px flex items-center justify-between h-full">
+            <div
+              v-for="(step, index) in steps"
+              :key="index"
+              class="flex items-center cursor-pointer mx-15px relative h-full"
+              :class="[
+                currentStep === index
+                  ? 'text-[#3473ff] border-[#3473ff] border-b-2 border-b-solid'
+                  : 'text-gray-500'
+              ]"
+              @click="handleStepClick(index)"
+            >
+              <div
+                class="w-28px h-28px rounded-full flex items-center justify-center mr-8px border-2 border-solid text-15px"
+                :class="[
+                  currentStep === index
+                    ? 'bg-[#3473ff] text-white border-[#3473ff]'
+                    : 'border-gray-300 bg-white text-gray-500'
+                ]"
+              >
+                {{ index + 1 }}
+              </div>
+              <span class="text-16px font-bold whitespace-nowrap">{{ step.title }}</span>
+            </div>
+          </div>
+        </div>
+
+        <!-- 鍙充晶鎸夐挳 -->
+        <div class="w-200px flex items-center justify-end gap-2">
+          <el-button v-if="actionType === 'update'" type="success" @click="handleDeploy">
+            鍙� 甯�
+          </el-button>
+          <el-button type="primary" @click="handleSave">
+            <span v-if="actionType === 'definition'">鎭� 澶�</span>
+            <span v-else>淇� 瀛�</span>
+          </el-button>
+        </div>
+      </div>
+
+      <!-- 涓讳綋鍐呭 -->
+      <div class="mt-50px">
+        <!-- 绗竴姝ワ細鍩烘湰淇℃伅 -->
+        <div v-if="currentStep === 0" class="mx-auto w-560px">
+          <BasicInfo
+            v-model="formData"
+            :categoryList="categoryList"
+            :userList="userList"
+            :deptList="deptList"
+            ref="basicInfoRef"
+          />
+        </div>
+
+        <!-- 绗簩姝ワ細琛ㄥ崟璁捐 -->
+        <div v-if="currentStep === 1" class="mx-auto w-560px">
+          <FormDesign v-model="formData" :formList="formList" ref="formDesignRef" />
+        </div>
+
+        <!-- 绗笁姝ワ細娴佺▼璁捐 -->
+        <ProcessDesign v-if="currentStep === 2" v-model="formData" ref="processDesignRef" />
+
+        <!-- 绗洓姝ワ細鏇村璁剧疆 -->
+        <div v-show="currentStep === 3" class="mx-auto w-700px">
+          <ExtraSettings ref="extraSettingsRef" v-model="formData" />
+        </div>
+      </div>
+    </div>
+  </ContentWrap>
+</template>
+
+<script lang="ts" setup>
+import { useRoute, useRouter } from 'vue-router'
+import { useMessage } from '@/hooks/web/useMessage'
+import { useTagsViewStore } from '@/store/modules/tagsView'
+import { useUserStoreWithOut } from '@/store/modules/user'
+import * as ModelApi from '@/api/bpm/model'
+import * as FormApi from '@/api/bpm/form'
+import { CategoryApi, CategoryVO } from '@/api/bpm/category'
+import * as UserApi from '@/api/system/user'
+import * as DeptApi from '@/api/system/dept'
+import * as DefinitionApi from '@/api/bpm/definition'
+import { BpmModelFormType, BpmModelType, BpmAutoApproveType } from '@/utils/constants'
+import BasicInfo from './BasicInfo.vue'
+import FormDesign from './FormDesign.vue'
+import ProcessDesign from './ProcessDesign.vue'
+import ExtraSettings from './ExtraSettings.vue'
+import { useTagsView } from '@/hooks/web/useTagsView'
+
+const router = useRouter()
+const { delView } = useTagsViewStore() // 瑙嗗浘鎿嶄綔
+const tagsView = useTagsView()
+const route = useRoute()
+const message = useMessage()
+const userStore = useUserStoreWithOut()
+
+// 缁勪欢寮曠敤
+const basicInfoRef = ref()
+const formDesignRef = ref()
+const processDesignRef = ref()
+const extraSettingsRef = ref()
+
+/** 姝ラ鏍¢獙鍑芥暟 */
+const validateBasic = async () => {
+  await basicInfoRef.value?.validate()
+}
+
+/** 琛ㄥ崟璁捐鏍¢獙 */
+const validateForm = async () => {
+  await formDesignRef.value?.validate()
+}
+
+/** 娴佺▼璁捐鏍¢獙 */
+const validateProcess = async () => {
+  await processDesignRef.value?.validate()
+}
+
+const currentStep = ref(-1) // 姝ラ鎺у埗銆�-1 鐢ㄤ簬锛屼竴寮�濮嬪叏閮ㄤ笉灞曠ず绛夊綋鍓嶉〉闈㈡暟鎹垵濮嬪寲瀹屾垚
+
+const steps = [
+  { title: '鍩烘湰淇℃伅', validator: validateBasic },
+  { title: '琛ㄥ崟璁捐', validator: validateForm },
+  { title: '娴佺▼璁捐', validator: validateProcess },
+  { title: '鏇村璁剧疆', validator: null }
+]
+
+// 琛ㄥ崟鏁版嵁
+const formData: any = ref({
+  id: undefined,
+  name: '',
+  key: '',
+  category: undefined,
+  icon: undefined,
+  description: '',
+  type: BpmModelType.BPMN,
+  formType: BpmModelFormType.NORMAL,
+  formId: '',
+  formCustomCreatePath: '',
+  formCustomViewPath: '',
+  visible: true,
+  startUserType: undefined,
+  startUserIds: [],
+  startDeptIds: [],
+  managerUserIds: [],
+  allowCancelRunningProcess: true,
+  processIdRule: {
+    enable: false,
+    prefix: '',
+    infix: '',
+    postfix: '',
+    length: 5
+  },
+  autoApprovalType: BpmAutoApproveType.NONE,
+  titleSetting: {
+    enable: false,
+    title: ''
+  },
+  summarySetting: {
+    enable: false,
+    summary: []
+  },
+  allowWithdrawTask: false,
+  printTemplateSetting: {
+    enable: false
+  }
+})
+
+// 娴佺▼鏁版嵁
+const processData = ref<any>()
+
+provide('processData', processData)
+provide('modelData', formData)
+
+// 鏁版嵁鍒楄〃
+const formList = ref([])
+const categoryList = ref<CategoryVO[]>([])
+const userList = ref<UserApi.UserVO[]>([])
+const deptList = ref<DeptApi.DeptVO[]>([])
+
+/** 鍒濆鍖栨暟鎹� */
+const actionType = route.params.type as string
+const initData = async () => {
+  if (actionType === 'definition') {
+    // 鎯呭喌涓�锛氭祦绋嬪畾涔夊満鏅紙鎭㈠锛�
+    const definitionId = route.params.id as string
+    const data = await DefinitionApi.getProcessDefinition(definitionId)
+    // 灏� definition => model锛屾渶缁堣祴鍊�
+    data.type = data.modelType
+    delete data.modelType
+    data.id = data.modelId
+    delete data.modelId
+    if (data.simpleModel) {
+      data.simpleModel = JSON.parse(data.simpleModel)
+    }
+    formData.value = data
+    formData.value.startUserType =
+      formData.value.startUserIds?.length > 0 ? 1 : formData.value?.startDeptIds?.length > 0 ? 2 : 0
+  } else if (['update', 'copy'].includes(actionType)) {
+    // 鎯呭喌浜岋細淇敼鍦烘櫙/澶嶅埗鍦烘櫙
+    const modelId = route.params.id as string
+    formData.value = await ModelApi.getModel(modelId)
+    formData.value.startUserType =
+      formData.value.startUserIds?.length > 0 ? 1 : formData.value?.startDeptIds?.length > 0 ? 2 : 0
+
+    // 鐗规畩锛氬鍒跺満鏅�
+    if (route.params.type === 'copy') {
+      delete formData.value.id
+      if (formData.value.bpmnXml) {
+        formData.value.bpmnXml = formData.value.bpmnXml.replaceAll(
+          formData.value.name,
+          formData.value.name + '鍓湰'
+        )
+        formData.value.bpmnXml = formData.value.bpmnXml.replaceAll(
+          formData.value.key,
+          formData.value.key + '_copy'
+        )
+      }
+      formData.value.name += '鍓湰'
+      formData.value.key += '_copy'
+      tagsView.setTitle('澶嶅埗娴佺▼')
+    }
+  } else {
+    // 鎯呭喌涓夛細鏂板鍦烘櫙
+    formData.value.startUserType = 0 // 鍏ㄤ綋
+    formData.value.managerUserIds.push(userStore.getUser.id)
+  }
+
+  // 鑾峰彇琛ㄥ崟鍒楄〃
+  formList.value = await FormApi.getFormSimpleList()
+  // 鑾峰彇鍒嗙被鍒楄〃
+  categoryList.value = await CategoryApi.getCategorySimpleList()
+  // 鑾峰彇鐢ㄦ埛鍒楄〃
+  userList.value = await UserApi.getSimpleUserList()
+  // 鑾峰彇閮ㄩ棬鍒楄〃
+  deptList.value = await DeptApi.getSimpleDeptList()
+
+  // 鏈�缁堬紝璁剧疆 currentStep 鍒囨崲鍒扮涓�姝�
+  currentStep.value = 0
+
+  // 鍏煎锛屼互鍓嶆湭閰嶇疆鏇村璁剧疆鐨勬祦绋�
+  extraSettingsRef.value.initData()
+}
+
+/** 鏍规嵁绫诲瀷鍒囨崲娴佺▼鏁版嵁 */
+watch(
+  async () => formData.value.type,
+  () => {
+    if (formData.value.type === BpmModelType.BPMN) {
+      processData.value = formData.value.bpmnXml
+    } else if (formData.value.type === BpmModelType.SIMPLE) {
+      processData.value = formData.value.simpleModel
+    }
+    console.log('鍔犺浇娴佺▼鏁版嵁', processData.value)
+  },
+  {
+    immediate: true
+  }
+)
+
+/** 鏍¢獙鎵�鏈夋楠ゆ暟鎹槸鍚﹀畬鏁� */
+const validateAllSteps = async () => {
+  try {
+    // 鍩烘湰淇℃伅鏍¢獙
+    try {
+      await validateBasic()
+    } catch (error) {
+      currentStep.value = 0
+      throw new Error('璇峰畬鍠勫熀鏈俊鎭�')
+    }
+
+    // 琛ㄥ崟璁捐鏍¢獙
+    try {
+      await validateForm()
+    } catch (error) {
+      currentStep.value = 1
+      throw new Error('璇峰畬鍠勮嚜瀹氫箟琛ㄥ崟淇℃伅')
+    }
+
+    // 娴佺▼璁捐鏍¢獙
+
+    // 琛ㄥ崟璁捐鏍¢獙
+    try {
+      await validateProcess()
+    } catch (error) {
+      currentStep.value = 2
+      throw new Error('璇疯璁℃祦绋�')
+    }
+
+    return true
+  } catch (error) {
+    throw error
+  }
+}
+
+/** 淇濆瓨鎿嶄綔 */
+const handleSave = async () => {
+  try {
+    // 淇濆瓨鍓嶆牎楠屾墍鏈夋楠ょ殑鏁版嵁
+    await validateAllSteps()
+
+    // 鏇存柊琛ㄥ崟鏁版嵁
+    const modelData = {
+      ...formData.value
+    }
+
+    if (actionType === 'definition') {
+      // 鎯呭喌涓�锛氭祦绋嬪畾涔夊満鏅紙鎭㈠锛�
+      await ModelApi.updateModel(modelData)
+      // 鎻愮ず鎴愬姛
+      message.success('鎭㈠鎴愬姛锛屽彲鐐瑰嚮銆愬彂甯冦�戞寜閽紝杩涜鍙戝竷妯″瀷')
+    } else if (actionType === 'update') {
+      // 淇敼鍦烘櫙
+      await ModelApi.updateModel(modelData)
+      // 鎻愮ず鎴愬姛
+      message.success('淇敼鎴愬姛锛屽彲鐐瑰嚮銆愬彂甯冦�戞寜閽紝杩涜鍙戝竷妯″瀷')
+    } else if (actionType === 'copy') {
+      // 鎯呭喌涓夛細澶嶅埗鍦烘櫙
+      formData.value.id = await ModelApi.createModel(modelData)
+      // 鎻愮ず鎴愬姛
+      message.success('澶嶅埗鎴愬姛锛屽彲鐐瑰嚮銆愬彂甯冦�戞寜閽紝杩涜鍙戝竷妯″瀷')
+    } else {
+      // 鎯呭喌鍥涳細鏂板鍦烘櫙
+      formData.value.id = await ModelApi.createModel(modelData)
+      // 鎻愮ず鎴愬姛
+      message.success('鏂板缓鎴愬姛锛屽彲鐐瑰嚮銆愬彂甯冦�戞寜閽紝杩涜鍙戝竷妯″瀷')
+    }
+
+    // 杩斿洖鍒楄〃椤碉紙鎺掗櫎鏇存柊鐨勬儏鍐碉級
+    if (actionType !== 'update') {
+      await router.push({ name: 'BpmModel' })
+    }
+  } catch (error: any) {
+    console.error('淇濆瓨澶辫触:', error)
+    message.warning(error.message || '璇峰畬鍠勬墍鏈夋楠ょ殑蹇呭~淇℃伅')
+  }
+}
+
+/** 鍙戝竷鎿嶄綔 */
+const handleDeploy = async () => {
+  try {
+    // 淇敼鍦烘櫙涓嬬洿鎺ュ彂甯冿紝鏂板鍦烘櫙涓嬮渶瑕佸厛纭
+    if (!formData.value.id) {
+      await message.confirm('鏄惁纭鍙戝竷璇ユ祦绋嬶紵')
+    }
+    // 鏍¢獙鎵�鏈夋楠�
+    await validateAllSteps()
+
+    // 鏇存柊琛ㄥ崟鏁版嵁
+    const modelData = {
+      ...formData.value
+    }
+
+    // 鍏堜繚瀛樻墍鏈夋暟鎹�
+    if (formData.value.id) {
+      await ModelApi.updateModel(modelData)
+    } else {
+      const result = await ModelApi.createModel(modelData)
+      formData.value.id = result.id
+    }
+
+    // 鍙戝竷
+    await ModelApi.deployModel(formData.value.id)
+    message.success('鍙戝竷鎴愬姛')
+    // 杩斿洖鍒楄〃椤�
+    await router.push({ name: 'BpmModel' })
+  } catch (error: any) {
+    console.error('鍙戝竷澶辫触:', error)
+    message.warning(error.message || '鍙戝竷澶辫触')
+  }
+}
+
+/** 姝ラ鍒囨崲澶勭悊 */
+const handleStepClick = async (index: number) => {
+  try {
+    if (index !== 0) {
+      await validateBasic()
+    }
+    if (index !== 1) {
+      await validateForm()
+    }
+    if (index !== 2) {
+      await validateProcess()
+    }
+
+    // 鍒囨崲姝ラ
+    currentStep.value = index
+
+    // 濡傛灉鍒囨崲鍒版祦绋嬭璁℃楠わ紝绛夊緟缁勪欢娓叉煋瀹屾垚鍚庡埛鏂拌璁″櫒
+    if (index === 2) {
+      await nextTick()
+      // 绛夊緟鏇撮暱鏃堕棿纭繚缁勪欢瀹屽叏鍒濆鍖�
+      await new Promise((resolve) => setTimeout(resolve, 200))
+      if (processDesignRef.value?.refresh) {
+        await processDesignRef.value.refresh()
+      }
+    }
+  } catch (error) {
+    console.error('姝ラ鍒囨崲澶辫触:', error)
+    message.warning('璇峰厛瀹屽杽褰撳墠姝ラ蹇呭~淇℃伅')
+  }
+}
+
+/** 杩斿洖鍒楄〃椤� */
+const handleBack = () => {
+  // 鍏堝垹闄ゅ綋鍓嶉〉绛�
+  delView(unref(router.currentRoute))
+  // 璺宠浆鍒板垪琛ㄩ〉
+  router.push({ name: 'BpmModel' })
+}
+
+/** 鍒濆鍖� */
+onMounted(async () => {
+  await initData()
+})
+
+// 娣诲姞缁勪欢鍗歌浇鍓嶇殑娓呯悊浠g爜
+onBeforeUnmount(() => {
+  // 娓呯悊鎵�鏈夌殑寮曠敤
+  basicInfoRef.value = null
+  formDesignRef.value = null
+  processDesignRef.value = null
+})
+</script>
+
+<style lang="scss" scoped>
+.border-bottom {
+  border-bottom: 1px solid #dcdfe6;
+}
+
+.text-primary {
+  color: #3473ff;
+}
+
+.bg-primary {
+  background-color: #3473ff;
+}
+
+.border-primary {
+  border-color: #3473ff;
+}
+</style>

--
Gitblit v1.8.0