hejianhao
2026-05-20 a425b038382ee367999e08e0725d45d49f48838f
fix(robotaxi): 修复车费计算与地图气泡,新增首页上车点临时保留逻辑

- 修复车费详情卡片硬编码0.00的问题,改为显示扣除红包和优惠券后的实际应付金额
- 新增目的地修改预览时隐藏车辆地图气泡的逻辑,避免预览时的UI干扰
- 新增首页手动选择上车点临时保留至下次访问的功能,优化用户体验
6个文件已修改
76 ■■■■■ 已修改文件
src/pages/robotaxi/home/hooks/use-home-bootstrap.ts 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/hooks/use-home-start-site-display.ts 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car-modules/fare-detail-card.tsx 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-android-overlays.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/hooks/use-view-delegates.tsx 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/hooks/use-home-bootstrap.ts
@@ -4,10 +4,12 @@
import { SocketOrderStatus, TripStatus, toTripStatus } from '../../../../robotaxi/pages/begin-route/constants/trip-status';
import {
  clearHomeStartSiteDisplayState,
  consumeRetainManualSelectedHomeStartSiteOnNextHome,
  HOME_START_SITE_SOURCE_ACTIVE_ORDER,
  isManualSelectedHomeStartSiteDisplayState,
  readHomeStartSiteDisplayState,
  resolveHomeStartSiteDisplaySite,
  shouldRetainManualSelectedHomeStartSiteOnNextHome,
  writeHomeStartSiteDisplayState
} from './use-home-start-site-display';
@@ -168,7 +170,8 @@
    const activeOrder = await deps.getOrderActive();
    if (!activeOrder) {
      const preferredState = readHomeStartSiteDisplayState();
      const preferredStartSite = isManualSelectedHomeStartSiteDisplayState(preferredState)
      const shouldKeepManualStartSiteOnNextHome = shouldRetainManualSelectedHomeStartSiteOnNextHome(preferredState);
      const preferredStartSite = shouldKeepManualStartSiteOnNextHome
        ? resolveHomeStartSiteDisplaySite()
        : null;
      Taro.removeStorageSync('orderId');
@@ -179,9 +182,16 @@
      } else {
        Taro.setStorageSync('startSite', preferredStartSite);
      }
      if (preferredState?.source === HOME_START_SITE_SOURCE_ACTIVE_ORDER) {
      if (shouldKeepManualStartSiteOnNextHome) {
        consumeRetainManualSelectedHomeStartSiteOnNextHome(preferredState);
      } else if (preferredState?.source === HOME_START_SITE_SOURCE_ACTIVE_ORDER || preferredState) {
        clearHomeStartSiteDisplayState();
      }
      if (!shouldKeepManualStartSiteOnNextHome) {
        deps.setCurrentSite({});
        deps.setCurrentAddress('');
        deps.setIsAdsorbed(false);
      }
      deps.setTripStatus(0);
      deps.setOrderData({});
      deps.setPreferredStartSite(preferredStartSite);
src/pages/robotaxi/home/hooks/use-home-start-site-display.ts
@@ -14,6 +14,8 @@
  source: HomeStartSiteDisplaySource;
  cityCode: string;
  updatedAt: number;
  /** 是否仅在下次回到首页时保留一次该上车点。 */
  retainOnNextHome: boolean;
};
export const HOME_START_SITE_DISPLAY_STATE_KEY = 'homeStartSiteDisplayState';
@@ -46,7 +48,8 @@
    site: cachedState.site,
    source,
    cityCode: String(cachedState?.cityCode || ''),
    updatedAt: Number(cachedState?.updatedAt || Date.now())
    updatedAt: Number(cachedState?.updatedAt || Date.now()),
    retainOnNextHome: Boolean(cachedState?.retainOnNextHome)
  } as HomeStartSiteDisplayState;
};
@@ -79,9 +82,24 @@
);
/**
 * 判断当前显示态是否需要在下次首页展示时保留一次手动上车点。
 */
export const shouldRetainManualSelectedHomeStartSiteOnNextHome = (
  state: HomeStartSiteDisplayState | null
) => (
  isManualSelectedHomeStartSiteDisplayState(state)
  && Boolean(state?.retainOnNextHome)
);
/**
 * 写入首页确认上车点显示态。
 */
export const writeHomeStartSiteDisplayState = (site: any, source: HomeStartSiteDisplaySource, cityCodeArg?: string) => {
export const writeHomeStartSiteDisplayState = (
  site: any,
  source: HomeStartSiteDisplaySource,
  cityCodeArg?: string,
  retainOnNextHome?: boolean
) => {
  if (!isValidHomeStartSite(site)) {
    clearHomeStartSiteDisplayState();
    return;
@@ -90,12 +108,25 @@
    site,
    source,
    cityCode: String(cityCodeArg || getSelectedCityCode() || ''),
    updatedAt: Date.now()
    updatedAt: Date.now(),
    retainOnNextHome: typeof retainOnNextHome === 'boolean'
      ? retainOnNextHome
      : source === HOME_START_SITE_SOURCE_MANUAL_SELECTED
  };
  Taro.setStorageSync(HOME_START_SITE_DISPLAY_STATE_KEY, nextState);
};
/**
 * 消费一次“下次首页保留手动上车点”的标记,避免后续重复命中。
 */
export const consumeRetainManualSelectedHomeStartSiteOnNextHome = (state: HomeStartSiteDisplayState | null) => {
  if (!shouldRetainManualSelectedHomeStartSiteOnNextHome(state)) {
    return;
  }
  writeHomeStartSiteDisplayState(state?.site, HOME_START_SITE_SOURCE_MANUAL_SELECTED, state?.cityCode, false);
};
/**
 * 解析当前可用的首页确认上车点。
 */
export const resolveHomeStartSiteDisplaySite = (cityCodeArg?: string) => {
src/robotaxi/pages/begin-route/components/calling-car-modules/fare-detail-card.tsx
@@ -188,7 +188,9 @@
                <View className="pay-box">
                    {
                        fareBreakdown?.operateFree != 1 ?
                            <View className="pay-box-money"><View>0.00</View><View className="unit">元</View></View>
                            <View className="pay-box-money"><View>{formatMoney(
                                (fareBreakdown?.orderMoney - fareBreakdown?.redPacketMoney - fareBreakdown?.couponMoney) <= 0
                                    ? 0 : (fareBreakdown?.orderMoney - fareBreakdown?.redPacketMoney - fareBreakdown?.couponMoney))}</View><View className="unit">元</View></View>
                            :
                            <View className="pay-box-free">载客测试免费</View>
                    }
src/robotaxi/pages/begin-route/hooks/use-android-overlays.ts
@@ -7,6 +7,8 @@
  isAndroid: boolean;
  tripStatus: TripStatus;
  mapScale: number;
  /** 修改目的地预览态下隐藏车辆气泡。 */
  isModifyDestinationReviewVisible: boolean;
  routeSummaryLocation: { latitude: number; longitude: number } | null;
  startSite: any;
  endSite: any;
@@ -98,7 +100,7 @@
  // 更新车辆气泡位置
  const updateCarCalloutPosition = async () => {
    if (!deps.isAndroid || !deps.vehicleLocation || ![TripStatus.VehicleApproaching, TripStatus.InService].includes(deps.tripStatus)) {
    if (!deps.isAndroid || deps.isModifyDestinationReviewVisible || !deps.vehicleLocation || ![TripStatus.VehicleApproaching, TripStatus.InService].includes(deps.tripStatus)) {
      setCarCalloutVisible(false);
      return;
    }
@@ -177,7 +179,7 @@
  useEffect(() => {
    updateCarCalloutPosition();
  }, [deps.isAndroid, deps.vehicleLocation?.latitude, deps.vehicleLocation?.longitude, deps.tripStatus]);
  }, [deps.isAndroid, deps.isModifyDestinationReviewVisible, deps.vehicleLocation?.latitude, deps.vehicleLocation?.longitude, deps.tripStatus]);
  useEffect(() => {
    updateArriveCalloutPosition();
src/robotaxi/pages/begin-route/hooks/use-view-delegates.tsx
@@ -196,6 +196,8 @@
export default function useViewDelegates(deps: Deps) {
  /** 时长文案 */
  const durationDisplay = useMemo(() => formatRemainingDurationDisplay(deps.routeDuration), [deps.routeDuration]);
  /** 修改目的地预览态下隐藏车辆公里/分钟气泡。 */
  const shouldShowVehicleMetricCallout = !deps.isModifyDestinationReviewVisible;
  const routeSummaryText = useMemo(() => (
    deps.routeDistance && deps.routeDuration !== null
      ? `${durationDisplay.value}${durationDisplay.unit} ${deps.routeDistance.value}${deps.routeDistance.unit === 'm' ? '米' : '公里'}`
@@ -252,7 +254,7 @@
              {(deps.tripStatus === TripStatus.PublishRoute || deps.showTrip1StyleEndpoint) && <CoverImage className='custom-callout-icon' src={deps.customCalloutIconSrc} />}
            </CoverView>
          )}
          {(item.name === '车辆位置' && [TripStatus.VehicleApproaching, TripStatus.InService].includes(deps.tripStatus) && !deps.isAndroid) && (
          {(item.name === '车辆位置' && [TripStatus.VehicleApproaching, TripStatus.InService].includes(deps.tripStatus) && !deps.isAndroid && shouldShowVehicleMetricCallout) && (
            <CoverView className='custom-callout-content car-callout-with-before' style={{ padding: '6px 10px', minWidth: '40px', justifyContent: 'center', zIndex: 2 }}>
              {deps.hasBeforeUserEndSite && (
                <CoverView className='car-time car-before-order-tip'>即将完成上一单</CoverView>
@@ -278,12 +280,14 @@
    deps.customCalloutIconSrc,
    deps.hasBeforeUserEndSite,
    deps.isAndroid,
    deps.isModifyDestinationReviewVisible,
    deps.routeDistance,
    deps.routeSummaryBgSrc,
    deps.showTrip1StyleEndpoint,
    deps.tripStatus,
    durationDisplay,
    routeSummaryText
    routeSummaryText,
    shouldShowVehicleMetricCallout
  ]);
  /**
@@ -319,7 +323,7 @@
          </View>
        </View>
      )}
      {deps.isAndroid && deps.carCalloutVisible && (
      {deps.isAndroid && deps.carCalloutVisible && shouldShowVehicleMetricCallout && (
        <View className="car-callout-android" style={deps.carCalloutStyle}>
          {androidCarCalloutContent}
        </View>
@@ -340,6 +344,7 @@
    deps.carCalloutStyle,
    deps.carCalloutVisible,
    deps.isAndroid,
    deps.isModifyDestinationReviewVisible,
    deps.markers,
    deps.routeSummaryBgSrc,
    deps.routeSummaryCalloutStyle,
@@ -349,7 +354,8 @@
    deps.waitingRadarStyle,
    deps.waitingRadarVisible,
    renderMarkerCallout,
    routeSummaryText
    routeSummaryText,
    shouldShowVehicleMetricCallout
  ]);
  /**
src/robotaxi/pages/begin-route/index.tsx
@@ -503,6 +503,7 @@
    isAndroid,
    tripStatus,
    mapScale,
    isModifyDestinationReviewVisible,
    routeSummaryLocation: routeSummaryMarker ? {
      latitude: routeSummaryMarker.latitude,
      longitude: routeSummaryMarker.longitude