hejianhao
2026-03-16 f4d4222ad84a6f159d3995085cd1607c6ddc68c3
fix: 修复订单金额显示异常、地图标记更新及费用格式化问题

- 修复费用计算中可能出现的负数金额,确保显示非负值
- 优化乘客须知页面的列表样式,确保在移动端正确显示
- 修复行程状态6时地图标记的更新逻辑,避免在特定条件下重复刷新
- 在费用详情页面使用统一的距离和时长格式化函数
- 简化订单详情页面的地图包含点计算逻辑,移除冗余代码
- 修复订单金额显示格式,确保金额始终显示两位小数
- 移除乘客须知组件中未使用的CSS样式属性
6个文件已修改
118 ■■■■■ 已修改文件
src/robotaxi/pages/begin-route/components/calling-car.tsx 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/css-folder/passenger-notice.less 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/passenger-notice.tsx 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/expense-detail/index.tsx 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/order/detail/index.tsx 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/calling-car.tsx
@@ -609,7 +609,9 @@
                            <View className="car-card-line" style="margin:24px 0;"></View>
                            <View className="car-card-end-particulars">
                                <View className="car-card-end-particulars-money">
                                    <View>{formatMoney(fareBreakdown?.orderMoney - fareBreakdown?.redPacketMoney - fareBreakdown?.couponMoney)}</View>
                                    <View>{formatMoney(
                                        (fareBreakdown?.orderMoney - fareBreakdown?.redPacketMoney - fareBreakdown?.couponMoney) < 0
                                            ? 0 : (fareBreakdown?.orderMoney - fareBreakdown?.redPacketMoney - fareBreakdown?.couponMoney))}</View>
                                    <View>元</View>
                                    <View>{formatMoney(fareBreakdown?.orderMoney)}元</View>
                                    {
src/robotaxi/pages/begin-route/components/css-folder/passenger-notice.less
@@ -35,8 +35,6 @@
        &-desc {
            margin-top: 34px;
            font-size: 28px;
            line-height: 48px;
            letter-spacing: normal;
            color: rgba(0, 0, 0, 0.9);
            height: 342px;
src/robotaxi/pages/begin-route/components/passenger-notice.tsx
@@ -44,8 +44,12 @@
        }
        getPrivacyContent(5).then((res: any) => {
            if (res.content) {
                res.content = res.content.replace(/<img/gi,
                    '<img style="max-width:100%;height:auto;margin:0 auto;display:block"')
                res.content = res.content
                    .replace(/<img/gi, '<img style="max-width:100%;height:auto;margin:0 auto;display:block"')
                    .replace(/<ol([^>]*)style="([^"]*)"/gi, '<ol$1style="$2;list-style-position:inside;padding-left:30px;margin:0;box-sizing:border-box"')
                    .replace(/<ol(?![^>]*style=)/gi, '<ol style="list-style-position:inside;padding-left:30px;margin:0;box-sizing:border-box"')
                    .replace(/<ul([^>]*)style="([^"]*)"/gi, '<ul$1style="$2;list-style-position:inside;padding-left:35px;margin:0;box-sizing:border-box"')
                    .replace(/<ul(?![^>]*style=)/gi, '<ul style="list-style-position:inside;padding-left:35px;margin:0;box-sizing:border-box"')
            }
            setNoticeContent(res.content);
        }).catch(() => { });
src/robotaxi/pages/begin-route/index.tsx
@@ -148,6 +148,7 @@
  const mapRectRef = useRef<any>(null);
  const viewportKeyRef = useRef<string>('');
  const tripStatus6ViewportLockedRef = useRef(false);
  const tripStatus6MarkerRefreshedRef = useRef(false);
  const polylineKeyRef = useRef<string>('');
  const orderDetailRouteRequestIdRef = useRef(0);
  const lastRoutePointRef = useRef<{ latitude: number; longitude: number } | null>(null);
@@ -171,9 +172,11 @@
    if (!wasHold && isHold) {
      orderRouteInitializedRef.current = false;
      tripStatus6ViewportLockedRef.current = false;
      tripStatus6MarkerRefreshedRef.current = false;
    }
    if (!isHold) {
      tripStatus6ViewportLockedRef.current = false;
      tripStatus6MarkerRefreshedRef.current = false;
    }
    lastTripStatusRef.current = tripStatus;
  }, [tripStatus]);
@@ -1049,10 +1052,14 @@
    if (statusRule.showCar && carMarker) nextMarkers.push(carMarker);
    if (statusRule.showDropoff && dropoffMarker) nextMarkers.push(dropoffMarker);
    const hasDropoffMarker = markersRef.current.some((m: any) => m.id === 2);
    const shouldSkipUpdate = tripStatus === 6 && carMarkerInitialized.current && statusRule.showCar && (!statusRule.showDropoff || hasDropoffMarker);
    const shouldHoldMarkerByTranslate = tripStatus === 6 && carMarkerInitialized.current && statusRule.showCar && (!statusRule.showDropoff || hasDropoffMarker);
    const shouldSkipUpdate = shouldHoldMarkerByTranslate && (isAndroid || tripStatus6MarkerRefreshedRef.current);
    if (shouldSkipUpdate) {
    } else {
      setMarkers(nextMarkers);
      if (!isAndroid && tripStatus === 6 && statusRule.showCar && !!carMarker && !tripStatus6MarkerRefreshedRef.current) {
        tripStatus6MarkerRefreshedRef.current = true;
      }
    }
    carMarkerInitialized.current = statusRule.showCar && !!carMarker;
  }, [tripStatus, startSite?.name, startSite?.latitude, startSite?.longitude, endSite.name, endSite?.latitude, endSite?.longitude, vehicleLocation, vehicleDirection]);
src/robotaxi/pages/expense-detail/index.tsx
@@ -3,6 +3,10 @@
import { View, Text, Image, Input } from '@tarojs/components';
import './index.less';
import Subtract from '../../assets/Subtract.png';
import {
  formatTripDistance,
  formatTripDurationFromSeconds
} from '../../../utils/Robotaxi-public-method';
export default function OrderPage() {
  const [pricingCard, setPricingCard] = useState<any>(null);
@@ -45,31 +49,31 @@
      <View className='price-card'>
        <View className='flex-between-card mb-16'>
          <View className='price-label'>订单总额</View>
          <View className='price-value'>{pricingCard.totalPrice}元</View>
          <View className='price-value'>{pricingCard.totalPriceStr}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>起步价</View>
          <View className='price-value'>{pricingCard.startPrice}元</View>
          <View className='price-value'>{pricingCard.startPriceStr}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>{pricingCard.time}({pricingCard.distance}公里,{pricingCard.duration}分钟)</View>
          <View className='price-notice-value'>{pricingCard.startPrice}元</View>
          <View className='price-notice-label'>{pricingCard.time}({formatTripDistance(pricingCard.distance)},{formatTripDurationFromSeconds(pricingCard.duration)})</View>
          <View className='price-notice-value'>{pricingCard.startPriceStr}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>里程费</View>
          <View className='price-value'>{pricingCard.distancePrice}元</View>
          <View className='price-value'>{pricingCard.distancePriceStr}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>普通时段({pricingCard.distancePriceNormal}公里)</View>
          <View className='price-notice-value'>{pricingCard.distancePrice}元</View>
          <View className='price-notice-label'>普通时段({formatTripDistance(pricingCard.distancePriceNormal)})</View>
          <View className='price-notice-value'>{pricingCard.distancePriceStr}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>时长费({pricingCard.durationPriceNormal}分钟)</View>
          <View className='price-value'>{pricingCard.durationPrice}元</View>
          <View className='price-label'>时长费({formatTripDurationFromSeconds(pricingCard.durationPriceNormal)})</View>
          <View className='price-value'>{pricingCard.durationPriceStr}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>普通时段({pricingCard.durationPriceNormal}分钟)</View>
          <View className='price-notice-value'>{pricingCard.durationPrice}元</View>
          <View className='price-notice-label'>普通时段({formatTripDurationFromSeconds(pricingCard.durationPriceNormal)})</View>
          <View className='price-notice-value'>{pricingCard.durationPriceStr}元</View>
        </View>
        {pricingCard.coupon && (
          <View className='flex-between-card'>
@@ -81,7 +85,7 @@
      {/* 总价格 */}
      <View className='flex-card total'>
        <Text className='total-text'>总费用</Text>
        <Text className='num'>{pricingCard.totalPrice}</Text>
        <Text className='num'>{pricingCard.totalPriceStr}</Text>
        <Text className='unit'>元</Text>
      </View>
      {/* 质疑事项 */}
src/robotaxi/pages/order/detail/index.tsx
@@ -29,7 +29,6 @@
  const [latitude, setLatitude] = useState(39.916527) // 地图中心点纬度
  const [markers, setMarkers] = useState<any[]>([]) // 起点和终点标记
  const [polyline, setPolyline] = useState<any[]>([]) // 行驶路径
  const lastIncludeKeyRef = useRef('');
  const getPointsCenter = (points: Array<{ longitude: number; latitude: number }>) => {
    if (!points.length) {
@@ -55,39 +54,6 @@
    if (Math.abs(lon) > 180 || Math.abs(lat) > 90) return null;
    if (lon === 0 && lat === 0) return null;
    return { longitude: lon, latitude: lat };
  };
  const getMarkerPoints = (markerList: any[]) => {
    if (!Array.isArray(markerList) || markerList.length === 0) {
      return [] as Array<{ longitude: number; latitude: number }>;
    }
    return markerList
      .map((item) => {
        const longitude = Number(item?.longitude);
        const latitude = Number(item?.latitude);
        if (Number.isNaN(longitude) || Number.isNaN(latitude)) return null;
        return { longitude, latitude };
      })
      .filter(Boolean) as Array<{ longitude: number; latitude: number }>;
  };
  const getMarkerPadding = (markerList: any[]) => {
    let top = 80;
    let right = 80;
    let bottom = 80;
    let left = 80;
    markerList.forEach((item) => {
      const width = Number(item?.width) || 22;
      const height = Number(item?.height) || 40;
      const anchorX = typeof item?.anchor?.x === 'number' ? item.anchor.x : 0.5;
      const anchorY = typeof item?.anchor?.y === 'number' ? item.anchor.y : 1;
      const safeGap = 28;
      top = Math.max(top, Math.ceil(height * (1 - anchorY) + safeGap));
      bottom = Math.max(bottom, Math.ceil(height * anchorY + safeGap));
      left = Math.max(left, Math.ceil(width * anchorX + safeGap));
      right = Math.max(right, Math.ceil(width * (1 - anchorX) + safeGap));
    });
    return [top, right, bottom, left] as [number, number, number, number];
  };
  useEffect(() => {
@@ -201,33 +167,12 @@
  useEffect(() => {
    const mapCtx = Taro.createMapContext('trip-map');
    const polylinePoints = polyline?.[0]?.points;
    const markerPoints = getMarkerPoints(markers);
    const markerPadding = getMarkerPadding(markers);
    if (Array.isArray(polylinePoints) && polylinePoints.length > 0) {
      const pointsForViewport = [...polylinePoints, ...markerPoints];
      const includeKey = `${pointsForViewport.length}|${pointsForViewport[0]?.longitude}|${pointsForViewport[0]?.latitude}|${pointsForViewport[pointsForViewport.length - 1]?.longitude}|${pointsForViewport[pointsForViewport.length - 1]?.latitude}|${markerPadding.join(',')}`;
      if (includeKey === lastIncludeKeyRef.current) return;
      lastIncludeKeyRef.current = includeKey;
      Taro.nextTick(() => {
        mapCtx.includePoints({
          points: pointsForViewport,
          padding: markerPadding
        });
    Taro.nextTick(() => {
      mapCtx.includePoints({
        points: polyline,
        padding: [80, 80, 80, 80]
      });
      return;
    }
    if (markerPoints.length > 0) {
      const includeKey = `${markerPoints.length}|${markerPoints[0]?.longitude}|${markerPoints[0]?.latitude}|${markerPoints[markerPoints.length - 1]?.longitude}|${markerPoints[markerPoints.length - 1]?.latitude}|${markerPadding.join(',')}`;
      if (includeKey === lastIncludeKeyRef.current) return;
      lastIncludeKeyRef.current = includeKey;
      Taro.nextTick(() => {
        mapCtx.includePoints({
          points: markerPoints,
          padding: markerPadding
        });
      });
    }
    });
  }, [polyline, markers])
  const todescription = () => {
@@ -324,7 +269,7 @@
          orderData.status != 0 &&
          <View className='trip-top'>
            <View className='price-card'>
              <Text className='price'>{orderData.payMoney || '0'}元</Text>
              <Text className='price'>{orderData.payMoney || '0.00'}元</Text>
              <Text className='unit'>元</Text>
              {orderData.orderMoney > orderData.payMoney && (
                <Text className='old-price'>{orderData.orderMoney || '-'}元</Text>