|
|
|
|
@ -3,6 +3,8 @@ import { adminHttp } from './http'
|
|
|
|
|
import type {
|
|
|
|
|
AdminApplicationDetail,
|
|
|
|
|
AdminApplicationExportMeta,
|
|
|
|
|
AdminApplicationExportMode,
|
|
|
|
|
AdminApplicationExportParams,
|
|
|
|
|
AdminApplicationListParams,
|
|
|
|
|
AdminApplicationRow,
|
|
|
|
|
Paginated,
|
|
|
|
|
@ -87,14 +89,26 @@ async function readExportError(error: unknown): Promise<Error> {
|
|
|
|
|
const text = await data.text()
|
|
|
|
|
try {
|
|
|
|
|
const payload = JSON.parse(text) as { message?: string; errors?: Record<string, string[]> }
|
|
|
|
|
return new Error(payload.errors?.export?.[0] || payload.errors?.part?.[0] || payload.message || '导出失败')
|
|
|
|
|
return new Error(
|
|
|
|
|
payload.errors?.export?.[0]
|
|
|
|
|
|| payload.errors?.application_ids?.[0]
|
|
|
|
|
|| payload.errors?.part?.[0]
|
|
|
|
|
|| payload.message
|
|
|
|
|
|| '导出失败',
|
|
|
|
|
)
|
|
|
|
|
} catch {
|
|
|
|
|
// ignore non-json blob errors
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (data && typeof data === 'object') {
|
|
|
|
|
const payload = data as { message?: string; errors?: Record<string, string[]> }
|
|
|
|
|
return new Error(payload.errors?.export?.[0] || payload.errors?.part?.[0] || payload.message || '导出失败')
|
|
|
|
|
return new Error(
|
|
|
|
|
payload.errors?.export?.[0]
|
|
|
|
|
|| payload.errors?.application_ids?.[0]
|
|
|
|
|
|| payload.errors?.part?.[0]
|
|
|
|
|
|| payload.message
|
|
|
|
|
|| '导出失败',
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -107,14 +121,28 @@ function sleep(ms: number): Promise<void> {
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function buildExportQueryParams(
|
|
|
|
|
params: AdminApplicationExportParams,
|
|
|
|
|
): Record<string, unknown> {
|
|
|
|
|
const { mode, application_ids, part, ...filters } = params
|
|
|
|
|
const query: Record<string, unknown> = { mode, ...filters }
|
|
|
|
|
if (application_ids?.length) {
|
|
|
|
|
query.application_ids = application_ids
|
|
|
|
|
}
|
|
|
|
|
if (part != null) {
|
|
|
|
|
query.part = part
|
|
|
|
|
}
|
|
|
|
|
return query
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function getAdminApplicationExportMeta(
|
|
|
|
|
competitionId: number,
|
|
|
|
|
params: AdminApplicationListParams,
|
|
|
|
|
params: AdminApplicationExportParams,
|
|
|
|
|
): Promise<AdminApplicationExportMeta> {
|
|
|
|
|
try {
|
|
|
|
|
const { data } = await adminHttp.get<AdminApplicationExportMeta>(
|
|
|
|
|
`/competitions/${competitionId}/applications/export/meta`,
|
|
|
|
|
{ params },
|
|
|
|
|
{ params: buildExportQueryParams(params) },
|
|
|
|
|
)
|
|
|
|
|
if (!data || typeof data !== 'object') throw new Error('导出信息无效')
|
|
|
|
|
return data
|
|
|
|
|
@ -125,13 +153,13 @@ export async function getAdminApplicationExportMeta(
|
|
|
|
|
|
|
|
|
|
export async function downloadAdminApplicationExportPart(
|
|
|
|
|
competitionId: number,
|
|
|
|
|
params: AdminApplicationListParams,
|
|
|
|
|
params: AdminApplicationExportParams,
|
|
|
|
|
part: number,
|
|
|
|
|
): Promise<void> {
|
|
|
|
|
let res
|
|
|
|
|
try {
|
|
|
|
|
res = await adminHttp.get<Blob>(`/competitions/${competitionId}/applications/export`, {
|
|
|
|
|
params: { ...params, part },
|
|
|
|
|
params: buildExportQueryParams({ ...params, part }),
|
|
|
|
|
responseType: 'blob',
|
|
|
|
|
timeout: 0,
|
|
|
|
|
})
|
|
|
|
|
@ -139,20 +167,29 @@ export async function downloadAdminApplicationExportPart(
|
|
|
|
|
throw await readExportError(error)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const fallback = params.mode === 'xlsx'
|
|
|
|
|
? '报名信息.xlsx'
|
|
|
|
|
: `报名信息导出_第${part}部分.zip`
|
|
|
|
|
const filename = parseDownloadFilename(
|
|
|
|
|
res.headers['content-disposition'] as string | undefined,
|
|
|
|
|
`报名信息导出_第${part}部分.zip`,
|
|
|
|
|
fallback,
|
|
|
|
|
)
|
|
|
|
|
triggerBlobDownload(res.data, filename)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export async function exportAdminApplications(
|
|
|
|
|
competitionId: number,
|
|
|
|
|
params: AdminApplicationListParams,
|
|
|
|
|
params: AdminApplicationExportParams,
|
|
|
|
|
onProgress?: (current: number, total: number) => void,
|
|
|
|
|
): Promise<AdminApplicationExportMeta> {
|
|
|
|
|
const meta = await getAdminApplicationExportMeta(competitionId, params)
|
|
|
|
|
|
|
|
|
|
if (params.mode === 'xlsx') {
|
|
|
|
|
onProgress?.(1, 1)
|
|
|
|
|
await downloadAdminApplicationExportPart(competitionId, params, 1)
|
|
|
|
|
return meta
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (let part = 1; part <= meta.part_count; part += 1) {
|
|
|
|
|
onProgress?.(part, meta.part_count)
|
|
|
|
|
await downloadAdminApplicationExportPart(competitionId, params, part)
|
|
|
|
|
@ -163,3 +200,5 @@ export async function exportAdminApplications(
|
|
|
|
|
|
|
|
|
|
return meta
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export type { AdminApplicationExportMode }
|
|
|
|
|
|