From eb33b81028e560b6db5de04bc47e3096e604e7ce Mon Sep 17 00:00:00 2001 From: dzc <2388224167@qq.com> Date: Wed, 26 Aug 2026 17:48:59 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E9=92=B1=E5=8C=85=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E9=83=BD=E6=94=B9=E4=B8=BA=E5=88=86=E6=89=B9?= =?UTF-8?q?=EF=BC=8C=E5=89=8D=E7=AB=AF=E6=98=BE=E7=A4=BA=E5=AF=BC=E5=87=BA?= =?UTF-8?q?=E8=BF=9B=E5=BA=A6=E6=9D=A1=E7=9A=84=E6=A8=A1=E5=BC=8F=E3=80=82?= =?UTF-8?q?=20fix:=E4=BF=AE=E6=94=B9=E5=90=84=E4=B8=AA=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E7=BB=9F=E8=AE=A1=E7=9A=84=E6=95=B0=E9=87=8F?= =?UTF-8?q?=E4=B8=8D=E4=B8=80=E8=87=B4=E7=9A=84=E6=83=85=E5=86=B5=E3=80=82?= =?UTF-8?q?=20fix:=E4=BF=AE=E6=94=B9=E6=94=AF=E4=BB=98=E5=AE=9D=E5=88=86?= =?UTF-8?q?=E8=B4=A6=E9=80=80=E6=AC=BE=E5=A4=B1=E8=B4=A5=E7=9A=84=E6=83=85?= =?UTF-8?q?=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wallet/composables/useWalletUserExport.ts | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 src/views/wallet/composables/useWalletUserExport.ts diff --git a/src/views/wallet/composables/useWalletUserExport.ts b/src/views/wallet/composables/useWalletUserExport.ts new file mode 100644 index 00000000..0974e2a1 --- /dev/null +++ b/src/views/wallet/composables/useWalletUserExport.ts @@ -0,0 +1,93 @@ +import type { AsyncTaskPollingConfig, AsyncTaskProgress } from "/@/api/asyncTask" +import AsyncTaskProgressComponent from "/@/components/AsyncTaskProgress.vue" +import { useMessage } from "/@/hooks/message" +import { downBlobFile } from "/@/utils/other" + +/** 钱包用户异步导出提交接口的最小统一响应。 */ +interface WalletUserExportTaskResponse { + /** 后端创建的初始任务进度。 */ + data: AsyncTaskProgress + /** 后端返回的任务提交提示。 */ + msg?: string +} + +/** 钱包用户异步导出页面配置。 */ +interface WalletUserExportOptions { + /** 与后端异步任务场景一致的 Redis 业务命名空间。 */ + redisKey: string + /** 页面对应的导出任务中文名称。 */ + taskName: string + /** 后端没有返回文件名时使用的下载文件名。 */ + fallbackFileName: string + /** 接收当前筛选快照并提交异步任务的 API 方法。 */ + submitTask: (query: Record) => Promise +} + +/** + * 复用钱包用户导出的提交互斥、进度轮询、结果下载和失败反馈。 + * + * @param options 当前钱包页面的任务命名空间、文件名和提交方法 + * @return 页面绑定进度组件及触发导出所需的响应式状态和回调 + */ +export const useWalletUserExport = (options: WalletUserExportOptions) => { + /** 统一异步进度弹窗引用,用于任务提交成功后开始轮询。 */ + const exportProgressRef = ref>() + /** 导出任务从提交到终态的互斥状态,防止重复任务覆盖当前进度跟踪。 */ + const exportSubmitting = ref(false) + /** 当前页面的轮询配置,命名空间必须与后端场景保持一致。 */ + const exportTaskConfig: AsyncTaskPollingConfig = { + progressUrl: "/wallet/async-task/progress", + redisKey: options.redisKey, + showDialogOnFinished: false, + waitingMessage: `正在生成${options.taskName}文件,请耐心等待进度达到 100%`, + downloadButtonText: "下载 Excel", + } + + /** 按页面当前筛选快照提交异步导出任务并打开进度弹窗。 */ + const submitExport = async (query: Record) => { + if (exportSubmitting.value) { + useMessage().warning(`已有${options.taskName}任务正在处理`) + return + } + exportSubmitting.value = true + try { + const response = await options.submitTask(query) + if (!response.data?.taskId) { + exportSubmitting.value = false + useMessage().error("导出任务提交成功,但响应中缺少任务ID") + return + } + useMessage().success(response.msg || `${options.taskName}任务已提交`) + exportProgressRef.value?.start(response.data) + } catch (error: any) { + exportSubmitting.value = false + useMessage().error(error?.msg || `${options.taskName}任务提交失败`) + } + } + + /** 任务成功后下载文件中心返回的完整工作簿。 */ + const handleExportSuccess = async (progress: AsyncTaskProgress) => { + exportSubmitting.value = false + if (!progress.resultFileUrl) { + useMessage().error("导出完成,但未返回文件下载地址") + return + } + useMessage().success(progress.message || `${options.taskName}完成`) + await downBlobFile(progress.resultFileUrl, {}, progress.resultFileName || options.fallbackFileName) + } + + /** 任务失败时展示后台保存的受控错误信息。 */ + const handleExportFailure = (progress: AsyncTaskProgress) => { + exportSubmitting.value = false + useMessage().error(progress.message || `${options.taskName}失败`) + } + + return { + exportProgressRef, + exportSubmitting, + exportTaskConfig, + submitExport, + handleExportSuccess, + handleExportFailure, + } +}