/** ASIN 中心导入/轮询通用模型(任务 76):启动结果、Excel 校验与导入进度归一(含 deletedCount),纯逻辑。 */ import { unwrap } from '../../api/envelope.ts' export const EXCEL_IMPORT_ALLOWED_EXT = /\.(xlsx|xls)$/i /** 是否为允许导入的 Excel 文件。 */ export function isAllowedExcelImportFile(fileName: unknown): boolean { return typeof fileName === 'string' && EXCEL_IMPORT_ALLOWED_EXT.test(fileName.trim()) } /** 解包导入启动结果并取回 importId;缺省抛可读错误。 */ export function parseImportStart(payload: unknown): string { const data = unwrap(payload) const record = data && typeof data === 'object' ? (data as Record) : null const importId = typeof record?.importId === 'string' ? record.importId.trim() : '' if (!importId) throw new Error('导入任务响应异常:缺少任务 ID') return importId } export type ImportStatus = 'pending' | 'running' | 'success' | 'failed' export interface ImportProgress { status: ImportStatus totalRows: number processedRows: number asinCount: number insertedCount: number deletedCount: number skippedCount: number errorMessage?: string } function intOrZero(value: unknown): number { return typeof value === 'number' && Number.isFinite(value) ? Math.floor(value) : 0 } /** 归一化导入进度负载;缺省按未开始(pending)处理,未知状态不改。 */ export function parseImportProgress(payload: unknown): ImportProgress { const data = unwrap(payload) const record = data && typeof data === 'object' ? (data as Record) : null const rawStatus = typeof record?.status === 'string' ? record.status.trim().toLowerCase() : '' const status: ImportStatus = rawStatus === 'running' || rawStatus === 'success' || rawStatus === 'failed' || rawStatus === 'pending' ? rawStatus : 'pending' const progress: ImportProgress = { status, totalRows: intOrZero(record?.totalRows), processedRows: intOrZero(record?.processedRows), asinCount: intOrZero(record?.asinCount), insertedCount: intOrZero(record?.insertedCount), deletedCount: intOrZero(record?.deletedCount), skippedCount: intOrZero(record?.skippedCount), } const errorMessage = typeof record?.errorMessage === 'string' && record.errorMessage.trim() ? record.errorMessage.trim() : undefined if (errorMessage) progress.errorMessage = errorMessage return progress } /** 是否到达终态(success/failed)。 */ export function importFinished(progress: Pick): boolean { return progress.status === 'success' || progress.status === 'failed' } /** 是否成功完成。 */ export function importSucceeded(progress: Pick): boolean { return progress.status === 'success' } /** 导入添加结果文案。 */ export function importOutcomeText(progress: ImportProgress): string { switch (progress.status) { case 'running': return `导入处理中:已处理 ${progress.processedRows}/${progress.totalRows} 行` case 'success': return `导入完成:处理 ${progress.insertedCount} 条,跳过 ${progress.skippedCount} 条` case 'failed': return progress.errorMessage ? `导入失败:${progress.errorMessage}` : '导入失败,请重试' case 'pending': default: return '等待导入任务开始…' } } /** 导入删除结果文案。 */ export function deleteOutcomeText(progress: ImportProgress): string { switch (progress.status) { case 'running': return `删除处理中:已处理 ${progress.processedRows}/${progress.totalRows} 行` case 'success': return `删除完成:删除 ${progress.deletedCount} 条,跳过 ${progress.skippedCount} 条` case 'failed': return progress.errorMessage ? `删除失败:${progress.errorMessage}` : '删除失败,请重试' case 'pending': default: return '等待删除任务开始…' } }