From b8199dcb5afa0dda05ec9ee1adeb13ba9c95f79c Mon Sep 17 00:00:00 2001 From: lingniu Date: Mon, 6 Jul 2026 00:41:55 +0800 Subject: [PATCH] feat(platform): add map vehicle handoff card --- .../apps/web/src/pages/Realtime.tsx | 41 +++++++++++++++++++ .../apps/web/src/styles/global.css | 2 +- .../apps/web/src/test/App.test.tsx | 9 ++++ 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx index e3523d95..b51f4f03 100644 --- a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx @@ -513,6 +513,29 @@ function mapCustomerPackageText({ ].filter(Boolean).join('\n'); } +function selectedMapVehicleHandoffText(row: VehicleRealtimeRow, protocol: string) { + const vin = row.vin || ''; + const vehicle = `${row.plate || '-'} / ${vin || '-'} / ${protocol || row.primaryProtocol || '-'}`; + const position = isValidCoordinate(row) ? `${row.longitude},${row.latitude}` : '无有效坐标'; + return [ + '【地图选中车辆交接卡】', + `车辆:${vehicle}`, + `服务状态:${vehicleServiceStatus(row).label}`, + `在线状态:${row.online ? '在线' : '离线'}`, + `最后上报:${row.lastSeen || '-'}`, + `位置:${position}`, + `速度:${row.speedKmh ?? '-'} km/h;SOC:${row.socPercent ?? '-'}%;总里程:${row.totalMileageKm ?? '-'} km`, + `问题:${realtimeIssueLabels(row).join(';')}`, + `建议动作:${realtimeIssueAction(row)}`, + `车辆服务:${appURL(buildAppHash({ page: 'detail', keyword: vin, protocol }))}`, + `实时地图:${appURL(buildAppHash({ page: 'map', keyword: vin, protocol }))}`, + `轨迹回放:${appURL(buildAppHash({ page: 'history', keyword: vin, protocol }))}`, + `统计查询:${appURL(buildAppHash({ page: 'mileage', keyword: vin, protocol }))}`, + `历史数据:${appURL(buildAppHash({ page: 'history-query', keyword: vin, protocol, filters: { tab: 'raw', includeFields: 'true' } }))}`, + `告警通知:${appURL(buildAppHash({ page: 'alert-events', keyword: vin, protocol }))}` + ].join('\n'); +} + function mapCustomerDecisionText({ filters, rows, @@ -1065,6 +1088,13 @@ export function Realtime({ filters: { tab: 'raw', includeFields: 'true' } }); }; + const copySelectedMapVehicleHandoff = () => { + if (!selectedMapRow || !canOpenVehicle(selectedMapRow.vin)) { + Toast.warning('请先选择可交接的车辆'); + return; + } + copyText(selectedMapVehicleHandoffText(selectedMapRow, selectedVehicleProtocol), '选中车辆交接卡'); + }; const mapVehicleWorkItems = [ { title: '车辆服务', @@ -2213,6 +2243,17 @@ export function Realtime({ 历史导出 {selectedMapRow ? selectedVehicleProtocol || selectedMapRow.primaryProtocol || '全部通道' : '等待选择'} + diff --git a/vehicle-data-platform/apps/web/src/styles/global.css b/vehicle-data-platform/apps/web/src/styles/global.css index a0df9714..647dc736 100644 --- a/vehicle-data-platform/apps/web/src/styles/global.css +++ b/vehicle-data-platform/apps/web/src/styles/global.css @@ -6177,7 +6177,7 @@ button.vp-realtime-command-item:focus-visible { .vp-map-selected-service-actions { min-width: 0; display: grid; - grid-template-columns: repeat(5, minmax(0, 1fr)); + grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; } diff --git a/vehicle-data-platform/apps/web/src/test/App.test.tsx b/vehicle-data-platform/apps/web/src/test/App.test.tsx index 58d9385f..2fd9fb8a 100644 --- a/vehicle-data-platform/apps/web/src/test/App.test.tsx +++ b/vehicle-data-platform/apps/web/src/test/App.test.tsx @@ -10771,6 +10771,15 @@ test('shows realtime freshness status for recently updated and stale vehicles', expect(screen.getByRole('button', { name: '地图选中车辆 轨迹复盘 打开轨迹' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '地图选中车辆 统计查询 统计查询' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: '地图选中车辆 数据导出 历史导出' })).toBeInTheDocument(); + expect(screen.getByRole('button', { name: '地图选中车辆 交接卡 复制交接' })).toBeInTheDocument(); + fireEvent.click(screen.getByRole('button', { name: '地图选中车辆 交接卡 复制交接' })); + await waitFor(() => { + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【地图选中车辆交接卡】')); + }); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆:粤A超时1 / VIN-STALE-001 / JT808')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('问题:')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('天未更新;JT808 离线')); + expect(writeText).toHaveBeenCalledWith(expect.stringContaining('车辆服务:http://localhost:3000/#/detail?keyword=VIN-STALE-001&protocol=JT808')); fireEvent.click(screen.getByRole('button', { name: /复制地图监控包/ })); await waitFor(() => { expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【客户地图监控包】'));