diff --git a/vehicle-data-platform/apps/web/src/pages/History.tsx b/vehicle-data-platform/apps/web/src/pages/History.tsx
index 759e42da..e9f3dc35 100644
--- a/vehicle-data-platform/apps/web/src/pages/History.tsx
+++ b/vehicle-data-platform/apps/web/src/pages/History.tsx
@@ -109,6 +109,10 @@ function timeValue(row?: HistoryLocationRow) {
return Number.isFinite(ms) ? ms : undefined;
}
+function playbackPointId(row: HistoryLocationRow, index: number) {
+ return `${row.vin || 'unknown'}-${row.deviceTime || row.serverTime || row.lastSeen || index}-${index}`;
+}
+
function formatDurationMinutes(value?: number, suffix = '') {
if (!isFiniteNumber(value)) return '-';
if (value < 1) return `${Math.round(value * 60)} 秒${suffix}`;
@@ -444,9 +448,10 @@ export function History({
const playbackRows = validLocations.length > 0 ? validLocations : locationItems;
const currentPlaybackIndex = playbackRows.length === 0 ? -1 : Math.min(playbackIndex, playbackRows.length - 1);
const currentPlayback = currentPlaybackIndex >= 0 ? playbackRows[currentPlaybackIndex] : undefined;
+ const currentPlaybackPointId = currentPlayback ? playbackPointId(currentPlayback, currentPlaybackIndex) : undefined;
const playbackAtEnd = playbackRows.length > 0 && currentPlaybackIndex >= playbackRows.length - 1;
const playbackPoints: VehicleMapPoint[] = validLocations.map((row, index) => ({
- id: `${row.vin}-${row.deviceTime || row.serverTime || index}`,
+ id: playbackPointId(row, index),
label: row.plate || row.vin || `点 ${index + 1}`,
longitude: row.longitude,
latitude: row.latitude,
@@ -539,6 +544,17 @@ export function History({
setPlaybackPlaying(false);
setPlaybackIndex((current) => Math.min(Math.max(current + delta, 0), playbackRows.length - 1));
};
+ const selectPlaybackPoint = (nextIndex: number) => {
+ if (playbackRows.length === 0) return;
+ setPlaybackPlaying(false);
+ setPlaybackIndex(Math.min(Math.max(nextIndex, 0), playbackRows.length - 1));
+ };
+ const selectPlaybackMapPoint = (point: VehicleMapPoint) => {
+ const index = playbackRows.findIndex((row, rowIndex) => playbackPointId(row, rowIndex) === point.id);
+ if (index >= 0) {
+ selectPlaybackPoint(index);
+ }
+ };
const openPlaybackVehicle = () => {
if (!currentPlayback || !canOpenVehicle(currentPlayback.vin)) return;
onOpenVehicle(currentPlayback.vin, currentPlayback.protocol);
@@ -648,6 +664,8 @@ export function History({