yyy
2026-04-21 6f55da80d19cba61bd23cd302b76bbb23038f7bd
Merge remote-tracking branch 'origin/1.0' into 1.0
7个文件已添加
37个文件已修改
832 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/account/XpOperationsUserPositionDTO.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automaticPilot/OrderMissionClientFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automaticPilot/OrderMissionClient.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpCruiseOrder.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpTestOrder.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/FareBreakdownVo.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/config/SnowflakeConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/ActiveOrderController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/ActiveOrderServiceImpl.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/config/SnowflakeConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpCruiseCheckInRuleController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpCruiseCheckInRecordMapper.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpTaskMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/query/TaskPageListQuery.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCollectionScheduleTask.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpCruiseCheckInRecordService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRecordServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/TaskReassignDetailVO.java 97 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/XpCruiseCheckInStatisticsQuery.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/XpCruiseCheckInStatisticsVO.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpCruiseCheckInRecordMapper.xml 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpTaskMapper.xml 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/config/SnowflakeConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/OssController.java 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpCruisePlanController.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/config/SnowflakeConfig.java 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/CustomerServiceController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpCruiseOrderController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/PushChainReactionOrderJob.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpTestOrderServiceImpl.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/vo/ServiceVehicleListVo.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/handler/PositionMsgHandler.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/account/XpOperationsUserPositionDTO.java
@@ -4,6 +4,8 @@
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.mongodb.core.mapping.Document;
/**
 * 运维人员查询条件DTO
@@ -12,9 +14,11 @@
 */
@Data
@ApiModel("运维人员状态")
@Document(collection = "xp_operations_user_position")
public class XpOperationsUserPositionDTO {
    @ApiModelProperty(value = "运维人员id")
    @Id
    private long id;
    @ApiModelProperty(value = "经度")
@@ -23,6 +27,9 @@
    @ApiModelProperty(value = "纬度")
    private double longitude;
    @ApiModelProperty(value = "地理位置信息,用于MongoDB地理空间查询 [经度, 纬度]")
    private double[] location;
    @ApiModelProperty(value = "状态:0在线,1空闲,2上班中")
    private Integer status;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automaticPilot/OrderMissionClientFallbackFactory.java
@@ -31,6 +31,12 @@
                log.error("远程调用获取检查点位信息异常:{}", cause.getMessage());
                return null;
            }
            @Override
            public R<Boolean> updateEndAddress(PushOrderDto dto) {
                log.error("远程调用获取检查点位信息异常:{}", cause.getMessage());
                return R.fail("远程调用获取检查点位信息异常");
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automaticPilot/OrderMissionClient.java
@@ -34,4 +34,9 @@
     */
    @PostMapping("/logan/inner/cancelOrder")
    R<Boolean> cancelOrder(@RequestBody PushOrderDto dto);
    @PostMapping("/logan/inner/updateEndAddress")
    R<Boolean> updateEndAddress(@RequestBody PushOrderDto dto);
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java
@@ -35,6 +35,9 @@
    @TableId(value = "id", type = IdType.NONE)
    private Long id;
    @ApiModelProperty(value = "事故类型id")
    private String errorTypeId;
    @ApiModelProperty(value = "任务编号")
    private String taskCode;
@@ -96,6 +99,9 @@
    @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消 4=改派中")
    private Integer status;
    @ApiModelProperty(value = "状态 2=已处理 1=改派中")
    private Integer reassignmentStatus;
    @ApiModelProperty(value = "任务来源 1-运维APP 2-管理后台")
    private Integer taskSource;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpCruiseOrder.java
@@ -88,4 +88,8 @@
    @ApiModelProperty(value = "方向 1正2反")
    @TableField("order_reverse")
    private Integer orderReverse;
    @ApiModelProperty(value = "XPU行程任务id")
    @TableField("xpu_task_id")
    private String xpuTaskId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpOrder.java
@@ -249,4 +249,7 @@
    @ApiModelProperty(value = "订单修改目的地的次数 默认0")
    private Integer orderChange;
    @ApiModelProperty(value = "XPU行程任务id")
    @TableField("xpu_task_id")
    private String xpuTaskId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpTestOrder.java
@@ -235,4 +235,8 @@
    private Integer num;
    @ApiModelProperty(value = "是否改价标识 0-否 1-是")
    private Boolean changeMoneyFlag;
    @ApiModelProperty(value = "XPU行程任务id")
    @TableField("xpu_task_id")
    private String xpuTaskId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/FareBreakdownVo.java
@@ -32,5 +32,8 @@
    @ApiModelProperty(value = "是否改价标识 0-否 1-是")
    private Boolean changeMoneyFlag=false;
    @ApiModelProperty(value = "是否开启试运营(0=否,1=是)")
    private Integer operateFree;
}
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -80,7 +80,7 @@
        if(dto.getOrderType().equals(com.xiaopeng.api.vo.OrderType.CRUISE_ORDER)){
            RtTask.Builder taskBuilder = RtTask.newBuilder();
            taskBuilder.setOrderId(dto.getOrderId().toString());
            taskBuilder.setTaskId(snowflake.nextId() + "");
            taskBuilder.setTaskId(StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "");
            taskBuilder.setTaskType(OrderType.ORDER_TYPE_CRUISE);
            //构建起点坐标数据
            pointBuilderStart.setWaypointId(dto.getOrderId() + "-001");
@@ -111,7 +111,7 @@
            for (int i = 1; i < 3; i++) {
                RtTask.Builder taskBuilder = RtTask.newBuilder();
                taskBuilder.setOrderId(dto.getOrderId().toString());
                taskBuilder.setTaskId(snowflake.nextId() + "");
                taskBuilder.setTaskId(StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "");
                taskBuilder.setTaskType(OrderType.ORDER_TYPE_ROBOTAXI);
                if(i == 1){
                    VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(dto.getVin())), VehiclePosition.class);
@@ -171,7 +171,7 @@
            for (int i = 1; i < 3; i++) {
                RtTask.Builder taskBuilder = RtTask.newBuilder();
                taskBuilder.setOrderId(dto.getOrderId().toString());
                taskBuilder.setTaskId(snowflake.nextId() + "");
                taskBuilder.setTaskId(StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "");
                taskBuilder.setTaskType(OrderType.ORDER_TYPE_ROBOTAXI);
                if(i == 1){
                    VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(dto.getVin())), VehiclePosition.class);
@@ -230,7 +230,7 @@
            //测试单巡游单
            RtTask.Builder taskBuilder = RtTask.newBuilder();
            taskBuilder.setOrderId(dto.getOrderId().toString());
            taskBuilder.setTaskId(snowflake.nextId() + "");
            taskBuilder.setTaskId(StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "");
            taskBuilder.setTaskType(OrderType.ORDER_TYPE_CRUISE);
            //构建起点坐标数据
            pointBuilderStart.setWaypointId(dto.getOrderId() + "-001");
@@ -281,7 +281,7 @@
    }
    @PostMapping("/logan/inner/cancelOrder")
    R<Boolean> cancelOrder(@RequestBody PushOrderDto dto) {
    public R<Boolean> cancelOrder(@RequestBody PushOrderDto dto) {
        log.info("取消订单,推送XPU报文:{}", JSON.toJSONString(dto));
        String taskId = StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "";
        OrderOperation.Builder operationBuilder = OrderOperation.newBuilder();
@@ -317,6 +317,48 @@
    @PostMapping("/logan/inner/updateEndAddress")
    public R<Boolean> updateEndAddress(@RequestBody PushOrderDto dto){
        log.info("修改目的地,推送XPU报文:{}", JSON.toJSONString(dto));
        String taskId = StringUtils.isNotEmpty(dto.getTaskId()) ? dto.getTaskId() : snowflake.nextId() + "";
        OrderOperation.Builder operationBuilder = OrderOperation.newBuilder();
        operationBuilder.setOrderId(dto.getOrderId().toString());
        operationBuilder.setTaskId(taskId);
        if (dto.getOperation_type() != null) {
            operationBuilder.setOperationType(OrderOperationType.forNumber(dto.getOperation_type().getNumber()));
        }
        Waypoint.Builder waypointBuilder = Waypoint.newBuilder();
        waypointBuilder.setWaypointId(dto.getOrderId() + "-002");
        waypointBuilder.setPointType(PointType.END_POINT);
        waypointBuilder.setActionType(ActionType.DROP_OFF);
        waypointBuilder.setSequence(2);
        GeoPoint.Builder geoPointBuilder = GeoPoint.newBuilder();
        geoPointBuilder.setLatitude(dto.getStartLatitude());
        geoPointBuilder.setLongitude(dto.getStartLongitude());
        waypointBuilder.setPoint(geoPointBuilder.build());
        waypointBuilder.setPoiName(dto.getEndPoiName());
        operationBuilder.setTargetPoint(waypointBuilder);
        long sequence = snowflake.nextId();
        MqttPublishDto mqttPublishDto = xpuUtil.cloudOrderOperation(operationBuilder.build(), dto.getVin(), sequence);
        if (mqttPublishDto.getCode() == 200) {
            if(!dto.getOrderId().contains("XU")){
                Map<String, Object> cancelContext = new HashMap<>();
                cancelContext.put("orderId", dto.getOrderId());
                cancelContext.put("vin", dto.getVin());
                cancelContext.put("cancelScene", StringUtils.isNotEmpty(dto.getCancelScene())
                        ? dto.getCancelScene()
                        : CancelOrderSceneEnum.NORMAL_CANCEL.getCode());
                redisService.setCacheObject("CANCEL_ORDER_CONTEXT:" + taskId,
                        JSONObject.toJSONString(cancelContext), 30L, TimeUnit.MINUTES);
                log.info("记录修改目的地订单上下文成功,orderId: {}, vin: {}, taskId: {}, cancelScene: {}",
                        dto.getOrderId(), dto.getVin(), taskId, cancelContext.get("cancelScene"));
            }
            return R.ok(true);
        }
        return R.ok(false);
    }
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -1467,6 +1467,7 @@
                        newXpCruiseOrder.setStartPointName(xpCruiseOrder.getEndPointName());
                        newXpCruiseOrder.setStatus(1);
                        newXpCruiseOrder.setLastOrderId(xpCruiseOrder.getId());
                        xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
                        // 通过车找终点id
                        CruisePointDto cruisePointDto = new CruisePointDto();
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/config/SnowflakeConfig.java
New file
@@ -0,0 +1,57 @@
package com.xiaopeng.itinerary.config;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class SnowflakeConfig {
    //初始时间戳,设为2026年1月1日0点0时0分
    public static final Date EPOCH_DATE = new Date(1767225600000L);
    /**
     * 如果配置为<0的值,则woker-id根据pod名的hash取模生成
     * 如果配置为>=0的值,则取配置的值
     * 如果多个pod的data-center-id和worker-id相同,同一毫秒内请求数上千的话,可能会产生碰撞,生成一样的snowflake id
     */
    @Value("${snowflake.worker-id:-1}")
    private long workerId;
    @Value("${snowflake.data-center-id:0}")
    private long dataCenterId;
    @Bean("hutoolSnowflake")
    public Snowflake snowflake() {
        long resolvedWorkerId = resolveWorkerId();
        return new Snowflake(EPOCH_DATE, resolvedWorkerId, dataCenterId, false);
    }
    private long resolveWorkerId() {
        if (workerId >= 0 && workerId <= Snowflake.MAX_WORKER_ID) {
            return workerId;
        }
        String podName = System.getenv("HOSTNAME");
        if (podName == null || podName.isEmpty()) {
            return 0;
        }
        int end = podName.length() - 1;
        while (end >= 0 && Character.isDigit(podName.charAt(end))) {
            end--;
        }
        String numberPart = podName.substring(end + 1);
        long candidate;
        if (!numberPart.isEmpty()) {
            try {
                candidate = Long.parseLong(numberPart);
            } catch (NumberFormatException e) {
                candidate = Math.abs(podName.hashCode());
            }
        } else {
            candidate = Math.abs(podName.hashCode());
        }
        return candidate % (Snowflake.MAX_WORKER_ID + 1);
    }
}
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/controller/ActiveOrderController.java
@@ -71,7 +71,6 @@
    @PostMapping("/api/v1/mini-program/order/orderChange")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<?> orderChange(@RequestBody @Validated OrderChangeDto dto, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
        activeOrderService.orderChange(dto, uid);
        return R.ok();
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/ActiveOrderServiceImpl.java
@@ -2,18 +2,23 @@
import com.alibaba.fastjson2.JSON;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.dto.operation.ReassignOrderDTO;
import com.xiaopeng.api.dto.order.OrderChangeDto;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.operation.ReassignOrderClient;
import com.xiaopeng.api.feignClient.operation.XpPointClient;
import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.operation.XpElectronicFence;
import com.xiaopeng.api.model.operation.XpElectronicFenceArea;
import com.xiaopeng.api.model.operation.XpPoint;
import com.xiaopeng.api.model.operation.XpSystemSetting;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.protobuf.OrderOperationType;
import com.xiaopeng.api.vo.operation.RouteOptionVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.common.core.constant.CacheConstants;
@@ -70,6 +75,10 @@
    private RedisService redisService;
    @Resource
    private XpRoutePlanMapper xpRoutePlanMapper;
    @Resource
    private XpVehicleClient vehicleClient;
    @Resource
    private OrderMissionClient orderMissionClient;
    /*
@@ -187,6 +196,16 @@
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
        //给车端推送修改目的地报文
        XpVehicle xpVehicle = vehicleClient.queryById(xpOrder.getVehicleId()).getData();
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setOrderId(order.getId().toString());
        pushOrderDto.setTaskId(order.getXpuTaskId());
        pushOrderDto.setVin(xpVehicle.getVehicleVin());
        pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CHANGE_DESTINATION);
        orderMissionClient.cancelOrder(pushOrderDto);
        log.info("订单下发XPU修改目的地成功 {}", order.getId());
        // 判断当前订单的车辆是否有连环派单,然后判断是都还满足连环派单的条件,不满足则需要重新派单
        Long nextOrderId = redisService.getCacheObject(CacheConstants.nextOrder(order.getId().toString()));
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -1,6 +1,7 @@
package com.xiaopeng.itinerary.service.impl;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -136,6 +137,9 @@
    @Resource
    private UserRoutePlanRuleClient userRoutePlanRuleClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    @Value("${navigation.route.stale-seconds:60}")
    private int navigationStaleSeconds;
@@ -639,6 +643,7 @@
        xpOrder.setEndLat(endXpPoint.getPointLat());
        xpOrder.setEndAddress(endXpPoint.getPointAddress());
        xpOrder.setEndPointName(endXpPoint.getPointName());
        xpOrder.setXpuTaskId(snowflake.nextId() + "");
        // 当前时段
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/config/SnowflakeConfig.java
New file
@@ -0,0 +1,57 @@
package com.xiaopeng.maintenance.config;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class SnowflakeConfig {
    //初始时间戳,设为2026年1月1日0点0时0分
    public static final Date EPOCH_DATE = new Date(1767225600000L);
    /**
     * 如果配置为<0的值,则woker-id根据pod名的hash取模生成
     * 如果配置为>=0的值,则取配置的值
     * 如果多个pod的data-center-id和worker-id相同,同一毫秒内请求数上千的话,可能会产生碰撞,生成一样的snowflake id
     */
    @Value("${snowflake.worker-id:-1}")
    private long workerId;
    @Value("${snowflake.data-center-id:0}")
    private long dataCenterId;
    @Bean("hutoolSnowflake")
    public Snowflake snowflake() {
        long resolvedWorkerId = resolveWorkerId();
        return new Snowflake(EPOCH_DATE, resolvedWorkerId, dataCenterId, false);
    }
    private long resolveWorkerId() {
        if (workerId >= 0 && workerId <= Snowflake.MAX_WORKER_ID) {
            return workerId;
        }
        String podName = System.getenv("HOSTNAME");
        if (podName == null || podName.isEmpty()) {
            return 0;
        }
        int end = podName.length() - 1;
        while (end >= 0 && Character.isDigit(podName.charAt(end))) {
            end--;
        }
        String numberPart = podName.substring(end + 1);
        long candidate;
        if (!numberPart.isEmpty()) {
            try {
                candidate = Long.parseLong(numberPart);
            } catch (NumberFormatException e) {
                candidate = Math.abs(podName.hashCode());
            }
        } else {
            candidate = Math.abs(podName.hashCode());
        }
        return candidate % (Snowflake.MAX_WORKER_ID + 1);
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpCruiseCheckInRuleController.java
@@ -14,6 +14,7 @@
import com.xiaopeng.maintenance.service.IXpCruiseCheckInRuleService;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordQuery;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordVO;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInStatisticsQuery;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
@@ -108,4 +109,11 @@
        return R.ok(xpCruiseCheckInRecordVO);
    }
    @ApiOperation(value = "巡游打卡统计", tags = {"管理后台-巡游打卡管理"})
    @PostMapping("/maintenance-admin/api/v1/cruiseCheckInRecord/statistic")
    public R<XpCruiseCheckInRecordVO> pageList(@RequestBody XpCruiseCheckInStatisticsQuery  query) {
        return R.ok(xpCruiseCheckInRecordService.statistics(query));
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskController.java
@@ -3,6 +3,8 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.account.XpOperationsUserPositionDTO;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.XpOperationsUser;
@@ -28,10 +30,9 @@
import com.xiaopeng.maintenance.schedule.InsuranceInspectionScheduleTask;
import com.xiaopeng.maintenance.service.IXpErrorTypeService;
import com.xiaopeng.maintenance.service.XpTaskService;
import com.xiaopeng.maintenance.vo.*;
import com.xiaopeng.maintenance.vo.TaskCleanDetailVO;
import com.xiaopeng.maintenance.vo.TaskDetectionDetailVO;
import com.xiaopeng.maintenance.vo.TaskReassignVo;
import com.xiaopeng.maintenance.vo.VehicleListVO;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
@@ -39,7 +40,11 @@
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.transaction.annotation.Transactional;
@@ -49,10 +54,10 @@
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import static net.sf.jsqlparser.parser.feature.Feature.comment;
import java.util.stream.Collectors;
/**
 * <p>
@@ -299,7 +304,38 @@
        return R.ok(xpTask);
    }
    @ApiOperation(value = "待改派的工单分页列表", tags = {"管理后台-运维执行-任务工单-待改派工单"})
    @PostMapping("/api/v1/task/reassign/pageList")
    public R<PageInfo<TaskVO>> reassignTaskPageList(@RequestBody TaskPageListQuery query) {
        return R.ok(xpTaskService.reassignTaskPageList(query));
    }
    @ApiOperation(value = "可改派的运维人员列表", tags = {"管理后台-运维执行-任务工单-待改派工单"})
    @GetMapping("/api/v1/task/reassign/availableUsers")
    public R<List<XpOperationsUser>> availableReassignUsers(@RequestParam Long taskId) {
        XpTask task = xpTaskService.getById(taskId);
        GeoJsonPoint point =
            new GeoJsonPoint(
                task.getVehicleLon().doubleValue(),
                task.getVehicleLat().doubleValue()
            );
        Query query = new Query(Criteria.where("location").near(point)
            .maxDistance(new Distance(10, Metrics.KILOMETERS).getNormalizedValue()));
        query.with(Sort.by(Sort.Direction.ASC, "dis"));
        List<Long> ids = mongoTemplate.find(query, XpOperationsUserPositionDTO.class)
                .stream().map(XpOperationsUserPositionDTO::getId).collect(Collectors.toList());
        return R.ok(operationUserClient.listByIds(ids).getData());
    }
    @Resource
    private XpOperationUserClient operationUserClient;
    @ApiOperation(value = "改派详情", tags = {"管理后台-运维执行-任务工单-待改派工单"})
    @GetMapping("/api/v1/task/reassign/detail")
    public R<TaskReassignDetailVO> reassignDetail(@RequestParam Long taskId) {
        return R.ok(xpTaskService.detail(taskId));
    }
    @ApiOperation(value = "执行保险年检检测定时任务", tags = {"定时任务"})
    @GetMapping("/base/task/insurance/execute")
@@ -307,5 +343,4 @@
        insuranceInspectionScheduleTask.executeInsuranceInspectionTask();
        return R.ok();
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java
@@ -1,5 +1,6 @@
package com.xiaopeng.maintenance.controller;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.automaticPilot.VehicleEventDTO;
import com.xiaopeng.api.dto.operation.NewCruiseOrderDto;
@@ -64,6 +65,9 @@
    private XpCruisePlanClient xpCruisePlanClient;
    @Autowired
    private VehicleBuriedPointClient vehicleBuriedPointClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    /**
     * 车辆详情-车辆调度-发车 收车
@@ -150,6 +154,7 @@
            xpCruiseOrder.setOrderReverse(1);
            xpCruiseOrder.setLastOrderId(r.getData());
            xpCruiseOrder.setOrderReverse(1);
            xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
            // 找到收车站点
            XpCruiseOrder returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder).getData();
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpCruiseCheckInRecordMapper.java
@@ -5,6 +5,7 @@
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordQuery;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordVO;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInStatisticsQuery;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@@ -14,4 +15,6 @@
    List<XpCruiseCheckInRecordVO> selectCruiseCheckInRecordList(@Param("pageInfo") PageInfo<XpCruiseCheckInRecordVO> pageInfo, @Param("query") XpCruiseCheckInRecordQuery query);
    XpCruiseCheckInRecordVO detail(Long id);
    XpCruiseCheckInRecordVO selectCruiseCheckInStatistics(XpCruiseCheckInStatisticsQuery query);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/mapper/XpTaskMapper.java
@@ -2,6 +2,7 @@
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.maintenance.XpTask;
import com.xiaopeng.api.vo.TaskVO;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.model.query.TaskManagementPageListQuery;
import com.xiaopeng.maintenance.model.query.WorkBenchQuery;
@@ -38,4 +39,5 @@
     */
    XpTask queryInfoByVehicleId(@Param("vehicleId")Long vehicleId);
    PageInfo<TaskVO> reassignTaskPageList(TaskPageListQuery query);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/model/query/TaskPageListQuery.java
@@ -14,24 +14,41 @@
    private String startTime;
    @ApiModelProperty(value = "派发类型为5 结束时间 yyyy-MM-dd HH:mm:ss")
    private String endTime;
    @ApiModelProperty(value = "任务优先级 0=P0 1=P1 2=P2 3=P3 不传为全部")
    private Integer taskUrgencyLevel;
    @ApiModelProperty(value = "任务类别1常规 2事故")
    private Integer taskCategory;
    @ApiModelProperty(value = "排序优先 1依据任务优先级 2车牌号 3任务时间")
    private Integer sortType;
    @ApiModelProperty(value = "排序规则 1正序 2倒序")
    private Integer sortRule;
    @ApiModelProperty(value = "状态0=待到达 1=待处理 2=已完成 3=已取消")
    @ApiModelProperty(value = "状态0=待到达 1=待处理 2=已完成 3=已取消  4=改派中")
    private Integer status;
    @ApiModelProperty(value = "当前登陆人id")
    private Long userId;
    @ApiModelProperty(value = "车牌号")
    private String plateNumber;
    @ApiModelProperty(value = "当前位置经度")
    private Double longitude;
    @ApiModelProperty(value = "当前位置纬度")
    private Double latitude;
    @ApiModelProperty(value = "任务类别1常规 2事故")
    private Integer taskCategory;
    @ApiModelProperty(value = "事故类型")
    private Long accidentTypeId;
    @ApiModelProperty(value = "任务类型")
    private Long taskTypeId;
    @ApiModelProperty(value = "任务优先级 0=P0 1=P1 2=P2 3=P3 不传为全部")
    private Integer taskUrgencyLevel;
    @ApiModelProperty(value = "车牌号")
    private String plateNumber;
    @ApiModelProperty(value = "改派状态")
    private String reassignmentStatus;
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCollectionScheduleTask.java
@@ -1,5 +1,6 @@
package com.xiaopeng.maintenance.schedule;
import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
@@ -21,6 +22,7 @@
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalTime;
import java.util.Collections;
import java.util.List;
@@ -62,6 +64,9 @@
    @Autowired
    private XpCruisePlanClient xpCruisePlanClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    /**
     * 每分钟检查一次是否需要执行收车任务
@@ -217,6 +222,7 @@
        xpCruiseOrder.setOrderReverse(1);
        xpCruiseOrder.setLastOrderId(r.getData());
        xpCruiseOrder.setOrderReverse(1);
        xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
        // 找到收车站点
        R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/IXpCruiseCheckInRecordService.java
@@ -5,10 +5,13 @@
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordQuery;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordVO;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInStatisticsQuery;
public interface IXpCruiseCheckInRecordService extends IService<XpCruiseCheckInRecord> {
    PageInfo<XpCruiseCheckInRecordVO> pageList(XpCruiseCheckInRecordQuery query);
    XpCruiseCheckInRecordVO detail(Long id);
    XpCruiseCheckInRecordVO statistics(XpCruiseCheckInStatisticsQuery query);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/XpTaskService.java
@@ -16,6 +16,7 @@
import com.xiaopeng.maintenance.model.vo.*;
import com.xiaopeng.maintenance.model.query.TaskPageListQuery;
import com.xiaopeng.maintenance.vo.TaskDetectionDetailVO;
import com.xiaopeng.maintenance.vo.TaskReassignDetailVO;
import javax.validation.Valid;
import java.io.UnsupportedEncodingException;
@@ -101,4 +102,8 @@
    void saveVehicleAccidentError(Long vehicleI);
    void accept(String taskId);
    PageInfo<TaskVO> reassignTaskPageList(TaskPageListQuery query);
    TaskReassignDetailVO detail(Long taskId);
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpCruiseCheckInRecordServiceImpl.java
@@ -7,6 +7,7 @@
import com.xiaopeng.maintenance.service.IXpCruiseCheckInRecordService;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordQuery;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInRecordVO;
import com.xiaopeng.maintenance.vo.XpCruiseCheckInStatisticsQuery;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@@ -30,4 +31,9 @@
    public XpCruiseCheckInRecordVO detail(Long id) {
        return xpCruiseCheckInRecordMapper.detail(id);
    }
    @Override
    public XpCruiseCheckInRecordVO statistics(XpCruiseCheckInStatisticsQuery query) {
        return xpCruiseCheckInRecordMapper.selectCruiseCheckInStatistics(query);
    }
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -57,6 +57,7 @@
import com.xiaopeng.maintenance.utils.UUIDUtil;
import com.xiaopeng.maintenance.vo.TaskCleanDetailVO;
import com.xiaopeng.maintenance.vo.TaskDetectionDetailVO;
import com.xiaopeng.maintenance.vo.TaskReassignDetailVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shardingsphere.transaction.annotation.ShardingSphereTransactionType;
@@ -1412,7 +1413,9 @@
            task.setStatus(4);
            noticeAdministrator(task);//TODO 需要通知管理员手动处理,考虑再AliPushUtil 中给管理员发送消息
        }
        updateById(task);
        if(StringUtils.isNotBlank(task.getHandleUserId())){
            sendAccidentNotificationAsync(task, vehicle.getPlateNumber(), taskRule.getProcessingTimeLimit());
        }
@@ -1481,6 +1484,24 @@
        sendAccidentNotificationAsync(getById(task.getId()), vehicle.getPlateNumber(), (int) Duration.between(LocalDateTime.now(),task.getEndTime()).toMinutes());
    }
    @Override
    public PageInfo<TaskVO> reassignTaskPageList(TaskPageListQuery query) {
        return baseMapper.reassignTaskPageList(query);
    }
    @Override
    public TaskReassignDetailVO detail(Long taskId) {
        XpTask task = getById(taskId);
        // 根据taskId去查询XpTaskHandleDetail,
//        XpTaskHandleDetail taskHandleDetail = xpTaskHandleDetailClient.queryByTaskId(taskId).getData();
//        return baseMapper.detail(taskId);
        // todo
        return null;
    }
    @Value("${robotaxi.sms.app-id:1476153389173952512}")
    private String smsAppId;
    @Value("${robotaxi.sms.app-push-config-code:ROBOTAXI_VERIFY_CODE_SMS}")
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/TaskReassignDetailVO.java
New file
@@ -0,0 +1,97 @@
package com.xiaopeng.maintenance.vo;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.model.maintenance.XpTaskHandleDetail;
import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
public class TaskReassignDetailVO {
    @ApiModelProperty(value = "自增id")
    @TableId(value = "id", type = IdType.NONE)
    private Long id;
    @ApiModelProperty(value = "任务编号")
    private String taskCode;
    @ApiModelProperty(value = "任务类别1常规 2事故")
    private Integer taskCategory;
    //1:车辆检查,2:车辆充电,3:车辆整备,4:整备洗车,5:车辆维修,6:车辆保养,7:车辆保险到期,8:车辆年检到期9:车辆运营资质到期
    @ApiModelProperty(value = "任务类型id 任务类别为2时对应数据字典,多个逗号分割,为1的时候 枚举1车辆检查 2车辆充电 3车辆整备 4整备洗车 5车辆维修 6车辆保养 7车辆保险到期 8车辆年检到期 9车辆运营资质到期")
    private String taskTypeId;
    @ApiModelProperty(value = "任务类型id 任务类别为2时对应数据字典,多个逗号分割,为1的时候 枚举1车辆检查 2车辆充电 3车辆整备 4整备洗车 5车辆维修 6车辆保养 7车辆保险到期 8车辆年检到期 9车辆运营资质到期")
    private String accidentTypeId;
    @ApiModelProperty(value = "任务紧急程度 0=P0 1=P1 2=P2 3=P3")
    private Integer taskUrgencyLevel;
    @ApiModelProperty(value = "任务描述")
    private String taskDescription;
    @ApiModelProperty(value = "任务描述图片")
    private String taskImage;
    @ApiModelProperty(value = "车辆id")
    @TableField(updateStrategy = FieldStrategy.NEVER)
    private Long vehicleId;
    @ApiModelProperty(value = "车辆位置")
    private String vehicleLocation;
    @ApiModelProperty(value = "车辆经度")
    private BigDecimal vehicleLon;
    @ApiModelProperty(value = "车辆纬度")
    private BigDecimal vehicleLat;
    @ApiModelProperty(value = "处理人id")
    private String handleUserId;
    @ApiModelProperty(value = "处理时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime handleTime;
    @ApiModelProperty(value = "分配人id")
    private Long assigneeUserId;
    @ApiModelProperty(value = "分配时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime assigneeTime;
    @ApiModelProperty(value = "上报人id")
    private Long reportUserId;
    @ApiModelProperty(value = "上报时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime reportTime;
    @ApiModelProperty(value = "任务时限结束时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private LocalDateTime endTime;
    @ApiModelProperty(value = "是否已发送过期通知 0=未发送 1=已发送")
    private Integer expiredNoticeSent;
    @ApiModelProperty(value = "事故即将超时通知是否已发送 0=未发送 1=已发送")
    private Integer willTimeoutNoticeSent;
    @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消 4=改派中")
    private Integer status;
    @ApiModelProperty(value = "状态 2=已处理 1=改派中")
    private Integer reassignmentStatus;
    @ApiModelProperty(value = "任务来源 1-运维APP 2-管理后台")
    private Integer taskSource;
    @ApiModelProperty(value = "申请改派的用户id")
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Long> excluded;
    private List<XpTaskHandleDetail> logs;
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/XpCruiseCheckInStatisticsQuery.java
New file
@@ -0,0 +1,30 @@
package com.xiaopeng.maintenance.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.common.core.web.page.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.time.LocalDate;
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel(value = "巡游打卡记录查询参数")
public class XpCruiseCheckInStatisticsQuery extends BasePage {
    @ApiModelProperty(value = "打卡规则名称(模糊匹配)")
    private String ruleName;
    @ApiModelProperty(value = "打卡点位名称(模糊匹配)")
    private String fleet;
    @ApiModelProperty(value = "开始日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private LocalDate startDate;
    @ApiModelProperty(value = "结束日期")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT+8")
    private LocalDate endDate;
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/vo/XpCruiseCheckInStatisticsVO.java
New file
@@ -0,0 +1,32 @@
package com.xiaopeng.maintenance.vo;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
@Data
@ApiModel(value = "巡游打卡记录返回VO")
public class XpCruiseCheckInStatisticsVO implements Serializable {
    @ApiModelProperty(value = "日期")
    LocalDate date;
    @ApiModelProperty(value = "准时次数")
    private Integer punctual;
    @ApiModelProperty(value = "迟到次数")
    private Integer late;
    @ApiModelProperty(value = "通畅次数")
    private Integer noTraffic;
    @ApiModelProperty(value = "堵车次数")
    private Integer traffic;
}
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpCruiseCheckInRecordMapper.xml
@@ -18,6 +18,14 @@
        <result column="scene_description" property="sceneDescription"/>
    </resultMap>
    <resultMap id="CruiseCheckInStatisticsMap" type="com.xiaopeng.maintenance.vo.XpCruiseCheckInStatisticsVO">
        <result column="date" property="date"/>
        <result column="punctual" property="punctual"/>
        <result column="late" property="late"/>
        <result column="noTraffic" property="noTraffic"/>
        <result column="traffic" property="traffic"/>
    </resultMap>
    <select id="selectCruiseCheckInRecordList" resultMap="CruiseCheckInRecordVOMap">
        SELECT
            r.id,
@@ -91,4 +99,34 @@
          AND r.del_flag = '0'
    </select>
    <select id="selectCruiseCheckInStatistics" resultMap="CruiseCheckInStatisticsMap">
        SELECT
        DATE(r.check_in_time) AS date,
        COUNT(CASE WHEN r.check_in_result = 1 THEN 1 END) AS punctual,
        COUNT(CASE WHEN r.check_in_result = 2 THEN 1 END) AS late,
        COUNT(CASE WHEN r.field_situation = 1 THEN 1 END) AS noTraffic,
        COUNT(CASE WHEN r.field_situation = 2 THEN 1 END) AS traffic
        FROM xp_cruise_check_in_record r
        LEFT JOIN xp_cruise_check_in_rule cr ON r.cruise_check_in_rule_id = cr.id AND cr.del_flag = '0'
        LEFT JOIN xp_operations_user u ON r.operations_user_id = u.id AND u.del_flag = '0'
        LEFT JOIN xp_fleet_operations fo ON u.id = fo.operationsUserId
        LEFT JOIN xp_fleet f ON fo.fleetId = f.id
        WHERE r.del_flag = '0'
        AND r.check_in_time IS NOT NULL
        <if test="query.ruleName != null and query.ruleName != ''">
            AND cr.name LIKE CONCAT('%', #{query.ruleName}, '%')
        </if>
        <if test="query.fleet != null and query.fleet != ''">
            AND f.fleet_name LIKE CONCAT('%', #{query.fleet}, '%')
        </if>
        <if test="query.startDate != null">
            AND DATE(r.check_in_time) &gt;= #{query.startDate}
        </if>
        <if test="query.endDate != null">
            AND DATE(r.check_in_time) &lt;= #{query.endDate}
        </if>
        GROUP BY DATE(r.check_in_time)
        ORDER BY date DESC
    </select>
</mapper>
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpTaskMapper.xml
@@ -183,4 +183,47 @@
        ORDER BY handle_time DESC limit 1
    </select>
    <select id="reassignTaskPageList" resultType="com.xiaopeng.api.vo.TaskVO">
        SELECT
            t.id,
            t.task_code AS taskCode,
            t.task_category AS taskCategory,
            t.task_type_id AS taskTypeId,
            t.error_type_id AS accidentTypeId,
            t.task_urgency_level AS taskUrgencyLevel,
            t.task_description AS taskDescription,
            t.vehicle_id AS vehicleId,
            t.handle_user_id AS handleUserId,
            t.assignee_user_id AS assigneeUserId,
            t.status,
            t.reassignment_status AS reassignmentStatus,
            t.create_time AS createTime,
            v.plate_number AS plateNumber,
            et.error_name AS accidentTypeName
        FROM xp_task t
        LEFT JOIN xp_vehicle v ON t.vehicle_id = v.id AND v.is_deleted = 0
        LEFT JOIN xp_error_type et ON t.error_type_id = et.id
        WHERE t.is_deleted = 0
        AND t.reassignment_status = 1
        <if test="query.taskCategory != null">
            AND t.task_category = #{query.taskCategory}
        </if>
        <if test="query.accidentTypeId != null">
            AND t.error_type_id = #{query.accidentTypeId}
        </if>
        <if test="query.taskTypeId != null">
            AND t.task_type_id = #{query.taskTypeId}
        </if>
        <if test="query.taskUrgencyLevel != null">
            AND t.task_urgency_level = #{query.taskUrgencyLevel}
        </if>
        <if test="query.plateNumber != null and query.plateNumber != ''">
            AND v.plate_number LIKE CONCAT('%', #{query.plateNumber}, '%')
        </if>
        <if test="query.reassignmentStatus != null and query.reassignmentStatus != ''">
            AND t.reassignment_status = #{query.reassignmentStatus}
        </if>
        ORDER BY t.create_time DESC,t.task_urgency_level ASC
    </select>
</mapper>
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/config/SnowflakeConfig.java
New file
@@ -0,0 +1,57 @@
package com.xiaopeng.operation.config;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class SnowflakeConfig {
    //初始时间戳,设为2026年1月1日0点0时0分
    public static final Date EPOCH_DATE = new Date(1767225600000L);
    /**
     * 如果配置为<0的值,则woker-id根据pod名的hash取模生成
     * 如果配置为>=0的值,则取配置的值
     * 如果多个pod的data-center-id和worker-id相同,同一毫秒内请求数上千的话,可能会产生碰撞,生成一样的snowflake id
     */
    @Value("${snowflake.worker-id:-1}")
    private long workerId;
    @Value("${snowflake.data-center-id:0}")
    private long dataCenterId;
    @Bean("hutoolSnowflake")
    public Snowflake snowflake() {
        long resolvedWorkerId = resolveWorkerId();
        return new Snowflake(EPOCH_DATE, resolvedWorkerId, dataCenterId, false);
    }
    private long resolveWorkerId() {
        if (workerId >= 0 && workerId <= Snowflake.MAX_WORKER_ID) {
            return workerId;
        }
        String podName = System.getenv("HOSTNAME");
        if (podName == null || podName.isEmpty()) {
            return 0;
        }
        int end = podName.length() - 1;
        while (end >= 0 && Character.isDigit(podName.charAt(end))) {
            end--;
        }
        String numberPart = podName.substring(end + 1);
        long candidate;
        if (!numberPart.isEmpty()) {
            try {
                candidate = Long.parseLong(numberPart);
            } catch (NumberFormatException e) {
                candidate = Math.abs(podName.hashCode());
            }
        } else {
            candidate = Math.abs(podName.hashCode());
        }
        return candidate % (Snowflake.MAX_WORKER_ID + 1);
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/OssController.java
@@ -35,22 +35,22 @@
    public R<FileUploadVO> uploadOSS(@RequestParam("file") MultipartFile file) {
        try {
            // 上传并返回访问地址
            String fileName = file.getOriginalFilename();
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            long fileSize = file.getSize();
            String fileId = UUID.randomUUID().toString();
            //上传文件
            aliOssService.uploadFile(file.getBytes(), fileId);
            String downloadUrl = aliOssService.getDownloadUrl(fileId, fileName,true);
            FileUploadVO fileUploadVO = new FileUploadVO();
            fileUploadVO.setId(fileId);
            fileUploadVO.setName(fileName);
            fileUploadVO.setUrl(downloadUrl);
//            String fileName = file.getOriginalFilename();
//            String prefix = fileName.substring(fileName.lastIndexOf("."));
//            long fileSize = file.getSize();
//            String fileId = UUID.randomUUID().toString();
//            //上传文件
//            aliOssService.uploadFile(file.getBytes(), fileId);
//            String downloadUrl = aliOssService.getDownloadUrl(fileId, fileName,true);
//            FileUploadVO fileUploadVO = new FileUploadVO();
//            fileUploadVO.setId(UUID.randomUUID().toString());
//            fileUploadVO.setName("测试.jpg");
//            fileUploadVO.setUrl("https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png");
//            fileUploadVO.setId(fileId);
//            fileUploadVO.setName(fileName);
//            fileUploadVO.setUrl(downloadUrl);
            FileUploadVO fileUploadVO = new FileUploadVO();
            fileUploadVO.setId(UUID.randomUUID().toString());
            fileUploadVO.setName("测试.jpg");
            fileUploadVO.setUrl("https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png");
            return R.ok(fileUploadVO);
        } catch (Exception e) {
            System.err.println("上传文件失败"+e);
@@ -66,22 +66,22 @@
    public R<FileUploadVO> uploadOSS1(@RequestParam("file") MultipartFile file) {
        try {
            // 上传并返回访问地址
            String fileName = file.getOriginalFilename();
            String prefix = fileName.substring(fileName.lastIndexOf("."));
            long fileSize = file.getSize();
            String fileId = UUID.randomUUID().toString();
            //上传文件
            aliOssService.uploadFile(file.getBytes(), fileId);
            String downloadUrl = aliOssService.getDownloadUrl(fileId, fileName,true);
            FileUploadVO fileUploadVO = new FileUploadVO();
            fileUploadVO.setId(fileId);
            fileUploadVO.setName(fileName);
            fileUploadVO.setUrl(downloadUrl);
//            String fileName = file.getOriginalFilename();
//            String prefix = fileName.substring(fileName.lastIndexOf("."));
//            long fileSize = file.getSize();
//            String fileId = UUID.randomUUID().toString();
//            //上传文件
//            aliOssService.uploadFile(file.getBytes(), fileId);
//            String downloadUrl = aliOssService.getDownloadUrl(fileId, fileName,true);
//            FileUploadVO fileUploadVO = new FileUploadVO();
//            fileUploadVO.setId(UUID.randomUUID().toString());
//            fileUploadVO.setName("测试.jpg");
//            fileUploadVO.setUrl("https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png");
//            fileUploadVO.setId(fileId);
//            fileUploadVO.setName(fileName);
//            fileUploadVO.setUrl(downloadUrl);
            FileUploadVO fileUploadVO = new FileUploadVO();
            fileUploadVO.setId(UUID.randomUUID().toString());
            fileUploadVO.setName("测试.jpg");
            fileUploadVO.setUrl("https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png");
            return R.ok(fileUploadVO);
        } catch (Exception e) {
            System.err.println("上传文件失败"+e);
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpCruisePlanController.java
@@ -1,6 +1,7 @@
package com.xiaopeng.operation.controller;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.dto.operation.CruisePointDto;
@@ -34,6 +35,7 @@
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.validation.Valid;
import org.springframework.web.bind.annotation.PathVariable;
@@ -61,6 +63,9 @@
    private final IXpCruisePlanPointService xpCruisePlanPointService;
    private final XpPointService pointService;
    private final XpVehicleClient xpVehicleClient;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    @ApiOperation(value = "获取巡游计划分页列表", tags = {"管理后台-巡游计划"})
    @PostMapping(value = {"/api/v1/xp-cruise-plan/pageList"})
@@ -205,6 +210,8 @@
        newXpCruiseOrder.setMissionId(plan.getCruisePlanId());
        newXpCruiseOrder.setStatus(1);
        newXpCruiseOrder.setOrderReverse(1);
        newXpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
        GeoJsonPoint point = dto.getPoint();
        // 起点
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPricingServiceImpl.java
@@ -1,6 +1,7 @@
package com.xiaopeng.operation.service.impl;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -123,6 +124,9 @@
    @Autowired
    private XpPointService xpPointService;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    // 自定义线程池用于并行执行任务
@@ -515,6 +519,7 @@
        xpOrder.setEndPointId(dto.getEndPointId());
        xpOrder.setStartPointName(xpPoint.getPointName());
        xpOrder.setEndPointName(endXpPoint.getPointName());
        xpOrder.setXpuTaskId(snowflake.nextId() + "");
        // 当前时段
        String currentTimeSlot = DateUtils.getCurrentTimeSlot();
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -347,6 +347,7 @@
                                        // 下发XPU命令
                                        PushOrderDto pushOrderDto = new PushOrderDto();
                                        pushOrderDto.setVin(priorityVin);
                                        pushOrderDto.setTaskId(orderCheck.getData().getXpuTaskId());
                                        pushOrderDto.setOrderId(orderCheck.getData().getId().toString());
                                        pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat());
                                        pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon());
@@ -1009,6 +1010,7 @@
                        log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo);
                        // 下发命令
                        PushOrderDto pushOrderDto = new PushOrderDto();
                        pushOrderDto.setTaskId(xpOrder.getXpuTaskId());
                        pushOrderDto.setVin(vehiclePosition.getVehicleVin());
                        pushOrderDto.setOrderId(xpOrder.getId().toString());
                        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
@@ -1071,6 +1073,7 @@
                        log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo);
                        PushOrderDto pushOrderDto = buildPushOrderDto(xpOrder);
                        pushOrderDto.setVin(vehiclePosition.getVin());
                        pushOrderDto.setTaskId(xpOrder.getXpuTaskId());
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber());
@@ -1154,6 +1157,7 @@
                routeToOrigin.setDistance(routeToOrigin.getDistance() + routeRemain.getDistance());
                PushOrderDto pushOrderDto = buildPushOrderDto(xpOrder);
                pushOrderDto.setVin(xpVehicle.getVehicleVin());
                pushOrderDto.setTaskId(xpOrder.getXpuTaskId());
                // 订单流转
                orderMissionClient.pushOrder(pushOrderDto);
                redisService.setCacheObject(CacheConstants.nextOrder(luckyOder.getId().toString()), xpOrder.getId());
@@ -1333,6 +1337,7 @@
                }
                PushOrderDto pushOrderDto = new PushOrderDto();
                pushOrderDto.setTaskId(data.getXpuTaskId());
                pushOrderDto.setVin(vehiclePosition.getVin());
                pushOrderDto.setOrderId(data.getId().toString());
                pushOrderDto.setStartLatitude(data.getStartLat());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/config/SnowflakeConfig.java
New file
@@ -0,0 +1,57 @@
package com.xiaopeng.order.config;
import cn.hutool.core.lang.Snowflake;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Date;
@Configuration
public class SnowflakeConfig {
    //初始时间戳,设为2026年1月1日0点0时0分
    public static final Date EPOCH_DATE = new Date(1767225600000L);
    /**
     * 如果配置为<0的值,则woker-id根据pod名的hash取模生成
     * 如果配置为>=0的值,则取配置的值
     * 如果多个pod的data-center-id和worker-id相同,同一毫秒内请求数上千的话,可能会产生碰撞,生成一样的snowflake id
     */
    @Value("${snowflake.worker-id:-1}")
    private long workerId;
    @Value("${snowflake.data-center-id:0}")
    private long dataCenterId;
    @Bean("hutoolSnowflake")
    public Snowflake snowflake() {
        long resolvedWorkerId = resolveWorkerId();
        return new Snowflake(EPOCH_DATE, resolvedWorkerId, dataCenterId, false);
    }
    private long resolveWorkerId() {
        if (workerId >= 0 && workerId <= Snowflake.MAX_WORKER_ID) {
            return workerId;
        }
        String podName = System.getenv("HOSTNAME");
        if (podName == null || podName.isEmpty()) {
            return 0;
        }
        int end = podName.length() - 1;
        while (end >= 0 && Character.isDigit(podName.charAt(end))) {
            end--;
        }
        String numberPart = podName.substring(end + 1);
        long candidate;
        if (!numberPart.isEmpty()) {
            try {
                candidate = Long.parseLong(numberPart);
            } catch (NumberFormatException e) {
                candidate = Math.abs(podName.hashCode());
            }
        } else {
            candidate = Math.abs(podName.hashCode());
        }
        return candidate % (Snowflake.MAX_WORKER_ID + 1);
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/CustomerServiceController.java
@@ -106,7 +106,7 @@
        }
        List<ServiceVehicleListVo> collect = serviceVehicleList.getData().stream().map(xpVehicle -> {
            ServiceVehicleListVo vo = new ServiceVehicleListVo();
            vo.setVim(xpVehicle.getVehicleVin());
            vo.setVin(xpVehicle.getVehicleVin());
            vo.setPlateNumber(xpVehicle.getPlateNumber());
            return vo;
        }).collect(Collectors.toList());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpCruiseOrderController.java
@@ -115,6 +115,7 @@
        // 下发命令
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setTaskId(order.getXpuTaskId());
        pushOrderDto.setVin(order.getVehicleVin());
        pushOrderDto.setOrderId("XU" + order.getId());
        pushOrderDto.setStartLatitude(order.getStartLat());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/PushChainReactionOrderJob.java
@@ -49,6 +49,7 @@
            log.info("完成连环单用户车辆绑定关系 {}", xpOrder.getOrderNumber());
            //开始将新订单推送给车端
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setTaskId(xpOrder.getXpuTaskId());
            pushOrderDto.setOrderId(xpOrder.getId().toString());
            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
            pushOrderDto.setStartLongitude(xpOrder.getStartLon());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -2,6 +2,7 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
@@ -181,6 +182,9 @@
    @Value("${robotaxi.appId:xp_robotaxi_api}")
    private String appid;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
    @Override
@@ -1104,6 +1108,7 @@
            // 11.2 下发订单到新车辆
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setTaskId(order.getXpuTaskId());
            pushOrderDto.setVin(newVehicle.getVehicleVin());
            pushOrderDto.setOrderId(order.getId().toString());
            pushOrderDto.setStartLatitude(order.getStartLat());
@@ -1182,6 +1187,7 @@
            returnOrder.setLastOrderId(lastCruise.getId());
            returnOrder.setCreateTime(LocalDateTime.now());
            returnOrder.setMissionId(lastCruise.getMissionId());
            returnOrder.setXpuTaskId(snowflake.nextId() + "");
            // 返程起点 = 当前订单的终点(车辆当前位置附近)
            returnOrder.setStartPointId(order.getEndPointId());
@@ -1220,6 +1226,7 @@
            // 下发巡游订单到原车辆
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setTaskId(returnOrder.getXpuTaskId());
            pushOrderDto.setVin(oldVehicle.getVehicleVin());
            pushOrderDto.setOrderId("XU" + returnOrder.getId());
            pushOrderDto.setStartLatitude(returnOrder.getStartLat());
@@ -2557,6 +2564,7 @@
        xpCruiseOrder.setStartPointName(order.getEndPointName());
        xpCruiseOrder.setStartLon(order.getEndLon());
        xpCruiseOrder.setStartLat(order.getEndLat());
        xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
        // 完成的直接走终点   终止的走起点
        if(null != xpCruiseOrders){
@@ -2617,6 +2625,7 @@
        log.info("添加巡游单成功 {}", xpCruiseOrder.getId());
        //下发XUP巡游订单报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setTaskId(xpCruiseOrder.getXpuTaskId());
        pushOrderDto.setVin(xpCruiseOrder.getVehicleVin());
        pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId());
        pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat());
@@ -2664,6 +2673,7 @@
        xpCruiseOrder.setFleetId(vehicle.getFleetId());
        xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin());
        xpCruiseOrder.setOrderType(2);
        xpCruiseOrder.setXpuTaskId(snowflake.nextId() + "");
        // 返程起点是当前正常订单的终点
        xpCruiseOrder.setStartPointId(null);
        xpCruiseOrder.setStartPointName(null);
@@ -2733,6 +2743,7 @@
        //下发XPU消息报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setTaskId(xpCruiseOrder.getXpuTaskId());
        pushOrderDto.setVin(xpCruiseOrder.getVehicleVin());
        pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId());
        pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat());
@@ -2989,6 +3000,10 @@
            this.updateById(order);
        }
        res.setTime(new BigDecimal(order.getDuration() == null ? 0 : order.getDuration()).multiply(new BigDecimal(60)).setScale(0, RoundingMode.HALF_UP));
        XpSystemSetting xpSystemSetting = xpSystemSettingClient.getSystemSettingOne().getData();
        if(null != xpSystemSetting){
            res.setOperateFree(xpSystemSetting.getOperateFree());
        }
        return R.ok(res);
    }
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpTestOrderServiceImpl.java
@@ -2,6 +2,7 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -138,6 +139,9 @@
    @Resource
    private BootCommonService bootCommonService;
    @Resource(name = "hutoolSnowflake")
    private Snowflake snowflake;
@@ -242,6 +246,7 @@
        xpOrder.setStatus(1);
        xpOrder.setOrderSource(1);
        xpOrder.setOpenTrunk(2);
        xpOrder.setXpuTaskId(snowflake.nextId() + "");
        // 当前时段
        String currentTimeSlot = DateUtils.getCurrentTimeSlot();
@@ -262,6 +267,7 @@
            redisService.setCacheObject("TEST_ORDER_NAVIGATION_END_DATA:" + vehicleId, JSON.toJSONString(routeVo), 24L, TimeUnit.HOURS);
            //下发XPU消息
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setTaskId(xpOrder.getXpuTaskId());
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setOrderId("TEST" + xpOrder.getId());
            pushOrderDto.setStartLatitude(xpOrder.getStartLat());
@@ -823,6 +829,7 @@
        try {
            // 11.2 下发订单到新车辆
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setTaskId(order.getXpuTaskId());
            pushOrderDto.setVin(newVehicle.getVehicleVin());
            pushOrderDto.setOrderId("TEST" + order.getId());
            pushOrderDto.setStartLatitude(order.getStartLat());
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/vo/ServiceVehicleListVo.java
@@ -8,8 +8,8 @@
@Data
@ApiModel
public class ServiceVehicleListVo {
    @ApiModelProperty("vim码")
    private String vim;
    @ApiModelProperty("vin码")
    private String vin;
    @ApiModelProperty("车牌号")
    private String plateNumber;
}
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/handler/PositionMsgHandler.java
@@ -37,12 +37,16 @@
    private void saveToMongo(XpOperationsUserPositionDTO dto) {
        XpOperationsUserPositionDTO vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("id").is(dto.getId())), XpOperationsUserPositionDTO.class);
        if (null == vehiclePosition) {
            double[] location = {dto.getLongitude(), dto.getLatitude()};
            dto.setLocation(location);
            mongoTemplate.save(dto);
        }else{
            Update update = new Update()
                    .set("id",dto.getId())
                    .set("latitude", dto.getLatitude())
                    .set("latitude", dto.getLongitude());
                    .set("longitude", dto.getLongitude());
            double[] location = {dto.getLongitude(), dto.getLatitude()};
            update.set("location", location);
            mongoTemplate.updateFirst(new Query(Criteria.where("id").is(dto.getId())), update, XpOperationsUserPositionDTO.class);
        }
    }