xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/automaticPilot/PushOrderDto.java
@@ -3,17 +3,21 @@ import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @ApiModel("推送订单Dto") @AllArgsConstructor @NoArgsConstructor public class PushOrderDto { @ApiModelProperty("车辆vin") private String vin; // 订单id @ApiModelProperty("订单id") private Long orderId; private String orderId; /** xp-robotaxi-api/src/main/java/com/xiaopeng/api/factory/order/XpCruiseOrderClientFallbackFactory.java
New file @@ -0,0 +1,51 @@ package com.xiaopeng.api.factory.order; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.common.core.domain.R; import lombok.extern.slf4j.Slf4j; import org.springframework.cloud.openfeign.FallbackFactory; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.ArrayList; /** * 订单Feign客户端降级工厂 * * @author mitao */ @Slf4j @Component public class XpCruiseOrderClientFallbackFactory implements FallbackFactory<XpCruiseOrderClient> { @Override public XpCruiseOrderClient create(Throwable cause) { log.error("订单服务调用失败: {}", cause.getMessage()); return new XpCruiseOrderClient() { @Override public R<String> addCruiseOrder(XpCruiseOrder order) { log.error("订单服务调用失败: {}", cause.getMessage()); return null; } @Override public R<String> updateCruiseOrder(String vin) { log.error("订单服务调用失败: {}", cause.getMessage()); return null; } @Override public R<XpCruiseOrder> getCruiseOrder(String orderId) { log.error("订单服务调用失败: {}", cause.getMessage()); return null; } }; } } xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/order/XpCruiseOrderClient.java
New file @@ -0,0 +1,55 @@ package com.xiaopeng.api.feignClient.order; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.factory.order.XpCruiseOrderClientFallbackFactory; import com.xiaopeng.api.factory.order.XpOrderClientFallbackFactory; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.dto.ServiceNameConstantsEnum; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; /** * 巡游订单Feign客户端 * * @author mitao */ @FeignClient(contextId = "XpCruiseOrderClient", value = ServiceNameConstantsEnum.XP_ORDER_SERVICE, fallbackFactory = XpCruiseOrderClientFallbackFactory.class) public interface XpCruiseOrderClient { /** * 添加订单 * * @param order 订单信息 */ @PostMapping("/inner/cruiseOrder/addCruiseOrder") R<String> addCruiseOrder(@RequestBody XpCruiseOrder order); /** * 查询并关闭订单信息 返回id信息 * * @param vin 订单信息 */ @PostMapping("/inner/cruiseOrder/updateCruiseOrder") R<String> updateCruiseOrder(@RequestParam String vin); /** * 查询订单信息 * * @param orderId 订单信息id */ @PostMapping("/inner/cruiseOrder/getCruiseOrder") R<XpCruiseOrder> getCruiseOrder(@RequestParam String orderId); } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPoint.java
@@ -88,4 +88,7 @@ @ApiModelProperty(value = "距离 单位米") @TableField(exist = false) private BigDecimal distance; @ApiModelProperty(value = "0正常点位 1充电点位 2收车点位") private Integer type; } xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/order/XpCruiseOrder.java
New file @@ -0,0 +1,84 @@ package com.xiaopeng.api.model.order; import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.xiaopeng.common.core.web.domain.BaseModel; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; import java.math.BigDecimal; import java.time.LocalDateTime; /** * <p> * 订单-巡游 * </p> * * @author mitao * @since 2026-02-03 */ @Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("xp_cruise_order") @ApiModel(value="XpCruiseOrder对象", description="订单巡游") public class XpCruiseOrder extends BaseModel { private static final long serialVersionUID = 1L; @TableId(value = "id", type = IdType.NONE) private String id; @ApiModelProperty(value = "车辆id") private Long vehicleId; @ApiModelProperty(value = "车辆vin") private String vehicleVin; @ApiModelProperty(value = "订单类型 1=正常巡游单 2返程单") private Integer orderType; @ApiModelProperty(value = "出发地经度值") private Double startLon; @ApiModelProperty(value = "出发地纬度值") private Double startLat; @ApiModelProperty(value = "目的地经度") private Double endLon; @ApiModelProperty(value = "目的地纬度") private Double endLat; @ApiModelProperty(value = "状态 1进行中 2已停止") private Integer status; @ApiModelProperty(value = "下单站点id") @TableField("start_point_id") private Long startPointId; @ApiModelProperty(value = "下单终点站点Id") @TableField("end_point_id") private Long endPointId; @ApiModelProperty(value = "下单站点名称") @TableField("start_point_name") private String startPointName; @ApiModelProperty(value = "下单终点站点名称") @TableField("end_point_name") private String endPointName; @ApiModelProperty(value = "任务id") @TableField("mission_id") private String missionId; @ApiModelProperty(value = "返程上次的订单id") @TableField("last_order_id") private String lastOrderId; } xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -40,15 +40,21 @@ @PostMapping("/inner/pushOrder") public R<Boolean> pushOrder(@RequestBody PushOrderDto dto) { RTTask task = new RTTask(); task.setOrder_id(dto.getOrderId().toString()); task.setOrder_id(dto.getOrderId()); task.setTask_id("MISSION_"+ IdUtil.fastUUID()); task.setTask_type(TaskType.ROBOTAXI); if(dto.getOrderId().contains("XU")){ task.setTask_type(TaskType.CRUISE); }else { task.setTask_type(TaskType.ROBOTAXI); } task.setStatus(TaskStatus.PENDING); SnowFlake snowFlake = new SnowFlake(0, 0); snowFlake.withStartTimestamp(1420041600000L); long sequence = snowFlake.nextId(); MqttPublishDto mqttPublishDto = xpuUtil.cloudCreateOrder(task, dto.getVin(),sequence); if (mqttPublishDto.getCode()== 200) { // 正常单子才修改 巡游单子不修改状态 if (!dto.getOrderId().contains("XU") && mqttPublishDto.getCode()== 200) { // 修改车子为接单状态 xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(dto.getVin(),1)); xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -1,8 +1,10 @@ package com.xiaopeng.automaticPilot.service; import cn.hutool.core.lang.Snowflake; import cn.hutool.core.util.IdUtil; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto; import com.xiaopeng.api.dto.map.OrderRouteAndFareDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.operation.ReassignOrderDTO; @@ -11,16 +13,21 @@ import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.operation.ReassignOrderClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.automaticPilot.VehiclePosition; import com.xiaopeng.api.vo.automaticPilot.proto.down.GeoPoint; import com.xiaopeng.api.vo.automaticPilot.proto.down.ResponseMessage; import com.xiaopeng.api.vo.automaticPilot.proto.down.StatusCode; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.RTTask; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskStatus; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudCreateOrder.TaskType; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.*; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudPushNavigation.RestoreNavigationData; import com.xiaopeng.api.vo.automaticPilot.proto.up.MessageType; @@ -41,6 +48,7 @@ import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.core.enums.PushMessageTypeEnum; import com.xiaopeng.common.core.utils.SnowFlake; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.utils.uuid.UUID; import lombok.extern.slf4j.Slf4j; @@ -89,6 +97,9 @@ @Resource private UserVehicleClient userVehicleClient; @Resource private XpCruiseOrderClient xpCruiseOrderClient; @Resource private Snowflake snowflake; @@ -687,7 +698,6 @@ if(orderId.contains("XU")){ //巡游单 //响应消息 // TODO 1.处理结束当前巡游订单 2.创建新的巡游订单 返航 3.调用xpu车机接口 (判断是返航还是正常 返航需要存储之前的订单id) responseMessage(sequence, ""); //前往目的地 if(OrderStatusEnum.IN_SERVICE.equals(status)){ @@ -696,6 +706,47 @@ //到达目的地 if(OrderStatusEnum.COMPLETED.equals(status)){ // 返程找到目前的订单 -》之前的订单 查询生成一个 正常巡游 找到下一个点位 若到达最后点位 则反向找点位 每次判断是否收车状态 是则不进行处理了 // 找到这个订单 R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(orderId); if(cruiseOrder!=null){ XpCruiseOrder xpCruiseOrder = cruiseOrder.getData(); Long vehicleId = xpCruiseOrder.getVehicleId(); // 关闭当前巡游单子 xpCruiseOrderClient.updateCruiseOrder(xpCruiseOrder.getVehicleVin()); R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId); XpVehicle xpVehicle = xpVehicleR.getData(); // 运营中 继续执行 if(xpVehicle.getOperatingStatus()==1 && xpVehicle.getState()==0){ // 创建新的巡游单子 判断是否为返程单子 if(xpCruiseOrder.getOrderType()==2){ R<XpCruiseOrder> lastOrder = xpCruiseOrderClient.getCruiseOrder(xpCruiseOrder.getLastOrderId()); XpCruiseOrder lastXpCruiseOrder = lastOrder.getData(); // 修改一下id 加一个一样的巡游单子 lastXpCruiseOrder.setId("XU"+ IdUtil.fastUUID()); xpCruiseOrderClient.addCruiseOrder(lastXpCruiseOrder); RTTask task = new RTTask(); task.setOrder_id(lastXpCruiseOrder.getId()); task.setTask_id("MISSION_"+ IdUtil.fastUUID()); task.setTask_type(TaskType.CRUISE); task.setStatus(TaskStatus.PENDING); SnowFlake snowFlake = new SnowFlake(0, 0); snowFlake.withStartTimestamp(1420041600000L); long sequence1 = snowFlake.nextId(); xpuUtil.cloudCreateOrder(task, xpVehicle.getVehicleVin(),sequence1); }else if(xpCruiseOrder.getOrderType()==1){ // 正常巡游 找到下一个点位 若到达最后点位 则反向找点位 TODO v } } } } }else{ //普通单 xp-robotaxi-itinerary-boot/src/main/resources/i18n/messages.properties
@@ -1,4 +1,4 @@ # 中文 path.not.found=????? to.work= ??????????,?????? path.not.found=路径不存在 to.work=当前的接送点距离过近。建议步行前往 welcome.message=欢迎来到我们的应用程序! xp-robotaxi-itinerary-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -1,4 +1,4 @@ # 中文 path.not.found=????? to.work=\ ??????????,?????? path.not.found=路径不存在 to.work=当前的接送点距离过近。建议步行前往 welcome.message=欢迎来到我们的应用程序! xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java
@@ -42,10 +42,23 @@ @ApiOperation(value = "车辆运维-车辆调度-发车/收车", tags = {"运维APP-车辆管理"}) @PostMapping("/api/v1/vehicle/vehicleDispatchDeparture") public R<String> vehicleDispatchDeparture(@RequestBody VehicleDispatchDepartureDTO dto) { // 判断是否有正在进行的正常订单 // 查询车辆 XpVehicle xpVehicle = xpVehicleClient.queryById(dto.getVehicleId()).getData(); if(xpVehicle.getState()==1){ return R.fail("车辆正在接单中"); } xpVehicle.setOperatingStatus(dto.getDepartureStatus()); xpVehicleClient.updateVehicleById(xpVehicle); // 发车 if(dto.getDepartureStatus()==1){ // 找车辆的任务 生成巡游单子 下发命令 TODO }else if(dto.getDepartureStatus()==3){ // 收车 关闭巡游单子 TODO } return R.ok(); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAgreementUserController.java
@@ -53,7 +53,7 @@ public R<Boolean> getPrivacyAgreement(HttpServletRequest request) { // uid已通过拦截器otp校验,可以直接使用 String uid = request.getHeader("XP-Uid"); long count = xpAgreementAppUserService.count(new LambdaQueryWrapper<XpAgreementAppUser>().eq(XpAgreementAppUser::getAppUserId, uid)); long count = xpAgreementAppUserService.count(new LambdaQueryWrapper<XpAgreementAppUser>().eq(XpAgreementAppUser::getAppUserId, Long.valueOf(uid))); if (count > 0) { return R.ok(true); } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointController.java
@@ -91,4 +91,6 @@ } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPointManagementController.java
@@ -1,6 +1,7 @@ package com.xiaopeng.operation.controller; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.xiaopeng.api.dto.operation.PointAddDto; import com.xiaopeng.api.dto.operation.PointUpdateDto; import com.xiaopeng.api.dto.operation.XpPointEnableDisableDto; @@ -8,6 +9,7 @@ import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.controller.BaseController; import com.xiaopeng.api.query.operation.PointPageListQuery; import com.xiaopeng.operation.dto.XpPointSpecialDto; import com.xiaopeng.operation.service.IXpElectronicFenceAreaService; import com.xiaopeng.operation.service.IXpElectronicFenceService; import com.xiaopeng.operation.service.XpPointService; @@ -110,4 +112,17 @@ xpPointService.updateById(xpPoint); return R.ok(); } /** * 设置特殊点位 */ @PostMapping("/setSpecialPoint") @ApiOperation(value = "设置特殊点位") public R setSpecialPoint(@RequestBody XpPointSpecialDto dto) { xpPointService.update(new LambdaUpdateWrapper<XpPoint>().set(XpPoint::getType, 0)); xpPointService.update(new LambdaUpdateWrapper<XpPoint>().in(XpPoint::getId,dto.getChargePoints()).set(XpPoint::getType,1)); xpPointService.update(new LambdaUpdateWrapper<XpPoint>().in(XpPoint::getId,dto.getParkingPoints()).set(XpPoint::getType,2)); return R.ok(); } } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpPointSpecialDto.java
New file @@ -0,0 +1,21 @@ package com.xiaopeng.operation.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.util.List; @Data @ApiModel(value = "XpPointSpecialDto",description = "特殊点位") public class XpPointSpecialDto { // 充电点位 @ApiModelProperty(value = "充电点位") private List<Long> chargePoints; // 收车点位 @ApiModelProperty(value = "收车点位") private List<Long> parkingPoints; } xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -8,6 +8,7 @@ import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.feignClient.map.XpMapClient; import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient; import com.xiaopeng.api.feignClient.order.XpOrderClient; import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient; import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient; @@ -65,7 +66,7 @@ private IXpTradingStrategyService xpTradingStrategyService; @Autowired private UserVehicleClient userVehicleClient; private XpCruiseOrderClient xpCruiseOrderClient; @Autowired private XpVehicleClient xpVehicleClient; @@ -769,11 +770,11 @@ lock.unlock(); continue; } // 关闭巡游单子 TODO // 关闭巡游单子 xpCruiseOrderClient.updateCruiseOrder(vehiclePosition.getVehicleVin()); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setVin(vehiclePosition.getVehicleVin()); @@ -806,11 +807,12 @@ lock.unlock(); continue; } // 关闭巡游单子 TODO // 关闭巡游单子 xpCruiseOrderClient.updateCruiseOrder(vehicleId1.getVehicleVin()); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(xpOrder.getId()); pushOrderDto.setOrderId(xpOrder.getId().toString()); pushOrderDto.setVin(vehiclePosition.getVin()); // 调用推送服务 orderId + carVin @@ -879,10 +881,11 @@ lock.unlock(); continue; } // 关闭巡游单子 TODO // 关闭巡游单子 xpCruiseOrderClient.updateCruiseOrder(vehicleId1.getVehicleVin()); PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(data.getId()); pushOrderDto.setOrderId(data.getId().toString()); pushOrderDto.setVin(vehiclePosition.getVin()); // 调用推送服务 orderId + carVin orderMissionClient.pushOrder(pushOrderDto); xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpCruiseOrderController.java
New file @@ -0,0 +1,81 @@ package com.xiaopeng.order.controller; import cn.hutool.core.util.IdUtil; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.order.service.IXpCruiseOrderService; import io.swagger.annotations.Api; import lombok.RequiredArgsConstructor; import org.springframework.context.annotation.Lazy; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * <p> * 订单 前端控制器 * </p> * * @author mitao * @since 2026-02-03 */ @RestController @Api(tags = "巡游订单") @RequiredArgsConstructor(onConstructor_ = @Lazy) public class XpCruiseOrderController { private final IXpCruiseOrderService xpCruiseOrderService; private final OrderMissionClient orderMissionClient; /** * 查询并关闭订单信息 返回id信息 * * @param */ @PostMapping("/inner/cruiseOrder/updateCruiseOrder") public R<String> updateCruiseOrder(@RequestParam String vin) { String id = xpCruiseOrderService.updateCruiseOrder(vin); return R.ok(id); } /** * 查询订单信息 * @param orderId * @return */ @PostMapping("/inner/cruiseOrder/getCruiseOrder") public R<XpCruiseOrder> getCruiseOrder(@RequestParam String orderId){ return R.ok(xpCruiseOrderService.getById(orderId)); } /** * 新增订单 下发命令 * * @param * @return 订单ID */ @PostMapping("/inner/cruiseOrder/addCruiseOrder") public R<String> addCruiseOrder(@RequestBody XpCruiseOrder order) { order.setId("XU"+ IdUtil.fastUUID()); boolean save = xpCruiseOrderService.save(order); if (!save) { return R.fail("新增失败"); } // 下发命令 PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setVin(order.getVehicleVin()); pushOrderDto.setOrderId(order.getId()); orderMissionClient.pushOrder(pushOrderDto); return R.ok(order.getId()); } } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/mapper/XpCruiseOrderMapper.java
New file @@ -0,0 +1,25 @@ package com.xiaopeng.order.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; import com.xiaopeng.order.model.vo.XpOrderHistoryListVO; import org.apache.ibatis.annotations.Param; import java.math.BigDecimal; import java.time.LocalDate; import java.util.List; /** * <p> * 订单 Mapper 接口 * </p> * * @author mitao * @since 2026-02-03 */ public interface XpCruiseOrderMapper extends BaseMapper<XpCruiseOrder> { } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/model/vo/XpOrderDetailVO.java
@@ -96,11 +96,19 @@ @TableField("start_point_id") private Long startPointId; @ApiModelProperty(value = "起点停车时间限制") private Integer startParkingTimeLimit; @ApiModelProperty(value = "下单终点站点Id") @TableField("end_point_id") private Long endPointId; @ApiModelProperty(value = "终点点停车时间限制") private Integer endParkingTimeLimit; @ApiModelProperty(value = "上车点") private String boardingAddress; xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpCruiseOrderService.java
New file @@ -0,0 +1,42 @@ package com.xiaopeng.order.service; import com.baomidou.mybatisplus.extension.service.IService; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.model.order.XpCruiseOrder; import com.xiaopeng.api.model.order.XpOrder; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.order.FareBreakdownVo; import com.xiaopeng.api.vo.order.XpHistoryEndPointsVo; import com.xiaopeng.api.vo.order.XpHistoryStartPointsVo; import com.xiaopeng.api.vo.order.XpPointInfoVo; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.model.dto.XpOrderCommentDto; import com.xiaopeng.order.model.dto.XpOrderPayDto; import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; import com.xiaopeng.order.model.query.XpOrderPageQuery; import com.xiaopeng.order.model.vo.XpOrderDetailVO; import com.xiaopeng.order.model.vo.XpOrderHistoryVO; import com.xiaopeng.order.model.vo.XpOrderPageVO; import com.xiaopeng.order.vo.OrderDetailVo; import java.util.List; /** * <p> * 订单 服务类 * </p> * * @author mitao * @since 2026-02-03 */ public interface IXpCruiseOrderService extends IService<XpCruiseOrder> { String updateCruiseOrder(String vin); } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpCruiseOrderServiceImpl.java
New file @@ -0,0 +1,133 @@ package com.xiaopeng.order.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.google.common.collect.ImmutableMap; import com.xiaopeng.api.dto.account.GetUserCouponDto; import com.xiaopeng.api.dto.account.UseUserCouponDto; import com.xiaopeng.api.dto.automaticPilot.PushOrderDto; import com.xiaopeng.api.dto.operation.LonLatDto; import com.xiaopeng.api.dto.order.GetOrderNumDto; import com.xiaopeng.api.dto.order.HistoryEndPointsDto; import com.xiaopeng.api.dto.order.HistoryStartPointsDto; import com.xiaopeng.api.dto.order.PopOrderDto; import com.xiaopeng.api.dto.pushMessage.SendMessageDTO; import com.xiaopeng.api.dto.statistics.DailyCountDTO; import com.xiaopeng.api.dto.statistics.OrderStatisticsDTO; import com.xiaopeng.api.dto.statistics.StatisticsQueryDTO; import com.xiaopeng.api.dto.vehicleConvoy.BaseVehicleUserDto; 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.operation.XpPointClient; import com.xiaopeng.api.feignClient.operation.XpPricingClient; import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient; 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.operation.XpFeedbackType; import com.xiaopeng.api.model.operation.XpGeoQueryEntity; import com.xiaopeng.api.model.operation.XpPoint; import com.xiaopeng.api.model.operation.XpPricing; import com.xiaopeng.api.model.order.*; import com.xiaopeng.api.model.vehicleConvoy.XpFleet; import com.xiaopeng.api.model.vehicleConvoy.XpVehicle; import com.xiaopeng.api.vo.account.UserCouponVo; import com.xiaopeng.api.vo.automaticPilot.proto.down.cloudOrderOperation.OrderOperationType; import com.xiaopeng.api.vo.order.*; import com.xiaopeng.api.vo.vehicleConvoy.AddTaxiPassengerVo; import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo; import com.xiaopeng.common.core.constant.CacheConstants; import com.xiaopeng.common.core.domain.R; import com.xiaopeng.common.core.enums.OrderStatusEnum; import com.xiaopeng.common.core.enums.PushMessageTypeEnum; import com.xiaopeng.common.core.exception.ServiceException; import com.xiaopeng.common.core.utils.DateUtils; import com.xiaopeng.common.core.utils.GeodesyUtil; import com.xiaopeng.common.core.utils.StringUtils; import com.xiaopeng.common.core.web.domain.BaseModel; import com.xiaopeng.common.core.web.page.PageInfo; import com.xiaopeng.common.redis.service.RedisService; import com.xiaopeng.common.security.utils.SecurityUtils; import com.xiaopeng.order.constant.I18nKeyConstant; 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.EndTripJob; import com.xiaopeng.order.job.jobs.OrderCancelJob; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.mangodb.service.OrderTrajectoryService; import com.xiaopeng.order.mapper.XpCruiseOrderMapper; import com.xiaopeng.order.mapper.XpOrderDetailMapper; import com.xiaopeng.order.mapper.XpOrderMapper; import com.xiaopeng.order.model.dto.XpOrderCommentDto; import com.xiaopeng.order.model.dto.XpOrderPayDto; import com.xiaopeng.order.model.query.XpHistoryOrderListQuery; import com.xiaopeng.order.model.query.XpOrderPageQuery; import com.xiaopeng.order.model.vo.*; import com.xiaopeng.order.service.*; import com.xiaopeng.order.utils.TaxiPricingDemoService; import com.xiaopeng.order.utils.TrajectoryGenerator; import com.xiaopeng.order.utils.holiday.HolidayUtil; import com.xiaopeng.order.vo.OrderDetailVo; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; import org.springframework.data.domain.Sort; 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.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import java.math.BigDecimal; import java.math.RoundingMode; import java.text.SimpleDateFormat; import java.time.*; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.function.Function; import java.util.stream.Collectors; /** * <p> * 订单 服务实现类 * </p> * * @author mitao * @since 2026-02-03 */ @Slf4j @Service @RequiredArgsConstructor(onConstructor_ = @Lazy) public class XpCruiseOrderServiceImpl extends ServiceImpl<XpCruiseOrderMapper, XpCruiseOrder> implements IXpCruiseOrderService { /** * 关闭当前巡游单子 * @param vin */ @Override public String updateCruiseOrder(String vin) { LambdaQueryWrapper<XpCruiseOrder> wrapper = new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleVin, vin).eq(XpCruiseOrder::getStatus, 1); XpCruiseOrder xpCruiseOrder = this.getOne(wrapper); if (xpCruiseOrder != null) { xpCruiseOrder.setStatus(2); this.update(xpCruiseOrder, wrapper); return xpCruiseOrder.getId(); } return null; } } xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -1,6 +1,7 @@ package com.xiaopeng.order.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -65,6 +66,7 @@ import com.xiaopeng.order.job.jobs.OrderCancelJob; import com.xiaopeng.order.mangodb.model.OrderTrajectory; import com.xiaopeng.order.mangodb.service.OrderTrajectoryService; import com.xiaopeng.order.mapper.XpCruiseOrderMapper; import com.xiaopeng.order.mapper.XpOrderDetailMapper; import com.xiaopeng.order.mapper.XpOrderMapper; import com.xiaopeng.order.model.dto.XpOrderCommentDto; @@ -132,6 +134,8 @@ private final XpPushMessageClient xpPushMessageClient; private final OrderMissionClient orderMissionClient; private final XpOrderDetailMapper xpOrderDetailMapper; private final XpCruiseOrderMapper xpCruiseOrderMapper; @Autowired private MongoTemplate mongoTemplate; @@ -762,7 +766,7 @@ // 下发命令 if(order.getStatus()>1){ PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId()); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.VEHICLE_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); @@ -810,7 +814,7 @@ // 下发命令 if(order.getStatus()>1){ PushOrderDto pushOrderDto = new PushOrderDto(); pushOrderDto.setOrderId(order.getId()); pushOrderDto.setOrderId(order.getId().toString()); pushOrderDto.setVin(xpVehicle.getVehicleVin()); pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER); orderMissionClient.cancelOrder(pushOrderDto); @@ -955,7 +959,14 @@ // TODO 加配置文件取 cancelTaxiPassengerVo.setAppId(""); userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo); // 修改车辆接单状态 vehicle.setState(0); xpVehicleClient.updateVehicleById(vehicle); } // 根据订单所属开通城市id 查询定价 R<XpPricing> pricingByCityId = xpPricingClient.getPricingByCid(order.getCityId()); XpPricing pricing = pricingByCityId.getData(); @@ -1187,6 +1198,49 @@ useUserCouponDto.setUserCouponId(order.getCouponId()); xpAppUserCouponClient.useUserCoupon(useUserCouponDto); } // 结束后的车辆操作 if(vehicle!=null){ // 生成新的巡游单子 回到最新巡游的初始起点位置 XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1")); XpCruiseOrder xpCruiseOrder = new XpCruiseOrder(); xpCruiseOrder.setVehicleId(vehicle.getId()); xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin()); xpCruiseOrder.setOrderType(2); // 返程起点是当前正常订单的终点 xpCruiseOrder.setStartPointId(order.getEndPointId()); xpCruiseOrder.setStartPointName(order.getEndPointName()); xpCruiseOrder.setStartLon(order.getEndLon()); xpCruiseOrder.setStartLat(order.getEndLat()); xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId()); xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName()); xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon()); xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat()); xpCruiseOrder.setStatus(1); xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId()); xpCruiseOrder.setCreateTime(LocalDateTime.now()); xpCruiseOrder.setId("XU"+ IdUtil.fastUUID()); xpCruiseOrderMapper.insert(xpCruiseOrder); //下发命令 orderMissionClient.pushOrder(new PushOrderDto(vehicle.getVehicleVin(),xpCruiseOrder.getId(),null)); } } @@ -1648,6 +1702,18 @@ return null; } BeanUtils.copyProperties(xpOrder, xpOrderDetailVO); R<XpPoint> xpPointR = xpPointClient.queryById(xpOrder.getStartPointId()); if (xpPointR.getCode() == R.SUCCESS) { XpPoint startPoint = xpPointR.getData(); xpOrderDetailVO.setStartParkingTimeLimit(startPoint.getParkingTimeLimit()); } R<XpPoint> xpPointR1 = xpPointClient.queryById(xpOrder.getEndPointId()); if (xpPointR1.getCode() == R.SUCCESS) { XpPoint endPoint = xpPointR1.getData(); xpOrderDetailVO.setEndParkingTimeLimit(endPoint.getParkingTimeLimit()); } // 算时间 if (xpOrder.getStatus() == 1) { R<Integer> r = xpPricingClient.getWaitTime(new LonLatDto(xpOrder.getStartLon(), xpOrder.getStartLat())); xp-robotaxi-order-boot/src/main/resources/mapper/order/XpCruiseOrderMapper.xml
New file @@ -0,0 +1,10 @@ <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.xiaopeng.order.mapper.XpCruiseOrderMapper"> <!-- 通用查询结果列 --> <sql id="Base_Column_List"> id, app_user_id, vehicle_id, fleet_id, order_number, transaction_id, order_source, ride_time, placement_lon, placement_lat, placement_address, start_lon, start_lat, end_lon, end_lat, start_address, end_address, boarding_lon, boarding_lat, boarding_address, boarding_time, getoff_lon, getoff_lat, getoff_address, getoff_time, pay_type, order_money, pay_money, prepay_money, start_mileage, start_money, mileage_kilometers, mileage_money, duration, duration_money, wait, wait_money, long_distance, long_distanceMoney, red_packet_money, coupon_money, red_packet_id, coupon_id, status, is_deleted, create_time, update_time, create_by, update_by,city_id </sql> </mapper>