puzhibing
2026-02-13 1ccbc5624eb3c7b194cfede0681494e12a10eb0b
Merge remote-tracking branch 'origin/master'
2个文件已添加
8个文件已修改
379 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-map-boot/src/main/resources/bootstrap.yml 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpRegionService.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java 125 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/RegionCascaderVO.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/RegionDistrictSyncResultVO.java 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpRegionMapper.xml 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java 1 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -25,4 +25,5 @@
com.xiaopeng.api.factory.vehicleConvoy.VehicleControlClientFallbackFactory
com.xiaopeng.api.factory.automaticPilot.XPUClientFallbackFactory
com.xiaopeng.api.factory.automaticPilot.XpuVimClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpCheckLocationClientFallbackFactory
com.xiaopeng.api.factory.maintenance.XpCheckLocationClientFallbackFactory
com.xiaopeng.api.factory.automaticPilot.OrderMissionClientFallbackFactory
xp-robotaxi-common/xp-common-core/src/main/java/com/xiaopeng/common/core/constant/CacheConstants.java
@@ -84,6 +84,11 @@
     */
    public static final String XP_REGION_CITY = "XP_REGION_CITY";
    /**
     * 省市区级联树
     */
    public static final String XP_REGION_CASCADER = "XP_REGION_CASCADER";
    /**
     * 节假日
xp-robotaxi-map-boot/src/main/resources/bootstrap.yml
@@ -159,137 +159,3 @@
        shared-configs:
          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
---
spring:
  shardingsphere:
    mode:
      type: Standalone
      repository:
        type: File
      overwrite: true
    datasource:
      names: xp0
      xp0:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://192.168.110.34:3306/xprt_operation?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
        username: root
        password: 123456
        druid:
          # 连接池初始化时创建的连接数。
          # 应根据实际应用场景设置,确保应用程序启动时即可获取数据库连接。
          initial-size: 10
          # 连接池中最小的空闲连接数,保证即使在低负载时也有足够的连接可用。
          min-idle: 10
          # 连接池中最大活动连接数,限制并发请求时的数据库连接数,避免过多的连接消耗系统资源。
          max-active: 100
          # 获取连接时的最大等待时间,超过该时间则抛出异常。单位通常为毫秒。
          max-wait: 60000
          # 两个连接检查之间的时间间隔,用于检测和清理空闲过久的连接。单位为毫秒。
          time-between-eviction-runs-millis: 60000
          # 连接在被清理前的最小空闲时间。单位为毫秒。
          min-evictable-idle-time-millis: 300000
          # 用于验证连接有效性的 SQL 查询语句。
          validation-query: SELECT 1
          # 如果为真,则连接空闲时会被定期测试有效性。
          test-while-idle: true
          # 如果为真,在获取连接前进行有效性测试。
          test-on-borrow: false
          # 如果为真,在归还连接时进行有效性测试。
          test-on-return: false
          # 是否开启 PreparedStatement 缓存。
          pool-prepared-statements: true
          # 单个连接上缓存的 PreparedStatement 最大数量。
          max-pool-prepared-statement-per-connection-size: 20
          # 指定要启用的过滤器,如 stat, log4j, wall 等,用于监控和日志记录。
          filters: stat,wall,log4j
          # 连接属性,例如配置日志级别或慢 SQL 阈值。
          connection-properties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
          # 是否自动回收超时连接
          remove-abandoned: true
          # 超时时间,单位秒
          remove-abandoned-timeout: 1800
          # 是否记录被遗弃的连接
          log-abandoned: true
          # StatViewServlet配置,访问监控页面
          stat-view-servlet:
            enabled: true
            url-pattern: /druid/*
            login-username: admin
            login-password: admin
            reset-enable: false
          # 防火墙配置
          wall:
            config:
              multi-statement-allow: false
    rules:
      sharding:
        tables:
          sys_oper_log:
            standard:
              sharding-column: userId
              sharding-algorithm-name: sys_oper_log_inline
            key-generate-strategy:
              column: oper_id
              key-generator-name: snowflake
          xp_agreement_app_user:
            standard:
              sharding-column: app_user_id
              sharding-algorithm-name: xp_agreement_app_user_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
          xp_point:
            standard:
              sharding-column: id
              sharding-algorithm-name: xp_point_inline
            key-generate-strategy:
              column: id
              key-generator-name: snowflake
      sharding-algorithms:
        sys_oper_log_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.sys_oper_log_${userId % 10}
        xp_agreement_app_user_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_agreement_app_user_${app_user_id % 10}
        xp_point_inline:
          type: INLINE
          props:
            algorithm-expression: xp0.xp_point_${id % 10}
        single-table:
          tables:
            - xp0.sys_config
            - xp0.sys_dict_data
            - xp0.sys_dict_type
            - xp0.sys_logininfor
            - xp0.sys_menu
            - xp0.xp_acticity
            - xp0.xp_acticity_coupon
            - xp0.xp_agreement
            - xp0.xp_banner
            - xp0.xp_coupon
            - xp0.xp_electronic_fence
            - xp0.xp_electronic_fence_area
            - xp0.xp_feedback_type
            - xp0.xp_frequently_asked_questions
            - xp0.xp_invitation_code
            - xp0.xp_notification
            - xp0.xp_open_city
            - xp0.xp_pricing
            - xp0.xp_pricing_item
            - xp0.xp_region
            - xp0.xp_ride_guide
            - xp0.xp_route_plan
            - xp0.xp_system_setting
            - xp0.xp_trading_strategy
            - xp0.xp_trading_strategy_city
            - xp0.xp_user_feedback
            - xp0.xp_whitelist
            - xp0.xp_whitelist_operlog
    props:
      sql-show: true
      sql-simple: true
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/controller/XpRegionController.java
@@ -11,6 +11,7 @@
import com.xiaopeng.operation.query.getProvinceQuery;
import com.xiaopeng.operation.service.XpOpenCityService;
import com.xiaopeng.operation.service.XpRegionService;
import com.xiaopeng.operation.vo.RegionCascaderVO;
import com.xiaopeng.operation.vo.RegionDistrictSyncResultVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -100,6 +101,15 @@
    }
    /**
     * 管理后台-省市区三级级联查询
     */
    @ApiOperation(value = "管理后台-省市区三级级联查询", tags = {"管理后台-省市区管理"})
    @GetMapping("/api/v1/region/cascader")
    public R<List<RegionCascaderVO>> getRegionCascader() {
        return R.ok(regionService.getRegionCascader());
    }
    /**
     * 管理后台-同步区级数据
     */
    @ApiOperation(value = "管理后台-同步区级数据", tags = {"管理后台-省市区管理"})
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/XpRegionService.java
@@ -3,6 +3,7 @@
import com.baomidou.mybatisplus.extension.service.IService;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.operation.vo.RegionCascaderVO;
import com.xiaopeng.operation.vo.RegionDistrictSyncResultVO;
import java.util.List;
@@ -24,6 +25,12 @@
    List<List<XpRegion>> getXpRegion();
    /**
     * 管理后台-省市区三级级联查询
     * @return 级联树
     */
    List<RegionCascaderVO> getRegionCascader();
    /**
     * 从xp_region_all同步区级数据到xp_region
     * @return 同步结果
     */
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/service/impl/XpRegionServiceImpl.java
@@ -3,19 +3,27 @@
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xiaopeng.api.model.operation.XpOpenCity;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.common.core.constant.CacheConstants;
import com.xiaopeng.common.redis.service.RedisService;
import com.xiaopeng.operation.mapper.XpRegionMapper;
import com.xiaopeng.api.model.operation.XpRegion;
import com.xiaopeng.operation.service.XpOpenCityService;
import com.xiaopeng.operation.service.XpRegionService;
import com.xiaopeng.operation.vo.RegionCascaderVO;
import com.xiaopeng.operation.vo.RegionDistrictSyncResultVO;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -31,6 +39,8 @@
    @Resource
    private RedisService redisService;
    @Resource
    private XpOpenCityService openCityService;
    @Override
    public List<List<XpRegion>> getXpRegion() {
@@ -69,10 +79,116 @@
    }
    @Override
    public List<RegionCascaderVO> getRegionCascader() {
        List<Object> cacheList = redisService.getCacheList(CacheConstants.XP_REGION_CASCADER);
        if (cacheList != null && !cacheList.isEmpty()) {
            try {
                return cacheList.stream()
                        .filter(item -> item instanceof RegionCascaderVO)
                        .map(item -> (RegionCascaderVO) item)
                        .collect(Collectors.toList());
            } catch (ClassCastException e) {
                redisService.deleteObject(CacheConstants.XP_REGION_CASCADER);
            }
        }
        List<XpRegion> regionList = this.baseMapper.selectList(Wrappers.lambdaQuery(XpRegion.class));
        if (regionList == null || regionList.isEmpty()) {
            return Collections.emptyList();
        }
        List<XpOpenCity> openCityList = openCityService.list(Wrappers.lambdaQuery(XpOpenCity.class)
                .eq(XpOpenCity::getStatus, 1));
        Set<String> openCityCodeSet = openCityList.stream()
                .map(XpOpenCity::getCityCode)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toCollection(HashSet::new));
        Set<String> openDistrictCodeSet = openCityList.stream()
                .map(XpOpenCity::getDistrictCode)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toCollection(HashSet::new));
        Map<Long, List<XpRegion>> childrenMap = regionList.stream()
                .collect(Collectors.groupingBy(region -> region.getParentId() == null ? 0L : region.getParentId()));
        List<XpRegion> provinceList = childrenMap.getOrDefault(0L, Collections.emptyList()).stream()
                .sorted(REGION_COMPARATOR)
                .collect(Collectors.toList());
        List<RegionCascaderVO> result = provinceList.stream()
                .map(region -> buildRegionNode(region, childrenMap, openCityCodeSet, openDistrictCodeSet))
                .collect(Collectors.toList());
        redisService.setCacheList(CacheConstants.XP_REGION_CASCADER, result);
        return result;
    }
    private RegionCascaderVO buildRegionNode(XpRegion current,
                                             Map<Long, List<XpRegion>> childrenMap,
                                             Set<String> openCityCodeSet,
                                             Set<String> openDistrictCodeSet) {
        List<XpRegion> children = childrenMap.getOrDefault(current.getId(), Collections.emptyList()).stream()
                .sorted(REGION_COMPARATOR)
                .collect(Collectors.toList());
        List<RegionCascaderVO> childNodes = children.stream()
                .map(child -> buildRegionNode(child, childrenMap, openCityCodeSet, openDistrictCodeSet))
                .collect(Collectors.toList());
        Integer level = resolveRegionLevel(current.getCode());
        Integer selfOpen = resolveSelfOpen(level, current.getCode(), openCityCodeSet, openDistrictCodeSet);
        boolean hasOpenChild = childNodes.stream().anyMatch(node -> Integer.valueOf(1).equals(node.getIsOpen()));
        RegionCascaderVO node = new RegionCascaderVO();
        node.setCode(current.getCode());
        node.setName(current.getName());
        node.setLeaf(Integer.valueOf(3).equals(level));
        node.setChildren(childNodes);
        node.setIsOpen(selfOpen == 1 || hasOpenChild ? 1 : 0);
        return node;
    }
    private Integer resolveRegionLevel(String code) {
        if (StringUtils.isBlank(code) || code.length() < 4) {
            return 3;
        }
        if (code.endsWith("0000")) {
            return 1;
        }
        if (code.endsWith("00")) {
            return 2;
        }
        return 3;
    }
    private Integer resolveSelfOpen(Integer level,
                                    String code,
                                    Set<String> openCityCodeSet,
                                    Set<String> openDistrictCodeSet) {
        if (StringUtils.isBlank(code)) {
            return 0;
        }
        if (Integer.valueOf(2).equals(level)) {
            return openCityCodeSet.contains(code) ? 1 : 0;
        }
        if (Integer.valueOf(3).equals(level)) {
            return openDistrictCodeSet.contains(code) ? 1 : 0;
        }
        return 0;
    }
    private static final Comparator<XpRegion> REGION_COMPARATOR = Comparator
            .comparing((XpRegion region) -> StringUtils.defaultString(region.getInitial()))
            .thenComparing((XpRegion region) -> StringUtils.defaultString(region.getCode()));
    @Override
    @Transactional(rollbackFor = Exception.class)
    public RegionDistrictSyncResultVO syncDistrictFromRegionAll() {
        Long cityCount = Objects.requireNonNullElse(this.baseMapper.countCityForDistrictSync(), 0L);
        Long candidateDistrictCount = Objects.requireNonNullElse(this.baseMapper.countCandidateDistrictForSync(), 0L);
        Long cityCount = this.baseMapper.countCityForDistrictSync();
        if (cityCount == null) {
            cityCount = 0L;
        }
        Long candidateDistrictCount = this.baseMapper.countCandidateDistrictForSync();
        if (candidateDistrictCount == null) {
            candidateDistrictCount = 0L;
        }
        List<XpRegion> missingDistrictList = this.baseMapper.selectMissingDistrictFromRegionAll();
        long insertedCount = 0L;
@@ -83,6 +199,7 @@
        redisService.deleteObject(CacheConstants.XP_REGION);
        redisService.deleteObject(CacheConstants.XP_REGION_CITY);
        redisService.deleteObject(CacheConstants.XP_REGION_CASCADER);
        RegionDistrictSyncResultVO result = new RegionDistrictSyncResultVO();
        result.setCityCount(cityCount);
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/RegionCascaderVO.java
New file
@@ -0,0 +1,33 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
/**
 * 省市区级联节点
 */
@Data
@ApiModel(value = "省市区级联节点")
public class RegionCascaderVO implements Serializable {
    private static final long serialVersionUID = 1L;
    @ApiModelProperty(value = "行政区编码")
    private String code;
    @ApiModelProperty(value = "行政区名称")
    private String name;
    @ApiModelProperty(value = "是否开通 0否1是")
    private Integer isOpen;
    @ApiModelProperty(value = "是否叶子节点")
    private Boolean leaf;
    @ApiModelProperty(value = "子节点")
    private List<RegionCascaderVO> children;
}
xp-robotaxi-operation-boot/src/main/java/com/xiaopeng/operation/vo/RegionDistrictSyncResultVO.java
New file
@@ -0,0 +1,25 @@
package com.xiaopeng.operation.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(value = "区级数据同步结果")
public class RegionDistrictSyncResultVO {
    @ApiModelProperty(value = "参与同步的市级总数")
    private Long cityCount;
    @ApiModelProperty(value = "候选区级总数")
    private Long candidateDistrictCount;
    @ApiModelProperty(value = "实际新增数量")
    private Long insertedCount;
    @ApiModelProperty(value = "跳过数量")
    private Long skippedCount;
    @ApiModelProperty(value = "结果信息")
    private String message;
}
xp-robotaxi-operation-boot/src/main/resources/mapper/operation/XpRegionMapper.xml
@@ -2,6 +2,42 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xiaopeng.operation.mapper.XpRegionMapper">
    <select id="selectMissingDistrictFromRegionAll" resultType="com.xiaopeng.api.model.operation.XpRegion">
        select
            district.name as name,
            district.code as code,
            district.citycode as cityCode,
            city.id as parentId,
            district.english as english,
            city.initial as initial
        from xp_region city
                 join xp_region_all all_city on all_city.code = city.code
                 join xp_region_all district on district.parent_id = all_city.id
                 left join xp_region existing on existing.code = district.code
        where city.parentId != 0
          and city.code like '%00'
          and city.code not like '%0000'
          and existing.id is null
        order by city.code, district.code
    </select>
    <select id="countCityForDistrictSync" resultType="java.lang.Long">
        select count(1)
        from xp_region city
                 join xp_region_all all_city on all_city.code = city.code
        where city.parentId != 0
          and city.code like '%00'
          and city.code not like '%0000'
    </select>
    <select id="countCandidateDistrictForSync" resultType="java.lang.Long">
        select count(1)
        from xp_region city
                 join xp_region_all all_city on all_city.code = city.code
                 join xp_region_all district on district.parent_id = all_city.id
        where city.parentId != 0
          and city.code like '%00'
          and city.code not like '%0000'
    </select>
</mapper>
xp-robotaxi-order-boot/src/main/java/com/xiaopeng/order/service/impl/XpOrderServiceImpl.java
@@ -131,7 +131,6 @@
    private final XpPushMessageClient xpPushMessageClient;
    private final OrderMissionClient orderMissionClient;
    private final XpOrderDetailMapper xpOrderDetailMapper;
    private final OrderMissionClient orderMissionClient;
    @Autowired
    private MongoTemplate mongoTemplate;