liujie
2026-04-03 199b087e97231bc602cd5ed8668f37d6f336dff4
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi
3个文件已删除
7个文件已添加
25个文件已修改
891 ■■■■■ 已修改文件
xp-robotaxi-account-boot/pom.xml 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/CaptchaConfig.java 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/KaptchaTextCreator.java 55 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/properties/CaptchaProperties.java 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/CaptchaController.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IValidateCodeService.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/ValidateCodeServiceImpl.java 84 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpAgreement.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/config/WebMvcConfig.java 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/CaptchaConfig.java 82 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/KaptchaTextCreator.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/RouterFunctionConfiguration.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/handler/ValidateCodeHandler.java 37 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/ValidateCodeService.java 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/impl/ValidateCodeServiceImpl.java 68 ●●●●● 补丁 | 查看 | 原始文档 | 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/exportExcel/XpTaskExportExcel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java 6 ●●●●● 补丁 | 查看 | 原始文档 | 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/XpElectronicFenceManagementController.java 19 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpOpenCityController.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpAgreementDTO.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpOpenCityService.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAgreementServiceImpl.java 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpOpenCityServiceImpl.java 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderEvaluateServiceImpl.java 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/exportExcel/XpVehicleExportExcel.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/AliOssDownloadUtil.java 87 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/VehicleControlUtil.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-account-boot/pom.xml
@@ -101,6 +101,10 @@
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>pro.fessional</groupId>
            <artifactId>kaptcha</artifactId>
        </dependency>
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
        </dependency>
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/CaptchaConfig.java
New file
@@ -0,0 +1,71 @@
package com.xiaopeng.account.config;
import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.google.code.kaptcha.util.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER;
import static com.google.code.kaptcha.Constants.KAPTCHA_BORDER_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_HEIGHT;
import static com.google.code.kaptcha.Constants.KAPTCHA_IMAGE_WIDTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_NOISE_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_OBSCURIFICATOR_IMPL;
import static com.google.code.kaptcha.Constants.KAPTCHA_SESSION_CONFIG_KEY;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_LENGTH;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_CHAR_SPACE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_COLOR;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_NAMES;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_FONT_SIZE;
import static com.google.code.kaptcha.Constants.KAPTCHA_TEXTPRODUCER_IMPL;
/**
 * 验证码配置
 *
 * @author ruoyi
 */
@Configuration
public class CaptchaConfig {
    @Bean(name = "captchaProducer")
    public DefaultKaptcha getKaptchaBean() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(KAPTCHA_BORDER, "yes");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        defaultKaptcha.setConfig(new Config(properties));
        return defaultKaptcha;
    }
    @Bean(name = "captchaProducerMath")
    public DefaultKaptcha getKaptchaBeanMath() {
        DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
        Properties properties = new Properties();
        properties.setProperty(KAPTCHA_BORDER, "yes");
        properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
        properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
        properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
        properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.xiaopeng.account.config.KaptchaTextCreator");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
        properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
        properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
        properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
        properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
        defaultKaptcha.setConfig(new Config(properties));
        return defaultKaptcha;
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/KaptchaTextCreator.java
New file
@@ -0,0 +1,55 @@
package com.xiaopeng.account.config;
import com.google.code.kaptcha.text.impl.DefaultTextCreator;
import java.util.Random;
/**
 * 验证码文本生成器
 *
 * @author ruoyi
 */
public class KaptchaTextCreator extends DefaultTextCreator {
    @Override
    public String getText() {
        int result;
        Random random = new Random();
        int x = random.nextInt(10);
        int y = random.nextInt(10);
        StringBuilder suChinese = new StringBuilder();
        int randomOperator = random.nextInt(3);
        if (randomOperator == 0) {
            result = x * y;
            suChinese.append(x);
            suChinese.append("*");
            suChinese.append(y);
        } else if (randomOperator == 1) {
            if ((x != 0) && (y % x == 0)) {
                result = y / x;
                suChinese.append(y);
                suChinese.append("/");
                suChinese.append(x);
            } else {
                result = x + y;
                suChinese.append(x);
                suChinese.append("+");
                suChinese.append(y);
            }
        } else {
            if (x >= y) {
                result = x - y;
                suChinese.append(x);
                suChinese.append("-");
                suChinese.append(y);
            } else {
                result = y - x;
                suChinese.append(y);
                suChinese.append("-");
                suChinese.append(x);
            }
        }
        suChinese.append("=?@").append(result);
        return suChinese.toString();
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/config/properties/CaptchaProperties.java
New file
@@ -0,0 +1,42 @@
package com.xiaopeng.account.config.properties;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Configuration;
/**
 * 验证码配置
 *
 * @author ruoyi
 */
@Configuration
@RefreshScope
@ConfigurationProperties(prefix = "security.captcha")
public class CaptchaProperties {
    /**
     * 验证码开关
     */
    private Boolean enabled;
    /**
     * 验证码类型(math 数组计算 char 字符)
     */
    private String type;
    public Boolean getEnabled() {
        return enabled;
    }
    public void setEnabled(Boolean enabled) {
        this.enabled = enabled;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/controller/CaptchaController.java
New file
@@ -0,0 +1,30 @@
package com.xiaopeng.account.controller;
import com.xiaopeng.account.service.IValidateCodeService;
import com.xiaopeng.common.core.exception.CaptchaException;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Lazy;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.io.IOException;
/**
 * 图形验证码控制器
 *
 * @author ruoyi
 */
@RestController
@RequiredArgsConstructor(onConstructor_ = @Lazy)
public class CaptchaController {
    private final IValidateCodeService validateCodeService;
    @ApiOperation(value = "获取图形验证码", tags = {"管理后台-用户登录"})
    @GetMapping("/base/v1/captcha")
    public AjaxResult captcha() throws CaptchaException, IOException {
        return validateCodeService.createCaptcha();
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/IValidateCodeService.java
New file
@@ -0,0 +1,19 @@
package com.xiaopeng.account.service;
import com.xiaopeng.common.core.exception.CaptchaException;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import java.io.IOException;
/**
 * 验证码处理
 *
 * @author ruoyi
 */
public interface IValidateCodeService {
    /**
     * 生成验证码
     */
    AjaxResult createCaptcha() throws IOException, CaptchaException;
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/ValidateCodeServiceImpl.java
New file
@@ -0,0 +1,84 @@
package com.xiaopeng.account.service.impl;
import com.google.code.kaptcha.Producer;
import com.xiaopeng.account.config.properties.CaptchaProperties;
import com.xiaopeng.account.service.IValidateCodeService;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.exception.CaptchaException;
import com.xiaopeng.common.core.utils.sign.Base64;
import com.xiaopeng.common.core.utils.uuid.IdUtils;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.common.redis.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
/**
 * 验证码实现处理
 *
 * @author ruoyi
 */
@Service
public class ValidateCodeServiceImpl implements IValidateCodeService {
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Autowired
    private RedisService redisService;
    @Autowired
    private CaptchaProperties captchaProperties;
    @Override
    public AjaxResult createCaptcha() throws IOException, CaptchaException {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = Boolean.TRUE.equals(captchaProperties.getEnabled());
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled) {
            return ajax;
        }
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        String capStr = null;
        String code = null;
        BufferedImage image = null;
        String captchaType = captchaProperties.getType();
        if ("math".equals(captchaType)) {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        } else {
            capStr = captchaProducer.createText();
            code = capStr;
            image = captchaProducer.createImage(capStr);
        }
        redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }
        ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }
}
xp-robotaxi-account-boot/src/main/java/com/xiaopeng/account/service/impl/XpOperationsUserNotificationServiceImpl.java
@@ -30,22 +30,15 @@
            XpOperationsUserNotificationPageQuery query) {
        // 创建分页对象
        Page<XpOperationsUserNotification> page = new Page<>(
            query.getPageNum(),
            query.getPageSize()
        );
        PageInfo<XpOperationsUserNotification> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        // 执行分页查询
        Page<XpOperationsUserNotification> resultPage = baseMapper.selectNotificationPageByUserId(
            page,
            pageInfo,
            query
        );
        // 封装分页结果
        PageInfo<XpOperationsUserNotification> pageInfo = new PageInfo<>();
        pageInfo.setRecords(resultPage.getRecords());
        pageInfo.setTotal(resultPage.getTotal());
        return pageInfo;
    }
    @Override
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpAgreement.java
@@ -28,7 +28,7 @@
    @TableId("id")
    private Long id;
    @ApiModelProperty(value = "类型 1=用户服务协议 2=平台隐私政策 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明")
    @ApiModelProperty(value = "类型 1=小鹏Robotaxi隐私政策 2=个人信息收集清单 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明 7=权限说明 8=运维APP-小鹏Robotaxi自动驾驶出行运维隐私政策 9=运维APP-第三方共享信息清单 10=运维APP-个人信息收集清单 11=运维APP-权限调用")
    @TableField("content_type")
    private Integer contentType;
xp-robotaxi-common/xp-common-security/src/main/java/com/xiaopeng/common/security/config/WebMvcConfig.java
@@ -12,7 +12,18 @@
public class WebMvcConfig implements WebMvcConfigurer
{
    /** 不需要拦截地址 */
    public static final String[] excludeUrls = { "/login", "/logout", "/refresh" };
    public static final String[] excludeUrls = {
            "/login",
            "/logout",
            "/refresh",
            "/register",
            "/base/v1/login",
            "/base/v1/captcha",
            "/base/v1/operationPasswordLogin",
            "/base/v1/verificationCodeLogin",
            "/base/v1/getVerificationCode",
            "/base/v1/updatePassword"
    };
    @Override
    public void addInterceptors(InterceptorRegistry registry)
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/CaptchaConfig.java
File was deleted
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/KaptchaTextCreator.java
File was deleted
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/config/RouterFunctionConfiguration.java
@@ -1,19 +1,13 @@
package com.xiaopeng.gateway.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.cors.reactive.CorsUtils;
import org.springframework.web.reactive.function.server.RequestPredicates;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import com.xiaopeng.gateway.handler.ValidateCodeHandler;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
@@ -35,17 +29,6 @@
    private static final String ALLOWED_ORIGIN = "*";
    private static final String ALLOWED_EXPOSE = "*";
    private static final String MAX_AGE = "18000L";
    @Autowired
    private ValidateCodeHandler validateCodeHandler;
    @SuppressWarnings("rawtypes")
    @Bean
    public RouterFunction routerFunction() {
        return RouterFunctions.route(
                RequestPredicates.GET("/code").and(RequestPredicates.accept(MediaType.TEXT_PLAIN)),
                validateCodeHandler);
    }
    /**
     * 跨域配置
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/handler/ValidateCodeHandler.java
File was deleted
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/ValidateCodeService.java
@@ -1,9 +1,6 @@
package com.xiaopeng.gateway.service;
import java.io.IOException;
import com.xiaopeng.common.core.exception.CaptchaException;
import com.xiaopeng.common.core.web.domain.AjaxResult;
/**
 * 验证码处理
@@ -11,11 +8,6 @@
 * @author ruoyi
 */
public interface ValidateCodeService {
    /**
     * 生成验证码
     */
    public AjaxResult createCaptcha() throws IOException, CaptchaException;
    /**
     * 校验验证码
     */
xp-robotaxi-gateway-boot/src/main/java/com/xiaopeng/gateway/service/impl/ValidateCodeServiceImpl.java
@@ -1,24 +1,11 @@
package com.xiaopeng.gateway.service.impl;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FastByteArrayOutputStream;
import com.google.code.kaptcha.Producer;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.core.constant.Constants;
import com.xiaopeng.common.core.exception.CaptchaException;
import com.xiaopeng.common.core.utils.StringUtils;
import com.xiaopeng.common.core.utils.sign.Base64;
import com.xiaopeng.common.core.utils.uuid.IdUtils;
import com.xiaopeng.common.core.web.domain.AjaxResult;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.gateway.config.properties.CaptchaProperties;
import com.xiaopeng.gateway.service.ValidateCodeService;
/**
@@ -28,62 +15,9 @@
 */
@Service
public class ValidateCodeServiceImpl implements ValidateCodeService {
    @Resource(name = "captchaProducer")
    private Producer captchaProducer;
    @Resource(name = "captchaProducerMath")
    private Producer captchaProducerMath;
    @Autowired
    private RedisService redisService;
    @Autowired
    private CaptchaProperties captchaProperties;
    /**
     * 生成验证码
     */
    @Override
    public AjaxResult createCaptcha() throws IOException, CaptchaException {
        AjaxResult ajax = AjaxResult.success();
        boolean captchaEnabled = captchaProperties.getEnabled();
        ajax.put("captchaEnabled", captchaEnabled);
        if (!captchaEnabled) {
            return ajax;
        }
        // 保存验证码信息
        String uuid = IdUtils.simpleUUID();
        String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
        String capStr = null, code = null;
        BufferedImage image = null;
        String captchaType = captchaProperties.getType();
        // 生成验证码
        if ("math".equals(captchaType)) {
            String capText = captchaProducerMath.createText();
            capStr = capText.substring(0, capText.lastIndexOf("@"));
            code = capText.substring(capText.lastIndexOf("@") + 1);
            image = captchaProducerMath.createImage(capStr);
        } else if ("char".equals(captchaType)) {
            capStr = code = captchaProducer.createText();
            image = captchaProducer.createImage(capStr);
        }
        redisService.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
        // 转换流信息写出
        FastByteArrayOutputStream os = new FastByteArrayOutputStream();
        try {
            ImageIO.write(image, "jpg", os);
        } catch (IOException e) {
            return AjaxResult.error(e.getMessage());
        }
        ajax.put("uuid", uuid);
        ajax.put("img", Base64.encode(os.toByteArray()));
        return ajax;
    }
    
    /**
     * 校验验证码
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/constant/I18nKeyConstant.java
@@ -12,4 +12,5 @@
    String REPAIR_MONEY_TOO_LONG = "repair.money.too.long";
    String TASK_SAVE_ERROR = "task.save.error";
    String TASK_VEHICLE_NOT_EXIST = "task.vehicle.not.exist";
    String ACCIDENT_TYPE_NOT_EXIST = "accident.type.not.exist";
}
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/exportExcel/XpTaskExportExcel.java
@@ -25,7 +25,7 @@
    @Excel(name = "车牌",width = 20)
    private String plateNumber;
    @ApiModelProperty(value = "任务类别1常规 2事故")
    @Excel(name = "任务类别",width = 20)
    @Excel(name = "任务类别",width = 20, replace = {"常规_1","事故_2"})
    private Integer taskCategory;
    @ApiModelProperty(value = "类型")
    @Excel(name = "类型",width = 40)
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/service/impl/XpTaskServiceImpl.java
@@ -1852,6 +1852,12 @@
            Map<Long, List<XpErrorType>> errorType = errorTypeMapper.selectList(new LambdaQueryWrapper<XpErrorType>()
                            .in(XpErrorType::getId, Arrays.asList(task.getTaskTypeId().split(","))))
                    .stream().collect(Collectors.groupingBy(XpErrorType::getParentId));
            if (CollUtil.isEmpty(errorType)) {
                throw new ServiceException(
                        "事故类型不存在",
                        I18nKeyConstant.ACCIDENT_TYPE_NOT_EXIST
                );
            }
            List<XpErrorType> xpErrorTypes = errorType.get(0L);
            for (XpErrorType xpErrorType : xpErrorTypes) {
                xpErrorType.setChild(errorType.get(xpErrorType.getId()));
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages.properties
@@ -4,4 +4,5 @@
vehicle.not.exist=车辆不存在
repair.money.too.long=维修费用不能超过10字符
task.save.error=获取车辆实时定位信息失败,请稍后重试
task.vehicle.not.exist=上报失败,未获取到车辆信息
task.vehicle.not.exist=上报失败,未获取到车辆信息
accident.type.not.exist=事故类型不存在
xp-robotaxi-maintenance-boot/src/main/resources/i18n/messages_en_US.properties
@@ -5,4 +5,5 @@
repair.money.too.long=The maintenance cost cannot exceed 10 characters
task.save.error=Failed to obtain the real-time positioning information of the vehicle. Please try again later
task.vehicle.not.exist=The report failed and no vehicle information was obtained
accident.type.not.exist=The accident type does not exist.
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
@@ -5,4 +5,5 @@
repair.money.too.long=维修费用不能超过10字符
task.save.error=获取车辆实时定位信息失败,请稍后重试
task.vehicle.not.exist=上报失败,未获取到车辆信息
accident.type.not.exist=事故类型不存在
task.rule.not.config=未配置车辆事故任务分配规则
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/controller/XpElectronicFenceManagementController.java
@@ -39,8 +39,10 @@
import java.time.LocalDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static com.xiaopeng.map.service.serviceimpl.XpElectronicFenceServiceImpl.getPinyinInitials;
@@ -239,7 +241,7 @@
                    I18nKeyConstant.FENCE_STATUS_CANNOT_COPIED
            );
        }
        electronicFence.setElectronicName("副本_"+electronicFence.getElectronicName());
        electronicFence.setElectronicName(buildCopyFenceName(electronicFence.getElectronicName()));
        electronicFence.setId(null);
        electronicFence.setStatus(0);
        List<XpElectronicFenceArea> electronicFenceAreaList = xpElectronicFenceAreaService.lambdaQuery().eq(XpElectronicFenceArea::getElectronicId, id)
@@ -267,6 +269,21 @@
        return R.ok(electronicFence.getId());
    }
    private String buildCopyFenceName(String sourceName) {
        Set<String> existingNames = new HashSet<>(xpElectronicFenceService.lambdaQuery()
                .likeRight(XpElectronicFence::getElectronicName, sourceName)
                .list()
                .stream()
                .map(XpElectronicFence::getElectronicName)
                .collect(Collectors.toSet()));
        String candidateName = sourceName + "_副本";
        while (existingNames.contains(candidateName)) {
            candidateName = candidateName + "_副本";
        }
        return candidateName;
    }
    /**
     * 根据ID列表批量查询电子围栏
     *
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpAgreementController.java
@@ -44,13 +44,13 @@
    @ApiOperation(value = "获取协议/隐私政策",tags = {"运维APP-个人中心"},response = XpAgreementVo.class)
    @GetMapping("/base/v1/privacy/content/{type}")
    public R<XpAgreementVo> getAppContent(@ApiParam(name = "type", value = "类型 1=用户服务协议 2=平台隐私政策 ") @PathVariable Integer type) {
    public R<XpAgreementVo> getAppContent(@ApiParam(name = "type", value = "类型 8=运维APP-小鹏Robotaxi自动驾驶出行运维隐私政策 9=运维APP-第三方共享信息清单 10=运维APP-个人信息收集清单 11=运维APP-权限调用") @PathVariable Integer type) {
        return R.ok(xpAgreementService.getContentByType(type));
    }
    @ApiOperation(value = "获取协议",tags = {"管理后台-内容中心"})
    @GetMapping("/api/v1/agreement/content/{type}")
    public R<XpAgreement> getAgreementContent(@ApiParam(name = "type", value = "类型 1=用户服务协议 2=平台隐私政策 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明 7= 法律法规") @PathVariable Integer type) {
    public R<XpAgreement> getAgreementContent(@ApiParam(name = "type", value = "类型 1=小鹏Robotaxi隐私政策 2=个人信息收集清单 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明 7=权限说明 8=运维APP-小鹏Robotaxi自动驾驶出行运维隐私政策 9=运维APP-第三方共享信息清单 10=运维APP-个人信息收集清单 11=运维APP-权限调用") @PathVariable Integer type) {
        return R.ok(xpAgreementService.getAgreementContent(type));
    }
    @ApiOperation(value = "保存协议",tags = {"管理后台-内容中心"})
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpOpenCityController.java
@@ -11,6 +11,7 @@
import com.xiaopeng.operation.vo.OpenCityListVO;
import com.xiaopeng.operation.vo.XpOpenCityVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
@@ -51,8 +52,9 @@
     */
    @ApiOperation(value = "获取开通城市列表(管理后台)", tags = {"管理后台-交易管理"}, response = OpenCityListVO.class)
    @GetMapping("/api/v1/openCity/list")
    public R<List<OpenCityListVO>> getOpenCityList() {
        List<OpenCityListVO> list = xpOpenCityService.getOpenCityListForAdmin();
    @ApiImplicitParam(name = "type", value = "类型:1-路线规划配置使用 2-定价管理配置使用", required = true, dataTypeClass = Integer.class)
    public R<List<OpenCityListVO>> getOpenCityList(@RequestParam("type") Integer type) {
        List<OpenCityListVO> list = xpOpenCityService.getOpenCityListForAdmin(type);
        return R.ok(list);
    }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/dto/XpAgreementDTO.java
@@ -17,7 +17,7 @@
@ApiModel("协议数据传输对象")
public class XpAgreementDTO {
    @NotNull(message = "协议类型不能为空")
    @ApiModelProperty(value = "类型 1=用户服务协议 2=平台隐私政策 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明")
    @ApiModelProperty(value = "类型 1=小鹏Robotaxi隐私政策 2=个人信息收集清单 3=敏感个人信息处理情况说明 4=向第三方提供个人信息情况的说明 5=乘车须知 6=计费规则说明 7=权限说明 8=运维APP-小鹏Robotaxi自动驾驶出行运维隐私政策 9=运维APP-第三方共享信息清单 10=运维APP-个人信息收集清单 11=运维APP-权限调用")
    private Integer contentType;
    @NotBlank(message = "协议内容不能为空")
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpOpenCityService.java
@@ -9,7 +9,6 @@
import com.xiaopeng.operation.query.OpenCityPageQuery;
import com.xiaopeng.operation.vo.OpenCityListVO;
import com.xiaopeng.operation.vo.XpOpenCityVo;
import org.springframework.web.bind.annotation.RequestParam;
import javax.validation.Valid;
import java.util.List;
@@ -32,7 +31,7 @@
     *
     * @return 开通城市列表
     */
    List<OpenCityListVO> getOpenCityListForAdmin();
    List<OpenCityListVO> getOpenCityListForAdmin(Integer type);
    /**
     * 开通城市分页列表
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpAgreementServiceImpl.java
@@ -106,8 +106,8 @@
            this.save(xpAgreement);
        }
        // 判断是否需要发送通知(用户服务协议=1 或 平台隐私政策=2)
        if (dto.getContentType() != null && (dto.getContentType() == 1 || dto.getContentType() == 2)) {
        // 判断是否需要发送通知 8=运维APP-小鹏Robotaxi自动驾驶出行运维隐私政策 9=运维APP-第三方共享信息清单 10=运维APP-个人信息收集清单 11=运维APP-权限调用
        if (dto.getContentType() != null && (dto.getContentType() == 8 || dto.getContentType() == 9 || dto.getContentType() == 10 || dto.getContentType() == 11)) {
            // 发送协议更新提示通知(type=9)
            sendAgreementUpdateNotification(dto.getContentType());
            // 发送协议授权通知(type=10)
@@ -170,10 +170,15 @@
     * @return 协议类型名称
     */
    private String getAgreementTypeName(Integer contentType) {
        if (contentType == 1) {
            return "用户服务协议";
        } else if (contentType == 2) {
            return "平台隐私政策";
        switch (contentType) {
            case 8:
                return "小鹏Robotaxi自动驾驶出行运维隐私政策";
            case 9:
                return "第三方共享信息清单";
            case 10:
                return "个人信息收集清单";
            case 11:
                return "权限调用";
        }
        return "协议";
    }
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpOpenCityServiceImpl.java
@@ -2,23 +2,28 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpOpenCity;
import com.xiaopeng.api.model.operation.XpPricing;
import com.xiaopeng.api.model.operation.XpRoutePlan;
import com.xiaopeng.common.core.exception.ServiceException;
import com.xiaopeng.common.core.web.page.PageInfo;
import com.xiaopeng.common.security.utils.SecurityUtils;
import com.xiaopeng.operation.constant.I18nKeyConstant;
import com.xiaopeng.operation.dto.OpenCityAddDTO;
import com.xiaopeng.operation.dto.OpenCityEditDTO;
import com.xiaopeng.operation.mapper.XpOpenCityMapper;
import com.xiaopeng.operation.query.OpenCityPageQuery;
import com.xiaopeng.operation.service.IXpPricingItemService;
import com.xiaopeng.operation.service.IXpRoutePlanService;
import com.xiaopeng.operation.service.XpOpenCityService;
import com.xiaopeng.operation.service.XpPricingService;
import com.xiaopeng.operation.vo.OpenCityListVO;
import com.xiaopeng.operation.vo.XpOpenCityNextVo;
import com.xiaopeng.operation.vo.XpOpenCityVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
@@ -36,7 +41,11 @@
 */
@Service
public class XpOpenCityServiceImpl extends ServiceImpl<XpOpenCityMapper, XpOpenCity> implements XpOpenCityService {
    @Autowired
    private IXpRoutePlanService xpRoutePlanService;
    @Autowired
    private XpPricingService xpPricingService;
    @Override
@@ -59,14 +68,26 @@
    }
    @Override
    public List<OpenCityListVO> getOpenCityListForAdmin() {
    public List<OpenCityListVO> getOpenCityListForAdmin(Integer type) {
        // 1. 查询所有启用状态的开通城市
        List<XpOpenCity> xpOpenCities = this.baseMapper.selectList(
                new LambdaQueryWrapper<XpOpenCity>()
                        .eq(XpOpenCity::getStatus, 1)
                        .orderByAsc(XpOpenCity::getId)
        );
        List<Long> existsOpenCityIds = new ArrayList<>();
        //2.根据type过滤已配置的开通城市
        if (Integer.valueOf(1).equals(type)) {
            //路径规划
            existsOpenCityIds = xpRoutePlanService.list().stream().map(XpRoutePlan::getOpenCityId).collect(Collectors.toList());
        } else {
            //定价管理
            existsOpenCityIds = xpPricingService.list().stream().map(XpPricing::getCityId).collect(Collectors.toList());
        }
        if (CollUtil.isNotEmpty(existsOpenCityIds)) {
            List<Long> finalExistsOpenCityIds = existsOpenCityIds;
            xpOpenCities = xpOpenCities.stream().filter(item -> !finalExistsOpenCityIds.contains(item.getId())).collect(Collectors.toList());
        }
        // 2. 转换为VO,处理区/县级拼接逻辑
        return xpOpenCities.stream()
                .map(city -> {
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderEvaluateServiceImpl.java
@@ -2,6 +2,7 @@
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.dto.account.UcUserInfo;
import com.xiaopeng.api.feignClient.account.UserResourcesClient;
@@ -54,6 +55,31 @@
    @Override
    public PageInfo<OrderEvaluatePageVO> pageList(OrderEvaluatePageQuery query) {
        List<Long> vehicleIdsFilter = null;
        if (StringUtils.isNotBlank(query.getPlateNumber())) {
            R<List<XpVehicle>> vehicleResult = xpVehicleClient.listByPlateNumber(query.getPlateNumber());
            if (vehicleResult == null || CollectionUtils.isEmpty(vehicleResult.getData())) {
                return buildEmptyEvaluatePage(query);
            }
            vehicleIdsFilter = vehicleResult.getData().stream()
                    .map(XpVehicle::getId)
                    .filter(Objects::nonNull)
                    .distinct()
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(vehicleIdsFilter)) {
                return buildEmptyEvaluatePage(query);
            }
        }
        Long appUserIdFilter = null;
        if (StringUtils.isNotBlank(query.getPhoneNumber())) {
            UcUserInfo userByMobile = userResourcesClient.getUserByMobile(query.getPhoneNumber());
            if (userByMobile == null || userByMobile.getUid() == null) {
                return buildEmptyEvaluatePage(query);
            }
            appUserIdFilter = userByMobile.getUid();
        }
        // 1. 构建查询条件
        LambdaQueryWrapper<XpOrderEvaluate> wrapper = new LambdaQueryWrapper<>();
@@ -70,19 +96,22 @@
        if (Objects.nonNull(query.getOrderRating())) {
            wrapper.eq(XpOrderEvaluate::getOrderRating, query.getOrderRating());
        }
        if (!CollectionUtils.isEmpty(vehicleIdsFilter)) {
            wrapper.in(XpOrderEvaluate::getVehicleId, vehicleIdsFilter);
        }
        if (Objects.nonNull(appUserIdFilter)) {
            wrapper.eq(XpOrderEvaluate::getAppUserId, appUserIdFilter);
        }
        // 排序:按评价时间降序
        wrapper.orderByDesc(XpOrderEvaluate::getEvaluateTime);
        // 2. 分页查询
        PageInfo<XpOrderEvaluate> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        PageInfo<XpOrderEvaluate> evaluatePage = this.page(pageInfo, wrapper);
        Page<XpOrderEvaluate> evaluatePage = this.page(pageInfo, wrapper);
        if (CollectionUtils.isEmpty(evaluatePage.getRecords())) {
            PageInfo<OrderEvaluatePageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize());
            resultPage.setTotal(0L);
            resultPage.setRecords(new ArrayList<>());
            return resultPage;
            return buildEmptyEvaluatePage(query);
        }
        // 3. 收集关联ID
@@ -107,16 +136,22 @@
        Map<Long, XpVehicle> vehicleMap = batchGetVehicles(vehicleIds);
        Map<Long, XpOrder> orderMap = batchGetOrders(orderIds);
        // 5. 根据查询条件过滤(手机号、车牌号)
        // 5. 组装 VO
        List<OrderEvaluatePageVO> voList = evaluatePage.getRecords().stream()
                .map(evaluate -> convertToPageVO(evaluate, userInfoMap, vehicleMap, orderMap))
                .filter(vo -> filterByQuery(vo, query))
                .collect(Collectors.toList());
        // 6. 返回分页结果
        PageInfo<OrderEvaluatePageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize());
        resultPage.setTotal(evaluatePage.getTotal());
        resultPage.setRecords(voList);
        return resultPage;
    }
    private PageInfo<OrderEvaluatePageVO> buildEmptyEvaluatePage(OrderEvaluatePageQuery query) {
        PageInfo<OrderEvaluatePageVO> resultPage = new PageInfo<>(query.getPageNum(), query.getPageSize());
        resultPage.setTotal(0L);
        resultPage.setRecords(new ArrayList<>());
        return resultPage;
    }
@@ -225,28 +260,5 @@
        }
        return vo;
    }
    /**
     * 根据查询条件过滤
     */
    private boolean filterByQuery(OrderEvaluatePageVO vo, OrderEvaluatePageQuery query) {
        // 手机号过滤
        if (StringUtils.isNotBlank(query.getPhoneNumber())) {
            if (StringUtils.isBlank(vo.getPhoneNumber()) ||
                    !vo.getPhoneNumber().contains(query.getPhoneNumber())) {
                return false;
            }
        }
        // 车牌号过滤
        if (StringUtils.isNotBlank(query.getPlateNumber())) {
            if (StringUtils.isBlank(vo.getPlateNumber()) ||
                    !vo.getPlateNumber().contains(query.getPlateNumber())) {
                return false;
            }
        }
        return true;
    }
}
xp-robotaxi-vehicle-convoy-boot/pom.xml
@@ -122,6 +122,11 @@
            <artifactId>snakeyaml</artifactId>
            <version>1.33</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.25.3</version>
        </dependency>
        <!-- easypoi -->
        <!-- Apache POI 核心依赖 -->
        <dependency>
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/controller/XpVehicleController.java
@@ -42,6 +42,7 @@
import com.xiaopeng.vehicleConvoy.service.IXpFleetVehicleService;
import com.xiaopeng.vehicleConvoy.service.IXpVehicleAnnualRecordService;
import com.xiaopeng.vehicleConvoy.service.IXpVehicleService;
import com.xiaopeng.vehicleConvoy.util.AliOssDownloadUtil;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -105,6 +106,7 @@
    private final TokenService tokenService;
    private final XpVehicleRepairClient xpVehicleRepairClient;
    private final AliOssService aliOssService;
    private final AliOssDownloadUtil aliOssDownloadUtil;
    /**
     * 根据ID列表批量查询车辆信息(内部接口)
     *
@@ -685,8 +687,15 @@
        List<XpVehicleExportExcel> exportList = BeanUtil.copyToList(dataList, XpVehicleExportExcel.class);
        for (XpVehicleExportExcel xpVehicleExportExcel : exportList) {
            if (StringUtils.isNotBlank(xpVehicleExportExcel.getVehiclePictures())) {
                JSONObject jsonObject = JSONObject.parseObject(xpVehicleExportExcel.getVehiclePictures());
                xpVehicleExportExcel.setVehiclePictures(jsonObject.containsKey("url") ? jsonObject.getString("url") : "");
                String pictureJSONObject = aliOssDownloadUtil.getPictureJSONObject(xpVehicleExportExcel.getVehiclePictures());
                if (StringUtils.isNotBlank(pictureJSONObject)) {
                    JSONObject jsonObject = JSONObject.parseObject(pictureJSONObject);
                    xpVehicleExportExcel.setVehiclePictures(jsonObject.containsKey("url") ? jsonObject.getString("url") : "");
                }
            }
            if (Integer.valueOf(2).equals(xpVehicleExportExcel.getStatus()) && Integer.valueOf(1).equals(xpVehicleExportExcel.getOperatingStatus())) {
                xpVehicleExportExcel.setStatus(4);
            }
        }
        // 3. 生成Excel
@@ -996,6 +1005,17 @@
        return R.ok(hvacInnerTemp.getValue());
    }
    @ApiOperation(value = "通过订单id查询当前车辆车门状态", tags = {"小程序-业务流程"})
    @GetMapping("/api/v1/mini-program/order/queryVehicleTrunkOpenStatus")
    public R<VehicleTemperatureDto> queryVehicleTrunkOpenStatus(@RequestParam Long orderId, HttpServletRequest request) {
        String uid = request.getHeader("XP-Uid");
        VehicleTemperatureDto vehicleTemperatureDto = xpVehicleService.queryTemperatureByOrderId(orderId,uid);
        return R.ok(vehicleTemperatureDto);
    }
    /**
     * 获取车辆不分页列表
     *
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/model/exportExcel/XpVehicleExportExcel.java
@@ -44,7 +44,7 @@
    private String procurementSource;
    @ApiModelProperty(value = "车辆状态")
    @Excel(name = "车辆状态", width = 15, replace = {"待完善_1", "待运营_2", "保险/年检过期_3"})
    @Excel(name = "车辆状态", width = 15, replace = {"待完善_1", "待运营_2", "保险/年检过期_3", "运营_4"})
    private Integer status;
    @ApiModelProperty(value = "运营状态 1运营中 2维修中 3已收车 4车辆异常")
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/AliOssDownloadUtil.java
New file
@@ -0,0 +1,87 @@
package com.xiaopeng.vehicleConvoy.util;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xiaopeng.evi.oss.service.AliOssService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.util.Objects;
/**
 * @author MiTao
 * @date 2026-03-25 11:24
 *
 */
@Slf4j
@Component
public class AliOssDownloadUtil {
    @Autowired
    private AliOssService aliOssService;
    public String getPictureJsonArray(String json) {
        JSONArray res = new JSONArray();
        if (json == null || json.isEmpty()) {
            return res.toJSONString();
        }
        if (json.startsWith("{")) {
            JSONObject jsonObject = JSONObject.parseObject(json);
            if (Objects.isNull(jsonObject)) {
                return res.toJSONString();
            }
            String downloadUrl = "";
            try {
                downloadUrl = aliOssService.getDownloadUrl(
                        jsonObject.getString("id"), jsonObject.getString("name"), true);
            } catch (UnsupportedEncodingException e) {
                log.error("获取图片下载地址失败", e);
            }
            jsonObject.put("url", downloadUrl);
            res.add(jsonObject);
        } else if (json.startsWith("[")) {
            JSONArray jsonArray = JSONArray.parseArray(json);
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                if (Objects.isNull(jsonObject)) {
                    continue;
                }
                String downloadUrl = "";
                try {
                    downloadUrl = aliOssService.getDownloadUrl(
                            jsonObject.getString("id"), jsonObject.getString("name"), true);
                } catch (UnsupportedEncodingException e) {
                    log.error("获取图片下载地址失败", e);
                }
                jsonObject.put("url", downloadUrl);
            }
            res = jsonArray;
        }
        return res.toJSONString();
    }
    /**
     * JSONObject类型图片
     * @param json
     * @return
     */
    public String getPictureJSONObject(String json){
        JSONObject jsonObject = JSONObject.parseObject(json);
        if (Objects.isNull(jsonObject)) {
            return new JSONObject().toJSONString();
        }
        String downloadUrl = jsonObject.getString("url");
        try {
            downloadUrl = aliOssService.getDownloadUrl(
                    jsonObject.getString("id"), jsonObject.getString("name"), true);
        } catch (UnsupportedEncodingException e) {
            log.error("获取图片下载地址失败", e);
        }
        jsonObject.put("url", downloadUrl);
        return jsonObject.toJSONString();
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/util/VehicleControlUtil.java
@@ -42,7 +42,8 @@
    public VehicleTemperatureDto queryVehicleTemperature(String uid, String vin) {
        String nonce = System.currentTimeMillis() + "";
        Set<String> stateList = Collections.singleton("hvacInnerTemp");
        stateList.add("trunkAjarCloseSt");
        stateList.add("trunkAjarCloseSt");//后备箱开合状态0-关闭;1-打开
        stateList.add("driverDoorLockSt");//车门解锁状态0-unlock;1-locked
        Map<String, String> map = new HashMap<>();
        map.put("nonce", nonce);
        map.put("openId", OPEN_ID_ROBOT_TAXI);