feat(platform): add map vehicle handoff card
This commit is contained in:
@@ -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/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({
|
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>
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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('【客户地图监控包】'));
|
||||||
|
|||||||
Reference in New Issue
Block a user