feat:钱包模块导出都改为分批,前端显示导出进度条的模式。
fix:修改各个统计模块统计的数量不一致的情况。 fix:修改支付宝分账退款失败的情况
This commit is contained in:
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,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user