import { useMutation } from '@tanstack/react-query'; import { Button, Card, Input, Select, Upload } from '@douyinfe/semi-ui'; import { useState } from 'react'; import { api } from '../../api/client'; import type { VehicleProfileSyncItem, VehicleProfileSyncResult } from '../../api/types'; import { parseVehicleProfileSyncCSV, vehicleProfileSyncCSVHeader } from '../domain/profileSync'; export default function VehicleProfileSyncPanel({ onClose }: { onClose: () => void }) { const [sourceSystem, setSourceSystem] = useState(''); const [sourceVersion, setSourceVersion] = useState(''); const [conflictPolicy, setConflictPolicy] = useState<'preserve' | 'overwrite'>('preserve'); const [items, setItems] = useState([]); const [fileName, setFileName] = useState(''); const [parseError, setParseError] = useState(''); const sync = useMutation({ mutationFn: (dryRun) => api.syncVehicleProfiles({ sourceSystem: sourceSystem.trim(), sourceVersion: sourceVersion.trim(), conflictPolicy, dryRun, items }) }); const readFile = async (file?: File) => { sync.reset(); setItems([]); setFileName(file?.name ?? ''); setParseError(''); if (!file) return; try { setItems(parseVehicleProfileSyncCSV(await file.text())); } catch (error) { setParseError(error instanceof Error ? error.message : 'CSV 解析失败'); } }; const ready = sourceSystem.trim() !== '' && sourceVersion.trim() !== '' && items.length > 0 && !sync.isPending; const issues = sync.data?.items.filter((item) => item.status.startsWith('conflict_') || item.status === 'missing_vehicle').slice(0, 20) ?? []; const applied = sync.data && !sync.data.dryRun; return
批量同步车辆主档

CSV 最多 500 辆;先预演,再写入。默认保留人工档案和其他来源。