#
Junjie
7 小时以前 656429e94f5989911bdf07848ef44b1cc71dfaf1
#
1个文件已添加
5个文件已修改
240 ■■■■■ 已修改文件
src/main/java/com/zy/asrs/controller/BasStationPathPolicyController.java 102 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/entity/BasStationPathProfile.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/service/impl/StationPathPolicyServiceImpl.java 44 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/sql/20260313_create_station_path_policy_tables.sql 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/resources/sql/20260319_migrate_station_path_default_profile_to_profile_table.sql 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/webapp/static/js/stationPathPolicy/stationPathPolicy.js 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/zy/asrs/controller/BasStationPathPolicyController.java
@@ -18,11 +18,7 @@
import com.zy.asrs.service.StationPathPolicyService;
import com.zy.common.model.NavigateNode;
import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.common.web.BaseController;
import com.zy.core.enums.RedisKeyType;
import com.zy.system.entity.Config;
import com.zy.system.service.ConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -41,16 +37,10 @@
@RequestMapping("/basStationPathPolicy")
public class BasStationPathPolicyController extends BaseController {
    private static final String CFG_DEFAULT_PROFILE_CODE = "stationPathDefaultProfileCode";
    @Autowired
    private BasStationPathProfileService basStationPathProfileService;
    @Autowired
    private BasStationPathRuleService basStationPathRuleService;
    @Autowired
    private ConfigService configService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private StationPathPolicyService stationPathPolicyService;
    @Autowired
@@ -63,11 +53,14 @@
    @RequestMapping("/data/auth")
    @ManagerAuth
    public R data() {
        List<BasStationPathProfile> profileList = basStationPathProfileService.list(new QueryWrapper<BasStationPathProfile>()
                .orderByDesc("is_default")
                .orderByAsc("priority", "id"));
        Map<String, Object> data = new HashMap<>();
        data.put("profiles", basStationPathProfileService.list(new QueryWrapper<BasStationPathProfile>().orderByAsc("priority", "id")));
        data.put("profiles", profileList);
        data.put("rules", basStationPathRuleService.list(new QueryWrapper<BasStationPathRule>().orderByAsc("priority", "id")));
        data.put("scoreMode", "twoStage");
        data.put("defaultProfileCode", getSystemConfig(CFG_DEFAULT_PROFILE_CODE, "default"));
        data.put("defaultProfileCode", resolveDefaultProfileCode(profileList));
        data.put("stations", buildStationSummaryList());
        data.put("levList", basMapService.getLevList());
        return R.ok(data);
@@ -78,11 +71,6 @@
    public R save(@RequestBody JSONObject payload) {
        JSONArray profiles = payload.getJSONArray("profiles");
        JSONArray rules = payload.getJSONArray("rules");
        upsertSystemConfig("站点路径默认模板编码", CFG_DEFAULT_PROFILE_CODE, defaultIfBlank(payload.getString("defaultProfileCode"), "default"), "String");
        basStationPathProfileService.remove(new QueryWrapper<>());
        basStationPathRuleService.remove(new QueryWrapper<>());
        List<BasStationPathProfile> profileList = new ArrayList<>();
        if (profiles != null) {
@@ -99,6 +87,7 @@
                profile.setProfileName(defaultIfBlank(item.getString("profileName"), item.getString("profileCode")));
                profile.setPriority(item.getInteger("priority") == null ? 100 : item.getInteger("priority"));
                profile.setStatus(item.getShort("status") == null ? (short) 1 : item.getShort("status"));
                profile.setIsDefault((short) 0);
                profile.setMemo(item.getString("memo"));
                Object configObj = item.get("config");
                if (configObj != null) {
@@ -109,6 +98,29 @@
                profileList.add(profile);
            }
        }
        if (profileList.isEmpty()) {
            return R.error("至少需要保留一个模板");
        }
        String defaultProfileCode = defaultIfBlank(payload.getString("defaultProfileCode"), profileList.get(0).getProfileCode());
        BasStationPathProfile defaultProfile = null;
        for (BasStationPathProfile profile : profileList) {
            if (profile != null && defaultProfileCode.equals(profile.getProfileCode())) {
                profile.setIsDefault((short) 1);
                defaultProfile = profile;
                break;
            }
        }
        if (defaultProfile == null) {
            return R.error("默认模板编码没有对应模板");
        }
        if (!Short.valueOf((short) 1).equals(defaultProfile.getStatus())) {
            return R.error("默认模板必须启用");
        }
        basStationPathProfileService.remove(new QueryWrapper<>());
        basStationPathRuleService.remove(new QueryWrapper<>());
        if (!profileList.isEmpty()) {
            basStationPathProfileService.saveBatch(profileList);
        }
@@ -143,8 +155,6 @@
        if (!ruleList.isEmpty()) {
            basStationPathRuleService.saveBatch(ruleList);
        }
        refreshSystemConfigCache();
        stationPathPolicyService.evictCache();
        return R.ok();
    }
@@ -265,44 +275,28 @@
        return result;
    }
    private void upsertSystemConfig(String name, String code, String value, String selectType) {
        String finalValue = value == null ? "" : value.trim();
        Config config = configService.getOne(new QueryWrapper<Config>().eq("code", code));
        if (config == null) {
            config = new Config(name, code, finalValue, (short) 1, (short) 1);
            config.setSelectType(selectType);
            configService.save(config);
        } else {
            config.setName(name);
            config.setValue(finalValue);
            config.setType((short) 1);
            config.setStatus((short) 1);
            config.setSelectType(selectType);
            configService.updateById(config);
    private String resolveDefaultProfileCode(List<BasStationPathProfile> profileList) {
        if (profileList == null || profileList.isEmpty()) {
            return "default";
        }
    }
    private void refreshSystemConfigCache() {
        HashMap<String, String> systemConfigMap = new HashMap<>();
        List<Config> configList = configService.list(new QueryWrapper<>());
        for (Config config : configList) {
            systemConfigMap.put(config.getCode(), config.getValue());
        }
        redisUtil.set(RedisKeyType.SYSTEM_CONFIG_MAP.key, systemConfigMap);
    }
    private String getSystemConfig(String code, String defaultValue) {
        Object mapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
        if (mapObj instanceof Map) {
            Object value = ((Map<?, ?>) mapObj).get(code);
            if (value != null) {
                String text = String.valueOf(value).trim();
                if (!text.isEmpty()) {
                    return text;
                }
        for (BasStationPathProfile profile : profileList) {
            if (profile != null
                    && Short.valueOf((short) 1).equals(profile.getIsDefault())
                    && !isBlank(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        return defaultValue;
        for (BasStationPathProfile profile : profileList) {
            if (profile != null && "default".equals(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        for (BasStationPathProfile profile : profileList) {
            if (profile != null && !isBlank(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        return "default";
    }
    private List<Integer> parseStationIdArray(JSONArray array) {
src/main/java/com/zy/asrs/entity/BasStationPathProfile.java
@@ -27,6 +27,9 @@
    private Short status;
    @TableField("is_default")
    private Short isDefault;
    @TableField("config_json")
    private String configJson;
src/main/java/com/zy/asrs/service/impl/StationPathPolicyServiceImpl.java
@@ -10,8 +10,6 @@
import com.zy.asrs.service.BasStationPathProfileService;
import com.zy.asrs.service.BasStationPathRuleService;
import com.zy.asrs.service.StationPathPolicyService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -32,8 +30,6 @@
    private BasStationPathProfileService basStationPathProfileService;
    @Autowired
    private BasStationPathRuleService basStationPathRuleService;
    @Autowired
    private RedisUtil redisUtil;
    private volatile CacheSnapshot cacheSnapshot = new CacheSnapshot();
    private volatile long cacheTime = 0L;
@@ -42,9 +38,9 @@
    public StationPathResolvedPolicy resolvePolicy(Integer startStationId, Integer endStationId) {
        StationPathResolvedPolicy resolved = new StationPathResolvedPolicy();
        resolved.setScoreMode("twoStage");
        resolved.setDefaultProfileCode(getSystemConfig("stationPathDefaultProfileCode", "default"));
        CacheSnapshot snapshot = getCacheSnapshot();
        resolved.setDefaultProfileCode(snapshot.defaultProfileCode);
        BasStationPathRule matchedRule = matchRule(snapshot.ruleList, startStationId, endStationId);
        BasStationPathProfile matchedProfile = null;
        if (matchedRule != null && notBlank(matchedRule.getProfileCode())) {
@@ -95,6 +91,7 @@
        try {
            List<BasStationPathProfile> profiles = basStationPathProfileService.list(new QueryWrapper<BasStationPathProfile>()
                    .eq("status", 1)
                    .orderByDesc("is_default")
                    .orderByAsc("priority", "id"));
            if (profiles != null) {
                snapshot.profileList.addAll(profiles);
@@ -103,6 +100,7 @@
                        snapshot.profileMap.put(profile.getProfileCode(), profile);
                    }
                }
                snapshot.defaultProfileCode = resolveDefaultProfileCode(profiles);
            }
        } catch (Exception e) {
            log.warn("加载站点路径模板失败,回退默认配置: {}", e.getMessage());
@@ -230,21 +228,28 @@
        return config;
    }
    private String getSystemConfig(String code, String defaultValue) {
        try {
            Object mapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
            if (mapObj instanceof Map) {
                Object value = ((Map<?, ?>) mapObj).get(code);
                if (value != null) {
                    String text = String.valueOf(value).trim();
                    if (!text.isEmpty()) {
                        return text;
                    }
                }
            }
        } catch (Exception ignore) {
    private String resolveDefaultProfileCode(List<BasStationPathProfile> profiles) {
        if (profiles == null || profiles.isEmpty()) {
            return "default";
        }
        return defaultValue;
        for (BasStationPathProfile profile : profiles) {
            if (profile != null
                    && Short.valueOf((short) 1).equals(profile.getIsDefault())
                    && notBlank(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        for (BasStationPathProfile profile : profiles) {
            if (profile != null && "default".equals(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        for (BasStationPathProfile profile : profiles) {
            if (profile != null && notBlank(profile.getProfileCode())) {
                return profile.getProfileCode();
            }
        }
        return "default";
    }
    private boolean notBlank(String value) {
@@ -257,6 +262,7 @@
    private static class CacheSnapshot {
        private boolean loaded = false;
        private String defaultProfileCode = "default";
        private final List<BasStationPathProfile> profileList = new ArrayList<>();
        private final List<BasStationPathRule> ruleList = new ArrayList<>();
        private final Map<String, BasStationPathProfile> profileMap = new HashMap<>();
src/main/resources/sql/20260313_create_station_path_policy_tables.sql
@@ -4,6 +4,7 @@
  `profile_name` VARCHAR(128) NOT NULL COMMENT '模板名称',
  `priority` INT NOT NULL DEFAULT 100 COMMENT '优先级,越小越优先',
  `status` TINYINT NOT NULL DEFAULT 1 COMMENT '状态 1启用 0禁用',
  `is_default` TINYINT NOT NULL DEFAULT 0 COMMENT '默认模板 1是 0否',
  `config_json` LONGTEXT NULL COMMENT '模板参数JSON',
  `memo` VARCHAR(255) NULL COMMENT '备注',
  `create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
@@ -37,22 +38,16 @@
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='输送站点路径人工规则';
INSERT INTO `asr_bas_station_path_profile`
(`profile_code`, `profile_name`, `priority`, `status`, `config_json`, `memo`)
(`profile_code`, `profile_name`, `priority`, `status`, `is_default`, `config_json`, `memo`)
SELECT
  'default',
  '默认模板',
  100,
  1,
  1,
  '{"calcMaxDepth":120,"calcMaxPaths":500,"calcMaxCost":300,"s1TopK":5,"s1LenWeight":1.0,"s1TurnWeight":3.0,"s1LiftWeight":8.0,"s1SoftDeviationWeight":4.0,"s1MaxLenRatio":1.15,"s1MaxTurnDiff":1,"s2BusyWeight":2.0,"s2RunBlockWeight":10.0,"s2LoopLoadWeight":12.0,"stationPathLenWeightPercent":50.0,"stationPathCongWeightPercent":50.0,"stationPathPassOtherOutStationWeightPercent":100.0,"stationPathPassOtherOutStationForceSkip":false}',
  '默认模板'
FROM dual
WHERE NOT EXISTS (
  SELECT 1 FROM `asr_bas_station_path_profile` WHERE `profile_code` = 'default'
);
INSERT INTO `sys_config`(`name`, `code`, `value`, `type`, `status`, `select_type`)
SELECT '站点路径默认模板编码', 'stationPathDefaultProfileCode', 'default', 1, 1, 'system'
FROM dual
WHERE NOT EXISTS (
  SELECT 1 FROM `sys_config` WHERE `code` = 'stationPathDefaultProfileCode'
);
src/main/resources/sql/20260319_migrate_station_path_default_profile_to_profile_table.sql
New file
@@ -0,0 +1,69 @@
SET @current_db := DATABASE();
SET @column_exists := (
  SELECT COUNT(1)
  FROM information_schema.COLUMNS
  WHERE TABLE_SCHEMA = @current_db
    AND TABLE_NAME = 'asr_bas_station_path_profile'
    AND COLUMN_NAME = 'is_default'
);
SET @add_column_sql := IF(
  @column_exists = 0,
  'ALTER TABLE asr_bas_station_path_profile ADD COLUMN is_default TINYINT NOT NULL DEFAULT 0 COMMENT ''默认模板 1是 0否'' AFTER status',
  'SELECT ''column is_default already exists'' '
);
PREPARE stmt_add_column FROM @add_column_sql;
EXECUTE stmt_add_column;
DEALLOCATE PREPARE stmt_add_column;
SET @default_profile_code := (
  SELECT COALESCE(MAX(TRIM(`value`)), 'default')
  FROM `sys_config`
  WHERE `code` = 'stationPathDefaultProfileCode'
);
UPDATE `asr_bas_station_path_profile`
SET `is_default` = 0;
UPDATE `asr_bas_station_path_profile`
SET `is_default` = 1
WHERE `profile_code` = @default_profile_code
  AND `status` = 1;
UPDATE `asr_bas_station_path_profile`
SET `is_default` = 1
WHERE `profile_code` = 'default'
  AND `status` = 1
  AND NOT EXISTS (
    SELECT 1
    FROM (
      SELECT `id`
      FROM `asr_bas_station_path_profile`
      WHERE `is_default` = 1
    ) t
  );
UPDATE `asr_bas_station_path_profile`
SET `is_default` = 1
WHERE `id` = (
  SELECT `id`
  FROM (
    SELECT `id`
    FROM `asr_bas_station_path_profile`
    WHERE `status` = 1
    ORDER BY `priority` ASC, `id` ASC
    LIMIT 1
  ) t
)
AND NOT EXISTS (
  SELECT 1
  FROM (
    SELECT `id`
    FROM `asr_bas_station_path_profile`
    WHERE `is_default` = 1
  ) t
);
DELETE FROM `sys_config`
WHERE `code` = 'stationPathDefaultProfileCode';
src/main/webapp/static/js/stationPathPolicy/stationPathPolicy.js
@@ -365,6 +365,17 @@
                this.$message.warning('默认模板编码没有对应模板')
                return
            }
            var defaultProfile = null
            for (var i = 0; i < this.profiles.length; i++) {
                if (this.profiles[i].profileCode === this.defaultProfileCode) {
                    defaultProfile = this.profiles[i]
                    break
                }
            }
            if (!defaultProfile || Number(defaultProfile.status) !== 1) {
                this.$message.warning('默认模板必须启用')
                return
            }
            var payload = {
                defaultProfileCode: this.defaultProfileCode,
                profiles: this.profiles.map(this.sanitizeProfileForSave),