hejianhao
2026-03-01 1226d624fc1bf33fb0a3a15f8f0bd563d8d257fb
fix(robotaxi): 修复路线页面车辆方向与距离显示问题

- 在 websocket 订单路线数据中解析并传递车辆方向
- 修复距离显示单位逻辑,支持米和公里动态切换
- 优化车辆位置标记旋转,根据方向动态调整
- 修正定位授权状态处理逻辑,避免页面显示异常
3个文件已修改
98 ■■■■■ 已修改文件
src/pages/robotaxi/home/index.tsx 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/websocket.ts 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/index.tsx
@@ -171,7 +171,7 @@
      success: (res) => {
        const auth = res.authSetting['scope.userLocation'];
        if (auth === false) {
          // setIsLocationAuthDenied(true);
          setIsLocationAuthDenied(true);
          // 检查是否有选中的城市缓存
          const selectedCity = Taro.getStorageSync('selectedCity');
          if (!selectedCity || !selectedCity.code) {
@@ -211,6 +211,7 @@
            });
          }
        } else {
          setIsLocationAuthDenied(false);
          // 检查缓存中是否有 startSite
          const startSite = Taro.getStorageSync('startSite');
          if (startSite && startSite.latitude && startSite.longitude) {
@@ -244,6 +245,11 @@
                });
            }
          } else {
            if (isCitySwitchingRef.current) {
              isCitySwitchingRef.current = false;
              skipNextLocationCenterRef.current = true;
              return;
            }
            const shouldUpdateCenter = !skipNextLocationCenterRef.current;
            skipNextLocationCenterRef.current = false;
            getLocationInfo(shouldUpdateCenter);
@@ -445,6 +451,7 @@
  const getLocationInfo = (updateCenter = true) => {
    Taro.getLocation({ type: 'gcj02' })
      .then(async res => {
        setIsLocationAuthDenied(false);
        if (updateCenter) {
          setLatitude(res.latitude);
          setLongitude(res.longitude);
@@ -500,8 +507,15 @@
          });
      })
      .catch(() => {
        setIsLocationAuthDenied(true);
        // 定位授权失败,尝试通过 IP 获取位置
        Taro.getSetting({
          success: (res) => {
            const auth = res.authSetting['scope.userLocation'];
            setIsLocationAuthDenied(auth === false);
          },
          fail: () => {
            setIsLocationAuthDenied(false);
          }
        });
        getLocationByIP().then(res => {
          setLatitude(res.latitude);
          setLongitude(res.longitude);
src/robotaxi/pages/begin-route/index.tsx
@@ -55,7 +55,8 @@
  const [walkingTime, setWalkingTime] = useState<number>(0);
  const [fareEstimate, setFareEstimate] = useState<any>({}); // 预估费用信息
  const [vehicleLocation, setVehicleLocation] = useState<{ latitude: number, longitude: number } | null>(null);
  const [routeDistance, setRouteDistance] = useState<number | null>(null); // 路线距离
  const [vehicleDirection, setVehicleDirection] = useState<number | null>(null);
  const [routeDistance, setRouteDistance] = useState<{ value: number; unit: 'km' | 'm' } | null>(null); // 路线距离
  const [routeDuration, setRouteDuration] = useState<number | null>(null); // 路线时间
  const [vehicleInfo, setVehicleInfo] = useState<any>({}); // 车辆信息
  const [orderId, setOrderId] = useState<string>(''); // 订单ID
@@ -188,13 +189,16 @@
    }
  };
  // 归一化距离(公里)
  // 归一化距离(公里或米)
  const normalizeDistanceKm = (value: any) => {
    const num = Number(value);
    if (Number.isNaN(num)) {
      return null;
    }
    return Number((num / 1000).toFixed(1));
    if (num >= 1000) {
      return { value: Number((num / 1000).toFixed(1)), unit: 'km' as const };
    }
    return { value: Math.max(0, Math.round(num)), unit: 'm' as const };
  };
  // 归一化时间(秒)
@@ -253,8 +257,8 @@
      const distanceKm = normalizeDistanceKm(distance);
      if (distanceKm !== null) {
        setRouteDistance(distanceKm);
        Taro.setStorageSync('orderRouteDistance', distanceKm);
        Taro.setStorageSync('orderRouteDistanceUnit', 'km');
        Taro.setStorageSync('orderRouteDistance', distanceKm.value);
        Taro.setStorageSync('orderRouteDistanceUnit', distanceKm.unit);
      }
      const durationSeconds = normalizeDurationSeconds(duration);
      if (durationSeconds !== null) {
@@ -315,7 +319,6 @@
    // 优化订单状态回调中的车辆信息拉取逻辑
    orderStatusHandlerRef.current = (payload) => {
      const mappedTripStatus = payload?.tripStatus;
      console.log('payload?.tripStatus', payload?.tripStatus)
      if (typeof mappedTripStatus === 'number') {
        setTripStatus(mappedTripStatus);
      }
@@ -368,11 +371,23 @@
    orderRouteHandlerRef.current = (payload) => {
      const points = payload?.points || [];
      if (tripStatusRef.current !== 5) {
      // if (tripStatusRef.current !== 5) {
      setTimeout(() => {
        applyRoutePoints(points);
      } else {
        setRoutePoints([]);
        setPolyline([]);
        if ([4, 5, 6].includes(tripStatusRef.current)) {
          const firstPoint = points?.[0];
          if (firstPoint && typeof firstPoint.latitude === 'number' && typeof firstPoint.longitude === 'number') {
            setVehicleLocation({ latitude: firstPoint.latitude, longitude: firstPoint.longitude });
          }
        }
      }, 500);
      // } else {
      //   setRoutePoints([]);
      //   setPolyline([]);
      // }
      const direction = payload?.direction;
      if (typeof direction === 'number' && Number.isFinite(direction)) {
        setVehicleDirection(direction);
      }
      const distance = Number(JSON.parse(payload?.content?.route)?.distance);
      const duration = Number(JSON.parse(payload?.content?.route)?.duration);
@@ -479,9 +494,12 @@
        setLatitude(e.latitude);
        setLongitude(e.longitude);
        const mapCtx = Taro.createMapContext('map');
        mapCtx.moveToLocation({
          latitude: e.latitude,
          longitude: e.longitude,
        mapCtx.includePoints({
          points: [{
            latitude: e.latitude,
            longitude: e.longitude,
          }],
          padding: [50, 50, 500, 50]
        });
      }
      setElapsedSeconds(0);
@@ -573,6 +591,7 @@
      height: 20,
      anchor: { x: 0.5, y: 1 },
      zIndex: 3,
      rotate: typeof vehicleDirection === 'number' ? vehicleDirection : 0,
      name: '车辆位置',
      customCallout: { anchorY: 50, anchorX: 0, display: 'ALWAYS' }
    } : null;
@@ -625,7 +644,7 @@
    } else {
      setPolyline([]);
    }
  }, [tripStatus, shouldShowRoute, routePoints, walkingPoints, startSite?.name, startSite?.latitude, startSite?.longitude, endSite.name, endSite?.latitude, endSite?.longitude, vehicleLocation]);
  }, [tripStatus, shouldShowRoute, routePoints, walkingPoints, startSite?.name, startSite?.latitude, startSite?.longitude, endSite.name, endSite?.latitude, endSite?.longitude, vehicleLocation, vehicleDirection]);
  const bindSocketListeners = () => {
    if (!orderStatusBound.current && orderStatusHandlerRef.current) {
@@ -685,7 +704,7 @@
      const routeType = cachedTripStatus <= 5 ? 1 : 2;
      queryOrderRoute({ orderId: cachedOrderId, routeType })
        .then((res: any) => {
          const data = res?.data ?? res?.result ?? res;
          const data = res;
          const rawPoints = Array.isArray(data?.polyline) ? data.polyline : [];
          const points = rawPoints
            .map((item: any) => ({
@@ -712,8 +731,8 @@
          const distanceKm = normalizeDistanceKm(distance);
          if (distanceKm !== null) {
            setRouteDistance(distanceKm);
            Taro.setStorageSync('orderRouteDistance', distanceKm);
            Taro.setStorageSync('orderRouteDistanceUnit', 'km');
            Taro.setStorageSync('orderRouteDistance', distanceKm.value);
            Taro.setStorageSync('orderRouteDistanceUnit', distanceKm.unit);
          }
          const duration = Number(data?.duration);
          const durationSeconds = normalizeDurationSeconds(duration);
@@ -722,6 +741,7 @@
            Taro.setStorageSync('orderRouteDuration', durationSeconds);
            Taro.setStorageSync('orderRouteDurationUnit', 's');
          }
          setVehicleDirection(data?.direction);
        })
        .catch(() => { });
    }
@@ -740,9 +760,15 @@
    }
    const storedDistance = Number(Taro.getStorageSync('orderRouteDistance'));
    const storedDistanceUnit = Taro.getStorageSync('orderRouteDistanceUnit');
    const normalizedStoredDistance = storedDistanceUnit === 'km' ? storedDistance : normalizeDistanceKm(storedDistance);
    if (normalizedStoredDistance !== null) {
      setRouteDistance(normalizedStoredDistance);
    if (storedDistanceUnit === 'km' || storedDistanceUnit === 'm') {
      if (!Number.isNaN(storedDistance)) {
        setRouteDistance({ value: storedDistance, unit: storedDistanceUnit });
      }
    } else {
      const normalizedStoredDistance = normalizeDistanceKm(storedDistance);
      if (normalizedStoredDistance !== null) {
        setRouteDistance(normalizedStoredDistance);
      }
    }
    const storedDuration = Number(Taro.getStorageSync('orderRouteDuration'));
    const storedDurationUnit = Taro.getStorageSync('orderRouteDurationUnit');
@@ -1065,8 +1091,8 @@
                  (item.name === '车辆位置' && [4, 6].includes(tripStatus)) &&
                  <CoverView className="custom-callout-content">
                    <CoverView className="car-time">
                      <CoverView className="car-time-num">{routeDistance ?? 0}</CoverView>
                      <CoverView>公里</CoverView>
                      <CoverView className="car-time-num">{routeDistance?.value ?? 0}</CoverView>
                      <CoverView>{routeDistance?.unit === 'm' ? '米' : '公里'}</CoverView>
                      <CoverView className="car-time-num">{durationDisplay.value}</CoverView>
                      <CoverView>{durationDisplay.unit}</CoverView>
                    </CoverView>
src/utils/websocket.ts
@@ -333,6 +333,7 @@
    }
    if (data?.type === 'ORDER_ROUTE') {
      const routeType = content?.routeType;
      const direction = Number(content?.direction);
      // 2-12 新增
      const duration = Number(JSON.parse(content?.route ?? '{}')?.duration ?? '0');
      const distance = Number(JSON.parse(content?.route ?? '{}')?.distance ?? '0');
@@ -356,7 +357,7 @@
          cached.latest = points;
        }
        Taro.setStorageSync('orderRoutePoints', cached);
        this.notifyListeners('order_route', { routeType, points, data, content });
        this.notifyListeners('order_route', { routeType, direction, points, data, content });
      }
    }
  }
@@ -365,8 +366,9 @@
  private normalizeRoutePoints(content: any) {
    const route = JSON.parse(content?.route ?? '{}');
    const rawPoints = route?.polyline ?? [];
    if (!Array.isArray(rawPoints)) return [];
    return rawPoints.map((item: any) => {
    const arrPoint=JSON.parse(rawPoints);
    if (!Array.isArray(arrPoint)) return [];
    return arrPoint.map((item: any) => {
      const latitude = item?.latitude;
      const longitude = item?.longitude;
      if (typeof latitude === 'number' && typeof longitude === 'number') {