feat: 添加IP定位兜底并优化订单详情页
- 在用户拒绝定位授权时,通过IP定位获取当前位置作为兜底方案
- 移除订单详情页中硬编码的地图中心点计算,改为动态处理
- 更新轨迹数据解析逻辑,适配新的location字段格式
- 替换车辆图片的默认占位图为远程URL
| | |
| | | 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'; |
| | |
| | | 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({ |
| | |
| | | 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'); |
| | |
| | | }) |
| | | .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); |
| | | }); |
| | | }); |
| | | } |
| | | |
| | |
| | | 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' |
| | |
| | | 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 = [ |
| | | { |
| | |
| | | |
| | | // 处理行驶路径 |
| | | 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 } |
| | |
| | | <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> |
| | |
| | | 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); |
| | | } |
| | | }); |
| | | }; |