feat: 新增通用导入中心
This commit is contained in:
79
apps/admin/src/api/imports.ts
Normal file
79
apps/admin/src/api/imports.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
import api from './index';
|
||||
import { validateResponse } from '../utils/validate';
|
||||
import { importRunEnvelopeSchema } from './schemas';
|
||||
import type {
|
||||
ImportPreviewResult,
|
||||
ImportReceipt,
|
||||
ImportRunDetail,
|
||||
ImportStageRequest,
|
||||
} from '../components/ImportWizard/types';
|
||||
|
||||
interface ApiEnvelope<T> {
|
||||
success: boolean;
|
||||
data: T;
|
||||
message?: string;
|
||||
}
|
||||
|
||||
export async function createImportRun(
|
||||
file: File,
|
||||
options: {
|
||||
source: 'ai' | 'manual';
|
||||
conversationId?: number;
|
||||
stages?: ImportStageRequest[];
|
||||
mapping?: Record<string, Record<string, string>>;
|
||||
},
|
||||
): Promise<ImportRunDetail> {
|
||||
const form = new FormData();
|
||||
form.append('file', file);
|
||||
form.append('source', options.source);
|
||||
if (options.conversationId) form.append('conversationId', String(options.conversationId));
|
||||
if (options.stages?.length) form.append('stages', JSON.stringify(options.stages));
|
||||
if (options.mapping && Object.keys(options.mapping).length > 0) {
|
||||
form.append('mapping', JSON.stringify(options.mapping));
|
||||
}
|
||||
const res = await api.post<ApiEnvelope<ImportRunDetail>>('/imports/runs', form, {
|
||||
headers: { 'Content-Type': 'multipart/form-data' },
|
||||
});
|
||||
return res.data;
|
||||
}
|
||||
|
||||
export async function getImportRun(runId: string): Promise<ImportRunDetail> {
|
||||
const res = await api.get<ApiEnvelope<ImportRunDetail>>(
|
||||
`/imports/runs/${encodeURIComponent(runId)}`,
|
||||
);
|
||||
return validateResponse<ApiEnvelope<ImportRunDetail>>(importRunEnvelopeSchema, res).data;
|
||||
}
|
||||
|
||||
export async function previewImportStep(
|
||||
runId: string,
|
||||
stepKey: string,
|
||||
body: { sheets?: string[]; mapping?: Record<string, string> },
|
||||
): Promise<ImportPreviewResult> {
|
||||
const res = await api.post<ApiEnvelope<ImportPreviewResult>>(
|
||||
`/imports/runs/${encodeURIComponent(runId)}/steps/${encodeURIComponent(stepKey)}/preview`,
|
||||
body,
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
export async function commitImportStep(
|
||||
runId: string,
|
||||
stepKey: string,
|
||||
decisions: Array<{ rowId: number; action: 'create' | 'update' | 'skip' }>,
|
||||
): Promise<ImportReceipt> {
|
||||
const res = await api.post<ApiEnvelope<ImportReceipt>>(
|
||||
`/imports/runs/${encodeURIComponent(runId)}/steps/${encodeURIComponent(stepKey)}/commit`,
|
||||
{ decisions },
|
||||
);
|
||||
return res.data;
|
||||
}
|
||||
|
||||
export function importErrorReportUrl(runId: string, stepKey?: string): string {
|
||||
const base = import.meta.env.PROD
|
||||
? '/api'
|
||||
: `http://localhost:${import.meta.env.VITE_API_PORT || 3002}/api`;
|
||||
const params = new URLSearchParams();
|
||||
if (stepKey) params.set('stepKey', stepKey);
|
||||
const query = params.toString();
|
||||
return `${base}/imports/runs/${encodeURIComponent(runId)}/report${query ? `?${query}` : ''}`;
|
||||
}
|
||||
Reference in New Issue
Block a user