xuhy
2026-04-17 105940ef605fff73fc1b7480db3ed1d7cf6be4d8
[feat] 连环派单应用配置策略
1 文件已重命名
2个文件已添加
7个文件已修改
160 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/account/XpOperationsUserPositionDTO.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpTradingStrategyClientFallbackFactory.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpTradingStrategyClient.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/XpTradingStrategyDetailVO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/XpPricingController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTradingStrategyController.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpTradingStrategyService.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyServiceImpl.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/account/XpOperationsUserPositionDTO.java
@@ -1,5 +1,6 @@
package com.xiaopeng.api.dto.account;
import com.baomidou.mybatisplus.annotation.EnumValue;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -22,19 +23,10 @@
    @ApiModelProperty(value = "纬度")
    private double longitude;
    @ApiModelProperty(value = "状态:0在线,1空闲,2上班中")
    private Integer status;
    @ApiModelProperty(value = "距离,这个是mongoDB查询时填充")
    private double distance;
    @ApiModelProperty(value = "状态;在线 , 上班中 , 空闲")
    private Long status;
    enum Status {
        online("在线"),working("上班中"),idle("空闲");
        String label;
        Status(String label) {
            this.label = label;
        }
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpTradingStrategyClientFallbackFactory.java
New file
@@ -0,0 +1,14 @@
package com.xiaopeng.api.factory.operation;
import com.xiaopeng.api.feignClient.operation.XpTradingStrategyClient;
import com.xiaopeng.common.core.domain.R;
import org.springframework.cloud.openfeign.FallbackFactory;
public class XpTradingStrategyClientFallbackFactory  implements FallbackFactory<XpTradingStrategyClient> {
    @Override
    public XpTradingStrategyClient create(Throwable cause) {
        return () -> R.fail("策略查询失败");
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpTradingStrategyClient.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.api.feignClient.operation;
import com.xiaopeng.api.factory.operation.XpTradingStrategyClientFallbackFactory;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
@FeignClient(contextId = "XpTradingStrategyClient", value = ServiceNameConstantsEnum.XP_OPERATION_SERVICE, fallbackFactory = XpTradingStrategyClientFallbackFactory.class)
public interface XpTradingStrategyClient {
    @GetMapping("/logan/inner/xpOperationStrategy/getOne")
    R<XpTradingStrategyDetailVO> queryById();
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/XpTradingStrategyDetailVO.java
File was renamed from xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/XpTradingStrategyDetailVO.java
@@ -1,4 +1,4 @@
package com.xiaopeng.operation.vo;
package com.xiaopeng.api.vo.operation;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.model.operation.XpTradingStrategyCity;
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/XpPricingController.java
@@ -220,27 +220,4 @@
        return R.ok(xpPricingService.getQueueStatus(orderId, uid));
    }
    /**
     * 当前行程可否修改
     *
     * @param
     * @return 订单数量
     */
    @GetMapping("/api/v1/mini-program/order/queryOrderTrajectory")
    public R<Integer> allowedModify(@RequestParam Long orderId){
//        1. 小于10分钟路程(后台配置)【取消行程】按钮应置灰;【取消行程】按钮应置灰;登录后获取系统和个人配置;
//        2. 当前剩余里程 < 800米 (后台配置)或 剩余时间 < 5分钟(后台配置)(以先到者为准),禁止修改,按钮置灰。
//        3. 单次行程最多允许修改 2次 (后台配置)目的地,防恶意高频调用
//
//                数据字典设置
//        取消行程 时间阈值 10 分钟
//        修改行程 时间阈值 5 分钟
//        修改行程 路程阈值 800 米
//        解除限制 时间阈值 3 分钟
//
//        若系统检测到车辆在当前坐标时速 < 3km/h 且持续时间 > 3分钟(后台配置)(判定为极度拥堵或异常停滞),此时解除限制
//        通过 redis 轨迹得到路程 < 3s/60s * 3000m,则为堵车
        return R.ok();
    }
}
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -16,6 +16,7 @@
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.operation.XpPointClient;
import com.xiaopeng.api.feignClient.operation.XpTradingStrategyClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
@@ -1022,7 +1023,9 @@
        payload.setDestination(routeAndFareDto.getDestination());
        payload.setUserCouponId(routeAndFareDto.getUserCouponId());
        payload.setRoutes(options);
        redisService.setCacheObject(CacheConstants.ORDER_MULTI_ROUTE_SNAPSHOT + userId + ":" + snapshotId, JSON.toJSONString(payload), 24L, TimeUnit.HOURS);
        XpTradingStrategyDetailVO strategyDetailVO = xpTradingStrategyClient.queryById().getData();
        redisService.setCacheObject(CacheConstants.ORDER_MULTI_ROUTE_SNAPSHOT + userId + ":" + snapshotId, JSON.toJSONString(payload), Long.valueOf(strategyDetailVO.getMaxStandingTiming()), TimeUnit.SECONDS);
        MultiRouteAndFareVo vo = new MultiRouteAndFareVo();
        vo.setSnapshotId(snapshotId);
@@ -1037,7 +1040,7 @@
        redisService.setCacheObject("ORDER_NAVIGATION_END_DATA:" + userId, JSON.toJSONString(first.getRoute()), 24L, TimeUnit.HOURS);
        return vo;
    }
    XpTradingStrategyClient xpTradingStrategyClient;
    @Override
    public void selectNavigationRoute(SelectNavigationRouteDto dto, String userId) {
        String json = redisService.getCacheObject(CacheConstants.ORDER_MULTI_ROUTE_SNAPSHOT + userId + ":" + dto.getSnapshotId());
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTradingStrategyController.java
@@ -4,7 +4,7 @@
import com.xiaopeng.common.core.web.controller.BaseController;
import com.xiaopeng.operation.dto.XpTradingStrategyEditDTO;
import com.xiaopeng.operation.service.IXpTradingStrategyService;
import com.xiaopeng.operation.vo.XpTradingStrategyDetailVO;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
@@ -41,6 +41,13 @@
        return R.ok(detail);
    }
    @ApiOperation(value = "获取交易策略配置", tags = {"inner-交易策略配置"})
    @GetMapping("/logan/inner/xpOperationStrategy/getOne")
    public R<XpTradingStrategyDetailVO> getOne() {
        XpTradingStrategyDetailVO detail = tradingStrategyService.queryDetail();
        return R.ok(detail);
    }
    /**
     * 修改交易策略
     *
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpTradingStrategyService.java
@@ -3,7 +3,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpTradingStrategy;
import com.xiaopeng.operation.dto.XpTradingStrategyEditDTO;
import com.xiaopeng.operation.vo.XpTradingStrategyDetailVO;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
/**
 * <p>
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyServiceImpl.java
@@ -10,7 +10,7 @@
import com.xiaopeng.operation.mapper.XpTradingStrategyMapper;
import com.xiaopeng.operation.service.IXpTradingStrategyCityService;
import com.xiaopeng.operation.service.IXpTradingStrategyService;
import com.xiaopeng.operation.vo.XpTradingStrategyDetailVO;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
import lombok.RequiredArgsConstructor;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -10,6 +10,7 @@
import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.operation.XpTradingStrategyClient;
import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
@@ -23,6 +24,7 @@
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.operation.VehiclePositionVo;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.domain.R;
@@ -48,6 +50,7 @@
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -79,6 +82,9 @@
    @Resource
    private XpCruiseOrderClient xpCruiseOrderClient;
    @Resource
    private XpTradingStrategyClient tradingStrategyClient;
    @Resource
    private XpVehicleClient xpVehicleClient;
@@ -1087,9 +1093,19 @@
                continue;
            }
            LonLatDto lonLatDto = new LonLatDto(Double.parseDouble(split[0]), Double.parseDouble(split[1]));
            LonLatDto current = new LonLatDto(Double.parseDouble(split[0]), Double.parseDouble(split[1]));//当前点位
            Optional<XpOrder> lucyOrderOpt = servingVehicles.getData().stream()
            XpTradingStrategyDetailVO strategyDetailVO = tradingStrategyClient.queryById().getData();
            Integer distanceRegardAsEnding = strategyDetailVO.getDistanceRegardAsEnding();
            Integer timeRegardAsEnding = strategyDetailVO.getTimeRegardAsEnding();
            Integer backupPower = strategyDetailVO.getBackupPower();
            Integer destToPassenger = strategyDetailVO.getDestToPassenger();
            Integer endingTimeToUseTime = strategyDetailVO.getEndingTimeToUseTime();
            LocalDateTime rideTime = xpOrder.getRideTime();
            LocalDateTime now = LocalDateTime.now();
            Optional<XpOrder> luckyOrderOpt = servingVehicles.getData().stream()
                    //获取位置
                    .map(vin -> mongoTemplate.findOne(new Query(Criteria.where("vin").is(vin)), VehiclePosition.class))
                    .map(VehiclePosition::getOrderId)
@@ -1097,23 +1113,48 @@
                    .filter(R::isSuccess)
                    .map(R::getData)
                    .filter(o -> {
                        RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                        routeAndFareDto.setDestination(lonLatDto);
                        return isClose(o, routeAndFareDto);
                        XpVehicle xpVehicle = xpVehicleClient.queryById(o.getVehicleId()).getData();
                        Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(o.getAppUserId().toString()));
                        RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                        if (routeRemain.getDuration() / 60 > timeRegardAsEnding) {
                            return false;
                        }
                        RouteAndFareDto remain = new RouteAndFareDto();
                        remain.setOrigin(current);
                        LonLatDto ll = new LonLatDto(o.getStartLon(), o.getStartLat());
                        remain.setDestination(ll);
                        RouteVo r = xpMapClient.getDistanceAndDuration(remain).getData();
                        if (r.getDistance() > distanceRegardAsEnding) {
                            return false;
                        }
                        if (r.getDuration() / 60 > timeRegardAsEnding) {
                            return false;
                        }
                        RouteAndFareDto next = new RouteAndFareDto();
                        next.setOrigin(new LonLatDto(o.getStartLon(),o.getStartLat()));
                        next.setDestination(new LonLatDto(o.getEndLon(),o.getEndLat()));
                        RouteVo route = xpMapClient.getDistanceAndDuration(next).getData();
                        if (route.getDistance() > backupPower + xpVehicle.getMileageRange())
                            return false;
                        return r.getDistance() < destToPassenger
                                || now.plusSeconds(routeRemain.getDuration())
                                .plusMinutes(endingTimeToUseTime)
                                .isBefore(rideTime);
                    })
                    .findAny();
            if (lucyOrderOpt.isPresent()) {
                XpOrder lucyOder = lucyOrderOpt.get();
                log.info("有空闲车辆 {} 订单 {}", lucyOder.getOrderNumber(), orderNo);
                XpVehicle xpVehicle = xpVehicleClient.queryById(lucyOder.getVehicleId()).getData();
            if (luckyOrderOpt.isPresent()) {
                XpOrder luckyOder = luckyOrderOpt.get();
                log.info("有空闲车辆 {} 订单 {}", luckyOder.getOrderNumber(), orderNo);
                XpVehicle xpVehicle = xpVehicleClient.queryById(luckyOder.getVehicleId()).getData();
                // 设置路线信息
                RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                routeAndFareDto.setDestination(lonLatDto);
                routeAndFareDto.setOrigin(new LonLatDto(lucyOder.getEndLon(),lucyOder.getEndLat()));
                Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(lucyOder.getAppUserId().toString()));
                RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                routeAndFareDto.setDestination(current);
                routeAndFareDto.setOrigin(new LonLatDto(luckyOder.getEndLon(),luckyOder.getEndLat()));
                RouteVo routeToOrigin = xpMapClient.getDistanceAndDuration(routeAndFareDto).getData();
                Object cacheObject = redisService.getCacheObject(CacheConstants.navigationEnd(luckyOder.getAppUserId().toString()));
                RouteVo routeRemain = JSON.parseObject(cacheObject.toString(), RouteVo.class);
                routeToOrigin.getPolyline().addAll(0, routeRemain.getPolyline());
                routeToOrigin.setDuration(routeToOrigin.getDuration() + routeRemain.getDuration());
                routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance());
@@ -1121,7 +1162,7 @@
                pushOrderDto.setVin(xpVehicle.getVehicleVin());
                // 订单流转
                orderMissionClient.pushOrder(pushOrderDto);
                redisService.setCacheObject(CacheConstants.nextOrder(lucyOder.getId().toString()), xpOrder.getId());
                redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), xpOrder.getId());
                redisService.setCacheObject(CacheConstants.navigationStart(xpOrder.getAppUserId().toString()), routeToOrigin);
                redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);