“mitao”
2026-02-26 7e0a3c88a82f16071da480fd2be79ac491dca9e4
Merge remote-tracking branch 'origin/master'
2个文件已添加
13个文件已修改
411 ■■■■■ 已修改文件
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/ThreadPoolConfig.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpAppUserCouponController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpAppUserCouponMapper.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpAppUserCouponService.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpAppUserCouponServiceImpl.java 93 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpAppUserCouponMapper.xml 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpQualificationAuditMapper.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/XpAppUserCoupon.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpVehicleDetection.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpChargingRecordServiceImpl.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpShiftMapper.xml 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpCouponController.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/AliPushUtil.java 160 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/ThreadPoolConfig.java
New file
@@ -0,0 +1,39 @@
package com.xiaopeng.account.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class ThreadPoolConfig {
    @Bean(name = "couponSendExecutor")
    public ThreadPoolTaskExecutor couponSendExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心参数
        executor.setCorePoolSize(5);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(20);  // 增大队列容量
        executor.setKeepAliveSeconds(60);
        // 线程名称前缀
        executor.setThreadNamePrefix("sendCoupon-");
        // 拒绝策略:调用者线程执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        // 初始化
        executor.initialize();
        return executor;
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/XpAppUserCouponController.java
@@ -59,19 +59,19 @@
    @PostMapping("/inner/appUserCoupon/getUserCoupon")
    public R<UserCouponVo> getUserCoupon(@RequestBody GetUserCouponDto dto) {
        String phone ="18888888888";
        if(dto.getUserId()>1){
            UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(dto.getUserId().toString());
            if(baseUserByUid!=null){
                Object data = baseUserByUid.getData();
                phone = JSONObject.parseObject(data.toString()).getString("mobile");
            }
        }
//        String phone ="18888888888";
//        if(dto.getUserId()>1){
//            UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(dto.getUserId().toString());
//            if(baseUserByUid!=null){
//                Object data = baseUserByUid.getData();
//                phone = JSONObject.parseObject(data.toString()).getString("mobile");
//            }
//        }
        UserCouponVo userCouponVo = new UserCouponVo();
        // 获取用户所有优惠券
        List<XpAppUserCoupon> couponList = xpAppUserCouponService.list(new LambdaQueryWrapper<XpAppUserCoupon>().eq(XpAppUserCoupon::getStatus, 1).eq(XpAppUserCoupon::getPhone,phone).apply("FIND_IN_SET({0}, open_city_id)", dto.getOpenCityId()) );
        List<XpAppUserCoupon> couponList = xpAppUserCouponService.list(new LambdaQueryWrapper<XpAppUserCoupon>().eq(XpAppUserCoupon::getStatus, 1).eq(XpAppUserCoupon::getAppUserId,dto.getUserId()).apply("FIND_IN_SET({0}, open_city_id)", dto.getOpenCityId()) );
        if(couponList.isEmpty()){
            return R.ok(userCouponVo);
        }
@@ -116,14 +116,14 @@
    public R<XpAppUserCouponVo> list(@RequestBody XpUserCouponListQuery query, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        String phone ="18888888888";
        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
        if(baseUserByUid!=null){
            Object data = baseUserByUid.getData();
            phone = JSONObject.parseObject(data.toString()).getString("mobile");
        }
//        String phone ="18888888888";
//        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
//        if(baseUserByUid!=null){
//            Object data = baseUserByUid.getData();
//            phone = JSONObject.parseObject(data.toString()).getString("mobile");
//        }
        XpAppUserCouponVo vo = xpAppUserCouponService.userCouponList(query, phone);
        XpAppUserCouponVo vo = xpAppUserCouponService.userCouponList(query, uid);
        return R.ok(vo);
    }
@@ -154,14 +154,14 @@
    public R<XpAppUserCouponListVo> detail(@PathVariable("couponId") Long couponId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        String phone ="18888888888";
        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
        if(baseUserByUid!=null){
            Object data = baseUserByUid.getData();
            phone = JSONObject.parseObject(data.toString()).getString("mobile");
        }
//        String phone ="18888888888";
//        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
//        if(baseUserByUid!=null){
//            Object data = baseUserByUid.getData();
//            phone = JSONObject.parseObject(data.toString()).getString("mobile");
//        }
        XpAppUserCoupon coupon = xpAppUserCouponService.getById(couponId);
        if(phone.equals(coupon.getPhone())){
        if(uid.equals(coupon.getAppUserId().toString())){
            XpAppUserCouponListVo vo = new XpAppUserCouponListVo();
            vo.setCouponId(coupon.getId().toString());
            vo.setTitle(coupon.getCouponName());
@@ -189,13 +189,13 @@
    public R<XpAppUserCouponTotalVo> total(HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        String phone ="18888888888";
        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
        if(baseUserByUid!=null){
            Object data = baseUserByUid.getData();
            phone = JSONObject.parseObject(data.toString()).getString("mobile");
        }
        XpAppUserCouponTotalVo vo = xpAppUserCouponService.userCouponTotal(phone);
//        String phone ="18888888888";
//        UserResourcesDto baseUserByUid = userResourcesClient.getBaseUserByUid(uid);
//        if(baseUserByUid!=null){
//            Object data = baseUserByUid.getData();
//            phone = JSONObject.parseObject(data.toString()).getString("mobile");
//        }
        XpAppUserCouponTotalVo vo = xpAppUserCouponService.userCouponTotal(uid);
        return R.ok(vo);
    }
@@ -206,7 +206,8 @@
    @PostMapping("/api/v1/appUserCoupon/send")
    @ApiOperation(value = "发放优惠券", tags = {"管理后台-发放优惠券"})
    public R<String> send(@RequestBody SendCouponDto dto) {
        return xpAppUserCouponService.send(dto);
        xpAppUserCouponService.send(dto);
        return R.ok();
    }
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/mapper/XpAppUserCouponMapper.java
@@ -17,6 +17,6 @@
 */
public interface XpAppUserCouponMapper extends BaseMapper<XpAppUserCoupon> {
    Page<XpAppUserCouponListVo> userCouponList(@Param("page") Page<XpAppUserCouponListVo> page, @Param("query") XpUserCouponListQuery query, @Param("phone") String phone);
    Page<XpAppUserCouponListVo> userCouponList(@Param("page") Page<XpAppUserCouponListVo> page, @Param("query") XpUserCouponListQuery query, @Param("uid") String uid);
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IXpAppUserCouponService.java
@@ -1,17 +1,16 @@
package com.xiaopeng.account.service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.account.model.dto.ReceiveCouponDto;
import com.xiaopeng.account.model.dto.SendCouponDto;
import com.xiaopeng.account.model.query.XpUserCouponListQuery;
import com.xiaopeng.account.model.vo.XpAppUserCouponListVo;
import com.xiaopeng.account.model.vo.XpAppUserCouponTotalVo;
import com.xiaopeng.account.model.vo.XpAppUserCouponVo;
import com.xiaopeng.api.model.account.XpAppUserCoupon;
import com.xiaopeng.common.core.domain.R;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
 * <p>
@@ -26,17 +25,17 @@
    /**
     * 获取用户优惠券列表
     * @param query
     * @param phone
     * @param uid
     * @return
     */
    XpAppUserCouponVo userCouponList(XpUserCouponListQuery query, String phone);
    XpAppUserCouponVo userCouponList(XpUserCouponListQuery query, String uid);
    /**+
     * 获取用户优惠券数量total
     * @param phone
     * @param uid
     * @return
     */
    XpAppUserCouponTotalVo userCouponTotal(String phone);
    XpAppUserCouponTotalVo userCouponTotal(String uid);
    /**
     * 领取优惠券
@@ -56,9 +55,10 @@
    /**
     * 发送优惠券
     *
     * @param dto
     * @return
     */
    R<String> send(SendCouponDto dto);
   R<String> send(SendCouponDto dto);
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpAppUserCouponServiceImpl.java
@@ -14,20 +14,22 @@
import com.xiaopeng.account.model.vo.XpAppUserCouponVo;
import com.xiaopeng.account.service.IXpAppUserCouponService;
import com.xiaopeng.account.util.holiday.HolidayUtil;
import com.xiaopeng.api.dto.account.UserResourcesDto;
import com.xiaopeng.api.feignClient.account.UserResourcesClient;
import com.xiaopeng.api.feignClient.operation.XpCouponClient;
import com.xiaopeng.api.feignClient.operation.XpWhiteListClient;
import com.xiaopeng.api.model.account.XpAppUserCoupon;
import com.xiaopeng.api.model.operation.XpCoupon;
import com.xiaopeng.api.model.operation.XpWhitelist;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.utils.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
 * <p>
@@ -49,16 +51,20 @@
    @Autowired
    private XpWhiteListClient xpWhiteListClient;
    @Autowired
    private UserResourcesClient userResourcesClient;
    /**
     * 获取用户优惠券列表
     * @param query
     * @param phone
     * @param uid
     * @return
     */
    @Override
    public XpAppUserCouponVo userCouponList(XpUserCouponListQuery query, String phone) {
    public XpAppUserCouponVo userCouponList(XpUserCouponListQuery query, String uid) {
        Page<XpAppUserCouponListVo> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<XpAppUserCouponListVo> list = baseMapper.userCouponList(page, query, phone);
        Page<XpAppUserCouponListVo> list = baseMapper.userCouponList(page, query, uid);
        XpAppUserCouponVo vo = new XpAppUserCouponVo();
        vo.setTotal((int) page.getTotal());
        vo.setList(list.getRecords());
@@ -67,12 +73,12 @@
    /**
     * 获取用户优惠券数量total
     * @param phone
     * @param uid
     * @return
     */
    @Override
    public XpAppUserCouponTotalVo userCouponTotal(String phone) {
        List<XpAppUserCoupon> couponList = baseMapper.selectList(new LambdaQueryWrapper<XpAppUserCoupon>().eq(XpAppUserCoupon::getPhone, phone));
    public XpAppUserCouponTotalVo userCouponTotal(String uid) {
        List<XpAppUserCoupon> couponList = baseMapper.selectList(new LambdaQueryWrapper<XpAppUserCoupon>().eq(XpAppUserCoupon::getAppUserId, uid));
        XpAppUserCouponTotalVo vo = new XpAppUserCouponTotalVo();
        vo.setAvailableNum((int) couponList.stream().filter(e -> e.getStatus() == 1).count());
        vo.setUsedNum((int) couponList.stream().filter(e -> e.getStatus() == 2).count());
@@ -89,7 +95,7 @@
    @Override
    public boolean receive(ReceiveCouponDto dto, String uid) {
        XpAppUserCoupon coupon = baseMapper.selectById(dto.getCouponId());
        if(coupon.getAppUserId().toString().equals(uid)){
        if (coupon.getAppUserId().toString().equals(uid)) {
            coupon.setStatus(1);
            return updateById(coupon);
@@ -104,12 +110,12 @@
     */
    @Override
    public List<XpAppUserCoupon> timeRule(List<XpAppUserCoupon> couponList) {
       List<XpAppUserCoupon> xpAppUserCoupons = new ArrayList<>();
        List<XpAppUserCoupon> xpAppUserCoupons = new ArrayList<>();
        for (XpAppUserCoupon coupon : couponList) {
            String timeJson = coupon.getTimeJson();
            Boolean inOperationTime = isInOperationTime(timeJson);
            if(inOperationTime){
            if (inOperationTime) {
                xpAppUserCoupons.add(coupon);
            }
        }
@@ -119,38 +125,61 @@
    /**
     * 发送优惠券
     *
     * @param dto
     * @return
     */
    @Override
    @Async("couponSendExecutor")
    public R<String> send(SendCouponDto dto) {
        R<XpCoupon> coupon = xpCouponClient.getCouponById(dto.getCouponId());
        if(coupon!=null){
        if (coupon != null) {
            XpCoupon xpCoupon = coupon.getData();
            if(dto.getPhone()==null){
            if (dto.getPhone() == null) {
                // 全部发放
                R<List<String>> allWhiteList = xpWhiteListClient.getAllWhiteList();
                if(allWhiteList!=null){
                if (allWhiteList != null) {
                    List<String> phoneList = allWhiteList.getData();
                    dto.setPhone(phoneList);
                }
            }
            for (String phone : dto.getPhone()) {
                XpAppUserCoupon xpAppUserCoupon = new XpAppUserCoupon();
                xpAppUserCoupon.setFullMoney(xpCoupon.getConditionalAmount());
                xpAppUserCoupon.setMoney(xpCoupon.getAmount());
                xpAppUserCoupon.setCouponId(dto.getCouponId());
                UserResourcesDto userByMobile = userResourcesClient.getUserByMobile(phone);
                if (userByMobile != null) {
                    Long uid = JSONObject.parseObject(userByMobile.getData().toString()).getLong("uid");
                    XpAppUserCoupon xpAppUserCoupon = new XpAppUserCoupon();
                    xpAppUserCoupon.setFullMoney(xpCoupon.getConditionalAmount());
                    xpAppUserCoupon.setMoney(xpCoupon.getAmount());
                    xpAppUserCoupon.setCouponId(dto.getCouponId());
                    xpAppUserCoupon.setAppUserId(uid);
                    xpAppUserCoupon.setExpirationTime(LocalDateTime.now().plusDays(100));
                    xpAppUserCoupon.setStatus(0);
                    xpAppUserCoupon.setCouponType(xpCoupon.getCouponType());
                    xpAppUserCoupon.setPhone(phone);
                xpAppUserCoupon.setExpirationTime(LocalDateTime.now().plusDays(100));
                xpAppUserCoupon.setStatus(0);
                xpAppUserCoupon.setCouponType(xpCoupon.getCouponType());
                xpAppUserCoupon.setPhone( phone);
                    xpAppUserCoupon.setCouponName(xpCoupon.getCouponName());
                    xpAppUserCoupon.setOpenCityId("0");
                    xpAppUserCoupon.setTimeJson("[{\"time\": [\"00:00-23:59\"], \"type\": 3, \"typeStr\": 0}]");
                    baseMapper.insert(xpAppUserCoupon);
                }else {
                    Long uid = 1l;
                    XpAppUserCoupon xpAppUserCoupon = new XpAppUserCoupon();
                    xpAppUserCoupon.setFullMoney(xpCoupon.getConditionalAmount());
                    xpAppUserCoupon.setMoney(xpCoupon.getAmount());
                    xpAppUserCoupon.setCouponId(dto.getCouponId());
                    xpAppUserCoupon.setAppUserId(uid);
                    xpAppUserCoupon.setExpirationTime(LocalDateTime.now().plusDays(100));
                    xpAppUserCoupon.setStatus(0);
                    xpAppUserCoupon.setCouponType(xpCoupon.getCouponType());
                    xpAppUserCoupon.setPhone(phone);
                xpAppUserCoupon.setCouponName(xpCoupon.getCouponName());
                xpAppUserCoupon.setOpenCityId("0");
                xpAppUserCoupon.setTimeJson("[{\"time\": [\"00:00-23:59\"], \"type\": 3, \"typeStr\": 0}]");
                baseMapper.insert(xpAppUserCoupon);
                    xpAppUserCoupon.setCouponName(xpCoupon.getCouponName());
                    xpAppUserCoupon.setOpenCityId("0");
                    xpAppUserCoupon.setTimeJson("[{\"time\": [\"00:00-23:59\"], \"type\": 3, \"typeStr\": 0}]");
                    baseMapper.insert(xpAppUserCoupon);
                }
            }
        }
@@ -167,9 +196,9 @@
        JSONArray jsonArray = JSONArray.parseArray(timeJson);
        Integer holidayToday = holidayUtil.isHolidayToday();
        for (Object o : jsonArray) {
            JSONObject jsonObject =JSONObject.parseObject(o.toString());
            JSONObject jsonObject = JSONObject.parseObject(o.toString());
            String type = jsonObject.getString("type");
            if(type.equals(holidayToday.toString())){
            if (type.equals(holidayToday.toString())) {
                JSONArray time = jsonObject.getJSONArray("time");
                // 判断当前时间 是否在time时间段中
                for (Object object : time) {
@@ -177,17 +206,17 @@
                    String startTime = timeArray[0];
                    String endTime = timeArray[1];
                    boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
                    if(currentTimeInRange){
                    if (currentTimeInRange) {
                        return true;
                    }
                }
            }else if(type.equals("3")){
            } else if (type.equals("3")) {
                // 判断是什么类型 0每天  1-7 想起
                String typeStr = jsonObject.getString("typeStr");
                // 查看今天周几
                Integer week = DateUtils.getWeek();
                // 包含每天 或者  包含当天
                if(typeStr.contains("0") || typeStr.contains(week.toString())){
                if (typeStr.contains("0") || typeStr.contains(week.toString())) {
                    JSONArray time = jsonObject.getJSONArray("time");
                    // 判断当前时间 是否在time时间段中
                    for (Object object : time) {
@@ -195,7 +224,7 @@
                        String startTime = timeArray[0];
                        String endTime = timeArray[1];
                        boolean currentTimeInRange = DateUtils.isCurrentTimeInRange(startTime, endTime);
                        if(currentTimeInRange){
                        if (currentTimeInRange) {
                            return true;
                        }
                    }
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpAppUserCouponMapper.xml
@@ -23,7 +23,7 @@
        else status
        end as `status`
        FROM xp_app_user_coupon
        WHERE phone = #{phone}
        WHERE app_user_id = #{uid}
        ) as t
        where 1=1
        <if test="query.status != null">
xp-robotaxi-account-boot/src/main/resources/mapper/account/XpQualificationAuditMapper.xml
@@ -14,7 +14,7 @@
        from xp_qualification_audit xqa
        left join xp_operations_user xou on xqa.operations_user_id = xou.id
        left join xp_operations_role xor on xou.id = xor.operations_user_id
        <where>
        where xqa.is_deleted = 0
            <if test="query.nickName != null and query.nickName != ''">
                and xou.nick_name like concat('%',#{query.nickName},'%')
            </if>
@@ -27,8 +27,6 @@
            <if test="query.auditStatus != null">
                and xqa.audit_status = #{query.auditStatus}
            </if>
            AND xqa.is_deleted = 0
        </where>
        order by xqa.create_time desc
    </select>
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/account/XpAppUserCoupon.java
@@ -31,7 +31,7 @@
    private static final long serialVersionUID = 1L;
    @TableId(value = "id", type = IdType.NONE)
    @TableId(value = "id", type = IdType.ASSIGN_ID)
    private Long id;
    @ApiModelProperty(value = "满减金额")
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/maintenance/XpVehicleDetection.java
@@ -6,6 +6,7 @@
import java.time.LocalDateTime;
import java.io.Serializable;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.xiaopeng.common.core.web.domain.BaseModel;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -91,6 +92,7 @@
    private Long operationsUserId;
    @ApiModelProperty(value = "检测时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private LocalDateTime checkTime;
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -426,7 +426,7 @@
            LonLatDto origin = new LonLatDto();
            if (orderId.contains("XU")) {
                orderType = OrderType.CRUISE_ORDER;
                // todo 下发巡游单的导航数据
                R<XpCruiseOrder> cruiseOrder = xpCruiseOrderClient.getCruiseOrder(orderId);
                XpCruiseOrder xpCruiseOrder = cruiseOrder.getData();
@@ -534,7 +534,7 @@
        Long vehicleId = null;
        String orderType = "";
        if (orderId.contains("XU")) {
            // todo 下发巡游单的导航数据
            orderType = OrderType.CRUISE_ORDER;
            //巡游单
            if (orderPhase.equals(OrderPhase.ROUTE_TO_CRUISE)) {
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleOperationsController.java
@@ -75,7 +75,13 @@
        // 发车
        if(dto.getDepartureStatus()==1){
            // 找车辆的任务  生成巡游单子 下发命令 TODO
            // 找车辆的任务  生成巡游单子 下发命令 TODO v
        }else if(dto.getDepartureStatus()==3){
            // 收车 关闭当前巡游单子 生成新的返程单子  找到收车站点
            xpCruiseOrderClient.updateCruiseOrder(xpVehicle.getVehicleVin());
@@ -90,10 +96,13 @@
            xpCruiseOrder.setOrderType(2);
            xpCruiseOrder.setStartLon(x);
            xpCruiseOrder.setStartLat(y);
            // TODO 找到收车站点
            // TODO v 找到收车站点
            xpCruiseOrder.setStatus(1);
            xpCruiseOrderClient.addCruiseOrder(xpCruiseOrder);
            // 下发命令
            orderMissionClient.pushOrder(new PushOrderDto( xpCruiseOrder.getVehicleVin(),xpCruiseOrder.getId(),null));
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpChargingRecordServiceImpl.java
@@ -202,7 +202,6 @@
        // 查询车辆当前充电信息
        XpChargingRecord xpChargingRecord = this.getOne(new LambdaQueryWrapper<XpChargingRecord>()
                .eq(XpChargingRecord::getVehicleId, vehicleId)
                .isNull(XpChargingRecord::getEndRemainingBattery)
                .isNull(XpChargingRecord::getTaskId)
                .orderByDesc(XpChargingRecord::getCreateTime)
                .last("LIMIT 1"));
xp-robotaxi-maintenance-boot/src/main/resources/mapper/maintenance/XpShiftMapper.xml
@@ -6,6 +6,7 @@
        select id, shift_name, shift_color, start_time, end_time, is_rest,
       rest_start_time, rest_end_time, create_by, create_time, update_by, update_time, is_deleted
        from xp_shift
        where is_deleted = 0
        order by create_time desc
    </select>
</mapper>
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpCouponController.java
@@ -8,12 +8,9 @@
import com.xiaopeng.operation.service.IXpCouponService;
import com.xiaopeng.operation.vo.XpBannerListVo;
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.*;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;
@@ -25,7 +22,7 @@
 * @author mitao
 * @since 2026-02-03
 */
@Controller
@RestController
@RequestMapping("")
public class XpCouponController {
@@ -47,7 +44,7 @@
     * 优惠券列表
     */
    @PostMapping("/v1/api/xp-coupon/list")
    @ApiOperation(value = "优惠券列表",tags = {"管理后台-优惠券列表"},response = XpCoupon.class)
    @ApiOperation(value = "优惠券列表",tags = {"管理后台-优惠券"},response = XpCoupon.class)
    public R<Page<XpCoupon>> list(@RequestBody XpCouponListQuery query ){
        return R.ok(xpCouponService.getList(query));
    }
@@ -61,7 +58,7 @@
     * @return
     */
    @PostMapping("/v1/api/xp-coupon/add")
    @ApiOperation(value = "添加优惠券",tags = {"管理后台-添加优惠券"},response = XpCoupon.class)
    @ApiOperation(value = "添加优惠券",tags = {"管理后台-优惠券"},response = XpCoupon.class)
    public R<?> add(@RequestBody XpCoupon xpCoupon){
        xpCouponService.save(xpCoupon);
        return R.ok();
xp-robotaxi-push-message-boot/src/main/java/com/xiaopeng/pushMessage/utils/AliPushUtil.java
New file
@@ -0,0 +1,160 @@
package com.xiaopeng.pushMessage.utils;
import com.aliyun.auth.credentials.Credential;
import com.aliyun.auth.credentials.provider.StaticCredentialProvider;
import com.aliyun.sdk.service.push20160801.models.*;
import com.aliyun.sdk.service.push20160801.*;
import com.google.gson.Gson;
import darabonba.core.client.ClientOverrideConfiguration;
import org.springframework.beans.factory.annotation.Value;
//import javax.net.ssl.KeyManager;
//import javax.net.ssl.X509TrustManager;
import java.util.concurrent.CompletableFuture;
public class AliPushUtil {
    @Value("${ali.push.accessKeyId}")
    private String accessKeyId;
    @Value("${ali.push.accessKeySecret}")
    private String accessKeySecret;
    @Value("${ali.push.appKey}")
    private Long appKey;
    @Value("${ali.push.regionId}")
    private String regionId;
    /**
     * 消息类型  MESSAGE 消息  NOTICE  通知
     */
    private final String PUSH_TYPE = "MESSAGE";
    /**
     * 设备类型 ALL 全部 HARMONY 鸿蒙  IOS ios设备 ANDROID 安卓设备
     */
    private final String DEVICE_TYPE_ALL = "ALL";
    private final String DEVICE_TYPE_HARMONY = "HARMONY";
    private final String DEVICE_TYPE_IOS = "IOS";
    private final String DEVICE_TYPE_ANDROID = "ANDROID";
    /**
     * 推送目标
     * DEVICE:根据设备推送。
     * ACCOUNT:根据账号推送。
     * ALIAS:根据别名推送。
     * TAG:根据标签推送。
     * ALL:推送给全部设备(同一种 DeviceType 的两次全推的间隔至少为 1 秒)。
     */
    private final String TARGET = "ACCOUNT";
    /**
     *
     * @param account 运维手机号
     * @param title 标题
     * @param body 消息内容
     * @throws Exception
     */
    public void push(String account, String title, String body) throws Exception {
        StaticCredentialProvider credentialProvider = StaticCredentialProvider.create(
                Credential.builder()
                        .accessKeyId(accessKeyId)
                        .accessKeySecret(accessKeySecret)
                        .build()
        );
        // Configure the Client
        try (AsyncClient client = AsyncClient.builder()
                .region(regionId) // Region ID
                .credentialsProvider(credentialProvider)
                .overrideConfiguration(
                    ClientOverrideConfiguration.create()
                    .setEndpointOverride("cloudpush.aliyuncs.com")
                )
                .build()) {
            // Parameter settings for API request
            PushRequest pushRequest = PushRequest.builder()
                    .appKey(appKey)
                    .pushType(PUSH_TYPE)
                    .deviceType(DEVICE_TYPE_ALL)
                    .target(TARGET)
                    .targetValue(account)
                    .title(title)
                    .body(body)
                    .build();
            CompletableFuture<PushResponse> response = client.push(pushRequest);
            PushResponse resp = response.get();
            System.out.println(new Gson().toJson(resp));
        }
    }
    public static void main(String[] args) throws Exception {
        // HttpClient Configuration
        /*HttpClient httpClient = new ApacheAsyncHttpClientBuilder()
                .connectionTimeout(Duration.ofSeconds(10)) // Set the connection timeout time, the default is 10 seconds
                .responseTimeout(Duration.ofSeconds(10)) // Set the response timeout time, the default is 20 seconds
                .maxConnections(128) // Set the connection pool size
                .maxIdleTimeOut(Duration.ofSeconds(50)) // Set the connection pool timeout, the default is 30 seconds
                // Configure the proxy
                .proxy(new ProxyOptions(ProxyOptions.Type.HTTP, new InetSocketAddress("<your-proxy-hostname>", 9001))
                        .setCredentials("<your-proxy-username>", "<your-proxy-password>"))
                // If it is an https connection, you need to configure the certificate, or ignore the certificate(.ignoreSSL(true))
                .x509TrustManagers(new X509TrustManager[]{})
                .keyManagers(new KeyManager[]{})
                .ignoreSSL(false)
                .build();*/
        // Configure Credentials authentication information
        StaticCredentialProvider credentialProvider = StaticCredentialProvider.create(
                Credential.builder()
                        .accessKeyId("LTAI5tRNNQCCPn6Hc42RJYLj")
                        .accessKeySecret("5b9sMu7b5Ab87e3Oa1qujQsBXwvjFx")
                        .build()
        );
        // Configure the Client
        try (AsyncClient client = AsyncClient.builder()
                .region("cn-hangzhou") // Region ID
                //.httpClient(httpClient) // Use the configured HttpClient, otherwise use the default HttpClient (Apache HttpClient)
                .credentialsProvider(credentialProvider)
                //.serviceConfiguration(Configuration.create()) // Service-level configuration
                // Client-level configuration rewrite, can set Endpoint, Http request parameters, etc.
                .overrideConfiguration(
                        ClientOverrideConfiguration.create()
                                // Endpoint 请参考 https://api.aliyun.com/product/Push
                                .setEndpointOverride("cloudpush.aliyuncs.com")
                        //.setConnectTimeout(Duration.ofSeconds(30))
                )
                .build()) {
            // Parameter settings for API request
            PushRequest pushRequest = PushRequest.builder()
                    .appKey(335666344L)
                    .pushType("MESSAGE")
                    .deviceType("ALL")
                    .target("ACCOUNT")
                    .targetValue("account1")
                    .title("消息通知")
                    .body("测试")
                    // Request-level configuration rewrite, can set Http request parameters, etc.
                    // .requestConfiguration(RequestConfiguration.create().setHttpHeaders(new HttpHeaders()))
                    .build();
            // Asynchronously get the return value of the API request
            CompletableFuture<PushResponse> response = client.push(pushRequest);
            // Synchronously get the return value of the API request
            PushResponse resp = response.get();
            System.out.println(new Gson().toJson(resp));
            // Asynchronous processing of return values
            /*response.thenAccept(resp -> {
                System.out.println(new Gson().toJson(resp));
            }).exceptionally(throwable -> { // Handling exceptions
                System.out.println(throwable.getMessage());
                return null;
            });*/
        }
    }
}