liujie
2026-03-18 15c0a773a587243e6fae4293d990c3c73f308792
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi
2个文件已添加
15个文件已修改
367 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automaticPilot/VmpOpenServiceClientFallbackFactory.java 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automaticPilot/VmpOpenServiceClient.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/AccidentTaskNotificationSupport.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/InsuranceInspectionScheduleTask.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/RoutinePreparationScheduleTask.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleChargingScheduleTask.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCleanScheduleTask.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleInspectionScheduleTask.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleMaintenanceScheduleTask.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/VehicleLocationFillService.java 116 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAgreementServiceImpl.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/automaticPilot/VmpOpenServiceClientFallbackFactory.java
New file
@@ -0,0 +1,40 @@
package com.xiaopeng.api.factory.automaticPilot;
import com.xiaopeng.api.dto.automaticPilot.VehicleBaseRespDto;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.automaticPilot.VmpOpenServiceClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.openfeign.FallbackFactory;
import org.springframework.stereotype.Component;
import java.util.Collections;
import java.util.List;
import java.util.Map;
@Slf4j
@Component
public class VmpOpenServiceClientFallbackFactory implements FallbackFactory<VmpOpenServiceClient> {
    @Override
    public VmpOpenServiceClient create(Throwable cause) {
        return new VmpOpenServiceClient(){
            @Override
            public VehicleBaseRespDto getVehicleInfoByVin(String vin, List<String> respList) {
                log.info("通过vin获取车辆基本信息失败:" + cause.getMessage());
                return null;
            }
            @Override
            public Map<String, String> getVehicleBindInfoByVin(String vin, List<String> typeList) {
                log.info("查询车辆绑定信息失败:" + cause.getMessage());
                return Collections.emptyMap();
            }
            @Override
            public String getVinByXpuId(String xpuId, Integer type) {
                log.info("通过车辆绑定信息获取车架号失败:" + cause.getMessage());
                return "";
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpOrderClientFallbackFactory.java
@@ -102,6 +102,12 @@
                log.error("保存订单轨迹数据失败,原因: {}", cause.getMessage());
                return R.fail("保存订单轨迹数据失败");
            }
            @Override
            public R<?> endTrip(Long orderId) {
                log.error("内部调用-结束订单失败,原因: {}", cause.getMessage());
                return R.fail("内部调用-结束订单失败:" + cause.getMessage());
            }
        };
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/automaticPilot/VmpOpenServiceClient.java
@@ -1,6 +1,9 @@
package com.xiaopeng.api.feignClient.automaticPilot;
import com.xiaopeng.api.dto.automaticPilot.VehicleBaseRespDto;
import com.xiaopeng.api.factory.automaticPilot.OrderMissionClientFallbackFactory;
import com.xiaopeng.api.factory.automaticPilot.VmpOpenServiceClientFallbackFactory;
import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@@ -8,7 +11,10 @@
import java.util.List;
import java.util.Map;
@FeignClient(name = "xp-vmp-open-boot")
@FeignClient(contextId = "VmpOpenServiceClient",
        value = "xp-vmp-open-boot",
        fallbackFactory = VmpOpenServiceClientFallbackFactory.class)
public interface VmpOpenServiceClient {
    /**
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpOrderClient.java
@@ -120,4 +120,14 @@
    @PostMapping("/inner/v1/order/saveVehicleLocation")
    R<String> saveVehicleLocation(@RequestBody OrderTrajectoryVo orderTrajectory);
    /**
     * 内部调用-结束订单
     * @param orderId
     * @return
     */
    @PostMapping("/inner/order/endTrip")
    R<?> endTrip(@RequestParam Long orderId);
}
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -859,8 +859,9 @@
                case ORDER_CANCELLED:
                    //已取消
                    if(!orderId.contains("XU")){
                        buildPushOrderStatus(orderId, OrderStatusEnum.CANCELED, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.CANCELED.getCode());
                        //行程中取消订单,按照行程结束处理
                        buildPushOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS, sequence);
                        xpOrderClient.updateOrderStatus(Long.parseLong(orderId), OrderStatusEnum.SEE_OFF_GUESTS.getCode());
                    }
                    break;
                case ORDER_ARRIVED_AT_CRUISE_DESTINATION:
@@ -961,6 +962,7 @@
            if (R.isError(stringR)) {
                log.error("推送消息失败:{}", stringR.getMsg());
            }
        }
    }
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -367,9 +367,9 @@
        // 10. 检查等待时间
        Integer waitTime = getWaitTime(routeAndFareDto.getOrigin().getLongitude(), routeAndFareDto.getOrigin().getLatitude());
        if (waitTime > 3) {
            throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
        }
//        if (waitTime > 3) {
//            throw new ServiceException("当前区域正在等待中,请耐心等待", I18nKeyConstant.WAITING_TIME);
//        }
        fareVo.setWaitingTime(waitTime);
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/AccidentTaskNotificationSupport.java
@@ -185,7 +185,7 @@
                        .body(bodyJson)
                        .account(account)
                        .title(title)
                        .pushType(AliPushTypeConstant.MESSAGE)
                        .pushType(AliPushTypeConstant.NOTICE)
                        .deviceType(entry.getKey())
                        .build());
                pushCount++;
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/InsuranceInspectionScheduleTask.java
@@ -9,11 +9,13 @@
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +23,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -66,6 +69,9 @@
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每天凌晨1点执行一次
@@ -149,6 +155,14 @@
        log.info("找到 {} 辆运营中的车辆", vehicles.size());
        Map<String, VehiclePosition> positionByVin = vehicleLocationFillService.loadPositionByVin(
                vehicles.stream()
                        .map(XpVehicle::getVehicleVin)
                        .filter(StringUtils::hasLength)
                        .distinct()
                        .collect(Collectors.toList())
        );
        Map<Long, Long> vehicleIdToFleetIdCache = new HashMap<>();
        Map<Long, Set<Long>> fleetIdToOperationUserIdsCache = new HashMap<>();
@@ -156,15 +170,15 @@
        // 3. 检查保险到期
        totalCreatedCount += checkAndCreateInsuranceExpireTasks(vehicles, roleOperationUserIdSet, taskRule,
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache, positionByVin);
        // 4. 检查年检到期
        totalCreatedCount += checkAndCreateInspectionExpireTasks(vehicles, roleOperationUserIdSet, taskRule,
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache, positionByVin);
        // 5. 检查运营资质到期
        totalCreatedCount += checkAndCreateQualificationExpireTasks(vehicles, roleOperationUserIdSet, taskRule,
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
                vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache, positionByVin);
        return totalCreatedCount;
    }
@@ -180,7 +194,8 @@
     * @return 创建的任务数量
     */
    private int checkAndCreateInsuranceExpireTasks(List<XpVehicle> vehicles, Set<Long> roleOperationUserIds, XpTaskRule taskRule,
                                                   Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache) {
                                                   Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache,
                                                   Map<String, VehiclePosition> positionByVin) {
        if (taskRule.getInsuranceExpires() == null || taskRule.getInsuranceExpires() <= 0) {
            log.info("保险到期提醒天数未配置,跳过保险到期检查");
            return 0;
@@ -205,7 +220,8 @@
                TaskScheduleConstants.TASK_TYPE_INSURANCE_EXPIRE,
                "保险即将到期",
                vehicleIdToFleetIdCache,
                fleetIdToOperationUserIdsCache
                fleetIdToOperationUserIdsCache,
                positionByVin
        );
    }
@@ -220,7 +236,8 @@
     * @return 创建的任务数量
     */
    private int checkAndCreateInspectionExpireTasks(List<XpVehicle> vehicles, Set<Long> roleOperationUserIds, XpTaskRule taskRule,
                                                    Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache) {
                                                    Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache,
                                                    Map<String, VehiclePosition> positionByVin) {
        if (taskRule.getInsuranceInspectionExpires() == null || taskRule.getInsuranceInspectionExpires() <= 0) {
            log.info("年检到期提醒天数未配置,跳过年检到期检查");
            return 0;
@@ -245,7 +262,8 @@
                TaskScheduleConstants.TASK_TYPE_INSPECTION_EXPIRE,
                "年检即将到期",
                vehicleIdToFleetIdCache,
                fleetIdToOperationUserIdsCache
                fleetIdToOperationUserIdsCache,
                positionByVin
        );
    }
@@ -260,7 +278,8 @@
     * @return 创建的任务数量
     */
    private int checkAndCreateQualificationExpireTasks(List<XpVehicle> vehicles, Set<Long> roleOperationUserIds, XpTaskRule taskRule,
                                                       Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache) {
                                                       Map<Long, Long> vehicleIdToFleetIdCache, Map<Long, Set<Long>> fleetIdToOperationUserIdsCache,
                                                       Map<String, VehiclePosition> positionByVin) {
        if (taskRule.getOperationQualificationExpires() == null || taskRule.getOperationQualificationExpires() <= 0) {
            log.info("运营资质到期提醒天数未配置,跳过运营资质到期检查");
            return 0;
@@ -285,7 +304,8 @@
                TaskScheduleConstants.TASK_TYPE_QUALIFICATION_EXPIRE,
                "运营资质即将到期",
                vehicleIdToFleetIdCache,
                fleetIdToOperationUserIdsCache
                fleetIdToOperationUserIdsCache,
                positionByVin
        );
    }
@@ -347,7 +367,8 @@
    private int createTasksForExpireType(List<XpVehicle> vehicles, Set<Long> roleOperationUserIds,
                                         XpTaskRule taskRule, String taskTypeId, String taskDescription,
                                         Map<Long, Long> vehicleIdToFleetIdCache,
                                         Map<Long, Set<Long>> fleetIdToOperationUserIdsCache) {
                                         Map<Long, Set<Long>> fleetIdToOperationUserIdsCache,
                                         Map<String, VehiclePosition> positionByVin) {
        List<XpTask> tasksToSave = new ArrayList<>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int skippedCount = 0;
@@ -378,6 +399,7 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            vehicleLocationFillService.fillFromVin(task, vehicle.getVehicleVin(), positionByVin);
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/RoutinePreparationScheduleTask.java
@@ -9,11 +9,13 @@
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +23,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -66,6 +69,9 @@
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每分钟检查一次是否需要执行任务下发
@@ -354,6 +360,14 @@
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int skippedCount = 0;
        Map<String, VehiclePosition> positionByVin = vehicleLocationFillService.loadPositionByVin(
                vehicles.stream()
                        .map(XpVehicle::getVehicleVin)
                        .filter(StringUtils::hasLength)
                        .distinct()
                        .collect(Collectors.toList())
        );
        for (XpVehicle vehicle : vehicles) {
            List<Long> handleUserIds = resolveHandleUserIds(vehicle.getId(), roleOperationUserIds,
                    vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
@@ -380,6 +394,7 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            vehicleLocationFillService.fillFromVin(task, vehicle.getVehicleVin(), positionByVin);
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleChargingScheduleTask.java
@@ -15,6 +15,7 @@
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -73,6 +74,9 @@
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每分钟执行一次电量检测
@@ -321,10 +325,7 @@
        task.setTaskDescription(desc);
        task.setVehicleId(vehicle.getId());
        if (position.getPoint() != null) {
            task.setVehicleLon(BigDecimal.valueOf(position.getPoint().getX()));
            task.setVehicleLat(BigDecimal.valueOf(position.getPoint().getY()));
        }
        vehicleLocationFillService.fillFromPosition(task, vehicle.getVehicleVin(), position);
        // 常规任务默认限时3天
        task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCleanScheduleTask.java
@@ -9,11 +9,13 @@
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +23,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -66,6 +69,9 @@
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每分钟检查一次是否需要执行任务下发
@@ -354,6 +360,14 @@
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int skippedCount = 0;
        Map<String, VehiclePosition> positionByVin = vehicleLocationFillService.loadPositionByVin(
                vehicles.stream()
                        .map(XpVehicle::getVehicleVin)
                        .filter(StringUtils::hasLength)
                        .distinct()
                        .collect(Collectors.toList())
        );
        for (XpVehicle vehicle : vehicles) {
            List<Long> handleUserIds = resolveHandleUserIds(vehicle.getId(), roleOperationUserIds,
                    vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
@@ -380,6 +394,7 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            vehicleLocationFillService.fillFromVin(task, vehicle.getVehicleVin(), positionByVin);
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleInspectionScheduleTask.java
@@ -9,11 +9,13 @@
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +23,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -66,6 +69,9 @@
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每分钟检查一次是否需要执行任务下发
@@ -314,6 +320,14 @@
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int skippedCount = 0;
        Map<String, VehiclePosition> positionByVin = vehicleLocationFillService.loadPositionByVin(
                vehicles.stream()
                        .map(XpVehicle::getVehicleVin)
                        .filter(StringUtils::hasLength)
                        .distinct()
                        .collect(Collectors.toList())
        );
        for (XpVehicle vehicle : vehicles) {
            List<Long> handleUserIds = resolveHandleUserIds(vehicle.getId(), roleOperationUserIds,
                    vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
@@ -340,6 +354,7 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            vehicleLocationFillService.fillFromVin(task, vehicle.getVehicleVin(), positionByVin);
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleMaintenanceScheduleTask.java
@@ -9,11 +9,13 @@
import com.xiaopeng.api.model.maintenance.XpTaskRule;
import com.xiaopeng.api.model.maintenance.XpTaskRuleRole;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.api.vo.maintenance.TaskScheduleConstants;
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
import com.xiaopeng.maintenance.service.VehicleLocationFillService;
import com.xiaopeng.maintenance.utils.UUIDUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -21,6 +23,7 @@
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
@@ -66,6 +69,9 @@
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private VehicleLocationFillService vehicleLocationFillService;
    /**
     * 每分钟检查一次是否需要执行任务下发
@@ -340,6 +346,14 @@
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
        int skippedCount = 0;
        Map<String, VehiclePosition> positionByVin = vehicleLocationFillService.loadPositionByVin(
                vehicles.stream()
                        .map(XpVehicle::getVehicleVin)
                        .filter(StringUtils::hasLength)
                        .distinct()
                        .collect(Collectors.toList())
        );
        for (XpVehicle vehicle : vehicles) {
            List<Long> handleUserIds = resolveHandleUserIds(vehicle.getId(), roleOperationUserIds,
                    vehicleIdToFleetIdCache, fleetIdToOperationUserIdsCache);
@@ -366,6 +380,7 @@
            // 设置车辆信息
            task.setVehicleId(vehicle.getId());
            vehicleLocationFillService.fillFromVin(task, vehicle.getVehicleVin(), positionByVin);
            // 设置任务时限 常规任务限时3天
            task.setEndTime(LocalDateTime.now().plusDays(3));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/VehicleLocationFillService.java
New file
@@ -0,0 +1,116 @@
package com.xiaopeng.maintenance.service;
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.maintenance.utils.GDMapGeocodingUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@Slf4j
@Service
public class VehicleLocationFillService {
    private static final String DEFAULT_VEHICLE_LOCATION = "四川省成都市双流区西航港街道机场路近都段辅路空港16区";
    private static final BigDecimal DEFAULT_VEHICLE_LON = new BigDecimal("104.001118");
    private static final BigDecimal DEFAULT_VEHICLE_LAT = new BigDecimal("30.575685");
    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    public Map<String, VehiclePosition> loadPositionByVin(Collection<String> vins) {
        if (CollectionUtils.isEmpty(vins)) {
            return Collections.emptyMap();
        }
        List<String> distinctVins = vins.stream()
                .filter(StringUtils::hasLength)
                .distinct()
                .collect(java.util.stream.Collectors.toList());
        if (CollectionUtils.isEmpty(distinctVins)) {
            return Collections.emptyMap();
        }
        try {
            Query query = new Query(Criteria.where("vin").in(distinctVins));
            List<VehiclePosition> positions = mongoTemplate.find(query, VehiclePosition.class);
            if (CollectionUtils.isEmpty(positions)) {
                return Collections.emptyMap();
            }
            Map<String, VehiclePosition> map = new HashMap<>();
            for (VehiclePosition position : positions) {
                if (position == null || !StringUtils.hasLength(position.getVin())) {
                    continue;
                }
                map.putIfAbsent(position.getVin(), position);
            }
            return map;
        } catch (Exception e) {
            log.error("查询车辆实时定位失败 vins={}", vins, e);
            return Collections.emptyMap();
        }
    }
    public void fillFromVin(com.xiaopeng.api.model.maintenance.XpTask task,
                            String vin,
                            Map<String, VehiclePosition> positionByVin) {
        if (task == null) {
            return;
        }
        if (!StringUtils.hasLength(vin)) {
            applyDefault(task);
            return;
        }
        VehiclePosition vehiclePosition = positionByVin == null ? null : positionByVin.get(vin);
        fillFromPosition(task, vin, vehiclePosition);
    }
    public void fillFromPosition(com.xiaopeng.api.model.maintenance.XpTask task,
                                 String vin,
                                 VehiclePosition vehiclePosition) {
        if (task == null) {
            return;
        }
        if (vehiclePosition == null || vehiclePosition.getPoint() == null) {
            applyDefault(task);
            return;
        }
        double lon = vehiclePosition.getPoint().getX();
        double lat = vehiclePosition.getPoint().getY();
        task.setVehicleLon(BigDecimal.valueOf(lon));
        task.setVehicleLat(BigDecimal.valueOf(lat));
        try {
            Map<String, String> geocode = gdMapGeocodingUtil.geocode(String.valueOf(lon), String.valueOf(lat));
            String address = geocode == null ? null : geocode.get("address");
            if (StringUtils.hasLength(address)) {
                task.setVehicleLocation(address);
                return;
            }
            log.warn("解析车辆地址为空 vin={}, lon={}, lat={}", vin, lon, lat);
            task.setVehicleLocation(DEFAULT_VEHICLE_LOCATION);
        } catch (Exception e) {
            log.error("解析车辆地址失败 vin={}, lon={}, lat={}", vin, lon, lat, e);
            task.setVehicleLocation(DEFAULT_VEHICLE_LOCATION);
        }
    }
    private void applyDefault(com.xiaopeng.api.model.maintenance.XpTask task) {
        task.setVehicleLocation(DEFAULT_VEHICLE_LOCATION);
        task.setVehicleLon(DEFAULT_VEHICLE_LON);
        task.setVehicleLat(DEFAULT_VEHICLE_LAT);
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAgreementServiceImpl.java
@@ -12,6 +12,7 @@
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.account.XpOperationsUserNotification;
import com.xiaopeng.api.model.operation.XpAgreement;
import com.xiaopeng.common.core.constant.AliPushTypeConstant;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.NotificationTypeEnum;
import com.xiaopeng.operation.dto.XpAgreementDTO;
@@ -259,7 +260,7 @@
        dto.setAccount(accounts);
        dto.setTitle("协议政策内容更新提示");
        dto.setBody(buildAgreementPushBodyJson(message));
        dto.setPushType("NOTICE");
        dto.setPushType(AliPushTypeConstant.MESSAGE);
        return dto;
    }
@@ -408,7 +409,7 @@
        dto.setAccount(accounts);
        dto.setTitle("协议政策内容更新授权");
        dto.setBody(buildAuthPushBodyJson(message));
        dto.setPushType("NOTICE");
        dto.setPushType(AliPushTypeConstant.NOTICE);
        return dto;
    }
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -63,6 +63,8 @@
import java.util.Arrays;
import java.util.List;
import static org.bouncycastle.asn1.x500.style.RFC4519Style.uid;
/**
 * <p>
 * 订单 前端控制器
@@ -425,6 +427,19 @@
    /**
     * 内部调用-结束订单
     * @param orderId
     * @return
     */
    @PostMapping("/inner/order/endTrip")
    public R<?> endTrip(@RequestParam Long orderId){
        XpOrder xpOrder = xpOrderService.getById(orderId);
        Boolean b = xpOrderService.endTrip(orderId, xpOrder.getAppUserId().toString());
        return R.ok(b);
    }
    /**
     * +
     * 获取行程费用明细
     */
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -290,20 +290,20 @@
            if(xpOrder.getOpenTrunk()==1){
                xpOrder.setOpenTrunk(2);
                // 添加定时任务
                xpOrderClient.updateOrderStatus(xpOrder.getId(),7);
                // 推送倒计时消息 消息推送
                Map<String, Object> params = new HashMap<>();
                Map<String, Object> content = new HashMap<>();
                content.put("orderId", xpOrder.getId().toString());
                content.put("isOpen", 1);
                params.put("type", PushMessageTypeEnum.OPEN_TRUNK.getDesc());
                params.put("content", JSONObject.toJSONString(content));
                params.put("timestamp", new Date().getTime() + "");
                String message = JSONObject.toJSONString(params);
                SendMessageDTO sendMessageDTO = new SendMessageDTO();
                sendMessageDTO.setMessage(message);
                sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId()));
                xpPushMessageClient.sendStatus(sendMessageDTO);
//                xpOrderClient.updateOrderStatus(xpOrder.getId(),7);
//                // 推送倒计时消息 消息推送
//                Map<String, Object> params = new HashMap<>();
//                Map<String, Object> content = new HashMap<>();
//                content.put("orderId", xpOrder.getId().toString());
//                content.put("isOpen", 1);
//                params.put("type", PushMessageTypeEnum.OPEN_TRUNK.getDesc());
//                params.put("content", JSONObject.toJSONString(content));
//                params.put("timestamp", new Date().getTime() + "");
//                String message = JSONObject.toJSONString(params);
//                SendMessageDTO sendMessageDTO = new SendMessageDTO();
//                sendMessageDTO.setMessage(message);
//                sendMessageDTO.setAppUserId(String.valueOf(xpOrder.getAppUserId()));
//                xpPushMessageClient.sendStatus(sendMessageDTO);
            }
        }
        try {
@@ -378,7 +378,11 @@
        xpVehicle.setWarehousingTime(LocalDateTime.now());
        //绑定XPUID
        String vin = xpVehicle.getVehicleVin();
        String xpuid = xpuVinClient.getXpuIdByVin(vin).getData();
        R<String> xpuIdByVin = xpuVinClient.getXpuIdByVin(vin);
        if(200 != xpuIdByVin.getCode()){
            throw new RuntimeException(xpuIdByVin.getMsg());
        }
        String xpuid = xpuIdByVin.getData();
        xpVehicle.setXpuId(xpuid);
        this.save(xpVehicle);
        if (isInfoComplete(xpVehicle)) {
@@ -419,7 +423,11 @@
        if (vinChanged || existingVehicle == null || StringUtils.isBlank(existingVehicle.getXpuId())) {
            // 仅在 VIN 变更或原 XPUID 为空时才重新绑定 XPUID,避免不必要的远程调用
            String vin = xpVehicle.getVehicleVin();
            String xpuid = xpuVinClient.getXpuIdByVin(vin).getData();
            R<String> xpuIdByVin = xpuVinClient.getXpuIdByVin(vin);
            if(200 != xpuIdByVin.getCode()){
                throw new RuntimeException(xpuIdByVin.getMsg());
            }
            String xpuid = xpuIdByVin.getData();
            xpVehicle.setXpuId(xpuid);
        } else {
            xpVehicle.setXpuId(existingVehicle.getXpuId());
@@ -903,7 +911,7 @@
                .like(StringUtils.isNotBlank(query.getVehicleVin()), XpVehicle::getVehicleVin, query.getVehicleVin())
                .like(StringUtils.isNotBlank(query.getPlateNumber()), XpVehicle::getPlateNumber, query.getPlateNumber())
                .eq(Objects.nonNull(query.getOperatingStatus()), XpVehicle::getOperatingStatus, query.getOperatingStatus())
                .eq(Objects.nonNull(query.getElectronicId()), XpVehicle::getElectronicId, query.getOperatingStatus());
                .eq(Objects.nonNull(query.getElectronicId()), XpVehicle::getElectronicId, query.getElectronicId());
        if (Objects.nonNull(query.getStartTime())) {
            wrapper.ge(XpVehicle::getAnnualInspectionDate, LocalDateTime.of(query.getStartTime(), LocalTime.MIN));
        }