package com.estate.expert.admin.stat.report.data; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.estate.expert.admin.domain.exam.eval.fuzzy.FuzzyResult; import com.estate.expert.admin.domain.exam.eval.fuzzy.FuzzyValue; import com.estate.expert.admin.domain.exam.eval.score.ScoreResult; import com.estate.expert.admin.domain.exam.eval.score.ScoreValue; import com.estate.expert.admin.domain.exam.record.error.ErrorRecord; import com.estate.expert.admin.domain.standard.hierachy.HierarchyData; import com.estate.expert.admin.utils.tree.TreeNode; import com.estate.expert.admin.utils.tree.TreeRoot; import lombok.experimental.SuperBuilder; import lombok.extern.slf4j.Slf4j; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; /** * 第三方评估报告数据 */ @Slf4j @SuperBuilder public abstract class SystemReportData extends ReportDataBase { List records; TreeRoot systemHierarchy; protected FuzzyResult sysResult; protected ScoreResult scoreResult; Map problemHazardCounts; long projectCheckCount; // 评估结果 @Override protected JSONObject buildEvalInfo() { JSONObject evalInfo = new JSONObject(); evalInfo.put("综合信息", buildAbstractInfo()); evalInfo.put("检查项", buildCheckItems()); evalInfo.put("隐患等级分布", buildErrorLevel(getFuzzyRoot())); return evalInfo; } /** * 获取模糊根节点 * @return 模糊根节点 */ protected TreeNode getFuzzyRoot(){ if(sysResult == null) return null; return sysResult.root(); } protected TreeNode getScoreRoot(){ if(scoreResult == null) return null; return scoreResult.root(); } /** * 根据路径获取对应的模糊节点 * @param path 节点路径 * @return 模糊节点,如果不存在则返回null */ protected TreeNode getFuzzyNodeByPath(String path) { if(sysResult == null || path == null) return null; return sysResult.get(path); } /** * 构建摘要信息 * @return 摘要信息 */ protected abstract JSONObject buildAbstractInfo(); /** * 构建节点 * @param info 信息 * @param node 节点 */ protected abstract void buildNode(JSONObject info, TreeNode node); /** * 构建检查项 * @return 检查项 */ protected JSONArray buildCheckItems(){ var root = getScoreRoot(); var result = new JSONArray(); if(root == null) return result; root.getChildren().values().forEach(node -> { var item = buildCheckItem(node); if(item!=null) result.add(item); }); return result; } // 处理检查项 /** * 构建检查项 * @param node 节点 * @return 检查项 */ private JSONObject buildCheckItem(TreeNode node){ if(node == null || node.getData().getTotalErrorCounts() == null) return null; var totalErrors = Arrays.stream(node.getData().getTotalErrorCounts()).sum(); if(totalErrors == 0) return null; JSONObject result = new JSONObject(); result.put("名称", node.getName()); buildNode(result, node); var cfuzzyNode = getFuzzyNodeByPath(node.getPath()); if(cfuzzyNode != null){ result.put("模糊评价", cfuzzyNode.getData().getRiskLevel().getDesc()); result.put("模糊得分", formatFloat(cfuzzyNode.getData().getScore())); } var categoryItems = new ArrayList<>(); AtomicInteger index = new AtomicInteger(); List itemInfos = new ArrayList<>(); for(var child : node.getChildren().values()) { for(var c : child.getChildren().values()) { for(var n : c.getChildren().values()) { var errorInfos = buildErrorInfo(n.getPath()); // if(CollectionUtils.isEmpty(errorInfos)) // continue; JSONObject info = new JSONObject(); info.put("类别", n.getName()); info.put("序号", index.getAndIncrement() + 1); buildNode(info, n); // 从fuzzyNode中获取评价 var fuzzyNode = getFuzzyNodeByPath(n.getPath()); if(fuzzyNode != null && fuzzyNode.getData() != null && fuzzyNode.getData().getRiskLevel() != null) { info.put("评价", fuzzyNode.getData().getRiskLevel().getDesc()); info.put("模糊得分", formatFloat(fuzzyNode.getData().getScore())); } else { info.put("评价", n.getData().getScore()); info.put("模糊得分", "-"); } int errorCnt = Arrays.stream(n.getData().getTotalErrorCounts()).sum(); info.put("问题数量", errorCnt); info.put("问题百分比", formatPercent(errorCnt * 1.0 / totalErrors)); info.put("问题", errorInfos); itemInfos.add(info); } } } JSONObject categoryItem = new JSONObject(); categoryItem.put("类别", "合并项目"); categoryItem.put("分项", itemInfos); categoryItems.add(categoryItem); result.put("问题合计数量", totalErrors); result.put("分项评估", categoryItems); return result; } /** * 构建错误信息 * @param nodePath 节点路径 * @return 错误信息 */ protected List buildErrorInfo(String nodePath) { var suffix = nodePath + "/"; var errors = new ArrayList<>(); // 按 problem.id 去重,相同问题只保留第一个记录 var nodeRecords = records.stream() .filter(record -> record.getProblem() != null && record.getProblem().getHierarchyPath() != null && record.getProblem().getHierarchyPath().startsWith(suffix)) .collect(java.util.stream.Collectors.toMap( record -> record.getProblem().getId(), record -> record, (existing, replacement) -> existing // 保留第一个遇到的记录 )) .values() .stream() // 按照record.errorLevel排序 .sorted(Comparator.comparing(ErrorRecord::getLevel, Comparator.nullsLast(Comparator.naturalOrder()))) .toList(); for(var record : nodeRecords){ var subItem = buildRecordDetail(record); subItem.put("项目级别", errorNodeName(record)); subItem.put("同类隐患出现频次", getProblemHazardCount(record)); subItem.put("检查频次", getProblemCheckCount(record)); errors.add(subItem); } return errors; } private long getProblemHazardCount(ErrorRecord record) { var problemId = record != null && record.getProblem() != null ? record.getProblem().getId() : null; if (problemId == null || problemHazardCounts == null) { return 0L; } return problemHazardCounts.getOrDefault(problemId, 0L); } private long getProblemCheckCount(ErrorRecord record) { return Math.max(projectCheckCount, 0L); } /** * 构建错误节点名称 * @param record 记录 * @return 错误节点名称 */ protected String errorNodeName(ErrorRecord record){ var hierarchyPath = record.getProblem().getHierarchyPath(); return systemHierarchy.get(hierarchyPath).getName(); } }