feat(platform): add map vehicle handoff card

This commit is contained in:
lingniu
2026-07-06 00:41:55 +08:00
parent c00cb0218a
commit b8199dcb5a
3 changed files with 51 additions and 1 deletions

View File

@@ -513,6 +513,29 @@ function mapCustomerPackageText({
].filter(Boolean).join('\n'); ].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/hSOC${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({ function mapCustomerDecisionText({
filters, filters,
rows, rows,
@@ -1065,6 +1088,13 @@ export function Realtime({
filters: { tab: 'raw', includeFields: 'true' } filters: { tab: 'raw', includeFields: 'true' }
}); });
}; };
const copySelectedMapVehicleHandoff = () => {
if (!selectedMapRow || !canOpenVehicle(selectedMapRow.vin)) {
Toast.warning('请先选择可交接的车辆');
return;
}
copyText(selectedMapVehicleHandoffText(selectedMapRow, selectedVehicleProtocol), '选中车辆交接卡');
};
const mapVehicleWorkItems = [ const mapVehicleWorkItems = [
{ {
title: '车辆服务', title: '车辆服务',
@@ -2213,6 +2243,17 @@ export function Realtime({
<strong></strong> <strong></strong>
<span>{selectedMapRow ? selectedVehicleProtocol || selectedMapRow.primaryProtocol || '全部通道' : '等待选择'}</span> <span>{selectedMapRow ? selectedVehicleProtocol || selectedMapRow.primaryProtocol || '全部通道' : '等待选择'}</span>
</button> </button>
<button
type="button"
className="vp-map-selected-service-action"
disabled={!selectedMapRow || !canOpenVehicle(selectedMapRow.vin)}
onClick={copySelectedMapVehicleHandoff}
aria-label="地图选中车辆 交接卡 复制交接"
>
<Tag color="blue"></Tag>
<strong></strong>
<span>{selectedMapRow ? realtimeIssueLabels(selectedMapRow)[0] : '等待选择'}</span>
</button>
</div> </div>
</div> </div>

View File

@@ -6177,7 +6177,7 @@ button.vp-realtime-command-item:focus-visible {
.vp-map-selected-service-actions { .vp-map-selected-service-actions {
min-width: 0; min-width: 0;
display: grid; display: grid;
grid-template-columns: repeat(5, minmax(0, 1fr)); grid-template-columns: repeat(6, minmax(0, 1fr));
gap: 10px; gap: 10px;
} }

View File

@@ -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();
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: /复制地图监控包/ })); fireEvent.click(screen.getByRole('button', { name: /复制地图监控包/ }));
await waitFor(() => { await waitFor(() => {
expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【客户地图监控包】')); expect(writeText).toHaveBeenCalledWith(expect.stringContaining('【客户地图监控包】'));