diff --git a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx index 3fa7b740..6da6e99e 100644 --- a/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Vehicles.tsx @@ -115,6 +115,62 @@ function exportFileName(filters: Record) { return `vehicle-coverage-${keyword}-${protocol}.csv`; } +type VehicleActionQueueItem = { + label: string; + count: number; + filters: Record; + color: 'orange' | 'red'; + priority: 'P0' | 'P1'; + detail: string; +}; + +function vehicleFilterSummary(filters: Record) { + return [ + filters.keyword ? `关键词:${filters.keyword}` : '', + filters.protocol ? `数据来源:${filters.protocol}` : '', + filters.coverage ? `来源覆盖:${coverageLabel[filters.coverage] ?? filters.coverage}` : '', + filters.missingProtocol ? `缺失来源:${filters.missingProtocol}` : '', + filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : '', + filters.online ? `在线:${onlineLabel[filters.online] ?? filters.online}` : '', + filters.bindingStatus ? `绑定:${bindingStatusLabel[filters.bindingStatus] ?? filters.bindingStatus}` : '', + filters.archiveStatus ? `档案:${archiveStatusLabel[filters.archiveStatus] ?? filters.archiveStatus}` : '', + filters.archiveMissing ? `档案缺项:${archiveMissingLabel[filters.archiveMissing] ?? filters.archiveMissing}` : '' + ].filter(Boolean); +} + +function vehicleGovernanceSummaryText({ + filters, + summary, + actionQueue +}: { + filters: Record; + summary: VehicleCoverageSummary | null; + actionQueue: VehicleActionQueueItem[]; +}) { + const archiveMissing = (summary?.archiveMissingFields ?? []) + .filter((item) => item.count > 0) + .map((item) => `${item.title} ${item.count.toLocaleString()}`) + .join('、') || '-'; + const missingSources = (summary?.missingSources ?? []) + .filter((item) => item.count > 0) + .map((item) => `${item.protocol} ${item.count.toLocaleString()}`) + .join('、') || '-'; + const actions = actionQueue.length > 0 + ? actionQueue.map((item) => `[${item.priority}] ${item.label} ${item.count.toLocaleString()}:${item.detail}`).join('\n') + : '暂无处置项'; + return [ + '【车辆治理摘要】', + `当前筛选:${vehicleFilterSummary(filters).join(';') || '全部车辆'}`, + `车辆总数:${(summary?.totalVehicles ?? 0).toLocaleString()},在线:${(summary?.onlineVehicles ?? 0).toLocaleString()}`, + `单源:${(summary?.singleSourceVehicles ?? 0).toLocaleString()},多源:${(summary?.multiSourceVehicles ?? 0).toLocaleString()},暂无来源:${(summary?.noDataVehicles ?? 0).toLocaleString()}`, + `待绑定:${(summary?.unboundVehicles ?? 0).toLocaleString()},档案不完整:${(summary?.archiveIncompleteVehicles ?? 0).toLocaleString()}`, + `档案缺项:${archiveMissing}`, + `缺失来源:${missingSources}`, + '处置队列:', + actions + ].join('\n'); +} + type VehicleActionRecommendation = { label: string; color: 'green' | 'orange' | 'red'; @@ -166,15 +222,19 @@ function sourceConsistencyAction(row: VehicleCoverageRow, onFilter: (filters: Re return {label}; } -async function copyVehicleShareURL() { +async function copyText(value: string, label: string) { try { - await navigator.clipboard.writeText(`${window.location.origin}${window.location.pathname}${window.location.hash}`); - Toast.success('已复制筛选链接'); + await navigator.clipboard.writeText(value); + Toast.success(`已复制${label}`); } catch { - Toast.error('复制筛选链接失败'); + Toast.error(`复制${label}失败`); } } +async function copyVehicleShareURL() { + await copyText(`${window.location.origin}${window.location.pathname}${window.location.hash}`, '筛选链接'); +} + export function Vehicles({ onOpenVehicle, onOpenQuality, @@ -219,8 +279,8 @@ export function Vehicles({ } return items; }, [pagination.total, summary]); - const actionQueue = useMemo; color: 'orange' | 'red'; priority: 'P0' | 'P1'; detail: string }>>(() => { - const items: Array<{ label: string; count: number; filters: Record; color: 'orange' | 'red'; priority: 'P0' | 'P1'; detail: string }> = []; + const actionQueue = useMemo(() => { + const items: VehicleActionQueueItem[] = []; const unboundCount = summary?.unboundVehicles ?? 0; if (unboundCount > 0) { items.push({ @@ -278,17 +338,7 @@ export function Vehicles({ } return items; }, [summary]); - const filterSummary = [ - filters.keyword ? `关键词:${filters.keyword}` : '', - filters.protocol ? `数据来源:${filters.protocol}` : '', - filters.coverage ? `来源覆盖:${coverageLabel[filters.coverage] ?? filters.coverage}` : '', - filters.missingProtocol ? `缺失来源:${filters.missingProtocol}` : '', - filters.serviceStatus ? `服务状态:${serviceStatusLabel[filters.serviceStatus] ?? filters.serviceStatus}` : '', - filters.online ? `在线:${onlineLabel[filters.online] ?? filters.online}` : '', - filters.bindingStatus ? `绑定:${bindingStatusLabel[filters.bindingStatus] ?? filters.bindingStatus}` : '', - filters.archiveStatus ? `档案:${archiveStatusLabel[filters.archiveStatus] ?? filters.archiveStatus}` : '', - filters.archiveMissing ? `档案缺项:${archiveMissingLabel[filters.archiveMissing] ?? filters.archiveMissing}` : '' - ].filter(Boolean); + const filterSummary = vehicleFilterSummary(filters); const load = (values: Record = filters, page = pagination.currentPage, pageSize = pagination.pageSize) => { setLoading(true); @@ -328,6 +378,9 @@ export function Vehicles({ downloadCsv(exportFileName(filters), buildCsv(vehicleExportColumns, rows)); Toast.success(`已导出 ${rows.length} 条车辆结果`); }; + const copyGovernanceSummary = () => { + copyText(vehicleGovernanceSummaryText({ filters, summary, actionQueue }), '治理摘要'); + }; useEffect(() => { setFilters(initialFilters); @@ -497,7 +550,16 @@ export function Vehicles({ ) : null} - + + 当前车辆结果 + + + )} + style={{ marginTop: 16 }} + >
{resultSummary.map((item) => (