import axios from 'axios'; import { decodeTextFile } from './utils'; export type ProcessJsonListItem = { floors: number; type: 'smap' | 'scene'; [key: string]: any; OriginalProperties: string; }; export type ProcessJsonListResult = | { kind: 'zip'; blob: Blob; filename: string | null; headers: Record } | { kind: 'json'; data: any; headers: Record }; export type FloorImportItem = { name: string; fileList: any[]; keepProperties: boolean }; export async function collectOriginalProperties( currentFloorScenes: any[] | any, floorImportList: FloorImportItem[], normalizeSceneJson: (raw: unknown) => unknown, ): Promise { const currentScenesArray: any[] = Array.isArray(currentFloorScenes) ? currentFloorScenes : currentFloorScenes ? [currentFloorScenes] : []; const list = await Promise.all( floorImportList.map(async (_floor, idx) => { const keep = !!_floor.keepProperties; if (!keep) return ''; let source: any = currentScenesArray[idx]; if (source == null && currentScenesArray.length === 1) { source = currentScenesArray[0]; } if (source == null) return ''; try { const normalized = normalizeSceneJson(source) as any; if (!normalized || typeof normalized !== 'object' || Array.isArray(normalized)) { return ''; } return JSON.stringify([normalized]); } catch { return ''; } }), ); return list; } export async function buildProcessJsonListPayload( floorImportList: FloorImportItem[], originalProperties: string[], ): Promise { const payload: ProcessJsonListItem[] = []; for (let i = 0; i < floorImportList.length; i += 1) { const floor = floorImportList[i]; const files = (floor.fileList || []) as any[]; if (!files.length) throw new Error(`楼层 ${floor.name} 需要至少选择一个文件`); const placeholders: string[] = []; const exts: string[] = []; for (const fileInfo of files) { const file = fileInfo.originFileObj as File; const content = await decodeTextFile(file); if (!content) throw new Error(`楼层 ${floor.name} 的文件 ${file?.name} 读取为空`); placeholders.push(content); const ext = String(file?.name || '').toLowerCase().split('.').pop() || ''; exts.push(ext); } // 校验 if (placeholders.length > 1) { const hasNonSmap = exts.some((e) => e !== 'smap'); if (hasNonSmap) { throw new Error(`楼层 ${floor.name} 上传了多个文件,但包含非 .smap 文件,请仅上传 .smap 文件`); } } else { const ext0 = exts[0]; if (ext0 !== 'smap' && ext0 !== 'scene') { throw new Error(`楼层 ${floor.name} 仅支持 .scene 或 .smap 文件`); } } // 类型推断 let type: 'scene' | 'smap' = 'scene'; const hasSmap = exts.some((e) => e === 'smap'); if (placeholders.length > 1 || hasSmap) { type = 'smap'; } else { type = exts[0] === 'smap' ? 'smap' : 'scene'; } const item: ProcessJsonListItem = { floors: i + 1, type, OriginalProperties: originalProperties[i] || '', } as ProcessJsonListItem; placeholders.forEach((p, idx) => { (item as any)[`placeholder${idx + 1}`] = p; }); payload.push(item); } return payload; } export async function postProcessJsonList(payload: ProcessJsonListItem[]): Promise { const client = axios.create(); const url = '/api/map-converter/process-json-list'; const response = await client.post(url, payload, { responseType: 'blob' }); const contentType = (response.headers?.['content-type'] || '').toString().toLowerCase(); const headers: Record = {}; Object.entries(response.headers || {}).forEach(([k, v]) => (headers[k] = String(v))); if (contentType.includes('application/json')) { const text = await (response.data as Blob).text(); const data = JSON.parse(text); return { kind: 'json', data, headers }; } let filename: string | null = null; const disposition = headers['content-disposition'] || ''; const match = disposition.match(/filename=([^;]+)/i); if (match && match[1]) { filename = decodeURIComponent(match[1].replace(/\"/g, '')); } return { kind: 'zip', blob: response.data as Blob, filename, headers }; }