From e01fc275e1464e99a4fd48708867fbb767a71e66 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Sun, 26 Oct 2025 09:10:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20[antd]->[bpm]=20=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E8=AF=84=E5=AE=A1=E4=BF=AE=E6=94=B9=2020%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/category-draggable-model.vue | 136 ++++++++++++------ .../bpm/processInstance/detail/index.vue | 44 +++--- .../detail/modules/operation-button.vue | 3 +- 3 files changed, 107 insertions(+), 76 deletions(-) diff --git a/apps/web-antd/src/views/bpm/model/modules/category-draggable-model.vue b/apps/web-antd/src/views/bpm/model/modules/category-draggable-model.vue index db06edeee..202ecaf8a 100644 --- a/apps/web-antd/src/views/bpm/model/modules/category-draggable-model.vue +++ b/apps/web-antd/src/views/bpm/model/modules/category-draggable-model.vue @@ -154,13 +154,17 @@ function handleModelSort() { /** 处理模型的排序提交 */ async function handleModelSortSubmit() { - // TODO @jason:loading 加一下,体验好点。 + // 确保数据已经正确同步 + if (!modelList.value || modelList.value.length === 0) { + message.error('排序数据异常,请重试'); + return; + } + + const hideLoading = message.loading({ + content: '正在保存排序...', + duration: 0, + }); try { - // 确保数据已经正确同步 - if (!modelList.value || modelList.value.length === 0) { - message.error('排序数据异常,请重试'); - return; - } // 保存排序 const ids = modelList.value.map((item) => item.id); await updateModelSortBatch(ids); @@ -170,6 +174,8 @@ async function handleModelSortSubmit() { emit('success'); } catch (error) { console.error('排序保存失败', error); + } finally { + hideLoading(); } } @@ -207,18 +213,29 @@ async function handleDeleteCategory() { return; } - // TODO @jason:改成 await;然后增加一个 loading; - confirm({ + await confirm({ + beforeClose: async ({ isConfirm }) => { + if (!isConfirm) return; + // 发起删除 + const hideLoading = message.loading({ + content: `正在删除分类: "${props.categoryInfo.name}"...`, + duration: 0, + }); + try { + await deleteCategory(props.categoryInfo.id); + } finally { + hideLoading(); + } + return true; + }, content: `确定要删除[${props.categoryInfo.name}]吗?`, - }).then(async () => { - // 发起删除 - await deleteCategory(props.categoryInfo.id); - message.success( - $t('ui.actionMessage.deleteSuccess', [props.categoryInfo.name]), - ); - // 刷新列表 - emit('success'); + icon: 'question', }); + message.success( + $t('ui.actionMessage.deleteSuccess', [props.categoryInfo.name]), + ); + // 刷新列表 + emit('success'); } /** 处理表单详情点击 */ @@ -249,21 +266,27 @@ async function modelOperation(type: string, id: number) { /** 发布流程 */ async function handleDeploy(row: any) { - // TODO @jason:改成 await;然后增加一个 loading; - confirm({ + await confirm({ beforeClose: async ({ isConfirm }) => { if (!isConfirm) return; // 发起部署 - await deployModel(row.id); + const hideLoading = message.loading({ + content: `正在发布流程: "${row.name}"...`, + duration: 0, + }); + try { + await deployModel(row.id); + } finally { + hideLoading(); + } return true; }, content: `确认要发布[${row.name}]流程吗?`, icon: 'question', - }).then(async () => { - message.success(`发布[${row.name}]流程成功`); - // 刷新列表 - emit('success'); }); + message.success(`发布[${row.name}]流程成功`); + // 刷新列表 + emit('success'); } /** '更多'操作按钮 */ @@ -300,63 +323,82 @@ function handleModelCommand(command: string, row: any) { } /** 更新状态操作 */ -function handleChangeState(row: any) { +async function handleChangeState(row: any) { const state = row.processDefinition.suspensionState; const newState = state === 1 ? 2 : 1; const statusState = state === 1 ? '停用' : '启用'; - // TODO @jason:改成 await;然后增加一个 loading; - confirm({ + await confirm({ beforeClose: async ({ isConfirm }) => { if (!isConfirm) return; // 发起更新状态 - await updateModelState(row.id, newState); + const hideLoading = message.loading({ + content: `正在${statusState}流程: "${row.name}"...`, + duration: 0, + }); + try { + await updateModelState(row.id, newState); + } finally { + hideLoading(); + } return true; }, content: `确认要${statusState}流程: "${row.name}" 吗?`, icon: 'question', - }).then(async () => { - message.success(`${statusState} 流程: "${row.name}" 成功`); - // 刷新列表 - emit('success'); }); + message.success(`${statusState} 流程: "${row.name}" 成功`); + // 刷新列表 + emit('success'); } /** 清理流程操作 */ -function handleClean(row: any) { - // TODO @jason:改成 await;然后增加一个 loading; - confirm({ +async function handleClean(row: any) { + await confirm({ beforeClose: async ({ isConfirm }) => { if (!isConfirm) return; // 发起清理操作 - await cleanModel(row.id); + const hideLoading = message.loading({ + content: `正在清理流程: "${row.name}"...`, + duration: 0, + }); + try { + await cleanModel(row.id); + } finally { + hideLoading(); + } return true; }, content: `确认要清理流程: "${row.name}" 吗?`, icon: 'question', - }).then(async () => { - message.success(`清理流程: "${row.name}" 成功`); - // 刷新列表 - emit('success'); }); + message.success(`清理流程: "${row.name}" 成功`); + // 刷新列表 + emit('success'); } /** 删除流程操作 */ -function handleDelete(row: any) { - // TODO @jason:改成 await;然后增加一个 loading; - confirm({ +async function handleDelete(row: any) { + await confirm({ beforeClose: async ({ isConfirm }) => { if (!isConfirm) return; // 发起删除操作 - await deleteModel(row.id); + const hideLoading = message.loading({ + content: $t('ui.actionMessage.deleting', [row.name]), + duration: 0, + }); + try { + await deleteModel(row.id); + } finally { + hideLoading(); + } return true; }, content: `确认要删除流程: "${row.name}" 吗?`, icon: 'question', - }).then(async () => { - message.success(`删除流程: "${row.name}" 成功`); - // 刷新列表 - emit('success'); }); + + message.success(`删除流程: "${row.name}" 成功`); + // 刷新列表 + emit('success'); } /** 跳转到指定流程定义列表 */ diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/index.vue b/apps/web-antd/src/views/bpm/processInstance/detail/index.vue index 6f60bf4c6..578f9aaaf 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/index.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/index.vue @@ -6,6 +6,7 @@ import { nextTick, onMounted, ref, shallowRef, watch } from 'vue'; import { Page } from '@vben/common-ui'; import { + BpmFieldPermissionType, BpmModelFormType, BpmModelType, BpmTaskStatusEnum, @@ -44,13 +45,6 @@ const props = defineProps<{ taskId?: string; // 任务编号 }>(); -// TODO @jason:是不是使用全局的 FieldPermissionType?export enum FieldPermissionType { -enum FieldPermissionType { - NONE = '3', // 隐藏 - READ = '1', // 只读 - WRITE = '2', // 编辑 -} - const processInstanceLoading = ref(false); // 流程实例的加载中 const processInstance = ref(); // 流程实例 const processDefinition = ref({}); // 流程定义 @@ -131,18 +125,16 @@ async function getApprovalDetail() { processInstance.value.formVariables, ); } - // TODO @jason:这里 await 来搞? - nextTick().then(() => { - fApi.value?.btn.show(false); - fApi.value?.resetBtn.show(false); - fApi.value?.disabled(true); - // 设置表单字段权限 - if (formFieldsPermission) { - Object.keys(data.formFieldsPermission).forEach((item) => { - setFieldPermission(item, formFieldsPermission[item]); - }); - } - }); + await nextTick(); + fApi.value?.btn.show(false); + fApi.value?.resetBtn.show(false); + fApi.value?.disabled(true); + // 设置表单字段权限 + if (formFieldsPermission) { + Object.keys(data.formFieldsPermission).forEach((item) => { + setFieldPermission(item, formFieldsPermission[item]); + }); + } } else { // 注意:data.processDefinition.formCustomViewPath 是组件的全路径,例如说:/crm/contract/detail/index.vue BusinessFormComponent.value = registerComponent( @@ -178,15 +170,15 @@ async function getProcessModelView() { /** 设置表单权限 */ function setFieldPermission(field: string, permission: string) { - if (permission === FieldPermissionType.READ) { + if (permission === BpmFieldPermissionType.READ) { fApi.value?.disabled(true, field); } - if (permission === FieldPermissionType.WRITE) { + if (permission === BpmFieldPermissionType.WRITE) { fApi.value?.disabled(false, field); // 加入可以编辑的字段 writableFields.push(field); } - if (permission === FieldPermissionType.NONE) { + if (permission === BpmFieldPermissionType.NONE) { fApi.value?.hidden(true, field); } } @@ -203,13 +195,11 @@ function setFieldPermission(field: string, permission: string) { /** 监听 Tab 切换,当切换到 "record" 标签时刷新任务列表 */ watch( () => activeTab.value, - (newVal) => { + async (newVal) => { if (newVal === 'record') { // 如果切换到流转记录标签,刷新任务列表 - // TODO @jason:await nextTick 要不? - nextTick(() => { - taskListRef.value?.refresh(); - }); + await nextTick(); + taskListRef.value?.refresh(); } }, ); diff --git a/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue b/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue index 14179827e..b6ab093fd 100644 --- a/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue +++ b/apps/web-antd/src/views/bpm/processInstance/detail/modules/operation-button.vue @@ -548,9 +548,8 @@ async function handleCancel() { /** 处理再次提交 */ async function handleReCreate() { // 跳转发起流程界面 - // TODO @jason:这个要优化成 push 到 name 么?这样后续 path 可以按需调整; await router.push({ - path: '/bpm/task/create', + name: 'BpmProcessInstanceCreate', query: { processInstanceId: props.processInstance?.id }, }); }