fix(robotaxi): 修复车费计算与地图气泡,新增首页上车点临时保留逻辑
- 修复车费详情卡片硬编码0.00的问题,改为显示扣除红包和优惠券后的实际应付金额
- 新增目的地修改预览时隐藏车辆地图气泡的逻辑,避免预览时的UI干扰
- 新增首页手动选择上车点临时保留至下次访问的功能,优化用户体验
| | |
| | | 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'; |
| | | |
| | |
| | | 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'); |
| | |
| | | } 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); |
| | |
| | | source: HomeStartSiteDisplaySource; |
| | | cityCode: string; |
| | | updatedAt: number; |
| | | /** 是否仅在下次回到首页时保留一次该上车点。 */ |
| | | retainOnNextHome: boolean; |
| | | }; |
| | | |
| | | export const HOME_START_SITE_DISPLAY_STATE_KEY = 'homeStartSiteDisplayState'; |
| | |
| | | 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; |
| | | }; |
| | | |
| | |
| | | ); |
| | | |
| | | /** |
| | | * 判断当前显示态是否需要在下次首页展示时保留一次手动上车点。 |
| | | */ |
| | | 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; |
| | |
| | | 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) => { |
| | |
| | | <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> |
| | | } |
| | |
| | | isAndroid: boolean; |
| | | tripStatus: TripStatus; |
| | | mapScale: number; |
| | | /** 修改目的地预览态下隐藏车辆气泡。 */ |
| | | isModifyDestinationReviewVisible: boolean; |
| | | routeSummaryLocation: { latitude: number; longitude: number } | null; |
| | | startSite: any; |
| | | endSite: any; |
| | |
| | | |
| | | // 更新车辆气泡位置 |
| | | 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; |
| | | } |
| | |
| | | |
| | | 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(); |
| | |
| | | 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' ? '米' : '公里'}` |
| | |
| | | {(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> |
| | |
| | | deps.customCalloutIconSrc, |
| | | deps.hasBeforeUserEndSite, |
| | | deps.isAndroid, |
| | | deps.isModifyDestinationReviewVisible, |
| | | deps.routeDistance, |
| | | deps.routeSummaryBgSrc, |
| | | deps.showTrip1StyleEndpoint, |
| | | deps.tripStatus, |
| | | durationDisplay, |
| | | routeSummaryText |
| | | routeSummaryText, |
| | | shouldShowVehicleMetricCallout |
| | | ]); |
| | | |
| | | /** |
| | |
| | | </View> |
| | | </View> |
| | | )} |
| | | {deps.isAndroid && deps.carCalloutVisible && ( |
| | | {deps.isAndroid && deps.carCalloutVisible && shouldShowVehicleMetricCallout && ( |
| | | <View className="car-callout-android" style={deps.carCalloutStyle}> |
| | | {androidCarCalloutContent} |
| | | </View> |
| | |
| | | deps.carCalloutStyle, |
| | | deps.carCalloutVisible, |
| | | deps.isAndroid, |
| | | deps.isModifyDestinationReviewVisible, |
| | | deps.markers, |
| | | deps.routeSummaryBgSrc, |
| | | deps.routeSummaryCalloutStyle, |
| | |
| | | deps.waitingRadarStyle, |
| | | deps.waitingRadarVisible, |
| | | renderMarkerCallout, |
| | | routeSummaryText |
| | | routeSummaryText, |
| | | shouldShowVehicleMetricCallout |
| | | ]); |
| | | |
| | | /** |
| | |
| | | isAndroid, |
| | | tripStatus, |
| | | mapScale, |
| | | isModifyDestinationReviewVisible, |
| | | routeSummaryLocation: routeSummaryMarker ? { |
| | | latitude: routeSummaryMarker.latitude, |
| | | longitude: routeSummaryMarker.longitude |