441917bfce
批量打包下载与单店下载接入 axios onDownloadProgress,progress 弹窗显示 百分比;后端未回 Content-Length 时退化为 indeterminate 流动条,避免用户 在大 zip 下载期间以为页面无响应。
89 lines
4.2 KiB
TypeScript
89 lines
4.2 KiB
TypeScript
/** 店铺数据任务列表/批量下载适配(任务 110/113)。 */
|
||
import { http } from '@/api/http'
|
||
import { parseShopDataTaskPage, type ShopDataTaskPageResult } from './shop-data-model.ts'
|
||
import { toShopDataQuery, type ShopDataFilter } from './shop-data-filter.ts'
|
||
import { shopDataFilenameFromDisposition, toShopDataZipRequest } from './shop-data-download.ts'
|
||
import { downloadZipHeaderCounts } from './image-video-download.ts'
|
||
import { parseTaskPermissionPayload, toPermissionUserIdsPayload, type TaskPermissionItem } from './task-permission.ts'
|
||
|
||
export const SHOP_DATA_CRAWL_TASKS_ENDPOINT = '/api/admin/shop-data-crawl-tasks'
|
||
export const SHOP_DATA_TASK_PERMISSIONS_ENDPOINT = '/api/admin/shop-data-crawl-task-permissions'
|
||
export const SHOP_DATA_SINGLE_ENDPOINT = '/api/admin/shop-data-crawl'
|
||
|
||
export async function fetchShopDataTaskList(
|
||
filter: ShopDataFilter,
|
||
page: number,
|
||
pageSize: number,
|
||
): Promise<ShopDataTaskPageResult> {
|
||
const { data } = await http.get<unknown>(SHOP_DATA_CRAWL_TASKS_ENDPOINT, {
|
||
params: toShopDataQuery(filter, page, pageSize),
|
||
})
|
||
return parseShopDataTaskPage(data)
|
||
}
|
||
|
||
export interface ShopDataZipDownloadResult {
|
||
blob: Blob
|
||
fileCount?: number
|
||
errorCount?: number
|
||
}
|
||
|
||
/** 批量下载选中结果文件为 zip:POST /download-zip(blob);从响应头读成功/失败计数。
|
||
* onProgress: 可选下载进度回调(0-100,后端未回 Content-Length 时退化为不定进度)。 */
|
||
export async function requestShopDataZipDownload(
|
||
resultIds: readonly (number | string)[],
|
||
onProgress?: (percent: number) => void,
|
||
): Promise<ShopDataZipDownloadResult> {
|
||
const { data, headers } = await http.post<Blob>(`${SHOP_DATA_CRAWL_TASKS_ENDPOINT}/download-zip`, toShopDataZipRequest(resultIds), {
|
||
responseType: 'blob',
|
||
...(onProgress ? { onDownloadProgress: toAxiosProgress(onProgress) } : {}),
|
||
})
|
||
const counts = downloadZipHeaderCounts(headers as Record<string, string>)
|
||
return { blob: data, fileCount: counts.fileCount, errorCount: counts.errorCount }
|
||
}
|
||
|
||
export interface ShopDataResultDownload {
|
||
blob: Blob
|
||
filename: string
|
||
}
|
||
|
||
/** 下载单店最新采集文件(按每日累计档 id):GET /api/admin/shop-data-crawl-tasks/daily-files/{id}/download。
|
||
* onProgress: 可选下载进度回调(0-100)。 */
|
||
export async function fetchShopDataResultDownload(
|
||
resultId: number | string,
|
||
onProgress?: (percent: number) => void,
|
||
): Promise<ShopDataResultDownload> {
|
||
const { data, headers } = await http.get<Blob>(`${SHOP_DATA_CRAWL_TASKS_ENDPOINT}/daily-files/${resultId}/download`, {
|
||
responseType: 'blob',
|
||
...(onProgress ? { onDownloadProgress: toAxiosProgress(onProgress) } : {}),
|
||
})
|
||
const disposition = (headers as Record<string, string> | undefined)?.['content-disposition']
|
||
return { blob: data, filename: shopDataFilenameFromDisposition(disposition, `shop-data-task-${resultId}.xlsx`) }
|
||
}
|
||
|
||
/** 将 axios 进度事件转为 0-100 百分比;响应未回 Content-Length 时报 -1,前端显示不定进度。 */
|
||
function toAxiosProgress(onProgress: (percent: number) => void) {
|
||
return (event: { loaded: number; total?: number }) => {
|
||
if (event.total) {
|
||
onProgress(Math.min(100, Math.round((event.loaded / event.total) * 100)))
|
||
} else {
|
||
onProgress(-1)
|
||
}
|
||
}
|
||
}
|
||
|
||
/** 删除该店这条店铺数据记录(按每日累计档 id,管理端显式操作):DELETE .../daily-files/{id}。 */
|
||
export async function deleteShopDataResultHistory(resultId: number | string): Promise<void> {
|
||
await http.delete<unknown>(`${SHOP_DATA_CRAWL_TASKS_ENDPOINT}/daily-files/${resultId}`)
|
||
}
|
||
|
||
/** 加载店铺数据任务数据范围授权用户:GET /api/admin/shop-data-crawl-task-permissions。 */
|
||
export async function fetchShopDataTaskPermissionUsers(): Promise<TaskPermissionItem[]> {
|
||
const { data } = await http.get<unknown>(SHOP_DATA_TASK_PERMISSIONS_ENDPOINT)
|
||
return parseTaskPermissionPayload(data)
|
||
}
|
||
|
||
/** 保存店铺数据任务数据范围授权:PUT /api/admin/shop-data-crawl-task-permissions { user_ids }。 */
|
||
export async function saveShopDataTaskPermissions(userIds: Iterable<number>): Promise<void> {
|
||
await http.put<unknown>(SHOP_DATA_TASK_PERMISSIONS_ENDPOINT, toPermissionUserIdsPayload(userIds))
|
||
}
|