From 703cdf412547680ca479d23403b683ba6f655698 Mon Sep 17 00:00:00 2001 From: dap <15891557205@163.com> Date: Wed, 28 Jan 2026 14:47:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E5=AF=BC=E5=87=BA):=20=E9=87=8D=E6=9E=84?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E5=8A=9F=E8=83=BD=E5=B9=B6=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=9B=BD=E9=99=85=E5=8C=96=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增通用的 `useBlobExport` 组合式函数,封装导出逻辑,支持加载状态和取消操作 - 在用户管理页面使用新的导出函数替换原有的 `commonDownloadExcel` 调用 - 添加中英文国际化文案,包括导出标题、加载提示和取消提示 - 为通用页面文案补充“取消”按钮的翻译 --- .../src/locales/langs/en-US/common.json | 7 ++ .../src/locales/langs/en-US/pages.json | 3 +- .../src/locales/langs/zh-CN/common.json | 7 ++ .../src/locales/langs/zh-CN/pages.json | 3 +- apps/web-antd/src/utils/file/export.tsx | 76 +++++++++++++++++++ apps/web-antd/src/views/system/user/index.vue | 19 +++-- 6 files changed, 106 insertions(+), 9 deletions(-) create mode 100644 apps/web-antd/src/locales/langs/en-US/common.json create mode 100644 apps/web-antd/src/locales/langs/zh-CN/common.json create mode 100644 apps/web-antd/src/utils/file/export.tsx diff --git a/apps/web-antd/src/locales/langs/en-US/common.json b/apps/web-antd/src/locales/langs/en-US/common.json new file mode 100644 index 00000000..cdfabf4c --- /dev/null +++ b/apps/web-antd/src/locales/langs/en-US/common.json @@ -0,0 +1,7 @@ +{ + "export": { + "title": "Export", + "loading": "Exporting...", + "canceled": "Export has been cancelled." + } +} diff --git a/apps/web-antd/src/locales/langs/en-US/pages.json b/apps/web-antd/src/locales/langs/en-US/pages.json index 901a75a1..ca0359ca 100644 --- a/apps/web-antd/src/locales/langs/en-US/pages.json +++ b/apps/web-antd/src/locales/langs/en-US/pages.json @@ -22,6 +22,7 @@ "tip": "Tip", "enable": "On", "disable": "Off", - "beforeCloseTip": "You have unsaved changes. Are you sure you want to exit?" + "beforeCloseTip": "You have unsaved changes. Are you sure you want to exit?", + "cancel": "Cancel" } } diff --git a/apps/web-antd/src/locales/langs/zh-CN/common.json b/apps/web-antd/src/locales/langs/zh-CN/common.json new file mode 100644 index 00000000..2577ab8b --- /dev/null +++ b/apps/web-antd/src/locales/langs/zh-CN/common.json @@ -0,0 +1,7 @@ +{ + "export": { + "title": "导出", + "loading": "导出中...", + "canceled": "导出已取消" + } +} diff --git a/apps/web-antd/src/locales/langs/zh-CN/pages.json b/apps/web-antd/src/locales/langs/zh-CN/pages.json index eab87798..c39978e2 100644 --- a/apps/web-antd/src/locales/langs/zh-CN/pages.json +++ b/apps/web-antd/src/locales/langs/zh-CN/pages.json @@ -22,6 +22,7 @@ "tip": "提示", "enable": "启用", "disable": "禁用", - "beforeCloseTip": "您有未保存的更改,确认要退出吗?" + "beforeCloseTip": "您有未保存的更改,确认要退出吗?", + "cancel": "取消" } } diff --git a/apps/web-antd/src/utils/file/export.tsx b/apps/web-antd/src/utils/file/export.tsx new file mode 100644 index 00000000..fbbdefb3 --- /dev/null +++ b/apps/web-antd/src/utils/file/export.tsx @@ -0,0 +1,76 @@ +import type { loginInfoExport } from '#/api/monitor/logininfo'; + +import { ref } from 'vue'; + +import { useRequest } from 'alova/client'; +import { Button } from 'antdv-next'; +import dayjs from 'dayjs'; + +import { $t } from '#/locales'; + +import { downloadByData } from './download'; + +// TODO: 这里的泛型实在难写 且基本都是统一按格式 +export type ExportBlobApi = typeof loginInfoExport; + +export interface ExportBlobFuncOptions { + fileName: string; + data?: any; +} + +export function useBlobExport(api: ExportBlobApi) { + const exportLoading = ref(false); + + const { send, abort } = useRequest(api, { immediate: false }); + + async function exportBlob(options: ExportBlobFuncOptions) { + const { fileName, data } = options; + + const hide = window.message.loading({ + content: ( +
+ {$t('common.export.loading')} + +
+ ), + duration: 9999, + }); + + exportLoading.value = true; + try { + const blob = await send(data ?? {}); + downloadByData(blob, fileName); + } catch (error) { + console.error(error); + } finally { + hide(); + exportLoading.value = false; + } + } + + /** + * 构建导出文件名 放在这里的好处是可以做国际化文案 + * @param module 模块名称 + * @returns 导出文件名 + */ + function buildExportFileName(module: string, extension = 'xlsx') { + return `${module} ${$t('common.export.title')} - ${dayjs().valueOf()}.${extension}`; + } + + return { + exportBlob, + exportLoading, + buildExportFileName, + }; +} diff --git a/apps/web-antd/src/views/system/user/index.vue b/apps/web-antd/src/views/system/user/index.vue index d2d50aee..6b62ee2c 100644 --- a/apps/web-antd/src/views/system/user/index.vue +++ b/apps/web-antd/src/views/system/user/index.vue @@ -24,7 +24,7 @@ import { userStatusChange, } from '#/api/system/user'; import ApiSwitch from '#/components/global/api-switch.vue'; -import { commonDownloadExcel } from '#/utils/file/download'; +import { useBlobExport } from '#/utils/file/export'; import { columns, querySchema } from './data'; import DeptTree from './dept-tree.vue'; @@ -156,10 +156,14 @@ function handleMultiDelete() { }); } -function handleDownloadExcel() { - commonDownloadExcel(userExport, '用户管理', tableApi.formApi.form.values, { - fieldMappingTime: formOptions.fieldMappingTime, - }); +const { exportBlob, exportLoading, buildExportFileName } = + useBlobExport(userExport); +async function handleExport() { + // 构建表单请求参数 + const formValues = await tableApi.formApi.getValues(); + // 文件名 + const fileName = buildExportFileName('用户信息'); + exportBlob({ data: formValues, fileName }); } const [UserInfoModal, userInfoModalApi] = useVbenModal({ @@ -202,7 +206,6 @@ function handleMenuClick(key: string, row: any) { } async function handleChangeStatus(checked: boolean, row: User) { - console.log(checked); await userStatusChange({ userId: row.userId, status: checked ? EnableStatus.Enable : EnableStatus.Disable, @@ -224,7 +227,9 @@ async function handleChangeStatus(checked: boolean, row: User) { {{ $t('pages.common.export') }}