yyy
2026-04-30 11e55e11d3d3397cd2b54a65b2cda202be822296
Merge branch '1.0' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi into 1.0
22个文件已添加
39个文件已修改
2545 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/XpActivityDto.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityStrategy.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityUser.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivity.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivityNotice.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpOfficialPartner.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPricing.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpTradingStrategyPush.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/vehicleConvoy/XpVehicle.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/XpTradingStrategyDetailVO.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/pom.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/AbstractJob.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/QuartzManager.java 128 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/TimeJobType.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/exceptions/TimeException.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/jobs/OrderExceptionJob.java 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/utils/SpringContextsUtil.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-redis/src/main/java/com/xiaopeng/common/redis/service/RedisService.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/mapper/XpTradingStrategyPushMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 243 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/vo/RedisQueuePointIdVo.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/resources/mapper/itinerary/XpTradingStrategyPushMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleModelController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpActicityController.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpOfficialPartnerController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTargetedServiceController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTradingStrategyController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpTradingStrategyEditDTO.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpOfficialPartnerMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpTradingStrategyPushMapper.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpOfficialPartnerService.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpTradingStrategyPushService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpTargetedServiceVehicleService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityServiceImpl.java 54 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityStrategyServiceImpl.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpOfficialPartnerServiceImpl.java 35 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTargetedServiceVehicleServiceImpl.java 27 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyPushServiceImpl.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyServiceImpl.java 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java 956 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OfficialPartnerVo.java 20 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OrderDistanceVo.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/PricingInfoVo.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpOfficialPartnerMapper.xml 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpTradingStrategyPushMapper.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/mapper/XpOrderMapper.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 120 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/controller/WebSocketController.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetVehicleController.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java 51 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/VehiclePositionDto.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IXpVehicleService.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/XpActivityDto.java
@@ -29,8 +29,11 @@
    @ApiModelProperty(value = "活动类型 如新人活动、媒体邀约活动、日常提频等")
    private Integer activityType;
    @ApiModelProperty(value = "活动类型 如新人活动、媒体邀约活动、日常提频等")
    private Integer acticityType;
    @ApiModelProperty(value = "是否开启活动总限额")
    private boolean enableTotalLimit;
    private Boolean enableTotalLimit;
    @ApiModelProperty(value = "是否开启活动总限额")
    private BigDecimal totalLimit;
@@ -67,7 +70,59 @@
    @ApiModelProperty(value = "发放用户")
    List<XpActicityUser> activityUser;
    @ApiModelProperty(value = "活动通知")
    XpActivityNotice notice;
    @ApiModelProperty("微信通知(0=否,1=是)")
    private Integer wechatNotification;
    @ApiModelProperty("微信通知到账提醒(0=否,1=是)")
    private Integer wechatReceivedReminder;
    @ApiModelProperty("微信通知即将过期提醒(0=否,1=是)")
    private Integer wechatAboutExpireReminder;
    @ApiModelProperty("微信通知即将过期天数")
    private Integer wechatAboutExpireDays;
    @ApiModelProperty("微信通知活动开始提醒(0=否,1=是)")
    private Integer wechatActicityStart;
    @ApiModelProperty("微信通知临近券生效前X分钟通知")
    private Integer wechatActicityStartMinutes;
    @ApiModelProperty("短信通知(0=否,1=是)")
    private Integer smsNotification;
    @ApiModelProperty("短信通知到账提醒(0=否,1=是)")
    private Integer smsReceivedReminder;
    @ApiModelProperty("短信通知即将过期提醒(0=否,1=是)")
    private Integer smsAboutExpireReminder;
    @ApiModelProperty("短信通知即将过期天数")
    private Integer smsAboutExpireDays;
    @ApiModelProperty("短信通知活动开始提醒(0=否,1=是)")
    private Integer smsActicityStart;
    @ApiModelProperty("短信通知临近券生效前X分钟通知")
    private Integer smsActicityStartMinutes;
    @ApiModelProperty("短信通知屏蔽开始时间")
    private String smsStartBlockingTime;
    @ApiModelProperty("短信通知屏蔽结束时间")
    private String smsEndBlockingTime;
    @ApiModelProperty("小程序弹窗通知(0=否,1=是)")
    private Integer miniProgramNotification;
    @ApiModelProperty("小程序弹窗标题")
    private String miniProgramPopupTitle;
    @ApiModelProperty("小程序弹窗按钮文案")
    private String miniProgramBtnText;
    @ApiModelProperty("小程序弹窗券到账提醒(0=否,1=是)")
    private String miniProgramReceivedReminder;
    @ApiModelProperty("小程序弹窗即将过期提醒(0=否,1=是)")
    private String miniProgramAboutExpireReminder;
    @ApiModelProperty("小程序弹窗临近券生效前X分钟")
    private Integer miniProgramAboutExpireMinutes;
    @ApiModelProperty("通知内容")
    private String expireMinutesNotificationContent;
    @ApiModelProperty("小程序弹窗临近到期时间前X天")
    private Integer aboutExpireDays;
    @ApiModelProperty("通知内容")
    private String expireDaysNotificationContent;
    @ApiModelProperty("是否开启浮窗(0=否,1=是)")
    private Integer enableFloatWindow;
    @ApiModelProperty("浮窗优先级权重")
    private Integer floatWindowPriority;
    @ApiModelProperty("浮窗跳转链接")
    private String floatWindowJumpUrl;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityStrategy.java
@@ -11,6 +11,7 @@
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.Value;
import lombok.experimental.Accessors;
import java.time.LocalDate;
@@ -44,6 +45,9 @@
    @ApiModelProperty(value = "发放规则(1=每日循环发放,2=仅发放一次,3=使用后发放)")
    private Integer distributionRules;
    @ApiModelProperty(value = "每日循环发放时间")
    private String distributionTime;
    @ApiModelProperty(value = "发放规则json,[]=本券使用后循环发放, [1,2,3]=指定优惠券使用后发放(优惠券id数组)")
    @TableField(typeHandler = JacksonTypeHandler.class)
@@ -87,4 +91,12 @@
    @ApiModelProperty(value = "是否自动使用(0=不开启,1=冒泡发单时自动使用)")
    private Integer startUsing;
    @ApiModelProperty(value = "优惠券id数据")
    @TableField(exist = false)
    private List<Long> couponIds;
    @ApiModelProperty(value = "优惠券列表数据")
    @TableField(exist = false)
    private List<XpCoupon> couponList;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActicityUser.java
@@ -2,14 +2,18 @@
import com.alibaba.fastjson2.JSONArray;
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.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
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.util.List;
/**
 * <p>
@@ -42,7 +46,8 @@
    private Integer userType;
    @ApiModelProperty(value = "指定用户json数组")
    private JSONArray userList;
    @TableField(typeHandler = JacksonTypeHandler.class)
    private List<Long> userList;
    @ApiModelProperty(value = "策略组名称")
    private String strategyName;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivity.java
@@ -5,6 +5,7 @@
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.vo.account.CouponVo;
import com.xiaopeng.common.core.web.domain.BaseModel;
@@ -50,7 +51,7 @@
    private BigDecimal limitation;
    @ApiModelProperty(value = "封面图片json")
    private JSONObject coverImage;
    private String coverImage;
    @ApiModelProperty(value = "开始时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@@ -98,9 +99,9 @@
    @ApiModelProperty("短信通知临近券生效前X分钟通知")
    private Integer smsActicityStartMinutes;
    @ApiModelProperty("短信通知屏蔽开始时间")
    private LocalDateTime smsStartBlockingTime;
    private String smsStartBlockingTime;
    @ApiModelProperty("短信通知屏蔽结束时间")
    private LocalDateTime smsEndBlockingTime;
    private String smsEndBlockingTime;
    @ApiModelProperty("小程序弹窗通知(0=否,1=是)")
    private Integer miniProgramNotification;
    @ApiModelProperty("小程序弹窗标题")
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpActivityNotice.java
@@ -66,9 +66,9 @@
    private List<String> blockTime;
    @ApiModelProperty(value = "miniProgram临近到期toast")
    private Integer toastBeforeExpiry;
    private String toastBeforeExpiry;
    @ApiModelProperty(value = "miniProgram临近生效toast")
    private Integer toastBeforeEffective;
    private String toastBeforeEffective;
    @ApiModelProperty(value = "是否开启浮窗")
    private Boolean enableFloatingWindow;
    @ApiModelProperty(value = "浮窗优先级权重1-100")
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpOfficialPartner.java
New file
@@ -0,0 +1,42 @@
package com.xiaopeng.api.model.operation;
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 lombok.Data;
/**
 * 合作商
 */
@Data
@TableName("xp_official_partner")
public class XpOfficialPartner extends BaseModel {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;
    /**
     * 名称
     */
    private String name;
    /**
     * 品牌名称
     */
    private String brandName;
    /**
     * 品牌logo
     */
    private String logoUrl;
    /**
     * 应用APPKey
     */
    private String appKey;
    /**
     * 应用APPSecret
     */
    private String appSecret;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpPricing.java
@@ -81,15 +81,6 @@
    private String dynamicPricingJson;
//    public XpPricingDynamicPricesVo getDynamicPricingJsonObj() {
//        if(StringUtils.isNotEmpty(dynamicPricingJson)){
//            return JSONObject.parseObject(dynamicPricingJson, XpPricingDynamicPricesVo.class);
//        }
//        return null;
//    }
    @ApiModelProperty(value = "价格规则")
    @TableField("price_rule")
    private String priceRule;
@@ -99,4 +90,9 @@
    @TableField("is_dynamic_price")
    private Integer isDynamicPrice;
    @ApiModelProperty(value = "合作商id")
    @TableField("official_partner_id")
    private Integer officialPartnerId;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpTradingStrategyPush.java
New file
@@ -0,0 +1,72 @@
package com.xiaopeng.api.model.operation;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.Min;
@Data
@TableName("xp_trading_strategy_push")
public class XpTradingStrategyPush {
    /**
     * 主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Integer id;
    /**
     * 交易策略id
     */
    private Long tradingStrategyId;
    /**
     * 开始时段
     */
    @ApiModelProperty(value = "开始时段")
    private String starTime;
    /**
     * 结束时段
     */
    @ApiModelProperty(value = "结束时段")
    private String endTime;
    @ApiModelProperty(value = "一轮推单距离")
    @Min(0)
    private Double onePushDistance;
    @ApiModelProperty(value = "一轮推单时间")
    @Min(0)
    private Integer onePushTime;
    @ApiModelProperty(value = "二轮推单距离")
    @Min(0)
    private Double twoPushDistance;
    @ApiModelProperty(value = "二轮推单时间")
    @Min(0)
    private Integer twoPushTime;
    @ApiModelProperty(value = "三轮推单距离")
    @Min(0)
    private Double threePushDistance;
    @ApiModelProperty(value = "三轮推单时间")
    @Min(0)
    private Integer threePushTime;
    @ApiModelProperty(value = "四轮推单距离")
    @Min(0)
    private Double fourPushDistance;
    @ApiModelProperty(value = "四轮推单时间")
    @Min(0)
    private Integer fourPushTime;
    @ApiModelProperty(value = "五轮推单距离")
    private Double fivePushDistance;
    @ApiModelProperty(value = "五轮推单时间")
    private Integer fivePushTime;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/vehicleConvoy/XpVehicle.java
@@ -120,6 +120,9 @@
    @ApiModelProperty(value = "车辆接单状态 1接单中 0空闲")
    private Integer state;
    @ApiModelProperty(value = "合作商ID")
    private Integer officialPartnerId;
    @ApiModelProperty(value = "运营区域")
    @TableField(exist = false)
    private String electronicName;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/XpTradingStrategyDetailVO.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.model.operation.XpTradingStrategyCity;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -125,7 +126,8 @@
    @ApiModelProperty(value = "播单—乘客上车后x分钟内未点击出车,订单自动取消")
    private Integer  bdNotBoardedTime;
    @ApiModelProperty("时段推单策略")
    private List<XpTradingStrategyPush> timePushStrategyList;
    //---------------播单策略------------------------------------
xp-robotaxi-automatic-pilot-boot/pom.xml
@@ -108,6 +108,10 @@
        </dependency>
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
        </dependency>
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.2.1</version>
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/controller/OrderMissionController.java
@@ -42,10 +42,7 @@
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
@@ -330,9 +327,6 @@
                && mqttPublishDto.getCode()== 200){
            // 修改车子为接单状态
            xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(dto.getVin(), 1));
            // TODO[流量接入] 通过设置的URL发送订单和导航路线给运力
        }
        if(null != mqttPublishDto && mqttPublishDto.getCode() == 200){
@@ -809,7 +803,7 @@
                    dto.setDistance(10.0);
                    dto.setDirection(60);
                    dto.setMessageType(PushMessageTypeEnum.ORDER_ROUTE.getDesc());
                    xpPushMessageClient.pushOrderRoute(dto);
                    R<String> stringR = xpPushMessageClient.pushOrderRoute(dto);
                    //存储历史轨迹
                    OrderTrajectoryVo orderTrajectory = new OrderTrajectoryVo();
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/AbstractJob.java
New file
@@ -0,0 +1,38 @@
package com.xiaopeng.automaticPilot.job.base;
import com.xiaopeng.api.feignClient.automaticPilot.OrderMissionClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.order.XpTestOrderClient;
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.UserVehicleClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.automaticPilot.job.utils.SpringContextsUtil;
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 XpPushMessageClient xpPushMessageClient;
    protected OrderMissionClient orderMissionClient;
    protected XpVehicleClient xpVehicleClient;
    protected UserVehicleClient userVehicleClient;
    protected XpOrderClient xpOrderClient;
    protected XpTestOrderClient xpTestOrderClient;
    public AbstractJob(){
        this.xpPushMessageClient = SpringContextsUtil.getBean(XpPushMessageClient.class);
        this.orderMissionClient = SpringContextsUtil.getBean(OrderMissionClient.class);
        this.xpVehicleClient = SpringContextsUtil.getBean(XpVehicleClient.class);
        this.userVehicleClient = SpringContextsUtil.getBean(UserVehicleClient.class);
        this.xpOrderClient = SpringContextsUtil.getBean(XpOrderClient.class);
        this.xpTestOrderClient = SpringContextsUtil.getBean(XpTestOrderClient.class);
    }
}
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/job/base/QuartzManager.java
New file
@@ -0,0 +1,128 @@
package com.xiaopeng.automaticPilot.job.base;
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,33 @@
package com.xiaopeng.automaticPilot.job.base;
/**
 * @Description 按时间点发布的任务类型
 * @date 2025年2月17日 下午7:22:28
 */
public enum TimeJobType {
    ORDER_CANCEL("order_cancel","订单取消"),
    TEST_ORDER_CANCEL("test_order_cancel","测试订单取消"),
    ADD_CRUISE_MISSION("add_cruise_mission","添加巡游任务"),
    ADD_CHAIN_REACTION_ORDER_MISSION("add_cruise_mission","添加派送连环单任务"),
    END_TRIP("end_trip","自动结束行程"),
    ERROR_ORDER_CANCEL("error_order_cancel","行程中异常订单取消");
    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/OrderExceptionJob.java
New file
@@ -0,0 +1,38 @@
package com.xiaopeng.automaticPilot.job.jobs;
import com.xiaopeng.api.vo.OrderType;
import com.xiaopeng.automaticPilot.job.base.AbstractJob;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.quartz.JobDataMap;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
/**
 * 异常订单定时任务,创建客服工单
 * @author Administrator
 *
 */
@Slf4j
public class OrderExceptionJob extends AbstractJob {
    public static final String name = "orderException_";
    @Override
    public void execute(JobExecutionContext context)
            throws JobExecutionException {
        JobDataMap maps = context.getMergedJobDataMap();
        Long orderId = maps.getLong("id");
        String orderType = maps.getString("orderType");
        if(OrderType.USER_ORDER.equals(orderType)){
            //修改订单状态
            xpOrderClient.updateOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode(), true);
        }
        if(OrderType.TEST_ORDER.equals(orderType)){
            xpTestOrderClient.updateOrderStatus(orderId, OrderStatusEnum.SEE_OFF_GUESTS.getCode());
        }
        //发起客服工单
    }
}
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
@@ -3,6 +3,7 @@
import cn.hutool.core.lang.Snowflake;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.xiaopeng.api.dto.automaticPilot.MqttPublishDto;
@@ -20,12 +21,14 @@
import com.xiaopeng.api.feignClient.map.XpMapClient;
import com.xiaopeng.api.feignClient.operation.ReassignOrderClient;
import com.xiaopeng.api.feignClient.operation.XpCruisePlanClient;
import com.xiaopeng.api.feignClient.operation.XpSystemSettingClient;
import com.xiaopeng.api.feignClient.order.XpCruiseOrderClient;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.feignClient.order.XpTestOrderClient;
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.operation.XpSystemSetting;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpTestOrder;
@@ -36,6 +39,9 @@
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.order.OrderTrajectoryVo;
import com.xiaopeng.api.vo.vehicleConvoy.CancelTaxiPassengerVo;
import com.xiaopeng.automaticPilot.job.base.QuartzManager;
import com.xiaopeng.automaticPilot.job.base.TimeJobType;
import com.xiaopeng.automaticPilot.job.jobs.OrderExceptionJob;
import com.xiaopeng.automaticPilot.util.XPUUtil;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
@@ -43,6 +49,7 @@
import com.xiaopeng.common.core.enums.CancelOrderSceneEnum;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.enums.PushMessageTypeEnum;
import com.xiaopeng.common.core.utils.DateUtils;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.uuid.UUID;
import com.xiaopeng.common.redis.service.RedisService;
@@ -60,6 +67,7 @@
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -134,6 +142,9 @@
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private XpSystemSettingClient systemSettingClient;
    private static final JsonFormat.Printer jsonPrinter = JsonFormat.printer()
            .printingEnumsAsInts()
@@ -1672,5 +1683,23 @@
        OrderPhase orderPhase = naviRequest.getOrderPhase();
        log.info("订单ID:{}", orderId);
        log.info("任务ID:{}", taskId);
        //获取系统异常订单超时配置,创建定时任务取消订单
        if(!orderId.contains("XU")){
            XpSystemSetting xpSystemSetting = systemSettingClient.getSystemSettingOne().getData();
            Map<String, ? extends Object> jobMaps =
                    new ImmutableMap.Builder<String, String>()
                            .put("id", orderId)
                            .put("orderType", orderId.contains("TEST") ? OrderType.TEST_ORDER : OrderType.USER_ORDER)
                            .build();
            QuartzManager.addJob(
                    OrderExceptionJob.class,
                    (OrderExceptionJob.name + orderId).toUpperCase(),
                    TimeJobType.ERROR_ORDER_CANCEL,
                    DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpSystemSetting.getOrderExceptionalTimeout())),
                    jobMaps
            );
        }
    }
}
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java
@@ -111,6 +111,11 @@
    public static final String QUEUE_POINT_ID = "QUEUE_POINT_ID";
    /**
     * 定向服务队列编号
     */
    public static final String SP_QUEUE_POINT_ID = "SP_QUEUE_POINT_ID";
    /**
     * 最大推单距离
     */
    public static final String MAX_PUSH_DISTANCE = "MAX_PUSH_DISTANCE";
xp-robotaxi-common/xp-common-redis/src/main/java/com/xiaopeng/common/redis/service/RedisService.java
@@ -438,6 +438,11 @@
        return key;
    }
    public String redisKey_SP_QUEUE_POINT_ID(Long xpPointId,Double pointLon,Double pointLat){
        String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPointId + "-" + pointLon + "," + pointLat;
        return key;
    }
    /**
     *
     * @param orderId 订单id
@@ -448,12 +453,10 @@
     * @param distance 距离 米
     * @param duration 时间
     * @param planRuleForQueue 选中路线对应的高德
     * @param targetedVal 是否定向 0 不定向 ,1-100 定向
     * @return
     */
    public String redisValue_QUEUE_POINT_ID(String orderId,String pointLon,String pointLat,String uid,String orderNumber ,String distance,String duration,String planRuleForQueue,Integer targetedVal){
        return orderId + "_" + pointLon + "," + pointLat + "_0" + "_" + uid + "_" + orderNumber + "_" + distance + "_" + duration + "_" + planRuleForQueue+"_" + targetedVal;
    public String redisValue_QUEUE_POINT_ID(String orderId,String pointLon,String pointLat,String uid,String orderNumber ,String distance,String duration,String planRuleForQueue){
        return orderId + "_" + pointLon + "," + pointLat + "_0" + "_" + uid + "_" + orderNumber + "_" + distance + "_" + duration + "_" + planRuleForQueue;
    }
}
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/mapper/XpTradingStrategyPushMapper.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.itinerary.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
public interface XpTradingStrategyPushMapper extends BaseMapper<XpTradingStrategyPush> {
}
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -64,6 +64,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
@@ -112,6 +113,9 @@
    @Resource
    private XpTradingStrategyMapper xpTradingStrategyMapper;
    @Resource
    private XpTradingStrategyPushMapper xpTradingStrategyPushMapper;
    @Resource
    private XpElectronicFenceAreaMapper xpElectronicFenceAreaMapper;
@@ -617,7 +621,6 @@
        if (!inTime) {
            throw new ServiceException("当前点位未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        // todo 需要判断用户是否白名单,且白名单当天最大订单量
        // 判断当天取消的次数 后台配置 redis 查询
        // 静默处理
@@ -636,15 +639,15 @@
//        }
        // 根据id获取手机号
        Boolean isPriorityDispatch = true;
//        R<XpAppUser> xpAppUserR = xpAppUserClient.queryOperationsUserById(Long.valueOf(uid));
//        if (xpAppUserR.getCode() == R.SUCCESS) {
//            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, xpAppUserR.getData().getPhoneNumber()).eq(XpWhitelist::getIsPriorityDispatch, 1));
//            if (count > 0) {
//                isPriorityDispatch = true;
//            }
//        }
        //判断是否在白名单且优先派单
        boolean isPriorityDispatch = false;
        UcUserInfo ucUserInfo = userResourcesClient.getBaseUserByUid(uid);
        if (null != ucUserInfo) {
            Long count = xpWhitelistMapper.selectCount(new LambdaQueryWrapper<XpWhitelist>().eq(XpWhitelist::getAccount, ucUserInfo.getMobile()).eq(XpWhitelist::getIsPriorityDispatch, 1));
            if (count > 0) {
                isPriorityDispatch = true;
            }
        }
        // 生成订单数据
        XpOrder xpOrder = new XpOrder();
@@ -752,77 +755,168 @@
        if (maxPushDistanceObj != null) {
            maxPushDistance = Double.valueOf(maxPushDistanceObj.toString());
        } else {
            maxPushDistance = xpTradingStrategyMapper.selectOne(null).getThreePushDistance();
            XpTradingStrategy xpTradingStrategy = xpTradingStrategyMapper.selectOne(null);
            List<XpTradingStrategyPush> xpTradingStrategyPushes = xpTradingStrategyPushMapper.selectList(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", xpTradingStrategy.getId()));
            long now = Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm")));
            XpTradingStrategyPush xpTradingStrategyPush = xpTradingStrategyPushes.stream().filter(item -> {
                long start = Long.parseLong(item.getStarTime().replace(":", ""));
                long end = Long.parseLong(item.getEndTime().replace(":", ""));
                return now >= start && now < end;
            }).findFirst().orElse(null);
            maxPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushDistance() : xpTradingStrategy.getFivePushDistance();
        }
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
        int targetedVal = 0;
        //获取定向服务配置
        R<List<XpTargetedServiceVehicleVo>> targetedServiceUserR = xpTargetedServiceClient.findListByUserIdAndCityCode(xpOrder.getAppUserId(), xpOrder.getCityCode());
        if(targetedServiceUserR.getCode() == R.SUCCESS && CollUtil.isNotEmpty(targetedServiceUserR.getData()) ){
            targetedVal = targetedServiceUserR.getData().get(0).getWeight();
            XpTargetedServiceVehicleVo xpTargetedServiceVehicleVo = targetedServiceUserR.getData().get(0);
            return addSpOrderPush(xpOrder, xpPoint, xpRoutePlan, maxPushDistance, xpTargetedServiceVehicleVo, orderId, currentTimeSlot, distance, duration, uid);
        }else{
            return addOrderPush(xpOrder, xpPoint, xpRoutePlan, maxPushDistance, isPriorityDispatch, orderId, currentTimeSlot, distance, duration, uid);
        }
        //String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        String redis_key = redisService.redisKey_QUEUE_POINT_ID(xpPoint.getId(), xpPoint.getPointLon(), xpPoint.getPointLat());
        //orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + planRuleForQueue+"_" + targetedVal;
        String redis_value = redisService.redisValue_QUEUE_POINT_ID(orderId.toString(), xpPoint.getPointLon().toString(), xpPoint.getPointLat().toString(), uid,
                xpOrder.getOrderNumber(), distance.toString(), duration.toString(), planRuleForQueue == null ? null : planRuleForQueue.toString(),targetedVal);
    }
    /**
     * 构建普通订单推送数据
     * @param xpOrder
     * @param xpPoint
     * @param xpRoutePlan
     * @param maxPushDistance
     * @param isPriorityDispatch
     * @param orderId
     * @param currentTimeSlot
     * @param distance
     * @param duration
     * @param uid
     * @return
     */
    private String addOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance,
                                Boolean isPriorityDispatch, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
        log.info("当前队列:{}", quoteMatchName);
        RedisQueuePointIdVo redisQueuePointIdVo = null;
        for (String s : quoteMatchName) {
//            QUEUE_POINT_ID-1-30.233,120.233
            String lonLat = s.split("-")[2];
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < maxPushDistance) {
//                String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + planRuleForQueue;
                if(targetedVal>0){ //todo yyy 这里添加数据需要优化 需要redis 加锁
                    List<String> cacheList = redisService.getCacheList(s);
                    cacheList.add(redis_value);
                    List<RedisQueuePointIdVo> ll = new ArrayList<>();
                    for (String string : cacheList) {
                        String[] split = string.split("_");
                        redisQueuePointIdVo = new RedisQueuePointIdVo();
                        redisQueuePointIdVo.setOrderId(split[0]);
                        redisQueuePointIdVo.setPointLon(split[1]);
                        redisQueuePointIdVo.setPointLat(split[2]);
                        redisQueuePointIdVo.setUid(split[3]);
                        redisQueuePointIdVo.setOrderNumber(split[4]);
                        redisQueuePointIdVo.setDistance(split[5]);
                        redisQueuePointIdVo.setDuration(split[6]);
                        redisQueuePointIdVo.setPlanRuleForQueue(split[7]);
                        if(split.length>8){
                            redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8]));
                        }else{
                            redisQueuePointIdVo.setTargetedVal(0);
                        }
                        ll.add(redisQueuePointIdVo);
                    }
                    ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal());
                    List<String> redis_values = new ArrayList<>();
                    for (RedisQueuePointIdVo vo : ll) {
                        String redis_value2 = redisService.redisValue_QUEUE_POINT_ID(vo.getOrderId(), vo.getPointLon(), vo.getPointLat(), vo.getUid(),
                                vo.getOrderNumber(), vo.getDistance(), vo.getDuration(), vo.getPlanRuleForQueue(),vo.getTargetedVal());
                        redis_values.add(redis_value2);
                    }
                    redisService.setCacheList(s, redis_values);
                }else{
                    if (isPriorityDispatch) {
                        // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                        redisService.addToHead(s, redis_value);
                        log.info("添加到队列头部:{} {}", s, redis_value);
                    } else {
                        // 尾部
                        redisService.addToTail(s, redis_value);
                        log.info("添加到队列尾部:{} {}", s, redis_value);
                    }
                String value = orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule();
                if (isPriorityDispatch) {
                    // 头部  value 订单_经纬度_状态_用户id_订单编号_距离_时间
                    redisService.addToHead(s, value);
                    log.info("添加到队列头部:{} {}", s, value);
                } else {
                    // 尾部
                    redisService.addToTail(s, value);
                    log.info("添加到队列尾部:{} {}", s, value);
                }
                xpOrder.setQueueName(s);
                xpOrderClient.updateOrder(xpOrder);
                // 存储mongodb 数据
                XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
                xpGeoQueryEntity.setOrderId(orderId.toString());
                xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
                // 计算2个时间的秒数
                xpGeoQueryEntity.setTime(currentTimeSlot);
                xpGeoQueryEntity.setStatus(0);
                xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                geoQueryEntityService.save(xpGeoQueryEntity);
                return orderId.toString();
            }
        }
        String key = CacheConstants.QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        if(xpRoutePlan==null){
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null));
        }else {
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule()));
        }
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
        // 存储mongodb 数据
        XpGeoQueryEntity xpGeoQueryEntity = new XpGeoQueryEntity();
        xpGeoQueryEntity.setOrderId(orderId.toString());
        xpGeoQueryEntity.setLocation(new GeoJsonPoint(xpPoint.getPointLon(), xpPoint.getPointLat()));
        // 计算2个时间的秒数
        xpGeoQueryEntity.setTime(currentTimeSlot);
        xpGeoQueryEntity.setStatus(0);
        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
        geoQueryEntityService.save(xpGeoQueryEntity);
        return orderId.toString();
    }
    /**
     * 构建定向服务订单推送数据
     * @param xpOrder
     * @param xpPoint
     * @param xpRoutePlan
     * @param maxPushDistance
     * @param xpTargetedServiceVehicleVo
     * @param orderId
     * @param currentTimeSlot
     * @param distance
     * @param duration
     * @param uid
     * @return
     */
    private String addSpOrderPush(XpOrder xpOrder, XpPoint xpPoint, XpRoutePlan xpRoutePlan, double maxPushDistance,
                                  XpTargetedServiceVehicleVo xpTargetedServiceVehicleVo, Long orderId, String currentTimeSlot, Integer distance, Integer duration, String uid){
        // 找出现在所有的队列 通过计算距离 算出目前应该放在那个队列  如果没有符合的新增一个队列  符合后看是否白名单账号 是则直接放在队列前端
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID);
        log.info("当前队列:{}", quoteMatchName);
        for (String s : quoteMatchName) {
//            QUEUE_POINT_ID-1-30.233,120.233
            String lonLat = s.split("-")[2];
            // 和上车点进行判断是否<maxPushDistance
            double v = FastDistanceCalculator.distanceFast(Double.parseDouble(lonLat.split(",")[1]), Double.parseDouble(lonLat.split(",")[0]), xpPoint.getPointLat(), xpPoint.getPointLon());
            if (v < maxPushDistance) {
                //在范围内,将队列中的数据转换成对象进行排序
                List<String> cacheList = redisService.getCacheList(s);
                List<RedisQueuePointIdVo> ll = new ArrayList<>();
                for (String string : cacheList) {
                    String[] split = string.split("_");
                    RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                    redisQueuePointIdVo.setOrderId(split[0]);
                    redisQueuePointIdVo.setPointLonLat(split[1]);
                    redisQueuePointIdVo.setPushStatus(split[2]);
                    redisQueuePointIdVo.setUid(split[3]);
                    redisQueuePointIdVo.setOrderNumber(split[4]);
                    redisQueuePointIdVo.setDistance(split[5]);
                    redisQueuePointIdVo.setDuration(split[6]);
                    redisQueuePointIdVo.setPlanRuleForQueue(split[7]);
                    redisQueuePointIdVo.setTargetedVal(Integer.valueOf(split[8]));
                    ll.add(redisQueuePointIdVo);
                }
                RedisQueuePointIdVo redisQueuePointIdVo = new RedisQueuePointIdVo();
                redisQueuePointIdVo.setOrderId(orderId.toString());
                redisQueuePointIdVo.setPointLonLat(xpPoint.getPointLon() + "," + xpPoint.getPointLat());
                redisQueuePointIdVo.setPushStatus("0");
                redisQueuePointIdVo.setUid(uid);
                redisQueuePointIdVo.setOrderNumber(xpOrder.getOrderNumber());
                redisQueuePointIdVo.setDistance(distance.toString());
                redisQueuePointIdVo.setDuration(duration.toString());
                redisQueuePointIdVo.setPlanRuleForQueue(xpRoutePlan.getRoutePlanRule().toString());
                redisQueuePointIdVo.setTargetedVal(xpTargetedServiceVehicleVo.getWeight());
                ll.add(redisQueuePointIdVo);
                //排序
                ll.sort((o1, o2) -> o2.getTargetedVal() - o1.getTargetedVal());
                List<String> collect = ll.stream().map(item -> {
                    String value = item.getOrderId() + "_" + item.getPointLonLat() + "_" + item.getPushStatus() + "_" + item.getUid() + "_" + item.getOrderNumber()
                            + "_" + item.getDistance() + "_" + item.getDuration() + "_" + item.getPlanRuleForQueue() + "_" + item.getTargetedVal();
                    return value;
                }).collect(Collectors.toList());
                redisService.setCacheList(s, cacheList);
                xpOrder.setQueueName(s);
                xpOrderClient.updateOrder(xpOrder);
@@ -836,12 +930,19 @@
                xpGeoQueryEntity.setStatus(0);
                xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
                geoQueryEntityService.save(xpGeoQueryEntity);
                return orderId.toString();
            }
        }
        redisService.setCacheList(redis_key, ListUtil.toList(redis_value) );
        log.info("订单推单:{}   {}", redis_key, redisService.getCacheList(redis_key));
        xpOrder.setQueueName(redis_key);
        String key = CacheConstants.SP_QUEUE_POINT_ID + "-" + xpPoint.getId() + "-" + xpPoint.getPointLon() + "," + xpPoint.getPointLat();
        if(xpRoutePlan==null){
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + null + "_" + xpTargetedServiceVehicleVo.getWeight()));
        }else {
            redisService.setCacheList(key, Arrays.asList(orderId + "_" + xpPoint.getPointLon() + "," + xpPoint.getPointLat() + "_0" + "_" + uid + "_" + xpOrder.getOrderNumber() + "_" + distance + "_" + duration + "_" + xpRoutePlan.getRoutePlanRule() + "_" + xpTargetedServiceVehicleVo.getWeight()));
        }
        log.info("订单推单:{}   {}", key, redisService.getCacheList(key));
        xpOrder.setQueueName(key);
        xpOrderClient.updateOrder(xpOrder);
@@ -854,9 +955,13 @@
        xpGeoQueryEntity.setStatus(0);
        xpGeoQueryEntity.setTimestamp(System.currentTimeMillis());
        geoQueryEntityService.save(xpGeoQueryEntity);
        return orderId.toString();
    }
    @Override
    public Boolean isInOperationTime(String operationStrategy) {
        JSONArray jsonArray = JSONArray.parseArray(operationStrategy);
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/vo/RedisQueuePointIdVo.java
@@ -8,10 +8,10 @@
    @ApiModelProperty(value = "订单id")
    private String orderId;
    @ApiModelProperty(value = "经度")
    private String pointLon;
    @ApiModelProperty(value = "纬度")
    private String pointLat;
    @ApiModelProperty(value = "经度维度")
    private String pointLonLat;
    @ApiModelProperty(value = "推送状态(0=还未推送,1=已推送)")
    private String pushStatus;
    @ApiModelProperty(value = "用户id")
    private String uid;
    @ApiModelProperty(value = "订单编码")
xp-robotaxi-itinerary-boot/src/main/resources/mapper/itinerary/XpTradingStrategyPushMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.itinerary.mapper.XpTradingStrategyPushMapper">
</mapper>
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleModelController.java
@@ -8,6 +8,8 @@
import com.xiaopeng.maintenance.model.query.XpVehicleModelPageQuery;
import com.xiaopeng.maintenance.service.IXpVehicleModelService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
@@ -138,8 +140,15 @@
    @GetMapping("/drainage/v1/vehicleModel/list")
    @ApiOperation(value = "查询可使用的车型列表", notes = "流量接入-基础信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<List<XpVehicleModel>> getVehicleModelList() {
        List<XpVehicleModel> list = xpVehicleModelService.queryList();
        return R.ok(list);
    }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpActicityController.java
@@ -161,7 +161,6 @@
            List<XpActicityStrategy> strategies = strategyService.lambdaQuery().eq(XpActicityStrategy::getActitcityId, dto.getId()).list();
            dto.setStrategy(strategies);
            dto.setActivityUser(userService.lambdaQuery().eq(XpActicityUser::getActitcityId, dto.getId()).list());
            dto.setNotice(noticeService.lambdaQuery().eq(XpActivityNotice::getActivityId, dto.getId()).one());
        }
        return R.ok(pageList);
    }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpOfficialPartnerController.java
New file
@@ -0,0 +1,50 @@
package com.xiaopeng.operation.controller;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.operation.service.IXpOfficialPartnerService;
import com.xiaopeng.operation.vo.OfficialPartnerVo;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
/**
 * 引流接口
 */
@RestController
@RequestMapping("/drainage")
public class XpOfficialPartnerController {
    @Resource
    private IXpOfficialPartnerService xpOfficialPartnerService;
    /**
     * 保存合作商信息
     * @param vo
     * @return
     */
    @PostMapping("/v1/officialPartner/save")
    @ApiOperation(value = "保存合作商信息", notes = "流量接入-基础信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<?> save(@RequestBody OfficialPartnerVo vo) {
        xpOfficialPartnerService.addOfficialPartner(vo);
        return R.ok();
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -20,10 +20,14 @@
import com.xiaopeng.operation.query.PricingPageListQuery;
import com.xiaopeng.operation.service.*;
import com.xiaopeng.operation.utils.ImageTagProcessor;
import com.xiaopeng.operation.vo.OfficialPartnerVo;
import com.xiaopeng.operation.vo.PricingInfoVo;
import com.xiaopeng.operation.vo.PricingPageListVO;
import com.xiaopeng.operation.vo.SaveOrderVo;
import com.xiaopeng.unifiedverification.interceptor.XpClientCheck;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
@@ -266,4 +270,18 @@
    }
//    /**
//     * 合作商添加计费策略 todo 现在的版本不支持手动选择车型
//     * @param vo
//     * @return
//     */
//    @PostMapping("/v1/pricing/save")
//    @ApiOperation(value = "保存计价规则", notes = "流量接入-基础信息")
//    @ApiImplicitParams({
//            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
//    })
//    public R<?> save(@RequestBody PricingInfoVo vo) {
//
//        return R.ok();
//    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTargetedServiceController.java
@@ -140,4 +140,6 @@
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpTradingStrategyController.java
@@ -42,8 +42,6 @@
    @ApiOperation(value = "获取交易策略配置", tags = {"inner-交易策略配置"})
    @GetMapping("/logan/inner/xpOperationStrategy/getOne")
    public R<XpTradingStrategyDetailVO> getOne() {
        // TODO[流量接入] 这里需要判断是哪个三方车队的,获取到对应的交易策略
        XpTradingStrategyDetailVO detail = tradingStrategyService.queryDetail();
        return R.ok(detail);
    }
@@ -58,15 +56,6 @@
    @PostMapping("/api/v1/tradingStrategy/edit")
    public R<?> edit(@Validated @RequestBody XpTradingStrategyEditDTO dto) {
        tradingStrategyService.editStrategy(dto);
        return R.ok();
    }
    @ApiOperation(value = "三方车队的交易策略", tags = {"流量接入-信息录入-设置交易策略"})
    @PostMapping("/api/v1/xp-rt/strategy")
    public R<?> add(@Validated @RequestBody XpTradingStrategy dto) {//创建只接收部分可设置的参数的dto
        // 通过key认证是哪个三方车队
        tradingStrategyService.save(dto);
        return R.ok();
    }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpTradingStrategyEditDTO.java
@@ -2,6 +2,7 @@
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.api.model.operation.XpTradingStrategyCity;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@@ -126,7 +127,8 @@
    @ApiModelProperty(value = "播单—乘客上车后x分钟内未点击出车,订单自动取消")
    private Integer  bdNotBoardedTime;
    @ApiModelProperty(value = "分时段推单列表")
    private List<XpTradingStrategyPush> pushTimeList;
    //---------------播单策略------------------------------------
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpOfficialPartnerMapper.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.operation.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpOfficialPartner;
public interface XpOfficialPartnerMapper extends BaseMapper<XpOfficialPartner> {
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/mapper/XpTradingStrategyPushMapper.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.operation.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
public interface XpTradingStrategyPushMapper extends BaseMapper<XpTradingStrategyPush> {
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpOfficialPartnerService.java
New file
@@ -0,0 +1,16 @@
package com.xiaopeng.operation.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpOfficialPartner;
import com.xiaopeng.operation.vo.OfficialPartnerVo;
import org.springframework.web.bind.annotation.RequestBody;
public interface IXpOfficialPartnerService extends IService<XpOfficialPartner> {
    /**
     * 添加合作商
     * @param vo
     */
    void addOfficialPartner(OfficialPartnerVo vo);
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/IXpTradingStrategyPushService.java
New file
@@ -0,0 +1,7 @@
package com.xiaopeng.operation.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
public interface IXpTradingStrategyPushService extends IService<XpTradingStrategyPush> {
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpTargetedServiceVehicleService.java
@@ -15,4 +15,11 @@
     */
    void deleteByTargetedServiceId(Long targetedServiceId);
    /**
     * 获取当前有效的所有定向服务车辆的VIN码
     * @return
     */
    List<String> getVehicleVinByTargetedService(String cityCode);
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityServiceImpl.java
@@ -5,18 +5,12 @@
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.operation.XpActivityDto;
import com.xiaopeng.api.feignClient.order.XpOrderClient;
import com.xiaopeng.api.model.operation.XpActicityStrategy;
import com.xiaopeng.api.model.operation.XpActicityUser;
import com.xiaopeng.api.model.operation.XpActivity;
import com.xiaopeng.api.model.operation.XpActivityNotice;
import com.xiaopeng.api.model.operation.*;
import com.xiaopeng.api.query.operation.XpActivityPageListQuery;
import com.xiaopeng.common.core.utils.bean.BeanUtils;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.operation.mapper.XpActicityMapper;
import com.xiaopeng.operation.service.IXpActicityService;
import com.xiaopeng.operation.service.IXpActicityStrategyService;
import com.xiaopeng.operation.service.IXpActicityUserService;
import com.xiaopeng.operation.service.IXpActivityNoticeService;
import com.xiaopeng.operation.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -49,6 +43,9 @@
    @Resource
    private XpOrderClient xpOrderClient;
    @Resource
    private IXpActicityCouponService xpActicityCouponService;
@@ -92,29 +89,43 @@
    }
    @Override
    @Transactional
    public void save(XpActivityDto dto) {
        XpActivity activity = new XpActivity();
        BeanUtils.copyBeanProp(activity, dto);
        activity.setActicityType(dto.getActivityType());
        activity.setAggregateLimit(dto.getEnableTotalLimit() ? 1 : 0);
        activity.setLimitation(dto.getTotalLimit());
        activity.setCoverImage(dto.getImg());
        activity.setRemarks(dto.getRichText());
        save(activity);
        List<XpActicityStrategy> strategy = dto.getStrategy();
        List<XpActicityUser> activityUser = dto.getActivityUser();
        XpActivityNotice notice = dto.getNotice();
        strategy.forEach(e -> e.setActitcityId(activity.getId().intValue()));
        strategyService.saveBatch(strategy);
        for (XpActicityStrategy xpActicityStrategy : strategy) {
            xpActicityStrategy.setActitcityId(activity.getId().intValue());
            xpActicityStrategy.setDeleted(false);
            strategyService.save(xpActicityStrategy);
            List<Long> couponIds = xpActicityStrategy.getCouponIds();
            for (Long couponId : couponIds) {
                XpActicityCoupon xpActicityCoupon = new XpActicityCoupon();
                xpActicityCoupon.setActicityStrategyId(xpActicityStrategy.getId().longValue());
                xpActicityCoupon.setCouponId(couponId);
                xpActicityCoupon.setActivityId(activity.getId());
                xpActicityCouponService.save(xpActicityCoupon);
            }
        }
        Map<String, XpActicityStrategy> strategyMap = strategy.stream().collect(Collectors.toMap(
                XpActicityStrategy::getName,
                Function.identity()
        ));
        activityUser.forEach(item -> {
            item.setActitcityId(activity.getId().intValue());
            item.setActitcityStrategeId(strategyMap.get(item.getStrategyName()).getId());
        });
        notice.setActivityId(activity.getId());
        userService.saveBatch(activityUser);
        activityNotice.save(notice);
        for (XpActicityUser xpActicityUser : activityUser) {
            xpActicityUser.setActitcityId(activity.getId().intValue());
            xpActicityUser.setActitcityStrategeId(strategyMap.get(xpActicityUser.getStrategyName()).getId());
            userService.save(xpActicityUser);
        }
    }
    @Override
@@ -122,6 +133,11 @@
        XpActivity byId = getById(id);
        XpActivityDto ret = new XpActivityDto();
        BeanUtils.copyBeanProp(ret, byId);
        ret.setActicityType(byId.getActicityType());
        ret.setEnableTotalLimit(byId.getAggregateLimit() == 1);
        ret.setTotalLimit(byId.getLimitation());
        ret.setImg(byId.getCoverImage());
        ret.setRichText(byId.getRemarks());
        ret.setStrategy(strategyService.listByActicityId(id));
        ret.setActivityUser(userService.listByActicityId(id));
        return ret;
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpActicityStrategyServiceImpl.java
@@ -1,13 +1,20 @@
package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpActicityCoupon;
import com.xiaopeng.api.model.operation.XpActicityStrategy;
import com.xiaopeng.api.model.operation.XpCoupon;
import com.xiaopeng.operation.mapper.XpActicityStrategyMapper;
import com.xiaopeng.operation.service.IXpActicityCouponService;
import com.xiaopeng.operation.service.IXpActicityStrategyService;
import com.xiaopeng.operation.service.IXpCouponService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
@@ -20,8 +27,23 @@
@Service
public class XpActicityStrategyServiceImpl extends ServiceImpl<XpActicityStrategyMapper, XpActicityStrategy> implements IXpActicityStrategyService {
    @Resource
    private IXpCouponService xpCouponService;
    @Resource
    private IXpActicityCouponService xpActicityCouponService;
    @Override
    public List<XpActicityStrategy> listByActicityId(Long id) {
        return baseMapper.selectList(new LambdaQueryWrapper<XpActicityStrategy>().eq(XpActicityStrategy::getActitcityId, id));
        List<XpActicityStrategy> xpActicityStrategies = baseMapper.selectList(new LambdaQueryWrapper<XpActicityStrategy>().eq(XpActicityStrategy::getActitcityId, id));
        for (XpActicityStrategy xpActicityStrategy : xpActicityStrategies) {
            List<XpActicityCoupon> list = xpActicityCouponService.list(new QueryWrapper<XpActicityCoupon>().eq("acticity_strategy_id", xpActicityStrategy.getId()));
            if(null != list && !list.isEmpty()){
                List<Long> couponIds = list.stream().map(XpActicityCoupon::getCouponId).collect(Collectors.toList());
                List<XpCoupon> xpCoupons = xpCouponService.list(new QueryWrapper<XpCoupon>().in("id", couponIds));
                xpActicityStrategy.setCouponList(xpCoupons);
            }
        }
        return xpActicityStrategies;
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpOfficialPartnerServiceImpl.java
New file
@@ -0,0 +1,35 @@
package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpOfficialPartner;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.operation.mapper.XpOfficialPartnerMapper;
import com.xiaopeng.operation.service.IXpOfficialPartnerService;
import com.xiaopeng.operation.vo.OfficialPartnerVo;
import org.springframework.stereotype.Service;
@Service
public class XpOfficialPartnerServiceImpl extends ServiceImpl<XpOfficialPartnerMapper, XpOfficialPartner> implements IXpOfficialPartnerService {
    /**
     * 添加合作商
     * @param vo
     */
    @Override
    public void addOfficialPartner(OfficialPartnerVo vo) {
        XpOfficialPartner officialPartner = this.getOne(new QueryWrapper<XpOfficialPartner>().eq("app_key", vo.getAppKey()).eq("is_deleted", 0));
        if(null == officialPartner){
            throw new ServiceException("权限校验失败");
        }
        if(!officialPartner.getAppSecret().equals(vo.getAppSecret())){
            throw new ServiceException("权限校验失败");
        }
        XpOfficialPartner xpOfficialPartner = new XpOfficialPartner();
        xpOfficialPartner.setName(vo.getName());
        xpOfficialPartner.setBrandName(vo.getBrandName());
        xpOfficialPartner.setLogoUrl(vo.getLogoUrl());
        this.updateById(xpOfficialPartner);
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpPointServiceImpl.java
@@ -5,6 +5,7 @@
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.operation.PointMapQuery;
import com.xiaopeng.api.dto.order.HistoryEndPointsDto;
@@ -29,6 +30,7 @@
import com.xiaopeng.operation.query.PointByNameQuery;
import com.xiaopeng.operation.service.IXpElectronicFenceAreaService;
import com.xiaopeng.operation.service.IXpElectronicFenceService;
import com.xiaopeng.operation.service.IXpTradingStrategyService;
import com.xiaopeng.operation.service.XpPointService;
import com.xiaopeng.operation.utils.TimeRangeChecker;
import com.xiaopeng.operation.utils.holiday.HolidayUtil;
@@ -83,6 +85,9 @@
    @Resource
    private AliOssService aliOssService;
    @Resource
    private IXpTradingStrategyService xpTradingStrategyService;
    /**
     * 如果站点是挂在场站下的  需要返回一个场站id   stationId
@@ -728,6 +733,13 @@
    @Override
    public OrderDistanceVo getOrderDistance() {
        OrderDistanceVo orderDistanceVo = new OrderDistanceVo();
        XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null);
        if(null != xpTradingStrategy){
            orderDistanceVo.setQueuePollingTime(xpTradingStrategy.getQueuePollingTime());
            orderDistanceVo.setWalkingNavigationDistance(xpTradingStrategy.getWalkingNavigationDistance());
            orderDistanceVo.setMaxStandingTiming(xpTradingStrategy.getMaxStandingTiming());
        }
        XpSystemSetting xpSystemSetting = xpSystemSettingMapper.selectOne(null);
        if (xpSystemSetting != null) {
            orderDistanceVo.setMaxDistance(xpSystemSetting.getOrderDistance());
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTargetedServiceVehicleServiceImpl.java
@@ -1,13 +1,16 @@
package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.operation.XpTargetedService;
import com.xiaopeng.api.model.operation.XpTargetedServiceVehicle;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.operation.mapper.XpTargetedServiceMapper;
import com.xiaopeng.operation.mapper.XpTargetedServiceVehicleMapper;
import com.xiaopeng.operation.service.XpTargetedServiceService;
import com.xiaopeng.operation.service.XpTargetedServiceVehicleService;
import org.springframework.stereotype.Service;
@@ -21,6 +24,12 @@
@Service
public class XpTargetedServiceVehicleServiceImpl  extends ServiceImpl<XpTargetedServiceVehicleMapper, XpTargetedServiceVehicle> implements XpTargetedServiceVehicleService {
    @Resource
    private XpVehicleClient xpVehicleClient;
    @Resource
    private XpTargetedServiceService xpTargetedServiceService;
    
    @Override
@@ -32,7 +41,23 @@
        wrapper.eq(XpTargetedServiceVehicle::getTargetedServiceId, targetedServiceId);
        this.remove(wrapper);
    }
    @Override
    public List<String> getVehicleVinByTargetedService(String cityCode) {
        List<XpTargetedService> targetedServices = xpTargetedServiceService.list(new QueryWrapper<XpTargetedService>().eq("status", 1)
                .eq("city_code", cityCode).last(" and (is_long_valid = 1 or now() between start_time and end_time)"));
        List<Long> collect = targetedServices.stream().map(XpTargetedService::getId).collect(Collectors.toList());
        if(collect.isEmpty()){
            return Collections.emptyList();
        }
        List<XpTargetedServiceVehicle> list = this.list(new QueryWrapper<XpTargetedServiceVehicle>().in("targeted_service_id", collect));
        List<String> vinList = list.stream().map(item -> {
            XpVehicle xpVehicle = xpVehicleClient.queryById(item.getVehicleId()).getData();
            return xpVehicle.getVehicleVin();
        }).collect(Collectors.toList());
        return vinList;
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyPushServiceImpl.java
New file
@@ -0,0 +1,12 @@
package com.xiaopeng.operation.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
import com.xiaopeng.operation.mapper.XpTradingStrategyPushMapper;
import com.xiaopeng.operation.service.IXpTradingStrategyPushService;
import org.springframework.stereotype.Service;
@Service
public class XpTradingStrategyPushServiceImpl extends ServiceImpl<XpTradingStrategyPushMapper, XpTradingStrategyPush> implements IXpTradingStrategyPushService {
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpTradingStrategyServiceImpl.java
@@ -2,13 +2,16 @@
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpTradingStrategy;
import com.xiaopeng.api.model.operation.XpTradingStrategyCity;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.operation.dto.XpTradingStrategyEditDTO;
import com.xiaopeng.operation.mapper.XpTradingStrategyMapper;
import com.xiaopeng.operation.service.IXpTradingStrategyCityService;
import com.xiaopeng.operation.service.IXpTradingStrategyPushService;
import com.xiaopeng.operation.service.IXpTradingStrategyService;
import com.xiaopeng.api.vo.operation.XpTradingStrategyDetailVO;
import lombok.RequiredArgsConstructor;
@@ -18,6 +21,7 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
@@ -34,6 +38,9 @@
public class XpTradingStrategyServiceImpl extends ServiceImpl<XpTradingStrategyMapper, XpTradingStrategy> implements IXpTradingStrategyService {
    private final IXpTradingStrategyCityService tradingStrategyCityService;
    @Resource
    private IXpTradingStrategyPushService xpTradingStrategyPushService;
    @Override
    public XpTradingStrategyDetailVO queryDetail() {
@@ -55,7 +62,8 @@
        // 3. 组装 VO
        XpTradingStrategyDetailVO vo = BeanUtil.copyProperties(strategy, XpTradingStrategyDetailVO.class);
        vo.setCityList(cityList);
        List<XpTradingStrategyPush> tradingStrategyId = xpTradingStrategyPushService.list(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", strategy.getId()).orderByAsc("start_time"));
        vo.setTimePushStrategyList(tradingStrategyId);
        return vo;
    }
@@ -73,6 +81,14 @@
        XpTradingStrategy updateStrategy = BeanUtil.copyProperties(dto, XpTradingStrategy.class);
        this.updateById(updateStrategy);
        //更新分时段推单策略
        xpTradingStrategyPushService.remove(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", dto.getId()));
        List<XpTradingStrategyPush> pushTimeList = dto.getPushTimeList();
        for (XpTradingStrategyPush xpTradingStrategyPush : pushTimeList) {
            xpTradingStrategyPush.setTradingStrategyId(dto.getId());
            xpTradingStrategyPushService.save(xpTradingStrategyPush);
        }
        // 3. 删除旧的城市关联
        tradingStrategyCityService.remove(
                new LambdaQueryWrapper<XpTradingStrategyCity>()
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/TaskOrderUtil.java
@@ -4,6 +4,7 @@
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.dto.map.RouteAndFareDto;
import com.xiaopeng.api.dto.operation.LonLatDto;
@@ -18,7 +19,9 @@
import com.xiaopeng.api.feignClient.pushMessage.XpPushMessageClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.operation.XpElectronicFence;
import com.xiaopeng.api.model.operation.XpTargetedServiceVehicle;
import com.xiaopeng.api.model.operation.XpTradingStrategy;
import com.xiaopeng.api.model.operation.XpTradingStrategyPush;
import com.xiaopeng.api.model.order.XpCruiseOrder;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.order.XpOrderReassign;
@@ -54,6 +57,7 @@
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@@ -63,10 +67,12 @@
@Slf4j
@Component
public class TaskOrderUtil {
    @Resource
    private XpTargetedServiceService xpTargetedServiceService;
    @Resource
    XpTargetedServiceService xpTargetedServiceService;
    private XpTargetedServiceVehicleService xpTargetedServiceVehicleService;
    @Resource
    private RedisService redisService;
@@ -84,6 +90,9 @@
    @Resource
    private IXpTradingStrategyService xpTradingStrategyService;
    @Resource
    private IXpTradingStrategyPushService xpTradingStrategyPushService;
    @Resource
    private XpCruiseOrderClient xpCruiseOrderClient;
@@ -138,25 +147,19 @@
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void taskOrder() {
//        System.out.println("5秒执行一次");
        System.out.println("5秒执行一次");
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
        for (String name : quoteMatchName) {
            String firstElement = redisService.getFirstElement(name);
            if (firstElement != null) {
                String[] split = firstElement.split("_");
                if(split.length>8){
                    String targetedVal = split[8];
                    if (!"0".equals(targetedVal)) {
                        continue;
                    }
                }
                String[] split = firstElement.toString().split("_");
                // 如果未处理 创建新任务
                if ("0".equals(split[2])) {
                if (split[2].equals("0")) {
                    String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7];
                    // 状态改为处理中
                    redisService.updateFirst(name, value);
                    threadPoolTaskExecutor.submit(() -> {
                        orderProcess(name, firstElement);
                        orderProcess(name, firstElement.toString(), false);
                    });
                }
            }
@@ -168,25 +171,20 @@
     */
    @Scheduled(cron = "0/5 * * * * ?")
    public void taskOrder_targeted() {
//        System.out.println("5秒执行一次");
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.QUEUE_POINT_ID);
        System.out.println("5秒执行一次");
        Set<String> quoteMatchName = redisService.getQuoteMatchName(CacheConstants.SP_QUEUE_POINT_ID);
        for (String name : quoteMatchName) {
            String firstElement = redisService.getFirstElement(name);
            if (firstElement != null) {
                String[] split = firstElement.split("_");
                if(split.length>8){
                    String targetedVal = split[8];
                    if (!"0".equals(targetedVal)) {
                        // 如果未处理 创建新任务
                        if ("0".equals(split[2])) {
                            String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7];
                            // 状态改为处理中
                            redisService.updateFirst(name, value);
                            threadPoolTaskExecutor.submit(() -> {
                                orderProcess(name, firstElement);
                            });
                        }
                    }
                String[] split = firstElement.toString().split("_");
                // 如果未处理 创建新任务
                if (split[2].equals("0")) {
                    String value = split[0] + "_" + split[1] + "_1" + "_" + split[3] + "_" + split[4] + "_" + split[5] + "_" + split[6] + "_" + split[7];
                    // 状态改为处理中
                    redisService.updateFirst(name, value);
                    threadPoolTaskExecutor.submit(() -> {
                        orderProcess(name, firstElement.toString(), true);
                    });
                }
            }
        }
@@ -198,7 +196,7 @@
     * @param quoteName 队列名称
     * @param firstElement 队列第一个元素
     */
    private void orderProcess(String quoteName, String firstElement) {
    private void orderProcess(String quoteName, String firstElement, Boolean isTargetedService) {
        XpTradingStrategy xpTradingStrategy = xpTradingStrategyService.getOne(null);
        String orderId = firstElement.split("_")[0];
        String lonLat = firstElement.split("_")[1];
@@ -214,58 +212,68 @@
        // 经纬度
        String[] split = lonLat.split(",");
        //查询当前时段是不是特殊推单时段
        List<XpTradingStrategyPush> tradingStrategyId = xpTradingStrategyPushService.list(new QueryWrapper<XpTradingStrategyPush>().eq("trading_strategy_id", xpTradingStrategy));
        long now = Long.parseLong(LocalDateTime.now().format(DateTimeFormatter.ofPattern("HHmm")));
        XpTradingStrategyPush xpTradingStrategyPush = tradingStrategyId.stream().filter(item -> {
            long start = Long.parseLong(item.getStarTime().replace(":", ""));
            long end = Long.parseLong(item.getEndTime().replace(":", ""));
            return now >= start && now < end;
        }).findFirst().orElse(null);
        // 5轮找车辆
        //每次查找车辆推单后的等待秒数
        int sleepTime = 3;
        Integer onePushTime = xpTradingStrategy.getOnePushTime();
        Double onePushDistance = xpTradingStrategy.getOnePushDistance();
        Integer onePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushTime() : xpTradingStrategy.getOnePushTime();
        Double onePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getOnePushDistance() : xpTradingStrategy.getOnePushDistance();
        int count = onePushTime / sleepTime;
        // 第一轮推单
        log.info("开始第一轮推单 {}", orderNo);
        Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule);
        Boolean processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, onePushDistance, distance, duration, planRule, isTargetedService);
        if(processed){
            log.info("订单推送成功 {}", orderNo);
            return;
        }
        // 第二轮推单
        Integer twoPushTime = xpTradingStrategy.getTwoPushTime();
        Double twoPushDistance = xpTradingStrategy.getTwoPushDistance();
        Integer twoPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushTime() : xpTradingStrategy.getTwoPushTime();
        Double twoPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getTwoPushDistance() : xpTradingStrategy.getTwoPushDistance();
        count = twoPushTime / sleepTime;
        log.info("开始第二轮推单 {}", orderNo);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, twoPushDistance, distance, duration, planRule, isTargetedService);
        if(processed){
            log.info("订单推送成功 {}", orderNo);
            return;
        }
        // 第三轮推单
        Integer threePushTime = xpTradingStrategy.getThreePushTime();
        Double threePushDistance = xpTradingStrategy.getThreePushDistance();
        Integer threePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushTime() : xpTradingStrategy.getThreePushTime();
        Double threePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getThreePushDistance() : xpTradingStrategy.getThreePushDistance();
        count = threePushTime / sleepTime;
        log.info("开始第三轮推单 {}", orderNo);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, threePushDistance, distance, duration, planRule, isTargetedService);
        if(processed){
            log.info("订单推送成功 {}", orderNo);
            return;
        }
        // 第四轮推单
        Integer fourPushTime = xpTradingStrategy.getFourPushTime();
        Double fourPushDistance = xpTradingStrategy.getFourPushDistance();
        Integer fourPushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushTime() : xpTradingStrategy.getFourPushTime();
        Double fourPushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFourPushDistance() : xpTradingStrategy.getFourPushDistance();
        count = fourPushTime / sleepTime;
        log.info("开始第四轮推单 {}", orderNo);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fourPushDistance, distance, duration, planRule, isTargetedService);
        if(processed){
            log.info("订单推送成功 {}", orderNo);
            return;
        }
        // 第五轮推单
        Integer fivePushTime = xpTradingStrategy.getFivePushTime();
        Double fivePushDistance = xpTradingStrategy.getFivePushDistance();
        Integer fivePushTime = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushTime() : xpTradingStrategy.getFivePushTime();
        Double fivePushDistance = null != xpTradingStrategyPush ? xpTradingStrategyPush.getFivePushDistance() : xpTradingStrategy.getFivePushDistance();
        count = fivePushTime / sleepTime;
        log.info("开始第五轮推单 {}", orderNo);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule);
        processed = processPushOrder(quoteName, count, sleepTime, uid, split, orderNo, xpTradingStrategy, fivePushDistance, distance, duration, planRule, isTargetedService);
        if(processed){
            log.info("订单推送成功 {}", orderNo);
            return;
@@ -320,7 +328,863 @@
     * @param xpTradingStrategy  规则
     */
    @SneakyThrows
    private Boolean processPushOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule) {
    private Boolean processPushOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule, Boolean isTargetedService) {
        log.info("进入推单环节 单号 {}", orderNo);
        if (count == 0) {
            count = 1;
        }
        // 订单状态
        R<XpOrder> xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo);
        if (xpOrderR.getCode() != 200) {
            return false;
        }
        if (xpOrderR.getData().getStatus() != 1) {
            return true;
        }
        XpOrder xpOrder = xpOrderR.getData();
        if (xpOrder.getStatus() == 0) {
            redisService.removeByPattern(quoteName, xpOrder.getOrderNumber());
        }
        // 找出围栏id
        Long xpElectronicFenceAreaId = xpOrder.getXpElectronicFenceAreaId();
        Long electronicId = xpElectronicFenceAreaService.getById(xpElectronicFenceAreaId).getElectronicId();
        XpElectronicFence xpElectronicFence = xpElectronicFenceMapper.selectById(electronicId);
        // ===== 新增:UID-VIN 优先匹配(仅 enabled=true 时生效)=====
        log.info("[人车订单绑定测试] >>>>>> 进入优先匹配判断, uid={}, orderNo={}, 围栏区域ID={}", uid, orderNo, xpElectronicFenceAreaId);
        if (uidVinBindingConfig.isEnabled()) {
            log.info("[人车订单绑定测试] 总开关已开启, 开始执行优先匹配逻辑, uid={}, orderNo={}", uid, orderNo);
            try {
                PriorityMatchResult priorityResult = uidVinPriorityMatcher.tryPriorityMatch(uid, orderNo, String.valueOf(xpElectronicFenceAreaId));
                log.info("[人车订单绑定测试] 优先匹配结果: matched={}, vin={}, failReason={}, uid={}, orderNo={}",
                        priorityResult != null ? priorityResult.isMatched() : "null",
                        priorityResult != null ? priorityResult.getVin() : "null",
                        priorityResult != null ? priorityResult.getFailReason() : "null",
                        uid, orderNo);
                if (priorityResult != null && priorityResult.isMatched()) {
                    String priorityVin = priorityResult.getVin();
                    log.info("[人车订单绑定测试] 匹配成功, 准备获取分布式锁, lockKey=FIND_CAR_{}, orderNo={}", priorityVin, orderNo);
                    RLock priorityLock = redissonClient.getLock("FIND_CAR_" + priorityVin);
                    priorityLock.lock(10, TimeUnit.SECONDS);
                    log.info("[人车订单绑定测试] 分布式锁获取成功, vin={}, orderNo={}", priorityVin, orderNo);
                    try {
                        // 二次校验车辆状态
                        log.info("[人车订单绑定测试] 开始二次校验车辆状态, vin={}, orderNo={}", priorityVin, orderNo);
                        R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(priorityVin);
                        log.info("[人车订单绑定测试] 二次校验-车辆查询结果: code={}, hasData={}, vin={}", vehicleR.getCode(), vehicleR.getData() != null, priorityVin);
                        if (vehicleR.getCode() == 200 && vehicleR.getData() != null) {
                            XpVehicle vehicle = vehicleR.getData();
                            //判断当前车辆是否在禁派单车辆内
                            String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId());
                            List<String> strings = new ArrayList<>();
                            if(null != cacheList){
                                strings = JSON.parseArray(cacheList, String.class);
                            }
                            log.info("[人车订单绑定测试] 二次校验-车辆状态: operatingStatus={}, state={}, vehicleType={}, vin={}",
                                    vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType(), priorityVin);
                            if (vehicle.getOperatingStatus() == 1 && vehicle.getState() == 0 && vehicle.getVehicleType() != 1 && !strings.contains(vehicle.getVehicleVin())) {
                                log.info("[人车订单绑定测试] 二次校验-车辆状态通过(空闲), 开始校验订单状态, orderNo={}", orderNo);
                                // 二次校验订单状态
                                R<XpOrder> orderCheck = xpOrderClient.queryOrderByOrderNo(orderNo);
                                log.info("[人车订单绑定测试] 二次校验-订单查询结果: code={}, status={}, orderNo={}",
                                        orderCheck.getCode(),
                                        orderCheck.getData() != null ? orderCheck.getData().getStatus() : "null",
                                        orderNo);
                                if (orderCheck.getCode() == 200 && orderCheck.getData() != null && orderCheck.getData().getStatus() == 1) {
                                    log.info("[人车订单绑定测试] 二次校验全部通过, 开始关闭巡游单, vin={}, orderNo={}", priorityVin, orderNo);
                                    // 关闭巡游单
                                    R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(priorityVin);
                                    log.info("[人车订单绑定测试] 关闭巡游单结果: code={}, vin={}, orderNo={}",
                                            stringR != null ? stringR.getCode() : "null", priorityVin, orderNo);
                                    if (stringR != null && stringR.getCode() == 200) {
                                        log.info("[人车订单绑定测试] 关闭巡游单成功, 开始下发XPU命令, vin={}, orderNo={}", priorityVin, orderNo);
                                        // 下发XPU命令
                                        PushOrderDto pushOrderDto = new PushOrderDto();
                                        pushOrderDto.setVin(priorityVin);
                                        pushOrderDto.setOrderId(orderCheck.getData().getId().toString());
                                        pushOrderDto.setStartLatitude(orderCheck.getData().getStartLat());
                                        pushOrderDto.setStartLongitude(orderCheck.getData().getStartLon());
                                        pushOrderDto.setEndLatitude(orderCheck.getData().getEndLat());
                                        pushOrderDto.setEndLongitude(orderCheck.getData().getEndLon());
                                        pushOrderDto.setEndPoiName(orderCheck.getData().getEndPointName());
                                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                                        pushOrderDto.setStage(1);
                                        log.info("[人车订单绑定测试] XPU推单参数: vin={}, orderId={}, startLat={}, startLon={}, endLat={}, endLon={}, orderNo={}",
                                                priorityVin, orderCheck.getData().getId(), orderCheck.getData().getStartLat(), orderCheck.getData().getStartLon(),
                                                orderCheck.getData().getEndLat(), orderCheck.getData().getEndLon(), orderNo);
                                        orderMissionClient.pushOrder(pushOrderDto);
                                        log.info("[人车订单绑定测试] ====== 派单成功! uid={}, vin={}, orderNo={}, 从队列移除订单 ======", uid, priorityVin, orderNo);
                                        redisService.removeByPattern(quoteName, orderNo);
                                        return true;
                                    } else {
                                        log.info("[人车订单绑定测试] 关闭巡游单失败, 回退常规流程, vin={}, orderNo={}", priorityVin, orderNo);
                                    }
                                } else {
                                    log.info("[人车订单绑定测试] 二次校验-订单状态不满足(非待派单), 回退常规流程, orderNo={}", orderNo);
                                }
                            } else {
                                if (vehicle.getState() != 0) {
                                    log.info("[人车订单绑定测试] 二次校验-车辆已接单(state={}), 当前有未完成订单, 无法指派, vin={}, plateNumber={}, orderNo={}",
                                            vehicle.getState(), priorityVin, vehicle.getPlateNumber(), orderNo);
                                } else {
                                    log.info("[人车订单绑定测试] 二次校验-车辆状态不满足, 回退常规流程, vin={}, operatingStatus={}, state={}, vehicleType={}",
                                            priorityVin, vehicle.getOperatingStatus(), vehicle.getState(), vehicle.getVehicleType());
                                }
                            }
                        } else {
                            log.info("[人车订单绑定测试] 二次校验-车辆查询失败, 回退常规流程, vin={}, code={}", priorityVin, vehicleR.getCode());
                        }
                    } catch (Exception e) {
                        log.error("[人车订单绑定测试] 锁内执行异常,回退常规流程, uid={}, vin={}, orderNo={}", uid, priorityVin, orderNo, e);
                    } finally {
                        priorityLock.unlock();
                        log.info("[人车订单绑定测试] 分布式锁已释放, vin={}, orderNo={}", priorityVin, orderNo);
                    }
                } else {
                    log.info("[人车订单绑定测试] 优先匹配未命中, 进入常规流程, uid={}, orderNo={}", uid, orderNo);
                }
            } catch (Exception e) {
                log.error("[人车订单绑定测试] 优先匹配过程异常,回退常规流程, uid={}, orderNo={}", uid, orderNo, e);
            }
        } else {
            log.info("[人车订单绑定测试] 总开关未开启(enabled=false), 跳过优先匹配, uid={}, orderNo={}", uid, orderNo);
        }
        // ===== 新增结束 =====
        for (int i = 0; i < count; i++) {
            //等到sleepTime秒钟
            Thread.sleep(sleepTime * 1000);
            // 根据距离找车
            // 车多则根据配置找具体车数量 根据距离最近
            // 更改 暂不限制数量
            List<VehiclePosition> positionList = vehiclePositionService.findAvailableVehiclesNearby(Double.parseDouble(split[0]), Double.parseDouble(split[1]), pushDistance, xpTradingStrategy.getSimultaneouslyOrderCount());
            log.info("根据距离找车 {} 距离 {}KM  经度 {} 维度 {} 查找结果 {} 单号 {}", orderNo, pushDistance, split[0], split[1], JSON.toJSONString(positionList), orderNo);
            // 获取车辆的区域信息
            if (positionList.isEmpty()) {
                continue;
            }
            Set<String> vinList = positionList.stream().map(VehiclePosition::getVin).collect(Collectors.toSet());
            //判断当前车辆是否在禁派单车辆内
            String cacheList = redisService.getCacheObject("CAN_NOT_RECEIVE_ORDER_VEHICLE:" + xpOrder.getId());
            if(Objects.nonNull(cacheList)){
                List<String> strings = JSON.parseArray(cacheList, String.class);
                Set<String> vins = new HashSet<>();
                for (String s : vinList) {
                    if (!strings.contains(s)) {
                        vins.add(s);
                    }
                }
                vinList = vins;
            }
            // 获取车辆的信息 筛选出可用车辆,定向服务的车辆排除
            R<List<String>> vehiclePositionVos = xpVehicleClient.queryVehiclePositionByVin(new VehiclePositionByVinDto(xpElectronicFence.getId(), vinList, xpTradingStrategy.getSimultaneouslyOrderCount()));
            log.info("筛选可用车辆结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
            List<String> vehicleVinByTargetedService = xpTargetedServiceVehicleService.getVehicleVinByTargetedService(xpOrderR.getData().getCityCode());
            if(!isTargetedService){
                vehiclePositionVos.getData().removeAll(vehicleVinByTargetedService);
                log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
            }else{
                vehicleVinByTargetedService.removeAll(vehiclePositionVos.getData());
                vehiclePositionVos.setData(vehicleVinByTargetedService);
                log.info("筛选调定向服务车辆后的结果 {} 单号 {}", JSON.toJSONString(vehiclePositionVos), orderNo);
            }
            if (vehiclePositionVos.getCode() != 200) {
                continue;
            }
            List<VehiclePositionVo> availableVehiclesNearby = BeanUtil.copyToList(positionList, VehiclePositionVo.class);
            List<String> data = vehiclePositionVos.getData();
            // 找出符合条件的
            availableVehiclesNearby = availableVehiclesNearby.stream().filter(e -> data.contains(e.getVin())).collect(Collectors.toList());
            if (!availableVehiclesNearby.isEmpty()) {
                if (availableVehiclesNearby.size() > 1) {
                    log.info("附近有 {} 辆车,进入权重判断流程 单号 {}", availableVehiclesNearby.size(), orderNo);
                    // 走权重
                    // 订单价值
                    Integer tendencyOrderValue = xpTradingStrategy.getTendencyOrderValue();
                    // 距离价值
                    Integer tendencyDistance = xpTradingStrategy.getTendencyDistance();
                    // 时间价值
                    Integer tendencyTime = xpTradingStrategy.getTendencyTime();
                    try {
                        // 电量价值
                        Integer tendencyElectricity = xpTradingStrategy.getTendencyElectricity();
                        // 找出最大的值是那个
                        Integer max = Math.max(tendencyOrderValue, Math.max(tendencyDistance, Math.max(tendencyTime, tendencyElectricity)));
                        if (max.equals(tendencyOrderValue)) {
                            // 订单价值
                            // 时间差权重
                            Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference();
                            // 距离差权重
                            Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference();
                            // 距离权重
                            Integer weightDistance = xpTradingStrategy.getWeightDistance();
                            // 时间权重
                            Integer weightTime = xpTradingStrategy.getWeightTime();
                            // 电量权重
                            Integer weightElectricity = xpTradingStrategy.getWeightElectricity();
                            // 找出最大的值是那个
                            Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity))));
                            //  时间差
                            if (max1.equals(weightTimeDifference)) {
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                    LonLatDto lonLatDto = new LonLatDto();
                                    lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                    lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                    routeAndFareDto.setOrigin(lonLatDto);
                                    LonLatDto lonLatDto1 = new LonLatDto();
                                    lonLatDto1.setLongitude(Double.valueOf(split[0]));
                                    lonLatDto1.setLatitude(Double.valueOf(split[1]));
                                    routeAndFareDto.setDestination(lonLatDto1);
                                    if(planRule!=null&& !"null".equals(planRule)){
                                        routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                    }
                                    R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                    if (distanceAndDuration.getCode() == 200) {
                                        // 送驾- 接驾
                                        Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration();
                                        vehiclePosition.setTimeDifference(durationDifference);
                                    }
                                }
                            }
                            // 距离差
                            if (max1.equals(weightDistanceDifference)) {
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                    LonLatDto lonLatDto = new LonLatDto();
                                    lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                    lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                    routeAndFareDto.setOrigin(lonLatDto);
                                    LonLatDto lonLatDto1 = new LonLatDto();
                                    lonLatDto1.setLongitude(Double.valueOf(split[0]));
                                    lonLatDto1.setLatitude(Double.valueOf(split[1]));
                                    routeAndFareDto.setDestination(lonLatDto1);
                                    if(planRule!=null&& !"null".equals(planRule)){
                                        routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                    }
                                    R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                    if (distanceAndDuration.getCode() == 200) {
                                        // 送驾- 接驾
                                        Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance();
                                        vehiclePosition.setDistanceDifference(distanceDifference);
                                    }
                                }
                            }
                            if (max1.equals(weightDistance)) {
                                log.info("车子距离~~");
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                    LonLatDto lonLatDto = new LonLatDto();
                                    lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                    lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                    routeAndFareDto.setOrigin(lonLatDto);
                                    LonLatDto lonLatDto1 = new LonLatDto();
                                    lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                    lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                    if(planRule!=null&& !"null".equals(planRule)){
                                        routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                    }
                                    routeAndFareDto.setDestination(lonLatDto1);
                                    //  调用地图 获取时间
                                    R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                    if (r.getCode() == 200) {
                                        log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo);
                                        vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance()));
                                    } else {
                                        vehiclePosition.setDistance(0.0);
                                    }
                                }
                                // 分数计算 把时间短的分数调高
                                availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList());
                                double score = 10;
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    vehiclePosition.setDistance(score);
                                    score--;
                                }
                            }
                            if (max1.equals(weightTime)) {
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                    LonLatDto lonLatDto = new LonLatDto();
                                    lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                    lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                    routeAndFareDto.setOrigin(lonLatDto);
                                    LonLatDto lonLatDto1 = new LonLatDto();
                                    lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                    lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                    if(planRule!=null&& !"null".equals(planRule)){
                                        routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                    }
                                    routeAndFareDto.setDestination(lonLatDto1);
                                    //  调用地图 获取时间
                                    R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                    if (r.getCode() == 200) {
                                        vehiclePosition.setSecond(r.getData().getDuration());
                                    } else {
                                        vehiclePosition.setSecond(0);
                                    }
                                }
                                // 分数计算 把时间短的分数调高
                                availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList());
                                int score = 10;
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    vehiclePosition.setSecond(score);
                                    score--;
                                }
                            }
                            if (max1.equals(weightElectricity)) {
                                // 计算车的分数  分数最大是车的size
                                availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList());
                                int size = tendencyElectricity;
                                // 做比对的分数
                                int temp = availableVehiclesNearby.get(0).getCurrentElectricity();
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size);
                                    if (temp != vehiclePosition.getCurrentElectricity()) {
                                        size--;
                                    }
                                }
                            }
                            // 算出总分 再来排序计算
                            for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) {
                                vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue());
                            }
                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList());
                            int size = tendencyOrderValue;
                            // 做比对的分数
                            double temp = availableVehiclesNearby.get(0).getOrderValueTotal();
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size);
                                if (temp != vehiclePosition.getOrderValueTotal()) {
                                    size--;
                                }
                            }
                        }
                        // 距离分数
                        if (max.equals(tendencyDistance)) {
                            log.info("车子距离~~");
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                LonLatDto lonLatDto = new LonLatDto();
                                lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                routeAndFareDto.setOrigin(lonLatDto);
                                LonLatDto lonLatDto1 = new LonLatDto();
                                lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                if(planRule!=null&& !"null".equals(planRule)){
                                    routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                }
                                routeAndFareDto.setDestination(lonLatDto1);
                                //  调用地图 获取时间
                                R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                if (r.getCode() == 200) {
                                    log.info("车子距离~~{},{},{}",vehiclePosition.getVin(),r.getData().getDistance(),orderNo);
                                    vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance()));
                                } else {
                                    vehiclePosition.setDistance(0.0);
                                }
                            }
//                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList());
//                            int size = tendencyDistance;
//                            // 做比对的分数
//                            double temp = availableVehiclesNearby.get(0).getDistance();
//                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
//                                vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size);
//                                if (temp != vehiclePosition.getDistance()) {
//                                    size--;
//                                }
//                            }
                            // 分数计算 把时间短的分数调高
                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList());
                            int score = 10;
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                vehiclePosition.setDistanceScore(score);
                                score--;
                            }
                        }
                        // 时间分数
                        if (max.equals(tendencyTime)) {
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                LonLatDto lonLatDto = new LonLatDto();
                                lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                routeAndFareDto.setOrigin(lonLatDto);
                                LonLatDto lonLatDto1 = new LonLatDto();
                                lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                if(planRule!=null&& !"null".equals(planRule)){
                                    routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                }
                                routeAndFareDto.setDestination(lonLatDto1);
                                //  调用地图 获取时间
                                R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                if (r.getCode() == 200) {
                                    vehiclePosition.setSecond(r.getData().getDuration());
                                } else {
                                    vehiclePosition.setSecond(0);
                                }
                            }
                            // 分数计算 把时间短的分数调高
                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList());
                            int score = 10;
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                vehiclePosition.setTimeScore(score);
                                score--;
                            }
//                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList());
//                            int size = tendencyTime;
//                            // 做比对的分数
//                            double temp = availableVehiclesNearby.get(0).getSecond();
//                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
//                                vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size);
//                                if (temp != vehiclePosition.getSecond()) {
//                                    size--;
//                                }
//                            }
                        }
                        // 电量分数
                        if (max.equals(tendencyElectricity)) {
                            // 计算车的分数  分数最大是车的size
                            availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList());
                            int size = tendencyElectricity;
                            // 做比对的分数
                            int temp = availableVehiclesNearby.get(0).getCurrentElectricity();
                            int maxTemp = 0;
                            for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size);
                                if (temp != vehiclePosition.getCurrentElectricity()) {
                                    size--;
                                } else {
                                    maxTemp++;
                                }
                            }
                            if (maxTemp > 1) {
                                // 证明有最高相同电量的  找下一个
                                // 找出最第二大的值是那个
                                // 将四个值放入列表
                                List<Integer> values = Arrays.asList(tendencyOrderValue, tendencyDistance, tendencyTime);
                                // 降序排序
                                values.sort(Collections.reverseOrder());
                                // 获取第二大值
                                Integer secondMax = values.get(1);
                                // 判断第二大的是哪个
                                if (Objects.equals(secondMax, tendencyDistance)) {
                                    for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                        RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                        LonLatDto lonLatDto = new LonLatDto();
                                        lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                        lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                        routeAndFareDto.setOrigin(lonLatDto);
                                        LonLatDto lonLatDto1 = new LonLatDto();
                                        lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                        lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                        if(planRule!=null&& !"null".equals(planRule)){
                                            routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                        }
                                        routeAndFareDto.setDestination(lonLatDto1);
                                        //  调用地图 获取时间
                                        R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                        if (r.getCode() == 200) {
                                            vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance()));
                                        } else {
                                            vehiclePosition.setDistance(0.0);
                                        }
                                    }
                                    availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getDistance)).collect(Collectors.toList());
                                    int size1 = tendencyDistance;
                                    // 做比对的分数
                                    double temp1 = availableVehiclesNearby.get(0).getDistance();
                                    for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                        vehiclePosition.setDistanceScore(vehiclePosition.getDistanceScore() + size1);
                                        if (temp1 != vehiclePosition.getDistance()) {
                                            size1--;
                                        }
                                    }
                                }
                                if (Objects.equals(secondMax, tendencyTime)) {
                                    for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                        RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                        LonLatDto lonLatDto = new LonLatDto();
                                        lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                        lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                        routeAndFareDto.setOrigin(lonLatDto);
                                        LonLatDto lonLatDto1 = new LonLatDto();
                                        lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                        lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                        if(planRule!=null&& !"null".equals(planRule)){
                                            routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                        }
                                        routeAndFareDto.setDestination(lonLatDto1);
                                        //  调用地图 获取时间
                                        R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                        if (r.getCode() == 200) {
                                            vehiclePosition.setSecond(r.getData().getDuration());
                                        } else {
                                            vehiclePosition.setSecond(0);
                                        }
                                    }
                                    availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getSecond)).collect(Collectors.toList());
                                    int size1 = tendencyTime;
                                    // 做比对的分数
                                    double temp1 = availableVehiclesNearby.get(0).getSecond();
                                    for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                        vehiclePosition.setTimeScore(vehiclePosition.getTimeScore() + size1);
                                        if (temp1 != vehiclePosition.getSecond()) {
                                            size1--;
                                        }
                                    }
                                }
                                // 订单价值
                                if (Objects.equals(secondMax, tendencyOrderValue)) {
                                    // 订单价值
                                    // 时间差权重
                                    Integer weightTimeDifference = xpTradingStrategy.getWeightTimeDifference();
                                    // 距离差权重
                                    Integer weightDistanceDifference = xpTradingStrategy.getWeightDistanceDifference();
                                    // 距离权重
                                    Integer weightDistance = xpTradingStrategy.getWeightDistance();
                                    // 时间权重
                                    Integer weightTime = xpTradingStrategy.getWeightTime();
                                    // 电量权重
                                    Integer weightElectricity = xpTradingStrategy.getWeightElectricity();
                                    // 找出最大的值是那个
                                    Integer max1 = Math.max(weightTimeDifference, Math.max(weightDistanceDifference, Math.max(weightDistance, Math.max(weightTime, weightElectricity))));
                                    //  时间差
                                    if (max1.equals(weightTimeDifference)) {
                                        for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                            LonLatDto lonLatDto = new LonLatDto();
                                            lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                            lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                            routeAndFareDto.setOrigin(lonLatDto);
                                            LonLatDto lonLatDto1 = new LonLatDto();
                                            lonLatDto1.setLongitude(Double.valueOf(split[0]));
                                            lonLatDto1.setLatitude(Double.valueOf(split[1]));
                                            routeAndFareDto.setDestination(lonLatDto1);
                                            if(planRule!=null&& !"null".equals(planRule)){
                                                routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                            }
                                            R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                            if (distanceAndDuration.getCode() == 200) {
                                                // 送驾- 接驾
                                                Integer durationDifference = Integer.parseInt(duration) - distanceAndDuration.getData().getDuration();
                                                vehiclePosition.setTimeDifference(durationDifference);
                                            }
                                        }
                                    }
                                    if (max1.equals(weightDistanceDifference)) {
                                        for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                            LonLatDto lonLatDto = new LonLatDto();
                                            lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                            lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                            routeAndFareDto.setOrigin(lonLatDto);
                                            LonLatDto lonLatDto1 = new LonLatDto();
                                            lonLatDto1.setLongitude(Double.valueOf(split[0]));
                                            lonLatDto1.setLatitude(Double.valueOf(split[1]));
                                            routeAndFareDto.setDestination(lonLatDto1);
                                            if(planRule!=null&& !"null".equals(planRule)){
                                                routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                            }
                                            R<RouteVo> distanceAndDuration = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                            if (distanceAndDuration.getCode() == 200) {
                                                // 送驾- 接驾
                                                Integer distanceDifference = Integer.parseInt(distance) - distanceAndDuration.getData().getDistance();
                                                vehiclePosition.setDistanceDifference(distanceDifference);
                                            }
                                        }
                                    }
                                    if (max1.equals(weightDistance)) {
                                        for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                            LonLatDto lonLatDto = new LonLatDto();
                                            lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                            lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                            routeAndFareDto.setOrigin(lonLatDto);
                                            LonLatDto lonLatDto1 = new LonLatDto();
                                            lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                            lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                            if(planRule!=null&& !"null".equals(planRule)){
                                                routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                            }
                                            routeAndFareDto.setDestination(lonLatDto1);
                                            //  调用地图 获取时间
                                            R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                            if (r.getCode() == 200) {
                                                vehiclePosition.setDistance(Double.valueOf(r.getData().getDistance()));
                                            } else {
                                                vehiclePosition.setDistance(0.0);
                                            }
                                        }
                                    }
                                    if (max1.equals(weightTime)) {
                                        for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                            RouteAndFareDto routeAndFareDto = new RouteAndFareDto();
                                            LonLatDto lonLatDto = new LonLatDto();
                                            lonLatDto.setLongitude(vehiclePosition.getPoint().getX());
                                            lonLatDto.setLatitude(vehiclePosition.getPoint().getY());
                                            routeAndFareDto.setOrigin(lonLatDto);
                                            LonLatDto lonLatDto1 = new LonLatDto();
                                            lonLatDto1.setLongitude(Double.parseDouble(split[0]));
                                            lonLatDto1.setLatitude(Double.parseDouble(split[1]));
                                            if(planRule!=null&& !"null".equals(planRule)){
                                                routeAndFareDto.setRoutePlanRule(Integer.valueOf(planRule));
                                            }
                                            routeAndFareDto.setDestination(lonLatDto1);
                                            //  调用地图 获取时间
                                            R<RouteVo> r = xpMapClient.getDistanceAndDuration(routeAndFareDto);
                                            if (r.getCode() == 200) {
                                                vehiclePosition.setSecond(r.getData().getDuration());
                                            } else {
                                                vehiclePosition.setSecond(0);
                                            }
                                        }
                                    }
                                    if (max1.equals(weightElectricity)) {
                                        // 计算车的分数  分数最大是车的size
                                        availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getCurrentElectricity).reversed()).collect(Collectors.toList());
                                        int size1 = tendencyElectricity;
                                        // 做比对的分数
                                        int temp1 = availableVehiclesNearby.get(0).getCurrentElectricity();
                                        for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                            vehiclePosition.setCurrentElectricityScore(vehiclePosition.getCurrentElectricityScore() + size1);
                                            if (temp1 != vehiclePosition.getCurrentElectricity()) {
                                                size1--;
                                            }
                                        }
                                    }
                                }
                                // 算出总分 再来排序计算
                                for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) {
                                    vehiclePositionVo.setOrderValueTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getDistanceDifference() + vehiclePositionVo.getTimeDifference()+vehiclePositionVo.getSecond()+vehiclePositionVo.getDistance().intValue());
                                }
                                availableVehiclesNearby = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getOrderValueTotal).reversed()).collect(Collectors.toList());
                                int size2 = tendencyOrderValue;
                                // 做比对的分数
                                double temp2 = availableVehiclesNearby.get(0).getOrderValueTotal();
                                for (VehiclePositionVo vehiclePosition : availableVehiclesNearby) {
                                    vehiclePosition.setValueScore(vehiclePosition.getValueScore() + size2);
                                    if (temp2 != vehiclePosition.getOrderValueTotal()) {
                                        size2--;
                                    }
                                }
                            }
                        }
                    } catch (Exception e) {
                        log.error("异常", e);
                    }
                    // 判断总分来计算
                    for (VehiclePositionVo vehiclePositionVo : availableVehiclesNearby) {
                        vehiclePositionVo.setTotal(vehiclePositionVo.getCurrentElectricityScore() + vehiclePositionVo.getDistanceScore() + vehiclePositionVo.getTimeScore() + vehiclePositionVo.getValueScore());
                    }
                    VehiclePositionVo vehiclePositionVo = availableVehiclesNearby.stream().sorted(Comparator.comparing(VehiclePositionVo::getTotal).reversed()).collect(Collectors.toList()).get(0);
//
//                    VehiclePositionVo vehiclePositionVo1 = vehiclePositionVo;
                    RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePositionVo.getVin());
                    lock.lock(10, TimeUnit.SECONDS);
                    log.info("队列 {} 车辆 {} 单号 {}", quoteName, vehiclePositionVo.getVin(), orderNo);
                    try {
//                        VehiclePosition vehiclePosition = vehiclePositionService.findByVehicleId(vehiclePositionVo.getVehicle_id());
                        R<XpVehicle> vehiclePositionR = xpVehicleClient.findByVehicleVin(vehiclePositionVo.getVin());
                        if (vehiclePositionR.getCode() != 200) {
                            continue;
                        }
                        XpVehicle vehiclePosition = vehiclePositionR.getData();
                        log.info("符合条件的车辆 {} ,直接推单XPU。单号 {}", vehiclePosition.getPlateNumber(), orderNo);
                        log.info("当前车辆状态 {} 单号 {}", vehiclePosition.getStatus(), orderNo);
                        if (vehiclePosition.getOperatingStatus() != 1 || vehiclePosition.getState() != 0 || vehiclePosition.getVehicleType() == 1) {
                            continue;
                        }
                        // 再次查询一下订单 看是否取消
                        xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo);
                        if (xpOrderR.getCode() != 200) {
                            continue;
                        }
                        xpOrder = xpOrderR.getData();
                        if (xpOrder.getStatus() != 1) {
                            continue;
                        }
                        //  关闭巡游单子
                        R stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehiclePosition.getVehicleVin());
                        if (stringR == null || stringR.getCode() != 200) {
                            log.info("关闭巡游单子失败 车牌号 {}", vehiclePosition.getPlateNumber());
                            continue;
                        }
                        log.info("关闭巡游单成功 {} {}", vehiclePosition.getPlateNumber(), orderNo);
                        // 下发命令
                        PushOrderDto pushOrderDto = new PushOrderDto();
                        pushOrderDto.setVin(vehiclePosition.getVehicleVin());
                        pushOrderDto.setOrderId(xpOrder.getId().toString());
                        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                        pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                        pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                        pushOrderDto.setStage(1);
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU。单号 {}", xpOrder.getOrderNumber(), orderNo);
                        redisService.removeByPattern(quoteName,xpOrder.getOrderNumber());
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                } else {
                    // 直接派单  定义一个锁来锁定车辆
                    VehiclePositionVo vehiclePosition = availableVehiclesNearby.get(0);
                    String vehicleVin = vehiclePosition.getVin();
                    RLock lock = redissonClient.getLock("FIND_CAR_" + vehiclePosition.getVin());
                    lock.lock(10, TimeUnit.SECONDS);
                    try {
                        // 查询车辆状态
                        R<XpVehicle> vehicleR = xpVehicleClient.findByVehicleVin(vehicleVin);
                        if (vehicleR.getCode() != 200) {
                            continue;
                        }
                        XpVehicle vehicleId1 = vehicleR.getData();
                        log.info("附近只有一个车辆 {} ,直接推单XPU。单号 {}", vehicleId1.getPlateNumber(), orderNo);
                        log.info("当前车辆状态 运营状态 {} 单号 {}", vehicleId1.getState(), orderNo);
                        if (vehicleId1.getOperatingStatus() != 1 || vehicleId1.getState() != 0 || vehicleId1.getVehicleType() == 1) {
                            continue;
                        }
                        // 再次查询一下订单 看是否取消
                        xpOrderR = xpOrderClient.queryOrderByOrderNo(orderNo);
                        if (xpOrderR.getCode() != 200) {
                            continue;
                        }
                        xpOrder = xpOrderR.getData();
                        if (xpOrder.getStatus() != 1) {
                            continue;
                        }
                        //  关闭巡游单子
                        R<?> stringR = xpCruiseOrderClient.cancelCruiseOrderByVin(vehicleId1.getVehicleVin());
                        if (stringR == null || stringR.getCode() != 200) {
                            log.info("关闭巡游单子失败 车牌号 {}", vehicleId1.getPlateNumber());
                            continue;
                        }
                        log.info("关闭巡游单成功 {} {}", vehicleId1.getPlateNumber(), orderNo);
                        PushOrderDto pushOrderDto = new PushOrderDto();
                        pushOrderDto.setVin(vehiclePosition.getVin());
                        pushOrderDto.setOrderId(xpOrder.getId().toString());
                        pushOrderDto.setStartLatitude(xpOrder.getStartLat());
                        pushOrderDto.setStartLongitude(xpOrder.getStartLon());
                        pushOrderDto.setEndLatitude(xpOrder.getEndLat());
                        pushOrderDto.setEndLongitude(xpOrder.getEndLon());
                        pushOrderDto.setEndPoiName(xpOrder.getEndPointName());
                        pushOrderDto.setOrderType(OrderType.USER_ORDER);
                        pushOrderDto.setStage(1);
                        // 调用推送服务  orderId + carVin
                        orderMissionClient.pushOrder(pushOrderDto);
                        log.info("开始推送 {} 订单到XPU", xpOrder.getOrderNumber());
                        redisService.popFirstElement(quoteName);
                        log.info("将订单 {} 从队列 {} 弹出去", orderNo, quoteName);
                        return true;
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
        return false;
    }
    /**
     * 定向服务订单处理
     * @param quoteName  队列名称
     * @param count 轮数
     * @param uid
     * @param split  经纬度
     * @param orderNo 订单号
     * @param xpTradingStrategy  规则
     */
    @SneakyThrows
    private Boolean processPushSpOrder(String quoteName, int count, int sleepTime, String uid, String[] split, String orderNo, XpTradingStrategy xpTradingStrategy, Double pushDistance, String distance, String duration, String planRule) {
        log.info("进入推单环节 单号 {}", orderNo);
        if (count == 0) {
            count = 1;
@@ -1256,6 +2120,8 @@
        return false;
    }
    private static PushOrderDto buildPushOrderDto(XpOrder xpOrder) {
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setOrderId(xpOrder.getId().toString());
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OfficialPartnerVo.java
New file
@@ -0,0 +1,20 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("合作商信息")
public class OfficialPartnerVo {
    @ApiModelProperty("合作商名称")
    private String name;
    @ApiModelProperty("合作商品牌名称")
    private String brandName;
    @ApiModelProperty("合作商品牌logo")
    private String logoUrl;
    @ApiModelProperty("应用APPKey")
    private String appKey;
    @ApiModelProperty("应用APPSecret")
    private String appSecret;
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/OrderDistanceVo.java
@@ -23,4 +23,13 @@
    @ApiModelProperty(value = "天气单位")
    private String temperatureUnit;
    @ApiModelProperty("首页轮询接口间隔 秒")
    private Integer queuePollingTime;
    @ApiModelProperty("步行图标控制距离 米")
    private Integer walkingNavigationDistance;
    @ApiModelProperty("下单页停留时长")
    private Integer maxStandingTiming;
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/PricingInfoVo.java
New file
@@ -0,0 +1,10 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel("定价信息")
public class PricingInfoVo {
}
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpOfficialPartnerMapper.xml
New file
@@ -0,0 +1,6 @@
<?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.operation.mapper.XpOfficialPartnerMapper">
</mapper>
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpTradingStrategyPushMapper.xml
New file
@@ -0,0 +1,7 @@
<?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.operation.mapper.XpTradingStrategyPushMapper">
</mapper>
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -500,7 +500,7 @@
     * +
     * 获取行程费用明细
     */
    @PutMapping("/api/v1/mini-program/order/fare-breakdown")
    @PostMapping("/api/v1/mini-program/order/fare-breakdown")
    @ApiOperation(value = "获取行程费用明细", tags = {"小程序-获取行程费用明细"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<FareBreakdownVo> fareBreakdown(@RequestBody com.xiaopeng.order.vo.FareBreakdownVo vo, HttpServletRequest request) {
@@ -619,8 +619,8 @@
        Object cacheObject = redisService.getCacheObject(key);
        RouteVo routeVo = JSON.parseObject(cacheObject.toString(), RouteVo.class);
        XpVehicle xpVehicle = xpVehicleClient.queryById(xpOrder.getVehicleId()).getData();
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
        routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90);
//        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(xpVehicle.getVehicleVin())), VehiclePosition.class);
//        routeVo.setDirection(null != vehiclePosition ? vehiclePosition.getCourse() : 90);
        Long vehicleId = xpOrder.getVehicleId();
        XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("vehicle_id", vehicleId).in("status", Arrays.asList(6, 7)).eq("is_deleted", 0));
@@ -721,7 +721,7 @@
        //判断流失用户
        XpOrder one = xpOrderService.getOne(new QueryWrapper<XpOrder>().eq("app_user_id", userId).in("status", Arrays.asList(9, 10)).last(" order by create_time desc limit 1"));
        if(null != one){
            long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("GMT+8")) - one.getCreateTime().toEpochSecond(ZoneOffset.of("GMT+8"));
            long time = LocalDateTime.now().toEpochSecond(ZoneOffset.of("+8")) - one.getCreateTime().toEpochSecond(ZoneOffset.of("+8"));
            if(time >= 60 * 60 * 24 * 5){
                return R.ok(4);
            }
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/mapper/XpOrderMapper.java
@@ -74,7 +74,11 @@
    List<XpOrder> listUserRecentValidOrders(@Param("uid") Long uid, @Param("startTime") LocalDateTime startTime);
    List<Long> timeSceneOrders(@Param("startDate") LocalDate startDate, @Param("endDate") LocalDateTime endDate, @Param("startMoment") LocalTime startMoment, @Param("endMoment") LocalTime endMoment, @Param("userId") Long userId);
    List<Long> timeSceneOrders(@Param("startDate") LocalDate startDate,
                               @Param("endDate") LocalDateTime endDate,
                               @Param("startMoment") LocalTime startMoment,
                               @Param("endMoment") LocalTime endMoment,
                               @Param("userId") Long userId);
    List<Long> frequencyOrders(LocalDate startDate, LocalDateTime endDate, LocalTime startMoment, LocalTime endMoment, Long userId);
}
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -2136,18 +2136,6 @@
                                .put("orderType", OrderType.USER_ORDER)
                                .build();
                //如果是异常订单,需要定时创建客服工单
                if(orderException){
                    XpSystemSetting xpSystemSetting = xpSystemSettingClient.getSystemSettingOne().getData();
                    QuartzManager.addJob(
                            OrderExceptionJob.class,
                            (OrderExceptionJob.name + xpOrder.getId()).toUpperCase(),
                            TimeJobType.ADD_CRUISE_MISSION,
                            DateUtils.localDateTimeToDate(LocalDateTime.now().plusMinutes(xpSystemSetting.getOrderExceptionalTimeout())),
                            jobMaps
                    );
                }
                //判断是否有连环单
                String json = redisService.getCacheObject(CacheConstants.nextOrder(xpOrder.getId().toString()));
                if (StringUtils.isNotEmpty(json)){
@@ -2284,19 +2272,19 @@
        order.setAppUserId(appUserId);
        bootCommonService.setCache_orderStatus(order.getId(),order,null);
        //删除蓝牙秘钥
        String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId);
        if(StringUtils.isNotBlank(token)){
            redisService.deleteObject("rt:bluetooth:unlock:" + token);
            redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId);
            XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
            BluetoothDeliverVo vo = new BluetoothDeliverVo();
            vo.setVim(xpVehicle.getVehicleVin());
            vo.setPassengerUid(order.getAppUserId());
            BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
            if(null == delete || delete.getCode() != 0){
                log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
            }
        }
//        String token = redisService.getCacheObject("rt:bluetooth:unlock:order:" + orderId);
//        if(StringUtils.isNotBlank(token)){
//            redisService.deleteObject("rt:bluetooth:unlock:" + token);
//            redisService.deleteObject("rt:bluetooth:unlock:order:" + orderId);
//            XpVehicle xpVehicle = xpVehicleClient.queryById(order.getVehicleId()).getData();
//            BluetoothDeliverVo vo = new BluetoothDeliverVo();
//            vo.setVim(xpVehicle.getVehicleVin());
//            vo.setPassengerUid(order.getAppUserId());
//            BaseVehicleUserDto delete = bluetoothUnlockClient.delete(vo);
//            if(null == delete || delete.getCode() != 0){
//                log.error("删除蓝牙解锁失败:{} {}", delete.getMsg(), order.getOrderNumber());
//            }
//        }
        // 根据订单所属开通城市id 查询定价
        XpPricing pricing = bootCommonService.getXpPricing(order.getCityId(),order.getVehicleId());
@@ -2353,12 +2341,15 @@
            xpOrderDetail.setType(1);
            xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDistancePrice()).setScale(2,RoundingMode.HALF_UP));
            xpOrderDetails.add(xpOrderDetail);
            xpOrderDetail = new XpOrderDetail();
            xpOrderDetail.setDetailType(3);
            xpOrderDetail.setOrderId(orderId);
            xpOrderDetail.setType(1);
            xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDurationPrice()).setScale(2, RoundingMode.HALF_UP));
            xpOrderDetails.add(xpOrderDetail);
            //时长费不是必填项
            if(null != xpPricingCardVo.getDurationPrice() && xpPricingCardVo.getDurationPrice() > 0){
                xpOrderDetail = new XpOrderDetail();
                xpOrderDetail.setDetailType(3);
                xpOrderDetail.setOrderId(orderId);
                xpOrderDetail.setType(1);
                xpOrderDetail.setMoney(new BigDecimal(xpPricingCardVo.getDurationPrice()).setScale(2, RoundingMode.HALF_UP));
                xpOrderDetails.add(xpOrderDetail);
            }
            BigDecimal totalPrice =BigDecimal.ZERO;
            for (XpOrderDetail xpOrderDetail1 : xpOrderDetails) {
@@ -2372,7 +2363,6 @@
        else {
            //动态计费
            if (pricing.getPricingType() == 1) {
                for (int i = 0; i < startingFareJsonArray.size(); i++) {
                    com.alibaba.fastjson2.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i);
                    String num1 = jsonObject.getString("num1");
@@ -2464,6 +2454,8 @@
                            // 触发调价了
                            redisService.setCacheObject("USER_DYNAMIC_PRICE_" + order.getCityId() + "_" + uid, priceRate, time.longValue(), TimeUnit.MINUTES);
                        }
                        //天气预报动态调价
                    }
                }
@@ -3579,34 +3571,34 @@
                        .plusMinutes(routeVo1.getDuration()).plusMinutes(endPoint.getParkingTimeLimit()).plusMinutes(30);
                long expirationTime = localDateTime.toEpochSecond(ZoneOffset.of("+8"));
                //生成token
                String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(),
                        order.getId(), order.getVehicleId(), expirationTime);
                log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber());
                //存储缓存
                JSONObject jsonObject = new JSONObject();
                jsonObject.put("userId", order.getAppUserId());
                jsonObject.put("orderId", order.getId());
                jsonObject.put("vehicleId", order.getVehicleId());
                jsonObject.put("expirationTime", expirationTime);
                jsonObject.put("orderNumber", order.getOrderNumber());
                jsonObject.put("vehicleVin", vehicle.getVehicleVin());
                jsonObject.put("createTime", System.currentTimeMillis());
                redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS);
                redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS);
                //开始下发蓝牙token
                BluetoothDeliverVo vo = new BluetoothDeliverVo();
                vo.setCredential(token);
                vo.setVim(vehicle.getVehicleVin());
                vo.setPassengerUid(order.getAppUserId());
                BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo);
                if(null == deliver){
                    throw new ServiceException("下发蓝牙token失败");
                }
                if(deliver.getCode() != 0){
                    log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber());
                    throw new ServiceException(deliver.getMsg());
                }
                log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber());
//                String token = bluetoothUnlockTokenUtil.generateBluetoothUnlockToken(order.getAppUserId(),
//                        order.getId(), order.getVehicleId(), expirationTime);
//                log.info("生成蓝牙token:{} 有效期:{} 订单号: {}", token, expirationTime, order.getOrderNumber());
//                //存储缓存
//                JSONObject jsonObject = new JSONObject();
//                jsonObject.put("userId", order.getAppUserId());
//                jsonObject.put("orderId", order.getId());
//                jsonObject.put("vehicleId", order.getVehicleId());
//                jsonObject.put("expirationTime", expirationTime);
//                jsonObject.put("orderNumber", order.getOrderNumber());
//                jsonObject.put("vehicleVin", vehicle.getVehicleVin());
//                jsonObject.put("createTime", System.currentTimeMillis());
//                redisService.setCacheObject("rt:bluetooth:unlock:" + token, jsonObject.toJSONString(), expirationTime, TimeUnit.SECONDS);
//                redisService.setCacheObject("rt:bluetooth:unlock:order:" + order.getId(), token, expirationTime, TimeUnit.SECONDS);
//                //开始下发蓝牙token
//                BluetoothDeliverVo vo = new BluetoothDeliverVo();
//                vo.setCredential(token);
//                vo.setVim(vehicle.getVehicleVin());
//                vo.setPassengerUid(order.getAppUserId());
//                BaseVehicleUserDto deliver = bluetoothUnlockClient.deliver(vo);
//                if(null == deliver){
//                    throw new ServiceException("下发蓝牙token失败");
//                }
//                if(deliver.getCode() != 0){
//                    log.error("下发蓝牙token失败:{} {}", deliver.getMsg(), order.getOrderNumber());
//                    throw new ServiceException(deliver.getMsg());
//                }
//                log.info("下发蓝牙token成功:{} {}", deliver.getData(), order.getOrderNumber());
            }
            if(order.getStatus() == 2){
@@ -3792,9 +3784,11 @@
        }
        Integer status = xpOrder.getStatus();
        if(status > 2 && status < 8){
            Boolean data = xpVehicleClient.getVehicleTrunkOpenStatus(xpOrder.getAppUserId(), xpOrder.getVehicleId()).getData();
            xpOrder.setOpenTrunk(data ? 1 : 2);
            xpOrderDetailVO.setOpenTrunk(data ? 1 : 2);
//            Boolean data = xpVehicleClient.getVehicleTrunkOpenStatus(xpOrder.getAppUserId(), xpOrder.getVehicleId()).getData();
//            xpOrder.setOpenTrunk(data ? 1 : 2);
//            xpOrderDetailVO.setOpenTrunk(data ? 1 : 2);
            xpOrder.setOpenTrunk(2);
            xpOrderDetailVO.setOpenTrunk(2);
            xpOrder.setAppUserId(null);
            this.updateById(xpOrder);
        }
xp-robotaxi-order-boot/src/main/resources/mapper/order/XpOrderMapper.xml
@@ -108,7 +108,7 @@
          AND is_deleted = 0
          AND status IN (9, 10)
          AND DATE(create_time) BETWEEN #{startDate} AND #{endDate}
          AND TIME(create_time) BETWEEN #{startTime} AND #{endTime}
          AND TIME(create_time) BETWEEN #{startMoment} AND #{endMoment}
        GROUP BY end_point_id
        ORDER BY COUNT(*) DESC
    </select>
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/webSocket/controller/WebSocketController.java
@@ -46,7 +46,7 @@
     * @return 操作结果
     */
    @ApiOperation(value = "发送订单状态")
    @PostMapping("/inner/websocket/order/sendStatus")
    @PostMapping("/logan/inner/websocket/order/sendStatus")
    public R<String> sendStatus(@RequestBody SendMessageDTO dto) {
        try {
            String message = dto.getMessage();
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetController.java
@@ -240,28 +240,4 @@
        return R.ok(xpFleetService.list());
    }
    @ApiOperation(value = "品牌信息", tags = {"流量接入-信息录入-品牌展示信息"})
    @PostMapping("/api/v1/xp-rt/brand-info")
    public R<?> JoinUs(
            @ApiParam(value = "车辆信息", required = true)
            @RequestBody BrandInfo brandInfo
    ) {
        //包含接收订单的URL
        XpFleet xpFleet = new XpFleet();
        XpOperationsUser operationsUser = new XpOperationsUser();
        operationsUser.setNickName(brandInfo.getOperationsUserName());
        operationsUser.setPhoneNumber(brandInfo.getPhoneNumber());
        operationsUser.setDeviceType(1);
        xpFleet.setFleetName(brandInfo.getBrandName());
//        xpFleetService.save(fleet);
        return R.ok();
    }
    XpOperationsUserClient xpOperationsUserClient;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpFleetVehicleController.java
@@ -60,29 +60,4 @@
        List<Long> vehicleIds = xpFleetVehicleService.listVehicleIdsByFleetId(fleetId);
        return R.ok(vehicleIds);
    }
    @ApiOperation(value = "添加车辆", tags = {"流量接入-信息录入-车辆"})
    @PostMapping("/api/v1/xp-rt/vehicle")
    public R<?> add(
            @ApiParam(value = "车辆信息", required = true)
            @RequestBody XpFleetVehicle fleetVehicle
            ) {
        xpFleetVehicleService.save(fleetVehicle);
        return R.ok();
    }
    @Resource
    MongoTemplate mongoTemplate;
    @ApiOperation(value = "车辆", tags = {"流量接入-信息录入-车辆"})
    @PostMapping("/api/v1/xp-rt/vehicle/info")
    public R<?> JoinUs(
            @ApiParam(value = "车辆位置信息", required = true)
            @RequestBody VehiclePosition vp
    ) {
        mongoTemplate.save(vp);
        return R.ok();
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -42,6 +42,7 @@
import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel;
import com.xiaopeng.vehicleConvoy.model.query.*;
import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO;
import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto;
import com.xiaopeng.vehicleConvoy.service.IXpFleetService;
import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService;
import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService;
@@ -746,26 +747,7 @@
    }
    public static void main(String[] args) {
        String inspectionAttachments = "[{\"id\": \"d57c4ac4-acb0-451b-8e94-70f226331e0c\", \"url\": \"https://huishou-1323682843.cos.ap-nanjing.myqcloud.com/images/552a3a31-e4dd-4a28-8748-fd8b87dd3055.png\", \"name\": \"测试.jpg\"}]";
        if (StringUtils.isNotBlank(inspectionAttachments)) {
            JSONArray jsonArray = JSONArray.parseArray(inspectionAttachments);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (Objects.isNull(jsonObject)) {
                    continue;
                }
                jsonObject.put("url", "downloadUrl");
            }
            String jsonString = JSONArray.toJSONString(jsonArray);
            System.out.println(jsonString);
        }
    }
    /**
     * 根据围栏id查询空闲车辆
@@ -1205,35 +1187,24 @@
        return R.ok(xpVehicleList);
    }
    @ApiOperation(value = "上报车辆位置", notes = "", tags = {"流量接入-上报车辆位置"})
    @PostMapping("/api/v1/xp-rt/vehicle/position")
    public R<List<XpVehicleVO>> pushVehiclePosition(@RequestBody VehiclePosition vp) {
        // 更新到mongodb,用于被分配订单
        // 如果是接单中,更新导航路线
        return R.ok();
    }
    /**
     * {@Link OrderStatusEnum}
     * @param vp
     * 上报车辆实时位置信息
     * @param dto
     * @return
     */
    @ApiOperation(value = "更新车辆状态", notes = "", tags = {"流量接入-更新车辆状态"})
    @PostMapping("/api/v1/xp-rt/vehicle/status")
    public R<List<XpVehicleVO>> pushVehicleStatus(@RequestBody VehiclePosition vp) {
        // 前往接驾,等待上车,前往终点,到达终点等待下车,结束订单
        // 更新order状态
    @PostMapping("/drainage/v1/vehicle/reportVehicleLocation")
    @ApiOperation(value = "上报车辆实时位置信息", notes = "流量接入-基础信息")
    @ApiImplicitParams({
            @ApiImplicitParam(value = "token", name = "token", required = true, paramType = "header")
    })
    public R<?> reportVehicleLocation(@RequestBody VehiclePositionDto dto){
        xpVehicleService.reportVehicleLocation(dto);
        return R.ok();
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/vo/VehiclePositionDto.java
New file
@@ -0,0 +1,61 @@
package com.xiaopeng.vehicleConvoy.model.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexType;
import org.springframework.data.mongodb.core.index.GeoSpatialIndexed;
@Data
@ApiModel("车辆位置信息")
public class VehiclePositionDto {
    /**
     * 车辆VIN
     */
    @ApiModelProperty(value = "车辆VIN")
    private String vin;
    /**
     * 车辆实时位置信息
     */
    @ApiModelProperty(value = "车辆经度")
    private Double longitude;
    @ApiModelProperty(value = "车辆纬度")
    private Double latitude;
    /**
     * 航向,单位:度,北零顺时针。范围:[0-360)。0 => 北, 90 => 东, 180 => 南, 270 => 西
     */
    @ApiModelProperty("车头北向夹角")
    private Double course;
    /**
     * 海拔 单位米
     */
    @ApiModelProperty("车辆海拔")
    private Float alt;
    /**
     * 当前速度
     */
    @ApiModelProperty("车辆速度")
    private Float speed;
    /**
     * 当前电量
     */
    @ApiModelProperty("车辆电量")
    private Integer currentElectricity;
    /**
     * 综合续航
     */
    @ApiModelProperty("车辆综合续航")
    private Float mileageRange;
    /**
     * 订单id
     */
    @ApiModelProperty("订单id")
    private Long orderId;
    /**
     * 总里程
     */
    @ApiModelProperty("总里程")
    private Long totalOdometer;
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/IXpVehicleService.java
@@ -5,12 +5,15 @@
import com.xiaopeng.api.dto.vehicleConvoy.VehicleTemperatureDto;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.api.vo.operation.VehiclePositionVo;
import com.xiaopeng.api.vo.vehicleConvoy.VehicleDoorStatusVo;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.vehicleConvoy.model.dto.*;
import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel;
import com.xiaopeng.vehicleConvoy.model.query.*;
import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO;
import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@@ -243,4 +246,11 @@
     * @return
     */
    VehicleDoorStatusVo getVehicleDoorStatus(Long orderId);
    /**
     * 上报车辆实时位置
     * @param dto
     */
    void reportVehicleLocation(VehiclePositionDto dto);
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -38,6 +38,7 @@
import com.xiaopeng.api.vo.automaticPilot.VehiclePosition;
import com.xiaopeng.api.vo.operation.ElectronicFenceDetailVo;
import com.xiaopeng.api.vo.operation.RouteVo;
import com.xiaopeng.api.vo.operation.VehiclePositionVo;
import com.xiaopeng.api.vo.vehicleConvoy.*;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.domain.R;
@@ -54,6 +55,7 @@
import com.xiaopeng.vehicleConvoy.model.importExcel.XpVehicleImportExcel;
import com.xiaopeng.vehicleConvoy.model.query.*;
import com.xiaopeng.api.vo.vehicleConvoy.XpVehicleVO;
import com.xiaopeng.vehicleConvoy.model.vo.VehiclePositionDto;
import com.xiaopeng.vehicleConvoy.service.AsyncVehicleStateService;
import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService;
import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService;
@@ -70,6 +72,7 @@
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -1446,4 +1449,43 @@
        vo.setTrunk(trunk_ajar_st_new == 5 ? 1 : 0);
        return vo;
    }
    /**
     * 上报车辆实时位置
     * @param dto
     */
    @Override
    public void reportVehicleLocation(VehiclePositionDto dto) {
        if(StringUtils.isEmpty(dto.getVin())){
            throw new ServiceException("无效数据");
        }
        if(null == dto.getLatitude() || null == dto.getLongitude()){
            throw new ServiceException("无效数据");
        }
        XpVehicle vehicle = this.getOne(new QueryWrapper<XpVehicle>().eq("vehicle_vin", dto.getVin()).eq("is_deleted", 0));
        if(null == vehicle){
            throw new ServiceException("无效数据");
        }
        VehiclePosition vehiclePosition = mongoTemplate.findOne(Query.query(Criteria.where("vin").is(dto.getVin())), VehiclePosition.class);
        if(null == vehiclePosition){
            BeanUtil.copyProperties(dto, vehiclePosition);
            vehiclePosition.setPoint(new GeoJsonPoint(dto.getLongitude(), dto.getLatitude()));
            vehiclePosition.setAddTime(System.currentTimeMillis());
            mongoTemplate.save(vehiclePosition);
        }else{
            Update update = new Update()
                    .set("point", new GeoJsonPoint(dto.getLongitude(), dto.getLatitude()))
                    .set("course", dto.getCourse())
                    .set("alt", dto.getAlt())
                    .set("speed", dto.getSpeed())
                    .set("currentElectricity", dto.getCurrentElectricity())
                    .set("mileageRange", dto.getMileageRange())
                    .set("orderId", dto.getOrderId())
                    .set("totalOdometer", dto.getTotalOdometer())
                    .set("addTime", System.currentTimeMillis());
            mongoTemplate.updateFirst(new Query(Criteria.where("vin").is(dto.getVin())), update, VehiclePosition.class);
        }
    }
}