liujie
2026-06-09 c96fbe6b0aeb413a17c429133ee6d81d138144b9
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -37,6 +37,9 @@
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.enums.PushMessageTypeEnum;
import com.xiaopeng.common.core.utils.SensitiveDataCryptoUtil;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.operation.config.UidVinBindingConfig;
import com.xiaopeng.operation.dto.PriorityMatchResult;
@@ -57,6 +60,7 @@
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
@@ -162,8 +166,19 @@
                    // 状态改为处理中
                    redisService.updateFirst(name, value);
                    threadPoolTaskExecutor.submit(() -> {
                        log.info("订单处理:{}", firstElement);
                        orderProcess(name, firstElement.toString(), false);
                    });
                }else{
                    //判断订单状态,如果不是待接单,则将数据清除
                    String orderId = split[0];
                    XpOrder xpOrder = xpOrderClient.queryOrderById(Long.valueOf(orderId)).getData();
                    if(xpOrder.getStatus() != OrderStatusEnum.PENDING_ORDER.getCode()){
                        if(StringUtils.isNotEmpty((xpOrder.getQueueName()))){
                            redisService.removeByPattern(xpOrder.getQueueName(), xpOrder.getOrderNumber());
                        }
                    }
                }
            }
        }
@@ -182,12 +197,23 @@
                String[] split = firstElement.toString().split("_");
                // 如果未处理 创建新任务
                if (split[2].equals("0")) {
                    String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7];
                    String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7] + "_" + split[8];
                    // 状态改为处理中
                    redisService.updateFirst(name, value);
                    threadPoolTaskExecutor.submit(() -> {
                        log.info("定向订单处理:{}", firstElement);
                        orderProcess(name, firstElement.toString(), true);
                    });
                }else{
                    //判断订单状态,如果不是待接单,则将数据清除
                    String orderId = split[0];
                    XpOrder xpOrder = xpOrderClient.queryOrderById(Long.valueOf(orderId)).getData();
                    if(xpOrder.getStatus() != OrderStatusEnum.PENDING_ORDER.getCode()){
                        if(StringUtils.isNotEmpty(xpOrder.getQueueName())){
                            redisService.removeByPattern(xpOrder.getQueueName(), xpOrder.getOrderNumber());
                        }
                    }
                }
            }
        }
@@ -287,8 +313,8 @@
        if (xpOrderR.getCode() == 200) {
            XpOrder xpOrder = xpOrderR.getData();
            if (xpOrder.getStatus() == 1) {
                log.info("五轮推单结束,无车辆接单,执行取消订单 {}", orderNo);
                xpOrderClient.cancelOrder(orderId);
                log.info("五轮推单结束,无车辆接单,执行取消订单 {}", orderNo);
                //推送订单状态给乘客
                SendMessageDTO dto = new SendMessageDTO();
                dto.setAppUserId(xpOrder.getAppUserId().toString());
@@ -312,9 +338,6 @@
                        }
                    });
                }
                //将订单从队列中移除
                log.info("五轮推单结束,无车辆接单,执行队列移除订单 {}", orderNo);
                redisService.popFirstElement(quoteName);
            }
        }
@@ -346,7 +369,11 @@
        }
        XpOrder xpOrder = xpOrderR.getData();
        if (xpOrder.getStatus() == 0) {
            redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
            log.info("订单已取消,退出退单逻辑 {}", orderNo);
            if(StringUtils.isNotEmpty(quoteName)){
                redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
            }
            return true;
        }
        // 找出围栏id
@@ -406,6 +433,10 @@
                                        PushOrderDto pushOrderDto = new PushOrderDto();
                                        pushOrderDto.setVin(priorityVin);
                                        pushOrderDto.setOrderId(orderCheck.getData().getId().toString());
                                        pushOrderDto.setStartTaskId(orderCheck.getData().getXpuStartTaskId());
                                        pushOrderDto.setEndTaskId(orderCheck.getData().getXpuEndTaskId());
                                        pushOrderDto.setStartWaypointId(orderCheck.getData().getStartPointId());
                                        pushOrderDto.setEndWaypointId(orderCheck.getData().getEndPointId());
                                        pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat());
                                        pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon());
                                        pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat());
@@ -418,7 +449,10 @@
                                                orderCheck.getData().getEndLat(), orderCheck.getData().getEndLon(), orderNo);
                                        orderMissionClient.pushOrder(pushOrderDto);
                                        log.info("[人车订单绑定测试] ====== 派单成功! uid={}, vin={}, orderNo={}, 从队列移除订单 ======", uid, priorityVin, orderNo);
                                        redisService.removeByPattern(quoteName, orderNo);
                                        if(StringUtils.isNotEmpty(quoteName)){
                                            redisService.removeByPattern(quoteName, orderNo);
                                        }
                                        return true;
                                    } else {
                                        log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo);
@@ -488,11 +522,10 @@
            List<String> vehicleVinByTargetedService = xpTargetedServiceVehicleService.getVehicleVinByTargetedService(xpOrderR.getData().getCityCode());
            if(!isTargetedService){
                vehiclePositionVos.getData().removeAll(vehicleVinByTargetedService);
                log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
                log.info("剔除定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
            }else{
                vehicleVinByTargetedService.removeAll(vehiclePositionVos.getData());
                vehiclePositionVos.setData(vehicleVinByTargetedService);
                log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
                log.info("查找定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
            }
            if (vehiclePositionVos.getCode() != 200) {
                continue;
@@ -1045,69 +1078,68 @@
                    }
                    VehiclePositionVo vehiclePositionVo = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getTotal).reversed()).collect(Collectors.toList()).get(0);
//
//                    VehiclePositionVo vehiclePositionVo1 = vehiclePositionVo;
                    RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin());
                    lock.lock(10, TimeUnit.SECONDS);
                    log.info("队列 {} 车辆 {} 单号 {}", quoteName, vehiclePositionVo.getVin(), orderNo);
                    try {
//                        VehiclePosition vehiclePosition = vehiclePositionService.findByVehicleId(vehiclePositionVo.getVehicle_id());
                        R<XpVehicle> vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin());
                        if (vehiclePositionR.getCode() != 200) {
                            continue;
                        }
                        XpVehicle vehiclePosition = vehiclePositionR.getData();
                        log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo);
                        log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getStatus(), orderNo);
                        if (vehiclePosition.getOperatingStatus() != 1 || vehiclePosition.getState() != 0 || vehiclePosition.getVehicleType() == 1) {
                            continue;
                        }
                        if (vehiclePositionR.getCode() == 200) {
                            XpVehicle vehiclePosition = vehiclePositionR.getData();
                            log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo);
                            log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getState(), orderNo);
                        // 再次查询一下订单 看是否取消
                        xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo);
                        if (xpOrderR.getCode() != 200) {
                            continue;
                        }
                        xpOrder = xpOrderR.getData();
                        if (xpOrder.getStatus() != 1) {
                            continue;
                        }
                            String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehiclePosition.getVehicleVin());
                            // 再次查询一下订单 看是否取消
                            xpOrder = xpOrderClient.queryOrderByOrderNo(orderNo).getData();
                            if (xpOrder.getStatus() == 1) {
                                //所有条件满足,走正常派单,不满足走后面的连环派单
                                if (vehiclePosition.getOperatingStatus() == 1 && vehiclePosition.getState() == 0 && vehiclePosition.getVehicleType() == 2) {
                                    //非合作商的车辆需要处理巡游单
                                    if(null == vehiclePosition.getOfficialPartnerId()){
                                        //  关闭巡游单子
                                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin);
                                        if (stringR != null && stringR.getCode() == 200) {
                                            log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo);
                                            XpCruiseOrder cruiseOrder = stringR.getData();
                                            // 下发命令
                                            PushOrderDto pushOrderDto = new PushOrderDto();
                                            pushOrderDto.setVin(vin);
                                            pushOrderDto.setOrderId(xpOrder.getId().toString());
                                            pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId());
                                            pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId());
                                            pushOrderDto.setStartWaypointId(xpOrder.getStartPointId());
                                            pushOrderDto.setEndWaypointId(xpOrder.getEndPointId());
                                            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                                            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                                            pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                                            pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                                            pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                                            pushOrderDto.setOrderType(OrderType.USER_ORDER);
                                            pushOrderDto.setStage(1);
                                            if(null != cruiseOrder){
                                                pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                                                pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                                            }
                                            pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                                            // 调用推送服务  orderId + carVin
                                            orderMissionClient.pushOrder(pushOrderDto);
                                            log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo);
                                        }
                                    }else {
                                        //流量接入-接单推送 合作商的车辆需要调用合作商的订单通知接口
                                        officialPartnerUtil.pushNewOrder(vehiclePosition.getOfficialPartnerId(), xpOrder);
                                    }
                                    if(StringUtils.isNotEmpty(quoteName)){
                                        redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
                                    }
                        //非合作商的车辆需要处理巡游单
                        if(null != vehiclePosition.getOfficialPartnerId()){
                            //  关闭巡游单子
                            R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin());
                            if (stringR == null || stringR.getCode() != 200) {
                                log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber());
                                continue;
                                    log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                                    return true;
                                }
                            }
                            log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo);
                            // 下发命令
                            PushOrderDto pushOrderDto = new PushOrderDto();
                            pushOrderDto.setVin(vehiclePosition.getVehicleVin());
                            pushOrderDto.setOrderId(xpOrder.getId().toString());
                            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                            pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                            pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                            pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                            pushOrderDto.setOrderType(OrderType.USER_ORDER);
                            pushOrderDto.setStage(1);
                            // 调用推送服务  orderId + carVin
                            orderMissionClient.pushOrder(pushOrderDto);
                            log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo);
                        }else {
                            //合作商的车辆需要调用合作商的订单通知接口
                            officialPartnerUtil.pusNewOrder(vehiclePosition.getOfficialPartnerId(), xpOrder);
                        }
                        redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
@@ -1124,61 +1156,195 @@
                    try {
                        // 查询车辆状态
                        R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin);
                        if (vehicleR.getCode() != 200) {
                            continue;
                        }
                        XpVehicle vehicleId1 = vehicleR.getData();
                        log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo);
                        log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo);
                        if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) {
                            continue;
                        }
                        if (vehicleR.getCode() == 200) {
                            XpVehicle vehicleId1 = vehicleR.getData();
                            log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo);
                            log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo);
                            // 再次查询一下订单 看是否取消
                            xpOrder = xpOrderClient.queryOrderByOrderNo(orderNo).getData();
                            if (xpOrder.getStatus() == 1) {
                                // 所有条件满足走正常派单,不满足走循环派单
                                if (vehicleId1.getOperatingStatus() == 1 && vehicleId1.getState() == 0 && vehicleId1.getVehicleType() == 2) {
                                    if(null == vehicleId1.getOfficialPartnerId()){
                                        //  关闭巡游单子
                                        String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicleId1.getVehicleVin());
                                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin);
                                        if (stringR != null && stringR.getCode() == 200) {
                                            log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo);
                                            XpCruiseOrder cruiseOrder = stringR.getData();
                                            PushOrderDto pushOrderDto = new PushOrderDto();
                                            pushOrderDto.setVin(vehiclePosition.getVin());
                                            pushOrderDto.setOrderId(xpOrder.getId().toString());
                                            pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId());
                                            pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId());
                                            pushOrderDto.setStartWaypointId(xpOrder.getStartPointId());
                                            pushOrderDto.setEndWaypointId(xpOrder.getEndPointId());
                                            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                                            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                                            pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                                            pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                                            pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                                            pushOrderDto.setOrderType(OrderType.USER_ORDER);
                                            pushOrderDto.setStage(1);
                                            if(null != cruiseOrder){
                                                pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                                                pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                                            }
                                            pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                                            // 调用推送服务  orderId + carVin
                                            orderMissionClient.pushOrder(pushOrderDto);
                                        }
                                    }else {
                                        //流量接入-接单推送 合作商的车辆需要调用合作商的订单通知接口
                                        officialPartnerUtil.pushNewOrder(vehicleId1.getOfficialPartnerId(), xpOrder);
                                    }
                                    log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber());
                        // 再次查询一下订单 看是否取消
                        xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo);
                        if (xpOrderR.getCode() != 200) {
                            continue;
                        }
                        xpOrder = xpOrderR.getData();
                        if (xpOrder.getStatus() != 1) {
                            continue;
                        }
                                    if(StringUtils.isNotEmpty(quoteName)){
                                        redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
                                    }
                        if(null == vehicleId1.getOfficialPartnerId()){
                            //  关闭巡游单子
                            R<?> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin());
                            if (stringR == null || stringR.getCode() != 200) {
                                log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber());
                                continue;
                                    log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                                    return true;
                                }
                            }
                            log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo);
                            PushOrderDto pushOrderDto = new PushOrderDto();
                            pushOrderDto.setVin(vehiclePosition.getVin());
                            pushOrderDto.setOrderId(xpOrder.getId().toString());
                            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                            pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                            pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                            pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                            pushOrderDto.setOrderType(OrderType.USER_ORDER);
                            pushOrderDto.setStage(1);
                            // 调用推送服务  orderId + carVin
                            orderMissionClient.pushOrder(pushOrderDto);
                        }else {
                            //合作商的车辆需要调用合作商的订单通知接口
                            officialPartnerUtil.pusNewOrder(vehicleId1.getOfficialPartnerId(), xpOrder);
                        }
                        log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber());
                        redisService.popFirstElement(quoteName);
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
            log.info("没有找到空闲车辆 {},尝试连环派单给即将服务结束的车辆", orderNo);
            // 查询状态为1的车辆vin
            R<List<String>> servingVehicles = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount(),1));
            if (servingVehicles.getCode() != 200) {
                continue;
            }
            log.info("连环派单查询车辆结果 {} {}", orderNo, JSON.toJSONString(servingVehicles.getData()));
            if(!isTargetedService){
                servingVehicles.getData().removeAll(vehicleVinByTargetedService);
                log.info("连环派单剔除定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(servingVehicles), orderNo);
            }else{
                servingVehicles.setData(vehicleVinByTargetedService);
                log.info("连环派单查找定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(servingVehicles), orderNo);
            }
            XpTradingStrategyDetailVO strategyDetailVO = tradingStrategyClient.queryById().getData();
            log.info("连环排查推单逻辑 {} {}", orderNo, JSON.toJSONString(strategyDetailVO));
            Integer distanceRegardAsEnding = strategyDetailVO.getDistanceRegardAsEnding();
            Integer timeRegardAsEnding = strategyDetailVO.getTimeRegardAsEnding();
            Integer backupPower = strategyDetailVO.getBackupPower();
            Integer destToPassenger = strategyDetailVO.getDestToPassenger();
            Integer endingTimeToUseTime = strategyDetailVO.getEndingTimeToUseTime();
            for (String vin : servingVehicles.getData()) {
                VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class);
                if(null == vehiclePosition){
                    log.info("连环派单 {} 车辆查询定位数据失败 {}", vin, orderNo);
                    continue;
                }
                XpOrder xpOrder1 = xpOrderClient.queryOrderById(vehiclePosition.getOrderId()).getData();
                String json = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder1.getId().toString()));
                if (StringUtils.isNotEmpty(json)){
                    log.info("车辆已经有连环订单 {} 单号 {}", vin, orderNo);
                    continue;
                }
                Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(xpOrder1.getAppUserId().toString()));
                RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                //距离和时间只要有一个满足条件就达到候选对象
                if (routeRemain.getDuration() > timeRegardAsEnding * 60 && routeRemain.getDistance() > distanceRegardAsEnding * 1000) {
                    log.info("连环派单 {} 车辆订单结束时间不满足条件 {} 秒 {} 米 {}", vin, routeRemain.getDuration(), routeRemain.getDistance(), orderNo);
                    continue;
                }
                //剩余里程》=下一单预估里程+50
                //预估接驾行程+送驾行程
                RouteAndFareDto next = new RouteAndFareDto();
                next.setOrigin(new LonLatDto(xpOrder1.getEndLon(),xpOrder1.getEndLat()));
                next.setDestination(new LonLatDto(xpOrder.getStartLon(),xpOrder.getStartLat()));
                RouteVo route = xpMapClient.getDistanceAndDuration(next).getData();
                Object new_cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(xpOrder.getAppUserId().toString()));
                RouteVo new_routeRemain = JSON.parseObject(new_cacheObject.toString(), RouteVo.class);
                //总续航里程 米
                long xh = new_routeRemain.getDistance() + route.getDistance() + backupPower * 1000;
                if(vehiclePosition.getMileageRange() * 1000 < xh){
                    log.info("连环派单 {} 车辆剩余续航不满足派车条件 {} 米 {}", vin, xh, orderNo);
                    continue;
                }
                //下一单的起点距离本单终点小于X公里,或者下一单的用车时间与本单的预计结束时间偏差小于X分钟
                //上一单的预估结束时间
                LocalDateTime localDateTime = LocalDateTime.now().plusSeconds(routeRemain.getDuration());
                //上一单预估结束时间与本单用车时间差 秒
                long time = localDateTime.toEpochSecond(ZoneOffset.of("+8")) - xpOrder1.getCreateTime().toEpochSecond(ZoneOffset.of("+8"));
                if(route.getDistance() <= destToPassenger * 1000 || time <= endingTimeToUseTime * 60){
                    log.info("连环派单 {} 找到满足条件的车辆 {} 距离 {} 时间 {}", orderNo, vin, route.getDistance(), time);
                    log.info("上一单终点与当前订单起点距离 {} 米 {}", route.getDistance(), orderNo);
                    log.info("当前订单用车时间与上一单预估结束时间偏差 {} 秒 {}", time, orderNo);
                    // 设置接驾导航数据
                    //将上一单的剩余导航添加到接驾导航中
                    route.getPolyline().addAll(0, routeRemain.getPolyline());
                    route.setDuration(route.getDuration() + routeRemain.getDuration());
                    route.setDistance(route.getDistance() + routeRemain.getDistance());
                    //此处找到车后先不忙给车推送接单消息,先修改订单上的车辆信息
                    xpOrder.setVehicleId(xpOrder1.getVehicleId());
                    xpOrder.setAcceptanceTime(LocalDateTime.now());
                    xpOrder.setStatus(2);
                    xpOrderClient.updateOrder(xpOrder);
                    log.info("连环派单 {} 修改订单状态为接单成功 {}", orderNo, xpOrder.getId());
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("orderId", xpOrder.getId());
                    jsonObject.put("endLongitude", xpOrder.getEndLon());
                    jsonObject.put("endLatitude", xpOrder.getEndLat());
                    redisService.setCacheObject(CacheConstants.nextOrder(xpOrder1.getId().toString()), jsonObject.toJSONString());
                    redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), JSON.toJSONString(route));
                    if(StringUtils.isNotEmpty(quoteName)){
                        redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                    }
                    log.info("连环派单 {} 设置下一单接驾导航数据 {}", orderNo, JSON.toJSONString(route));
                    //构建推送消息
                    Map<String, Object> params = new HashMap<>();
                    Map<String, Object> content = new HashMap<>();
                    content.put("orderId", xpOrder.getId().toString());
                    content.put("status", 2);
                    params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc());
                    params.put("content", JSONObject.toJSONString(content));
                    params.put("timestamp", System.currentTimeMillis() + "");
                    String message = JSONObject.toJSONString(params);
                    SendMessageDTO dto1 = new SendMessageDTO();
                    dto1.setAppUserId(xpOrder.getAppUserId() + "");
                    dto1.setMessage(message);
                    R<String> stringR = xpPushMessageClient.sendStatus(dto1);
                    //推送失败,重试3次
                    if (stringR.getCode() != Constants.SUCCESS) {
                        ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>());
                        XpOrder finalXpOrder = xpOrder;
                        executor.execute(() -> {
                            for (int j = 0; j < 3; j++) {
                                R<String> stringR1 = xpPushMessageClient.sendStatus(dto1);
                                if (stringR1.getCode() == Constants.SUCCESS) {
                                    break;
                                }
                                try {
                                    Thread.sleep(1000);
                                } catch (InterruptedException e) {
                                    throw new RuntimeException(e);
                                }
                                log.info("推送订单状态消息失败:{} {} {}", stringR1.getMsg(), JSON.toJSONString(dto1), finalXpOrder.getOrderNumber());
                            }
                        });
                    }
                    return true;
                }
            }
        }
@@ -1211,7 +1377,10 @@
        }
        XpOrder xpOrder = xpOrderR.getData();
        if (xpOrder.getStatus() == 0) {
            redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
            if(StringUtils.isNotEmpty(quoteName)){
                redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
            }
        }
        // 找出围栏id
@@ -1268,6 +1437,8 @@
                                        pushOrderDto.setStartTaskId(orderCheck.getData().getXpuStartTaskId());
                                        pushOrderDto.setEndTaskId(orderCheck.getData().getXpuEndTaskId());
                                        pushOrderDto.setOrderId(orderCheck.getData().getId().toString());
                                        pushOrderDto.setStartWaypointId(orderCheck.getData().getStartPointId());
                                        pushOrderDto.setEndWaypointId(orderCheck.getData().getEndPointId());
                                        pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat());
                                        pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon());
                                        pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat());
@@ -1275,15 +1446,21 @@
                                        pushOrderDto.setEndPoiName(orderCheck.getData().getEndPointName());
                                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                                        pushOrderDto.setStage(1);
                                        pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                                        pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                                        if(null != cruiseOrder){
                                            pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                                            pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                                        }
                                        pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                                        log.info("[人车订单绑定测试] XPU推单参数: vin={}, orderId={}, startLat={}, startLon={}, endLat={}, endLon={}, orderNo={}",
                                                priorityVin, orderCheck.getData().getId(), orderCheck.getData().getStartLat(), orderCheck.getData().getStartLon(),
                                                orderCheck.getData().getEndLat(), orderCheck.getData().getEndLon(), orderNo);
                                        orderMissionClient.pushOrder(pushOrderDto);
                                        log.info("[人车订单绑定测试] ====== 派单成功! uid={}, vin={}, orderNo={}, 从队列移除订单 ======", uid, priorityVin, orderNo);
                                        redisService.removeByPattern(quoteName, orderNo);
                                        if(StringUtils.isNotEmpty(quoteName)){
                                            redisService.removeByPattern(quoteName, orderNo);
                                        }
                                        return true;
                                    } else {
                                        log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo);
@@ -1931,9 +2108,9 @@
                            continue;
                        }
                        String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehiclePosition.getVehicleVin());
                        //  关闭巡游单子
                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin());
                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin);
                        if (stringR == null || stringR.getCode() != 200) {
                            log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber());
                            continue;
@@ -1944,8 +2121,10 @@
                        PushOrderDto pushOrderDto = new PushOrderDto();
                        pushOrderDto.setStartTaskId(xpOrder.getXpuStartTaskId());
                        pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId());
                        pushOrderDto.setVin(vehiclePosition.getVehicleVin());
                        pushOrderDto.setVin(vin);
                        pushOrderDto.setOrderId(xpOrder.getId().toString());
                        pushOrderDto.setStartWaypointId(xpOrder.getStartPointId());
                        pushOrderDto.setEndWaypointId(xpOrder.getEndPointId());
                        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
@@ -1953,14 +2132,17 @@
                        pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                        pushOrderDto.setStage(1);
                        pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                        pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                        if(null != cruiseOrder){
                            pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                            pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                        }
                        pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo);
                        redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                        if(StringUtils.isNotEmpty(quoteName)){
                            redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
                        }
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
@@ -1983,6 +2165,7 @@
                            continue;
                        }
                        XpVehicle vehicleId1 = vehicleR.getData();
                        String vin = SensitiveDataCryptoUtil.decryptIfPossible(vehicleId1.getVehicleVin());
                        log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo);
                        log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo);
                        if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) {
@@ -2001,7 +2184,7 @@
                        }
                        //  关闭巡游单子
                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin());
                        R<XpCruiseOrder> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vin);
                        if (stringR == null || stringR.getCode() != 200) {
                            log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber());
                            continue;
@@ -2014,6 +2197,8 @@
                        pushOrderDto.setEndTaskId(xpOrder.getXpuEndTaskId());
                        pushOrderDto.setVin(vehiclePosition.getVin());
                        pushOrderDto.setOrderId(xpOrder.getId().toString());
                        pushOrderDto.setStartWaypointId(xpOrder.getStartPointId());
                        pushOrderDto.setEndWaypointId(xpOrder.getEndPointId());
                        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
@@ -2021,13 +2206,18 @@
                        pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                        pushOrderDto.setStage(1);
                        pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                        pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                        if(null != cruiseOrder){
                            pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                            pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                        }
                        pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber());
                        redisService.popFirstElement(quoteName);
                        if(StringUtils.isNotEmpty(quoteName)){
                            redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
                        }
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
@@ -2120,11 +2310,14 @@
//                orderMissionClient.pushOrder(pushOrderDto);
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("orderId", xpOrder.getId());
                jsonObject.put("endLongitude", xpOrder.getEndLat());
                jsonObject.put("endLongitude", xpOrder.getEndLon());
                jsonObject.put("endLatitude", xpOrder.getEndLat());
                redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString());
                redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), routeToOrigin);
                redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                if(StringUtils.isNotEmpty(quoteName)){
                    redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                }
                log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                break;
            }
@@ -2137,6 +2330,8 @@
    private static PushOrderDto buildPushOrderDto(XpOrder xpOrder) {
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setOrderId(xpOrder.getId().toString());
        pushOrderDto.setStartWaypointId(xpOrder.getStartPointId());
        pushOrderDto.setEndWaypointId(xpOrder.getEndPointId());
        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
@@ -2272,7 +2467,7 @@
                    routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance());
                    JSONObject jsonObject = new JSONObject();
                    jsonObject.put("orderId", data.getId());
                    jsonObject.put("endLongitude", data.getEndLat());
                    jsonObject.put("endLongitude", data.getEndLon());
                    jsonObject.put("endLatitude", data.getEndLat());
                    redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), jsonObject.toJSONString());
                    redisService.setCacheObject(CacheConstants.navigationStart(data.getAppUserId().toString()), routeToOrigin);
@@ -2320,6 +2515,8 @@
                pushOrderDto.setEndTaskId(data.getXpuEndTaskId());
                pushOrderDto.setVin(vehiclePosition.getVin());
                pushOrderDto.setOrderId(data.getId().toString());
                pushOrderDto.setStartWaypointId(data.getStartPointId());
                pushOrderDto.setEndWaypointId(data.getEndPointId());
                pushOrderDto.setStartLatitude(data.getStartLat());
                pushOrderDto.setStartLongitude(data.getStartLon());
                pushOrderDto.setEndLatitude(data.getEndLat());
@@ -2327,8 +2524,10 @@
                pushOrderDto.setEndPoiName(data.getEndPointName());
                pushOrderDto.setOrderType(OrderType.USER_ORDER);
                pushOrderDto.setStage(1);
                pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                if(null != cruiseOrder){
                    pushOrderDto.setLastOrderId("XU" + cruiseOrder.getId());
                    pushOrderDto.setLastXpuTaskId(cruiseOrder.getXpuTaskId());
                }
                pushOrderDto.setTaskActionType(TaskActionType.kTerminateForNewTask);
                // 调用推送服务  orderId + carVin
                orderMissionClient.pushOrder(pushOrderDto);
@@ -2337,7 +2536,7 @@
                entity.setIsComplete(true);
//                //接单成功 将 修改 订单的状态=1 ( 状态 0=已取消,1=待接单,2=待出发,3=接驾中,4=待客上车,5=乘客已上车,6=服务中,7=待客下车,8=待付款,9=待评价,10=已完成)
//                orderCarStatus = true;
                xpOrderClient.updateOrderStatus(data.getId(), OrderStatusEnum.PENDING_ORDER.getCode(), false);
                xpOrderClient.updateOrderStatus(data.getId(), OrderStatusEnum.PENDING_ORDER.getCode());
                redisService.setCacheObject("ORDER_STATUS:" + data.getId(), OrderStatusEnum.PENDING_ORDER.getCode(), 24L, TimeUnit.HOURS);
                break;