feat:钱包模块导出都改为分批,前端显示导出进度条的模式。

fix:修改各个统计模块统计的数量不一致的情况。
fix:修改支付宝分账退款失败的情况
This commit is contained in:
dzc committed 2026-08-26 17:48:59 +08:00
1 parent b5ad897188
commit eb33b81028
1 file changed
+93
@@ -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<string, unknown>) => Promise<WalletUserExportTaskResponse>
}
/**
* 复用钱包用户导出的提交互斥、进度轮询、结果下载和失败反馈。
*
* @param options 当前钱包页面的任务命名空间、文件名和提交方法
* @return 页面绑定进度组件及触发导出所需的响应式状态和回调
*/
export const useWalletUserExport = (options: WalletUserExportOptions) => {
/** 统一异步进度弹窗引用,用于任务提交成功后开始轮询。 */
const exportProgressRef = ref<InstanceType<typeof AsyncTaskProgressComponent>>()
/** 导出任务从提交到终态的互斥状态,防止重复任务覆盖当前进度跟踪。 */
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<string, unknown>) => {
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,
}
}