修改:模板导入冲突参数解决(预览版)
This commit is contained in:
parent
906fc81dc5
commit
221869b7f1
@ -50,17 +50,18 @@ public class SheetDataListener implements ReadListener<Parameter> {
|
||||
.map(ReadCellData::getStringValue)
|
||||
.filter(Objects::nonNull)
|
||||
.collect(Collectors.toSet());
|
||||
// 第一次读取数据时检查表头
|
||||
// if (!headerChecked) {
|
||||
// checkHeaderAndSkipIfNeeded(context);
|
||||
// headerChecked = true;
|
||||
// }
|
||||
currentSheetName = context.readSheetHolder().getSheetName();
|
||||
log.info("开始解析Sheet: {}", currentSheetName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void invoke(Parameter data, AnalysisContext context) {
|
||||
// 第一次读取数据时检查表头
|
||||
// if (!headerChecked) {
|
||||
// checkHeaderAndSkipIfNeeded(context);
|
||||
// headerChecked = true;
|
||||
// }
|
||||
|
||||
|
||||
// 如果sheet无效,直接返回,不处理数据
|
||||
// if (!validSheet) {
|
||||
@ -69,8 +70,7 @@ public class SheetDataListener implements ReadListener<Parameter> {
|
||||
|
||||
if (data.getSubsystemName() == null) {
|
||||
problems.setFlag(true);
|
||||
problems.getErrors().add(currentSheetName +"模板的参数"+data.getParameterName()+"的子系统字段为空");
|
||||
return;
|
||||
problems.getErrors().add("模板导入失败:"+currentSheetName +"模板的参数"+data.getParameterName()+"的子系统字段为空");
|
||||
}
|
||||
|
||||
if (data.getPartsName() == null || data.getPartsName().isEmpty()) {
|
||||
|
||||
@ -11,6 +11,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.Resource;
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineManager;
|
||||
@ -26,8 +27,17 @@ public class ParameterValueCalculationTimer {
|
||||
@Resource
|
||||
private BusinessDatabase bd;
|
||||
|
||||
// @Scheduled(cron = "0 0 0 * * ?")
|
||||
// @Scheduled(cron = "0 */1 * * * *")
|
||||
private ScriptEngineManager scriptEngineManager;
|
||||
private ScriptEngine scriptEngine;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
scriptEngineManager = new ScriptEngineManager();
|
||||
scriptEngine = scriptEngineManager.getEngineByName("JavaScript");
|
||||
}
|
||||
|
||||
// 每天凌晨执行一次
|
||||
// @Scheduled(cron = "0 0 0 * * ?")
|
||||
public MyResponse dailyCalculate() {
|
||||
MyResponse myResponse = new MyResponse();
|
||||
myResponse.setErrors(new ArrayList<>());
|
||||
@ -81,6 +91,8 @@ public class ParameterValueCalculationTimer {
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 5.遍历参数,计算需运算的参数值
|
||||
int successCount = 0;
|
||||
int failureCount = 0;
|
||||
for (CalculationParameterView parameterValue : parameterValues) {
|
||||
if (Objects.equals(parameterValue.getParameterSource(), "公式计算")) {
|
||||
String formula = parameterValue.getNumberOrFormula();
|
||||
@ -93,29 +105,49 @@ public class ParameterValueCalculationTimer {
|
||||
toUpdate.add(parameterValue);
|
||||
log.info("参数【{}】计算结果:{}", parameterValue.getParameterName(), formattedResult);
|
||||
myResponse.getErrors().add("参数【"+parameterValue.getParameterName()+"】计算结果:"+formattedResult);
|
||||
successCount++;
|
||||
} catch (Exception e) {
|
||||
log.error("参数【{}】计算失败:{},公式:{},模型ID:{}",
|
||||
parameterValue.getParameterName(), e.getMessage(), formula, modelId, e);
|
||||
myResponse.getErrors().add("参数【"+parameterValue.getParameterName()+"】计算失败:"+e.getMessage()+",公式:"+formula+"模型ID:"+modelId);
|
||||
parameterValue.setParameterValue(null);
|
||||
toUpdate.add(parameterValue); // 仍然添加到更新列表,用于更新null值
|
||||
failureCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 批量插入或更新计算结果
|
||||
// if (!toUpdate.isEmpty()) {
|
||||
// toUpdate.forEach(parameterValue -> {
|
||||
// if (parameterValue.getParameterValue() != null) {
|
||||
// bd.getBusinessDatabase()
|
||||
// .table("engine_param_detail")
|
||||
// .eq("id", parameterValue.getId())
|
||||
// .update("parameter_value", parameterValue.getParameterValue())
|
||||
// .doUpdate();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// log.info("{}参数计算完成,成功处理{}个参数,失败参数已跳过", today, toUpdate.stream()
|
||||
// .filter(p -> p.getParameterValue() != null).count());
|
||||
if (!toUpdate.isEmpty()) {
|
||||
int updatedCount = 0;
|
||||
for (CalculationParameterView parameterValue : toUpdate) {
|
||||
try {
|
||||
if (parameterValue.getParameterValue() != null) {
|
||||
bd.getBusinessDatabase()
|
||||
.table("engine_param_detail")
|
||||
.eq("id", parameterValue.getId())
|
||||
.update("parameter_value", parameterValue.getParameterValue())
|
||||
.doUpdate();
|
||||
updatedCount++;
|
||||
} else {
|
||||
// 对于计算失败的参数,也更新为null值
|
||||
bd.getBusinessDatabase()
|
||||
.table("engine_param_detail")
|
||||
.eq("id", parameterValue.getId())
|
||||
.update("parameter_value", null)
|
||||
.doUpdate();
|
||||
updatedCount++;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("参数【{}】更新数据库失败:{}", parameterValue.getParameterName(), e.getMessage(), e);
|
||||
myResponse.getErrors().add("参数【"+parameterValue.getParameterName()+"】更新数据库失败:"+e.getMessage());
|
||||
}
|
||||
}
|
||||
log.info("{}参数计算完成,成功处理{}个参数,失败{}个参数,更新{}个参数", today, successCount, failureCount, updatedCount);
|
||||
} else {
|
||||
log.info("{}参数计算完成,无需更新任何参数", today);
|
||||
}
|
||||
myResponse.getErrors().add("参数计算完成,成功处理"+successCount+"个参数,失败"+failureCount+"个参数");
|
||||
return myResponse;
|
||||
}
|
||||
|
||||
@ -153,12 +185,10 @@ public class ParameterValueCalculationTimer {
|
||||
|
||||
private Double calculateWithScriptEngine(String expression) {
|
||||
try {
|
||||
ScriptEngineManager manager = new ScriptEngineManager();
|
||||
ScriptEngine engine = manager.getEngineByName("JavaScript");
|
||||
if (!isSafeExpression(expression)) {
|
||||
throw new SecurityException("表达式包含不安全内容");
|
||||
}
|
||||
Object result = engine.eval(expression);
|
||||
Object result = scriptEngine.eval(expression);
|
||||
if (result instanceof Number) {
|
||||
return ((Number) result).doubleValue();
|
||||
}
|
||||
@ -171,11 +201,11 @@ public class ParameterValueCalculationTimer {
|
||||
|
||||
private boolean isSafeExpression(String expression) {
|
||||
// 允许的字符:数字、基本运算符、括号、数学常量和函数
|
||||
String safePattern = "^[0-9+\\-*/().\\sMathPIEsincostanlogsqrtabs]*$";
|
||||
String safePattern = "^[0-9+\\-*/().\\sMathPIEsincostanlogsqrtabs]+$";
|
||||
if (!expression.matches(safePattern)) {
|
||||
return false;
|
||||
}
|
||||
String[] dangerousKeywords = {"java", "class", "runtime", "exec", "system", "process", "file"};
|
||||
String[] dangerousKeywords = {"java", "class", "runtime", "exec", "system", "process", "file", "import"};
|
||||
for (String keyword : dangerousKeywords) {
|
||||
if (expression.toLowerCase().contains(keyword)) {
|
||||
return false;
|
||||
|
||||
@ -13,6 +13,7 @@ import com.xdap.self_development.listener.SheetDataListener;
|
||||
import com.xdap.self_development.pojo.*;
|
||||
import com.xdap.self_development.service.TemplateService;
|
||||
import com.xdap.self_development.utils.FormulaValidator;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -245,6 +246,10 @@ public class TemplateServiceImpl implements TemplateService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (problems.getFlag()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 验证公式
|
||||
for (Parameter data : dataList) {
|
||||
data.setCreatedBy(createBy);
|
||||
@ -252,7 +257,7 @@ public class TemplateServiceImpl implements TemplateService {
|
||||
Map<String, Object> validationResult = FormulaValidator.validateFormulaDetailed(
|
||||
data.getNumberOrFormula());
|
||||
if (!(Boolean) validationResult.get("isValid")) {
|
||||
String errorMsg = String.format("模板'%s'的参数'%s'公式格式错误, %s",
|
||||
String errorMsg = String.format("模板导入失败:"+"模板'%s'的参数'%s'公式格式错误, %s",
|
||||
sheetName, data.getParameterName(),
|
||||
validationResult.get("errorMessage"));
|
||||
problems.setFlag(true);
|
||||
@ -274,7 +279,7 @@ public class TemplateServiceImpl implements TemplateService {
|
||||
// 页名和模板名不一致不允许导入
|
||||
if (!Objects.equals(templateName, sheetName)) {
|
||||
problems.setFlag(true);
|
||||
problems.getErrors().add("Excel页名与模板名不一致");
|
||||
problems.getErrors().add("\"模板导入失败:\"+Excel页名与模板名不一致");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -297,14 +302,15 @@ public class TemplateServiceImpl implements TemplateService {
|
||||
.doQuery(TemplateAndParameter.class);
|
||||
// 最新模板有参数
|
||||
if (!list.isEmpty()) {
|
||||
// insertAndUpdateParameters(List<Parameter> dataList, Template lastTemplate)
|
||||
problems.setFlag(true);
|
||||
problems.getErrors().add("模板‘"+templateName+"’已有参数,无法导入");
|
||||
problems.getErrors().add("模板导入失败:"+"模板‘"+templateName+"’已有参数,无法导入");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case "APPROVING":
|
||||
problems.setFlag(true);
|
||||
problems.getErrors().add("模板‘"+templateName+"‘的最新版本正在审核中,无法导入");
|
||||
problems.getErrors().add("模板导入失败:"+"模板‘"+templateName+"‘的最新版本正在审核中,无法导入");
|
||||
return;
|
||||
// 最新版本已发布,增加版本号新增
|
||||
default:
|
||||
@ -395,4 +401,169 @@ public class TemplateServiceImpl implements TemplateService {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
private void insertAndUpdateParameters(
|
||||
List<Parameter> dataList, Template lastTemplate
|
||||
) {
|
||||
// 获取原模板参数
|
||||
List<Parameter> parameters = bd.getBusinessDatabase().viewQueryMode(true)
|
||||
.view("selectParametersByTemplateId")
|
||||
.setVar("template_id", lastTemplate.getId())
|
||||
.doQuery(Parameter.class);
|
||||
|
||||
// 筛选变更和新增的参数
|
||||
ProcessResult processResult = processParameters(parameters, dataList);
|
||||
List<Parameter> toAdd = processResult.getToAdd();
|
||||
List<ParameterChange> toUpdate = processResult.getToUpdate();
|
||||
|
||||
if (!toAdd.isEmpty()) {
|
||||
// 保存参数
|
||||
bd.getBusinessDatabase().doBatchInsert(toAdd);
|
||||
List<TemplateAndParameter> relations = new ArrayList<>();
|
||||
|
||||
// 保存关联关系
|
||||
toAdd.forEach(parameter -> {
|
||||
TemplateAndParameter relation = new TemplateAndParameter();
|
||||
RevisionRecord record = new RevisionRecord();
|
||||
relation.setTemplateId(lastTemplate.getId());
|
||||
relation.setParameterId(parameter.getId());
|
||||
relations.add(relation);
|
||||
});
|
||||
bd.getBusinessDatabase().doBatchInsert(relations);
|
||||
|
||||
// 保存修改记录
|
||||
List<RevisionRecord> revisionRecords = toAdd.stream()
|
||||
.map(parameter -> {
|
||||
return new RevisionRecord(
|
||||
lastTemplate.getTemplateName(),
|
||||
lastTemplate.getVersion(),
|
||||
parameter.getParameterNumber(),
|
||||
"新增参数",
|
||||
lastTemplate.getId(),
|
||||
null,
|
||||
Timestamp.valueOf(LocalDateTime.now()),
|
||||
parameter.getId()
|
||||
);
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
bd.getBusinessDatabase().doBatchInsert(revisionRecords);
|
||||
}
|
||||
|
||||
if (!toUpdate.isEmpty()) {
|
||||
|
||||
toUpdate.forEach(parameterChange -> {
|
||||
// 更新参数
|
||||
parameterChange.getUpdated().setId(parameterChange.getOriginal().getId());
|
||||
bd.getBusinessDatabase()
|
||||
.eq("id", parameterChange.getUpdated().getId())
|
||||
.doUpdate(parameterChange.getUpdated());
|
||||
|
||||
// 保存修改记录
|
||||
RevisionRecord record = new RevisionRecord(
|
||||
lastTemplate.getTemplateName(),
|
||||
lastTemplate.getVersion(),
|
||||
parameterChange.getUpdated().getParameterNumber(),
|
||||
parameterChange.getChangeDescription(),
|
||||
lastTemplate.getId(),
|
||||
parameterChange.getOriginal().getId(),
|
||||
Timestamp.valueOf(LocalDateTime.now()),
|
||||
parameterChange.getUpdated().getId()
|
||||
);
|
||||
bd.getBusinessDatabase().doInsert(record);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private String getParameterChange(Parameter originalParameter, Parameter updatedParameter) {
|
||||
return handleParameterChange("参数名", originalParameter.getParameterName(), updatedParameter.getParameterName()) +
|
||||
handleParameterChange("参数类型", originalParameter.getParameterType(), updatedParameter.getParameterType()) +
|
||||
handleParameterChange("子系统", originalParameter.getSubsystemName(), updatedParameter.getSubsystemName()) +
|
||||
handleParameterChange("部件名", originalParameter.getPartsName(), updatedParameter.getPartsName()) +
|
||||
handleParameterChange("单位名", originalParameter.getUnit(), updatedParameter.getUnit()) +
|
||||
handleParameterChange("参数来源", originalParameter.getParameterSource(), updatedParameter.getParameterSource()) +
|
||||
handleParameterChange("公式或编号", originalParameter.getNumberOrFormula(), updatedParameter.getNumberOrFormula()) +
|
||||
handleParameterChange("部门名", originalParameter.getDepartment(), updatedParameter.getDepartment());
|
||||
}
|
||||
|
||||
private String handleParameterChange(String name, String originalParameter, String updatedParameter) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (!Objects.equals(originalParameter, updatedParameter)) {
|
||||
if (originalParameter == null || originalParameter.isEmpty()) {
|
||||
if (updatedParameter == null || updatedParameter.isEmpty()) {
|
||||
sb.append(name).append(": ").append("变更为空值").append("\n");
|
||||
} else {
|
||||
sb.append(name).append(": ").append("变更为: '").append(updatedParameter).append("' ").append("\n");
|
||||
}
|
||||
} else {
|
||||
if (updatedParameter == null || updatedParameter.isEmpty()) {
|
||||
sb.append(name).append(": '").append(originalParameter).append("' 变更为 空值").append("\n");
|
||||
} else {
|
||||
sb.append(name).append(": '").append(originalParameter).append("' 变更为 '").append(updatedParameter).append("'\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class ProcessResult {
|
||||
private List<Parameter> toAdd;
|
||||
private List<ParameterChange> toUpdate;
|
||||
|
||||
public ProcessResult(List<Parameter> toAdd, List<ParameterChange> toUpdate) {
|
||||
this.toAdd = toAdd;
|
||||
this.toUpdate = toUpdate;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Getter
|
||||
public static class ParameterChange {
|
||||
private Parameter original;
|
||||
private Parameter updated;
|
||||
private String changeDescription;
|
||||
|
||||
public ParameterChange(Parameter original, Parameter updated, String changeDescription) {
|
||||
this.original = original;
|
||||
this.updated = updated;
|
||||
this.changeDescription = changeDescription;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public ProcessResult processParameters(List<Parameter> oldList, List<Parameter> newList) {
|
||||
// 过滤掉newList中number为空的项
|
||||
List<Parameter> validNewList = newList.stream()
|
||||
.filter(p -> p.getParameterNumber() != null
|
||||
&& !p.getParameterNumber().toString().trim().isEmpty())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<Parameter> toAdd = new ArrayList<>();
|
||||
List<ParameterChange> toUpdate = new ArrayList<>();
|
||||
|
||||
// 创建旧列表中number到Parameter的映射
|
||||
Map<Object, Parameter> oldMap = oldList.stream()
|
||||
.filter(p -> p.getParameterNumber() != null
|
||||
&& !p.getParameterNumber().toString().trim().isEmpty())
|
||||
.collect(Collectors.toMap(
|
||||
Parameter::getParameterNumber,
|
||||
p -> p,
|
||||
(existing, replacement) -> existing));
|
||||
|
||||
// 处理新列表中的每个参数
|
||||
for (Parameter newParam : validNewList) {
|
||||
Integer number = newParam.getParameterNumber();
|
||||
|
||||
if (oldMap.containsKey(number)) {
|
||||
Parameter oldParam = oldMap.get(number);
|
||||
String changeDescription = getParameterChange(oldParam, newParam);
|
||||
ParameterChange change = new ParameterChange(oldParam, newParam, changeDescription);
|
||||
toUpdate.add(change);
|
||||
oldMap.remove(number);
|
||||
} else {
|
||||
toAdd.add(newParam);
|
||||
}
|
||||
}
|
||||
return new ProcessResult(toAdd, toUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user