From 955c9066fb99669df5ab5050c4125bbb892ce0ce Mon Sep 17 00:00:00 2001
From: hejianhao <15708179461@qq.com>
Date: 星期五, 17 四月 2026 22:57:38 +0800
Subject: [PATCH] fix: 修复行程状态切换时定时器与地图视角的竞争条件
---
src/robotaxi/pages/begin-route/components/calling-car-modules/use-trip-countdown.ts | 10 +++++
src/robotaxi/pages/begin-route/hooks/use-map-viewport.ts | 61 ++++++++++++++++++++++++++++++
src/robotaxi/pages/begin-route/hooks/use-trip-runtime.ts | 2
src/robotaxi/pages/begin-route/index.tsx | 2
src/robotaxi/pages/begin-route/hooks/use-map-markers.ts | 20 ---------
src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts | 4 -
6 files changed, 75 insertions(+), 24 deletions(-)
diff --git a/src/robotaxi/pages/begin-route/components/calling-car-modules/use-trip-countdown.ts b/src/robotaxi/pages/begin-route/components/calling-car-modules/use-trip-countdown.ts
index eec4cd5..a5844c0 100644
--- a/src/robotaxi/pages/begin-route/components/calling-car-modules/use-trip-countdown.ts
+++ b/src/robotaxi/pages/begin-route/components/calling-car-modules/use-trip-countdown.ts
@@ -36,6 +36,7 @@
const pickupTimerRef = useRef<any>(null);
const finishTimerRef = useRef<any>(null);
const countdownFinishedRef = useRef(false);
+ const pickupTripStatusRef = useRef(tripStatus);
const pickupEndTimeRef = useRef<number | null>(null);
const finishEndTimeRef = useRef<number | null>(null);
const lastFareOrderIdRef = useRef<string | null>(null);
@@ -108,12 +109,21 @@
}, [tripStatus]);
useEffect(() => {
+ pickupTripStatusRef.current = tripStatus;
+ }, [tripStatus]);
+
+ useEffect(() => {
if (tripStatus !== 5) {
clearPickupTimer();
return;
}
const runPickupTick = () => {
+ // 防止状态已切换后,旧定时回调仍触发取消逻辑
+ if (pickupTripStatusRef.current !== 5) {
+ clearPickupTimer();
+ return;
+ }
const remaining = getRemainingSeconds(pickupEndTimeRef.current);
if (remaining !== null && remaining <= 0) {
if (!countdownFinishedRef.current) {
diff --git a/src/robotaxi/pages/begin-route/hooks/use-map-markers.ts b/src/robotaxi/pages/begin-route/hooks/use-map-markers.ts
index 45d4c3e..ff7e315 100644
--- a/src/robotaxi/pages/begin-route/hooks/use-map-markers.ts
+++ b/src/robotaxi/pages/begin-route/hooks/use-map-markers.ts
@@ -159,26 +159,8 @@
].join('|'))
.join(';');
const hasDropoffMarker = markersRef.current.some((m: any) => m.id === 2);
- const hasCarMarker = markersRef.current.some((m: any) => m.id === deps.vehicleMarkerId);
- const currentCarMarker = markersRef.current.find((m: any) => m.id === deps.vehicleMarkerId);
- const currentRotate = Number(currentCarMarker?.rotate);
- const targetRotate = Number(deps.vehicleDirection);
- const angleDiff = (a: number, b: number) => {
- const diff = Math.abs(((a - b + 540) % 360) - 180);
- return diff;
- };
- const isArrivedAngleSynced = Number.isFinite(currentRotate)
- && Number.isFinite(targetRotate)
- && angleDiff(currentRotate, targetRotate) < 1;
const shouldHoldMarkerByTranslate = [4, 6].includes(deps.tripStatus) && carMarkerInitialized.current && deps.statusRule.showCar && (!deps.statusRule.showDropoff || hasDropoffMarker);
- const shouldHoldMarkerWhenArrived = deps.tripStatus === 7
- && deps.arrivedTooltipReady
- && carMarkerInitialized.current
- && effectiveShowCar
- && hasCarMarker
- && isArrivedAngleSynced
- && (!deps.statusRule.showDropoff || hasDropoffMarker);
- const shouldSkipUpdate = (shouldHoldMarkerByTranslate && (deps.isAndroid || tripStatus6MarkerRefreshedRef.current)) || shouldHoldMarkerWhenArrived;
+ const shouldSkipUpdate = shouldHoldMarkerByTranslate && (deps.isAndroid || tripStatus6MarkerRefreshedRef.current);
applyMarkerState(nextMarkers, nextMarkersSignature, shouldSkipUpdate, carMarker);
}, [deps.tripStatus, deps.startSite?.name, deps.startSite?.latitude, deps.startSite?.longitude, deps.endSite?.name, deps.endSite?.latitude, deps.endSite?.longitude, deps.vehicleLocation, deps.vehicleDirection, deps.vehicleMarkerId, deps.isAndroid, deps.statusRule.showPickup, deps.statusRule.showCar, deps.statusRule.showDropoff]);
diff --git a/src/robotaxi/pages/begin-route/hooks/use-map-viewport.ts b/src/robotaxi/pages/begin-route/hooks/use-map-viewport.ts
index f725a89..b278b54 100644
--- a/src/robotaxi/pages/begin-route/hooks/use-map-viewport.ts
+++ b/src/robotaxi/pages/begin-route/hooks/use-map-viewport.ts
@@ -49,7 +49,10 @@
const mapRectRef = useRef<any>(null);
const viewportKeyRef = useRef<string>('');
+ const orderDetailViewportLockedRef = useRef(false);
const tripStatus6ViewportLockedRef = useRef(false);
+ const orderDetailEnterSignatureRef = useRef('');
+ const orderDetailRouteUpdatedAfterEnterRef = useRef(false);
const isAndroid = useMemo(() => {
try {
@@ -183,6 +186,22 @@
return { points, keyParts };
};
+ const buildOrderDetailRouteSignature = (pickupSite: any, dropoffSite: any) => {
+ const firstPoint = deps.routePoints[0];
+ const lastPoint = deps.routePoints[deps.routePoints.length - 1];
+ return [
+ deps.routePoints.length,
+ firstPoint?.latitude ?? '',
+ firstPoint?.longitude ?? '',
+ lastPoint?.latitude ?? '',
+ lastPoint?.longitude ?? '',
+ pickupSite?.latitude ?? '',
+ pickupSite?.longitude ?? '',
+ dropoffSite?.latitude ?? '',
+ dropoffSite?.longitude ?? '',
+ ].join('|');
+ };
+
const updateViewportByPayload = (viewportType: string, points: any[]) => {
const mapCtx = Taro.createMapContext('map');
const bottomPadding = computeBottomPadding(points, viewportType);
@@ -274,11 +293,48 @@
}, [deps.tripStatus, deps.statusRule?.viewport, deps.endSite?.latitude, deps.endSite?.longitude, mapScale]);
useEffect(() => {
+ if (![8, 9].includes(deps.tripStatus)) {
+ orderDetailViewportLockedRef.current = false;
+ orderDetailRouteUpdatedAfterEnterRef.current = false;
+ orderDetailEnterSignatureRef.current = '';
+ return;
+ }
+ const { pickupSite, dropoffSite } = resolveViewportSites();
+ orderDetailEnterSignatureRef.current = buildOrderDetailRouteSignature(pickupSite, dropoffSite);
+ orderDetailRouteUpdatedAfterEnterRef.current = false;
+ orderDetailViewportLockedRef.current = false;
+ viewportKeyRef.current = '';
+ setMapScale(14);
+ }, [deps.tripStatus]);
+
+ useEffect(() => {
+ if (![8, 9].includes(deps.tripStatus)) return;
+ const { pickupSite, dropoffSite } = resolveViewportSites();
+ const currentSignature = buildOrderDetailRouteSignature(pickupSite, dropoffSite);
+ if (!orderDetailEnterSignatureRef.current) {
+ orderDetailEnterSignatureRef.current = currentSignature;
+ return;
+ }
+ if (currentSignature === orderDetailEnterSignatureRef.current) return;
+ orderDetailRouteUpdatedAfterEnterRef.current = true;
+ orderDetailViewportLockedRef.current = false;
+ viewportKeyRef.current = '';
+ }, [deps.tripStatus, deps.routePoints, deps.startSite?.latitude, deps.startSite?.longitude, deps.endSite?.latitude, deps.endSite?.longitude]);
+
+ useEffect(() => {
const { pickupSite, dropoffSite } = resolveViewportSites();
const viewportType = deps.statusRule.viewport;
if (viewportType === 'dropoff') return;
const { points, keyParts } = buildViewportPayload(viewportType, pickupSite, dropoffSite);
if (points.length === 0) return;
+ if (
+ [8, 9].includes(deps.tripStatus) &&
+ viewportType === 'order_detail' &&
+ orderDetailViewportLockedRef.current &&
+ orderDetailRouteUpdatedAfterEnterRef.current
+ ) {
+ return;
+ }
if (deps.tripStatus === 6 && viewportType === 'route' && tripStatus6ViewportLockedRef.current) return;
const nextKey = keyParts.join('|');
if (nextKey === viewportKeyRef.current) return;
@@ -286,6 +342,10 @@
updateViewportByPayload(viewportType, points);
if (deps.tripStatus === 6 && viewportType === 'route') {
tripStatus6ViewportLockedRef.current = true;
+ }
+ if ([8, 9].includes(deps.tripStatus) && viewportType === 'order_detail') {
+ const hasOrderDetailRouteAfterEnter = orderDetailRouteUpdatedAfterEnterRef.current && deps.routePoints.length > 0;
+ orderDetailViewportLockedRef.current = hasOrderDetailRouteAfterEnter;
}
}, [deps.tripStatus, deps.statusRule, deps.routePoints, deps.walkingPoints, deps.startSite?.latitude, deps.startSite?.longitude, deps.endSite?.latitude, deps.endSite?.longitude, deps.vehicleLocation, deps.longitude, deps.latitude, mapBottomPadding]);
@@ -314,6 +374,7 @@
setShowLocationFlag,
mapRectRef,
viewportKeyRef,
+ orderDetailViewportLockedRef,
tripStatus6ViewportLockedRef,
isAndroid,
resolveSafeBottomInset,
diff --git a/src/robotaxi/pages/begin-route/hooks/use-trip-runtime.ts b/src/robotaxi/pages/begin-route/hooks/use-trip-runtime.ts
index 7095372..8285eed 100644
--- a/src/robotaxi/pages/begin-route/hooks/use-trip-runtime.ts
+++ b/src/robotaxi/pages/begin-route/hooks/use-trip-runtime.ts
@@ -231,7 +231,7 @@
useEffect(() => {
const wasHold = [4, 6].includes(deps.lastTripStatusRef.current);
const isHold = [4, 6].includes(deps.tripStatus);
- if (deps.tripStatus != 4) Taro.removeStorageSync('pickupEndTime');
+ if (deps.tripStatus != 5) Taro.removeStorageSync('pickupEndTime');
if (deps.tripStatus != 7) Taro.removeStorageSync('finishEndTime');
if (!wasHold && isHold) {
deps.orderRouteInitializedRef.current = false;
diff --git a/src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts b/src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts
index a72ecc0..384199c 100644
--- a/src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts
+++ b/src/robotaxi/pages/begin-route/hooks/use-web-socket-events.ts
@@ -202,12 +202,10 @@
const currentTripStatus = Number(deps.tripStatusRef.current);
if (currentTripStatus === 7) {
const lastPoint = deps.lastVehiclePointRef.current;
- const lastUpdateAt = Number(deps.lastVehicleUpdateAtRef.current || 0);
- const now = Date.now();
const latDiff = Math.abs(Number(lastPoint?.latitude || 0) - targetPoint.latitude);
const lngDiff = Math.abs(Number(lastPoint?.longitude || 0) - targetPoint.longitude);
const almostSamePoint = latDiff < 0.000003 && lngDiff < 0.000003;
- if (almostSamePoint || (now - lastUpdateAt < 1200)) {
+ if (almostSamePoint) {
return;
}
}
diff --git a/src/robotaxi/pages/begin-route/index.tsx b/src/robotaxi/pages/begin-route/index.tsx
index afda77b..95989f3 100644
--- a/src/robotaxi/pages/begin-route/index.tsx
+++ b/src/robotaxi/pages/begin-route/index.tsx
@@ -110,7 +110,7 @@
4: { showPickup: true, showDropoff: false, showCar: true, showRoute: true, showWalking: false, viewport: 'route', translateCar: true },
5: { showPickup: true, showDropoff: false, showCar: true, showRoute: false, showWalking: false, viewport: 'car_user', translateCar: true },
6: { showPickup: false, showDropoff: true, showCar: true, showRoute: true, showWalking: false, viewport: 'route', translateCar: true },
- 7: { showPickup: false, showDropoff: true, showCar: true, showRoute: false, showWalking: false, viewport: 'dropoff', translateCar: false },
+ 7: { showPickup: false, showDropoff: true, showCar: true, showRoute: false, showWalking: false, viewport: 'car_user', translateCar: true },
8: { showPickup: true, showDropoff: true, showCar: false, showRoute: true, showWalking: false, viewport: 'order_detail', translateCar: false },
9: { showPickup: true, showDropoff: true, showCar: false, showRoute: true, showWalking: false, viewport: 'order_detail', translateCar: false },
10: { showPickup: true, showDropoff: false, showCar: false, showRoute: false, showWalking: false, viewport: 'pickup', translateCar: false },
--
Gitblit v1.7.1