hejianhao
2026-02-28 b73ccf1ccc21fdce3623862f94d4727090d070f8
feat: 添加IP定位兜底并优化订单详情页

- 在用户拒绝定位授权时,通过IP定位获取当前位置作为兜底方案
- 移除订单详情页中硬编码的地图中心点计算,改为动态处理
- 更新轨迹数据解析逻辑,适配新的location字段格式
- 替换车辆图片的默认占位图为远程URL
3个文件已修改
122 ■■■■■ 已修改文件
src/pages/robotaxi/home/index.tsx 53 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/order/detail/index.tsx 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/Robotaxi-public-method.ts 58 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/index.tsx
@@ -21,7 +21,8 @@
  handleBannerJump,
  fetchMapData,
  getCityLocation,
  getCityInfoWithId
  getCityInfoWithId,
  getLocationByIP
} from '../../../utils/Robotaxi-public-method';
import { _ROBOTAXI_WS_HOST } from '../../../constants/api';
import { getGeofence, getBannerList, getAgreement, getOrderActive } from '../../../robotaxi/api/home';
@@ -171,6 +172,23 @@
        const auth = res.authSetting['scope.userLocation'];
        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({
@@ -181,6 +199,17 @@
            name: '北京市',
            code: '110000',
          });
            });
          } else {
            // 有缓存,但授权被拒绝,仍然可以尝试通过 IP 更新中心点
            getLocationByIP().then(res => {
              setLatitude(res.latitude);
              setLongitude(res.longitude);
            }).catch(() => {
              setLatitude(DEFAULT_LATITUDE);
              setLongitude(DEFAULT_LONGITUDE);
            });
          }
        } else {
          // 检查缓存中是否有 startSite
          const startSite = Taro.getStorageSync('startSite');
@@ -472,6 +501,28 @@
      })
      .catch(() => {
        setIsLocationAuthDenied(true);
        // 定位授权失败,尝试通过 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);
          setCurrentAddress(cityName);
          setCurrentSite({
            name: cityName,
            latitude: res.latitude,
            longitude: res.longitude
          });
        }).catch(() => {
          setLatitude(DEFAULT_LATITUDE);
          setLongitude(DEFAULT_LONGITUDE);
        });
      });
  }
src/robotaxi/pages/order/detail/index.tsx
@@ -9,7 +9,6 @@
import activeBad from '../../../assets/active-bad.png'
import activeNormal from '../../../assets/active-normal.png'
import right from '../../../assets/right.png'
import car from '../../../assets/car.png'
import up from '../../../assets/up.png'
import down from '../../../assets/down.png'
import lineRight from '../../../assets/line-right.png'
@@ -59,12 +58,6 @@
  const initMap = (data: OrderDetail) => {
    const { startLat, startLon, endLat, endLon, trajectories } = data;
    // 设置地图中心点(起点和终点的中间位置)
    const centerLng = (startLon + endLon) / 2;
    const centerLat = (startLat + endLat) / 2;
    setLongitude(centerLng);
    setLatitude(centerLat);
    // 设置起点和终点标记
    const markerList = [
      {
@@ -90,7 +83,7 @@
    // 处理行驶路径
    const routePath = trajectories?.length > 0 
      ? trajectories.map(item => ({ longitude: item.longitude || item.lon, latitude: item.latitude || item.lat }))
      ? trajectories.map(item => ({ longitude: item.location.split(',')[0], latitude: item.location.split(',')[1] }))
      : [
          { longitude: startLon, latitude: startLat },
          { longitude: endLon, latitude: endLat }
@@ -138,7 +131,7 @@
              <Text className='code'>{orderData.vehicleCode}</Text>
            </View>
          </View>
          <Image src={orderData.vehiclePictures || car} className='car-img' />
          <Image src={orderData.vehiclePictures || 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png'} className='car-img' />
        </View>
        <View className='evaluate-card'>
          <View className='card-title'>您对本次行程满意吗?</View>
src/utils/Robotaxi-public-method.ts
@@ -371,3 +371,61 @@
  Taro.removeStorageSync('orderId');
  Taro.removeStorageSync('tripStatus');
};
/**
 * 通过 IP 获取当前位置信息(用于定位授权失败时的兜底)
 */
export const getLocationByIP = (): Promise<any> => {
  return new Promise(async (resolve, reject) => {
    try {
      // 1. 获取当前 network IP
      // 微信小程序没有直接获取公网 IP 的接口,通常由后端从请求头中获取,或者通过第三方接口获取
      // 这里模拟调用服务端提供的 IP 定位接口,假设接口会自动识别请求来源 IP
      const res: any = await request({
        url: _ROBOTAXI_HOST + '/map/base/v1/mini-program/point/getPointByIp',
        method: 'GET',
      });
      if (res && res.point && typeof res.point.latitude === 'number' && typeof res.point.longitude === 'number') {
        resolve({
          longitude: res.point.longitude,
          latitude: res.point.latitude,
          city: res.city || '',
          adcode: res.adcode || ''
        });
      } else {
        // 如果后端接口不可用或未返回数据,尝试使用第三方接口作为备选获取 IP
        Taro.request({
          url: 'https://api.ipify.org?format=json',
          success: (ipRes) => {
            const ip = ipRes.data?.ip;
            if (ip) {
              // 拿着获取到的 IP 去请求服务端接口
              request({
                url: _ROBOTAXI_HOST + '/map/base/v1/mini-program/point/getPointByIp',
                method: 'POST',
                payload: { ip }
              }).then((businessRes: any) => {
                if (businessRes && businessRes.point && typeof businessRes.point.latitude === 'number' && typeof businessRes.point.longitude === 'number') {
                  resolve({
                    longitude: businessRes.point.longitude,
                    latitude: businessRes.point.latitude,
                    city: businessRes.city || '',
                    adcode: businessRes.adcode || ''
                  });
                } else {
                  reject('Business IP location failed');
                }
              }).catch(reject);
            } else {
              reject('Failed to get network IP');
            }
          },
          fail: reject
        });
      }
    } catch (error) {
      reject(error);
    }
  });
};