From f941da4ef0742ee067bcf9cb54ccf39c9ca2fefe Mon Sep 17 00:00:00 2001
From: xuhy <3313886187@qq.com>
Date: 星期三, 15 四月 2026 18:25:01 +0800
Subject: [PATCH] [feat]连环派代70%

---
 xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java |    2 
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/VehiclePositionByVinDto.java                    |   11 +++++
 xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/map/RouteAndFareDto.java                                  |    4 +-
 xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java                     |   67 ++++++++++++++++++++++++++++++++-
 xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java |   19 ++++++++-
 5 files changed, 93 insertions(+), 10 deletions(-)

diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/map/RouteAndFareDto.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/map/RouteAndFareDto.java
index 7dd231f..dbe5e9d 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/map/RouteAndFareDto.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/map/RouteAndFareDto.java
@@ -33,7 +33,7 @@
     @ApiModelProperty("车辆id")
     private Long vehicleId;
 
-
-
+    public RouteAndFareDto() {
+    }
 
 }
diff --git a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/VehiclePositionByVinDto.java b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/VehiclePositionByVinDto.java
index 4d603ee..31348b5 100644
--- a/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/VehiclePositionByVinDto.java
+++ b/xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/VehiclePositionByVinDto.java
@@ -20,7 +20,16 @@
     // 车辆vin
     private Set<String> vinList;
 
-
     // 数量
     private Integer num;
+
+    public VehiclePositionByVinDto(Long fenceId, Set<String> vinList, Integer num) {
+        this.fenceId = fenceId;
+        this.vinList = vinList;
+        this.num = num;
+    }
+
+    // 状态
+    private Integer status;
+
 }
diff --git a/xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java b/xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
index e5685b7..8a43dbc 100644
--- a/xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
+++ b/xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -62,9 +62,7 @@
 
 import javax.annotation.Resource;
 import java.util.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
 
 
 /**
@@ -1107,6 +1105,7 @@
 
     }
 
+    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);
 
     /**
      * 订单状态更新事件
@@ -1202,6 +1201,19 @@
                     log.info("到达目的地,不做任何处理:{}", orderId);
                     break;
                 case ORDER_WAITING_FOR_DROPOFF:
+                    // 根据车辆id查询订单,如果未完成订单数量不唯一则下发循环订单任务
+                    List ret = new ArrayList(2);//TODO
+                    if(ret.size() > 1){
+                        scheduler.schedule(() -> {
+                            //下发循环订单任务
+//                        xpOrderClient.createLoopOrderTask(vin, orderId);
+                            log.info("下发循环订单任务:{}", orderId);
+                            // 修改订单状态,和推送消息的状态
+                        }, 3, TimeUnit.SECONDS);
+
+                        break;
+                    }
+
                     //等待乘客下车,开始倒计时发下巡游单
                     if(!orderId.contains("XU")){
                         if(orderId.contains("TEST")){
@@ -1211,6 +1223,7 @@
                             xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                         }
                     }
+
                     break;
                 case ORDER_DROPOFF_COMPLETED:
                     //下车完成,不需要处理状态,由后续的乘客主动触发或者定时任务触发
diff --git a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
index 7531c25..3327966 100644
--- a/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
+++ b/xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -40,15 +40,16 @@
 import lombok.extern.slf4j.Slf4j;
 import org.redisson.api.RLock;
 import org.redisson.api.RedissonClient;
+import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.query.Criteria;
+import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Component;
 
 import javax.annotation.Resource;
 import java.util.*;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+import java.util.concurrent.*;
 import java.util.stream.Collectors;
 
 @Slf4j
@@ -106,6 +107,8 @@
 
     // 自定义线程池
     private static final ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
+
+    ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20);
 
     static {
         threadPoolTaskExecutor.setCorePoolSize(20);
@@ -1081,12 +1084,70 @@
                     }
 
                 }
+            }
 
+            log.info("没有找到空闲车辆 {},尝试连环派单给即将服务结束的车辆", orderNo);
+            // 查询状态为1的车辆vin
+            R<List<String>> servingVehicles = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount(),1));
+            if (vehiclePositionVos.getCode() != 200) {
+                continue;
+            }
+            LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split[0]), Double.parseDouble(split[1]));
+            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
+            routeAndFareDto.setDestination(lonLatDto);
+
+            Optional<XpOrder> lucyOrderOpt = servingVehicles.getData().stream()
+                    //获取位置
+                    .map(vin -> mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class))
+                    .map(VehiclePosition::getOrderId)
+                    .map(xpOrderClient::queryOrderById)
+                    .filter(R::isSuccess)
+                    .map(R::getData)
+                    .filter(o -> isClose(o, routeAndFareDto))
+                    .findAny();
+
+            if (lucyOrderOpt.isPresent()) {
+                XpOrder lucyOder = lucyOrderOpt.get();
+                routeAndFareDto.setOrigin(new LonLatDto(lucyOder.getEndLon(),lucyOder.getEndLat()));
+                routeAndFareDto.setOrigin(lonLatDto);
+
+                RouteAndFareDto routeAndFare = null;//TODO 获取导航路线
+                if (null == routeAndFare) { //轨迹不在运营区
+                    continue;
+                }
+                // 当轨迹是否在运营区内,存储
+                xpOrder.setStatus(1);
+                xpOrderClient.updateOrder(xpOrder);
+                scheduler.scheduleWithFixedDelay(this::pushProgress, 0, 5, TimeUnit.SECONDS);
             }
         }
         return false;
     }
 
+    private void pushProgress() {
+        //TODO 调用push message 服务
+        PushOrderDto pushOrderDto = new PushOrderDto();
+//        pushOrderDto.setVin(lucyOrder.get().getVin());
+//        pushOrderDto.setOrderId(xpOrder.getId().toString());
+//        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
+//        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
+//        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
+//        pushOrderDto.setEndLongitude(xpOrder.getEndLon());
+//        pushOrderDto.setOrderType(OrderType.USER_ORDER);
+    }
+
+    private boolean isClose(XpOrder xpOrder,RouteAndFareDto routeAndFareDto) {
+        LonLatDto lonLatDto = new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat());
+        routeAndFareDto.setOrigin(lonLatDto);
+        return xpMapClient.getDistanceAndDuration(routeAndFareDto).getData().getDistance() < 800;
+    }
+
+    @Resource
+    private MongoTemplate mongoTemplate;
+    boolean isClose(Long orderId) {
+        // yong id 去查目的地坐标,判断是否小于800
+        return false;
+    }
     /**
      * 订单处理
      * @param count 轮数
diff --git a/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java b/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
index fb4bd5b..85f9e52 100644
--- a/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
+++ b/xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -779,7 +779,7 @@
      */
     @PostMapping("/logan/inner/vehicle/queryVehiclePositionByVin")
     public R<List<String>> queryVehiclePositionByVin(@RequestBody VehiclePositionByVinDto dto){
-        List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, 0)
+        List<XpVehicle> list = xpVehicleService.list(new LambdaQueryWrapper<XpVehicle>().eq(XpVehicle::getState, Optional.ofNullable(dto.getStatus()).orElse(0))
                 .eq(XpVehicle::getOperatingStatus, 1).eq(XpVehicle::getElectronicId, dto.getFenceId()).in(XpVehicle::getVehicleVin,
                 dto.getVinList()));
         if (list.isEmpty()) {

--
Gitblit v1.7.1