董国庆
2026-02-13 ae7bee7219f0784bdaa9056de1d628444956d7ff
跑大概流程
5个文件已添加
10个文件已修改
1137 ■■■■■ 已修改文件
config/dev.js 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/app.config.ts 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/robotaxi/home/index.tsx 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/api/coupon.ts 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/api/order.ts 163 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/components/release-route.tsx 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/begin-route/index.tsx 165 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/expense-description/index.tsx 224 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/expense-detail/index.tsx 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/order/detail.txt 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/order/detail/index.tsx 179 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/order/index.tsx 149 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/pricing-rules/index.config.ts 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/pricing-rules/index.less 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/robotaxi/pages/pricing-rules/index.tsx 73 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
config/dev.js
@@ -16,8 +16,11 @@
const CAR_CONTROL_BIZ_HOST = '"https://apps-biz.deploy-test.xiaopeng.com"';
const COMMON_OSS_HOST = '"https://spre.xiaopeng.com"'; // 官渠通用 oss 资源前缀
const ADMIN_OSS_HOST = '"https://pre-xps01.xiaopeng.com"'; // 运营后台上传的额文件的 oss 域名
const ROBOTAXI_HOST = '"http://192.168.110.80:8000"'; // 打车接口域名
const ROBOTAXI_WS_HOST = '"ws://192.168.110.34:8888/websocket"';
// const ROBOTAXI_HOST = '"http://192.168.110.80:8000"'; // 打车接口域名
// const ROBOTAXI_WS_HOST = '"ws://192.168.110.34:8888/websocket"';
const ROBOTAXI_HOST = '"http://221.182.45.100:8000"';
const ROBOTAXI_WS_HOST = '"ws://221.182.45.100:8888/websocket"';
const XP_APPID_MAP = {
  weapp: '"xxxxxxx"', // 用户中心登录appId
src/app.config.ts
@@ -32,6 +32,7 @@
        'pages/expense-detail/index',
        'pages/expense-description/index',
        'pages/passenger-notice/index',
        'pages/pricing-rules/index',
      ],
    }
  ];
src/pages/robotaxi/home/index.tsx
@@ -520,7 +520,7 @@
      Taro.setStorageSync('startSite', currentSite);
    }
    Taro.navigateTo({
      url: `/robotaxi/pages/site-search/index?pageType=${type}&electronicAreaId=${electronicAreaId}&longitude=${longitude}&latitude=${latitude}`
      url: `/robotaxi/pages/site-search/index?pageType=${type}&electronicAreaId=${electronicAreaId}&longitude=${currentSite.longitude}&latitude=${currentSite.latitude}`
    })
  }
@@ -540,12 +540,20 @@
  }
  const toCoupon = () => {
    if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
      setShowPrivacy(true);
      return;
    }
    Taro.navigateTo({
      url: '/robotaxi/pages/coupon/index',
    })
  }
  const toOrder = () => {
    if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
      setShowPrivacy(true);
      return;
    }
    Taro.navigateTo({
      url: '/robotaxi/pages/order/index',
    })
src/robotaxi/api/coupon.ts
@@ -32,7 +32,7 @@
// 优惠券列表
export const getCouponList = async (payload: GetCouponListPayload): Promise<GetCouponListResponse> => {
    const res = await request({
        url: _ROBOTAXI_HOST + '/account/api/v1/coupon/list',
        url: _ROBOTAXI_HOST + '/account/api/v1/mini-program/coupon/list',
        method: 'POST',
        payload
    });
@@ -55,7 +55,7 @@
// 领取优惠券
export const receiveCoupon = async (payload: { couponId: string }) => {
    return request({
        url: _ROBOTAXI_HOST + '/account/api/v1/coupon/receive',
        url: _ROBOTAXI_HOST + '/account/api/v1/mini-program/coupon/receive',
        method: 'POST',
        payload
    });
@@ -64,7 +64,7 @@
// 优惠券详情
export const getCouponDetail = async (couponId: string): Promise<CouponDetail> => {
    const res = await request({
        url: _ROBOTAXI_HOST + `/account/api/v1/coupon/detail/${couponId}`,
        url: _ROBOTAXI_HOST + `/account/api/v1/mini-program/coupon/detail/${couponId}`,
        method: 'POST'
    });
src/robotaxi/api/order.ts
New file
@@ -0,0 +1,163 @@
import request from '../../utils/request';
import { _ROBOTAXI_HOST } from '../../constants/api';
export interface OrderHistoryOrder {
    amount: number;
    destinationAddress: string;
    orderId: string;
    orderTime: string;
    originAddress: string;
    time?: string;
}
export interface OrderHistoryGroup {
    dateLabel: string;
    orders: OrderHistoryOrder[];
}
export interface GetOrderHistoryPayload {
    pageNum: number;
    pageSize: number;
    status: number | string;
}
export interface GetOrderHistoryResponse {
    list: OrderHistoryGroup[];
    total: number;
}
export const getOrderHistoryList = async (payload: GetOrderHistoryPayload): Promise<GetOrderHistoryResponse> => {
    return request({
        url: _ROBOTAXI_HOST + '/order/api/v1/mini-program/order/history/list',
        method: 'POST',
        payload
    });
}
export interface OrderDetail {
    acceptanceTime: string;
    appUserId: number;
    arrivalTime: string;
    boardingAddress: string;
    boardingLat: number;
    boardingLon: number;
    boardingTime: string;
    cityCode: string;
    cityId: number;
    cityName: string;
    couponId: number;
    couponMoney: number;
    createBy: string;
    createTime: string;
    deleted: boolean;
    duration: number;
    durationMoney: number;
    endAddress: string;
    endLat: number;
    endLon: number;
    endPointId: number;
    endPointName: string;
    estimatedTime: string;
    feedbackContent: string;
    feedbackPictures: string;
    feedbackTypeName: string;
    fleetId: number;
    getoffAddress: string;
    getoffLat: number;
    getoffLon: number;
    getoffTime: string;
    id: number;
    longDistance: number;
    longDistancemoney: number;
    mileageKilometers: number;
    mileageMoney: number;
    orderMoney: number;
    orderNumber: string;
    orderRating: number;
    orderSource: number;
    orderTime: number;
    payMoney: number;
    payType: number;
    placementAddress: string;
    placementLat: number;
    placementLon: number;
    placementValue: number;
    plateNumber: string;
    prepayMoney: number;
    redPacketId: number;
    redPacketMoney: number;
    rideTime: string;
    startAddress: string;
    startLat: number;
    startLon: number;
    startMileage: number;
    startMoney: number;
    startPointId: number;
    startPointName: string;
    status: number;
    timeSlot: string;
    totalMileage: number;
    trajectories: any[];
    transactionId: string;
    tripBegin: string;
    tripEnd: string;
    updateBy: string;
    updateTime: string;
    vehicleCode: string;
    vehicleColor: string;
    vehicleId: number;
    vehiclePictures: string;
    wait: number;
    waitMoney: number;
    xpElectronicFenceAreaId: number;
}
export const getOrderDetail = async (orderId: string | number): Promise<OrderDetail> => {
    return request({
        url: _ROBOTAXI_HOST + `/order/api/v1/mini-program/order/orderDetail/${orderId}`,
        method: 'PUT'
    });
}
export interface FareItem {
    duration: number;
    mileage: number;
    money: number;
    time: string;
    type: number; // type=1 普通时段 type=2 夜间行驶时段 3高峰时段 4节假日时段
}
export interface FareBreakdownResponse {
    couponMoney: number;
    duration: FareItem[];
    kilometer: number;
    longDistance: FareItem[];
    mileage: FareItem[];
    orderMoney: number;
    redPacketMoney: number;
    start: FareItem[];
    time: number;
    payMoney?: number; // 实际支付金额,虽然detail.txt没写,但页面展示需要,可能包含在返回中或需计算
}
export const getFareBreakdown = async (orderId: string | number): Promise<FareBreakdownResponse> => {
    return request({
        url: _ROBOTAXI_HOST + `/order/api/v1/mini-program/order/fare-breakdown/${orderId}`,
        method: 'PUT'
    });
}
export interface FAQItem {
    id: number;
    questions: string;
    answer: string;
    createTime: string;
    updateTime: string;
}
export const getFAQList = async (): Promise<FAQItem[]> => {
    return request({
        url: _ROBOTAXI_HOST + '/operation/base/v1/mini-program/frequently-asked-questions/getList',
        method: 'GET'
    });
}
src/robotaxi/pages/begin-route/components/release-route.tsx
@@ -20,6 +20,11 @@
            url: '/robotaxi/pages/site-search/index?type=' + type
        })
    }
    const toPriceDescription = () => {
        Taro.navigateTo({
            url: `/robotaxi/pages/expense-detail/index`,
        })
    }
    return (
        <View className='release-route'>
@@ -51,7 +56,7 @@
                    <View className="route-content-top">
                        <View className="route-content-txt">预估等待{fareEstimate.waitingTime || 0}分钟</View>
                        <View className="route-content-top-money">
                            <Image className="tip-icon" src={tipDefaultIcon} />
                            <Image className="tip-icon" src={tipDefaultIcon}  onClick={() => toPriceDescription()} />
                            预估
                            <Text className="money-num">{fareEstimate.finalFare || 0}</Text>
                            元
src/robotaxi/pages/begin-route/index.tsx
@@ -19,6 +19,10 @@
import suggest from '../../../robotaxi/assets/suggest.png'
import originIcon from '../../../robotaxi/assets/origin-icon.png'
import wsManager from '../../../utils/websocket';
// 2-13修改的备注 start: 引入步行路径方法与箭头资源
import { getWalkingRoute } from '../../../utils/Robotaxi-public-method';
import lineRight from '../../../robotaxi/assets/line-right.png';
// 2-13修改的备注 end
import {
  saveOrder,
  queryRouteAndFare,
@@ -44,6 +48,9 @@
  const [cancelType, setCancelType] = useState(1); // 取消类型
  const [showEvaluatePopup, setShowEvaluatePopup] = useState(false); // 评价弹窗是否显示
  const [routePoints, setRoutePoints] = useState<any[]>([]); // 路线点集合
  // 2-13修改的备注 start: 新增步行路径点
  const [walkingPoints, setWalkingPoints] = useState<any[]>([]);
  // 2-13修改的备注 end
  const [fareEstimate, setFareEstimate] = useState<any>({}); // 预估费用信息
  const [vehicleLocation, setVehicleLocation] = useState<{ latitude: number, longitude: number } | null>(null);
  const [routeDistance, setRouteDistance] = useState<number | null>(null); // 路线距离
@@ -53,7 +60,9 @@
  const tripStatusRef = useRef(tripStatus); // 行程状态引用
  const routeRequestKeyRef = useRef<string>(''); // 路线请求键
  const shouldShowRoute = [4, 5, 6, 8, 9].includes(tripStatus);
  // 2-13修改的备注 start: 在发布行程状态也允许展示路线
  const shouldShowRoute = [1, 4, 5, 6, 8, 9].includes(tripStatus);
  // 2-13修改的备注 end
  const authSuccessBound = useRef(false); // 认证成功是否绑定
  const messageBound = useRef(false); // 消息是否绑定
  const orderStatusBound = useRef(false); // 订单状态是否绑定
@@ -64,6 +73,9 @@
  const orderStatusHandlerRef = useRef<(data: any) => void>(); // 订单状态处理函数
  const orderRouteHandlerRef = useRef<(data: any) => void>(); // 订单路线处理函数
  const vehicleLocationHandlerRef = useRef<(data: any) => void>(); // 车辆位置处理函数
  // 2-13修改的备注 start: 记录已为某订单拉取过车辆信息,避免重复
  const lastFetchedVehicleOrderIdRef = useRef<string | null>(null);
  // 2-13修改的备注 end
  // 应用路线点
  const applyRoutePoints = (points: any[]) => {
@@ -122,9 +134,55 @@
      if (res?.fareEstimate) {
        setFareEstimate(res.fareEstimate);
      }
      if(res?.xpPricingCard){
        Taro.setStorageSync('xpPricingCard', res.xpPricingCard);
      }
      // 2-13修改的备注 start: 解析预估阶段返回的路线并展示
      const route = res?.route;
      const distance = Number(route?.distance);
      const duration = Number(route?.duration);
      const points = (Array.isArray(route?.polyline) ? route?.polyline : []);
      if (!Number.isNaN(distance)) {
        setRouteDistance(distance);
      }
      if (!Number.isNaN(duration)) {
        setRouteDuration(duration);
      }
      if (Array.isArray(points) && points.length > 0) {
        applyRoutePoints(points);
      } else {
        applyRoutePoints([]);
      }
      // 2-13修改的备注 end
    }).catch(() => {
    });
  };
  // 2-13修改的备注 start: 计算“当前位置→上车点”的步行路径
  const updateWalkingRouteForStart = async () => {
    try {
      const loc = await Taro.getLocation({ type: 'gcj02' });
      const originLat = loc.latitude;
      const originLng = loc.longitude;
      const targetLat = startSite?.latitude;
      const targetLng = startSite?.longitude;
      if (!originLat || !originLng || !targetLat || !targetLng) {
        setWalkingPoints([]);
        return;
      }
      const origin = `${originLng},${originLat}`;
      const destination = `${targetLng},${targetLat}`;
      const wPoints = await getWalkingRoute(origin, destination);
      if (Array.isArray(wPoints) && wPoints.length > 0) {
        setWalkingPoints(wPoints);
      } else {
        setWalkingPoints([]);
      }
    } catch (e) {
      setWalkingPoints([]);
    }
  };
  // 2-13修改的备注 end
  // 认证成功处理函数
  useEffect(() => {
@@ -138,10 +196,32 @@
    messageHandlerRef.current = (data) => {
      console.log('ws message:', data);
    };
    // 2-13修改的备注 start: 优化订单状态回调中的车辆信息拉取逻辑
    orderStatusHandlerRef.current = (payload) => {
      const mappedTripStatus = payload?.tripStatus;
      console.log('payload?.tripStatus',payload?.tripStatus)
      if (typeof mappedTripStatus === 'number') {
        setTripStatus(mappedTripStatus);
      }
      // 车辆信息拉取:当收到有效的订单号时,在首次达到呼叫及后续阶段拉取车辆信息
      const incomingOrderId = payload?.content?.orderId || Taro.getStorageSync('orderId');
      const vehicleInfoEmpty =
        !vehicleInfo ||
        (!vehicleInfo.plateNumber && !vehicleInfo.vehicleCode && !vehicleInfo.vehicleColor && !vehicleInfo.vehiclePictures);
      const shouldFetchVehicle =
        !!incomingOrderId &&
        (lastFetchedVehicleOrderIdRef.current !== incomingOrderId) &&
        (vehicleInfoEmpty || orderId !== incomingOrderId);
      if (incomingOrderId && orderId !== incomingOrderId) {
        setOrderId(incomingOrderId);
      }
      if (shouldFetchVehicle) {
        lastFetchedVehicleOrderIdRef.current = incomingOrderId;
        queryVehicleByOrderId({ orderId: incomingOrderId })
          .then((res: any) => {
            setVehicleInfo(res);
          })
          .catch(() => { });
      }
      if (payload?.clearRoute) {
        setRoutePoints([]);
@@ -172,6 +252,7 @@
        }
      }
    };
    // 2-13修改的备注 end
    orderRouteHandlerRef.current = (payload) => {
      const points = payload?.points || [];
      applyRoutePoints(points);
@@ -248,18 +329,35 @@
    applyRoutePoints(storedPoints);
  }, [tripStatus]);
  // 2-13修改的备注 start: 在tripStatus=1时也绘制预估路线与步行路线
  useEffect(() => {
    if (shouldShowRoute && routePoints.length > 0) {
      setPolyline([{
        points: routePoints,
        color: '#6D7FD9',
        width: 10,
        arrowLine: true,
      }]);
    if ((shouldShowRoute) && (routePoints.length > 0 || walkingPoints.length > 0)) {
      const lines: any[] = [];
      if (routePoints.length > 0) {
        lines.push({
          points: routePoints,
          color: '#6D7FD9',
          width: 10,
          arrowLine: true,
        });
      }
      if (walkingPoints.length > 0) {
        lines.push({
          points: walkingPoints,
          color: '#6D7FD9',
          width: 6,
          dottedLine: true,
          arrowLine: true,
          arrowIconPath: lineRight,
          borderColor: '#FFFFFF',
        });
      }
      setPolyline(lines);
    } else {
      setPolyline([]);
    }
  }, [tripStatus, routePoints]);
  }, [tripStatus, routePoints, walkingPoints]);
  // 2-13修改的备注 end
  // 页面初始化
  useDidShow(() => {
@@ -302,6 +400,11 @@
    if (originLng && originLat && e?.longitude && e?.latitude) {
      requestRouteAndFare(originLat, originLng, e.latitude, e.longitude);
    }
    // 2-13修改的备注 start: 初始阶段尝试计算步行路线
    if (tripStatus === 1 && s?.latitude && s?.longitude) {
      updateWalkingRouteForStart();
    }
    // 2-13修改的备注 end
  });
  useEffect(() => {
@@ -310,6 +413,11 @@
    if (originLng && originLat && endSite?.longitude && endSite?.latitude) {
      requestRouteAndFare(originLat, originLng, endSite.latitude, endSite.longitude);
    }
    // 2-13修改的备注 start: 选择或更新上车点后重新计算步行路线
    if (tripStatus === 1 && startSite?.latitude && startSite?.longitude) {
      updateWalkingRouteForStart();
    }
    // 2-13修改的备注 end
  }, [startSite?.longitude, startSite?.latitude, endSite?.longitude, endSite?.latitude, longitude, latitude]);
  // 生成标记点
@@ -370,22 +478,21 @@
    setMarkers(nextMarkers);
  }, [tripStatus, startSite?.name, startSite?.latitude, startSite?.longitude, endSite.name, endSite?.latitude, endSite?.longitude, vehicleLocation])
  // 2-13修改的备注 start: 调整视图以包含所有路线点(含步行)
  useEffect(() => {
    if (shouldShowRoute && routePoints.length > 0) {
    if (shouldShowRoute && (routePoints.length > 0 || walkingPoints.length > 0)) {
      const mapCtx = Taro.createMapContext('map');
      if ([8, 9].includes(tripStatus)) {
        mapCtx.includePoints({
          points: routePoints,
          padding: [50, 50, 500, 50]
        })
      } else {
        mapCtx.moveToLocation({
          longitude: routePoints[0].longitude,
          latitude: routePoints[0].latitude
        })
      }
      const allPoints = [
        ...routePoints,
        ...walkingPoints,
      ];
      mapCtx.includePoints({
        points: allPoints,
        padding: [50, 50, 500, 50]
      });
    }
  }, [tripStatus, routePoints])
  }, [tripStatus, routePoints, walkingPoints]);
  // 2-13修改的备注 end
  const formatTime = (sec: number) => {
    const m = Math.floor(sec / 60);
@@ -572,12 +679,26 @@
  }
  const toCoupon = () => {
    if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
      Taro.showToast({
        title: '请先同意协议',
        icon: 'none'
      });
      return;
    }
    Taro.navigateTo({
      url: '/robotaxi/pages/coupon/index',
    })
  }
  const toOrder = () => {
    if (Taro.getStorageSync('has_show_privicy_Robotaxi') !== 'true') {
      Taro.showToast({
        title: '请先同意协议',
        icon: 'none'
      });
      return;
    }
    Taro.navigateTo({
      url: '/robotaxi/pages/order/index',
    })
src/robotaxi/pages/expense-description/index.tsx
@@ -1,52 +1,46 @@
import Taro from '@tarojs/taro';
import { Component, useState, useEffect } from 'react';
import { View, Text, Image, Input } from '@tarojs/components';
import Taro, { useRouter } from '@tarojs/taro';
import { useState, useEffect } from 'react';
import { View, Text, Image } from '@tarojs/components';
import { getFareBreakdown, FareBreakdownResponse, getFAQList, FAQItem } from '../../api/order';
import EvaluatePopup from '../begin-route/components/evaluate-popup';
import './index.less';
import Subtract from '../../assets/Subtract.png';
import more from '../../assets/more.png';
// FAQ数据
const faqData = [
  {
    id: 1,
    question: '为什么我的优惠券用不了?',
    answer: '惊喜特价不可叠加使用优惠券'
  },
  {
    id: 2,
    question: '如何申请发票?',
    answer: '您可以在订单详情页面点击"申请发票"按钮,填写相关信息后提交申请'
  },
  {
    id: 3,
    question: '取消订单会扣费吗?',
    answer: '根据取消时间不同,可能会产生不同的取消费用,具体请查看取消规则'
  },
  {
    id: 4,
    question: '如何联系客服?',
    answer: '您可以在APP首页点击"客服"按钮,或拨打客服热线400-xxx-xxxx'
  },
  {
    id: 5,
    question: '支付失败怎么办?',
    answer: '请检查您的支付方式是否正常,或尝试更换其他支付方式'
  },
  {
    id: 6,
    question: '行程中可以修改目的地吗?',
    answer: '可以的,您可以在行程中联系客服或在APP中修改目的地'
  },
  {
    id: 7,
    question: '如何评价订单?',
    answer: '订单完成后,您可以在订单详情页面进行评价'
  }
];
export default function OrderPage() {
  const router = useRouter();
  const { orderId } = router.params;
  const [showAllFaq, setShowAllFaq] = useState(false); // 是否显示全部FAQ
  const [expandedItems, setExpandedItems] = useState<number[]>([]); // 展开的FAQ项ID列表
  const [fareData, setFareData] = useState<FareBreakdownResponse | null>(null);
  const [faqData, setFaqData] = useState<FAQItem[]>([]);
  const [showEvaluatePopup, setShowEvaluatePopup] = useState(false);
  useEffect(() => {
    if (orderId) {
      fetchData(orderId);
    }
    fetchFAQ();
  }, [orderId]);
  const fetchData = async (id: string) => {
    try {
      const res = await getFareBreakdown(id);
      setFareData(res);
    } catch (error) {
      console.error('获取费用明细失败', error);
      Taro.showToast({ title: '获取费用明细失败', icon: 'none' });
    }
  };
  const fetchFAQ = async () => {
    try {
      const res = await getFAQList();
      setFaqData(res || []);
    } catch (error) {
      console.error('获取常见问题失败', error);
    }
  };
  // 切换FAQ项的展开/收起状态
  const toggleFaqItem = (id: number) => {
@@ -65,13 +59,34 @@
  // 根据showAllFaq状态决定显示的FAQ数量
  const displayedFaq = showAllFaq ? faqData : faqData.slice(0, 5);
  const getTimeLabel = (type: number) => {
    const labels = {
      1: '普通时段',
      2: '夜间行驶时段',
      3: '高峰时段',
      4: '节假日时段'
    };
    return labels[type] || '其他时段';
  };
  const sumMoney = (items: any[]) => {
    if (!Array.isArray(items)) return '0.00';
    return items.reduce((sum, item) => sum + (item.money || 0), 0).toFixed(2);
  };
  const formatMoney = (amount: number | undefined) => {
    return (amount || 0).toFixed(2);
  };
  if (!fareData) return null;
  return (
    <View className='expense-detail-page'>
      {/* 账单信息 */}
      <View className='order-info'>
        <View className='flex-between-card'>
          <View className='title'>账单信息</View>
          <View className='look-rule'>
          <View className='look-rule' onClick={() => Taro.navigateTo({ url: '/robotaxi/pages/expense-rule/index' })}>
            <Text className='look-rule-txt'>查看计价规则</Text>
            <Image className='arrow-icon' src={Subtract}></Image>
          </View>
@@ -79,81 +94,110 @@
        <View className='price-card'>
          <View className='flex-between-card mb-16'>
            <View className='price-label'>订单总额</View>
            <View className='price-value'>36.6元</View>
            <View className='price-value'>{formatMoney(fareData.orderMoney)}元</View>
          </View>
          {/* 起步费 */}
          <View className='flex-between-card'>
            <View className='price-label'>起步价</View>
            <View className='price-value'>12.5元</View>
            <View className='price-value'>{sumMoney(fareData.start)}元</View>
          </View>
          <View className='flex-between-card mb-16'>
            <View className='price-notice-label'>17:00-19:00(3.2公里,12.0分钟)</View>
            <View className='price-notice-value'>12.5元</View>
          </View>
          {fareData.start?.map((item, index) => (
            <View className='flex-between-card mb-16' key={index}>
              <View className='price-notice-label'>
                {item.startTime}-{item.endTime}({item.distance}公里,{item.duration}分钟)
              </View>
              <View className='price-notice-value'>{formatMoney(item.money)}元</View>
            </View>
          ))}
          {/* 里程费 */}
          <View className='flex-between-card'>
            <View className='price-label'>里程费</View>
            <View className='price-value'>8.6元</View>
            <View className='price-value'>{sumMoney(fareData.mileage)}元</View>
          </View>
          <View className='flex-between-card mb-16'>
            <View className='price-notice-label'>普通时段(7.2公里)</View>
            <View className='price-notice-value'>8.6元</View>
          </View>
          {fareData.mileage?.map((item, index) => (
            <View className='flex-between-card mb-16' key={index}>
              <View className='price-notice-label'>{getTimeLabel(item.type)}({item.distance}公里)</View>
              <View className='price-notice-value'>{formatMoney(item.money)}元</View>
            </View>
          ))}
          {/* 时长费 */}
          <View className='flex-between-card'>
            <View className='price-label'>时长费(20分钟)</View>
            <View className='price-value'>8.6元</View>
            <View className='price-label'>时长费</View>
            <View className='price-value'>{sumMoney(fareData.duration)}元</View>
          </View>
          <View className='flex-between-card mb-16'>
            <View className='price-notice-label'>普通时段(20分钟)</View>
            <View className='price-notice-value'>4.0元</View>
          </View>
          {fareData.duration?.map((item, index) => (
            <View className='flex-between-card mb-16' key={index}>
              <View className='price-notice-label'>{getTimeLabel(item.type)}({item.duration}分钟)</View>
              <View className='price-notice-value'>{formatMoney(item.money)}元</View>
            </View>
          ))}
          {/* 优惠券 */}
          <View className='flex-between-card'>
            <View className='price-label'>优惠券</View>
            <View className='price-value color-red'>-2.3元</View>
            <View className='price-value color-red'>-{formatMoney(fareData.couponMoney)}元</View>
          </View>
        </View>
        {/* 总价格 */}
        <View className='flex-card total'>
          <Text className='total-text'>总费用</Text>
          <Text className='num'>34.0</Text>
          <Text className='num'>{formatMoney(fareData.payMoney)}</Text>
          <Text className='unit'>元</Text>
        </View>
      </View>
      {/* 常见问题 */}
      <View className='faq'>
        <View className='title'>常见问题</View>
        {displayedFaq.map((item) => (
          <View className='faq-item' key={item.id}>
            <View className='question' onClick={() => toggleFaqItem(item.id)}>
              <Text className='question-text'>{item.question}</Text>
      {/* 常见问题 */}
      {faqData.length > 0 && (
        <View className='faq'>
          <View className='title'>常见问题</View>
          {displayedFaq.map((item) => (
            <View className='faq-item' key={item.id}>
              <View className='question' onClick={() => toggleFaqItem(item.id)}>
                <Text className='question-text'>{item.questions}</Text>
                <Image
                  className={`arrow-icon ${expandedItems.includes(item.id) ? 'rotated' : ''}`}
                  src={more}
                ></Image>
              </View>
              {expandedItems.includes(item.id) && (
                <View className='answer'>{item.answer}</View>
              )}
            </View>
          ))}
          {/* 展开更多/收起 */}
          {faqData.length > 5 && (
            <View className='expand-more' onClick={toggleShowAll}>
              <Text className='expand-more-text'>{showAllFaq ? '收起' : '展开更多'}</Text>
              <Image
                className={`arrow-icon ${expandedItems.includes(item.id) ? 'rotated' : ''}`}
                className={`arrow-icon ${showAllFaq ? 'rotated' : ''}`}
                src={more}
              ></Image>
            </View>
            {expandedItems.includes(item.id) && (
              <View className='answer'>{item.answer}</View>
            )}
          </View>
        ))}
        {/* 展开更多/收起 */}
        {faqData.length > 5 && (
          <View className='expand-more' onClick={toggleShowAll}>
            <Text className='expand-more-text'>{showAllFaq ? '收起' : '展开更多'}</Text>
            <Image
              className={`arrow-icon ${showAllFaq ? 'rotated' : ''}`}
              src={more}
            ></Image>
          </View>
        )}
      </View>
          )}
        </View>
      )}
      {/* 去投诉 */}
      <View className='complaint'>
      <View className='complaint' onClick={() => setShowEvaluatePopup(true)}>
        <Text className='complaint-text'>不认可车费,去投诉</Text>
      </View>
      {/* 评价弹窗 */}
      <EvaluatePopup
        show={showEvaluatePopup}
        orderId={orderId}
        orderRating={1}
        onClose={() => setShowEvaluatePopup(false)}
        onConfirm={() => {
          setShowEvaluatePopup(false);
          Taro.showToast({ title: '投诉已提交', icon: 'success' });
        }}
      />
    </View>
  )
}
src/robotaxi/pages/expense-detail/index.tsx
@@ -5,60 +5,77 @@
import Subtract from '../../assets/Subtract.png';
export default function OrderPage() {
  const [pricingCard, setPricingCard] = useState<any>(null);
  const [startSite, setStartSite] = useState<any>(null);
  const [endSite, setEndSite] = useState<any>(null);
  useEffect(() => {
    const card = Taro.getStorageSync('xpPricingCard');
    const start = Taro.getStorageSync('startSite');
    const end = Taro.getStorageSync('endSite');
    if (card) setPricingCard(card);
    if (start) setStartSite(start);
    if (end) setEndSite(end);
  }, []);
  if (!pricingCard) return null;
  return (
    <View className='expense-detail-page'>
      <View className='car-code'>粤PXV7029</View>
      {/* <View className='car-code'>粤PXV7029</View> */}
      <View className='relative'>
        <View className='flex-card start'>
          <View className='start-icon'></View>
          <View className='start-address'>广州岭南职业技术学院-南1门(公交站)</View>
          <View className='start-address'>{startSite?.name || '未知起点'}</View>
        </View>
        <View className='line'></View>
        <View className='flex-card'>
          <View className='end-icon'></View>
          <View className='start-address'>小鹏科技园2号楼</View>
          <View className='start-address'>{endSite?.name || '未知终点'}</View>
        </View>
      </View>
      {/* 订单价格 */}
      <View className='price-card'>
        <View className='flex-between-card mb-16'>
          <View className='price-label'>订单总额</View>
          <View className='price-value'>36.6元</View>
          <View className='price-value'>{pricingCard.totalPrice}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>起步价</View>
          <View className='price-value'>12.5元</View>
          <View className='price-value'>{pricingCard.startPrice}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>17:00-19:00(3.2公里,12.0分钟)</View>
          <View className='price-notice-value'>12.5元</View>
          <View className='price-notice-label'>{pricingCard.time}({pricingCard.distance}公里,{pricingCard.duration}分钟)</View>
          <View className='price-notice-value'>{pricingCard.startPrice}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>里程费</View>
          <View className='price-value'>8.6元</View>
          <View className='price-value'>{pricingCard.distancePrice}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>普通时段(7.2公里)</View>
          <View className='price-notice-value'>8.6元</View>
          <View className='price-notice-label'>普通时段({pricingCard.distancePriceNormal}公里)</View>
          <View className='price-notice-value'>{pricingCard.distancePrice}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>时长费(20分钟)</View>
          <View className='price-value'>8.6元</View>
          <View className='price-label'>时长费({pricingCard.durationPriceNormal}分钟)</View>
          <View className='price-value'>{pricingCard.durationPrice}元</View>
        </View>
        <View className='flex-between-card mb-16'>
          <View className='price-notice-label'>普通时段(20分钟)</View>
          <View className='price-notice-value'>4.0元</View>
          <View className='price-notice-label'>普通时段({pricingCard.durationPriceNormal}分钟)</View>
          <View className='price-notice-value'>{pricingCard.durationPrice}元</View>
        </View>
        <View className='flex-between-card'>
          <View className='price-label'>优惠券</View>
          <View className='price-value color-red'>-2.3元</View>
        </View>
        {pricingCard.coupon && (
          <View className='flex-between-card'>
            <View className='price-label'>优惠券</View>
            <View className='price-value color-red'>-{pricingCard.coupon}元</View>
          </View>
        )}
      </View>
      {/* 总价格 */}
      <View className='flex-card total'>
        <Text className='total-text'>总费用</Text>
        <Text className='num'>34.0</Text>
        <Text className='num'>{pricingCard.totalPrice}</Text>
        <Text className='unit'>元</Text>
      </View>
      {/* 质疑事项 */}
src/robotaxi/pages/order/detail.txt
New file
@@ -0,0 +1,16 @@
{
  "code": 0,
  "data": [
    {
      "answer": "string", answer
      "createBy": "string",
      "createTime": "2026-02-13T10:10:04.780Z",
      "deleted": true,
      "id": 0,
      "questions": "string", questions
      "updateBy": "string",
      "updateTime": "2026-02-13T10:10:04.780Z"
    }
  ],
  "msg": "string"
}
src/robotaxi/pages/order/detail/index.tsx
@@ -1,5 +1,5 @@
import Taro from '@tarojs/taro';
import { Component, useState, useEffect } from 'react';
import Taro, { useRouter } from '@tarojs/taro';
import { useState, useEffect } from 'react';
import { View, Text, Image, Map } from '@tarojs/components';
import './index.less';
import good from '../../../assets/good.png'
@@ -13,8 +13,7 @@
import up from '../../../assets/up.png'
import down from '../../../assets/down.png'
import lineRight from '../../../assets/line-right.png'
import { AMAP_KEY } from '../../../constants/api';
import amapFile from '../../../libs/amap-wx.130'
import { getOrderDetail, OrderDetail } from '../../../api/order';
// Marker样式配置
const MARKER_CONFIG = {
@@ -22,39 +21,14 @@
  height: 36,       // marker高度(包含底部小圆点)
  anchorX: 0.55,     // 锚点X(0.5表示居中)
  anchorY: 0.8,       // 锚点Y(1表示底部对齐坐标点)
  // 起点样式
  start: {
    bgColor: '#5B8CFF',      // 蓝色背景
    textColor: '#FFFFFF',     // 白色文字
    text: '下',               // 显示文字
    dotColor: '#3D6FE6'       // 底部小圆点颜色
  },
  // 终点样式
  end: {
    bgColor: '#7FD15C',       // 绿色背景
    textColor: '#FFFFFF',     // 白色文字
    text: '下',               // 显示文字
    dotColor: '#5FB83D'       // 底部小圆点颜色
  }
}
export default function orderDetailPage() {
  const [activeIndex, setActiveIndex] = useState(3) // 默认选中"非常满意"
  const router = useRouter();
  const { orderId } = router.params;
  // 虚拟订单数据
  const mockOrderData = {
    carNumber: '粤B·XP8888',
    carColor: '白色',
    carCode: '07',
    price: '28.5',
    oldPrice: '35.0',
    distance: '5.2',
    duration: '18',
    startAddress: '天府广场地铁站A口',
    endAddress: '成都东站',
    startPoint: { longitude: 104.065735, latitude: 30.659462 }, // 成都天府广场
    endPoint: { longitude: 104.141728, latitude: 30.641982 } // 成都东站
  }
  const [activeIndex, setActiveIndex] = useState(3) // 默认选中"非常满意"
  const [orderData, setOrderData] = useState<OrderDetail | null>(null);
  // 地图相关状态
  const [longitude, setLongitude] = useState(104.103731) // 地图中心点经度
@@ -63,68 +37,75 @@
  const [polyline, setPolyline] = useState<any[]>([]) // 行驶路径
  useEffect(() => {
    const { startPoint, endPoint, startAddress, endAddress } = mockOrderData
    if (orderId) {
      fetchOrderDetail(orderId);
    }
  }, [orderId]);
  const fetchOrderDetail = async (id: string) => {
    try {
      const res = await getOrderDetail(id);
      setOrderData(res);
      initMap(res);
      if (res.orderRating) {
        setActiveIndex(res.orderRating);
      }
    } catch (error) {
      console.error('获取订单详情失败', error);
      Taro.showToast({ title: '获取详情失败', icon: 'none' });
    }
  };
  const initMap = (data: OrderDetail) => {
    const { startLat, startLon, endLat, endLon, trajectories } = data;
    // 设置地图中心点(起点和终点的中间位置)
    const centerLng = (startPoint.longitude + endPoint.longitude) / 2
    const centerLat = (startPoint.latitude + endPoint.latitude) / 2
    setLongitude(centerLng)
    setLatitude(centerLat)
    const centerLng = (startLon + endLon) / 2;
    const centerLat = (startLat + endLat) / 2;
    setLongitude(centerLng);
    setLatitude(centerLat);
    // 异步创建自定义marker图标
    const initMarkers = async () => {
      const startIcon = up
      const endIcon = down
    // 设置起点和终点标记
    const markerList = [
      {
        id: 1,
        longitude: startLon,
        latitude: startLat,
        width: MARKER_CONFIG.width,
        height: MARKER_CONFIG.height,
        iconPath: 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/51e7cb75-72af-4994-9d6e-d999efb2fbc7.png',
        anchor: { x: MARKER_CONFIG.anchorX, y: MARKER_CONFIG.anchorY },
      },
      {
        id: 2,
        longitude: endLon,
        latitude: endLat,
        width: MARKER_CONFIG.width,
        height: MARKER_CONFIG.height,
        iconPath: 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/6a56b1eb-ec37-4839-8733-262942af070d.png',
        anchor: { x: MARKER_CONFIG.anchorX, y: MARKER_CONFIG.anchorY }
      }
    ];
    setMarkers(markerList);
      // 设置起点和终点标记
      const markerList = [
        {
          id: 1,
          longitude: startPoint.longitude,
          latitude: startPoint.latitude,
          width: MARKER_CONFIG.width,
          height: MARKER_CONFIG.height,
          iconPath: 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/51e7cb75-72af-4994-9d6e-d999efb2fbc7.png',
          anchor: { x: MARKER_CONFIG.anchorX, y: MARKER_CONFIG.anchorY },
        },
        {
          id: 2,
          longitude: endPoint.longitude,
          latitude: endPoint.latitude,
          width: MARKER_CONFIG.width,
          height: MARKER_CONFIG.height,
          iconPath: 'https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/6a56b1eb-ec37-4839-8733-262942af070d.png',
          anchor: { x: MARKER_CONFIG.anchorX, y: MARKER_CONFIG.anchorY }
        }
      ]
      setMarkers(markerList)
    }
    initMarkers()
    // 模拟真实的行驶路径(模拟从天府广场到成都东站的路线)
    const routePath = [
      { longitude: 104.065735, latitude: 30.659462 }, // 起点:天府广场
      { longitude: 104.073856, latitude: 30.657891 }, // 途经点1
      { longitude: 104.082145, latitude: 30.655234 }, // 途经点2
      { longitude: 104.095678, latitude: 30.651456 }, // 途经点3
      { longitude: 104.108234, latitude: 30.648123 }, // 途经点4
      { longitude: 104.121567, latitude: 30.645789 }, // 途经点5
      { longitude: 104.132890, latitude: 30.643456 }, // 途经点6
      { longitude: 104.141728, latitude: 30.641982 }  // 终点:成都东站
    ]
    // 处理行驶路径
    const routePath = trajectories?.length > 0
      ? trajectories.map(item => ({ longitude: item.longitude || item.lon, latitude: item.latitude || item.lat }))
      : [
          { longitude: startLon, latitude: startLat },
          { longitude: endLon, latitude: endLat }
        ];
    const polylineData = [{
      points: routePath,
      color: '#6D7FD9',
      width: 10,
      arrowLine: true, // 显示箭头
      arrowLine: true,
      arrowIconPath: lineRight,
      borderColor: '#FFFFFF',
      // borderWidth: 2
    }]
    setPolyline(polylineData)
  }, [])
    }];
    setPolyline(polylineData);
  };
  useEffect(() => {
    if (!polyline.length || !polyline[0]?.points?.length) return;
@@ -137,9 +118,11 @@
  const todescription = () => {
    Taro.navigateTo({
      url: '/robotaxi/pages/expense-description/index',
      url: `/robotaxi/pages/expense-description/index?orderId=${orderId}`,
    })
  }
  if (!orderData) return null;
  return (
    <View className='order-detail-page'>
@@ -147,28 +130,28 @@
      <View className='car-info'>
        <View className='info-top'>
          <View>
            <View className='car-name'>{mockOrderData.carNumber}</View>
            <View className='car-name'>{orderData.plateNumber}</View>
            <View className='info'>
              <Text className='car-color'>{mockOrderData.carColor}</Text>
              <Text className='car-color'>{orderData.vehicleColor}</Text>
              <Text className='info-line'></Text>
              <Text className='car-code'>车身编码: </Text>
              <Text className='code'>{mockOrderData.carCode}</Text>
              <Text className='code'>{orderData.vehicleCode}</Text>
            </View>
          </View>
          <Image src={car} className='car-img' />
          <Image src={orderData.vehiclePictures || car} className='car-img' />
        </View>
        <View className='evaluate-card'>
          <View className='card-title'>您对本次行程满意吗?</View>
          <View className='card-content'>
            <View className={`evaluate-item ${activeIndex == 1 ? 'active' : ''}`} onClick={() => { setActiveIndex(1) }}>
            <View className={`evaluate-item ${activeIndex == 1 ? 'active' : ''}`}>
              <Image src={activeIndex == 1 ? activeBad : bad} className='evaluate-img' />
              <Text className={`evaluate-text ${activeIndex == 1 ? 'active-text' : ''}`}>非常不满意</Text>
            </View>
            <View className={`evaluate-item ${activeIndex == 2 ? 'active' : ''}`} onClick={() => { setActiveIndex(2) }}>
            <View className={`evaluate-item ${activeIndex == 2 ? 'active' : ''}`}>
              <Image src={activeIndex == 2 ? activeNormal : normal} className='evaluate-img' />
              <Text className={`evaluate-text ${activeIndex == 2 ? 'active-text' : ''}`}>一般般</Text>
            </View>
            <View className={`evaluate-item ${activeIndex == 3 ? 'active' : ''}`} onClick={() => { setActiveIndex(3) }}>
            <View className={`evaluate-item ${activeIndex == 3 ? 'active' : ''}`}>
              <Image src={activeIndex == 3 ? activeGood : good} className='evaluate-img' />
              <Text className={`evaluate-text ${activeIndex == 3 ? 'active-text' : ''}`}>非常满意</Text>
            </View>
@@ -179,9 +162,11 @@
      <View className='trip-info'>
        <View className='trip-top'>
          <View className='price-card'>
            <Text className='price'>{mockOrderData.price}</Text>
            <Text className='price'>{orderData.payMoney || 0}</Text>
            <Text className='unit'>元</Text>
            <Text className='old-price'>{mockOrderData.oldPrice}元</Text>
            {orderData.orderMoney > orderData.payMoney && (
              <Text className='old-price'>{orderData.orderMoney || 0}元</Text>
            )}
          </View>
          <View onClick={todescription} className='price-remark'>
            <Text className='remark-text'>费用说明</Text>
@@ -203,14 +188,14 @@
        </View>
        {/* 行程信息 */}
        <View className='trip-line'>
          <View className='line-name'>全程{mockOrderData.distance}公里|{mockOrderData.duration}分钟</View>
          <View className='line-name'>全程{orderData.totalMileage || 0}公里|{orderData.orderTime || 0}分钟</View>
          <View className='line-address'>
            <View className='line-icon first-icon'></View>
            <Text className='line-text'>{mockOrderData.startAddress}</Text>
            <Text className='line-text'>{orderData.startAddress}</Text>
          </View>
          <View className='line-address'>
            <View className='line-icon'></View>
            <Text className='line-text'>{mockOrderData.endAddress}</Text>
            <Text className='line-text'>{orderData.endAddress}</Text>
          </View>
        </View>
      </View>
src/robotaxi/pages/order/index.tsx
@@ -1,111 +1,84 @@
import Taro from '@tarojs/taro';
import Taro, { useReachBottom } from '@tarojs/taro';
import { Component, useState, useEffect } from 'react';
import { View, Text, Image, Input } from '@tarojs/components';
import './index.less';
import { getOrderHistoryList, OrderHistoryGroup, OrderHistoryOrder } from '../../../robotaxi/api/order';
export default function OrderPage() {
  const [orderList, setOrderList] = useState([
    {
      id: '1',
      time: '2026年02月03日 14:30',
      start: '深圳湾科技生态园',
      end: "南山区科技园地铁站"
    },
    {
      id: '2',
      time: '2026年02月02日 09:15',
      start: '腾讯滨海大厦',
      end: "深圳北站"
    },
    {
      id: '3',
      time: '2026年02月01日 18:45',
      start: '华强北商业街',
      end: "福田口岸"
    },
    {
      id: '4',
      time: '2026年01月31日 16:20',
      start: '宝安国际机场T3航站楼',
      end: "前海自贸区管理局"
    },
    {
      id: '5',
      time: '2026年01月30日 11:00',
      start: '深圳市民中心',
      end: "欢乐海岸购物中心"
    },
    {
      id: '6',
      time: '2026年01月29日 20:30',
      start: '世界之窗',
      end: "南山文体中心"
    },
    {
      id: '7',
      time: '2026年01月28日 08:45',
      start: '龙华富士康科技园',
      end: "坂田华为基地"
    },
    {
      id: '8',
      time: '2026年01月27日 13:15',
      start: '罗湖口岸',
      end: "东门老街"
    },
    {
      id: '9',
      time: '2026年01月26日 17:50',
      start: '蛇口邮轮中心',
      end: "海上世界文化艺术中心"
    },
    {
      id: '10',
      time: '2026年01月25日 10:30',
      start: '龙岗大运中心',
      end: "坪山高铁站"
    },
    {
      id: '11',
      time: '2026年01月24日 15:20',
      start: '科技楼2号',
      end: "科技楼2号"
    },
    {
      id: '12',
      time: '2026年01月23日 19:00',
      start: '福田CBD金融中心',
      end: "车公庙地铁站"
  const [groups, setGroups] = useState<OrderHistoryGroup[]>([])
  const [pageNum, setPageNum] = useState(1)
  const [hasMore, setHasMore] = useState(true)
  const pageSize = 10
  const formatTime = (t?: string, fallback?: string) => {
    if (!t) return fallback || '-';
    const d = new Date(t);
    const y = d.getFullYear();
    const m = String(d.getMonth() + 1).padStart(2, '0');
    const day = String(d.getDate()).padStart(2, '0');
    const hh = String(d.getHours()).padStart(2, '0');
    const mm = String(d.getMinutes()).padStart(2, '0');
    return `${y}年${m}月${day}日 ${hh}:${mm}`;
  }
  const getList = async (page: number, isRefresh = false) => {
    try {
      const res = await getOrderHistoryList({ pageNum: page, pageSize, status: 9 });
      const newList = (res && (res as any).list) || [];
      if (isRefresh) {
        setGroups(newList);
      } else {
        setGroups(prev => [...prev, ...newList]);
      }
      const count = newList.reduce((acc, g) => acc + (g.orders?.length || 0), 0);
      setHasMore(count >= pageSize);
    } catch (e) {
      if (isRefresh) setGroups([]);
    }
  ])
  }
  useEffect(() => {
    setPageNum(1);
    setHasMore(true);
    getList(1, true);
  }, [])
  const toOrderDetail = (item) => {
    Taro.navigateTo({
      url: '/robotaxi/pages/order/detail/index'
      url: `/robotaxi/pages/order/detail/index?orderId=${item.orderId || ''}`
    })
  }
  const againOrder = () => {
  const againOrder = (item?: OrderHistoryOrder) => {
    Taro.navigateTo({
      url: '/pages/robotaxi/home/index'
    })
  }
  useReachBottom(() => {
    if (hasMore) {
      const nextPage = pageNum + 1;
      setPageNum(nextPage);
      getList(nextPage);
    }
  })
  return (
    <View className='order-page'>
      {
        orderList.map((item, index) => {
          return <View className='order-item' key={item.id || index} onClick={() => toOrderDetail(item)}>
            <View className='order-time'>{item.time || '-'}</View>
            <View className='order-start'>起点:{item.start || '-'}</View>
            <View className='order-start'>终点:{item.end || '-'}</View>
            <View onClick={againOrder} className='order-again'>
              <Text className='order-again-text'>再来一单</Text>
      {groups.map((group, gi) => {
        return <View key={group.dateLabel || gi}>
          {(group.orders || []).map((item, index) => {
            return <View className='order-item' key={item.orderId || index} onClick={() => toOrderDetail(item)}>
              <View className='order-time'>{`${item.time} ${item.orderTime}` || formatTime(item.time)}</View>
              <View className='order-start'>起点:{item.originAddress || '-'}</View>
              <View className='order-start'>终点:{item.destinationAddress || '-'}</View>
              <View onClick={(e) => { e.stopPropagation(); againOrder(item) }} className='order-again'>
                <Text className='order-again-text'>再来一单</Text>
              </View>
            </View>
          </View>
        })
      }
          })}
        </View>
      })}
    </View>
  )
src/robotaxi/pages/pricing-rules/index.config.ts
New file
@@ -0,0 +1,3 @@
export default {
  navigationBarTitleText: '计价规则',
};
src/robotaxi/pages/pricing-rules/index.less
New file
@@ -0,0 +1,79 @@
.pricing-rules-page {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  padding: 72px 64px;
  .title {
    font-family: PingFang SC;
    font-size: 28px;
    font-weight: 500;
    line-height: 44px;
    letter-spacing: normal;
    /* 文字色/黑色/重要字 90% */
    color: rgba(0, 0, 0, 0.9);
    margin-bottom: 16px;
  }
  .dis {
    font-family: PingFang SC;
    font-size: 24px;
    font-weight: normal;
    line-height: 40px;
    letter-spacing: normal;
    /* 文字色/黑色/次要文字 60% */
    color: rgba(0, 0, 0, 0.6);
  }
  .value-text {
    font-family: PingFang SC;
    font-size: 24px;
    font-weight: normal;
    line-height: 40px;
    letter-spacing: normal;
    /* 文字色/黑色/次要文字 60% */
    color: rgba(0, 0, 0, 0.6);
    margin-top: 16px;
  }
  .item-title {
    font-family: PingFang SC;
    font-size: 28px;
    font-weight: 500;
    line-height: 44px;
    letter-spacing: normal;
    /* 文字色/黑色/重要字 90% */
    color: rgba(0, 0, 0, 0.9);
    margin: 36px 0 16px 0;
  }
  .item-value {
    font-family: PingFang SC;
    font-size: 24px;
    font-weight: normal;
    line-height: 40px;
    letter-spacing: normal;
    /* 文字色/黑色/次要文字 60% */
    color: rgba(0, 0, 0, 0.6);
  }
}
.relative {
  position: relative;
}
.flex-card {
  display: flex;
  align-items: center;
}
.flex-between-card {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.color-red {
  color: #FF4D4F !important;
}
src/robotaxi/pages/pricing-rules/index.tsx
New file
@@ -0,0 +1,73 @@
import Taro from '@tarojs/taro';
import { Component, useState, useEffect } from 'react';
import { View, Text, Image, Input } from '@tarojs/components';
import './index.less';
import Subtract from '../../assets/Subtract.png';
export default function PricingRulesPage() {
  return (
    <View className='pricing-rules-page'>
      <View className='title'>起步价(3公里,8分钟)</View>
      <View className='dis'>
        包含里程3公里,包含时长8分钟,包含里程或包含时长(低速时长)任何一项超出时,将在起步价基础上累加计费。
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>4.0元 </View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>00:00-07:00</View>
        <View className='item-value'>4.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>07:00-18:00</View>
        <View className='item-value'>4.0元</View>
      </View>
      {/* 里程费 */}
      <View className='item-title'>里程费</View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      {/* 时长费 */}
      <View className='item-title'>时长费</View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      {/* 远途费 */}
      <View className='item-title'>远途费</View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
      <View className='flex-between-card'>
        <View className='item-value'>普通时段</View>
        <View className='item-value'>1.0元</View>
      </View>
    </View>
  )
}