fix(robotaxi): 修复订单费用明细接口调用及优惠券选择逻辑
- 将查询费用明细接口从 PUT 改为 POST,并支持传入优惠券参数
- 优化优惠券选择弹窗的显示条件,支持行程结束后使用
- 在费用明细卡片中增加优惠券选择入口,行程结束后可更换优惠券
- 使用订单ID+优惠券ID作为费用请求去重键,避免重复请求
| | |
| | | // 查询订单费用明细 |
| | | export const queryFareBreakdown = async (payload) => { |
| | | return request({ |
| | | url: _ROBOTAXI_HOST + `/order/api/v1/mini-program/order/fare-breakdown/${payload}`, |
| | | method: 'PUT', |
| | | payload: { |
| | | orderId: String(payload) |
| | | } |
| | | url: _ROBOTAXI_HOST + '/order/api/v1/mini-program/order/fare-breakdown', |
| | | method: 'POST', |
| | | payload |
| | | }, true); |
| | | } |
| | | |
| | |
| | | resetDetailVersion?: number; |
| | | onToggleDetailFade?: (expanded: boolean, hasFare: boolean) => void; |
| | | handlePay?: () => void; |
| | | onOpenCouponSelect?: () => void; |
| | | }; |
| | | |
| | | export default function FareDetailCard({ |
| | |
| | | orderId, |
| | | resetDetailVersion, |
| | | onToggleDetailFade, |
| | | handlePay |
| | | handlePay, |
| | | onOpenCouponSelect |
| | | }: Props) { |
| | | const [showDetail, setShowDetail] = useState(false); // 费用明细展开状态 |
| | | |
| | |
| | | <Image src={require('../../../../assets/ccc-icon-right.png')} /> |
| | | </View> |
| | | { |
| | | (fareBreakdown?.redPacketMoney + fareBreakdown?.couponMoney > 0 && fareBreakdown?.operateFree != 1) && |
| | | (fareBreakdown?.operateFree != 1 && [TripStatus.TripFinished, TripStatus.PaymentSuccess].includes(tripStatus)) && |
| | | <View className="car-card-end-through"> |
| | | <View className="car-card-end-through-label">优惠活动</View> |
| | | <View className="car-card-end-through-content"> |
| | | <View className="car-card-end-through-content" onClick={onOpenCouponSelect}> |
| | | <View className="car-card-end-through-content-title">最佳优惠</View> |
| | | <View className="car-card-end-through-content-money">-{formatMoney(fareBreakdown?.redPacketMoney + fareBreakdown?.couponMoney)}元</View> |
| | | <Image src={require('../../../../assets/ccc-icon-right.png')} /> |
| | | <Image src={require('../../../../assets/change-coupon.png')} /> |
| | | </View> |
| | | </View> |
| | | } |
| | |
| | | const pickupTripStatusRef = useRef(tripStatus); |
| | | const pickupEndTimeRef = useRef<number | null>(null); |
| | | const finishEndTimeRef = useRef<number | null>(null); |
| | | const lastFareOrderIdRef = useRef<string | null>(null); |
| | | const lastFareRequestKeyRef = useRef<string | null>(null); // 费用明细请求去重键(订单+优惠券) |
| | | |
| | | const requestFareBreakdown = useCallback((force = false) => { |
| | | const targetOrderId = getTargetOrderId(orderId); |
| | | if (!targetOrderId) return; |
| | | if (!force && lastFareOrderIdRef.current === targetOrderId) return; |
| | | lastFareOrderIdRef.current = targetOrderId; |
| | | queryFareBreakdown(targetOrderId).then((res: any) => { |
| | | setFareBreakdown(res?.data ?? res?.result ?? res); |
| | | const selectedCouponId = String(Taro.getStorageSync('selectedCouponId') || ''); // 当前选择优惠券ID |
| | | const requestKey = `${targetOrderId}_${selectedCouponId}`; |
| | | if (!force && lastFareRequestKeyRef.current === requestKey) return; |
| | | lastFareRequestKeyRef.current = requestKey; |
| | | const payload: any = { |
| | | orderId: String(targetOrderId) |
| | | }; |
| | | if (selectedCouponId) { |
| | | payload.userCouponId = selectedCouponId; |
| | | } |
| | | queryFareBreakdown(payload).then((res: any) => { |
| | | const nextFareBreakdown = res; |
| | | setFareBreakdown(nextFareBreakdown); |
| | | const resolvedCouponId = String(nextFareBreakdown?.userCouponId); // 接口返回的当前生效券 |
| | | if (resolvedCouponId) { |
| | | Taro.setStorageSync('selectedCouponId', resolvedCouponId); |
| | | } |
| | | }).catch(() => { }); |
| | | }, [orderId]); |
| | | |
| | |
| | | handleCloseSuccessAuthPopup?: () => void; |
| | | handleAuthorizeBluetooth?: () => void; |
| | | pageDidShowVersion?: number; |
| | | onOpenCouponSelect?: () => void; |
| | | } |
| | | |
| | | export default function CallingCar({ |
| | |
| | | handleCloseAuthBluetoothPopup, |
| | | handleCloseSuccessAuthPopup, |
| | | handleAuthorizeBluetooth, |
| | | pageDidShowVersion = 0 |
| | | pageDidShowVersion = 0, |
| | | onOpenCouponSelect |
| | | }: Props) { |
| | | // 汇总行程中的倒计时与费用数据 |
| | | const { |
| | |
| | | resetDetailVersion={resetDetailVersion} |
| | | onToggleDetailFade={onToggleDetailFade} |
| | | handlePay={handlePay} |
| | | onOpenCouponSelect={onOpenCouponSelect} |
| | | /> |
| | | |
| | | <TripActionBar |
| | |
| | | evaluateCloseVersion={deps.evaluateCloseVersion} |
| | | handleOpenOverRoutePopup={deps.handleOpenOverRoutePopup} |
| | | handlePay={deps.handlePay} |
| | | onOpenCouponSelect={deps.handleOpenCouponSelect} |
| | | handleOpenEvaluatePopup={deps.handleOpenEvaluatePopup} |
| | | estimatedWaitMinutes={deps.fareEstimate?.waitingTime} |
| | | routeDurationSeconds={deps.routeDuration} |
| | |
| | | currentFullRouteRef, |
| | | orderDetailRouteRequestIdRef, |
| | | routePoints, |
| | | startSite, |
| | | endSite: effectiveEndSite, |
| | | longitude, |
| | | latitude, |
| | |
| | | }; |
| | | // 打开优惠券选择弹窗 |
| | | const handleOpenCouponSelect = () => { |
| | | if (tripStatus !== TripStatus.PublishRoute) { |
| | | if (![TripStatus.PublishRoute, TripStatus.TripFinished, TripStatus.PaymentSuccess].includes(tripStatus)) { |
| | | return; |
| | | } |
| | | setShowCouponSelectPopup(true); |
| | |
| | | } |
| | | Taro.setStorageSync('selectedCouponId', selectedCouponId); |
| | | setShowCouponSelectPopup(false); |
| | | if ([TripStatus.TripFinished, TripStatus.PaymentSuccess].includes(tripStatus)) { |
| | | setPriceUpdateVersion(v => v + 1); |
| | | return; |
| | | } |
| | | const cachedStartSite = Taro.getStorageSync('startSite') || {}; |
| | | const originLat = Number(startSite?.latitude ?? cachedStartSite?.latitude); |
| | | const originLng = Number(startSite?.longitude ?? cachedStartSite?.longitude); |