xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/SysUserController.java
@@ -74,6 +74,15 @@ PageInfo<SysUser> page = userService.getList(pageInfo, sysUserListQuery); return AjaxResult.success(page); } /** * 获取用户不分页列表 */ @GetMapping("/api/v1/sys-user/listAll") @ApiOperation(value = "账号管理不分页列表", tags = {"管理后台-账号管理"}) public R<List<SysUser>> listAll() { List<SysUser> listAll = userService.list(); return R.ok(listAll); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/pushMessage/AliPushMessageDTO.java
@@ -2,15 +2,15 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Builder; import lombok.Data; import lombok.*; import lombok.experimental.Accessors; import java.io.Serializable; @Data @Builder @Accessors(chain = true) @ApiModel(value = "ali推送消息AliPushMessageDTO") @AllArgsConstructor @NoArgsConstructor public class AliPushMessageDTO implements Serializable { @ApiModelProperty(value = "设备类型") xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/operation/XpElectronicClientFallbackFactory.java
@@ -5,6 +5,7 @@ import com.xiaopeng.api.dto.operation.ElectronicFenceUpdateDto; import com.xiaopeng.api.feignClient.operation.XpElectronicClient; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.api.query.operation.ElectronicPageListQuery; import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo; import com.xiaopeng.common.core.domain.R; @@ -67,6 +68,12 @@ log.error("根据ID列表批量查询电子围栏失败:{}", cause.getMessage()); return R.fail("根据ID列表批量查询电子围栏失败"); } @Override public R<XpElectronicFenceArea> queryElectronicFenceAreaById(Long id) { log.error("通过区域ID查询围栏失败:{}", cause.getMessage()); return R.fail("通过区域ID查询围栏失败"); } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/operation/XpElectronicClient.java
@@ -5,6 +5,7 @@ import com.xiaopeng.api.dto.operation.ElectronicFenceUpdateDto; import com.xiaopeng.api.factory.operation.XpPointClientFallbackFactory; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.api.query.operation.ElectronicPageListQuery; import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo; import com.xiaopeng.common.core.domain.R; @@ -57,4 +58,13 @@ */ @PostMapping("/api/v1/electronicFence/listByIds") R<List<XpElectronicFence>> listByIds(@RequestBody Collection<Long> electronicIdSet); /** * 根据区域ID查询电子围栏区域信息 * * @param id 区域ID * @return 区域信息 */ @PostMapping("/inner/v1/xp-electronic-fence-area/queryById") R<XpElectronicFenceArea> queryElectronicFenceAreaById(@RequestParam("id") Long id); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/XpOperationsUserNotification.java
@@ -50,4 +50,7 @@ @ApiModelProperty(value = "是否已读 0-未读 1-已读") private Integer readStatus; @ApiModelProperty(value = "阿里云推送body内容") private String notificationExt; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpTask.java
@@ -85,6 +85,6 @@ @ApiModelProperty(value = "状态 0=待到达 1=待处理 2=已完成 3=已取消") private Integer status; private String belongUserIds; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpWorkOrder.java
@@ -63,6 +63,7 @@ @ApiModelProperty(value = "处理状态 1待处理 2处理中 3已处理") private Integer handleStatus; @ApiModelProperty(value = "如果状态为待处理或者处理中 是否可以处理 0否 1是") @TableField(exist = false) private Integer isHandle; @ApiModelProperty(value = "处理人id") private Long handleUserId; @@ -72,6 +73,9 @@ @ApiModelProperty(value = "处理日志") @TableField(exist = false) private List<XpWorkOrderLog> workOrderLogs; @ApiModelProperty(value = "创建人id") private Long createById; @ApiModelProperty(value = "创建人头像") @TableField(exist = false) private String createByAvatar; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpWorkOrderLog.java
@@ -46,6 +46,10 @@ @ApiModelProperty(value = "所属处理人名称") @TableField(exist = false) private String handleUserName; @ApiModelProperty(value = "所属处理人touxiang") @TableField(exist = false) private String handleUserAvatar; @ApiModelProperty(value = "操作类型 1移交 2办结") private Integer handleType; xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/order/XpPricingCardVo.java
@@ -44,4 +44,9 @@ @ApiModelProperty(value = "优惠券") private String coupon; @ApiModelProperty("系统优惠金额") private Double systemDiscount; } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/AbstractJob.java
New file @@ -0,0 +1,35 @@ package com.xiaopeng.automaticPilot.job.base; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.order.job.utils.SpringContextsUtil; import com.xiaopeng.order.service.IXpCruiseOrderService; import com.xiaopeng.order.service.IXpOrderService; import com.xiaopeng.order.service.XpOrderTimeoutLogService; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public abstract class AbstractJob implements Job { protected Logger logger = LoggerFactory.getLogger(getClass()); @Override public abstract void execute(JobExecutionContext context) throws JobExecutionException; protected IXpOrderService xpOrderService; protected XpPushMessageClient xpPushMessageClient; protected XpOrderTimeoutLogService xpOrderTimeoutLogService; protected IXpCruiseOrderService xpCruiseOrderService; protected OrderMissionClient orderMissionClient; protected XpVehicleClient xpVehicleClient; public AbstractJob(){ this.xpOrderService = SpringContextsUtil.getBean(IXpOrderService.class); this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class); this.xpOrderTimeoutLogService = SpringContextsUtil.getBean(XpOrderTimeoutLogService.class); } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/QuartzManager.java
New file @@ -0,0 +1,129 @@ package com.xiaopeng.automaticPilot.job.base; import com.xiaopeng.order.job.base.TimeJobType; import org.quartz.*; import org.quartz.impl.StdSchedulerFactory; import java.util.Date; import java.util.Map; public class QuartzManager { private static SchedulerFactory factory = new StdSchedulerFactory(); private static final String TRIGGER_NAME_PREFIX = "TRIGGER_PREFIX_"; private static final String JOB_NAME_PREFIX = "JOB_PREFIX_"; /** * 添加定时任务:具体某个时间点执行一次的任务,如:在某个2015-06-01 12:00发送一条消息 * * @param jobName * 具体的任务名+ID标识唯一 * @param jobType * @param date * @param jp */ public synchronized static void addJob(Class<? extends Job> jobClass, String jobName, TimeJobType jobType, Date date, Map<String, ? extends Object> jp) { //logger.debug("ADD JOB {},jobName={},jobTyep={},jobDate={},",jobClass.getName(),jobName,jobType,date); try { Scheduler sched = factory.getScheduler(); JobDetail job = JobBuilder.newJob(jobClass).withIdentity(JOB_NAME_PREFIX + jobName, jobType.getType()) .setJobData(new JobDataMap(jp)).build(); SimpleTrigger trigger = (SimpleTrigger) TriggerBuilder.newTrigger() .withIdentity(TRIGGER_NAME_PREFIX + jobName, jobType.getType()).startAt(date).build(); removeJob(jobName, jobType); sched.scheduleJob(job, trigger); if (!sched.isShutdown()) { sched.start(); } } catch (Exception e) { //logger.error("ADD JOB exception {},jobName={},jobTyep={},jobDate={},",jobClass.getName(),jobName,jobType,date); } } /** * 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名) * @param jobName * @param time */ public synchronized static void modifyJobTime(String jobName,TimeJobType jobType, Date time) { //logger.error("Update JOB exception,jobName={},jobTyep={},jobDate={}," ,jobName,jobType,time); try { JobKey jobKey = new JobKey(JOB_NAME_PREFIX + jobName, jobType.getType()); TriggerKey key = new TriggerKey(TRIGGER_NAME_PREFIX + jobName, jobType.getType()); Scheduler sched = factory.getScheduler(); SimpleTrigger trigger = (SimpleTrigger) sched.getTrigger(key); if(trigger == null) { return; } Date oldTime = trigger.getStartTime(); if (oldTime.getTime() != time.getTime()) { JobDetail jobDetail = sched.getJobDetail(jobKey); Class<? extends Job> objJobClass = jobDetail.getJobClass(); removeJob(jobName,jobType); Map<String, Object> jp = jobDetail.getJobDataMap(); addJob(objJobClass, jobName, jobType, time, jp); } } catch (Exception e) { // logger.error("Update JOB exception,jobName={},jobTyep={},jobDate={}," ,jobName,jobType,time); } } /** * 移除一个任务 * * @param jobName */ public synchronized static void removeJob(String jobName, TimeJobType jobType) { try { JobKey jobKey = new JobKey(JOB_NAME_PREFIX + jobName, jobType.getType()); TriggerKey key = new TriggerKey(TRIGGER_NAME_PREFIX + jobName, jobType.getType()); Scheduler sched = factory.getScheduler(); JobDetail detail = sched.getJobDetail(jobKey); if (detail != null) { sched.pauseJob(jobKey); sched.pauseTrigger(key);// 停止触发器 sched.unscheduleJob(key);// 移除触发器 sched.deleteJob(jobKey);// 删除任务 } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 启动所有定时任务 */ public synchronized static void startJobs() { try { Scheduler sched = factory.getScheduler(); sched.start(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } /** * 关闭所有定时任务 */ public synchronized static void shutdownJobs() { try { Scheduler sched = factory.getScheduler(); if (!sched.isShutdown()) { sched.shutdown(); } } catch (Exception e) { e.printStackTrace(); throw new RuntimeException(e); } } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/TimeJobType.java
New file @@ -0,0 +1,30 @@ package com.xiaopeng.automaticPilot.job.base; /** * @Description 按时间点发布的任务类型 * @date 2025年2月17日 下午7:22:28 */ public enum TimeJobType { ORDER_CANCEL("order_cancel","订单取消"), ADD_CRUISE_MISSION("add_cruise_mission","添加巡游任务"), END_TRIP("end_trip","自动结束行程"); private String type; private String desc; private TimeJobType(String type, String desc) { this.type = type; this.desc = desc; } public String getType() { return type; } public void setType(String type) { this.type = type; } public String getDesc() { return desc; } public void setDesc(String desc) { this.desc = desc; } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/exceptions/TimeException.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.automaticPilot.job.exceptions; /** * @文件说明:定时器任务执行异常 * @版权所有:成都喜来达 * @项目名称: fengsheng * @创建者: Leeyns * @创建日期: 2016年5月18日 * @最近修改者:Leeyns * @最近修改日期:2016年5月18日 */ public class TimeException extends Exception { /** * TODO */ private static final long serialVersionUID = 5703430073981692250L; private String message; public TimeException() { super(); } public TimeException(String message) { super(message); this.message = message; } public String getMessage() { return message; } public void setMessage(String message) { this.message = message; } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/jobs/AddCruiseMissionJob.java
New file @@ -0,0 +1,40 @@ package com.xiaopeng.automaticPilot.job.jobs; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.order.job.base.AbstractJob; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * 推送定时任务 * @author Administrator * */ @Slf4j public class AddCruiseMissionJob extends AbstractJob { public static final String name = "addCruiseMission_"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); Long orderId = maps.getLong("id"); try { log.info("开始执行添加任务"); XpCruiseOrder xpCruiseOrder = xpCruiseOrderService.getById(orderId); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpCruiseOrder.getVehicleId()); if(xpVehicleR.getData().getState()==0){ orderMissionClient.pushOrder(new PushOrderDto(xpCruiseOrder.getVehicleVin(),xpCruiseOrder.getId(),null)); } }catch(Exception e){ e.printStackTrace(); } } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/jobs/EndTripJob.java
New file @@ -0,0 +1,41 @@ package com.xiaopeng.automaticPilot.job.jobs; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.order.XpOrderTimeoutLog; import com.xiaopeng.order.job.base.AbstractJob; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; /** * 推送定时任务 * @author Administrator * */ @Slf4j public class EndTripJob extends AbstractJob { public static final String name = "endTrip_"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); Long orderId = maps.getLong("id"); try { log.info("开始执行自动结束行程任务"); XpOrder xpOrder = xpOrderService.getById(orderId); xpOrderService.endTrip(xpOrder.getId(), String.valueOf(xpOrder.getAppUserId())); log.info("结束执行自动结束行程任务"); // 添加超时记录 XpOrderTimeoutLog xpOrderTimeoutLog = new XpOrderTimeoutLog(); xpOrderTimeoutLog.setOrderId(xpOrder.getId()); xpOrderTimeoutLog.setUserId(xpOrder.getAppUserId()); xpOrderTimeoutLogService.save(xpOrderTimeoutLog); }catch(Exception e){ e.printStackTrace(); } } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/jobs/OrderCancelJob.java
New file @@ -0,0 +1,40 @@ package com.xiaopeng.automaticPilot.job.jobs; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.order.job.base.AbstractJob; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.util.Objects; /** * 直播推送定时任务 * @author Administrator * */ @Slf4j public class OrderCancelJob extends AbstractJob { public static final String name = "orderCancel_"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); Long orderId = maps.getLong("id"); try { log.info("开始执行订单取消任务"); XpOrder xpOrder = xpOrderService.getById(orderId); if(Objects.nonNull(xpOrder)){ log.info("订单取消开始"); xpOrderService.cancelOrder(String.valueOf(xpOrder.getId())); log.info("订单取消状态修改完成"); } }catch(Exception e){ e.printStackTrace(); } } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/utils/SpringContextsUtil.java
New file @@ -0,0 +1,37 @@ package com.xiaopeng.automaticPilot.job.utils; import org.springframework.beans.BeansException; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.stereotype.Component; @Component public class SpringContextsUtil implements ApplicationContextAware{ private static ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { if (SpringContextsUtil.applicationContext == null) { SpringContextsUtil.applicationContext = applicationContext; } } // 获取applicationContext public static ApplicationContext getApplicationContext() { return applicationContext; } // 通过name获取 Bean. public static Object getBean(String name) { return getApplicationContext().getBean(name); } // 通过class获取Bean. public static <T> T getBean(Class<T> clazz) { return getApplicationContext().getBean(clazz); } // 通过name,以及Clazz返回指定的Bean public static <T> T getBean(String name, Class<T> clazz) { System.out.println(getApplicationContext().getBean(name, clazz)); return getApplicationContext().getBean(name, clazz); } } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -27,6 +27,14 @@ import com.xiaopeng.api.vo.OrderType; import com.xiaopeng.api.vo.SystemEventType; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.ActionType; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.PointType; import com.xiaopeng.api.vo.automaticPilot.proto.up.navigationDeviationEvent.NavigationDeviationEvent; import com.xiaopeng.api.vo.automaticPilot.proto.up.navigationDeviationEvent.NavigationDeviationMessage; import com.xiaopeng.api.vo.automaticPilot.proto.up.orderStateUpdateEvent.OrderStatusInfoEvent; import com.xiaopeng.api.vo.automaticPilot.proto.up.systemStatusXpu.*; import com.xiaopeng.api.vo.automaticPilot.proto.up.xpuNavigationRequest.NavigationRequest; import com.xiaopeng.api.vo.automaticPilot.protobuf.*; import com.xiaopeng.api.vo.operation.RouteVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; @@ -846,6 +854,15 @@ lastXpCruiseOrder.setStatus(1); xpCruiseOrderClient.addCruiseOrder(lastXpCruiseOrder); // 获取点位id Long endPointId = xpCruiseOrder.getEndPointId(); // 获取点位信息 获取点位是否需要停车 // xpCruisePlanClient.getPlanPointInfo(endPointId); com.xiaopeng.api.vo.automaticPilot.protobuf.RtTask.Builder taskBuilder = com.xiaopeng.api.vo.automaticPilot.protobuf.RtTask.newBuilder(); taskBuilder.setOrderId(lastXpCruiseOrder.getId()); taskBuilder.setTaskId("MISSION_"+ IdUtil.fastUUID()); xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -287,7 +287,13 @@ } UserCouponVo userCouponVo = couponResult.getData(); if (userCouponVo != null) { Double money = userCouponVo.getMoney(); xpPricingCardVo.setCoupon(String.valueOf(userCouponVo.getMoney())); if(xpPricingCardVo.getTotalPrice()> money){ xpPricingCardVo.setSystemDiscount(xpPricingCardVo.getTotalPrice() - money); } } // 8. 构建响应对象 xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpTaskManagementController.java
@@ -156,7 +156,7 @@ return xpTaskService.taskDetail(id); } @ApiOperation(value = "查询车辆不分页列表") @PostMapping(" /listVehicle") @PostMapping("/listVehicle") public R<List<XpVehicle>> listVehicle() { List<XpVehicle> vehicles = xpVehicleClient.listVehicle().getData(); if (vehicles == null){ @@ -177,7 +177,7 @@ @ApiOperation(value = "事故类型列表", response = XpErrorType.class, tags = "管理后台-车辆管理-运营车辆管理") @GetMapping(" /errorTypeTreeList") @GetMapping("/errorTypeTreeList") public R<List<XpErrorType>> errorTypeTreeList() { return xpErrorTypeService.errorTypeList(); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpWorkOrderController.java
@@ -55,6 +55,7 @@ @ApiOperation(value = "创建工单") @PostMapping("/saveWorkOrder") public R saveWordOrder(@RequestBody XpWorkOrder workOrder) { workOrder.setCreateById(tokenService.getLoginUser().getSysUser().getId()); workOrderService.save(workOrder); return R.ok(); } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/InsuranceInspectionScheduleTask.java
@@ -353,7 +353,7 @@ task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE); // 设置任务接收人(配置角色下的所有运维人员都可以看到) task.setBelongUserIds(belongUserIds); task.setHandleUserId(belongUserIds); // 设置创建信息 task.setReportTime(LocalDateTime.now()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/RoutinePreparationScheduleTask.java
@@ -373,7 +373,7 @@ task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE); // 设置任务接收人(配置角色下的所有运维人员都可以看到) task.setBelongUserIds(belongUserIds); task.setHandleUserId(belongUserIds); // 设置创建信息 task.setReportTime(LocalDateTime.now()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCleanScheduleTask.java
@@ -373,7 +373,7 @@ task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE); // 设置任务接收人(配置角色下的所有运维人员都可以看到) task.setBelongUserIds(belongUserIds); task.setHandleUserId(belongUserIds); // 设置创建信息 task.setReportTime(LocalDateTime.now()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleCollectionScheduleTask.java
@@ -1,14 +1,24 @@ package com.xiaopeng.maintenance.schedule; import cn.hutool.core.util.IdUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.maintenance.XpTaskRule; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; 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.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import org.springframework.util.CollectionUtils; @@ -42,6 +52,18 @@ @Autowired private XpVehicleClient xpVehicleClient; @Autowired private XpCruiseOrderClient xpCruiseOrderClient; @Autowired private MongoTemplate mongoTemplate; @Autowired private OrderMissionClient orderMissionClient; @Autowired private XpCruisePlanClient xpCruisePlanClient; /** * 每分钟检查一次是否需要执行收车任务 @@ -162,6 +184,7 @@ return result.getData().stream() .filter(v -> v.getVehicleType() != null && v.getVehicleType() == 2) .filter(v -> v.getOperatingStatus() != null && v.getOperatingStatus() == 1) .filter(v -> v.getState() != null && v.getState() == 0) .collect(Collectors.toList()); } } catch (Exception e) { @@ -179,10 +202,37 @@ * 2. 更新车辆状态为"已收车" * </p> * * @param vehicle 车辆信息 * @param xpVehicle 车辆信息 */ private void sendCollectionCommand(XpVehicle vehicle) { // TODO: 具体发送收车指令的实现 log.info("向车辆[{}]发送收车指令", vehicle.getPlateNumber()); private void sendCollectionCommand(XpVehicle xpVehicle) { // 收车 关闭当前巡游单子 生成新的返程单子 找到收车站点 R<String> r = xpCruiseOrderClient.updateCruiseOrder(xpVehicle.getVehicleVin()); // mongodb 获取当前最新经纬度位置 VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class); XpCruiseOrder xpCruiseOrder = new XpCruiseOrder(); if(vehiclePosition!=null){ double x = vehiclePosition.getPoint().getX(); double y = vehiclePosition.getPoint().getY(); xpCruiseOrder.setStartLon(x); xpCruiseOrder.setStartLat(y); } xpCruiseOrder.setId("XU"+ IdUtil.fastUUID()); xpCruiseOrder.setVehicleId(xpVehicle.getId()); xpCruiseOrder.setFleetId(xpVehicle.getFleetId()); xpCruiseOrder.setOrderType(2); xpCruiseOrder.setStatus(1); xpCruiseOrder.setOrderReverse(1); xpCruiseOrder.setLastOrderId(r.getData()); // 找到收车站点 R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder); if(returnCruisePoint!=null){ xpCruiseOrderClient.addCruiseOrder(returnCruisePoint.getData()); // 下发命令 orderMissionClient.pushOrder(new PushOrderDto( xpCruiseOrder.getVehicleVin(),xpCruiseOrder.getId(),null)); } log.info("向车辆[{}]发送收车指令", xpVehicle.getPlateNumber()); } } xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleInspectionScheduleTask.java
@@ -333,7 +333,7 @@ task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE); // 设置任务接收人(配置角色下的所有运维人员都可以看到) task.setBelongUserIds(belongUserIds); task.setHandleUserId(belongUserIds); // 设置创建信息 task.setReportTime(LocalDateTime.now()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/VehicleMaintenanceScheduleTask.java
@@ -359,7 +359,7 @@ task.setStatus(TaskScheduleConstants.TASK_STATUS_PENDING_ARRIVE); // 设置任务接收人(配置角色下的所有运维人员都可以看到) task.setBelongUserIds(belongUserIds); task.setHandleUserId(belongUserIds); // 设置创建信息 task.setReportTime(LocalDateTime.now()); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpSchedulingDetailServiceImpl.java
@@ -1,16 +1,24 @@ package com.xiaopeng.maintenance.service.impl; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.xiaopeng.api.dto.pushMessage.AliPushMessageDTO; import com.xiaopeng.api.feignClient.account.XpOperationUserClient; import com.xiaopeng.api.feignClient.account.XpOperationUserNotificationClient; import com.xiaopeng.api.feignClient.maintenance.XpCheckLocationClient; import com.xiaopeng.api.feignClient.pushMessage.XpAliPushMessageClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient; import com.xiaopeng.api.model.account.XpOperationsUser;import com.xiaopeng.api.model.maintenance.*; import com.xiaopeng.api.model.account.XpOperationsUser; import com.xiaopeng.api.model.account.XpOperationsUserNotification; import com.xiaopeng.api.model.maintenance.*; import com.xiaopeng.api.model.vehicleConvoy.XpFleet; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.NotificationTypeEnum; import com.xiaopeng.common.core.utils.poi.ExcelUtil; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.maintenance.dto.ExportSchedulingDetailDto; @@ -36,6 +44,9 @@ import java.time.format.TextStyle; import java.time.temporal.TemporalAdjusters; import java.util.*; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * <p> @@ -64,6 +75,10 @@ private XpFleetOperationsClient xpFleetOperationsClient; @Resource private XpOperationUserClient xpOperationUserClient; @Resource private XpAliPushMessageClient xpAliPushMessageClient; @Resource private XpOperationUserNotificationClient xpOperationUserNotificationClient; @Override public ShiftAttendanceVO shiftAttendance(ShiftAttendanceDTO dto) { @@ -395,6 +410,10 @@ //构建排班明细数据 List<SaveSchedulingDetailVo> datas = vo.getDatas(); List<XpSchedulingDetail> schedulingDetails = new ArrayList<>(); //存放推送消息 List<AliPushMessageDTO> pushMessage = new ArrayList<>(); //存放通知数据 List<XpOperationsUserNotification> notifications = new ArrayList<>(); for (SaveSchedulingDetailVo data : datas) { Long fleetId = data.getFleetId(); List<SaveSchedulingDetailDay> days = data.getDays(); @@ -428,7 +447,12 @@ for (XpOperationsUser xpOperationsUser : data1) { String nickName = xpOperationsUser.getNickName(); String message = nickName + "请注意," + month + "你的排班由" + xpShift1.getShiftName() + "变更为了" + xpShift2.getShiftName() + "。详情请联系平台管理员。"; //构建消息推送对象 AliPushMessageDTO aliPushMessageDTO = buildPushMessage(message, xpOperationsUser); pushMessage.add(aliPushMessageDTO); //构建消息存储 XpOperationsUserNotification operationsUserNotification = buildXpOperationsUserNotification(message, aliPushMessageDTO.getBody(), xpOperationsUser); notifications.add(operationsUserNotification); } } } @@ -448,11 +472,74 @@ if(schedulingDetails.isEmpty()){ this.saveOrUpdateBatch(schedulingDetails); } //异步处理消息通知数据 pushMessage(pushMessage, notifications); return R.ok(); } /** * 构建推送消息对象 * @param message * @param xpOperationsUser * @return */ private AliPushMessageDTO buildPushMessage(String message, XpOperationsUser xpOperationsUser){ JSONObject body = new JSONObject(); body.put("content", message); body.put("strategy", 4); body.put("type", 0); body.put("id", 0); AliPushMessageDTO aliPushMessageDTO = new AliPushMessageDTO(); aliPushMessageDTO.setDeviceType(xpOperationsUser.getDeviceType()); aliPushMessageDTO.setAccount(xpOperationsUser.getPhoneNumber()); aliPushMessageDTO.setTitle("排班变更提示"); aliPushMessageDTO.setBody(body.toJSONString()); aliPushMessageDTO.setPushType("NOTICE"); return aliPushMessageDTO; } /** * 构建消息存储 * @param body * @param xpOperationsUser * @return */ private XpOperationsUserNotification buildXpOperationsUserNotification(String message, String body, XpOperationsUser xpOperationsUser){ XpOperationsUserNotification operationsUserNotification = new XpOperationsUserNotification(); operationsUserNotification.setNotificationType(NotificationTypeEnum.SCHEDULE_CHANGED.getCode()); operationsUserNotification.setNotificationContent(message); operationsUserNotification.setOperationsUserId(xpOperationsUser.getId()); operationsUserNotification.setReadStatus(0); operationsUserNotification.setNotificationExt(body); return operationsUserNotification; } /** * 异步处理消息推送 * @param pushMessage * @param notifications */ private void pushMessage(List<AliPushMessageDTO> pushMessage, List<XpOperationsUserNotification> notifications) { if(pushMessage.isEmpty()){ return; } ThreadPoolExecutor executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); executor.execute(() -> { xpOperationUserNotificationClient.addNotificationBatch(notifications); for (AliPushMessageDTO aliPushMessageDTO : pushMessage) { xpAliPushMessageClient.pushMessage(aliPushMessageDTO); } }); } /** * 导出排班数据 * @param month * @param response xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -949,6 +949,7 @@ task.setVehicleLat(dto.getVehicleLat()); task.setReportUserId(reportUserId); task.setReportTime(LocalDateTime.now()); saveTask.add( task); } this.saveBatch(saveTask); @@ -1246,16 +1247,19 @@ } XpTaskHandleDetail xpTaskHandleDetail = xpTaskHandleDetailMapper.selectOne(new LambdaQueryWrapper<XpTaskHandleDetail>() .eq(XpTaskHandleDetail::getTaskId, id)); res.setDeathCount(xpTaskHandleDetail.getDeathCount()); res.setSevereCount(xpTaskHandleDetail.getSevereCount()); res.setMinorCount(xpTaskHandleDetail.getMinorCount()); res.setResponsibilityJudgment(xpTaskHandleDetail.getResponsibilityJudgment()); res.setResponsibleDescription(xpTaskHandleDetail.getResponsibleDescription()); res.setResponsibleImage(xpTaskHandleDetail.getResponsibleImage()); res.setDisposalDescription(xpTaskHandleDetail.getDisposalDescription()); res.setDisposalImage(xpTaskHandleDetail.getDisposalImage()); res.setSituationDescription(xpTaskHandleDetail.getSituationDescription()); res.setSituationImage(xpTaskHandleDetail.getSituationImage()); if (xpTaskHandleDetail != null){ res.setDeathCount(xpTaskHandleDetail.getDeathCount()); res.setSevereCount(xpTaskHandleDetail.getSevereCount()); res.setMinorCount(xpTaskHandleDetail.getMinorCount()); res.setResponsibilityJudgment(xpTaskHandleDetail.getResponsibilityJudgment()); res.setResponsibleDescription(xpTaskHandleDetail.getResponsibleDescription()); res.setResponsibleImage(xpTaskHandleDetail.getResponsibleImage()); res.setDisposalDescription(xpTaskHandleDetail.getDisposalDescription()); res.setDisposalImage(xpTaskHandleDetail.getDisposalImage()); res.setSituationDescription(xpTaskHandleDetail.getSituationDescription()); res.setSituationImage(xpTaskHandleDetail.getSituationImage()); } managementDetailVO.setAccidentDetailVO(res); } return R.ok(managementDetailVO); xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpWorkOrderServiceImpl.java
@@ -17,6 +17,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -88,14 +89,25 @@ } List<Long> handleUserIds = workOrderLogs.stream().map(XpWorkOrderLog::getHandleUserId).collect(Collectors.toList()); List<SysUser> sysUsers = sysUserClient.listByIds(handleUserIds).getData(); Map<Long, String> userMap = new HashMap<>(); if (workOrder.getCreateById()!=null){ List<Long> createUserId = new ArrayList<>(); createUserId.add(workOrder.getCreateById()); List<SysUser> sysUser = sysUserClient.listByIds(createUserId).getData(); if (sysUser != null && !sysUser.isEmpty()){ workOrder.setCreateByAvatar(sysUser.get(0).getAvatar()); } } Map<Long, SysUser> userMap = new HashMap<>(); if (sysUsers != null) { userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getId, SysUser::getNickName)); userMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getId, e->e)); } for (XpWorkOrderLog workOrderLog : workOrderLogs) { if (workOrderLog.getHandleUserId() != null) { String handleUserName = userMap.get(workOrderLog.getHandleUserId()); String handleUserName = userMap.get(workOrderLog.getHandleUserId()).getNickName(); workOrderLog.setHandleUserName(handleUserName); String avatar = userMap.get(workOrderLog.getHandleUserId()).getAvatar(); workOrderLog.setHandleUserAvatar(avatar); } } workOrder.setWorkOrderLogs(workOrderLogs); @@ -108,11 +120,13 @@ if (workOrderLog.getHandleType() == 2) { // 办结 工单状态流转为已完成 workOrder.setHandleStatus(3); workOrder.setFeedbackUserPhone(null); workOrder.setHandleUserId(workOrderLog.getHandleUserId()); this.updateById(workOrder); }else{ // 移交 workOrder.setHandleStatus(2); workOrder.setFeedbackUserPhone(null); workOrder.setHandleUserId(workOrderLog.getHandleUserId()); this.updateById(workOrder); } xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -59,8 +59,8 @@ */ @PostMapping("/add") @ApiOperation(value = "新增电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R add(@Validated @RequestBody ElectronicFenceAddDto dto) { return xpElectronicClient.add(dto); @@ -74,8 +74,8 @@ @PostMapping("/updateStatus") @ResponseBody @ApiOperation(value = "修改状态") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R updateStatus(@RequestBody ElectronicFenceAreaUpdateStatusDto dto) { return xpElectronicClient.updateStatus(dto); @@ -97,8 +97,9 @@ @PostMapping("/edit") @ResponseBody @ApiOperation(value = "编辑电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated @RequestBody ElectronicFenceUpdateDto dto) { // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated @RequestBody ElectronicFenceUpdateDto dto) { return xpElectronicClient.edit(dto); } @@ -107,8 +108,8 @@ */ @PostMapping("/copy") @ApiOperation(value = "复制电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R<Long> copy(@RequestParam("id") Integer id) { return xpElectronicClient.copy(id); } xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java
@@ -121,8 +121,8 @@ @PostMapping("/add") @ApiOperation(value = "新增点位") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R add(@Validated @RequestBody PointAddDto pointAddDto) { xpPointClient.add(pointAddDto); return R.ok(); @@ -131,9 +131,9 @@ * 编辑点位 */ @PostMapping("/edit") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) @ApiOperation(value = "编辑点位") // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated@RequestBody PointUpdateDto pointAddDto) { xpPointClient.edit(pointAddDto); return R.ok(); @@ -142,10 +142,9 @@ * 批量删除点位 */ @GetMapping("/deletePoint") @ResponseBody @ApiOperation(value = "删除点位") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R deletePoint(@RequestParam("ids") String ids) { xpPointClient.deletePoint(ids); return R.ok(); @@ -165,8 +164,8 @@ @PostMapping("/enableDisable") @ResponseBody @ApiOperation(value = "启用/禁用") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R enableDisable(@RequestBody XpPointEnableDisableDto dto) { return xpPointClient.enableDisable(dto); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpElectronicFenceAreaController.java
@@ -4,11 +4,12 @@ import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import io.swagger.annotations.ApiOperation; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import javax.annotation.Resource; @@ -20,8 +21,21 @@ * @author mitao * @since 2026-02-03 */ @Controller @RequestMapping("/xp-electronic-fence-area") @RestController public class XpElectronicFenceAreaController { @Resource private IXpElectronicFenceAreaService xpElectronicFenceAreaService; /** * 根据区域ID查询区域信息 * * @param id 区域ID * @return 区域信息 */ @ApiOperation(value = "根据区域ID查询区域信息", notes = "根据区域ID查询区域信息", tags = {"内部接口"}) @PostMapping("/inner/v1/xp-electronic-fence-area/queryById/queryById") public R<XpElectronicFenceArea> queryById(@RequestParam("id") Long id) { return R.ok(xpElectronicFenceAreaService.getById(id)); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpElectronicFenceController.java
@@ -84,8 +84,8 @@ */ @PostMapping("/add") @ApiOperation(value = "新增电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R add(@Validated @RequestBody ElectronicFenceAddDto dto) { return xpElectronicFenceService.addElectronic(dto); } @@ -98,8 +98,8 @@ @PostMapping("/updateStatus") @ResponseBody @ApiOperation(value = "修改状态") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R updateStatus(@RequestBody ElectronicFenceAreaUpdateStatusDto dto) { XpElectronicFenceArea electronicFenceArea = xpElectronicFenceAreaService.getById(dto.getId()); if (electronicFenceArea == null) { @@ -138,8 +138,8 @@ */ @PostMapping("/edit") @ApiOperation(value = "编辑电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated @RequestBody ElectronicFenceUpdateDto dto) { return xpElectronicFenceService.editElectronic(dto); } @@ -149,8 +149,8 @@ */ @PostMapping("/copy") @ApiOperation(value = "复制电子围栏") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R<Long> copy(@RequestParam("id") Integer id) { XpElectronicFence electronicFence = xpElectronicFenceService.getById(id); if (electronicFence.getStatus()==2){ xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointManagementController.java
@@ -85,9 +85,9 @@ */ @PostMapping("/addPoint") @ResponseBody @Transactional @ShardingSphereTransactionType(TransactionType.BASE) @ApiOperation(value = "新增点位") // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R add(@Validated @RequestBody PointAddDto pointAddDto) { XpPoint xpPoint = new XpPoint(); BeanUtils.copyProperties(pointAddDto, xpPoint); @@ -100,8 +100,8 @@ @GetMapping("/deletePoint") @ResponseBody @ApiOperation(value = "删除点位") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R deletePoint(@RequestParam("ids") String ids) { xpPointService.removeBatchByIds(Arrays.stream(ids.split(",")).map(Long::parseLong).collect(Collectors.toList())); return R.ok(); @@ -111,8 +111,8 @@ */ @PostMapping("/editPoint") @ApiOperation(value = "编辑点位") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R edit(@Validated@RequestBody PointUpdateDto pointAddDto) { XpPoint xpPoint = new XpPoint(); BeanUtils.copyProperties(pointAddDto, xpPoint); @@ -132,8 +132,8 @@ */ @PostMapping("/enableDisablePoint") @ApiOperation(value = "启用/禁用") @Transactional @ShardingSphereTransactionType(TransactionType.BASE) // @Transactional // @ShardingSphereTransactionType(TransactionType.BASE) public R enableDisable(@RequestBody XpPointEnableDisableDto dto) { XpPoint xpPoint = xpPointService.getById(dto.getId()); xpPoint.setOperationStatus(dto.getOperationStatus()); xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpWhitelistController.java
@@ -117,6 +117,8 @@ SysUser sysUser = tokenService.getLoginUser().getSysUser(); XpWhitelist xpWhitelist = new XpWhitelist(); BeanUtils.copyProperties(dto, xpWhitelist); xpWhitelist.setUpdateBy(tokenService.getLoginUser().getSysUser().getNickName()); return xpWhitelistService.editWhitelist(xpWhitelist, sysUser); } @@ -190,6 +192,7 @@ @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW) @PostMapping("/importExcel") public AjaxResult<String> importExcel(@RequestPart("file") MultipartFile file) { ImportParams params = new ImportParams(); // params.setTitleRows(1); // 标题行数 params.setHeadRows(1); //表头行数 @@ -235,6 +238,7 @@ xpWhitelist.setStatus(true); xpWhitelist.setIsPriorityDispatch(true); xpWhitelist.setWhitelistSource(1); xpWhitelist.setCreateBy(tokenService.getLoginUser().getSysUser().getNickName()); addList.add(xpWhitelist); } if (!result.isEmpty()) { @@ -250,6 +254,7 @@ xpWhitelistOperlog.setOperationIp(IpUtils.getIpAddr()); xpWhitelistOperlog.setOperationAccountId(sysUser.getId()); xpWhitelistOperlog.setOperationContent(operationContent.toString()); xpWhitelistOperlog.setCreateBy(tokenService.getLoginUser().getSysUser().getNickName()); xpWhitelistOperlogService.save(xpWhitelistOperlog); return AjaxResult.success(); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/exportExcle/XpWhitelistExportExcel.java
@@ -33,12 +33,12 @@ private String account; @ApiModelProperty(value = "状态 0=冻结 1=正常") @cn.afterturn.easypoi.excel.annotation.Excel(name = "状态",width = 20,replace = {"true_正常","false_冻结"}) @cn.afterturn.easypoi.excel.annotation.Excel(name = "状态",width = 20,replace = {"正常_true","冻结_false"}) private Boolean status; @ApiModelProperty(value = "优先派单 1=是 0=否") @cn.afterturn.easypoi.excel.annotation.Excel(name = "优先派单",width = 20,replace = {"true_是","false_否"}) @cn.afterturn.easypoi.excel.annotation.Excel(name = "优先派单",width = 20,replace = {"是_true","否_false"}) private Boolean isPriorityDispatch; xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpWhitelistServiceImpl.java
@@ -53,6 +53,10 @@ @Override public R addWhitelist(WhitelistAddDto dto, SysUser sysUser) { XpWhitelist old = this.lambdaQuery().eq(XpWhitelist::getAccount, dto.getAccount()).last("limit 1").one(); if (old != null) { return R.fail("该账号已存在"); } List<XpWhitelist> addList = new ArrayList<>(); List<String> accounts = Arrays.asList(dto.getAccount().split(",")); StringBuilder operationContent = new StringBuilder("新增账号:"); @@ -63,6 +67,7 @@ xpWhitelist.setStatus(true); xpWhitelist.setIsPriorityDispatch(dto.getIsPriorityDispatch()); xpWhitelist.setWhitelistSource(1); xpWhitelist.setCreateBy(sysUser.getCreateBy()); addList.add(xpWhitelist); accountBuilder.append("\"").append(account).append("\"").append(","); } xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpWhitelistMapper.xml
@@ -18,7 +18,7 @@ and status = #{query.status} </if> <if test="query.whitelistSource != null"> and whitelist_source = #{query.source} and whitelist_source = #{query.whitelistSource} </if> order by create_time desc </select> xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -270,7 +270,7 @@ * @param dto 改派请求参数 * @return 操作结果 */ @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"},notes = "车辆列表在maintenance服务") @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"},notes = "车辆列表在vehicleConvoy服务") @PostMapping("/api/v1/order/reassignById") public R<?> reassignById(@Validated @RequestBody XpOrderReassignDTO dto) { xpOrderService.reassignOrder( xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/base/AbstractJob.java
@@ -1,6 +1,10 @@ package com.xiaopeng.order.job.base; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.order.service.IXpCruiseOrderService; import com.xiaopeng.order.service.IXpOrderService; import com.xiaopeng.order.job.utils.SpringContextsUtil; import com.xiaopeng.order.service.XpOrderTimeoutLogService; @@ -19,7 +23,9 @@ protected IXpOrderService xpOrderService; protected XpPushMessageClient xpPushMessageClient; protected XpOrderTimeoutLogService xpOrderTimeoutLogService; protected IXpCruiseOrderService xpCruiseOrderService; protected OrderMissionClient orderMissionClient; protected XpVehicleClient xpVehicleClient; public AbstractJob(){ this.xpOrderService = SpringContextsUtil.getBean(IXpOrderService.class); this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/base/TimeJobType.java
@@ -6,6 +6,7 @@ */ public enum TimeJobType { ORDER_CANCEL("order_cancel","订单取消"), ADD_CRUISE_MISSION("add_cruise_mission","添加巡游任务"), END_TRIP("end_trip","自动结束行程"); private String type; private String desc; xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/AddCruiseMissionJob.java
New file @@ -0,0 +1,43 @@ package com.xiaopeng.order.job.jobs; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.order.job.base.AbstractJob; import lombok.extern.slf4j.Slf4j; import org.quartz.JobDataMap; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import java.util.Objects; /** * 推送定时任务 * @author Administrator * */ @Slf4j public class AddCruiseMissionJob extends AbstractJob { public static final String name = "addCruiseMission_"; @Override public void execute(JobExecutionContext context) throws JobExecutionException { JobDataMap maps = context.getMergedJobDataMap(); Long orderId = maps.getLong("id"); try { log.info("开始执行添加任务"); XpCruiseOrder xpCruiseOrder = xpCruiseOrderService.getById(orderId); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(xpCruiseOrder.getVehicleId()); if(xpVehicleR.getData().getState()==0){ orderMissionClient.pushOrder(new PushOrderDto(xpCruiseOrder.getVehicleVin(),xpCruiseOrder.getId(),null)); } }catch(Exception e){ e.printStackTrace(); } } } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -28,15 +28,19 @@ import com.xiaopeng.api.feignClient.account.XpAppUserClient; import com.xiaopeng.api.feignClient.account.XpAppUserCouponClient; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.maintenance.XpTaskRuleClient; import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient; import com.xiaopeng.api.feignClient.operation.XpPointClient; import com.xiaopeng.api.feignClient.operation.XpPricingClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.account.XpAppUser; import com.xiaopeng.api.model.maintenance.XpTaskRule; import com.xiaopeng.api.model.operation.XpFeedbackType; import com.xiaopeng.api.model.operation.XpGeoQueryEntity; import com.xiaopeng.api.model.operation.XpPoint; @@ -69,6 +73,7 @@ import com.xiaopeng.order.dto.MileageDto; import com.xiaopeng.order.job.base.QuartzManager; import com.xiaopeng.order.job.base.TimeJobType; import com.xiaopeng.order.job.jobs.AddCruiseMissionJob; import com.xiaopeng.order.job.jobs.EndTripJob; import com.xiaopeng.order.job.jobs.OrderCancelJob; import com.xiaopeng.order.mangodb.model.OrderTrajectory; @@ -100,6 +105,7 @@ 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.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; @@ -144,6 +150,8 @@ private final OrderMissionClient orderMissionClient; private final XpOrderDetailMapper xpOrderDetailMapper; private final XpCruiseOrderMapper xpCruiseOrderMapper; private final XpTaskRuleClient xpTaskRuleClient; private final XpCruisePlanClient xpCruisePlanClient; @Autowired @@ -511,7 +519,20 @@ orderCancel.setCancelReason("运营人员取消订单"); orderCancel.setCreateBy(SecurityUtils.getLoginUser().getSysUser().getNickName()); xpOrderCancelService.save(orderCancel); //查询车辆信息 R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getId()); if (xpVehicleR.getCode() == HttpStatus.SUCCESS && Objects.nonNull(xpVehicleR.getData())) { // 下发命令 if (order.getStatus() > 1) { PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicleR.getData().getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); } } else { log.info("查询车辆信息失败,订单ID: {}, 下发取消订单命令失败", order.getId()); } log.info("订单取消成功,订单ID: {}, 操作人: {}", order.getId(), SecurityUtils.getUsername()); } @@ -538,10 +559,10 @@ throw new ServiceException("订单不存在"); } // 2. 校验订单状态(只有待接单、待出发、接驾中状态可以改派) // 2. 校验订单状态(只有待出发、接驾中、待乘客上车状态可以改派) Integer currentStatus = order.getStatus(); if (currentStatus != 1 && currentStatus != 2 && currentStatus != 3) { throw new ServiceException("当前订单状态不允许改派,只有待接单、待出发、接驾中状态的订单可以改派", I18nKeyConstant.ORDER_REASSIGN_FAILED); if (currentStatus != 2 && currentStatus != 3 && currentStatus != 4) { throw new ServiceException("当前订单状态不允许改派,只有待出发、接驾中、待乘客上车状态的订单可以改派", I18nKeyConstant.ORDER_REASSIGN_FAILED); } // 3. 校验新旧车辆是否相同 @@ -580,6 +601,47 @@ // 6. 保存原车辆和车队信息 Long oldVehicleId = order.getVehicleId(); Long oldFleetId = order.getFleetId(); // 6.1 处理原车辆:取消订单指令、解绑乘客、更新状态、创建返程巡游订单 if (Objects.nonNull(oldVehicleId)) { try { R<XpVehicle> oldVehicleResult = xpVehicleClient.queryById(oldVehicleId); if (oldVehicleResult != null && oldVehicleResult.getCode() == HttpStatus.SUCCESS && oldVehicleResult.getData() != null) { XpVehicle oldVehicle = oldVehicleResult.getData(); // 6.1.1 取消原订单指令 PushOrderDto cancelDto = new PushOrderDto(); cancelDto.setOrderId(order.getId().toString()); cancelDto.setVin(oldVehicle.getVehicleVin()); cancelDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(cancelDto); log.info("已取消原车辆订单指令,订单ID: {}, VIN: {}", orderId, oldVehicle.getVehicleVin()); // 6.1.2 解绑乘客与原车辆关系 if (Objects.nonNull(order.getAppUserId())) { CancelTaxiPassengerVo cancelVo = new CancelTaxiPassengerVo(); cancelVo.setVin(oldVehicle.getVehicleVin()); cancelVo.setUid(order.getAppUserId().toString()); cancelVo.setOrderNo(order.getOrderNumber()); cancelVo.setAppId(""); userVehicleClient.cancelTaxiPassenger(cancelVo); log.info("已解绑乘客与原车辆关系,用户ID: {}, VIN: {}", order.getAppUserId(), oldVehicle.getVehicleVin()); } // 6.1.3 修改原车辆状态为空闲 oldVehicle.setState(0); xpVehicleClient.updateVehicleById(oldVehicle); log.info("已将原车辆状态设为空闲,车辆ID: {}", oldVehicleId); // 6.1.4 为原车辆创建返程巡游订单 createReturnCruiseOrder(oldVehicle, order); } else { log.warn("查询原车辆信息失败,车辆ID: {}", oldVehicleId); } } catch (Exception e) { log.error("处理原车辆失败,车辆ID: {},错误: {}", oldVehicleId, e.getMessage()); } } // 7. 查询新车辆关联的车队ID Long newFleetId = null; @@ -634,7 +696,118 @@ log.info("订单改派成功,订单ID: {}, 原车辆ID: {}, 新车辆ID: {}, 原车队ID: {}, 新车队ID: {}, 操作人: {}", orderId, oldVehicleId, newVehicleId, oldFleetId, newFleetId, SecurityUtils.getUsername()); //推送消息 // 11. 处理新车辆:绑定乘客、下发订单、更新状态 try { // 11.1 绑定乘客与新车辆关系 if (Objects.nonNull(order.getAppUserId())) { AddTaxiPassengerVo addVo = new AddTaxiPassengerVo(); addVo.setVin(newVehicle.getVehicleVin()); addVo.setUid(order.getAppUserId().toString()); addVo.setOrderNo(order.getOrderNumber()); addVo.setAppId(""); // TODO 获取appId userVehicleClient.addTaxiPassenger(addVo); log.info("已绑定乘客与新车辆关系,用户ID: {}, VIN: {}", order.getAppUserId(), newVehicle.getVehicleVin()); } // 11.2 下发订单到新车辆 PushOrderDto pushDto = new PushOrderDto(); pushDto.setOrderId(order.getId().toString()); pushDto.setVin(newVehicle.getVehicleVin()); orderMissionClient.pushOrder(pushDto); log.info("已下发订单到新车辆,订单ID: {}, VIN: {}", orderId, newVehicle.getVehicleVin()); // 11.3 更新新车辆状态为已接单 newVehicle.setState(1); xpVehicleClient.updateVehicleById(newVehicle); log.info("已将新车辆状态设为已接单,车辆ID: {}", newVehicleId); } catch (Exception e) { log.error("处理新车辆失败,车辆ID: {},错误: {}", newVehicleId, e.getMessage()); } } /** * 为原车辆创建返程巡游订单 * <p> * 改派时,原车辆需要返回巡游路线: * - 若最新巡游订单状态为已终止(status=2),返回原出发点 * - 若最新巡游订单状态为已完成(status=3),返回原终点 * - 其他状态,默认返回原出发点 * </p> * * @param oldVehicle 原车辆信息 * @param order 当前订单信息 */ private void createReturnCruiseOrder(XpVehicle oldVehicle, XpOrder order) { try { // 查询该车辆最新的一条巡游订单 XpCruiseOrder lastCruise = xpCruiseOrderMapper.selectOne( new LambdaQueryWrapper<XpCruiseOrder>() .eq(XpCruiseOrder::getVehicleId, oldVehicle.getId()) .orderByDesc(BaseModel::getCreateTime) .last("limit 1") ); if (lastCruise == null) { log.warn("原车辆没有巡游订单记录,跳过创建返程订单,车辆ID: {}", oldVehicle.getId()); return; } XpCruiseOrder returnOrder = new XpCruiseOrder(); returnOrder.setId("XU" + IdUtil.fastUUID()); returnOrder.setVehicleId(oldVehicle.getId()); returnOrder.setVehicleVin(oldVehicle.getVehicleVin()); returnOrder.setFleetId(oldVehicle.getFleetId()); returnOrder.setOrderType(2); // 返程单 returnOrder.setStatus(1); // 进行中 returnOrder.setLastOrderId(lastCruise.getId()); returnOrder.setCreateTime(LocalDateTime.now()); // 返程起点 = 当前订单的终点(车辆当前位置附近) returnOrder.setStartPointId(order.getEndPointId()); returnOrder.setStartPointName(order.getEndPointName()); returnOrder.setStartLon(order.getEndLon()); returnOrder.setStartLat(order.getEndLat()); // 根据最新巡游订单状态决定返程终点 if (lastCruise.getStatus() != null && lastCruise.getStatus() == 2) { // 已终止(status=2) -> 返回原出发点 returnOrder.setEndPointId(lastCruise.getStartPointId()); returnOrder.setEndPointName(lastCruise.getStartPointName()); returnOrder.setEndLon(lastCruise.getStartLon()); returnOrder.setEndLat(lastCruise.getStartLat()); log.info("巡游订单状态为已终止,返回原出发点"); } else if (lastCruise.getStatus() != null && lastCruise.getStatus() == 3) { // 已完成(status=3) -> 返回原终点 returnOrder.setEndPointId(lastCruise.getEndPointId()); returnOrder.setEndPointName(lastCruise.getEndPointName()); returnOrder.setEndLon(lastCruise.getEndLon()); returnOrder.setEndLat(lastCruise.getEndLat()); log.info("巡游订单状态为已完成,返回原终点"); } else { // 其他状态(进行中等),默认返回原出发点 returnOrder.setEndPointId(lastCruise.getStartPointId()); returnOrder.setEndPointName(lastCruise.getStartPointName()); returnOrder.setEndLon(lastCruise.getStartLon()); returnOrder.setEndLat(lastCruise.getStartLat()); log.info("巡游订单状态为{},默认返回原出发点", lastCruise.getStatus()); } xpCruiseOrderMapper.insert(returnOrder); // 下发巡游订单到原车辆 PushOrderDto pushDto = new PushOrderDto(); pushDto.setVin(oldVehicle.getVehicleVin()); pushDto.setOrderId(returnOrder.getId()); orderMissionClient.pushOrder(pushDto); log.info("为原车辆创建返程巡游订单成功,订单ID: {}, 车辆ID: {}", returnOrder.getId(), oldVehicle.getId()); } catch (Exception e) { log.error("创建返程巡游订单失败,车辆ID: {},错误: {}", oldVehicle.getId(), e.getMessage()); } } @Override @@ -1238,7 +1411,7 @@ useUserCouponDto.setUserCouponId(order.getCouponId()); xpAppUserCouponClient.useUserCoupon(useUserCouponDto); } // 计算完价格后 挑选优惠券 // 计算完价格后 挑选优惠券 GetUserCouponDto getUserCouponDto = new GetUserCouponDto(); getUserCouponDto.setUserId(Long.valueOf(uid)); getUserCouponDto.setTotalAmount(order.getOrderMoney().doubleValue()); @@ -1250,10 +1423,28 @@ } order.setAppUserId(null); baseMapper.updateById(order); // 结束后的车辆操作 if(vehicle!=null){ // 修改车辆状态 vehicle.setState(0); // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作 R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail(); XpTaskRule xpTaskRule = xpTaskRuleR.getData(); // 生成新的巡游单子 回到最新巡游的初始起点位置 XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1")); int temp=0; if(xpCruiseOrders==null){ temp=1; //特殊情况 可能没有产生终止的订单 (到站点就被正常接单了)所以找正常订单 xpCruiseOrders=xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 3).orderByDesc(BaseModel::getCreateTime).last("limit 1")); } XpCruiseOrder xpCruiseOrder = new XpCruiseOrder(); xpCruiseOrder.setVehicleId(vehicle.getId()); xpCruiseOrder.setFleetId(vehicle.getFleetId()); @@ -1265,19 +1456,54 @@ xpCruiseOrder.setStartLon(order.getEndLon()); xpCruiseOrder.setStartLat(order.getEndLat()); xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat()); // 完成的直接走终点 终止的走起点 if(temp==0){ xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat()); }else { xpCruiseOrder.setEndPointId(xpCruiseOrders.getEndPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getEndPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getEndLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getEndLat()); } xpCruiseOrder.setStatus(1); xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId()); xpCruiseOrder.setCreateTime(LocalDateTime.now()); xpCruiseOrder.setId("XU"+ IdUtil.fastUUID()); // 判断当前时分秒是否大于收车时间 LocalTime vehicleCollectionTime = xpTaskRule.getVehicleCollectionTime(); if (vehicleCollectionTime.isBefore(LocalTime.now())) { vehicle.setOperatingStatus(3); //找到车辆的收车点位 更新终点点位 R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder); xpCruiseOrder = returnCruisePoint.getData(); } xpVehicleClient.updateVehicleById(vehicle); xpCruiseOrderMapper.insert(xpCruiseOrder); R<XpPoint> xpPointR = xpPointClient.queryById(order.getEndPointId()); XpPoint data = xpPointR.getData(); //下发命令 orderMissionClient.pushOrder(new PushOrderDto(vehicle.getVehicleVin(),xpCruiseOrder.getId(),null)); // 添加自动结束行程定时任务job Map<String, ? extends Object> jobMaps = new ImmutableMap.Builder<String, String>(). put("id", xpCruiseOrder.getId()) .build(); QuartzManager.addJob( AddCruiseMissionJob.class, (AddCruiseMissionJob.name + xpCruiseOrder.getId()).toUpperCase(), TimeJobType.ADD_CRUISE_MISSION, DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(data.getParkingTimeLimit())), jobMaps ); } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -479,8 +479,9 @@ */ @ApiOperation(value = "查询可改派的车辆列表", tags = {"管理后台-订单管理"}) @GetMapping("/api/v1/vehicle/availableList") public R<List<XpVehicle>> listAvailableVehicles() { List<XpVehicle> list = xpVehicleService.listAvailableVehicles(); @ApiImplicitParam(name = "orderId", value = "订单ID", required = true, dataTypeClass = Long.class) public R<List<XpVehicle>> listAvailableVehicles(@RequestParam Long orderId) { List<XpVehicle> list = xpVehicleService.listAvailableVehicles(orderId); return R.ok(list); } xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IXpVehicleService.java
@@ -33,7 +33,7 @@ * * @return 车辆列表 */ List<XpVehicle> listAvailableVehicles(); List<XpVehicle> listAvailableVehicles(Long orderId); /** * 查询车辆列表接口-地图 xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -11,6 +11,7 @@ import com.xiaopeng.api.feignClient.operation.XpElectronicClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.model.operation.XpElectronicFence; import com.xiaopeng.api.model.operation.XpElectronicFenceArea; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.model.vehicleConvoy.XpVehicleAnnualRecord; @@ -83,22 +84,45 @@ } @Override public List<XpVehicle> listAvailableVehicles() { // 构建查询条件 LambdaQueryWrapper<XpVehicle> wrapper = new LambdaQueryWrapper<>(); public List<XpVehicle> listAvailableVehicles(Long orderId) { // 1. 通过订单ID查询订单信息,获取区域ID R<XpOrder> orderResult = xpOrderClient.queryOrderById(orderId); if (orderResult == null || orderResult.getData() == null) { log.warn("查询订单失败,orderId: {}", orderId); return Collections.emptyList(); } // 必要条件:可改派车辆的4个核心条件 wrapper.ne(XpVehicle::getStatus, 3) // 状态不是保险/年检过期 .isNotNull(XpVehicle::getStatus) .eq(XpVehicle::getOperatingStatus, 1) // 运营中 .eq(XpVehicle::getAcceptOrTest, 1) // 接单模式 .eq(XpVehicle::getAcceptOrTestStatus, 1); // 开始接单 XpOrder order = orderResult.getData(); Long areaId = order.getXpElectronicFenceAreaId(); if (areaId == null) { log.warn("订单区域ID为空,orderId: {}", orderId); return Collections.emptyList(); } // 2. 通过区域ID查询围栏ID R<XpElectronicFenceArea> areaResult = xpElectronicClient.queryElectronicFenceAreaById(areaId); if (areaResult == null || areaResult.getData() == null) { log.warn("查询围栏区域失败,areaId: {}", areaId); return Collections.emptyList(); } Long electronicId = areaResult.getData().getElectronicId(); if (electronicId == null) { log.warn("围栏ID为空,areaId: {}", areaId); return Collections.emptyList(); } // 3. 根据围栏ID查询车辆列表 (operatingStatus=1 且 state=0) LambdaQueryWrapper<XpVehicle> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(XpVehicle::getElectronicId, electronicId) .eq(XpVehicle::getOperatingStatus, 1) .eq(XpVehicle::getState, 0); // 排序:按电量降序、入库时间降序 wrapper.orderByDesc(XpVehicle::getCurrentElectricity) .orderByDesc(XpVehicle::getWarehousingTime); // 执行查询 return this.list(wrapper); } xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages.properties
@@ -1,7 +1,7 @@ # 中文 fleet.operation.user.bound.v2=当前车队已和该人员关联 policy.application.audit.ids.notEmpty=保单申请ID列表不能为空 fleet.user.bound=运维人员[{0}]已绑定车队[{1}] fleet.operation.user.bound.v1=运维人员[{0}]已绑定车队[{1}] fleet.vehicle.bound.v2=当前车队已和该车辆关联 fleet.vehicle.bound.v1=车辆[{0}]已绑定车队[{1}] policy.application.audit.status.notNull=保单审核状态不能为空 xp-robotaxi-vehicle-convoy-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -2,6 +2,7 @@ fleet.operation.user.bound.v2=当前车队已和该人员关联 policy.application.audit.ids.notEmpty=保单申请ID列表不能为空 fleet.user.bound=运维人员[{0}]已绑定车队[{1}] fleet.operation.user.bound.v1=运维人员[{0}]已绑定车队[{1}] fleet.vehicle.bound.v2=当前车队已和该车辆关联 policy.application.audit.status.notNull=保单审核状态不能为空 welcome.message=欢迎来到我们的应用程序!