liujie
2026-03-04 5515b16ec685193ee38e39d14f86886c7966b14d
Merge branch 'master' of http://120.76.84.145:10101/gitblit/r/java/Robotaxi
1个文件已添加
5个文件已修改
225 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/vehicleConvoy/BaseVehicleUserDto.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java 34 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/GDMapGeocodingUtil.java 56 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/dto/vehicleConvoy/BaseVehicleUserDto.java
@@ -6,7 +6,7 @@
@Data
public class BaseVehicleUserDto {
    /**
     * 状态码
     * 状态码 0成功
     */
    private Integer code;
    /**
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/service/serviceimpl/XpElectronicFenceServiceImpl.java
@@ -26,6 +26,7 @@
import com.xiaopeng.map.mapper.XpPointMapper;
import com.xiaopeng.map.mapper.XpRegionMapper;
import com.xiaopeng.map.service.XpElectronicFenceService;
import com.xiaopeng.map.utils.GDMapGeocodingUtil;
import com.xiaopeng.map.utils.PolygonOverlapService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
@@ -66,6 +67,8 @@
    private XpPointMapper xpPointMapper;
    @Autowired
    private XpRegionMapper xpRegionMapper;
    @Autowired
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    @Override
    public PageInfo<XpElectronicFence> pageList(ElectronicPageListQuery query) {
@@ -155,6 +158,16 @@
                }
            }
        }
        //根据经纬度获取当前城市code
        XpElectronicFenceArea xpElectronicFenceArea = dto.getElectronicFenceAreas().get(0);
        String[] split = xpElectronicFenceArea.getFencePoints().split(",")[0].split("_");
        Map<String, String> geocode = gdMapGeocodingUtil.geocode(split[0], split[1]);
        if(null == geocode){
            return R.fail("经纬度转换城市code失败");
        }
        String cityCode = geocode.get("cityCode");
        dto.setCityCode(cityCode);
        xpElectronicFence.setCityCode(dto.getCityCode());
        // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收
        XpRegion xpRegion = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>()
@@ -363,6 +376,15 @@
                    }
                }
            }
            //根据经纬度获取当前城市code
            XpElectronicFenceArea electronicFenceArea = dto.getElectronicFenceAreas().get(0);
            String[] split = electronicFenceArea.getFencePoints().split(",")[0].split("_");
            Map<String, String> geocode = gdMapGeocodingUtil.geocode(split[0], split[1]);
            if(null == geocode){
                return R.fail("经纬度转换城市code失败");
            }
            String cityCode = geocode.get("cityCode");
            dto.setCityCode(cityCode);
            xpElectronicFence.setCityCode(dto.getCityCode());
            this.updateById(xpElectronicFence);
xp-robotaxi-map-boot/src/main/java/com/xiaopeng/map/utils/GDMapGeocodingUtil.java
@@ -13,6 +13,7 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
 * 高德地图的地理编码工具类
@@ -121,4 +122,37 @@
        return jsonObject.getString("data");
    }
    /**
     * 根据经纬度获取行政区域信息
     * @param lon
     * @param lan
     * @return
     * @throws Exception
     */
    public Map<String, String> geocode(String lon, String lan) {
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        String forObject = HttpUtils.sendGet(url);
        JSONObject jsonObject = JSON.parseObject(forObject);
        Map<String, String> map = new HashMap<>();
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            String address = regeocode.getString("formatted_address");
            map.put("address", address);
            String code = addressComponent.getString("adcode");
            String province = addressComponent.getString("province");
            String city = addressComponent.getString("city");
            String district = addressComponent.getString("district");
            map.put("province", province);
            map.put("provinceCode", code.substring(0, 2) + "0000");
            map.put("city", city);
            map.put("cityCode", code.substring(0, 4) + "00");
            map.put("district", district);
            map.put("districtCode", code);
        }
        return map;
    }
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpElectronicFenceServiceImpl.java
@@ -28,6 +28,7 @@
import com.xiaopeng.operation.mapper.XpPointMapper;
import com.xiaopeng.operation.mapper.XpRegionMapper;
import com.xiaopeng.operation.service.IXpElectronicFenceService;
import com.xiaopeng.operation.utils.GDMapGeocodingUtil;
import com.xiaopeng.operation.utils.PolygonOverlapService;
import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.PinyinHelper;
@@ -67,6 +68,8 @@
    private XpPointMapper xpPointMapper;
    @Autowired
    private XpRegionMapper xpRegionMapper;
    @Autowired
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    @Override
    public PageInfo<XpElectronicFence> pageList(ElectronicPageListQuery query) {
@@ -157,6 +160,15 @@
                    }
                }
            }
            //根据经纬度获取当前城市code
            XpElectronicFenceArea xpElectronicFenceArea = dto.getElectronicFenceAreas().get(0);
            String[] split = xpElectronicFenceArea.getFencePoints().split(",")[0].split("_");
            Map<String, String> geocode = gdMapGeocodingUtil.geocode(split[0], split[1]);
            if(null == geocode){
                return R.fail("经纬度转换城市code失败");
            }
            String cityCode = geocode.get("cityCode");
            dto.setCityCode(cityCode);
            xpElectronicFence.setCityCode(dto.getCityCode());
            // 生成围栏id 规则:城市首字母-类型简写-4位自增流水号(如 SZ-OP-001),支持复制;数据停用或删除后,流水号不回收
            XpRegion xpRegion = xpRegionMapper.selectOne(new LambdaQueryWrapper<XpRegion>()
@@ -366,8 +378,16 @@
                    }
                }
            }
            //根据经纬度获取当前城市code
            XpElectronicFenceArea electronicFenceArea = dto.getElectronicFenceAreas().get(0);
            String[] split = electronicFenceArea.getFencePoints().split(",")[0].split("_");
            Map<String, String> geocode = gdMapGeocodingUtil.geocode(split[0], split[1]);
            if(null == geocode){
                return R.fail("经纬度转换城市code失败");
            }
            String cityCode = geocode.get("cityCode");
            dto.setCityCode(cityCode);
            xpElectronicFence.setCityCode(dto.getCityCode());
            this.updateById(xpElectronicFence);
            // 删除旧的区域数据,然后保存新的区域数据
            xpElectronicFenceAreaMapper.delete(new LambdaQueryWrapper<XpElectronicFenceArea>()
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/utils/GDMapGeocodingUtil.java
New file
@@ -0,0 +1,56 @@
package com.xiaopeng.operation.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xiaopeng.common.core.utils.HttpUtils;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
/**
 * 高德地图的地理编码工具类
 */
@Component
@Lazy
public class GDMapGeocodingUtil {
    private String key = "66ae577f63898dae3016d599fda57221";
    /**
     * 根据经纬度获取行政区域信息
     * @param lon
     * @param lan
     * @return
     * @throws Exception
     */
    public Map<String, String> geocode(String lon, String lan) {
        String url = "https://restapi.amap.com/v3/geocode/regeo?key=" + key + "&location=" + lon + "," + lan;
        String forObject = HttpUtils.sendGet(url);
        JSONObject jsonObject = JSON.parseObject(forObject);
        Map<String, String> map = new HashMap<>();
        if(jsonObject.getString("status").equals("1")){
            JSONObject regeocode = jsonObject.getJSONObject("regeocode");
            JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
            String address = regeocode.getString("formatted_address");
            map.put("address", address);
            String code = addressComponent.getString("adcode");
            String province = addressComponent.getString("province");
            String city = addressComponent.getString("city");
            String district = addressComponent.getString("district");
            map.put("province", province);
            map.put("provinceCode", code.substring(0, 2) + "0000");
            map.put("city", city);
            map.put("cityCode", code.substring(0, 4) + "00");
            map.put("district", district);
            map.put("districtCode", code);
        }
        return map;
    }
}
xp-robotaxi-vehicle-convoy-boot/src/main/java/com/xiaopeng/vehicleConvoy/service/impl/XpVehicleServiceImpl.java
@@ -49,6 +49,7 @@
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
@@ -348,21 +349,21 @@
        Locale locale = LocaleContextHolder.getLocale();
        if (dto.getAnnualInspectionDate() != null && dto.getAnnualInspectionDate().isBefore(now)) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                expiredItems.add("年检到期时间");
            } else {
                expiredItems.add("Annual inspection expiration date");
            }
        }
        if (dto.getInsuranceEndTime() != null && dto.getInsuranceEndTime().isBefore(now)) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                expiredItems.add("保险到期时间");
            } else {
                expiredItems.add("Insurance expiration date");
            }
        }
        if (dto.getQualificationExpireTime() != null && dto.getQualificationExpireTime().isBefore(now)) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                expiredItems.add("运营资质到期时间");
            } else {
                expiredItems.add("Operation qualification expiration date");
@@ -371,7 +372,7 @@
        if (!expiredItems.isEmpty()) {
            String detail;
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                detail = String.join("、", expiredItems);
            } else {
                detail = String.join("; ", expiredItems);
@@ -393,7 +394,7 @@
                || StringUtils.isBlank(vehicle.getInsurancePhone())
                || vehicle.getInsuranceEndTime() == null
                || StringUtils.isBlank(vehicle.getPolicyInformation())) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                missingItems.add("保险信息");
            } else {
                missingItems.add("Insurance information");
@@ -403,7 +404,7 @@
        // 校验年检信息
        if (vehicle.getAnnualInspectionDate() == null
                || StringUtils.isBlank(vehicle.getInspectionAttachments())) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                missingItems.add("年检信息");
            } else {
                missingItems.add("Annual inspection information");
@@ -412,7 +413,7 @@
        // 校验运营区域
        if (vehicle.getElectronicId() == null) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                missingItems.add("运营区域");
            } else {
                missingItems.add("Operation area");
@@ -422,7 +423,7 @@
        // 校验运营资质
        if (StringUtils.isBlank(vehicle.getOperationQualification())
                || vehicle.getQualificationExpireTime() == null) {
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                missingItems.add("运营资质");
            } else {
                missingItems.add("Operation qualification");
@@ -431,7 +432,7 @@
        if (!missingItems.isEmpty()) {
            String detail;
            if (locale.equals(Locale.CHINESE)) {
            if ("zh".equals(locale.getLanguage())) {
                detail = String.join("、", missingItems);
            } else {
                detail = String.join("; ", missingItems);
@@ -455,6 +456,32 @@
                && vehicle.getQualificationExpireTime() != null;
    }
    /**
     * 检查车辆是否有任意一项证件过期(精确到日期)
     * - 精确度:yyyy-MM-dd(只比较日期部分)
     * - 到期日期等于今天不算过期(使用 isBefore)
     * @param vehicle 车辆信息
     * @param today 今天日期
     */
    private boolean isAnyDateExpired(XpVehicle vehicle, LocalDate today) {
        // 年检到期时间检查:已过期
        if (vehicle.getAnnualInspectionDate() != null
                && vehicle.getAnnualInspectionDate().toLocalDate().isBefore(today)) {
            return true;
        }
        // 保险到期时间检查:已过期
        if (vehicle.getInsuranceEndTime() != null
                && vehicle.getInsuranceEndTime().toLocalDate().isBefore(today)) {
            return true;
        }
        // 运营资质到期时间检查:已过期
        if (vehicle.getQualificationExpireTime() != null
                && vehicle.getQualificationExpireTime().toLocalDate().isBefore(today)) {
            return true;
        }
        return false;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void batchOperation(String idStr) {
@@ -464,7 +491,7 @@
        List<String> ids = Arrays.asList(idStr.split(","));
        // 查询车辆完整信息
        List<XpVehicle> vehicles = this.listByIds(ids);
        LocalDateTime now = LocalDateTime.now();
        LocalDate now = LocalDate.now();
        List<String> errorMessages = new ArrayList<>();
        for (XpVehicle vehicle : vehicles) {
@@ -473,38 +500,38 @@
            // 校验状态为待运营
            if (!Integer.valueOf(2).equals(vehicle.getStatus())) {
                if (locale.equals(Locale.CHINESE)) {
                if ("zh".equals(locale.getLanguage())) {
                    reasons.add("状态非待运营");
                } else {
                    reasons.add("Status is not 'Pending Operation'");
                }
            }
            // 校验年检到期时间
            if (vehicle.getAnnualInspectionDate() == null || vehicle.getAnnualInspectionDate().isBefore(now)) {
                if (locale.equals(Locale.CHINESE)) {
            if (vehicle.getAnnualInspectionDate() == null || vehicle.getAnnualInspectionDate().toLocalDate().isBefore(now)) {
                if ("zh".equals(locale.getLanguage())) {
                    reasons.add("年检已过期");
                } else {
                    reasons.add("Annual inspection has expired");
                }
            }
            // 校验保险到期时间
            if (vehicle.getInsuranceEndTime() == null || vehicle.getInsuranceEndTime().isBefore(now)) {
                if (locale.equals(Locale.CHINESE)) {
            if (vehicle.getInsuranceEndTime() == null || vehicle.getInsuranceEndTime().toLocalDate().isBefore(now)) {
                if ("zh".equals(locale.getLanguage())) {
                    reasons.add("保险已过期");
                } else {
                    reasons.add("Insurance has expired");
                }
            }
            // 校验运营资质到期时间
            if (vehicle.getQualificationExpireTime() == null || vehicle.getQualificationExpireTime().isBefore(now)) {
                if (locale.equals(Locale.CHINESE)) {
            if (vehicle.getQualificationExpireTime() == null || vehicle.getQualificationExpireTime().toLocalDate().isBefore(now)) {
                if ("zh".equals(locale.getLanguage())) {
                    reasons.add("运营资质已过期");
                } else {
                    reasons.add("Operation qualification has expired");
                }
            }
            if (!reasons.isEmpty()) {
                if (locale.equals(Locale.CHINESE)) {
                if ("zh".equals(locale.getLanguage())) {
                    errorMessages.add("车辆[" + vehicle.getPlateNumber() + "]:" + String.join("、", reasons));
                } else {
                    errorMessages.add("Vehicles [" + vehicle.getPlateNumber() + "]: " + String.join("; ", reasons));
@@ -558,6 +585,32 @@
    public PageInfo<XpVehicle> vehiclePageList(VehiclePageQuery query) {
        PageInfo<XpVehicle> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<XpVehicle> list = this.baseMapper.vehiclePageList(pageInfo, query);
        if (CollUtil.isNotEmpty(list)) {
            LocalDate today = LocalDate.now();
            List<Long> expiredVehicleIds = new ArrayList<>();
            for (XpVehicle vehicle : list) {
                // 检查是否有任意一项过期(精确到 yyyy-MM-dd)
                boolean isExpired = isAnyDateExpired(vehicle, today);
                if (isExpired && !Integer.valueOf(3).equals(vehicle.getStatus())) {
                    // 记录需要更新状态的车辆ID
                    expiredVehicleIds.add(vehicle.getId());
                    // 同时更新返回结果中的状态
                    vehicle.setStatus(3);
                }
            }
            // 批量更新过期车辆状态到数据库
            if (CollUtil.isNotEmpty(expiredVehicleIds)) {
                LambdaUpdateWrapper<XpVehicle> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(XpVehicle::getId, expiredVehicleIds)
                             .set(XpVehicle::getStatus, 3);
                this.update(updateWrapper);
            }
        }
        pageInfo.setRecords(list);
        return pageInfo;
    }