feat(pickup): 支持线下提号 CSV 导出

This commit is contained in:
yml
2026-11-12 14:53:36 +08:00
parent a5601eb76c
commit e8a281fce6
8 changed files with 628 additions and 2 deletions
@@ -1,3 +1,4 @@
import axios from 'axios'
import { apiClient } from '@/shared/api/client'
import type { ApiResponse, PaginatedResult } from '@/shared/types/types'
@@ -166,6 +167,8 @@ export interface AdminPickupListQuery {
end_time?: string
}
export type AdminPickupExportQuery = Omit<AdminPickupListQuery, 'page' | 'page_size'>
export interface PickupShop {
id: number
name: string
@@ -254,11 +257,57 @@ export async function fetchAdminPickups(query: AdminPickupListQuery = {}) {
}
}
export async function exportAdminPickups(query: AdminPickupExportQuery = {}) {
try {
const response = await apiClient.get<Blob>('/admin/pickups/export', {
params: cleanParams(query),
responseType: 'blob',
timeout: 60000,
skipErrorHandler: true,
})
return {
blob: response.data,
filename: readExportFilename(response.headers['content-disposition']),
rowCount: Number(response.headers['x-export-row-count'] || 0),
}
} catch (error) {
if (axios.isAxiosError(error) && error.response?.data instanceof Blob) {
const text = await error.response.data.text()
let message = ''
try {
const payload = JSON.parse(text) as { message?: unknown }
if (typeof payload.message === 'string') {
message = payload.message
}
} catch {
// 非 JSON 错误响应保留原始 Axios 错误。
}
if (message) {
error.message = message
}
}
throw error
}
}
export async function fetchAdminPickup(id: string | number) {
const { data } = await apiClient.get<ApiResponse<AdminPickup>>(`/admin/pickups/${id}`)
return data.data
}
function readExportFilename(contentDisposition: unknown) {
if (typeof contentDisposition !== 'string') return 'pickup-export.csv'
const encoded = contentDisposition.match(/filename\*=UTF-8''([^;]+)/i)?.[1]
if (encoded) {
try {
return decodeURIComponent(encoded)
} catch {
return encoded
}
}
return contentDisposition.match(/filename="?([^";]+)"?/i)?.[1] || 'pickup-export.csv'
}
export async function fetchAdminPickupShopOptions(platform = '') {
const { data } = await apiClient.get<ApiResponse<string[]>>('/admin/pickups/shop-options', {
params: cleanParams({ platform }),