From bfb020da5cf8aa89c5eaae9e59e9ea8e04a49448 Mon Sep 17 00:00:00 2001
From: “mitao” <“2763622819@qq.com”>
Date: 星期五, 13 二月 2026 17:15:06 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/master'

---
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java                            |    8 +
 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java                      |   10 +
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java |   34 +++++
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java                 |    6 +
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java                                        |    4 
 xp-robotaxi-operation-boot/pom.xml                                                                             |    6 +
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java          |    9 
 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java                      |  182 +++++++++++++++++++++--------
 xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java                   |   71 +++++++++--
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java         |    5 
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java        |    5 
 11 files changed, 263 insertions(+), 77 deletions(-)

diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java
index ba1fe70..43f8fe8 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automatic/OrderMissionClientFallbackFactory.java
@@ -1,7 +1,7 @@
 package com.xiaopeng.api.factory.automatic;
 
-import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
 import com.xiaopeng.api.feignClient.automatic.OrderMissionClient;
+import com.xiaopeng.api.feignClient.maintenance.XpChargingRecordClient;
 import com.xiaopeng.common.core.domain.R;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.cloud.openfeign.FallbackFactory;
@@ -22,7 +22,8 @@
         return new OrderMissionClient() {
             @Override
             public R<Boolean> pushOrder(PushOrderDto dto) {
-                return null;
+                log.error("推送订单失败,原因: {}", cause.getMessage());
+                return R.fail();
             }
         };
     }
diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
index 1b2e7de..4807d64 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
@@ -82,6 +82,12 @@
                 log.error("订单出队失败,原因: {}", cause.getMessage());
                 return R.fail();
             }
+
+            @Override
+            public R<?> updateOrder(XpOrder xpOrder) {
+                log.error("更新订单失败,原因: {}", cause.getMessage());
+                return R.fail();
+            }
         };
     }
 }
diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
index 2939e88..4c46788 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
@@ -91,4 +91,12 @@
     @PostMapping("/inner/order/popOrder")
     R<?> popOrder(@RequestBody PopOrderDto dto);
 
+    /**
+     * 修改订单信息
+     *
+     * @param xpOrder 订单信息
+     */
+    @PostMapping("/inner/order/updateOrder")
+    R<?> updateOrder(@RequestBody XpOrder xpOrder);
+
 }
diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
index 191cdbf..c378bce 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
@@ -207,4 +207,8 @@
     @ApiModelProperty(value = "行程结束时间")
     private LocalDateTime tripEnd;
 
+
+    @ApiModelProperty(value = "队列名称")
+    @TableField("queue_name")
+    private String queueName;
 }
diff --git a/xp-robotaxi-operation-boot/pom.xml b/xp-robotaxi-operation-boot/pom.xml
index 31632fb..bdf03df 100644
--- a/xp-robotaxi-operation-boot/pom.xml
+++ b/xp-robotaxi-operation-boot/pom.xml
@@ -15,12 +15,18 @@
     </description>
 
     <dependencies>
+
         <!--mongodb-->
         <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-data-mongodb</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.belerweb</groupId>
+            <artifactId>pinyin4j</artifactId>
+            <version>2.5.1</version>
+        </dependency>
+        <dependency>
             <groupId>com.github.stuxuhai</groupId>
             <artifactId>jpinyin</artifactId>
             <version>1.1.8</version>
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
index 63d8037..9ed6f73 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
@@ -137,14 +137,13 @@
     /**
      * 批量冻结
      */
-    @PutMapping("/freezeByIds")
+    @GetMapping("/freezeByIds")
     @ResponseBody
     @ApiOperation(value = "批量冻结")
-    public R freezeByIds(List<Long> ids) {
+    public R freezeByIds(String ids) {
         SysUser sysUser = tokenService.getLoginUser().getSysUser();
-
-
-        return xpWhitelistService.freezeByIds(ids, sysUser);
+        List<Long> whiteIds = Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList());
+        return xpWhitelistService.freezeByIds(whiteIds, sysUser);
     }
 
     @ApiOperation(value = "白名单导入模板下载")
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java
index ce296ef..00486bf 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java
@@ -12,6 +12,7 @@
 import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
 import com.xiaopeng.api.model.operation.XpPoint;
 import com.xiaopeng.api.query.operation.ElectronicPageListQuery;
+import com.xiaopeng.api.model.operation.XpRegion;
 import com.xiaopeng.common.core.domain.R;
 import com.xiaopeng.common.core.exception.ServiceException;
 import com.xiaopeng.common.core.utils.DateUtils;
@@ -25,9 +26,15 @@
 import com.xiaopeng.operation.mapper.XpElectronicFenceAreaMapper;
 import com.xiaopeng.operation.mapper.XpElectronicFenceMapper;
 import com.xiaopeng.operation.mapper.XpPointMapper;
+import com.xiaopeng.api.query.operation.ElectronicPageListQuery;
+import com.xiaopeng.operation.mapper.XpRegionMapper;
 import com.xiaopeng.operation.service.IXpElectronicFenceService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.xiaopeng.operation.service.IXpRegionService;
 import com.xiaopeng.operation.utils.PolygonOverlapService;
 import lombok.extern.slf4j.Slf4j;
+import net.sourceforge.pinyin4j.PinyinHelper;
+import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.geo.Point;
 import org.springframework.data.mongodb.core.MongoTemplate;
@@ -62,6 +69,8 @@
     private MongoTemplate mongoTemplate;
     @Autowired
     private XpPointMapper xpPointMapper;
+    @Autowired
+    private XpRegionMapper xpRegionMapper;
 
     @Override
     public PageInfo<XpElectronicFence> pageList(ElectronicPageListQuery query) {
@@ -90,7 +99,18 @@
         pageInfo.setRecords(list);
         return pageInfo;
     }
-
+    public static String getPinyinInitials(String chinese) {
+        StringBuilder pinyinInitials = new StringBuilder();
+        for (char c : chinese.toCharArray()) {
+            // 获取拼音数组(多音字会返回多个拼音)
+            String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(c);
+            if (pinyinArray != null && pinyinArray.length > 0) {
+                // 取第一个拼音的首字母
+                pinyinInitials.append(pinyinArray[0].charAt(0));
+            }
+        }
+        return pinyinInitials.toString();
+    }
     @Override
     public R addElectronic(ElectronicFenceAddDto dto) {
         try {
@@ -142,7 +162,17 @@
                 }
             }
             xpElectronicFence.setCityCode(dto.getCityCode());
+            // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收
+            XpRegion xpRegion = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>()
+                    .eq(XpRegion::getCode, dto.getCityCode()));
+            String name = xpRegion.getName();
             this.save(xpElectronicFence);
+            // 根据城市中文名,截取前两位的首字母并且大写
+            // 截取前两个字符
+            String prefix = name.substring(0, 2);
+            // 获取拼音首字母并大写
+            String result = getPinyinInitials(prefix).toUpperCase();
+            xpElectronicFence.setElectronicNumber(result + "-OP-" + String.format("%04d", xpElectronicFence.getId()));
             if (dto.getStatus() == 0) {
                 xpElectronicFence.setStatus(0);
             } else if (dto.getStatus() == 1) {
@@ -216,7 +246,7 @@
                         xpGeoFencingPolygon.setFenceId(String.valueOf(xpElectronicFence.getId()));
                         xpGeoFencingPolygon.setName(xpElectronicFence.getElectronicName());
                         xpGeoFencingPolygon.setAreaId(String.valueOf(newElectronicFenceArea.getId()));
-                        xpGeoFencingPolygon.setCityCode("510100");
+                        xpGeoFencingPolygon.setCityCode(xpElectronicFence.getCityCode());
                         xpGeoFencingPolygon.setOperationStrategy(xpElectronicFence.getOperationStrategy());
                         // 将围栏点转换为GeoJSON多边形
                         GeoJsonPolygon geoJsonPolygon = convertToGeoJsonPolygon(newElectronicFenceArea.getFencePoints());
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
index a416a26..52c4bab 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -514,12 +514,17 @@
                     // 尾部
                     redisService.addToTail(s, orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule());
                 }
+                xpOrder.setQueueName(s);
+                xpOrderClient.updateOrder(xpOrder);
+
                 return orderId;
             }
         }
 
         String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
         redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule()));
+        xpOrder.setQueueName(key);
+        xpOrderClient.updateOrder(xpOrder);
         return orderId;
 
 //
diff --git a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
index bc4cd5f..94c96c4 100644
--- a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
+++ b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -128,6 +128,16 @@
         return R.ok();
     }
 
+    /**
+     * 修改订单信息
+     *
+     * @param xpOrder 订单信息
+     */
+    @PostMapping("/inner/order/updateOrder")
+    public R<?> updateOrder(@RequestBody XpOrder xpOrder){
+        return xpOrderService.updateById(xpOrder)?R.ok():R.fail();
+    }
+
 
     /**
      * 新增订单
diff --git a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
index bac5080..fdfcc32 100644
--- a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
+++ b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -71,6 +71,7 @@
 import com.xiaopeng.order.service.IXpOrderEvaluateService;
 import com.xiaopeng.order.service.IXpOrderReassignService;
 import com.xiaopeng.order.service.IXpOrderService;
+import com.xiaopeng.order.utils.TaxiPricingDemoService;
 import com.xiaopeng.order.utils.holiday.HolidayUtil;
 import com.xiaopeng.order.vo.OrderDetailVo;
 import io.swagger.annotations.ApiModelProperty;
@@ -771,11 +772,11 @@
         // 消息推送
         Map<String, Object> params = new HashMap<>();
         Map<String, Object> content = new HashMap<>();
-        content.put("orderId",order.getId());
+        content.put("orderId", order.getId());
         content.put("status", OrderStatusEnum.CANCELED.getCode());
         params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc());
         params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content));
-        params.put("timestamp", new Date().getTime()+"");
+        params.put("timestamp", new Date().getTime() + "");
         String message = JSONObject.toJSONString(params);
         SendMessageDTO sendMessageDTO = new SendMessageDTO();
         sendMessageDTO.setMessage(message);
@@ -920,7 +921,41 @@
 
             userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
         }
-        // 计算起步价
+        // 费用
+        // 查询订单轨迹
+        List<OrderTrajectory> trajectories = mongoTemplate.find(
+                new Query(Criteria.where("orderId").is(orderId))
+                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
+                OrderTrajectory.class
+        );
+        List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>();
+        for (OrderTrajectory trajectory : trajectories) {
+            TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(),trajectory.getLocatetime() );
+            gpsPoints.add(point);
+        }
+        TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig();
+        config.peak = new TaxiPricingDemoService.PricingRule("高峰期", "14:40", "14:46", 15.0, 3.0, 5.0, 3.0, 0.8);
+        config.night = new TaxiPricingDemoService.PricingRule("夜间行驶", "14:47", "14:48", 18.0, 3.0, 5.0, 3.5, 1.0);
+        config.holiday = new TaxiPricingDemoService.PricingRule("节假日", "18:47", "18:48", 18.0, 3.0, 5.0, 4, 2.0);
+        config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", "14:46", "14:47", 10.0, 3.0, 5.0, 2.4, 0.5));
+        config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", "14:48", "17:59", 10.0, 3.0, 5.0, 2.4, 0.5));
+
+        // --- 远途加价区间配置 (关键修改) ---
+        // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2)
+        config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(5.0, 6.0, 1.2));
+        // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0)
+        config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(6.0, 7.0, 2.0));
+        // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值
+        config.longSteps.add(new TaxiPricingDemoService.LongRangeStep(7.0, 8.0, 3.5));
+
+        TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService();
+        Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getCreateTime()), order.getMileageKilometers(), gpsPoints, config);
+        System.err.println("======= 订单计费账单 =======");
+        bill.forEach((detail, price) -> System.err.println(detail + ": " + price + " 元"));
+
+        BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+        System.err.println("--------------------------");
+        System.err.println("应付总额: " + totalAmount + " 元");
 
 //        // 计算实际价格
 //        // 根据订单所属开通城市id 查询定价
@@ -1276,11 +1311,10 @@
 ////        );
 
 
-
     }
 
 
-    private MileageDto  mileageType(MileageDto param,JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) {
+    private MileageDto mileageType(MileageDto param, JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) {
         // 计算出是在哪个普通时间段内
         for (Object o : startingFareJsonArray) {
             JSONObject startingFare = (JSONObject) o;
@@ -1295,7 +1329,7 @@
             calendarEnd.set(Calendar.MINUTE, Integer.valueOf(startingFare.getString("num2").split(":")[1]));
             // 找到符合条件的直接跳出循环
             if (mileageDate.getTime() > calendarStart.getTimeInMillis() && mileageDate.getTime() < calendarEnd.getTimeInMillis()) {
-                param.setMileage(startingFare.getString("num6")) ;
+                param.setMileage(startingFare.getString("num6"));
                 param.setTime(startingFare.getString("num7"));
                 param.setMileageTypeTemp(1);
                 break;
@@ -1317,7 +1351,7 @@
         if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()
         ) {
 
-            param.setMileage(num16) ;
+            param.setMileage(num16);
             param.setTime(num17);
             param.setMileageTypeTemp(2);
         }
@@ -1344,7 +1378,7 @@
         if ((date.getTime() > calendar1Start.getTimeInMillis() && date.getTime() < calendar1End.getTimeInMillis())
                 || (date.getTime() > calendar2Start.getTimeInMillis() && date.getTime() < calendar2End.getTimeInMillis())) {
 
-            param.setMileage(num24) ;
+            param.setMileage(num24);
             param.setTime(num25);
             param.setMileageTypeTemp(3);
         }
@@ -1352,7 +1386,7 @@
         boolean holiday = holidayUtil.isHoliday(localDate);
         if (holiday) {
             // 判断是否为节假日 起步价修改
-            param.setMileage(num30) ;
+            param.setMileage(num30);
             param.setTime(num31);
             param.setMileageTypeTemp(4);
         }
@@ -1604,7 +1638,7 @@
         BeanUtils.copyProperties(order, orderDetailVo);
         // 查询车辆信息
         XpVehicle vehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
-        if (vehicle!=null){
+        if (vehicle != null) {
             orderDetailVo.setVehicleCode(vehicle.getVehicleCode());
             orderDetailVo.setPlateNumber(vehicle.getPlateNumber());
             orderDetailVo.setVehicleColor(vehicle.getVehicleColor());
@@ -1626,15 +1660,15 @@
                 OrderTrajectory.class
         );
         orderDetailVo.setTrajectories(trajectories);
-        if (order.getTripBegin()!=null&&order.getTripEnd()!=null){
+        if (order.getTripBegin() != null && order.getTripEnd() != null) {
             // 计算两个时间相差多少分钟
             long minutesDifference = Duration.between(order.getTripBegin(), order.getTripEnd()).toMinutes();
             orderDetailVo.setOrderTime(minutesDifference);
-        }else{
+        } else {
             orderDetailVo.setOrderTime(0l);
         }
-        if (order.getStartMileage()!=null){
-            orderDetailVo.setTotalMileage(order.getStartMileage()+(order.getMileageKilometers()!=null?order.getMileageKilometers():0D));
+        if (order.getStartMileage() != null) {
+            orderDetailVo.setTotalMileage(order.getStartMileage() + (order.getMileageKilometers() != null ? order.getMileageKilometers() : 0D));
 
         }
         return orderDetailVo;
@@ -1643,6 +1677,7 @@
 
     /**
      * 成功操作下发命令后调用 用于弹出redis队列的获取成功的数据
+     *
      * @param dto
      */
     @Override
@@ -1652,12 +1687,16 @@
 
         XpOrder order = this.getById(dto.getOrderId());
         order.setAcceptanceTime(LocalDateTime.now());
-        order.setVehicleId(dto.getXpVehicleId());
+
+        R<XpVehicle> byVehicleVin = xpVehicleClient.findByVehicleVin(dto.getXpVehicleVin());
+        if (byVehicleVin.getCode()==200){
+            order.setVehicleId(byVehicleVin.getData().getId());
+        }
         order.setStatus(2);
 
         // Redis弹出这个队列元素
         // value 订单Id_经纬度_状态_用户id_订单编号_距离_时间
-        String popFirstElement = redisService.popFirstElement(dto.getQueueName());
+        String popFirstElement = redisService.popFirstElement(order.getQueueName());
         XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
         String[] split = popFirstElement.split("_");
         xpGeoQueryEntity.setOrderId(split[0]);
diff --git a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java
index 1518bde..ebd23ef 100644
--- a/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java
+++ b/xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaxiPricingDemoService.java
@@ -1,5 +1,4 @@
 package com.xiaopeng.order.utils;
-
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.time.LocalTime;
@@ -16,11 +15,11 @@
         PricingConfig config = setupMockConfig();
 
         Calendar cal = Calendar.getInstance();
-        cal.set(2023, Calendar.OCTOBER, 10, 16, 50, 0);
+        cal.set(2026, Calendar.MARCH, 13, 14, 40, 15);
         Date orderTime = cal.getTime();
 
         // 模拟总里程 25.0 km,以触发多级远途加价
-        double totalMillige = 25.0;
+        double totalMillige = 7.874;
 
         // 模拟 GPS 轨迹点
         List<GpsPoint> points = createMockGpsPoints(orderTime);
@@ -42,7 +41,7 @@
             BigDecimal totalMileage = BigDecimal.valueOf(totalMileageKm);
 
             PricingRule baseRule = config.findMatchedRule(orderTime);
-            result.put("起步价(" + baseRule.ruleName + ")", baseRule.baseFare);
+            result.put("起步价(" + baseRule.ruleName + ")"+"-"+baseRule.start+"-"+baseRule.end, baseRule.baseFare);
 
             if (totalMileage.compareTo(baseRule.baseKm) <= 0) {
                 return formatMap(result);
@@ -51,6 +50,15 @@
             BigDecimal remainBaseM = baseRule.baseKm.multiply(new BigDecimal("1000"));
             BigDecimal remainBaseMs = baseRule.baseMin.multiply(new BigDecimal("60000"));
             BigDecimal currentTotalM = BigDecimal.ZERO;
+            BigDecimal currentTotalMs = BigDecimal.ZERO;
+
+            boolean isOverBaseM = false;
+            boolean isOverBaseMs = false;
+
+            // 超出里程和分钟数的集合
+            Map<String, BigDecimal> bill = new LinkedHashMap<>();
+            Map<String, BigDecimal> activeRuleNameRate = new LinkedHashMap<>();
+            Set<String> activeRuleNameList = new HashSet<>();
 
             for (int i = 1; i < points.size(); i++) {
                 GpsPoint curr = points.get(i);
@@ -59,65 +67,94 @@
                 BigDecimal segM = BigDecimal.valueOf(curr.getDistance());
                 BigDecimal segMs = BigDecimal.valueOf(curr.getLocatetime() - prev.getLocatetime());
                 currentTotalM = currentTotalM.add(segM); // 累计当前已行驶的总里程
+                currentTotalMs = currentTotalMs.add(segMs); // 累计当前已行驶的总时间
 
                 PricingRule activeRule = config.findMatchedRule(new Date(curr.getLocatetime()));
 
                 // 扣除起步额度逻辑
                 BigDecimal billM = BigDecimal.ZERO;
-                if (remainBaseM.compareTo(BigDecimal.ZERO) > 0) {
-                    if (segM.compareTo(remainBaseM) > 0) {
-                        billM = segM.subtract(remainBaseM);
-                        remainBaseM = BigDecimal.ZERO;
-                    } else {
-                        remainBaseM = remainBaseM.subtract(segM);
-                    }
-                } else {
-                    billM = segM;
+                if (currentTotalM.compareTo(remainBaseM) > 0) {
+//                    billM = currentTotalM.subtract(remainBaseM);
+                    isOverBaseM = true;
                 }
-
                 BigDecimal billMs = BigDecimal.ZERO;
-                if (remainBaseMs.compareTo(BigDecimal.ZERO) > 0) {
-                    if (segMs.compareTo(remainBaseMs) > 0) {
-                        billMs = segMs.subtract(remainBaseMs);
-                        remainBaseMs = BigDecimal.ZERO;
-                    } else {
-                        remainBaseMs = remainBaseMs.subtract(segMs);
-                    }
-                } else {
-                    billMs = segMs;
+                if (currentTotalMs.compareTo(remainBaseMs) > 0) {
+//                    billMs = currentTotalMs.subtract(remainBaseMs);
+                    isOverBaseMs = true;
                 }
-
                 // 1. 基础费率计算
-                BigDecimal distFee = billM.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP).multiply(activeRule.perKmRate);
-                BigDecimal timeFee = billMs.divide(new BigDecimal(60000), 10, RoundingMode.HALF_UP).multiply(activeRule.perMinRate);
+//                BigDecimal distFee = billM.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP).multiply(activeRule.perKmRate);
+//                BigDecimal timeFee = billMs.multiply(activeRule.perMinRate);
 
                 // 2. 远途加价计算 (基于区间判定)
-                BigDecimal longExtra = calculateLongDistExtra(currentTotalM, billM, config.longSteps);
+//                BigDecimal longExtra = calculateLongDistExtra(currentTotalM, billM, config.longSteps);
 
-                BigDecimal totalSeg = distFee.add(timeFee).add(longExtra);
-                result.put(activeRule.ruleName, result.getOrDefault(activeRule.ruleName, BigDecimal.ZERO).add(totalSeg));
+//                BigDecimal totalSeg = distFee.add(timeFee).add(longExtra);
+                // 超出里程
+                if (isOverBaseM) {
+                    bill.put(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ml", BigDecimal.ZERO).add(segM));
+                }
+                // 超出时间
+                if (isOverBaseMs) {
+                    bill.put(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms", bill.getOrDefault(activeRule.ruleName + activeRule.start + "-" + activeRule.end + "_Ms", BigDecimal.ZERO).add(segMs));
+                }
+
+                // 若不存在规则名称,则添加
+                activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml", k -> activeRule.perKmRate); // 超出里程的加价
+                activeRuleNameRate.computeIfAbsent(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms",k ->activeRule.perMinRate); // 超出时间的加价
+
+                activeRuleNameList.add(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ml");
+                activeRuleNameList.add(activeRule.ruleName + "-"+activeRule.start + "-" + activeRule.end + "_Ms");
+//                result.put(activeRule.ruleName, result.getOrDefault(activeRule.ruleName, BigDecimal.ZERO).add(totalSeg));
             }
+            // 1. 基础费率计算
+            for (String ruleName : activeRuleNameList) {
+                String[] split = ruleName.split("_");
+                if(ruleName.endsWith("_Ml")){
+                    BigDecimal exceedValue = bill.get(ruleName);
+                    if(Objects.nonNull(exceedValue)){
+                        exceedValue = exceedValue.divide(new BigDecimal(1000), 2, RoundingMode.HALF_UP);
+                    }else{
+                        exceedValue = BigDecimal.ZERO;
+                    }
+                    BigDecimal exceedRate = activeRuleNameRate.get(ruleName);
+                    result.put(split[0], result.getOrDefault(split[0], BigDecimal.ZERO).add(exceedValue.multiply(exceedRate)));
+                }else{
+                    BigDecimal exceedValue = bill.get(ruleName);
+                    if(Objects.nonNull(exceedValue)){
+                        exceedValue = exceedValue.divide(new BigDecimal(60000), 2, RoundingMode.HALF_UP);
+                    }else{
+                        exceedValue = BigDecimal.ZERO;
+                    }
+                    BigDecimal exceedRate = activeRuleNameRate.get(ruleName);
+                    result.put(split[0], result.getOrDefault(split[0], BigDecimal.ZERO).add(exceedValue.multiply(exceedRate)));
+                }
+            }
+            // 2. 远途加价计算 (基于区间判定)
+            BigDecimal longExtra = calculateLongDistExtra(BigDecimal.valueOf(totalMileageKm), config.longSteps);
+            result.put("远途费", longExtra);
             return formatMap(result);
         }
 
         /**
          * 远途加价核心逻辑:判断当前行驶到的里程处于哪个加价区间
          */
-        private BigDecimal calculateLongDistExtra(BigDecimal currentTotalM, BigDecimal billM, List<LongRangeStep> steps) {
+        private BigDecimal calculateLongDistExtra(BigDecimal billM, List<LongRangeStep> steps) {
             if (billM.compareTo(BigDecimal.ZERO) <= 0) return BigDecimal.ZERO;
 
             // 当前点所在的公里数
-            BigDecimal currentKm = currentTotalM.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP);
+            BigDecimal extraStart = BigDecimal.ZERO;
             BigDecimal extraRate = BigDecimal.ZERO;
 
             // 匹配区间规则
             for (LongRangeStep step : steps) {
-                if (step.isMatch(currentKm)) {
+                if (step.isMatch(billM)) {
                     extraRate = step.addPrice;
+                    extraStart = step.numStart;
                     break;
                 }
             }
-            return billM.divide(new BigDecimal(1000), 10, RoundingMode.HALF_UP).multiply(extraRate);
+            return billM.subtract(extraStart).multiply(extraRate);
         }
 
         private Map<String, BigDecimal> formatMap(Map<String, BigDecimal> map) {
@@ -145,16 +182,15 @@
     }
 
     public static class PricingConfig {
-        PricingRule holiday;
-        PricingRule peak;
-        PricingRule night;
-        List<PricingRule> normals = new ArrayList<>();
-        List<LongRangeStep> longSteps = new ArrayList<>(); // 修改为区间列表
-        boolean isHoliday = false;
+        public PricingRule holiday;
+        public PricingRule peak;
+        public PricingRule night;
+        public List<PricingRule> normals = new ArrayList<>();
+        public List<LongRangeStep> longSteps = new ArrayList<>(); // 修改为区间列表
 
         public PricingRule findMatchedRule(Date date) {
             LocalTime t = date.toInstant().atZone(ZoneId.systemDefault()).toLocalTime();
-            if (isHoliday) return holiday;
+            if (holiday.isMatch(t)) return holiday;
             if (peak.isMatch(t)) return peak;
             if (night.isMatch(t)) return night;
             for (PricingRule r : normals) if (r.isMatch(t)) return r;
@@ -163,9 +199,9 @@
     }
 
     public static class PricingRule {
-        String ruleName;
-        LocalTime start, end;
-        BigDecimal baseFare, baseKm, baseMin, perKmRate, perMinRate;
+        public String ruleName;
+        public LocalTime start, end;
+        public BigDecimal baseFare, baseKm, baseMin, perKmRate, perMinRate;
 
         public PricingRule(String n, String s, String e, double bf, double bk, double bm, double pkr, double pmr) {
             this.ruleName = n;
@@ -193,17 +229,19 @@
 
     private static PricingConfig setupMockConfig() {
         PricingConfig config = new PricingConfig();
-        config.peak = new PricingRule("高峰期", "17:00", "19:00", 15.0, 3.0, 5.0, 3.0, 0.8);
-        config.night = new PricingRule("夜间行驶", "22:00", "05:00", 18.0, 3.0, 5.0, 3.5, 1.0);
-        config.normals.add(new PricingRule("普通时段", "05:00", "17:00", 12.0, 3.0, 5.0, 2.4, 0.5));
+        config.peak = new PricingRule("高峰期", "14:40", "14:46", 15.0, 3.0, 5.0, 3.0, 0.8);
+        config.night = new PricingRule("夜间行驶", "14:47", "14:48", 18.0, 3.0, 5.0, 3.5, 1.0);
+        config.holiday = new PricingRule("节假日", "18:47", "18:48", 18.0, 3.0, 5.0, 4, 2.0);
+        config.normals.add(new PricingRule("普通时段", "14:46", "14:47", 10.0, 3.0, 5.0, 2.4, 0.5));
+        config.normals.add(new PricingRule("普通时段", "14:48", "17:59", 10.0, 3.0, 5.0, 2.4, 0.5));
 
         // --- 远途加价区间配置 (关键修改) ---
         // 1. 超过 num1(12) 不足 num2(20), 加收 num3(1.2)
-        config.longSteps.add(new LongRangeStep(12.0, 20.0, 1.2));
+        config.longSteps.add(new LongRangeStep(5.0, 6.0, 1.2));
         // 2. 超过 num4(20) 不足 num5(35), 加收 num6(2.0)
-        config.longSteps.add(new LongRangeStep(20.0, 35.0, 2.0));
+        config.longSteps.add(new LongRangeStep(6.0, 7.0, 2.0));
         // 3. 超过 num7(35) 以后, 加收 num8(3.5) -> numEnd 传个极大值
-        config.longSteps.add(new LongRangeStep(35.0, 999999.0, 3.5));
+        config.longSteps.add(new LongRangeStep(7.0, 8.0, 3.5));
 
         return config;
     }
@@ -213,9 +251,49 @@
         long startTs = startTime.getTime();
         list.add(new GpsPoint(0, startTs));
         // 模拟行驶了 20km
-        list.add(new GpsPoint(12000, startTs + 15 * 60 * 1000));
-        list.add(new GpsPoint(8000, startTs + 25 * 60 * 1000));
-        list.add(new GpsPoint(5000, startTs + 35 * 60 * 1000));
+        list.add(new GpsPoint(120, startTs + 2 * 10 * 1000));
+        list.add(new GpsPoint(204, startTs + 2 * 20 * 1000));
+        list.add(new GpsPoint(231, startTs + 2 * 30 * 1000));
+        list.add(new GpsPoint(252, startTs + 2 * 40 * 1000));
+        list.add(new GpsPoint(188, startTs + 2 * 50 * 1000));
+        list.add(new GpsPoint(150, startTs + 2 * 60 * 1000));
+        list.add(new GpsPoint(126, startTs + 2 * 70 * 1000));
+        list.add(new GpsPoint(138, startTs + 2 * 80 * 1000));
+        list.add(new GpsPoint(119, startTs + 2 * 90 * 1000));
+        list.add(new GpsPoint(147, startTs + 2 * 100 * 1000));
+        list.add(new GpsPoint(155, startTs + 2 * 110 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 120 * 1000));
+        list.add(new GpsPoint(172, startTs + 2 * 130 * 1000));
+        list.add(new GpsPoint(202, startTs + 2 * 140 * 1000));
+        list.add(new GpsPoint(162, startTs + 2 * 150 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 160 * 1000));
+        list.add(new GpsPoint(132, startTs + 2 * 170 * 1000));
+        list.add(new GpsPoint(142, startTs + 2 * 180 * 1000));
+        list.add(new GpsPoint(262, startTs + 2 * 190 * 1000));
+        list.add(new GpsPoint(242, startTs + 2 * 200 * 1000));
+        list.add(new GpsPoint(282, startTs + 2 * 210 * 1000));
+        list.add(new GpsPoint(222, startTs + 2 * 220 * 1000));
+        list.add(new GpsPoint(212, startTs + 2 * 230 * 1000));
+        list.add(new GpsPoint(142, startTs + 2 * 240 * 1000));
+        list.add(new GpsPoint(262, startTs + 2 * 250 * 1000));
+        list.add(new GpsPoint(169, startTs + 2 * 260 * 1000));
+        list.add(new GpsPoint(170, startTs + 2 * 270 * 1000));
+        list.add(new GpsPoint(180, startTs + 2 * 280 * 1000));
+        list.add(new GpsPoint(165, startTs + 2 * 290 * 1000));
+        list.add(new GpsPoint(180, startTs + 2 * 300 * 1000));
+        list.add(new GpsPoint(198, startTs + 2 * 310 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 320 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 330 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 340 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 350 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 360 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 370 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 380 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 390 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 400 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 410 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 420 * 1000));
+        list.add(new GpsPoint(182, startTs + 2 * 430 * 1000));
         return list;
     }
 }
\ No newline at end of file

--
Gitblit v1.7.1