liujie
2026-04-13 9b89d6842bdad135cd50fb5bc57c93e5ae306318
修改bug
4个文件已修改
201 ■■■■■ 已修改文件
xp-robotaxi-api/src/main/java/com/xiaopeng/api/enums/RouteStrategyKind.java 89 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpRoutePlan.java 4 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/RoutePreferenceItemVo.java 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java 106 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
xp-robotaxi-api/src/main/java/com/xiaopeng/api/enums/RouteStrategyKind.java
@@ -2,6 +2,16 @@
import lombok.Getter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
/**
 * 路线策略(与高德 strategy 参数对应,见 xp_route_plan 注释)
 */
@@ -12,7 +22,54 @@
    /** 时间优先 → 速度最快 */
    TIME(38, "时间优先", 2),
    /** 低价优先 → 少收费 */
    PRICE(36, "低价优先", 3);
    PRICE(36, "低价优先", 3),
    /** 躲避拥堵 */
    AVOID_CONGESTION(33, "躲避拥堵", 4),
    /** 高速优先 */
    HIGHWAY_PRIORITY(34, "高速优先", 5),
    /** 不走高速 */
    NO_HIGHWAY(35, "不走高速", 6),
    /** 大路优先 */
    MAIN_ROAD(37, "大路优先", 7),
    /** 躲避拥堵 + 高速优先 */
    AVOID_CONGESTION_HIGHWAY_PRIORITY(39, "躲避拥堵+高速优先", 8),
    /** 躲避拥堵 + 不走高速 */
    AVOID_CONGESTION_NO_HIGHWAY(40, "躲避拥堵+不走高速", 9),
    /** 躲避拥堵 + 少收费 */
    AVOID_CONGESTION_PRICE(41, "躲避拥堵+低价优先", 10),
    /** 少收费 + 不走高速 */
    PRICE_NO_HIGHWAY(42, "低价优先+不走高速", 11),
    /** 躲避拥堵 + 少收费 + 不走高速 */
    AVOID_CONGESTION_PRICE_NO_HIGHWAY(43, "躲避拥堵+低价优先+不走高速", 12),
    /** 躲避拥堵 + 大路优先 */
    AVOID_CONGESTION_MAIN_ROAD(44, "躲避拥堵+大路优先", 13),
    /** 躲避拥堵 + 速度最快 */
    AVOID_CONGESTION_TIME(45, "躲避拥堵+时间优先", 14),
    /** 速度优先,只返回一条路线 */
    SPEED_PRIORITY(0, "速度优先", 15),
    /** 费用优先,只返回一条路线 */
    FEE_PRIORITY(1, "费用优先", 16),
    /** 常规最快,只返回一条路线 */
    REGULAR_FASTEST(2, "常规最快", 17);
    private static final Comparator<RouteStrategyKind> BY_PRIORITY = Comparator.comparingInt(RouteStrategyKind::getPriority);
    private static final Map<Integer, RouteStrategyKind> AMAP_STRATEGY_INDEX;
    private static final List<RouteStrategyKind> ORDERED_VALUES;
    private static final List<RouteStrategyKind> DEFAULT_PREFERENCE_KINDS;
    static {
        Map<Integer, RouteStrategyKind> strategyIndex = new LinkedHashMap<>();
        for (RouteStrategyKind kind : values()) {
            strategyIndex.put(kind.amapStrategy, kind);
        }
        AMAP_STRATEGY_INDEX = Collections.unmodifiableMap(strategyIndex);
        List<RouteStrategyKind> orderedValues = new ArrayList<>(Arrays.asList(values()));
        orderedValues.sort(BY_PRIORITY);
        ORDERED_VALUES = Collections.unmodifiableList(orderedValues);
        DEFAULT_PREFERENCE_KINDS = Collections.unmodifiableList(Arrays.asList(SMART, TIME, PRICE));
    }
    private final int amapStrategy;
    private final String displayName;
@@ -25,21 +82,33 @@
    }
    /**
     * 主标签优先级:数值越小越优先(智能 &gt; 时间 &gt; 低价)
     * 主标签优先级:数值越小越优先(默认保留智能 &gt; 时间 &gt; 低价,再补充其余全量策略)
     */
    public static RouteStrategyKind primaryOf(java.util.Collection<RouteStrategyKind> kinds) {
    public static RouteStrategyKind primaryOf(Collection<RouteStrategyKind> kinds) {
        if (kinds == null || kinds.isEmpty()) {
            return SMART;
        }
        return kinds.stream().min((a, b) -> Integer.compare(a.priority, b.priority)).orElse(SMART);
        return kinds.stream().min(BY_PRIORITY).orElse(SMART);
    }
    public static java.util.Optional<RouteStrategyKind> fromAmapStrategy(int strategy) {
        for (RouteStrategyKind k : values()) {
            if (k.amapStrategy == strategy) {
                return java.util.Optional.of(k);
            }
    public static Optional<RouteStrategyKind> fromAmapStrategy(int strategy) {
        return Optional.ofNullable(AMAP_STRATEGY_INDEX.get(strategy));
    }
    public static List<RouteStrategyKind> orderedValues() {
        return ORDERED_VALUES;
    }
    public static List<RouteStrategyKind> defaultPreferenceKinds() {
        return DEFAULT_PREFERENCE_KINDS;
    }
    public static List<RouteStrategyKind> orderedOf(Collection<RouteStrategyKind> kinds) {
        if (kinds == null || kinds.isEmpty()) {
            return Collections.emptyList();
        }
        return java.util.Optional.empty();
        List<RouteStrategyKind> ordered = new ArrayList<>(kinds);
        ordered.sort(BY_PRIORITY);
        return ordered;
    }
}
xp-robotaxi-api/src/main/java/com/xiaopeng/api/model/operation/XpRoutePlan.java
@@ -68,12 +68,12 @@
            "36:少收费\n" +
            "37:大路优先\n" +
            "38:速度最快\n" +
            "躲避拥堵+高速优先39:\n" +
            "39:躲避拥堵+高速优先\n" +
            "40:躲避拥堵+不走高速\n" +
            "41:躲避拥堵+少收费\n" +
            "42:少收费+不走高速\n" +
            "43:躲避拥堵+少收费+不走高速\n" +
            "44:与躲避拥堵+大路优先\n" +
            "44:躲避拥堵+大路优先\n" +
            "45:躲避拥堵+速度最快")
    private Integer routePlanRule;
xp-robotaxi-api/src/main/java/com/xiaopeng/api/vo/operation/RoutePreferenceItemVo.java
@@ -8,7 +8,7 @@
@ApiModel("路线偏好选项")
public class RoutePreferenceItemVo {
    @ApiModelProperty("策略编码 SMART/TIME/PRICE")
    @ApiModelProperty("策略编码,如 SMART/TIME/PRICE/AVOID_CONGESTION")
    private String code;
    @ApiModelProperty("展示名称")
xp-robotaxi-itinerary-boot/src/main/java/com/xiaopeng/itinerary/service/impl/XpPricingServiceImpl.java
@@ -131,7 +131,6 @@
    @Resource
    private GDMapGeocodingUtil gdMapGeocodingUtil;
    @Resource
    private XpPointClient xpPointClient;
@@ -142,7 +141,7 @@
    private double navigationPriceWavePercent;
    /**
     * 后台可配置的偏好项编码,逗号分隔,如 SMART,TIME,PRICE
     * 后台可配置的偏好项编码,逗号分隔,如 SMART,TIME,PRICE,AVOID_CONGESTION
     */
    @Value("${navigation.route.preference.enabled-codes:SMART,TIME,PRICE}")
    private String navigationPreferenceEnabledCodes;
@@ -907,7 +906,8 @@
            throw new ServiceException("当前区域未开通服务", I18nKeyConstant.NO_CURRENT_REGION);
        }
        List<RouteStrategyKind> kinds = buildStrategyKindsForPlanning(userId);
        StrategyPlanningConfig planningConfig = buildStrategyKindsForPlanning(userId, routeAndFareDto.getOpenCityId());
        List<RouteStrategyKind> kinds = planningConfig.getKinds();
        Map<String, RouteVo> routeById = new LinkedHashMap<>();
        Map<String, Set<RouteStrategyKind>> strategiesById = new LinkedHashMap<>();
        for (RouteStrategyKind kind : kinds) {
@@ -946,14 +946,11 @@
            RouteAndFareVo part = pricingForRoute(pricingDto, rv, xpPricing, userId);
            RouteOptionVo opt = new RouteOptionVo();
            opt.setPathFingerprint(fid);
            List<String> labels = new ArrayList<>();
            for (RouteStrategyKind k : Arrays.asList(RouteStrategyKind.SMART, RouteStrategyKind.TIME, RouteStrategyKind.PRICE)) {
                if (kindsOnRoute.contains(k)) {
                    labels.add(k.getDisplayName());
                }
            }
            List<String> labels = RouteStrategyKind.orderedOf(kindsOnRoute).stream()
                    .map(kind -> resolveStrategyDisplayName(kind, planningConfig.getDisplayNames()))
                    .collect(Collectors.toList());
            opt.setStrategyLabels(labels);
            opt.setPrimaryStrategyLabel(primary.getDisplayName());
            opt.setPrimaryStrategyLabel(resolveStrategyDisplayName(primary, planningConfig.getDisplayNames()));
            opt.setPrimaryRoutePlanRule(primary.getAmapStrategy());
            opt.setRoute(part.getRoute());
            opt.setFareEstimate(part.getFareEstimate());
@@ -1063,15 +1060,16 @@
    public List<RoutePreferenceItemVo> listRoutePreferences(Long openCityId, String userId) {
        Set<String> enabledCodes = parseEnabledPreferenceCodes();
        Optional<RouteStrategyKind> savedPref = resolveUserPreferredKind(userId);
        Map<RouteStrategyKind, String> displayNames = buildStrategyKindsForPlanning(userId, openCityId).getDisplayNames();
        List<RoutePreferenceItemVo> list = new ArrayList<>();
        int i = 0;
        for (RouteStrategyKind k : Arrays.asList(RouteStrategyKind.SMART, RouteStrategyKind.TIME, RouteStrategyKind.PRICE)) {
        for (RouteStrategyKind k : RouteStrategyKind.orderedValues()) {
            if (!enabledCodes.contains(k.name())) {
                continue;
            }
            RoutePreferenceItemVo v = new RoutePreferenceItemVo();
            v.setCode(k.name());
            v.setName(k.getDisplayName());
            v.setName(resolveStrategyDisplayName(k, displayNames));
            v.setEnabled(true);
            v.setSortOrder(i++);
            v.setAmapStrategy(k.getAmapStrategy());
@@ -1101,9 +1099,9 @@
            }
        }
        if (set.isEmpty()) {
            set.add(RouteStrategyKind.SMART.name());
            set.add(RouteStrategyKind.TIME.name());
            set.add(RouteStrategyKind.PRICE.name());
            for (RouteStrategyKind kind : RouteStrategyKind.defaultPreferenceKinds()) {
                set.add(kind.name());
            }
        }
        return set;
    }
@@ -1111,24 +1109,43 @@
    /**
     * 用户偏好策略优先请求,其余策略仍请求以便合并去重。
     */
    private List<RouteStrategyKind> buildStrategyKindsForPlanning(String userId) {
        List<RouteStrategyKind> all = new ArrayList<>();
    private StrategyPlanningConfig buildStrategyKindsForPlanning(String userId, Long openCityId) {
        Set<String> enabled = parseEnabledPreferenceCodes();
        for (RouteStrategyKind k : Arrays.asList(RouteStrategyKind.SMART, RouteStrategyKind.TIME, RouteStrategyKind.PRICE)) {
        List<XpRoutePlan> xpRoutePlans = xpRoutePlanMapper.selectList(new LambdaQueryWrapper<XpRoutePlan>().eq(XpRoutePlan::getOpenCityId, openCityId));
        Map<RouteStrategyKind, String> displayNames = new LinkedHashMap<>();
        List<RouteStrategyKind> configuredKinds = new ArrayList<>();
        if (xpRoutePlans.isEmpty()) {
            configuredKinds.addAll(RouteStrategyKind.defaultPreferenceKinds());
        } else {
            for (XpRoutePlan xpRoutePlan : xpRoutePlans) {
                Integer strategy = xpRoutePlan.getRoutePlanRule();
                if (strategy == null) {
                    continue;
                }
                RouteStrategyKind.fromAmapStrategy(strategy).ifPresent(kind -> {
                    configuredKinds.add(kind);
                    if (StringUtils.isNotBlank(xpRoutePlan.getPlanName())) {
                        displayNames.putIfAbsent(kind, xpRoutePlan.getPlanName().trim());
                    }
                });
            }
        }
        List<RouteStrategyKind> all = new ArrayList<>();
        for (RouteStrategyKind k : configuredKinds) {
            if (enabled.contains(k.name())) {
                all.add(k);
                addIfAbsent(all, k);
            }
        }
        if (all.isEmpty()) {
            all.add(RouteStrategyKind.SMART);
            all.add(resolveDefaultEnabledKind(enabled));
        }
        Optional<RouteStrategyKind> pref = resolveUserPreferredKind(userId);
        if (!pref.isPresent()) {
            return all;
            return new StrategyPlanningConfig(all, displayNames);
        }
        RouteStrategyKind p = pref.get();
        if (!all.contains(p)) {
            return all;
            return new StrategyPlanningConfig(all, displayNames);
        }
        List<RouteStrategyKind> ordered = new ArrayList<>();
        ordered.add(p);
@@ -1137,7 +1154,50 @@
                ordered.add(k);
            }
        }
        return ordered;
        return new StrategyPlanningConfig(ordered, displayNames);
    }
    private String resolveStrategyDisplayName(RouteStrategyKind kind, Map<RouteStrategyKind, String> displayNames) {
        String configuredName = displayNames.get(kind);
        return StringUtils.isNotBlank(configuredName) ? configuredName : kind.getDisplayName();
    }
    private void addIfAbsent(List<RouteStrategyKind> kinds, RouteStrategyKind kind) {
        if (!kinds.contains(kind)) {
            kinds.add(kind);
        }
    }
    private RouteStrategyKind resolveDefaultEnabledKind(Set<String> enabled) {
        for (RouteStrategyKind kind : RouteStrategyKind.defaultPreferenceKinds()) {
            if (enabled.contains(kind.name())) {
                return kind;
            }
        }
        for (RouteStrategyKind kind : RouteStrategyKind.orderedValues()) {
            if (enabled.contains(kind.name())) {
                return kind;
            }
        }
        return RouteStrategyKind.SMART;
    }
    private static final class StrategyPlanningConfig {
        private final List<RouteStrategyKind> kinds;
        private final Map<RouteStrategyKind, String> displayNames;
        private StrategyPlanningConfig(List<RouteStrategyKind> kinds, Map<RouteStrategyKind, String> displayNames) {
            this.kinds = kinds;
            this.displayNames = displayNames;
        }
        private List<RouteStrategyKind> getKinds() {
            return kinds;
        }
        private Map<RouteStrategyKind, String> getDisplayNames() {
            return displayNames;
        }
    }
    private Optional<RouteStrategyKind> resolveUserPreferredKind(String userId) {