“mitao”
2026-03-14 4e6453cc91184f149530a22c3015085a04c74b30
Merge remote-tracking branch 'origin/master'
14个文件已修改
719 ■■■■■ 已修改文件
sql/增量sql/xprt_operation.sql 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 70 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpVehicleRepairServiceImpl.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java 254 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/base/AbstractJob.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/AddCruiseMissionJob.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/EndTripJob.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 237 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/XpVehicleVO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
sql/增量sql/xprt_operation.sql
@@ -1,7 +1,19 @@
ALTER TABLE `xp_banner` ADD COLUMN `sort` int NULL DEFAULT NULL COMMENT '排序' AFTER `banner_status`;
ALTER TABLE `xp_point_0` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_cruise_plan_vehicle` ADD COLUMN `id` bigint NOT NULL COMMENT '自增id' FIRST;
ALTER TABLE `xp_point_1` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_cruise_plan_vehicle` ADD PRIMARY KEY (`id`) USING BTREE;
ALTER TABLE `xp_point_2` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_cruise_plan_vehicle` MODIFY COLUMN `id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增id';
ALTER TABLE `xp_point_3` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_4` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_5` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_6` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_7` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_8` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
ALTER TABLE `xp_point_9` ADD COLUMN `fp_electronic_area_id` bigint NULL DEFAULT NULL COMMENT '分片建' AFTER `electronic_area_id`;
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -793,8 +793,10 @@
                    break;
                case ORDER_RECEIVED:
                    //收到订单
                    buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.READY_DEPART.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.READY_DEPART, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.READY_DEPART.getCode());
                    }
                    break;
                case ORDER_STARTED:
                    //开始执行订单
@@ -802,8 +804,10 @@
                    break;
                case ORDER_EN_ROUTE_TO_PICKUP:
                    //前往上车点
                    buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.PICK_UP.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP.getCode());
                    }
                    break;
                case ORDER_ARRIVED_AT_PICKUP:
                    //到达上车点
@@ -811,49 +815,41 @@
                    break;
                case ORDER_WAITING_FOR_PICKUP:
                    //等待乘客上车
                    buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.PICK_UP_GUESTS.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.PICK_UP_GUESTS, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PICK_UP_GUESTS.getCode());
                    }
                    break;
                case ORDER_PASSENGER_ONBOARD:
                    //乘客已上车
                    buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.PASSENGER_BOARDED.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.PASSENGER_BOARDED, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.PASSENGER_BOARDED.getCode());
                    }
                    break;
                case ORDER_EN_ROUTE_TO_DESTINATION:
                    //前往目的地
                    buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.IN_SERVICE.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.IN_SERVICE, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.IN_SERVICE.getCode());
                    }
                    break;
                case ORDER_ARRIVED_AT_DESTINATION:
                    //到达目的地
                    log.info("到达目的地,不做任何处理:{}", orderId);
                    break;
                case ORDER_WAITING_FOR_DROPOFF:
                    //等待乘客下车
                    buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                    //等待乘客下车,开始倒计时发下巡游单
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                    }
                    break;
                case ORDER_DROPOFF_COMPLETED:
                    //下车完成
                    buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode());
                    // 下发巡游任务
                    R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId));
                    if(xpOrderR.getCode()==200){
                        XpOrder orderData = xpOrderR.getData();
                        Long vehicleId =orderData.getVehicleId();
                        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId);
                        if(xpVehicleR.getData()!=null){
                            XpVehicle xpVehicle = xpVehicleR.getData();
                            //订单结束,在添加导航数据之前先将车辆状态修改为空闲
                            xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
                            xpVehicle = xpVehicleClient.queryById(vehicleId).getData();
                            AddCruiseMissionDto addCruiseMissionDto = new AddCruiseMissionDto();
                            addCruiseMissionDto.setOrder(orderData);
                            addCruiseMissionDto.setVehicle(xpVehicle);
                            xpCruiseOrderClient.addCruiseMission(addCruiseMissionDto);
                        }
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode());
                    }
                    break;
                case ORDER_COMPLETED:
@@ -862,12 +858,16 @@
                    break;
                case ORDER_CANCELLED:
                    //已取消
                    buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.CANCELED.getCode());
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.CANCELED.getCode());
                    }
                    break;
                case ORDER_ARRIVED_AT_CRUISE_DESTINATION:
                    //到达巡游终点
                    buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
                    if(orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.COMPLETED, sequence);
                    }
                    break;
                case ORDER_PAUSED:
                    //订单暂停
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -217,7 +217,7 @@
        }
//        // 算距离
        // 算距离
        R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
        if (distanceAndDuration.getCode() != 200) {
            throw new ServiceException("获取导肮信息失败", I18nKeyConstant.PATH_NOT_FOUND);
@@ -310,35 +310,7 @@
        // 8. 构建响应对象
        RouteAndFareVo routeAndFareVo = new RouteAndFareVo();
        // MOCK数据
//        RouteVo routeVo = new RouteVo();
//        routeVo.setDistance(3000);
//        routeVo.setDuration(5);
//        routeVo.setRouteID("1");
//        List<LonLatDto> routePolyline = Arrays.asList(
//                // 起点:天府新谷
//                new LonLatDto(104.05363, 30.58937),
//
//                // 途经点1:府城大道与交子北二路交叉口附近
//                new LonLatDto(104.05821, 30.58745),
//
//                // 途经点2:交子大道与成汉南路交叉口
//                new LonLatDto(104.06418, 30.58492),
//
//                // 途经点3:交子大道与万象南路交叉口
//                new LonLatDto(104.06975, 30.58321),
//
//                // 途经点4:交子大道与益州大道交叉口
//                new LonLatDto(104.07366, 30.58198),
//
//                // 终点:金融城(地铁站附近)
//                new LonLatDto(104.076544, 30.581039)
//        );
//        routeVo.setPolyline(routePolyline);
        routeAndFareVo.setRoute(routeVo);
        routeAndFareVo.setXpPricingCard(xpPricingCardVo);
        FareVo fareVo = new FareVo();
@@ -393,8 +365,6 @@
        redisService.setCacheObject(key, voJsonStr, 5l, TimeUnit.MINUTES);
        //缓存导航数据,用于下单后推送导航给车端和乘客端
        redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + userId, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
        return routeAndFareVo;
    }
@@ -562,18 +532,6 @@
        xpOrder.setCreateTime(LocalDateTime.now());
        // 计算距离 和 时间
        RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
        LonLatDto lonLatDto = new LonLatDto();
        lonLatDto.setLongitude(xpPoint.getPointLon());
        lonLatDto.setLatitude(xpPoint.getPointLat());
        routeAndFareDto.setOrigin(lonLatDto);
        LonLatDto lonLatDto1 = new LonLatDto();
        lonLatDto1.setLongitude(endXpPoint.getPointLon());
        lonLatDto1.setLatitude(endXpPoint.getPointLat());
        routeAndFareDto.setDestination(lonLatDto1);
        XpOpenCity openCities = xpOpenCityMapper.selectById(dto.getOpenCityId());
        if (openCities == null) {
            throw new ServiceException("获取城市信息失败", I18nKeyConstant.CITY_NOT_FOUND);
@@ -582,18 +540,15 @@
        dto.setOpenCityId(xpOpenCity.getId());
        xpOrder.setCityCode(xpOpenCity.getCityCode());
        XpRoutePlan xpRoutePlan = xpRoutePlanMapper.selectOne(new LambdaQueryWrapper<XpRoutePlan>().eq(XpRoutePlan::getAuditStatus, 2).eq(XpRoutePlan::getCityCode, xpOpenCity.getCityCode()));
        if (xpRoutePlan != null) {
            routeAndFareDto.setRoutePlanRule(xpRoutePlan.getRoutePlanRule());
        }
        R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
        Integer distance = 0;
        Integer duration = 0;
        if (distanceAndDuration.getCode() != 200) {
//            throw new ServiceException("订单生成失败", I18nKeyConstant.ORDER_CREATE_FAIL);
        Object cacheObject = redisService.getCacheObject("ORDER_NAVIGATION_END_DATA:" + uid);
        if (cacheObject != null) {
            RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
            distance = routeVo.getDistance();
            duration = routeVo.getDuration();
        }
//        distance = distanceAndDuration.getData().getDistance();
//        duration = distanceAndDuration.getData().getDuration();
        // 产生订单
        R<Long> addOrderR = xpOrderClient.addOrder(xpOrder);
@@ -626,7 +581,7 @@
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < maxPushDistance) {
                String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + routeAndFareDto.getRoutePlanRule();
                String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule();
                if (isPriorityDispatch) {
                    // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                    redisService.addToHead(s, value);
@@ -654,7 +609,7 @@
        }
        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()));
        redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule()));
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
@@ -670,17 +625,6 @@
        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
        geoQueryEntityService.save(xpGeoQueryEntity);
        return orderId.toString();
//
//        XpElectronicFenceArea xpElectronicFenceArea = xpElectronicFenceAreaMapper.selectById(dto.getXpElectronicFenceAreaId());
//        // 获取电子围栏的车辆
//        R<List<XpVehicle>> vehicles = xpVehicleClient.listByFenceId(xpElectronicFenceArea.getElectronicId());
//
        // 产生订单  存订单数据  // 下发指令  消息推送用户端
//        return null;
    }
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java
@@ -58,8 +58,8 @@
    @PostMapping("/api/v1/vehicleRepair/saveReturnRepair")
    public R<String> saveReturnRepair(@Validated @RequestBody XpVehicleRepairReturnDTO dto) {
        Long id = tokenService.getLoginOperationUser().getId();
        if (dto.getRepairMoney().toString().length() > 200) {
            throw new ServiceException("维修费用不能超过200字符", I18nKeyConstant.REPAIR_MONEY_TOO_LONG);
        if (dto.getRepairMoney()>99999999.99) {
            throw new ServiceException("维修费用不能超过10字符", I18nKeyConstant.REPAIR_MONEY_TOO_LONG);
        }
        xpVehicleRepairService.saveReturnRepair(dto,id);
        return R.ok();
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpVehicleRepairServiceImpl.java
@@ -240,5 +240,6 @@
        xpVehicleRepair.setRepairMoneyDetail(dto.getRepairMoneyDetail());
        xpVehicleRepair.setReturnUserId(id);
        xpVehicleRepair.setReturnTime(LocalDateTime.now());
        this.updateById(xpVehicleRepair);
    }
}
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -2,4 +2,4 @@
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
repair.money.too.long=维修费用不能超过200字符
repair.money.too.long=维修费用不能超过10字符
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -2,5 +2,5 @@
welcome.message=Welcome to our application!
task.not.exist=The task does not exist.
vehicle.not.exist=The vehicle does not exist.
repair.money.too.long=The maintenance cost cannot exceed 200 characters
repair.money.too.long=The maintenance cost cannot exceed 10 characters
task.rule.not.config=The vehicle accident task allocation rules have not been configured
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -2,5 +2,5 @@
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
repair.money.too.long=维修费用不能超过200字符
repair.money.too.long=维修费用不能超过10字符
task.rule.not.config=未配置车辆事故任务分配规则
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java
@@ -32,200 +32,8 @@
    @Autowired
    private XpGeoFencingPolygonService xpGeoFencingPolygonService;
    // 自定义线程池配置
    private static final int CORE_POOL_SIZE = 5;  // 核心线程数
    private static final int MAX_POOL_SIZE = 10;  // 最大线程数
    private static final long KEEP_ALIVE_TIME = 60L; // 线程空闲存活时间
    private static final int QUEUE_CAPACITY = 100; // 阻塞队列容量
    // 创建自定义线程池
    private final ExecutorService customThreadPool = new ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_SIZE,
            KEEP_ALIVE_TIME,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(QUEUE_CAPACITY),
            new ThreadFactory() {
                private final AtomicInteger threadNumber = new AtomicInteger(1);
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "route-check-thread-" + threadNumber.getAndIncrement());
                    t.setDaemon(true); // 设置为守护线程,避免应用关闭时线程未停止
                    return t;
                }
            },
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略:调用线程执行
    );
//    public RouteVo getDistanceAndTime(LonLatDto start, LonLatDto end, String avoidRoads, String fenceId, Integer routePlanRule) {
//        RouteVo routeVo = new RouteVo();
//
//        String url = "https://tsapi.amap.com/v1/route/price?key=" + key + "&extensions=all&start=" + start.getLongitude() + "," + start.getLatitude();
//        HashMap<String, Object> params = new HashMap<>();
//        params.put("extensions", "all");
//        params.put("start", start.getLongitude() + "," + start.getLatitude());
//        params.put("end", end.getLongitude() + "," + end.getLatitude());
//        params.put("routeUserType", 2);
//        if (avoidRoads != null && !avoidRoads.isEmpty()) {
//            params.put("voidPolygons", avoidRoads);
//        }
//        if (routePlanRule != null) {
//            params.put("strategy", routePlanRule);
//        }
//
//        String post = HttpUtils.post(url, JSON.toJSONString(params));
//        System.out.println("高德地图返回结果:" + post);
//
//        JSONObject jsonObject = JSON.parseObject(post);
//        String data = jsonObject.getString("data");
//        JSONObject jsonObject1 = JSON.parseObject(data);
//        JSONArray path = jsonObject1.getJSONArray("paths");
//
//        if (path == null || path.isEmpty()) {
//            return null;
//        }
//
//        // 使用自定义线程池并行处理每个路径的围栏检查
//        List<Future<PathCheckResult>> futures = new ArrayList<>();
//        CountDownLatch latch = new CountDownLatch(path.size()); // 用于等待所有任务完成
//
//        // 提交每个路径的处理任务
//        for (int j = 0; j < path.size(); j++) {
//            final int index = j;
//            JSONObject pathObject = path.getJSONObject(index);
//
//            Future<PathCheckResult> future = customThreadPool.submit(() -> {
//                try {
//                    PathCheckResult result = new PathCheckResult();
//                    result.setIndex(index);
//                    result.setPathObject(pathObject);
//
//                    String points = pathObject.getString("points");
//                    String[] split = points.split(";");
//
//                    // 检查点位是否在围栏内
//                    boolean inFence = checkPointsInFence(split, fenceId);
//                    result.setInFence(inFence);
//
//                    return result;
//                } finally {
//                    latch.countDown(); // 任务完成,计数器减1
//                }
//            });
//
//            futures.add(future);
//        }
//
//        try {
//            // 等待所有任务完成,设置超时时间
//            if (!latch.await(10, TimeUnit.SECONDS)) {
//                System.out.println("路径检查任务超时");
//                // 取消所有未完成的任务
//                for (Future<PathCheckResult> future : futures) {
//                    if (!future.isDone()) {
//                        future.cancel(true);
//                    }
//                }
//            }
//        } catch (InterruptedException e) {
//            Thread.currentThread().interrupt();
//            System.out.println("路径检查任务被中断");
//            return null;
//        }
//
//        // 收集处理结果,找到第一个不在围栏内的路径
//        PathCheckResult validPathResult = null;
//
//        for (Future<PathCheckResult> future : futures) {
//            try {
//                if (future.isDone() && !future.isCancelled()) {
//                    PathCheckResult result = future.get();
//                    if (!result.isInFence()) {
//                        validPathResult = result;
//                        break; // 找到有效的就停止
//                    }
//                }
//            } catch (InterruptedException | ExecutionException e) {
//                System.out.println("获取路径检查结果失败: " + e.getMessage());
//                e.printStackTrace();
//            }
//        }
//
//        // 如果找到了有效路径,处理该路径数据
//        if (validPathResult != null) {
//            JSONObject validPath = validPathResult.getPathObject();
//            String routeID = validPath.getString("routeID");
//            String points = validPath.getString("points");
//            String[] split = points.split(";");
//
//            Integer costTime = validPath.getInteger("costTime");
//            Integer distance = validPath.getInteger("distance");
//
//            routeVo.setDistance(distance);
//            routeVo.setDuration(costTime);
//
//            ArrayList<LonLatDto> lonLatDtos = new ArrayList<>(split.length);
//            for (String s : split) {
//                String[] split1 = s.split(",");
//                LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]));
//                lonLatDtos.add(lonLatDto);
//            }
//            routeVo.setPolyline(lonLatDtos);
//            routeVo.setRouteID(routeID);
//
//            return routeVo;
//        }
//
//        return null;
//    }
    /**
     * 路径检查结果内部类
     */
    private static class PathCheckResult {
        private int index;
        private JSONObject pathObject;
        private boolean inFence; // true: 所有点都在围栏内, false: 有点不在围栏内
        public int getIndex() {
            return index;
        }
        public void setIndex(int index) {
            this.index = index;
        }
        public JSONObject getPathObject() {
            return pathObject;
        }
        public void setPathObject(JSONObject pathObject) {
            this.pathObject = pathObject;
        }
        public boolean isInFence() {
            return inFence;
        }
        public void setInFence(boolean inFence) {
            this.inFence = inFence;
        }
    }
    /**
     * 检查路径点位是否在围栏内
     */
    private boolean checkPointsInFence(String[] points, String fenceId) {
        // 取5分之一的点位进行检查
        for (int i = 0; i < points.length; i++) {
            if (i % 5 == 0) {
                String[] split1 = points[i].split(",");
                LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]));
                if (!xpGeoFencingPolygonService.isInFence(lonLatDto.getLongitude(), lonLatDto.getLatitude(), fenceId, "operating_area")) {
                    return false; // 有点位不在围栏内
                }
            }
        }
        return true; // 所有检查的点都在围栏内
    }
    /**
     * 根据起始点获取驾车距离 和 时间  以及避让区域
@@ -263,23 +71,22 @@
        JSONObject jsonObject1 = JSON.parseObject(data);
        JSONArray path = jsonObject1.getJSONArray("paths");
        log.info("开始判断导航路径是否在运营区域范围内 {}", fenceId);
        for (Object o : path) {
            JSONObject jsonObject2 = (JSONObject) o;
            String routeID = jsonObject2.getString("routeID");
            String points = jsonObject2.getString("points");
            String[] split = points.split(";");
            int temp=0;
            // 取5分之一的点位
            for (int i = 0; i < split.length; i++) {
                if (i % 10 == 0) {
                    String[] split1 = split[i].split(",");
                    LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]));
                    if (!xpGeoFencingPolygonService.isInFence(lonLatDto.getLongitude(), lonLatDto.getLatitude(), fenceId, "operating_area")) {
                        temp++;
                        break;
                    }
                }
            List<LonLatDto> pointsArray = new ArrayList<>();
            for (String string : split) {
                String[] split1 = string.split(",");
                LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split1[0]), Double.parseDouble(split1[1]));
                pointsArray.add(lonLatDto);
            }
            ForkJoinPool pool = new ForkJoinPool(); // 创建ForkJoinPool对象(默认使用处理器的核心数作为线程池大小)
            ArrayPointsTask arrayPointsTask = new ArrayPointsTask(pointsArray, fenceId); // 创建求和任务对象并传入数组作为参数(这里也可以传入数组的一部分作为参数来实现更细粒度的拆分)
            Long temp = pool.invoke(arrayPointsTask); // 提交任务并等待处理完成(也可以使用submit方法提交任务并获取一个Future对象来异步获取结果)
            pool.shutdown(); // 关闭ForkJoinPool(释放资源)
            if(temp==0){
                Integer costTime = jsonObject2.getInteger("costTime");
                Integer distance = jsonObject2.getInteger("distance");
@@ -293,15 +100,54 @@
                }
                routeVo.setPolyline(lonLatDtos);
                routeVo.setRouteID(routeID);
                log.info("导航 {} 在 {} 运营区域内", routeVo.getRouteID(), fenceId);
                return routeVo;
            }
        }
        return null;
    }
    class ArrayPointsTask extends RecursiveTask<Long>{
        //最大定位集合阈值
        private final int THRESHOLD = 10;
        //围栏ID
        String fenceId;
        //定位点集合
        List<LonLatDto> pointsArray;
        public ArrayPointsTask(List<LonLatDto> pointsArray, String fenceId) {
            this.pointsArray = pointsArray;
            this.fenceId = fenceId;
        }
        @Override
        protected Long compute() {
            if(this.pointsArray.size() > THRESHOLD){
                int num = this.pointsArray.size() / 2;
                ArrayPointsTask task1 = new ArrayPointsTask(this.pointsArray.subList(0, num), fenceId);
                ArrayPointsTask task2 = new ArrayPointsTask(this.pointsArray.subList(num, this.pointsArray.size()), fenceId);
                task1.fork();
                task2.fork();
                return task1.join() + task2.join();
            }else{
                long temp = 0;
                for (LonLatDto lonLatDto : this.pointsArray) {
                    if (!xpGeoFencingPolygonService.isInFence(lonLatDto.getLongitude(), lonLatDto.getLatitude(), fenceId, "operating_area")) {
                        temp++;
                        break;
                    }
                }
                return temp;
            }
        }
    }
    /**
     * 线路还原接口
     * 车端使用的数据
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/base/AbstractJob.java
@@ -2,6 +2,7 @@
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.order.service.IXpCruiseOrderService;
@@ -26,6 +27,7 @@
    protected IXpCruiseOrderService xpCruiseOrderService;
    protected OrderMissionClient orderMissionClient;
    protected XpVehicleClient xpVehicleClient;
    protected UserVehicleClient userVehicleClient;
    public AbstractJob(){
        this.xpOrderService = SpringContextsUtil.getBean(IXpOrderService.class);
        this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class);
@@ -33,6 +35,7 @@
        this.xpCruiseOrderService = SpringContextsUtil.getBean(IXpCruiseOrderService.class);
        this.orderMissionClient = SpringContextsUtil.getBean(OrderMissionClient.class);
        this.xpVehicleClient = SpringContextsUtil.getBean(XpVehicleClient.class);
        this.userVehicleClient = SpringContextsUtil.getBean(UserVehicleClient.class);
    }
     
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/AddCruiseMissionJob.java
@@ -5,6 +5,7 @@
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.order.job.base.AbstractJob;
import lombok.extern.slf4j.Slf4j;
@@ -29,26 +30,23 @@
            throws JobExecutionException {
        JobDataMap maps = context.getMergedJobDataMap();
        Long orderId = maps.getLong("id");
        try {
            log.info("开始执行添加任务");
            XpCruiseOrder xpCruiseOrder = xpCruiseOrderService.getById(orderId);
            R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpCruiseOrder.getVehicleId());
            if(xpVehicleR.getData().getState()==0){
                PushOrderDto pushOrderDto = new PushOrderDto();
                pushOrderDto.setVin(xpCruiseOrder.getVehicleVin());
                pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId());
                pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat());
                pushOrderDto.setStartLongitude(xpCruiseOrder.getStartLon());
                pushOrderDto.setEndLatitude(xpCruiseOrder.getEndLat());
                pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon());
                pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
                pushOrderDto.setStage(2);
                // 调用推送服务  orderId + carVin
                orderMissionClient.pushOrder(pushOrderDto);
            }
        }catch(Exception e){
            e.printStackTrace();
        }
        String appid = maps.getString("appid");
        XpOrder xpOrder = xpOrderService.getById(orderId);
        // 解绑用户与车辆关系
        CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
        XpVehicle vehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
        if (vehicle != null) {
            cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin());
            cancelTaxiPassengerVo.setUid(xpOrder.getAppUserId().toString());
            cancelTaxiPassengerVo.setOrderNo(xpOrder.getOrderNumber());
            cancelTaxiPassengerVo.setAppId(appid);
            userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
            // 修改车辆接单状态
            vehicle.setState(0);
            xpVehicleClient.updateVehicleById(vehicle);
        }
        xpOrderService.addCruiseMission(vehicle, xpOrder);
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/EndTripJob.java
@@ -3,6 +3,7 @@
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpOrderTimeoutLog;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.order.job.base.AbstractJob;
import lombok.extern.slf4j.Slf4j;
@@ -25,19 +26,18 @@
            throws JobExecutionException {
        JobDataMap maps = context.getMergedJobDataMap();
        Long orderId = maps.getLong("id");
        try {
        try {
            log.info("开始执行自动结束行程任务");
            XpOrder xpOrder = xpOrderService.getById(orderId);
            xpOrderService.endTrip(xpOrder.getId(), String.valueOf(xpOrder.getAppUserId()));
            if(xpOrder.getStatus() == 7){
                xpOrderService.endTrip(xpOrder.getId(), String.valueOf(xpOrder.getAppUserId()));
            }
            log.info("结束执行自动结束行程任务");
            // 添加超时记录
            XpOrderTimeoutLog xpOrderTimeoutLog = new XpOrderTimeoutLog();
            xpOrderTimeoutLog.setOrderId(xpOrder.getId());
            xpOrderTimeoutLog.setUserId(xpOrder.getAppUserId());
            xpOrderTimeoutLogService.save(xpOrderTimeoutLog);
            R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpOrder.getVehicleId());
            xpOrderService.addCruiseMission(xpVehicleR.getData(),xpOrder);
        }catch(Exception e){
            e.printStackTrace();
        }
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -1381,7 +1381,9 @@
        if (xpOrder.getStatus() == 0) {
            return R.fail("订单已取消");
        }
        xpOrder.setStatus(status);
        if(xpOrder.getStatus() >= 8){
            return R.fail("订单已结束");
        }
        switch (status) {
            case 4:
                // 查询起点点位
@@ -1412,37 +1414,51 @@
                xpOrder.setTripBegin(LocalDateTime.now());
                break;
            case 7:
                // 查询自动结束行程时间
                if (xpOrder.getOpenTrunk() != 1) {
                    Integer arriveTime = xpSystemSettingClient.getOrderFinishTime().getData();
                    // 添加自动结束行程定时任务job
                    Map<String, ? extends Object> endTripJobMaps =
                            new ImmutableMap.Builder<String, Long>().
                                    put("id", xpOrder.getId())
                                    .build();
                    QuartzManager.addJob(
                            EndTripJob.class,
                            (EndTripJob.name + xpOrder.getId()).toUpperCase(),
                            TimeJobType.END_TRIP,
                            DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(arriveTime)),
                            endTripJobMaps
                    );
                    // 推送倒计时消息
                    Map<String, Object> params = new HashMap<>();
                    Map<String, Object> content = new HashMap<>();
                    content.put("orderId", xpOrder.getId().toString());
                    content.put("isOpen", 1);
                    params.put("type", PushMessageTypeEnum.OPEN_TRUNK.getDesc());
                    params.put("content", JSONObject.toJSONString(content));
                    params.put("timestamp", new Date().getTime() + "");
                    String message = JSONObject.toJSONString(params);
                    SendMessageDTO sendMessageDTO = new SendMessageDTO();
                    sendMessageDTO.setMessage(message);
                    sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId()));
                    xpPushMessageClient.sendStatus(sendMessageDTO);
                }
                Integer arriveTime = xpSystemSettingClient.getOrderFinishTime().getData();
                // 添加自动结束行程定时任务job
                Map<String, ? extends Object> endTripJobMaps =
                        new ImmutableMap.Builder<String, String>()
                                .put("id", xpOrder.getId().toString())
                                .put("appid", appid)
                                .build();
                QuartzManager.addJob(
                        EndTripJob.class,
                        (EndTripJob.name + xpOrder.getId()).toUpperCase(),
                        TimeJobType.END_TRIP,
                        DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(arriveTime)),
                        endTripJobMaps
                );
                // 添加车辆到达终点后限停时间到后驶离的定时任务
                //时间到后添加巡游订单,解绑车辆关系,车辆驶离点位
                XpPoint point = xpPointClient.queryById(xpOrder.getEndPointId()).getData();
                Map<String, ? extends Object> jobMaps =
                        new ImmutableMap.Builder<String, String>()
                                .put("id", xpOrder.getId().toString())
                                .put("appid", appid)
                                .build();
                QuartzManager.addJob(
                        AddCruiseMissionJob.class,
                        (AddCruiseMissionJob.name + xpOrder.getId()).toUpperCase(),
                        TimeJobType.ADD_CRUISE_MISSION,
                        DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(point.getParkingTimeLimit())),
                        jobMaps
                );
                // 推送倒计时消息
                Map<String, Object> params = new HashMap<>();
                Map<String, Object> content = new HashMap<>();
                content.put("orderId", xpOrder.getId().toString());
                content.put("isOpen", 1);
                params.put("type", PushMessageTypeEnum.OPEN_TRUNK.getDesc());
                params.put("content", JSONObject.toJSONString(content));
                params.put("timestamp", new Date().getTime() + "");
                String message = JSONObject.toJSONString(params);
                SendMessageDTO sendMessageDTO = new SendMessageDTO();
                sendMessageDTO.setMessage(message);
                sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId()));
                xpPushMessageClient.sendStatus(sendMessageDTO);
                break;
        }
        xpOrder.setStatus(status);
        xpOrder.setAppUserId(null);
        this.updateById(xpOrder);
        return R.ok();
@@ -1477,24 +1493,7 @@
        exactMinutes = new BigDecimal(exactMinutes).setScale(2, RoundingMode.HALF_UP).doubleValue();
        order.setDuration(exactMinutes);
//        order.setMileageKilometers(80.0);
        baseMapper.updateById(order);
        // 解绑用户与车辆关系
        CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
        XpVehicle vehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
        if (vehicle != null) {
            cancelTaxiPassengerVo.setVin(vehicle.getVehicleVin());
            cancelTaxiPassengerVo.setUid(uid);
            cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
            // TODO 加配置文件取
            cancelTaxiPassengerVo.setAppId(appid);
            userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
            // 修改车辆接单状态
            vehicle.setState(0);
            xpVehicleClient.updateVehicleById(vehicle);
        }
        // 根据订单所属开通城市id 查询定价
        R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCid(order.getCityId());
@@ -1514,9 +1513,6 @@
            TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime());
            gpsPoints.add(point);
        }
//         补充临时轨迹数据
//        List<TaxiPricingDemoService.GpsPoint> gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime()));
        TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig();
        JSONArray startingFareJsonArray = JSONArray.parseArray(pricing.getStartingFareJson());
@@ -1535,16 +1531,7 @@
            Double duration1 = order.getDuration();
            com.alibaba.fastjson.JSONObject basicPricingJson = com.alibaba.fastjson.JSONObject.parseObject(pricing.getBasicPricingJson());
//            String num1 = "00:00";
//            String num2 = "23:59";
//            String num3 = basicPricingJson.getString("num1");
//            String num4 = basicPricingJson.getString("num2");
//            String num5 = basicPricingJson.getString("num3");
//            String num6 = basicPricingJson.getString("num4");
//            String num7 = basicPricingJson.getString("num5");
//            config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7)));
//            paramNum4 = basicPricingJson.getDouble("num2");
//            paramNum5 = basicPricingJson.getDouble("num3");
            XpPricingCardVo xpPricingCardVo = xpPricingUtil.calculationFixedPrice(orderAppUserId.toString(), basicPricingJson, null, mileageKilometers, duration1, 0, 0.0, pricing.getIsDynamicPrice(), order.getCityId(), pricing.getDynamicPricingJson());
            XpOrderDetail xpOrderDetail = new XpOrderDetail();
            xpOrderDetail.setDetailType(1);
@@ -1577,11 +1564,7 @@
            order.setOrderMoney(totalPrice);
            order.setAppUserId(null);
            baseMapper.updateById(order);
        } else {
            //动态计费
            if (pricing.getPricingType() == 1) {
@@ -1831,18 +1814,7 @@
                BigDecimal add = order.getDurationMoney().add(fareBreakdownDetailVo.getMoney());
                order.setDurationMoney(add);
            }
//        for (XpOrderDetail xpOrderDetail : xpOrderDetails) {
//            if (xpOrderDetail.getDetailType() == 1) {
//                order.setDurationType(xpOrderDetail.getType());
//                order.setDurationMoney(xpOrderDetail.getMoney());
////                order.setDuration(Double.parseDouble(xpOrderDetail.getDuration() + ""));
//            } else {
//                order.setLongDistanceType(order.getDurationType());
//                order.setLongDistance(xpOrderDetail.getMileage().doubleValue());
//                order.setLongDistancemoney(xpOrderDetail.getMoney());
//            }
//
//        }
            BigDecimal orderMoney = startMoney.add(mileageMoney).add(order.getDurationMoney() != null ? order.getDurationMoney() : BigDecimal.ZERO)
                    .add(order.getLongDistancemoney() != null ? order.getLongDistancemoney() : BigDecimal.ZERO)
@@ -1875,87 +1847,6 @@
        }
        order.setAppUserId(null);
        baseMapper.updateById(order);
        // 结束后的车辆操作
        if (vehicle != null) {
            // 修改车辆状态
            vehicle.setState(0);
            //发送巡游订单
            addCruiseMission(vehicle, order);
//            // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作
//            R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail();
//            XpTaskRule xpTaskRule = xpTaskRuleR.getData();
//
//            // 生成新的巡游单子 回到最新巡游的初始起点位置
//            XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
//            int temp=0;
//            if(xpCruiseOrders==null){
//                temp=1;
//                //特殊情况 可能没有产生终止的订单  (到站点就被正常接单了)所以找正常订单
//                xpCruiseOrders=xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 3).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
//            }
//            XpCruiseOrder xpCruiseOrder = new XpCruiseOrder();
//            xpCruiseOrder.setVehicleId(vehicle.getId());
//            xpCruiseOrder.setFleetId(vehicle.getFleetId());
//            xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin());
//            xpCruiseOrder.setOrderType(2);
//            // 返程起点是当前正常订单的终点
//            xpCruiseOrder.setStartPointId(order.getEndPointId());
//            xpCruiseOrder.setStartPointName(order.getEndPointName());
//            xpCruiseOrder.setStartLon(order.getEndLon());
//            xpCruiseOrder.setStartLat(order.getEndLat());
//
//            // 完成的直接走终点   终止的走起点
//            if(temp==0){
//                xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId());
//                xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName());
//                xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon());
//                xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat());
//            }else {
//                xpCruiseOrder.setEndPointId(xpCruiseOrders.getEndPointId());
//                xpCruiseOrder.setEndPointName(xpCruiseOrders.getEndPointName());
//                xpCruiseOrder.setEndLon(xpCruiseOrders.getEndLon());
//                xpCruiseOrder.setEndLat(xpCruiseOrders.getEndLat());
//            }
//
//
//            xpCruiseOrder.setStatus(0);
//            xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId());
//            xpCruiseOrder.setCreateTime(LocalDateTime.now());
//            xpCruiseOrder.setId("XU"+ IdUtil.fastUUID());
//
//            // 判断当前时分秒是否大于收车时间
//            LocalTime vehicleCollectionTime = xpTaskRule.getVehicleCollectionTime();
//            if (vehicleCollectionTime.isBefore(LocalTime.now())) {
//                vehicle.setOperatingStatus(3);
//                //找到车辆的收车点位 更新终点点位
//                R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
//                xpCruiseOrder = returnCruisePoint.getData();
//            }
//            xpVehicleClient.updateVehicleById(vehicle);
//
//            xpCruiseOrderMapper.insert(xpCruiseOrder);
//
//
//            R<XpPoint> xpPointR = xpPointClient.queryById(order.getEndPointId());
//            XpPoint data = xpPointR.getData();
//            //下发命令
//            // 添加自动结束行程定时任务job
//            Map<String, ? extends Object> jobMaps =
//                    new ImmutableMap.Builder<String, String>().
//                            put("id", xpCruiseOrder.getId())
//                            .build();
//            QuartzManager.addJob(
//                    AddCruiseMissionJob.class,
//                    (AddCruiseMissionJob.name + xpCruiseOrder.getId()).toUpperCase(),
//                    TimeJobType.ADD_CRUISE_MISSION,
//                    DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(data.getParkingTimeLimit())),
//                    jobMaps
//            );
        }
    }
@@ -1967,6 +1858,7 @@
     */
    public void addCruiseMission(XpVehicle vehicle, XpOrder order) {
        log.info("添加巡游订单 {}", vehicle.getPlateNumber());
        if (vehicle.getState() != 0 || vehicle.getOperatingStatus() != 1) {
            log.info("添加巡游单失败,车辆状态限制 {}", vehicle.getState());
            return;
@@ -2051,25 +1943,20 @@
            }
            xpVehicleClient.updateVehicleById(vehicle);
        }
        xpCruiseOrderMapper.insert(xpCruiseOrder);
        R<XpPoint> xpPointR = xpPointClient.queryById(order.getEndPointId());
        XpPoint data = xpPointR.getData();
        //下发命令
        // 添加自动结束行程定时任务job
        Map<String, ? extends Object> jobMaps =
                new ImmutableMap.Builder<String, String>().
                        put("id", xpCruiseOrder.getId() + "")
                        .build();
        QuartzManager.addJob(
                AddCruiseMissionJob.class,
                (AddCruiseMissionJob.name + xpCruiseOrder.getId()).toUpperCase(),
                TimeJobType.ADD_CRUISE_MISSION,
                DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(data.getParkingTimeLimit())),
                jobMaps
        );
        log.info("添加巡游单成功 {}", xpCruiseOrder.getId());
        //下发XUP巡游订单报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setVin(xpCruiseOrder.getVehicleVin());
        pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId());
        pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat());
        pushOrderDto.setStartLongitude(xpCruiseOrder.getStartLon());
        pushOrderDto.setEndLatitude(xpCruiseOrder.getEndLat());
        pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon());
        pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
        pushOrderDto.setStage(2);
        orderMissionClient.pushOrder(pushOrderDto);
        log.info("下发XUP巡游订单报文成功");
    }
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/XpVehicleVO.java
@@ -24,7 +24,7 @@
    private String fleetName;
    @ApiModelProperty(value = "下次保养时间")
    @JsonFormat(pattern = "yyyy-MM-dd",timezone = "GMT+8")
    @JsonFormat(pattern = "yyyy年M月dd日",timezone = "GMT+8")
    private LocalDate nextMaintenanceTime;
    @ApiModelProperty(value = "车辆经度")