package com.zy.asrs.service.impl;
|
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.core.exception.CoolException;
|
import com.zy.asrs.service.RuntimeConfigService;
|
import com.zy.system.entity.Config;
|
import com.zy.system.service.ConfigService;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.stereotype.Service;
|
import org.springframework.transaction.annotation.Transactional;
|
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
import java.util.Objects;
|
import java.util.Set;
|
|
@Service("runtimeConfigService")
|
public class RuntimeConfigServiceImpl implements RuntimeConfigService {
|
|
private static final LinkedHashMap<String, RuntimeConfigRule> RUNTIME_CONFIG_RULE_MAP = buildRuntimeConfigRuleMap();
|
|
@Autowired
|
private ConfigService configService;
|
|
@Override
|
@Transactional
|
public Map<String, Object> updateRuntimeConfig(Map<String, Object> configMap) {
|
if (configMap == null || configMap.isEmpty()) {
|
throw new CoolException("参数不能为空");
|
}
|
|
LinkedHashMap<String, String> normalizedMap = new LinkedHashMap<>();
|
for (Map.Entry<String, Object> entry : configMap.entrySet()) {
|
String code = entry.getKey();
|
RuntimeConfigRule rule = RUNTIME_CONFIG_RULE_MAP.get(code);
|
if (rule == null) {
|
throw new CoolException("不支持的运行参数: " + code);
|
}
|
|
Config config = getConfig(code);
|
if (config == null) {
|
throw new CoolException("运行参数不存在: " + code);
|
}
|
if (!Short.valueOf((short) 1).equals(config.getStatus())) {
|
throw new CoolException("运行参数已禁用: " + code);
|
}
|
|
normalizedMap.put(code, rule.normalize(code, entry.getValue()));
|
}
|
|
LinkedHashMap<String, String> changedMap = saveChangedConfig(normalizedMap);
|
if (!changedMap.isEmpty()) {
|
configService.refreshSystemConfigCache();
|
}
|
|
LinkedHashMap<String, Object> result = new LinkedHashMap<>();
|
result.put("changed", changedMap);
|
result.put("current", buildRuntimeConfigSnapshot(normalizedMap.keySet()));
|
return result;
|
}
|
|
private LinkedHashMap<String, String> saveChangedConfig(LinkedHashMap<String, String> normalizedMap) {
|
LinkedHashMap<String, String> changedMap = new LinkedHashMap<>();
|
for (Map.Entry<String, String> entry : normalizedMap.entrySet()) {
|
Config config = getConfig(entry.getKey());
|
if (config == null) {
|
throw new CoolException("运行参数不存在: " + entry.getKey());
|
}
|
if (Objects.equals(config.getValue(), entry.getValue())) {
|
continue;
|
}
|
config.setValue(entry.getValue());
|
if (!configService.updateById(config)) {
|
throw new CoolException("保存失败: " + entry.getKey());
|
}
|
changedMap.put(entry.getKey(), entry.getValue());
|
}
|
return changedMap;
|
}
|
|
private LinkedHashMap<String, String> buildRuntimeConfigSnapshot(Set<String> codeSet) {
|
LinkedHashMap<String, String> result = new LinkedHashMap<>();
|
for (String code : codeSet) {
|
Config config = getConfig(code);
|
if (config != null) {
|
result.put(code, config.getValue());
|
}
|
}
|
return result;
|
}
|
|
private Config getConfig(String code) {
|
return configService.getOne(new QueryWrapper<Config>().eq("code", code).last("limit 1"));
|
}
|
|
private static LinkedHashMap<String, RuntimeConfigRule> buildRuntimeConfigRuleMap() {
|
LinkedHashMap<String, RuntimeConfigRule> ruleMap = new LinkedHashMap<>();
|
putIntRule(ruleMap, "conveyorStationTaskLimit", 1, 1000);
|
putIntRule(ruleMap, "stationMaxTaskCountLimit", 0, 1000);
|
putIntRule(ruleMap, "stationCommandSendLength", 1, 200);
|
putRatioRule(ruleMap, "stationCommandSegmentAdvanceRatio");
|
putIntRule(ruleMap, "stationCommandConfigRefreshSeconds", 5, 300);
|
putIntRule(ruleMap, "stationV5SegmentExecutorPoolSize", 16, 512);
|
putIntRule(ruleMap, "stationV5SegmentExecutorQueueCapacity", 64, 4096);
|
putIntRule(ruleMap, "crnOutBatchRunningLimit", 0, 1000);
|
putBooleanRule(ruleMap, "crnOutRequireStationOutEnable");
|
putIntRule(ruleMap, "deviceCommandAutoRollbackLimit", 1, 100);
|
putBooleanRule(ruleMap, "checkDeepLocOutTaskBlockReport");
|
return ruleMap;
|
}
|
|
private static void putIntRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap,
|
String code,
|
int min,
|
int max) {
|
ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.INT, min, max));
|
}
|
|
private static void putRatioRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap, String code) {
|
ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.RATIO, 0, 100));
|
}
|
|
private static void putBooleanRule(LinkedHashMap<String, RuntimeConfigRule> ruleMap, String code) {
|
ruleMap.put(code, new RuntimeConfigRule(RuntimeConfigValueType.BOOLEAN, 0, 0));
|
}
|
|
private enum RuntimeConfigValueType {
|
INT,
|
RATIO,
|
BOOLEAN
|
}
|
|
private static class RuntimeConfigRule {
|
|
private final RuntimeConfigValueType valueType;
|
private final int min;
|
private final int max;
|
|
private RuntimeConfigRule(RuntimeConfigValueType valueType, int min, int max) {
|
this.valueType = valueType;
|
this.min = min;
|
this.max = max;
|
}
|
|
private String normalize(String code, Object rawValue) {
|
if (rawValue == null) {
|
throw new CoolException(code + " 参数不能为空");
|
}
|
String value = String.valueOf(rawValue).trim();
|
if (value.isEmpty()) {
|
throw new CoolException(code + " 参数不能为空");
|
}
|
if (RuntimeConfigValueType.BOOLEAN.equals(valueType)) {
|
return normalizeBoolean(code, value);
|
}
|
if (RuntimeConfigValueType.RATIO.equals(valueType)) {
|
return normalizeRatio(code, value);
|
}
|
return normalizeInt(code, value);
|
}
|
|
private String normalizeBoolean(String code, String value) {
|
if ("Y".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "1".equals(value)) {
|
return "Y";
|
}
|
if ("N".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value) || "0".equals(value)) {
|
return "N";
|
}
|
throw new CoolException(code + " 仅支持 Y/N、true/false 或 1/0");
|
}
|
|
private String normalizeRatio(String code, String value) {
|
String text = value;
|
boolean percentText = text.endsWith("%");
|
if (percentText) {
|
text = text.substring(0, text.length() - 1).trim();
|
}
|
double parsed;
|
try {
|
parsed = Double.parseDouble(text);
|
} catch (Exception e) {
|
throw new CoolException(code + " 必须为 0~1 比例或 0~100 百分比");
|
}
|
if (parsed < 0d || parsed > 100d) {
|
throw new CoolException(code + " 必须为 0~1 比例或 0~100 百分比");
|
}
|
if (percentText || parsed > 1d) {
|
parsed = parsed / 100d;
|
}
|
return stripTrailingZero(parsed);
|
}
|
|
private String normalizeInt(String code, String value) {
|
int parsed;
|
try {
|
parsed = Integer.parseInt(value);
|
} catch (Exception e) {
|
throw new CoolException(code + " 必须为整数");
|
}
|
if (parsed < min || parsed > max) {
|
throw new CoolException(code + " 必须在 " + min + "~" + max + " 范围内");
|
}
|
return String.valueOf(parsed);
|
}
|
|
private String stripTrailingZero(double value) {
|
String text = java.math.BigDecimal.valueOf(value).stripTrailingZeros().toPlainString();
|
return "-0".equals(text) ? "0" : text;
|
}
|
}
|
}
|