xuhy
2026-03-13 606841e8477fe937e7d8afa9f30d5f633887eca2
Merge remote-tracking branch 'origin/master'

# Conflicts:
# xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java
1个文件已添加
36个文件已修改
906 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointAddDto.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointUpdateDto.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/XpOperationUserClient.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/maintenance/VehicleCleanQuery.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/operation/ElectronicPageListQuery.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/pom.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/SecurityConstants.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/context/SecurityContextHolder.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/utils/JwtUtils.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthLogic.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthUtil.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/interceptor/HeaderInterceptor.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/service/TokenService.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/utils/SecurityUtils.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/filter/AuthFilter.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleCleanController.java 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/XpVehicleRepairReturnDTO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/resources/mapper/XpElectronicFenceMapper.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpElectronicFenceMapper.xml 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java 96 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/OrderCancelJob.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 336 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaskOrderCancelUtil.java 62 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-push-message-boot/pom.xml 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/DataUpdateHandlerConfig.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointAddDto.java
@@ -18,6 +18,9 @@
public class PointAddDto implements Serializable {
    @ApiModelProperty(value = "电子围栏区域id")
    private Long electronicAreaId;
    @ApiModelProperty(value = "电子围栏id")
    private String fenceId;
    @ApiModelProperty(value = "点位名称")
    @NotEmpty(message = "点位名称不能为空")
    private String pointName;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/operation/PointUpdateDto.java
@@ -17,6 +17,10 @@
    private Long id;
    @ApiModelProperty(value = "电子围栏区域id")
    private Long electronicAreaId;
    @ApiModelProperty(value = "围栏id")
    private String fenceId;
    @ApiModelProperty(value = "点位名称")
    @NotBlank(message = "点位名称不能为空")
xp-robotaxi-api/src/main/java/com/xiaopeng/api/feignClient/account/XpOperationUserClient.java
@@ -2,6 +2,7 @@
import com.xiaopeng.api.dto.account.XpOperationsUserQueryDTO;
import com.xiaopeng.api.factory.account.XpAppUserClientFallbackFactory;
import com.xiaopeng.api.factory.account.XpOperationUserClientFallbackFactory;
import com.xiaopeng.api.model.account.XpOperationsRole;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.vo.account.XpOperationsUserWithRoleVO;
@@ -23,7 +24,7 @@
 */
@FeignClient(contextId = "XpOperationUserClient",
        value = ServiceNameConstantsEnum.XP_ACCOUNT_SERVICE,
        fallbackFactory = XpAppUserClientFallbackFactory.class)
        fallbackFactory = XpOperationUserClientFallbackFactory.class)
public interface XpOperationUserClient {
    /**
     * 根据ID列表批量查询运维用户信息
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/maintenance/VehicleCleanQuery.java
@@ -10,4 +10,13 @@
public class VehicleCleanQuery extends BasePage {
    @ApiModelProperty(value = "车辆ID")
    private Long vehicleId;
    @ApiModelProperty(value = "开始时间")
    private String startTime;
    @ApiModelProperty(value = "结束时间")
    private String endTime;
    @ApiModelProperty(value = "操作人")
    private String operationUserName;
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/query/operation/ElectronicPageListQuery.java
@@ -33,7 +33,7 @@
    @ApiModelProperty(value = "更新结束时间")
    private String updateEndTime;
    @ApiModelProperty(value = "开始时间 1正序 2倒序")
    private String createSort;
    private Integer createSort;
    @ApiModelProperty(value = "更新时间 1正序 2倒序")
    private String updateSort;
    private Integer updateSort;
}
xp-robotaxi-automatic-pilot-boot/pom.xml
@@ -143,16 +143,6 @@
    <build>
        <finalName>${project.artifactId}</finalName>
        <plugins>
<!--            <plugin>-->
<!--                <groupId>org.apache.maven.plugins</groupId>-->
<!--                <artifactId>maven-surefire-plugin</artifactId>-->
<!--                <configuration>-->
<!--                    <argLine>-->
<!--                        &#45;&#45;add-opens java.base/java.lang=ALL-UNNAMED-->
<!--                        &#45;&#45;add-opens java.base/java.util=ALL-UNNAMED-->
<!--                    </argLine>-->
<!--                </configuration>-->
<!--            </plugin>-->
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
xp-robotaxi-automatic-pilot-boot/src/main/java/com/xiaopeng/automaticPilot/service/KafkaConsumerService.java
@@ -837,7 +837,6 @@
                    //下车完成
                    buildPushOrderStatus(orderId, OrderStatusEnum.APPROVAL_REJECTION, sequence);
                    xpOrderClient.updateOrderStatus(Long.parseLong(orderId.contains("XU") ? orderId.substring(2) : orderId), OrderStatusEnum.APPROVAL_REJECTION.getCode());
                    // 下发巡游任务
                    R<XpOrder> xpOrderR = xpOrderClient.queryOrderById(Long.parseLong(orderId));
                    if(xpOrderR.getCode()==200){
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java
@@ -10,7 +10,7 @@
    /**
     * 缓存有效期,默认720(分钟)
     */
    public final static long EXPIRATION = 720;
    public final static long EXPIRATION = 720 * 2; //24小时
    public final static long EXPIRATION_APPLET = 365 * 24 * 60;
    /**
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/SecurityConstants.java
@@ -42,7 +42,7 @@
    public static final String OPERATION_USER_KEY = "operation_user_key";
    /**
     * 用户类型(system/applet)
     * 用户类型(system/operation)
     */
    public static final String USER_TYPE = "user_type";
    /**
@@ -59,4 +59,9 @@
     * 角色权限
     */
    public static final String ROLE_PERMISSION = "role_permission";
    /**
     * 登录运维人员
     */
    public static final String LOGIN_OPERATION_USER = "login_oeeration_user";
}
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/context/SecurityContextHolder.java
@@ -76,11 +76,20 @@
        return get(SecurityConstants.USER_KEY);
    }
    public static String getOperationUserKey()
    {
        return get(SecurityConstants.OPERATION_USER_KEY);
    }
    public static void setUserKey(String userKey)
    {
        set(SecurityConstants.USER_KEY, userKey);
    }
    public static void setOperationUserKey(String userKey)
    {
        set(SecurityConstants.OPERATION_USER_KEY, userKey);
    }
    public static String getPermission()
    {
        return get(SecurityConstants.ROLE_PERMISSION);
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/utils/JwtUtils.java
@@ -73,6 +73,17 @@
    {
        return getValue(claims, SecurityConstants.USER_KEY);
    }
    /**
     * 根据令牌获取运维用户标识
     *
     * @param claims 身份信息
     * @return 用户ID
     */
    public static String getOperationUserKey(Claims claims)
    {
        return getValue(claims, SecurityConstants.OPERATION_USER_KEY);
    }
    
    /**
     * 根据令牌获取用户类型
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthLogic.java
@@ -4,6 +4,7 @@
import java.util.HashSet;
import java.util.Set;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.common.core.utils.JwtUtils;
import com.xiaopeng.api.vo.account.LoginUser;
import io.jsonwebtoken.Claims;
@@ -106,6 +107,16 @@
    }
    /**
     * 获取当前运维用户缓存信息, 如果未登录,则抛出异常
     *
     * @param token 前端传递的认证信息
     * @return 用户缓存信息
     */
    public LoginOperationUser getOperationLoginUser(String token)
    {
        return tokenService.getLoginOperationUser(token);
    }
    /**
     * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存
     * 
     * @param loginUser 当前用户信息
@@ -116,6 +127,16 @@
    }
    /**
     * 验证当前用户有效期, 如果相差不足120分钟,自动刷新缓存
     *
     * @param loginOperationUser 当前用户信息
     */
    public void verifyOperationLoginUserExpire(LoginOperationUser loginOperationUser)
    {
        tokenService.verifyToken(loginOperationUser);
    }
    /**
     * 验证用户是否具备某权限
     * 
     * @param permission 权限字符串
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/auth/AuthUtil.java
@@ -1,5 +1,6 @@
package com.xiaopeng.common.security.auth;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.common.security.annotation.RequiresPermissions;
import com.xiaopeng.common.security.annotation.RequiresRoles;
import com.xiaopeng.api.vo.account.LoginUser;
@@ -54,6 +55,17 @@
    }
    /**
     * 获取当前登录用户信息
     *
     * @param token 指定token
     * @return 用户信息
     */
    public static LoginOperationUser getOperationLoginUser(String token)
    {
        return authLogic.getOperationLoginUser(token);
    }
    /**
     * 验证当前用户有效期
     * 
     * @param loginUser 用户信息
@@ -62,7 +74,15 @@
    {
        authLogic.verifyLoginUserExpire(loginUser);
    }
    /**
     * 验证当前用户有效期
     *
     * @param loginOperationUser 用户信息
     */
    public static void verifyOperationLoginUserExpire(LoginOperationUser loginOperationUser)
    {
        authLogic.verifyOperationLoginUserExpire(loginOperationUser);
    }
    /**
     * 当前账号是否含有指定角色标识, 返回true或false
     * 
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/interceptor/HeaderInterceptor.java
@@ -3,7 +3,10 @@
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.api.vo.account.LoginUser;
import com.xiaopeng.common.core.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.AsyncHandlerInterceptor;
import com.xiaopeng.common.core.constant.SecurityConstants;
@@ -32,15 +35,27 @@
        SecurityContextHolder.setUserId(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USER_ID));
        SecurityContextHolder.setUserName(ServletUtils.getHeader(request, SecurityConstants.DETAILS_USERNAME));
        SecurityContextHolder.setUserKey(ServletUtils.getHeader(request, SecurityConstants.USER_KEY));
        SecurityContextHolder.setOperationUserKey(ServletUtils.getHeader(request, SecurityConstants.OPERATION_USER_KEY));
        String token = SecurityUtils.getToken();
        if (StringUtils.isNotEmpty(token))
        {
            LoginUser loginUser = AuthUtil.getLoginUser(token);
            if (StringUtils.isNotNull(loginUser))
            {
                AuthUtil.verifyLoginUserExpire(loginUser);
                SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser);
            String userType = JwtUtils.getUserType(token);
            if ("system".equals(userType)) {
                LoginUser loginUser = AuthUtil.getLoginUser(token);
                if (StringUtils.isNotNull(loginUser))
                {
                    AuthUtil.verifyLoginUserExpire(loginUser);
                    SecurityContextHolder.set(SecurityConstants.LOGIN_USER, loginUser);
                }
            }
            if ("operation".equals(userType)) {
                LoginOperationUser operationLoginUser = AuthUtil.getOperationLoginUser(token);
                if (StringUtils.isNotNull(operationLoginUser))
                {
                    AuthUtil.verifyOperationLoginUserExpire(operationLoginUser);
                    SecurityContextHolder.set(SecurityConstants.LOGIN_OPERATION_USER, operationLoginUser);
                }
            }
        }
        return true;
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/service/TokenService.java
@@ -207,6 +207,19 @@
            refreshToken(loginUser);
        }
    }
    /**
     * 验证令牌有效期,相差不足120分钟,自动刷新缓存
     *
     * @param loginOperationUser
     */
    public void verifyToken(LoginOperationUser loginOperationUser) {
        long expireTime = loginOperationUser.getExpireTime();
        long currentTime = System.currentTimeMillis();
        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
            refreshTokenOperationUser(loginOperationUser);
        }
    }
    
    /**
     * 刷新令牌有效期
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/utils/SecurityUtils.java
@@ -2,6 +2,7 @@
import javax.servlet.http.HttpServletRequest;
import com.xiaopeng.api.vo.account.LoginOperationUser;
import com.xiaopeng.api.vo.account.LoginUser;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import com.xiaopeng.common.core.constant.SecurityConstants;
@@ -50,6 +51,13 @@
    }
    /**
     * 获取登录运维人员信息
     */
    public static LoginOperationUser getLoginOperationUser()
    {
        return SecurityContextHolder.get(SecurityConstants.LOGIN_OPERATION_USER, LoginOperationUser.class);
    }
    /**
     * 获取请求token
     */
    public static String getToken()
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/filter/AuthFilter.java
@@ -66,18 +66,37 @@
        }catch (Exception e){
            return unauthorizedResponse(exchange, e.getMessage());
        }
        String token = getToken(request);
        Claims claims = JwtUtils.parseToken(token);
        String userkey = JwtUtils.getUserKey(claims);
        String userid = JwtUtils.getUserId(claims);
        String username = JwtUtils.getUserName(claims);
        String userType = JwtUtils.getUserType(claims);
        String operationUserKey = JwtUtils.getOperationUserKey(claims);
        String redisKey = "";
        if ("system".equals(userType)) {
            redisKey = StringUtils.isNotBlank(userkey) ? getTokenKey(userkey) : "";
        }
        if ("operation".equals(userType)) {
            redisKey = StringUtils.isNotBlank(operationUserKey) ? getTokenKey(operationUserKey) : "";
        }
        if (StringUtils.isBlank(redisKey)) {
            return unauthorizedResponse(exchange, "登录状态已过期");
        }
        boolean islogin = redisService.hasKey(redisKey);
        if (!islogin)
        {
            return unauthorizedResponse(exchange, "登录状态已过期");
        }
        // 设置用户信息到请求
        addHeader(mutate, SecurityConstants.USER_KEY, userkey);
        addHeader(mutate, SecurityConstants.DETAILS_USER_ID, userid);
        addHeader(mutate, SecurityConstants.DETAILS_USERNAME, username);
        addHeader(mutate, SecurityConstants.USER_TYPE, userType);
        addHeader(mutate, SecurityConstants.OPERATION_USER_KEY, operationUserKey);
        // 内部请求来源参数清除
        removeHeader(mutate, SecurityConstants.FROM_SOURCE);
        return chain.filter(exchange.mutate().request(mutate.build()).build());
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java
@@ -9,4 +9,5 @@
    String TASK_NOT_EXIST = "task.not.exist";
    String VEHICLE_NOT_EXIST = "vehicle.not.exist";
    String REPAIR_MONEY_TOO_LONG = "repair.money.too.long";
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleCleanController.java
@@ -4,6 +4,7 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
import com.xiaopeng.api.model.account.XpOperationsUser;
import com.xiaopeng.api.model.maintenance.XpVehicleClean;
import com.xiaopeng.api.query.maintenance.VehicleCleanQuery;
import com.xiaopeng.common.core.domain.R;
@@ -22,6 +23,9 @@
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import java.util.List;
import java.util.stream.Collectors;
/**
 * <p>
@@ -84,7 +88,40 @@
    @PostMapping("/api/v1/vehicleClean/list")
    public R<PageInfo<XpVehicleClean>> list(@RequestBody VehicleCleanQuery query) {
        PageInfo<XpVehicleClean> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        PageInfo<XpVehicleClean> page = xpVehicleCleanService.page(pageInfo, new LambdaQueryWrapper<XpVehicleClean>().eq(XpVehicleClean::getVehicleId, query.getVehicleId()).orderByDesc(BaseModel::getCreateTime));
        LambdaQueryWrapper<XpVehicleClean> wrapper = new LambdaQueryWrapper<XpVehicleClean>().eq(XpVehicleClean::getVehicleId, query.getVehicleId());
        List<XpOperationsUser> data=null;
        if(query.getOperationUserName()!=null && !query.getOperationUserName().isEmpty()){
            R<List<XpOperationsUser>> r = xpOperationUserClient.listByName(query.getOperationUserName());
            if(r.getCode()!=200 || r.getData().isEmpty()){
                return R.ok(pageInfo);
            }
            data = r.getData();
            wrapper.in(XpVehicleClean::getOperationsUserId, data.stream().map(XpOperationsUser::getId).collect(Collectors.toList()));
        }
        if(query.getStartTime()!=null && !query.getStartTime().isEmpty() && query.getEndTime()!=null && !query.getEndTime().isEmpty()){
            wrapper.between(XpVehicleClean::getCreateTime, query.getStartTime(), query.getEndTime());
        }
        PageInfo<XpVehicleClean> page = xpVehicleCleanService.page(pageInfo, wrapper.orderByDesc(BaseModel::getCreateTime));
        List<XpVehicleClean> records = page.getRecords();
        if(data==null){
            List<Long> userIds = records.stream().map(XpVehicleClean::getOperationsUserId).collect(Collectors.toList());
            if(userIds.isEmpty()){
                return R.ok(page);
            }
            R<List<XpOperationsUser>> r = xpOperationUserClient.listByIds(userIds);
            if(r.getData().isEmpty()){
                return R.ok(page);
            }
            data = r.getData();
        }
        for (XpVehicleClean record : records) {
            data.stream().filter(xpOperationsUser -> xpOperationsUser.getId().equals(record.getOperationsUserId())).findFirst().ifPresent(xpOperationsUser -> record.setCreateBy(xpOperationsUser.getNickName()));
        }
        return R.ok(page);
    }
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/controller/XpVehicleRepairController.java
@@ -3,8 +3,10 @@
import com.xiaopeng.api.model.maintenance.XpVehicleRepair;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.security.service.TokenService;
import com.xiaopeng.maintenance.constant.I18nKeyConstant;
import com.xiaopeng.maintenance.dto.XpVehicleRepairReturnDTO;
import com.xiaopeng.maintenance.dto.XpVehicleRepairStartDTO;
import com.xiaopeng.maintenance.model.query.XpVehicleRepairPageQuery;
@@ -56,6 +58,9 @@
    @PostMapping("/api/v1/vehicleRepair/saveReturnRepair")
    public R<String> saveReturnRepair(@Validated @RequestBody XpVehicleRepairReturnDTO dto) {
        Long id = tokenService.getLoginOperationUser().getId();
        if (dto.getRepairMoney().toString().length() > 200) {
            throw new ServiceException("维修费用不能超过200字符", I18nKeyConstant.REPAIR_MONEY_TOO_LONG);
        }
        xpVehicleRepairService.saveReturnRepair(dto,id);
        return R.ok();
    }
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/dto/XpVehicleRepairReturnDTO.java
@@ -5,6 +5,7 @@
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.Max;
import java.io.Serializable;
@Data
@@ -14,7 +15,6 @@
    @ApiModelProperty(value = "维修id")
    private Long id;
    @Length(max = 200, message = "维修费用长度不能超过200字")
    @ApiModelProperty(value = "维修费用")
    private Double repairMoney;
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -1,4 +1,5 @@
# 中文
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
vehicle.not.exist=车辆不存在
repair.money.too.long=维修费用不能超过200字符
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -2,4 +2,5 @@
welcome.message=Welcome to our application!
task.not.exist=The task does not exist.
vehicle.not.exist=The vehicle does not exist.
repair.money.too.long=The maintenance cost cannot exceed 200 characters
task.rule.not.config=The vehicle accident task allocation rules have not been configured
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_zh_CN.properties
@@ -2,4 +2,5 @@
welcome.message=欢迎来到我们的应用程序!
task.not.exist=任务不存在
vehicle.not.exist=车辆不存在
repair.money.too.long=维修费用不能超过200字符
task.rule.not.config=未配置车辆事故任务分配规则
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpPointManagementController.java
@@ -16,6 +16,7 @@
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.api.dto.map.XpPointExportExcelQuery;
import com.xiaopeng.map.exportExcel.XpPointExportExcel;
import com.xiaopeng.map.mangodb.service.XpGeoFencingPolygonService;
import com.xiaopeng.map.service.XpElectronicFenceAreaService;
import com.xiaopeng.map.service.XpElectronicFenceService;
import com.xiaopeng.map.service.XpPointService;
@@ -64,6 +65,8 @@
    private XpElectronicFenceAreaService xpElectronicFenceAreaService;
    @Resource
    private XpElectronicFenceService xpElectronicFenceService;
    @Resource
    private XpGeoFencingPolygonService xpGeoFencingPolygonService;
    @ApiOperation(value = "获取所有运营中的区域", response = XpElectronicFenceArea.class)
@@ -151,7 +154,10 @@
    @PostMapping("/add")
    @ResponseBody
    @ApiOperation(value = "新增点位")
    public R<XpPoint> add(@Validated @RequestBody PointAddDto pointAddDto) {
    public R<?> add(@Validated @RequestBody PointAddDto pointAddDto) {
        if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) {
            return R.ok("in_prohibited_area");
        }
        return R.ok(xpPointService.addPointWithGeneratedNumber(pointAddDto));
    }
@@ -177,8 +183,17 @@
        XpPoint xpPoint = xpPointService.getById(pointAddDto.getId());
        if (!xpPoint.getElectronicAreaId().equals(pointAddDto.getElectronicAreaId())) {
            BeanUtils.copyProperties(pointAddDto, xpPoint);
            if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) {
                return R.ok("in_prohibited_area");
            }
            xpPointService.updateById(xpPoint);
        } else {
            if (xpGeoFencingPolygonService.isInFence(pointAddDto.getPointLon(), pointAddDto.getPointLat(), pointAddDto.getFenceId(), "prohibited_area")) {
                return R.ok("in_prohibited_area");
            }
            //先删除原有的数据,因为会存在点位的从属区域变化的情况,所以先删除原有的数据后添加新的数据重新分片到新的库中
            BeanUtils.copyProperties(pointAddDto, xpPoint);
            xpPointService.removeById(pointAddDto.getId());
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -86,9 +86,6 @@
        }
        normalizeProhibitedAreaCountFilter(query);
        PageInfo<XpElectronicFence> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        if (StringUtils.isEmpty(query.getCreateSort())&& StringUtils.isEmpty(query.getUpdateSort())){
            query.setCreateSort("2");
        }
        List<XpElectronicFence> list = this.baseMapper.pageList(pageInfo, query);
        if (list.isEmpty()) {
            return new PageInfo<>();
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java
@@ -254,10 +254,10 @@
        if(routePlanRule!=null){
            params.put("strategy", routePlanRule);
        }
        log.info("高德地图接口:{}", url);
        log.info("高德地图参数:{}", params);
        String post = HttpUtils.post(url, JSON.toJSONString(params));
        System.out.println("高德地图返回结果:"+ post);
//        String forObject = restTemplate.getForObject(url, String.class, params);
        log.info("高德地图返回结果:"+ post);
        JSONObject jsonObject = JSON.parseObject(post);
        String data = jsonObject.getString("data");
xp-robotaxi-map-boot/src/main/resources/mapper/XpElectronicFenceMapper.xml
@@ -30,7 +30,7 @@
        from xp_electronic_fence ef
        left join xp_electronic_fence_area efa on efa.electronic_id = ef.id and efa.is_deleted = 0
        where ef.is_deleted = 0
        <if test="query.electronicNumberOrName != null">
        <if test="query.electronicNumberOrName != null and query.electronicNumberOrName != ''">
            and( ef.electronic_name like concat('%',#{query.electronicNumberOrName},'%')
            or ef.electronic_number like concat('%',#{query.electronicNumberOrName},'%')
            )
@@ -71,39 +71,27 @@
                having sum(case when efa.area_type = 2 then 1 else 0 end) &lt;= #{query.prohibitedAreaCountMax}
            </when>
        </choose>
        <if test="query.createSort != null and query.updateSort != null">
            order by
            <if test="query.createSort == 1">
                ef.create_time asc,
            </if>
            <if test="query.createSort == 2">
                ef.create_time desc,
            </if>
            <if test="query.updateSort == 1">
                ef.update_time asc
            </if>
            <if test="query.updateSort == 2">
                ef.update_time desc
            </if>
        </if>
        <if test="query.createSort != null">
            order by
            <if test="query.createSort == 1">
                ef.create_time asc
            </if>
            <if test="query.createSort == 2">
                ef.create_time desc
            </if>
        </if>
        <if test="query.updateSort != null">
            order by
            <if test="query.updateSort == 1">
                ef.update_time asc
            </if>
            <if test="query.updateSort == 2">
                ef.update_time desc
            </if>
        </if>
        <choose>
            <when test="query.createSort == 1 or query.createSort == 2 or query.updateSort == 1 or query.updateSort == 2">
                <trim prefix="order by" suffixOverrides=",">
                    <if test="query.createSort == 1">
                        ef.create_time asc,
                    </if>
                    <if test="query.createSort == 2">
                        ef.create_time desc,
                    </if>
                    <if test="query.updateSort == 1">
                        ef.update_time asc,
                    </if>
                    <if test="query.updateSort == 2">
                        ef.update_time desc,
                    </if>
                </trim>
            </when>
            <otherwise>
                order by ef.update_time desc
            </otherwise>
        </choose>
    </select>
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpPricingController.java
@@ -60,7 +60,7 @@
    @PostMapping("/base/v1/mini-program/navigation/route-and-fare")
    @ApiOperation(value = "导航-获取路线和费用", tags = {"小程序-获取路线和费用"}, response = RouteAndFareVo.class)
    @ApiOperation(value = "导航-获取路线和费用(弃用)", tags = {"小程序-获取路线和费用(弃用)"}, response = RouteAndFareVo.class)
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<RouteAndFareVo> getRouteAndFare(@RequestBody @Valid RouteAndFareDto routeAndFareDto, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
@@ -83,7 +83,7 @@
    @GetMapping("/base/v1/mini-program/pricing/rules/{openCityId}")
    @ApiOperation(value = "获取费用规则", tags = {"小程序-根据开通城市获取费用规则"}, response = String.class)
    @ApiOperation(value = "获取费用规则(弃用)", tags = {"小程序-根据开通城市获取费用规则(弃用)"}, response = String.class)
    public R<?> getPricingRules(@PathVariable Long openCityId) {
        XpPricing xpPricing = xpPricingService.getOne(new LambdaQueryWrapper<XpPricing>().eq(XpPricing::getCityId, openCityId).eq(XpPricing::getPricingType, 1).last("limit 1"));
        if (xpPricing != null) {
@@ -99,7 +99,7 @@
     * @return
     */
    @PostMapping("/base/v1/mini-program/pricing/getWaitTime")
    @ApiOperation(value = "获取等待时间", tags = {"小程序-获取等待时间"}, response = Integer.class)
    @ApiOperation(value = "获取等待时间(弃用)", tags = {"小程序-获取等待时间(弃用)"}, response = Integer.class)
    public R<Integer> getWaitTime(@RequestBody LonLatDto dto) {
        return R.ok(xpPricingService.getWaitTime(dto.getLongitude(), dto.getLatitude()));
    }
@@ -151,7 +151,7 @@
     * 播单
     */
    @PostMapping("/base/v1/mini-program/order/save")
    @ApiOperation(value = "保存订单", tags = {"小程序-保存订单"})
    @ApiOperation(value = "保存订单(弃用)", tags = {"小程序-保存订单(弃用)"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<SaveOrderVo> saveOrder(@RequestBody @Validated XpOrderDto dto, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpElectronicFenceMapper.xml
@@ -12,7 +12,7 @@
        from xp_electronic_fence ef
        left join xp_electronic_fence_area efa on efa.electronic_id = ef.id
        where ef.is_deleted = 0
        <if test="query.electronicNumberOrName != null">
        <if test="query.electronicNumberOrName != null and query.electronicNumberOrName != ''">
            and( ef.electronic_name like concat('%',#{query.electronicNumberOrName},'%')
                or ef.electronic_number like concat('%',#{query.electronicNumberOrName},'%')
                )
@@ -45,39 +45,27 @@
            and #{query.updateEndTime} >= ef.update_time
        </if>
        group by ef.id
        <if test="query.createSort != null and query.updateSort != null">
         order by
            <if test="query.createSort == 1">
                ef.create_time asc,
            </if>
            <if test="query.createSort == 2">
                ef.create_time desc,
            </if>
            <if test="query.updateSort == 1">
                ef.update_time asc
            </if>
            <if test="query.updateSort == 2">
                ef.update_time desc
            </if>
        </if>
        <if test="query.createSort != null">
            order by
            <if test="query.createSort == 1">
                ef.create_time asc
            </if>
            <if test="query.createSort == 2">
                ef.create_time desc
            </if>
        </if>
        <if test="query.updateSort != null">
            order by
            <if test="query.updateSort == 1">
                ef.update_time asc
            </if>
            <if test="query.updateSort == 2">
                ef.update_time desc
            </if>
        </if>
        <choose>
            <when test="query.createSort == 1 or query.createSort == 2 or query.updateSort == 1 or query.updateSort == 2">
                <trim prefix="order by" suffixOverrides=",">
                    <if test="query.createSort == 1">
                        ef.create_time asc,
                    </if>
                    <if test="query.createSort == 2">
                        ef.create_time desc,
                    </if>
                    <if test="query.updateSort == 1">
                        ef.update_time asc,
                    </if>
                    <if test="query.updateSort == 2">
                        ef.update_time desc,
                    </if>
                </trim>
            </when>
            <otherwise>
                order by ef.update_time desc
            </otherwise>
        </choose>
    </select>
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/controller/XpOrderController.java
@@ -97,9 +97,9 @@
     */
    @PostMapping("/inner/order/has-unpaid-order")
    @ApiOperation(value = "查询是否有未支付订单 或 正在进行的订单", tags = {"内部接口"})
    public R<Long> hasUnPaodOrder(String uid){
    public R<Long> hasUnPaodOrder(String uid) {
        List<XpOrder> list = xpOrderService.list(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getAppUserId, Long.parseLong(uid)).in(XpOrder::getStatus, Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8)));
        if(!list.isEmpty()){
        if (!list.isEmpty()) {
            return R.ok(list.get(0).getId());
        }
        return R.ok(0l);
@@ -113,12 +113,12 @@
     * @return 订单详情
     */
    @PostMapping("/inner/order/queryOrderById")
    public R<XpOrder> queryOrderById(@RequestParam Long orderId){
    public R<XpOrder> queryOrderById(@RequestParam Long orderId) {
        return R.ok(xpOrderService.getById(orderId));
    }
    @PostMapping("/inner/order/queryOrderByOrderNo")
    public R<XpOrder> queryOrderByOrderNo(@RequestParam String orderNo){
    public R<XpOrder> queryOrderByOrderNo(@RequestParam String orderNo) {
        return R.ok(xpOrderService.getOne(new LambdaQueryWrapper<XpOrder>().eq(XpOrder::getOrderNumber, orderNo)));
    }
@@ -128,17 +128,16 @@
     * @return 订单数量
     */
    @PostMapping("/inner/order/getOrderNum")
    public  R<Integer> getOrderNum(@RequestBody GetOrderNumDto dto){
    public R<Integer> getOrderNum(@RequestBody GetOrderNumDto dto) {
        return R.ok(xpOrderService.getOrderNum(dto));
    }
    /**
     * 成功操作下发命令后调用 用于弹出redis队列的获取成功的数据
     */
    @PostMapping("/inner/order/popOrder")
    public  R<?> popOrder(@RequestBody PopOrderDto dto){
    public R<?> popOrder(@RequestBody PopOrderDto dto) {
        xpOrderService.popOrder(dto);
        return R.ok();
    }
@@ -149,9 +148,9 @@
     * @param xpOrder 订单信息
     */
    @PostMapping("/inner/order/updateOrder")
    public R<?> updateOrder(@RequestBody XpOrder xpOrder){
    public R<?> updateOrder(@RequestBody XpOrder xpOrder) {
        xpOrder.setAppUserId(null);
        return xpOrderService.updateById(xpOrder)?R.ok():R.fail();
        return xpOrderService.updateById(xpOrder) ? R.ok() : R.fail();
    }
@@ -162,9 +161,9 @@
     * @return 订单ID
     */
    @PostMapping("/inner/order/addOrder")
    public R<Long> addOrder(@RequestBody XpOrder xpOrder){
    public R<Long> addOrder(@RequestBody XpOrder xpOrder) {
        boolean save = xpOrderService.addOrder(xpOrder);
        if(!save){
        if (!save) {
            return R.fail("新增失败");
        }
        return R.ok(xpOrder.getId());
@@ -178,7 +177,7 @@
     * @return 操作结果
     */
    @PostMapping("/inner/order/cancelOrder")
    public R<?> cancelOrder(@RequestParam("orderId") String orderId){
    public R<?> cancelOrder(@RequestParam("orderId") String orderId) {
        xpOrderService.cancelOrder(orderId);
        return R.ok();
    }
@@ -281,38 +280,42 @@
     * @param dto 改派请求参数
     * @return 操作结果
     */
    @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"},notes = "车辆列表在vehicleConvoy服务")
    @ApiOperation(value = "改派订单", tags = {"管理后台-交易管理-订单管理"}, notes = "车辆列表在vehicleConvoy服务")
    @PostMapping("/api/v1/order/reassignById")
    public R<?> reassignById(@Validated @RequestBody XpOrderReassignDTO dto) {
        xpOrderService.reassignOrder(
            dto.getOrderId(),
            dto.getVehicleId(),
            dto.getReassignReason()
                dto.getOrderId(),
                dto.getVehicleId(),
                dto.getReassignReason()
        );
        return R.ok();
    }
    @ApiOperation(value = "订单改价", tags = {"管理后台-交易管理-订单管理"})
    @PostMapping("/api/v1/order/changeAmount")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "订单ID", required = true, dataType = "Long"),
            @ApiImplicitParam(name = "amount", value = "新的订单金额", required = true, dataType = "BigDecimal")
    })
    public R<?> changeAmount(@RequestParam("id") Long id ,@RequestParam("amount") BigDecimal amount) {
    public R<?> changeAmount(@RequestParam("id") Long id, @RequestParam("amount") BigDecimal amount) {
        xpOrderService.changeAmount(id, amount);
        return R.ok();
    }
    /**
     * 获取用户快捷胶囊 历史 时段 终点高点
     */
    @ApiOperation(value = "获取用户快捷胶囊 历史 时段 终点高点", tags = {"小程序-获取用户快捷胶囊 历史 时段 终点高点"})
    @GetMapping("/api/v1/mini-program/order/getUserQuickCapsule")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<XpPointInfoVo> getUserQuickCapsule(HttpServletRequest  request) {
    public R<XpPointInfoVo> getUserQuickCapsule(HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.getUserQuickCapsule(uid));
    }
    /**
     * 获取订单详情
     */
@@ -322,7 +325,7 @@
    public R<OrderDetailVo> orderDetail(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.orderDetail(orderId,uid));
        return R.ok(xpOrderService.orderDetail(orderId, uid));
    }
@@ -332,21 +335,22 @@
    @ApiOperation(value = "获取历史下单成功起点10条数据列表", tags = {"小程序-获取历史下单成功起点10条数据列表"})
    @GetMapping("/base/v1/mini-program/history/startPoints")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon,double lat,HttpServletRequest  request) {
    public R<List<XpHistoryStartPointsVo>> getHistoryStartPoints(double lon, double lat, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.getHistoryStartPoints(uid,lon,lat));
        return R.ok(xpOrderService.getHistoryStartPoints(uid, lon, lat));
    }
    /**
     * 获取历史下单成功终点点10条数据列表
     */
    @ApiOperation(value = "获取历史下单成功终点10条数据列表", tags = {"小程序-获取历史下单成功终点10条数据列表"})
    @GetMapping("/base/v1/mini-program/history/endPoints")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat, HttpServletRequest  request) {
    public R<List<XpHistoryEndPointsVo>> getHistoryEndPoints(double lon, double lat, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.getHistoryEndPoints(uid,lon,lat));
        return R.ok(xpOrderService.getHistoryEndPoints(uid, lon, lat));
    }
@@ -356,7 +360,7 @@
    @ApiOperation(value = "获取正在进行中的订单", tags = {"小程序-获取正在进行中的订单"})
    @GetMapping("/api/v1/mini-program/order/active")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<XpOrderDetailVO> getActiveOrder(HttpServletRequest  request) {
    public R<XpOrderDetailVO> getActiveOrder(HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.getActiveOrder(uid));
@@ -369,49 +373,50 @@
    @ApiOperation(value = "查询历史订单列表", tags = {"小程序-查询历史订单列表"})
    @PostMapping("/api/v1/mini-program/order/history/list")
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R<XpOrderHistoryVO> getHistoryOrderList(@RequestBody XpHistoryOrderListQuery query, HttpServletRequest  request) {
    public R<XpOrderHistoryVO> getHistoryOrderList(@RequestBody XpHistoryOrderListQuery query, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.getHistoryOrderList(query, uid));
    }
    /**+
    /**
     * +
     * 取消订单
     */
    @PutMapping("/api/v1/mini-program/order/cancel/{orderId}")
    @ApiOperation(value = "取消订单", tags = {"小程序-取消订单"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R cancelOrder(@PathVariable("orderId") Long orderId,HttpServletRequest request) {
    public R cancelOrder(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        xpOrderService.cancelOrder(orderId,uid);
        xpOrderService.cancelOrder(orderId, uid);
        return R.ok();
    }
    /**+
    /**
     * +
     * 手动结束订单
     */
    @PutMapping("/api/v1/mini-program/order/endTrip/{orderId}")
    @ApiOperation(value = "结束行程", tags = {"小程序-结束行程"})
    @XpClientCheck(checkToken = false, checkOtpToken = true)
    public R endTrip(@PathVariable("orderId") Long orderId,HttpServletRequest request) {
    public R endTrip(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        try {
            xpOrderService.endTrip(orderId,uid);
        }catch (Exception e){
            xpOrderService.endTrip(orderId, uid);
        } catch (Exception e) {
            return R.ok();
        }
        return R.ok();
    }
    /**+
    /**
     * +
     * 获取行程费用明细
     */
    @PutMapping("/api/v1/mini-program/order/fare-breakdown/{orderId}")
@@ -420,9 +425,11 @@
    public R<FareBreakdownVo> fareBreakdown(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return xpOrderService.fareBreakdown(orderId,uid);
        return xpOrderService.fareBreakdown(orderId, uid);
    }
    /**+
    /**
     * +
     * 获取行程费用明细
     */
    @PutMapping("/api/v1/mini-program/order/feeDescription/{orderId}")
@@ -431,8 +438,9 @@
    public R<String> feeDescription(@PathVariable("orderId") Long orderId, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return xpOrderService.feeDescription(orderId,uid);
        return xpOrderService.feeDescription(orderId, uid);
    }
    /**
     * 订单评价
     */
@@ -442,7 +450,7 @@
    public R payment(@Validated @RequestBody XpOrderPayDto dto, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        return xpOrderService.payment(dto,uid);
        return xpOrderService.payment(dto, uid);
    }
    /**
@@ -454,7 +462,7 @@
    public R comment(@Validated @RequestBody XpOrderCommentDto dto, HttpServletRequest request) {
        // uid已通过拦截器otp校验,可以直接使用
        String uid = request.getHeader("XP-Uid");
        xpOrderService.comment(dto,uid);
        xpOrderService.comment(dto, uid);
        return R.ok();
    }
@@ -465,7 +473,7 @@
    @PostMapping("/inner/v1/order/updateOrderStatus")
    public R<String> updateOrderStatus(@RequestParam Long orderId,
                                       @RequestParam Integer status) {
        return xpOrderService.updateOrderStatus(orderId,status);
        return xpOrderService.updateOrderStatus(orderId, status);
    }
    /**
@@ -476,7 +484,7 @@
    @GetMapping("/api/v1/mini-program/order/queryVehicleByOrderId")
    public R<XpVehicle> queryVehicleByOrderId(@RequestParam Long orderId, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
        return R.ok(xpOrderService.queryVehicleByOrderId(orderId,uid));
        return R.ok(xpOrderService.queryVehicleByOrderId(orderId, uid));
    }
    /**
@@ -505,11 +513,11 @@
        String key = "";
        //接驾情况,获取车辆位置到起点的导航
        if(xpOrder.getStatus() < 5){
        if (xpOrder.getStatus() < 5) {
            key = "ORDER_NAVIGATION_START_DATA:" + xpOrder.getAppUserId();
        }
        //服务中,获取起点到终点的导航数据
        if(xpOrder.getStatus() >= 5){
        if (xpOrder.getStatus() >= 5) {
            key = "ORDER_NAVIGATION_END_DATA:" + xpOrder.getAppUserId();
        }
        Object cacheObject = redisService.getCacheObject(key);
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/job/jobs/OrderCancelJob.java
@@ -1,8 +1,11 @@
package com.xiaopeng.order.job.jobs;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.api.dto.automaticPilot.PushOrderDto;
import com.xiaopeng.api.dto.pushMessage.SendMessageDTO;
import com.xiaopeng.api.dto.vehicleConvoy.UpdateVehicleStateDto;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.api.model.vehicleConvoy.XpVehicle;
import com.xiaopeng.common.core.domain.R;
import com.xiaopeng.common.core.enums.OrderStatusEnum;
import com.xiaopeng.common.core.enums.PushMessageTypeEnum;
@@ -37,8 +40,23 @@
            XpOrder xpOrder = xpOrderService.getById(orderId);
            if(Objects.nonNull(xpOrder) && xpOrder.getStatus()==4){
                log.info("订单取消开始");
                xpOrderService.cancelOrder(String.valueOf(xpOrder.getId()));
                log.info("订单取消状态修改完成");
                XpOrder order = xpOrderService.cancelOrder(String.valueOf(xpOrder.getId()));
                // 下发命令
                if (null != order.getVehicleId()) {
                    R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
                    XpVehicle xpVehicle = xpVehicleR.getData();
                    //还原车辆状态为空闲
                    xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
                    PushOrderDto pushOrderDto = new PushOrderDto();
                    pushOrderDto.setOrderId(order.getId().toString());
                    pushOrderDto.setVin(xpVehicle.getVehicleVin());
                    pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                    orderMissionClient.cancelOrder(pushOrderDto);
                    //车辆继续巡游单
                    xpOrderService.addCruiseMission(xpVehicle);
                }
                log.info("订单取消状态修改完成");
            }
        }catch(Exception e){
            e.printStackTrace();
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/IXpOrderService.java
@@ -142,7 +142,7 @@
     * 取消订单
     * @param orderId
     */
    void cancelOrder(String orderId);
    XpOrder cancelOrder(String orderId);
    /**
     * 评价订单
@@ -169,6 +169,12 @@
     */
    void addCruiseMission(XpVehicle vehicle, XpOrder order);
    /**
     * 取消订单后的继续巡游任务
     * @param vehicle
     */
    void addCruiseMission(XpVehicle vehicle);
    R<FareBreakdownVo> fareBreakdown(Long orderId, String uid);
    R payment(XpOrderPayDto dto, String uid);
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -316,7 +316,7 @@
        // 6. 获取评价信息
        LambdaQueryWrapper<XpOrderEvaluate> evaluateWrapper = new LambdaQueryWrapper<>();
        evaluateWrapper.eq(XpOrderEvaluate::getOrderId, id);
        XpOrderEvaluate evaluate = xpOrderEvaluateService.getOne(evaluateWrapper);
        XpOrderEvaluate evaluate = xpOrderEvaluateService.getOne(evaluateWrapper.orderByDesc(XpOrderEvaluate::getCreateTime).last(" limit 0,1"));
        if (Objects.nonNull(evaluate)) {
            vo.setOrderRating(evaluate.getOrderRating());
        }
@@ -641,8 +641,22 @@
        orderCancel.setUserId(SecurityUtils.getUserId()); // 当前登录用户ID
        orderCancel.setCancelReason("运营人员取消订单");
        xpOrderCancelService.save(orderCancel);
        // 消息推送
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> content = new HashMap<>();
        content.put("orderId", order.getId().toString());
        content.put("status", OrderStatusEnum.CANCELED.getCode());
        params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc());
        params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content));
        params.put("timestamp", new Date().getTime() + "");
        String message = JSONObject.toJSONString(params);
        SendMessageDTO sendMessageDTO = new SendMessageDTO();
        sendMessageDTO.setMessage(message);
        sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId()));
        xpPushMessageClient.sendStatus(sendMessageDTO);
        //查询车辆信息
        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getId());
        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
        if (xpVehicleR.getCode() == HttpStatus.SUCCESS && Objects.nonNull(xpVehicleR.getData())) {
            XpVehicle xpVehicle = xpVehicleR.getData();
            // 组装调用车机参数
@@ -650,9 +664,7 @@
            cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin());
            cancelTaxiPassengerVo.setUid(order.getAppUserId().toString());
            cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
            // TODO 加配置文件取
            cancelTaxiPassengerVo.setAppId(appid);
            BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
            if (baseVehicleUserDto == null) {
                // TODO 本地无法调通
@@ -660,33 +672,17 @@
            }
            //还原车辆状态
            if (1 == xpVehicle.getState()) {
                xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
            }
            // 消息推送
            Map<String, Object> params = new HashMap<>();
            Map<String, Object> content = new HashMap<>();
            content.put("orderId", order.getId().toString());
            content.put("status", OrderStatusEnum.CANCELED.getCode());
            params.put("type", PushMessageTypeEnum.ORDER_STATUS.getDesc());
            params.put("content", com.alibaba.fastjson2.JSONObject.toJSONString(content));
            params.put("timestamp", new Date().getTime() + "");
            String message = JSONObject.toJSONString(params);
            SendMessageDTO sendMessageDTO = new SendMessageDTO();
            sendMessageDTO.setMessage(message);
            sendMessageDTO.setAppUserId(String.valueOf(order.getAppUserId()));
            xpPushMessageClient.sendStatus(sendMessageDTO);
            xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
            // 下发命令
            if (order.getStatus() > 1) {
                PushOrderDto pushOrderDto = new PushOrderDto();
                pushOrderDto.setOrderId(order.getId().toString());
                pushOrderDto.setVin(xpVehicle.getVehicleVin());
                pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
                orderMissionClient.cancelOrder(pushOrderDto);
            }
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setOrderId(order.getId().toString());
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            orderMissionClient.cancelOrder(pushOrderDto);
            //车辆继续巡游
            addCruiseMission(xpVehicle);
        } else {
            log.info("查询车辆信息失败,订单ID: {}, 下发取消订单命令失败", order.getId());
        }
@@ -1184,26 +1180,6 @@
            return;
        }
        order.setStatus(0);
        // 组装调用车机参数
        CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
        Long vehicleId = order.getVehicleId();
        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(vehicleId);
        XpVehicle xpVehicle = xpVehicleR.getData();
        if (xpVehicle == null) {
            throw new ServiceException("车辆不存在", I18nKeyConstant.VEHICLE_NOT_EXISTS);
        }
        cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin());
        cancelTaxiPassengerVo.setUid(order.getAppUserId().toString());
        cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
        // TODO 加配置文件取
        cancelTaxiPassengerVo.setAppId(appid);
        BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
        if (baseVehicleUserDto == null) {
            // TODO 本地无法调通
//            throw new RuntimeException("取消订单失败");
        }
        order.setAppUserId(null);
        baseMapper.updateById(order);
        XpOrderCancel xpOrderCancel = new XpOrderCancel();
@@ -1212,10 +1188,7 @@
        xpOrderCancel.setCancelSource(1);
        xpOrderCancel.setCancelReason("用户取消订单");
        xpOrderCancelService.save(xpOrderCancel);
        //还原车辆状态
        if (1 == xpVehicle.getState()) {
            xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
        }
        // 设置当天的取消次数缓存
        Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + uid);
@@ -1246,11 +1219,37 @@
        // 下发命令
        if (null != order.getVehicleId()) {
            R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
            // 组装调用车机参数
            CancelTaxiPassengerVo cancelTaxiPassengerVo = new CancelTaxiPassengerVo();
            XpVehicle xpVehicle = xpVehicleR.getData();
            if (xpVehicle == null) {
                throw new ServiceException("车辆不存在", I18nKeyConstant.VEHICLE_NOT_EXISTS);
            }
            cancelTaxiPassengerVo.setVin(xpVehicle.getVehicleVin());
            cancelTaxiPassengerVo.setUid(order.getAppUserId().toString());
            cancelTaxiPassengerVo.setOrderNo(order.getOrderNumber());
            cancelTaxiPassengerVo.setAppId(appid);
            BaseVehicleUserDto baseVehicleUserDto = userVehicleClient.cancelTaxiPassenger(cancelTaxiPassengerVo);
            if (baseVehicleUserDto == null) {
                // TODO 本地无法调通
//            throw new RuntimeException("取消订单失败");
            }
            //还原车辆状态
            if (1 == xpVehicle.getState()) {
                xpVehicleClient.updateVehicleStatus(new UpdateVehicleStateDto(xpVehicle.getVehicleVin(), 0));
            }
            //下发XPU报文
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setOrderId(order.getId().toString());
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            orderMissionClient.cancelOrder(pushOrderDto);
            //车辆继续巡游
            addCruiseMission(xpVehicle);
        }
    }
@@ -1258,7 +1257,7 @@
    @Override
    @Transactional
    @ShardingSphereTransactionType(TransactionType.BASE)
    public void cancelOrder(String orderId) {
    public XpOrder cancelOrder(String orderId) {
        XpOrder order = this.getById(orderId);
        if (order == null) {
            throw new ServiceException("订单不存在", I18nKeyConstant.ORDER_NOT_EXISTS);
@@ -1275,10 +1274,6 @@
        xpOrderCancelService.save(xpOrderCancel);
        redisService.removeByPattern(order.getQueueName(), order.getOrderNumber());
        R<XpVehicle> xpVehicleR = xpVehicleClient.queryById(order.getVehicleId());
        XpVehicle xpVehicle = xpVehicleR.getData();
        // 消息推送
@@ -1298,16 +1293,16 @@
        // 移除mongo数据
        xpPricingClient.deleteXpGeoQueryEntity(order.getId().toString());
        // 下发命令
        if (null != order.getVehicleId()) {
            PushOrderDto pushOrderDto = new PushOrderDto();
            pushOrderDto.setOrderId(order.getId().toString());
            pushOrderDto.setVin(xpVehicle.getVehicleVin());
            pushOrderDto.setOperation_type(OrderOperationType.CLOUD_CANCEL_ORDER);
            orderMissionClient.cancelOrder(pushOrderDto);
        Long uid = order.getAppUserId();
        // 设置当天的取消次数缓存
        Object cacheObject = redisService.getCacheObject("CANCEL_ORDER_" + uid);
        if (cacheObject == null) {
            redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, 1);
        } else {
            Integer i = Integer.valueOf(cacheObject.toString());
            redisService.setCacheCancelOrder("CANCEL_ORDER_" + uid, i + 1);
        }
        return order;
    }
    /**
@@ -1476,19 +1471,19 @@
            throw new ServiceException("当前城市未配置定价规则", I18nKeyConstant.ORDER_PRICING_NOT_EXISTS);
        }
        // 费用
//        // 查询订单轨迹
//        List<OrderTrajectory> trajectories = mongoTemplate.find(
//                new Query(Criteria.where("orderId").is(orderId))
//                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
//                OrderTrajectory.class
//        );
//        List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>();
//        for (OrderTrajectory trajectory : trajectories) {
//            TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime());
//            gpsPoints.add(point);
//        }
        // 补充临时轨迹数据
        List<TaxiPricingDemoService.GpsPoint> gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime()));
        // 查询订单轨迹
        List<OrderTrajectory> trajectories = mongoTemplate.find(
                new Query(Criteria.where("orderId").is(orderId))
                        .with(Sort.by(Sort.Direction.ASC, "locatetime")),
                OrderTrajectory.class
        );
        List<TaxiPricingDemoService.GpsPoint> gpsPoints = new ArrayList<>();
        for (OrderTrajectory trajectory : trajectories) {
            TaxiPricingDemoService.GpsPoint point = new TaxiPricingDemoService.GpsPoint(trajectory.getDistance(), trajectory.getLocatetime());
            gpsPoints.add(point);
        }
//         补充临时轨迹数据
//        List<TaxiPricingDemoService.GpsPoint> gpsPoints = TaxiPricingDemoService.createMockGpsPoints(DateUtils.toDate(order.getCreateTime()));
        TaxiPricingDemoService.PricingConfig config = new TaxiPricingDemoService.PricingConfig();
@@ -1502,39 +1497,57 @@
        double paramNum5 =0.0;
        for (int i = 0; i < startingFareJsonArray.size(); i++) {
            com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i);
            String num1 = jsonObject.getString("num1");
            String num2 = jsonObject.getString("num2");
            String num3 = jsonObject.getString("num3");
            String num4 = jsonObject.getString("num4");
            String num5 = jsonObject.getString("num5");
            String num6 = jsonObject.getString("num6");
            String num7 = jsonObject.getString("num7");
        //一口价
        if(pricing.getPricingType() == 2){
            JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson());
            String num1 = "00:00";
            String num2 = "23:59";
            String num3 = basicPricingJson.getString("num1");
            String num4 = basicPricingJson.getString("num2");
            String num5 = basicPricingJson.getString("num3");
            String num6 = basicPricingJson.getString("num4");
            String num7 = basicPricingJson.getString("num5");
            config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7)));
            // 判断当前是那个时段
            Calendar calendarStart = Calendar.getInstance();
            calendarStart.setTime(date);
            calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0]));
            calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1]));
            Calendar calendarEnd = Calendar.getInstance();
            calendarEnd.setTime(date);
            calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0]));
            calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1]));
            // 找到符合条件的直接跳出循环
            if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) {
                paramNum4 = jsonObject.getDouble("num4");
                paramNum5 = jsonObject.getDouble("num5");
                break;
            }
            paramNum4 = basicPricingJson.getDouble("num2");
            paramNum5 = basicPricingJson.getDouble("num3");
        }
        //动态计费
        if (pricing.getPricingType() == 1) {
            for (int i = 0; i < startingFareJsonArray.size(); i++) {
                com.alibaba.fastjson.JSONObject jsonObject = startingFareJsonArray.getJSONObject(i);
                String num1 = jsonObject.getString("num1");
                String num2 = jsonObject.getString("num2");
                String num3 = jsonObject.getString("num3");
                String num4 = jsonObject.getString("num4");
                String num5 = jsonObject.getString("num5");
                String num6 = jsonObject.getString("num6");
                String num7 = jsonObject.getString("num7");
                config.normals.add(new TaxiPricingDemoService.PricingRule("普通时段", num1, num2, Double.parseDouble(num3), Double.parseDouble(num4), Double.parseDouble(num5), Double.parseDouble(num6), Double.parseDouble(num7)));
                // 判断当前是那个时段
                Calendar calendarStart = Calendar.getInstance();
                calendarStart.setTime(date);
                calendarStart.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num1").split(":")[0]));
                calendarStart.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num1").split(":")[1]));
                Calendar calendarEnd = Calendar.getInstance();
                calendarEnd.setTime(date);
                calendarEnd.set(Calendar.HOUR_OF_DAY, Integer.valueOf(jsonObject.getString("num2").split(":")[0]));
                calendarEnd.set(Calendar.MINUTE, Integer.valueOf(jsonObject.getString("num2").split(":")[1]));
                // 找到符合条件的直接跳出循环
                if (date.getTime() > calendarStart.getTimeInMillis() && date.getTime() < calendarEnd.getTimeInMillis()) {
                    paramNum4 = jsonObject.getDouble("num4");
                    paramNum5 = jsonObject.getDouble("num5");
                    break;
                }
            }
            JSONObject basicPricingJson = JSONObject.parseObject(pricing.getBasicPricingJson());
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num21").split(" - ")[0], basicPricingJson.getString("num21").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")),paramNum4, paramNum5,  Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25"))));
            config.peaks.add(new TaxiPricingDemoService.PricingRule("高峰期", basicPricingJson.getString("num22").split(" - ")[0], basicPricingJson.getString("num22").split(" - ")[1], Double.parseDouble(basicPricingJson.getString("num23")), paramNum4, paramNum5, Double.parseDouble(basicPricingJson.getString("num24")), Double.parseDouble(basicPricingJson.getString("num25"))));
@@ -1551,17 +1564,14 @@
        TaxiPricingDemoService.TaxiPricingService service = new TaxiPricingDemoService.TaxiPricingService();
        Integer holidayToday = holidayUtil.isHolidayToday();
        Map<String, BigDecimal> bill = service.calculateOrderPrice(DateUtils.toDate(order.getBoardingTime()), order.getMileageKilometers(), gpsPoints, config,holidayToday);
        System.err.println("======= 订单计费账单 =======");
        bill.forEach((detail, price) -> System.err.println(detail + ": " + price + " 元"));
        log.info("======= 订单计费账单 =======");
        bill.forEach((detail, price) -> log.info(detail + ": " + price + " 元"));
        BigDecimal totalAmount = bill.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
        System.err.println("--------------------------");
        System.err.println("应付总额: " + totalAmount + " 元");
        log.info("--------------------------");
        log.info("应付总额: " + totalAmount + " 元");
        BigDecimal startMoney = BigDecimal.ZERO;
        // 默认费率1
        double priceRate = 1;
@@ -1789,8 +1799,7 @@
        if (vehicle != null) {
            // 修改车辆状态
            vehicle.setState(0);
            //发送巡游订单
            addCruiseMission(vehicle, order);
//            // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作
//            R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail();
@@ -1961,6 +1970,97 @@
                jobMaps
        );
    }
    /**
     * 取消订单后的继续巡游任务
     * @param vehicle
     */
    public void addCruiseMission(XpVehicle vehicle) {
        if (vehicle.getState() != 0 || vehicle.getOperatingStatus() != 1) {
            return;
        }
        if (vehicle.getState() != 0 || vehicle.getOperatingStatus() != 1) {
            return;
        }
        // 判断是否有计划
        R<XpCruisePlanVehicle> xpCruisePlanR = xpCruisePlanClient.getCruisePlan(vehicle.getId());
        if (xpCruisePlanR == null || xpCruisePlanR.getData() == null) {
            return;
        }
        VehiclePosition vehiclePosition = mongoTemplate.findOne(new Query(Criteria.where("vin").is(vehicle.getVehicleVin())), VehiclePosition.class);
        // 获取配置 根据配置判断是否该收车 如果是则找到收车点位进行收车操作
        R<XpTaskRule> xpTaskRuleR = xpTaskRuleClient.queryDetail();
        XpTaskRule xpTaskRule = xpTaskRuleR.getData();
        // 生成新的巡游单子 回到最新巡游的初始起点位置
        XpCruiseOrder xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 2).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
        int temp = 0;
        if (xpCruiseOrders == null) {
            temp = 1;
            //特殊情况 可能没有产生终止的订单  (到站点就被正常接单了)所以找正常订单
            xpCruiseOrders = xpCruiseOrderMapper.selectOne(new LambdaQueryWrapper<XpCruiseOrder>().eq(XpCruiseOrder::getVehicleId, vehicle.getId()).eq(XpCruiseOrder::getStatus, 3).orderByDesc(BaseModel::getCreateTime).last("limit 1"));
        }
        XpCruiseOrder xpCruiseOrder = new XpCruiseOrder();
        xpCruiseOrder.setVehicleId(vehicle.getId());
        xpCruiseOrder.setFleetId(vehicle.getFleetId());
        xpCruiseOrder.setVehicleVin(vehicle.getVehicleVin());
        xpCruiseOrder.setOrderType(2);
        // 返程起点是当前正常订单的终点
        xpCruiseOrder.setStartPointId(null);
        xpCruiseOrder.setStartPointName(null);
        xpCruiseOrder.setStartLon(vehiclePosition.getPoint().getX());
        xpCruiseOrder.setStartLat(vehiclePosition.getPoint().getY());
        // 完成的直接走终点   终止的走起点
        if (temp == 0) {
            xpCruiseOrder.setEndPointId(xpCruiseOrders.getStartPointId());
            xpCruiseOrder.setEndPointName(xpCruiseOrders.getStartPointName());
            xpCruiseOrder.setEndLon(xpCruiseOrders.getStartLon());
            xpCruiseOrder.setEndLat(xpCruiseOrders.getStartLat());
        } else {
            xpCruiseOrder.setEndPointId(xpCruiseOrders.getEndPointId());
            xpCruiseOrder.setEndPointName(xpCruiseOrders.getEndPointName());
            xpCruiseOrder.setEndLon(xpCruiseOrders.getEndLon());
            xpCruiseOrder.setEndLat(xpCruiseOrders.getEndLat());
        }
        xpCruiseOrder.setStatus(0);
        xpCruiseOrder.setLastOrderId(xpCruiseOrders.getId());
        xpCruiseOrder.setCreateTime(LocalDateTime.now());
        // 判断当前时分秒是否大于收车时间
        LocalTime vehicleCollectionTime = xpTaskRule.getVehicleCollectionTime();
        if (vehicleCollectionTime.isBefore(LocalTime.now())) {
            vehicle.setOperatingStatus(3);
            //找到车辆的收车点位 更新终点点位
            R<XpCruiseOrder> returnCruisePoint = xpCruisePlanClient.findReturnCruisePoint(xpCruiseOrder);
            xpCruiseOrder = returnCruisePoint.getData();
        }
        xpVehicleClient.updateVehicleById(vehicle);
        xpCruiseOrderMapper.insert(xpCruiseOrder);
        //下发XPU消息报文
        PushOrderDto pushOrderDto = new PushOrderDto();
        pushOrderDto.setVin(xpCruiseOrder.getVehicleVin());
        pushOrderDto.setOrderId("XU" + xpCruiseOrder.getId());
        pushOrderDto.setStartLatitude(xpCruiseOrder.getStartLat());
        pushOrderDto.setStartLongitude(xpCruiseOrder.getStartLon());
        pushOrderDto.setEndLatitude(xpCruiseOrder.getEndLat());
        pushOrderDto.setEndLongitude(xpCruiseOrder.getEndLon());
        pushOrderDto.setOrderType(OrderType.CRUISE_ORDER);
        pushOrderDto.setStage(2);
        // 调用推送服务  orderId + carVin
        orderMissionClient.pushOrder(pushOrderDto);
    }
    private MileageDto mileageType(MileageDto param, JSONArray startingFareJsonArray, Date mileageDate, LocalDateTime begin, String num14, String num16, String num17, String num21, String num22, String num24, String num25, String num30, String num31) {
        // 计算出是在哪个普通时间段内
@@ -2212,7 +2312,7 @@
        res.setRedPacketMoney(order.getRedPacketMoney());
        res.setCouponMoney(order.getCouponMoney());
        res.setOrderMoney(order.getOrderMoney());
        res.setKilometer(order.getMileageKilometers() == null ? BigDecimal.ZERO : BigDecimal.valueOf(order.getMileageKilometers()));
        res.setKilometer(order.getMileageKilometers() == null ? BigDecimal.ZERO : BigDecimal.valueOf(order.getMileageKilometers()).multiply(BigDecimal.valueOf(1000)));
        LocalDateTime createTime = order.getCreateTime();
        LocalDateTime tripEnd = order.getTripEnd();
        if (tripEnd == null) {
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/utils/TaskOrderCancelUtil.java
New file
@@ -0,0 +1,62 @@
package com.xiaopeng.order.utils;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xiaopeng.api.model.order.XpOrder;
import com.xiaopeng.order.service.IXpOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDateTime;
import java.util.List;
@Slf4j
@Component
public class TaskOrderCancelUtil {
    @Autowired
    private IXpOrderService xpOrderService;
    /**
     * 30秒执行一次
     */
    @Scheduled(cron = "0/30 * * * * ?")
    public void taskOrder() {
        // 计算30分钟前的时间
        LocalDateTime thirtyMinutesAgo = LocalDateTime.now().minusMinutes(30);
        // 查询状态为1且创建时间超过30分钟的订单
        List<XpOrder> expiredOrders = xpOrderService.list(new LambdaQueryWrapper<XpOrder>()
                .eq(XpOrder::getStatus, 1)
                .lt(XpOrder::getCreateTime, thirtyMinutesAgo)  // 使用lt避免边界问题
                .orderByAsc(XpOrder::getCreateTime)  // 按创建时间正序处理,先处理最早的
                .last("LIMIT 1000")  // 防止一次处理太多数据,可以分批处理
        );
        if (CollectionUtils.isNotEmpty(expiredOrders)) {
            for (XpOrder order : expiredOrders) {
                try {
                    // 处理过期订单
                    processExpiredOrder(order);
                } catch (Exception e) {
                    log.error("处理过期订单失败,订单ID: {}", order.getId(), e);
                }
            }
        }
    }
    private void processExpiredOrder(XpOrder order){
        Long appUserId = order.getAppUserId();
        order.setAppUserId(null);
        order.setStatus(0);
        xpOrderService.updateById(order);
    }
}
xp-robotaxi-push-message-boot/pom.xml
@@ -108,11 +108,11 @@
                </exclusion>
            </exclusions>
        </dependency>
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-base-seata-at</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->
        <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-transaction-base-seata-at</artifactId>
            <version>5.2.1</version>
        </dependency>
        <dependency>
            <groupId>org.yaml</groupId>
            <artifactId>snakeyaml</artifactId>
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/config/DataUpdateHandlerConfig.java
@@ -47,7 +47,6 @@
        }
        this.setFieldValByName("createTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName("updateTime", LocalDateTime.now(), metaObject);
        this.setFieldValByName("createBy", userName, metaObject);
    }
    /**