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