界面优化
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
package com.solution.rule.domain.config;
|
||||
|
||||
import com.solution.common.annotation.Excel;
|
||||
import lombok.Data;
|
||||
|
||||
@Data
|
||||
public class RuleConfigExcelRow {
|
||||
|
||||
@Excel(name = "规则编码")
|
||||
private String ruleCode;
|
||||
|
||||
@Excel(name = "规则名称")
|
||||
private String ruleName;
|
||||
|
||||
@Excel(name = "层级编码")
|
||||
private String levelCode;
|
||||
|
||||
@Excel(name = "类别编码")
|
||||
private String kindCode;
|
||||
|
||||
@Excel(name = "模块编码")
|
||||
private String moduleCode;
|
||||
|
||||
@Excel(name = "优先级", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Integer priorityNo;
|
||||
|
||||
@Excel(name = "条件表达式", width = 24)
|
||||
private String conditionExpr;
|
||||
|
||||
@Excel(name = "动作表达式", width = 24)
|
||||
private String actionExpr;
|
||||
|
||||
@Excel(name = "版本号", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Integer versionNo;
|
||||
|
||||
@Excel(name = "规则启用", cellType = Excel.ColumnType.NUMERIC, prompt = "1=启用,0=停用")
|
||||
private Integer enabled;
|
||||
|
||||
@Excel(name = "备注", width = 20)
|
||||
private String remark;
|
||||
|
||||
@Excel(name = "任务类型列表", width = 20, prompt = "多个任务类型用英文逗号分隔")
|
||||
private String taskTypesCsv;
|
||||
|
||||
@Excel(name = "参数名称")
|
||||
private String paramName;
|
||||
|
||||
@Excel(name = "参数键")
|
||||
private String paramKey;
|
||||
|
||||
@Excel(name = "参数值", width = 24)
|
||||
private String paramVal;
|
||||
|
||||
@Excel(name = "参数值类型")
|
||||
private String valType;
|
||||
|
||||
@Excel(name = "参数排序", cellType = Excel.ColumnType.NUMERIC)
|
||||
private Integer sortNo;
|
||||
|
||||
@Excel(name = "参数启用", cellType = Excel.ColumnType.NUMERIC, prompt = "1=启用,0=停用")
|
||||
private Integer paramEnabled;
|
||||
|
||||
@Excel(name = "参数备注", width = 20)
|
||||
private String paramRemark;
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.solution.rule.service;
|
||||
|
||||
import com.solution.rule.domain.config.RuleConfig;
|
||||
import com.solution.rule.domain.config.RuleConfigExcelRow;
|
||||
import com.solution.rule.domain.config.RuleConfigQuery;
|
||||
import com.solution.rule.domain.config.RuleDictItem;
|
||||
import com.solution.rule.domain.config.RuleParamMeta;
|
||||
@@ -28,6 +29,10 @@ public interface IRuleConfigService {
|
||||
|
||||
List<RuleParamMeta> selectParamMetaList();
|
||||
|
||||
List<RuleConfigExcelRow> exportRuleConfigRows(RuleConfigQuery query);
|
||||
|
||||
String importRuleConfigRows(List<RuleConfigExcelRow> rows, boolean updateSupport);
|
||||
|
||||
/**
|
||||
* 根据当前页规则主数据构建知识图谱(节点与边),参数与任务类型从库批量加载。
|
||||
*/
|
||||
|
||||
@@ -4,6 +4,7 @@ import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.solution.common.constant.ExceptionConstants;
|
||||
import com.solution.rule.domain.config.RuleConfig;
|
||||
import com.solution.rule.domain.config.RuleConfigExcelRow;
|
||||
import com.solution.rule.domain.config.RuleConfigParam;
|
||||
import com.solution.rule.domain.config.RuleConfigQuery;
|
||||
import com.solution.rule.domain.config.RuleConfigTaskTypeRow;
|
||||
@@ -131,6 +132,118 @@ public class RuleConfigServiceImpl implements IRuleConfigService {
|
||||
return new ArrayList<>(metaMap().values());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<RuleConfigExcelRow> exportRuleConfigRows(RuleConfigQuery query) {
|
||||
List<RuleConfig> configs = selectRuleConfigList(query == null ? new RuleConfigQuery() : query);
|
||||
List<RuleConfigExcelRow> rows = new ArrayList<>();
|
||||
for (RuleConfig config : configs) {
|
||||
if (config == null || ObjectUtil.isEmpty(config.getRuleCode())) {
|
||||
continue;
|
||||
}
|
||||
RuleConfig detail = selectRuleConfigByCode(config.getRuleCode());
|
||||
if (detail == null) {
|
||||
continue;
|
||||
}
|
||||
List<RuleConfigParam> params = CollUtil.isNotEmpty(detail.getParams()) ? detail.getParams() : Collections.singletonList(new RuleConfigParam());
|
||||
String taskTypesCsv = joinTaskTypes(detail.getTaskTypes());
|
||||
for (RuleConfigParam param : params) {
|
||||
RuleConfigExcelRow row = new RuleConfigExcelRow();
|
||||
row.setRuleCode(detail.getRuleCode());
|
||||
row.setRuleName(detail.getRuleName());
|
||||
row.setLevelCode(detail.getLevelCode());
|
||||
row.setKindCode(detail.getKindCode());
|
||||
row.setModuleCode(detail.getModuleCode());
|
||||
row.setPriorityNo(detail.getPriorityNo());
|
||||
row.setConditionExpr(detail.getConditionExpr());
|
||||
row.setActionExpr(detail.getActionExpr());
|
||||
row.setVersionNo(detail.getVersionNo());
|
||||
row.setEnabled(detail.getEnabled());
|
||||
row.setRemark(detail.getRemark());
|
||||
row.setTaskTypesCsv(taskTypesCsv);
|
||||
if (param != null) {
|
||||
row.setParamName(param.getParamName());
|
||||
row.setParamKey(param.getParamKey());
|
||||
row.setParamVal(param.getParamVal());
|
||||
row.setValType(param.getValType());
|
||||
row.setSortNo(param.getSortNo());
|
||||
row.setParamEnabled(param.getEnabled());
|
||||
row.setParamRemark(param.getRemark());
|
||||
}
|
||||
rows.add(row);
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String importRuleConfigRows(List<RuleConfigExcelRow> rows, boolean updateSupport) {
|
||||
if (CollUtil.isEmpty(rows)) {
|
||||
throw new RuntimeException("Import data cannot be empty");
|
||||
}
|
||||
Map<String, RuleConfig> grouped = new LinkedHashMap<>();
|
||||
for (RuleConfigExcelRow row : rows) {
|
||||
if (row == null || isEmptyImportRow(row)) {
|
||||
continue;
|
||||
}
|
||||
String ruleCode = trimmed(row.getRuleCode());
|
||||
if (ObjectUtil.isEmpty(ruleCode)) {
|
||||
throw new RuntimeException("Import failed: ruleCode is required");
|
||||
}
|
||||
RuleConfig config = grouped.computeIfAbsent(ruleCode, code -> {
|
||||
RuleConfig rc = new RuleConfig();
|
||||
rc.setRuleCode(code);
|
||||
rc.setParams(new ArrayList<>());
|
||||
rc.setTaskTypes(new ArrayList<>());
|
||||
return rc;
|
||||
});
|
||||
mergeRuleBase(config, row);
|
||||
if (ObjectUtil.isNotEmpty(trimmed(row.getParamKey()))) {
|
||||
RuleConfigParam param = new RuleConfigParam();
|
||||
param.setRuleCode(ruleCode);
|
||||
param.setParamName(trimmed(row.getParamName()));
|
||||
param.setParamKey(trimmed(row.getParamKey()));
|
||||
param.setParamVal(trimmed(row.getParamVal()));
|
||||
param.setValType(trimmed(row.getValType()));
|
||||
param.setSortNo(row.getSortNo());
|
||||
param.setEnabled(row.getParamEnabled());
|
||||
param.setRemark(trimmed(row.getParamRemark()));
|
||||
config.getParams().add(param);
|
||||
}
|
||||
}
|
||||
if (grouped.isEmpty()) {
|
||||
throw new RuntimeException("Import data cannot be empty");
|
||||
}
|
||||
|
||||
int inserted = 0;
|
||||
int updated = 0;
|
||||
for (RuleConfig config : grouped.values()) {
|
||||
fillImportDefaults(config);
|
||||
validateBase(config);
|
||||
if (CollUtil.isEmpty(config.getParams())) {
|
||||
throw new RuntimeException("Rule " + config.getRuleCode() + " must contain at least one param row");
|
||||
}
|
||||
boolean exists = ruleConfigMapper.countByRuleCode(config.getRuleCode()) > 0;
|
||||
if (exists) {
|
||||
if (!updateSupport) {
|
||||
throw new RuntimeException("Rule already exists: " + config.getRuleCode());
|
||||
}
|
||||
ruleConfigMapper.updateRuleConfig(fillDefault(config));
|
||||
String[] ruleCodes = {config.getRuleCode()};
|
||||
ruleConfigMapper.deleteParamsByRuleCodes(ruleCodes);
|
||||
ruleConfigMapper.deleteTaskTypesByRuleCodes(ruleCodes);
|
||||
saveChildren(config);
|
||||
updated++;
|
||||
} else {
|
||||
ruleConfigMapper.insertRuleConfig(fillDefault(config));
|
||||
saveChildren(config);
|
||||
inserted++;
|
||||
}
|
||||
}
|
||||
syncDrlAfterCrud();
|
||||
return "Import completed. inserted=" + inserted + ", updated=" + updated;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RuleGraphVO buildKnowledgeGraph(List<RuleConfig> ruleConfigs) {
|
||||
RuleGraphVO graph = new RuleGraphVO();
|
||||
@@ -595,6 +708,107 @@ public class RuleConfigServiceImpl implements IRuleConfigService {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
private boolean isEmptyImportRow(RuleConfigExcelRow row) {
|
||||
return ObjectUtil.isAllEmpty(
|
||||
trimmed(row.getRuleCode()),
|
||||
trimmed(row.getRuleName()),
|
||||
trimmed(row.getParamKey()),
|
||||
trimmed(row.getParamVal()),
|
||||
trimmed(row.getTaskTypesCsv()));
|
||||
}
|
||||
|
||||
private void mergeRuleBase(RuleConfig config, RuleConfigExcelRow row) {
|
||||
config.setRuleName(mergeStringField(config.getRuleCode(), "ruleName", config.getRuleName(), row.getRuleName()));
|
||||
config.setLevelCode(mergeStringField(config.getRuleCode(), "levelCode", config.getLevelCode(), row.getLevelCode()));
|
||||
config.setKindCode(mergeStringField(config.getRuleCode(), "kindCode", config.getKindCode(), row.getKindCode()));
|
||||
config.setModuleCode(mergeStringField(config.getRuleCode(), "moduleCode", config.getModuleCode(), row.getModuleCode()));
|
||||
config.setConditionExpr(mergeStringField(config.getRuleCode(), "conditionExpr", config.getConditionExpr(), row.getConditionExpr()));
|
||||
config.setActionExpr(mergeStringField(config.getRuleCode(), "actionExpr", config.getActionExpr(), row.getActionExpr()));
|
||||
config.setRemark(mergeStringField(config.getRuleCode(), "remark", config.getRemark(), row.getRemark()));
|
||||
config.setPriorityNo(mergeIntegerField(config.getRuleCode(), "priorityNo", config.getPriorityNo(), row.getPriorityNo()));
|
||||
config.setVersionNo(mergeIntegerField(config.getRuleCode(), "versionNo", config.getVersionNo(), row.getVersionNo()));
|
||||
config.setEnabled(mergeIntegerField(config.getRuleCode(), "enabled", config.getEnabled(), row.getEnabled()));
|
||||
String taskTypesCsv = trimmed(row.getTaskTypesCsv());
|
||||
if (ObjectUtil.isNotEmpty(taskTypesCsv)) {
|
||||
List<String> parsed = parseTaskTypes(taskTypesCsv);
|
||||
if (CollUtil.isNotEmpty(config.getTaskTypes()) && !config.getTaskTypes().equals(parsed)) {
|
||||
throw new RuntimeException("Rule " + config.getRuleCode() + " has conflicting taskTypesCsv values");
|
||||
}
|
||||
config.setTaskTypes(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
private void fillImportDefaults(RuleConfig config) {
|
||||
if (config.getParams() == null) {
|
||||
config.setParams(new ArrayList<>());
|
||||
}
|
||||
if (config.getTaskTypes() == null) {
|
||||
config.setTaskTypes(new ArrayList<>());
|
||||
}
|
||||
int sortNo = 0;
|
||||
for (RuleConfigParam param : config.getParams()) {
|
||||
if (param.getSortNo() == null) {
|
||||
param.setSortNo(sortNo);
|
||||
}
|
||||
if (param.getEnabled() == null) {
|
||||
param.setEnabled(1);
|
||||
}
|
||||
sortNo++;
|
||||
}
|
||||
}
|
||||
|
||||
private String mergeStringField(String ruleCode, String fieldName, String currentValue, String newValue) {
|
||||
String current = trimmed(currentValue);
|
||||
String incoming = trimmed(newValue);
|
||||
if (ObjectUtil.isEmpty(incoming)) {
|
||||
return current;
|
||||
}
|
||||
if (ObjectUtil.isEmpty(current)) {
|
||||
return incoming;
|
||||
}
|
||||
if (!Objects.equals(current, incoming)) {
|
||||
throw new RuntimeException("Rule " + ruleCode + " has conflicting values for field " + fieldName);
|
||||
}
|
||||
return current;
|
||||
}
|
||||
|
||||
private Integer mergeIntegerField(String ruleCode, String fieldName, Integer currentValue, Integer newValue) {
|
||||
if (newValue == null) {
|
||||
return currentValue;
|
||||
}
|
||||
if (currentValue == null) {
|
||||
return newValue;
|
||||
}
|
||||
if (!Objects.equals(currentValue, newValue)) {
|
||||
throw new RuntimeException("Rule " + ruleCode + " has conflicting values for field " + fieldName);
|
||||
}
|
||||
return currentValue;
|
||||
}
|
||||
|
||||
private List<String> parseTaskTypes(String taskTypesCsv) {
|
||||
if (ObjectUtil.isEmpty(taskTypesCsv)) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
return Arrays.stream(taskTypesCsv.split(","))
|
||||
.map(this::trimmed)
|
||||
.filter(ObjectUtil::isNotEmpty)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private String joinTaskTypes(List<String> taskTypes) {
|
||||
if (CollUtil.isEmpty(taskTypes)) {
|
||||
return null;
|
||||
}
|
||||
return taskTypes.stream()
|
||||
.filter(ObjectUtil::isNotEmpty)
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
private String trimmed(String value) {
|
||||
return value == null ? null : value.trim();
|
||||
}
|
||||
|
||||
private void saveChildren(RuleConfig ruleConfig) {
|
||||
if (CollUtil.isNotEmpty(ruleConfig.getParams())) {
|
||||
Set<String> keys = new HashSet<>();
|
||||
|
||||
Reference in New Issue
Block a user