diff --git a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx index 49321eb9..9252e0e5 100644 --- a/vehicle-data-platform/apps/web/src/pages/Realtime.tsx +++ b/vehicle-data-platform/apps/web/src/pages/Realtime.tsx @@ -1214,6 +1214,39 @@ export function Realtime({ disabled: rows.length === 0 } ]; + const realtimeNextActions = [ + { + level: degradedCount > 0 || staleCount > 0 ? '优先' : '巡检', + title: degradedCount > 0 || staleCount > 0 ? '先处理异常车辆' : '先看在线车辆', + value: degradedCount > 0 || staleCount > 0 ? `${degradedCount.toLocaleString()} 降级 / ${staleCount.toLocaleString()} 超时` : `${onlineCount.toLocaleString()} 在线`, + detail: degradedCount > 0 || staleCount > 0 + ? '离线、更新超时、坐标无效或服务降级会直接影响客户看车体验。' + : `当前页 ${locatedCount.toLocaleString()} 辆有有效坐标,可进入地图查看分布。`, + action: degradedCount > 0 || staleCount > 0 ? '关注异常' : '打开地图', + color: degradedCount > 0 || staleCount > 0 ? 'orange' as const : 'green' as const, + onClick: () => degradedCount > 0 || staleCount > 0 ? applyFilters({ ...filters, serviceStatus: 'degraded' }) : (window.location.hash = buildAppHash({ page: 'map', protocol: filters.protocol, filters })) + }, + { + level: selectedMapRow ? '单车' : '选车', + title: selectedMapRow ? '复盘选中车辆' : '先选择一辆车', + value: selectedMapRow?.plate || selectedMapRow?.vin || '等待选车', + detail: selectedMapRow ? `${vehicleServiceStatus(selectedMapRow).label},${dataFreshness(selectedMapRow).detail}` : '从地图或实时列表选择车辆后,进入轨迹、里程、历史和告警。', + action: selectedMapRow ? '轨迹回放' : '查看车辆', + color: selectedMapRow ? vehicleServiceStatus(selectedMapRow).color : 'blue' as const, + disabled: selectedMapRow ? !canOpenVehicle(selectedMapRow.vin) : false, + onClick: () => selectedMapRow && canOpenVehicle(selectedMapRow.vin) ? onOpenHistory?.(selectedMapRow.vin, selectedVehicleProtocol) : applyFilters({ ...filters, online: 'online' }) + }, + { + level: '交付', + title: '导出当前实时清单', + value: `${rows.length.toLocaleString()} 辆当前页`, + detail: '客户问询或运营交接时,先导出当前筛选的车辆在线、位置、速度和里程。', + action: '导出 CSV', + color: rows.length > 0 ? 'blue' as const : 'grey' as const, + disabled: rows.length === 0, + onClick: exportRealtime + } + ]; const timeWindowMonitorBlock = (
@@ -1634,6 +1667,24 @@ export function Realtime({
+
+ {realtimeNextActions.map((item) => ( + + ))} +
{realtimeCustomerJourneyItems.map((item) => (