hejianhao
2026-03-12 1007a41342c99827e9abb31d1c712ea59d2b9fc2
fix(robotaxi): 修复路线查询失败时按钮状态和定位授权逻辑

- 在路线/费用查询失败时禁用“立即呼叫”按钮并显示禁用样式
- 优化定位授权被拒绝时的地图中心点设置和城市选择逻辑
- 修复站点选择时未传递electronicAreaId导致的问题
- 为Android设备优化路线绘制点的数量以防止渲染问题
- 调整定位授权恢复后的地图缩放和城市信息刷新
6个文件已修改
205 ■■■■■ 已修改文件
src/pages/robotaxi/home/index.tsx 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/release-route.less 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/release-route.tsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/select-map-site/index.tsx 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/site-search/index.tsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/index.tsx
@@ -90,9 +90,9 @@
    code: '',
  }); // 选中的城市
  const ensureSelectedCityReady = async (lng: number, lat: number, skipCityEffect = false) => {
  const ensureSelectedCityReady = async (lng: number, lat: number, skipCityEffect = false, forceRefresh = false) => {
    const cachedCity = Taro.getStorageSync('selectedCity');
    if (cachedCity?.code) {
    if (!forceRefresh && cachedCity?.code && typeof cachedCity?.id === 'number') {
      return cachedCity;
    }
    try {
@@ -227,44 +227,10 @@
        }
        if (auth === false) {
          setIsLocationAuthDenied(true);
          // 检查是否有选中的城市缓存
          const selectedCity = Taro.getStorageSync('selectedCity');
          if (!selectedCity || !selectedCity.code) {
            // 没有缓存,尝试通过 IP 获取位置
            getLocationByIP().then(res => {
              setLatitude(res.latitude);
              setLongitude(res.longitude);
              const cityName = res.city || res.province || '北京市';
              const cityCode = convertAdcodeToCityCode(res.adcode, cityName, res.province);
              const cityInfo = {
                name: cityName,
                code: cityCode
              };
              setSelectedCity(cityInfo);
              Taro.setStorageSync('selectedCity', cityInfo);
            }).catch(() => {
              // IP 获取失败,使用默认值
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
              setSelectedCity({
                name: '北京市',
                code: '110000',
              })
              Taro.setStorageSync('selectedCity', {
                name: '北京市',
                code: '110000',
              });
            });
          } else {
            // 有缓存,但授权被拒绝,仍然可以尝试通过 IP 更新中心点
            getLocationByIP().then(res => {
              setLatitude(res.latitude);
              setLongitude(res.longitude);
            }).catch(() => {
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
            });
          }
          setMapScale(3);
          setLatitude(DEFAULT_LATITUDE);
          setLongitude(DEFAULT_LONGITUDE);
          return;
        } else {
          setIsLocationAuthDenied(false);
          // 检查缓存中是否有 startSite
@@ -418,12 +384,14 @@
      return;
    }
    if (!selectedCity.code) return;
    const allowMapMove = !isLocationAuthDenied;
    getGeofence({ cityCode: selectedCity.code }).then((res: any) => {
      if (res && Array.isArray(res) && res.length > 0) {
        const newPolygons = formatGeofencePolygons(res);
        setPolygons(newPolygons);
        if (!Taro.getStorageSync('startSite')) {
        const shouldIncludeOperatingArea = allowMapMove && !Taro.getStorageSync('startSite');
        if (shouldIncludeOperatingArea) {
          if (skipFenceIncludePointsRef.current) {
            skipFenceIncludePointsRef.current = false;
          } else {
@@ -439,7 +407,7 @@
        setPolygons([]);
        if ((orderData || orderData?.id) && JSON.stringify(orderData) != '{}') return;
        // 定位到城市中心
        if (selectedCity.name) {
        if (selectedCity.name && allowMapMove) {
          getCityLocation(selectedCity.name).then(loc => {
            setLatitude(loc.latitude);
            setLongitude(loc.longitude);
@@ -459,7 +427,7 @@
      console.error('获取电子围栏失败', err);
      setPolygons([]);
      // 定位到城市中心
      if (selectedCity.name) {
      if (selectedCity.name && allowMapMove) {
        getCityLocation(selectedCity.name).then(loc => {
          setLatitude(loc.latitude);
          setLongitude(loc.longitude);
@@ -475,7 +443,7 @@
        });
      }
    });
  }, [selectedCity.code, selectedCity.name]);
  }, [selectedCity.code, selectedCity.name, isLocationAuthDenied]);
  const calculateBoxHeight = () => {
    // 延迟计算,确保 DOM 渲染完成
@@ -515,7 +483,7 @@
  }
  // 获取用户位置信息
  const getLocationInfo = (updateCenter = true) => {
  const getLocationInfo = (updateCenter = true, forceCityRefresh = false) => {
    console.log('getLocation获取用户位置信息');
    Taro.getLocation({ type: 'gcj02' })
      .then(async res => {
@@ -526,7 +494,7 @@
        }
        try {
          const cityInfo = await ensureSelectedCityReady(res.longitude, res.latitude);
          const cityInfo = await ensureSelectedCityReady(res.longitude, res.latitude, false, forceCityRefresh);
          if (cityInfo?.code) {
            const { newMarkers, sites } = await updateMapData(res.latitude, res.longitude, cityInfo.code);
            const { targetMarker, minDistance } = findNearestMarker(res.latitude, res.longitude, sites.length > 0 ? sites : newMarkers);
@@ -578,32 +546,60 @@
        Taro.getSetting({
          success: (res) => {
            const auth = res.authSetting['scope.userLocation'];
            setIsLocationAuthDenied(auth === false);
            if (auth === false) {
              setIsLocationAuthDenied(true);
              setMapScale(3);
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
              return;
            }
            setIsLocationAuthDenied(false);
            getLocationByIP().then(res => {
              setLatitude(res.latitude);
              setLongitude(res.longitude);
              const cityName = res.city || res.province || '北京市';
              const cityCode = convertAdcodeToCityCode(res.adcode, cityName, res.province);
              const cityInfo = {
                name: cityName,
                code: cityCode
              };
              setSelectedCity(cityInfo);
              Taro.setStorageSync('selectedCity', cityInfo);
              setCurrentAddress(cityName);
              setCurrentSite({
                name: cityName,
                latitude: res.latitude,
                longitude: res.longitude
              });
            }).catch(() => {
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
            });
          },
          fail: () => {
            setIsLocationAuthDenied(false);
            getLocationByIP().then(res => {
              setLatitude(res.latitude);
              setLongitude(res.longitude);
              const cityName = res.city || res.province || '北京市';
              const cityCode = convertAdcodeToCityCode(res.adcode, cityName, res.province);
              const cityInfo = {
                name: cityName,
                code: cityCode
              };
              setSelectedCity(cityInfo);
              Taro.setStorageSync('selectedCity', cityInfo);
              setCurrentAddress(cityName);
              setCurrentSite({
                name: cityName,
                latitude: res.latitude,
                longitude: res.longitude
              });
            }).catch(() => {
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
            });
          }
        });
        getLocationByIP().then(res => {
          setLatitude(res.latitude);
          setLongitude(res.longitude);
          const cityName = res.city || res.province || '北京市';
          const cityCode = convertAdcodeToCityCode(res.adcode, cityName, res.province);
          const cityInfo = {
            name: cityName,
            code: cityCode
          };
          setSelectedCity(cityInfo);
          Taro.setStorageSync('selectedCity', cityInfo);
          setCurrentAddress(cityName);
          setCurrentSite({
            name: cityName,
            latitude: res.latitude,
            longitude: res.longitude
          });
        }).catch(() => {
          setLatitude(DEFAULT_LATITUDE);
          setLongitude(DEFAULT_LONGITUDE);
        });
      });
  }
@@ -621,6 +617,7 @@
  const toOrigin = async () => {
    const ok = await ensureNetwork();
    if (!ok) return;
    if (isLocationAuthDenied) return;
    shouldIgnoreRegionChange.current = false;
    isReturningToOrigin.current = true;
    setMapScale(14);
@@ -633,6 +630,7 @@
    const type = e?.type || e?.detail?.type;
    // 获取触发源: gesture (手势), update (接口调用)
    const causedBy = e?.causedBy || e?.detail?.causedBy;
    if (isLocationAuthDenied) return;
    // 如果是用户手势拖动,则必须触发,且重置忽略标记
    if (causedBy === 'gesture' || causedBy === 'drag' || causedBy === 'scale') {
@@ -877,7 +875,8 @@
      success: (res) => {
        if (res.authSetting['scope.userLocation']) {
          setIsLocationAuthDenied(false);
          getLocationInfo();
          setMapScale(14);
          getLocationInfo(true, true);
        }
      }
    })
@@ -901,6 +900,7 @@
      return;
    }
    if (isToMapStart) {
      Taro.setStorageSync('startSite', currentSite);
      Taro.navigateTo({
        url: '/robotaxi/pages/select-map-site/index?pageType=' + type,
      })
@@ -982,6 +982,7 @@
  const handleViewOperatingArea = async () => {
    const ok = await ensureNetwork();
    if (!ok) return;
    if (isLocationAuthDenied) return;
    if (!selectedCity?.code) {
      Taro.showToast({
        title: '此城市暂未开通运营区域',
@@ -1052,8 +1053,8 @@
    <View className="home-container">
      <Map
        id="map"
        longitude={longitude ?? 104.066541}
        latitude={latitude ?? 30.572269}
        longitude={longitude ?? DEFAULT_LONGITUDE}
        latitude={latitude ?? DEFAULT_LATITUDE}
        scale={mapScale}
        markers={isLocationAuthDenied ? [] : markers}
        polygons={polygons}
src/robotaxi/pages/begin-route/components/css-folder/release-route.less
@@ -224,5 +224,10 @@
            letter-spacing: normal;
            color: #FFFFFF;
        }
        .confirm-btn-disabled {
            background: #C0C6D4;
            color: rgba(255, 255, 255, 0.9);
            pointer-events: none;
        }
    }
}
}
src/robotaxi/pages/begin-route/components/release-route.tsx
@@ -12,9 +12,10 @@
    fareEstimate?: any;
    handleOpenPassengerNotice?: () => void;
    walkingTime?: number;
    isCallDisabled?: boolean;
}
export default function ReleaseRoute({ startSite, endSite, callImmediately, fareEstimate = {}, handleOpenPassengerNotice, walkingTime = 0 }: Props) {
export default function ReleaseRoute({ startSite, endSite, callImmediately, fareEstimate = {}, handleOpenPassengerNotice, walkingTime = 0, isCallDisabled = false }: Props) {
    const toSeleteSitePage = (type: string) => {
        Taro.navigateTo({
@@ -77,8 +78,8 @@
                        </View>
                    </View>
                </View>
                <View onClick={callImmediately} className="confirm-btn">立即呼叫</View>
                <View onClick={() => !isCallDisabled && callImmediately()} className={`confirm-btn${isCallDisabled ? ' confirm-btn-disabled' : ''}`}>立即呼叫</View>
            </View>
        </View>
    )
}
}
src/robotaxi/pages/begin-route/index.tsx
@@ -60,6 +60,7 @@
  const [walkingTime, setWalkingTime] = useState<number>(0);
  const carMarkerInitialized = useRef(false);
  const [fareEstimate, setFareEstimate] = useState<any>({}); // 预估费用信息
  const [routeAndFareError, setRouteAndFareError] = useState(false);
  const [vehicleLocation, setVehicleLocation] = useState<{ latitude: number, longitude: number } | null>(null);
  const [vehicleDirection, setVehicleDirection] = useState<number | null>(null);
  const [routeDistance, setRouteDistance] = useState<{ value: number; unit: 'km' | 'm' } | null>(null); // 路线距离
@@ -469,6 +470,7 @@
      },
    };
    queryRouteAndFare(params).then((res: any) => {
      setRouteAndFareError(false);
      if (res?.fareEstimate) {
        setFareEstimate(res.fareEstimate);
      }
@@ -507,6 +509,7 @@
      }
    }).catch(() => {
      setRouteAndFareError(true);
    });
  };
@@ -1207,6 +1210,9 @@
      })
      return
    }
    if (routeAndFareError) {
      return
    }
    const s = Taro.getStorageSync('startSite');
    if (!s?.latitude || !s?.longitude || !endSite?.latitude || !endSite?.longitude) {
      Taro.showToast({
@@ -1407,7 +1413,7 @@
  const toSelectSite = (pageType: 'start' | 'end') => {
    Taro.navigateTo({
      url: `/robotaxi/pages/site-search/index?pageType=${pageType}&longitude=${startSite.longitude}&latitude=${startSite.latitude}`
      url: `/robotaxi/pages/site-search/index?pageType=${pageType}&longitude=${startSite.longitude}&latitude=${startSite.latitude}&electronicAreaId=${startSite.electronicAreaId}`
    })
  }
@@ -1601,6 +1607,7 @@
                  fareEstimate={fareEstimate}
                  handleOpenPassengerNotice={handleOpenPassengerNotice}
                  walkingTime={walkingTime}
                  isCallDisabled={routeAndFareError}
                />
              }
              {/* 发布中弹窗 */}
src/robotaxi/pages/select-map-site/index.tsx
@@ -49,6 +49,7 @@
  const [outOfServiceRange, setOutOfServiceRange] = useState(false);
  const tooltipBgUrl = require('../../../robotaxi/assets/tooltip-bg.png');
  const [tooltipBgSrc, setTooltipBgSrc] = useState(tooltipBgUrl);
  const [isAndroid, setIsAndroid] = useState(false);
  const router = Taro.useRouter();
@@ -63,6 +64,8 @@
  // 页面初始化
  useEffect(() => {
    const systemInfo = Taro.getSystemInfoSync();
    setIsAndroid(systemInfo?.platform === 'android');
    const pType = router.params.pageType || 'end';
    setPageType(pType);
@@ -363,6 +366,22 @@
    });
  }
  const reducePoints = (points: any[], maxCount: number) => {
    if (!Array.isArray(points) || points.length <= maxCount) {
      return points;
    }
    const step = Math.ceil(points.length / maxCount);
    const reduced = [];
    for (let i = 0; i < points.length; i += step) {
      reduced.push(points[i]);
    }
    const last = points[points.length - 1];
    if (reduced[reduced.length - 1] !== last) {
      reduced.push(last);
    }
    return reduced;
  }
  useEffect(() => {
    if (pageType !== 'start') {
      setPolyline([]);
@@ -381,8 +400,14 @@
        setPolyline([]);
        return;
      }
      const safePoints = points.filter((item: any) => Number.isFinite(item?.latitude) && Number.isFinite(item?.longitude));
      const displayPoints = isAndroid ? reducePoints(safePoints, 120) : safePoints;
      if (displayPoints.length === 0) {
        setPolyline([]);
        return;
      }
      const line = [{
        points,
        points: displayPoints,
        color: '#6D7FD9',
        width: 6,
        dottedLine: true,
@@ -392,7 +417,7 @@
    }).catch(() => {
      setPolyline([]);
    });
  }, [pageType, userLatitude, userLongitude, latitude, longitude, selectedSite?.latitude, selectedSite?.longitude]);
  }, [pageType, userLatitude, userLongitude, latitude, longitude, selectedSite?.latitude, selectedSite?.longitude, isAndroid]);
  const toCoupon = async () => {
    const otp = await checkOtp(false);
src/robotaxi/pages/site-search/index.tsx
@@ -69,7 +69,8 @@
      if (otp && lat && lon) {
        const payload = {
          lat: Number(lat),
          lon: Number(lon)
          lon: Number(lon),
          electronicAreaId
        };
        const handleSuccess = (res) => {
@@ -198,6 +199,13 @@
  }
  const onChangeSelectSite = async (item, isNonOperational = true) => {
    if (item?.operationStatus === 2) {
      Taro.showToast({
        title: '当前点位暂未开放,请重新选点',
        icon: 'none',
      })
      return
    }
    if (!isNonOperational) {
      Taro.showToast({
        title: '当前点位暂未开放,请重新选点',