“mitao”
2026-03-25 309b5eb17c510c781daec96bbfef3b693f3a4d7e
feat:报告导出
10个文件已修改
246 ■■■■■ 已修改文件
admin-server/src/main/java/com/estate/expert/admin/domain/exam/record/error/ErrorRecordRepository.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/exam/record/warning/WarningRecordRepository.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/exam/task/check/CheckTaskRepository.java 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/service/impl/ReportServiceImpl.java 110 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/stat/report/data/DeviceReportData.java 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/stat/report/data/SystemReportData.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/stat/report/render/CheckInfoTablePolicy.java 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/stat/report/render/DeviceTablePolicy.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/resources/templates/第三方评估报告.docx 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/resources/templates/设备风险评估报告.docx 补丁 | 查看 | 原始文档 | blame | 历史
admin-server/src/main/java/com/estate/expert/admin/domain/exam/record/error/ErrorRecordRepository.java
@@ -99,6 +99,39 @@
            "and w.deleted = false")
    List<ErrorRecord> listDeviceErrors(Integer checkTaskId);
    @Query("select w.problem.id, count(w) from ErrorRecord w " +
            "where w.deleted = false " +
            "and w.device is null " +
            "and w.level is not null " +
            "and w.problem is not null " +
            "and w.problem.id in :problemIds " +
            "and w.checkTask.project.id = :projectId " +
            "and w.checkTask.state in :taskStates " +
            "group by w.problem.id")
    List<Object[]> countSystemHazardsByProjectAndProblemIds(@Param("projectId") Integer projectId,
                                                           @Param("taskStates") List<com.estate.expert.admin.domain.exam.task.check.CheckTaskState> taskStates,
                                                           @Param("problemIds") List<Integer> problemIds);
    @Query("select w.problem.id, count(w) from ErrorRecord w " +
            "where w.deleted = false " +
            "and w.device is null " +
            "and w.problem is not null " +
            "and w.problem.id in :problemIds " +
            "and w.checkTask.id in :taskIds " +
            "group by w.problem.id")
    List<Object[]> countSystemHazardsByTaskIdsAndProblemIds(@Param("taskIds") List<Integer> taskIds,
                                                           @Param("problemIds") List<Integer> problemIds);
    @Query(value = "select r.device_id, r.problem_id, count(*) " +
            "from record r " +
            "where r.deleted = false " +
            "and r.device_id is not null " +
            "and r.problem_id is not null " +
            "and r.record_type = 'error' " +
            "and r.check_task_id in (:taskIds) " +
            "group by r.device_id, r.problem_id", nativeQuery = true)
    List<Object[]> countDeviceHazardsByTaskIds(@Param("taskIds") List<Integer> taskIds);
    //根据人员来获取检查成果
    @Query("select w from ErrorRecord w where w.deleted = false  and w.creator.id = :creatorId"+ " and ( :startDate is null or w.createTime >= :startDate) " +
            "and ( :endDate is null or w.createTime < :endDate) " )
admin-server/src/main/java/com/estate/expert/admin/domain/exam/record/warning/WarningRecordRepository.java
@@ -24,6 +24,18 @@
            "order by w.updateTime desc")
    List<WarningRecord> list(Integer checkTaskId);
    @Query("select w.problem.id, count(w) from WarningRecord w " +
            "where w.deleted = false " +
            "and w.device is null " +
            "and w.problem is not null " +
            "and w.problem.id in :problemIds " +
            "and w.checkTask.project.id = :projectId " +
            "and w.checkTask.state in :taskStates " +
            "group by w.problem.id")
    List<Object[]> countSystemWarningsByProjectAndProblemIds(@Param("projectId") Integer projectId,
                                                            @Param("taskStates") List<com.estate.expert.admin.domain.exam.task.check.CheckTaskState> taskStates,
                                                            @Param("problemIds") List<Integer> problemIds);
    @Query("select w from WarningRecord w where ( :clientId is null or w.checkTask.project.client.id = :clientId) " +
            "and ( :planId is null or w.checkTask.plan.id = :planId) " +
            "and ( :taskId is null or w.checkTask.id = :taskId) " +
admin-server/src/main/java/com/estate/expert/admin/domain/exam/task/check/CheckTaskRepository.java
@@ -1,7 +1,9 @@
package com.estate.expert.admin.domain.exam.task.check;
import com.estate.expert.admin.domain.common.EntityBaseRepository;
import com.estate.expert.admin.domain.plan.PlanState;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
@@ -56,4 +58,12 @@
    List<CheckTask> findAllByPlanIdAndDeleted(Integer planId, boolean deleted);
    CheckTask getFirstByPlanIdAndProjectIdAndDeleted(Integer planId, Integer projectId, boolean deleted);
    @Query("select t.id from CheckTask t " +
            "where t.deleted = false " +
            "and t.project.id = :projectId " +
            "and t.plan.deleted = false " +
            "and t.plan.state = :planState")
    List<Integer> listTaskIdsByProjectAndPlanState(@Param("projectId") Integer projectId,
                                                   @Param("planState") PlanState planState);
}
admin-server/src/main/java/com/estate/expert/admin/service/impl/ReportServiceImpl.java
@@ -5,7 +5,12 @@
import com.estate.expert.admin.domain.business.device.usage.DeviceUsage;
import com.estate.expert.admin.domain.exam.eval.fuzzy.EvalFuzzyResult;
import com.estate.expert.admin.domain.exam.eval.score.EvalScoreResult;
import com.estate.expert.admin.domain.exam.record.error.ErrorRecord;
import com.estate.expert.admin.domain.exam.record.error.ErrorRecordRepository;
import com.estate.expert.admin.domain.exam.record.RecordRepository;
import com.estate.expert.admin.domain.exam.task.check.CheckTaskRepository;
import com.estate.expert.admin.domain.report.ReportTemplate;
import com.estate.expert.admin.domain.plan.PlanState;
import com.estate.expert.admin.enums.BizResultCode;
import com.estate.expert.admin.service.*;
import com.estate.expert.admin.service.eval.EvalFuzzyService;
@@ -13,6 +18,7 @@
import com.estate.expert.admin.stat.report.builder.DeviceReportBuilder;
import com.estate.expert.admin.stat.report.builder.ReportBuilderBase;
import com.estate.expert.admin.stat.report.builder.SystemReportBuilder;
import com.estate.expert.admin.stat.report.data.DeviceReportData;
import com.estate.expert.admin.stat.report.data.impl.DeviceFuzzyReportData;
import com.estate.expert.admin.stat.report.data.impl.DeviceScoreReportData;
import com.estate.expert.admin.stat.report.data.impl.SystemFuzzyReportData;
@@ -27,6 +33,10 @@
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 报告数据服务实现类
@@ -52,6 +62,15 @@
    @Resource
    private ErrorRecordService errorRecordService;
    @Resource
    private ErrorRecordRepository errorRecordRepository;
    @Resource
    private RecordRepository recordRepository;
    @Resource
    private CheckTaskRepository checkTaskRepository;
    @Resource
    private DeviceService deviceService;
@@ -188,6 +207,8 @@
        var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
        var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
        var problemFrequency = buildSystemProblemFrequency(project.getId(), records);
        // 生成报告数据
        return SystemFuzzyReportData.builder()
                .reportId(evalFuzzyResult.getId())
@@ -199,6 +220,8 @@
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .problemHazardCounts(problemFrequency.problemHazardCounts())
                .problemCheckCounts(problemFrequency.problemCheckCounts())
                .build()
                .generate();
    }
@@ -213,6 +236,8 @@
        var devices= deviceUsages.stream().map(DeviceUsage::getDevice).toList();
        var hierarchy = evalFuzzyResult.getPlan().getSystemScoreExpert().getModel().getHierarchy().getContent();
        var problemFrequency = buildSystemProblemFrequency(project.getId(), records);
        // 生成报告数据
        return SystemScoreReportData.builder()
                .reportId(evalFuzzyResult.getId())
@@ -224,8 +249,87 @@
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .problemHazardCounts(problemFrequency.problemHazardCounts())
                .problemCheckCounts(problemFrequency.problemCheckCounts())
                .build()
                .generate();
    }
    private record ProblemFrequency(Map<Integer, Long> problemHazardCounts, Map<Integer, Long> problemCheckCounts) {
    }
    private record DeviceProblemFrequency(Map<String, Long> problemHazardCounts, Map<String, Long> problemCheckCounts) {
    }
    private ProblemFrequency buildSystemProblemFrequency(Integer projectId, List<com.estate.expert.admin.domain.exam.record.error.ErrorRecord> currentTaskRecords) {
        if (projectId == null || currentTaskRecords == null || currentTaskRecords.isEmpty()) {
            return new ProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
        }
        var problemIds = currentTaskRecords.stream()
                .map(r -> r.getProblem() != null ? r.getProblem().getId() : null)
                .filter(java.util.Objects::nonNull)
                .distinct()
                .toList();
        if (problemIds.isEmpty()) {
            return new ProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
        }
        var taskIds = checkTaskRepository.listTaskIdsByProjectAndPlanState(projectId, PlanState.COMPLETE);
        if (taskIds == null || taskIds.isEmpty()) {
            return new ProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
        }
        Map<Integer, Long> hazardCounts = new HashMap<>();
        for (var row : errorRecordRepository.countSystemHazardsByTaskIdsAndProblemIds(taskIds, problemIds)) {
            if (row == null || row.length < 2 || row[0] == null || row[1] == null) {
                continue;
            }
            hazardCounts.put(((Number) row[0]).intValue(), ((Number) row[1]).longValue());
        }
        Map<Integer, Long> checkCounts = new HashMap<>();
        for (var row : recordRepository.countSystemChecksByTaskIdsAndProblemIds(taskIds, problemIds)) {
            if (row == null || row.length < 2 || row[0] == null || row[1] == null) {
                continue;
            }
            checkCounts.put(((Number) row[0]).intValue(), ((Number) row[1]).longValue());
        }
        return new ProblemFrequency(hazardCounts, checkCounts);
    }
    private DeviceProblemFrequency buildDeviceProblemFrequency(Integer projectId) {
        if (projectId == null) {
            return new DeviceProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
        }
        var taskIds = checkTaskRepository.listTaskIdsByProjectAndPlanState(projectId, PlanState.COMPLETE);
        if (taskIds == null || taskIds.isEmpty()) {
            return new DeviceProblemFrequency(Collections.emptyMap(), Collections.emptyMap());
        }
        Map<String, Long> hazardCounts = new HashMap<>();
        for (var row : errorRecordRepository.countDeviceHazardsByTaskIds(taskIds)) {
            collectDeviceFrequency(row, hazardCounts);
        }
        Map<String, Long> checkCounts = new HashMap<>();
        for (var row : recordRepository.countDeviceChecksByTaskIds(taskIds)) {
            collectDeviceFrequency(row, checkCounts);
        }
        return new DeviceProblemFrequency(hazardCounts, checkCounts);
    }
    private void collectDeviceFrequency(Object[] row, Map<String, Long> target) {
        if (row == null || row.length < 3 || row[0] == null || row[2] == null) {
            return;
        }
        Integer deviceId = ((Number) row[0]).intValue();
        Integer problemId = row[1] == null ? null : ((Number) row[1]).intValue();
        Long count = ((Number) row[2]).longValue();
        target.put(DeviceReportData.buildDeviceProblemKey(deviceId, problemId), count);
    }
    private JSONObject buildFuzzyDeviceReportData(EvalFuzzyResult evalFuzzyResult, EvalScoreResult scoreResult,  ReportTemplate reportTemplate) {
@@ -236,6 +340,7 @@
        var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
        var devices = deviceService.findAllById(deviceIds);
        var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
        var problemFrequency = buildDeviceProblemFrequency(project.getId());
        // 生成报告数据
        return DeviceFuzzyReportData.builder()
@@ -247,6 +352,8 @@
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
                .deviceProblemCheckCounts(problemFrequency.problemCheckCounts())
                .build()
                .generate();
    }
@@ -259,6 +366,7 @@
        var deviceIds = evalFuzzyResult.getDeviceResMap().keySet();
        var devices = deviceService.findAllById(deviceIds);
        var hierarchy = evalFuzzyResult.getPlan().getDeviceScoreExpert().getModel().getHierarchy().getContent();
        var problemFrequency = buildDeviceProblemFrequency(project.getId());
        // 生成报告数据
        return DeviceScoreReportData.builder()
@@ -271,6 +379,8 @@
                .projectInfo(projectInfo)
                .devices(devices)
                .records(records)
                .deviceProblemHazardCounts(problemFrequency.problemHazardCounts())
                .deviceProblemCheckCounts(problemFrequency.problemCheckCounts())
                .build()
                .generate();
    }
admin-server/src/main/java/com/estate/expert/admin/stat/report/data/DeviceReportData.java
@@ -17,6 +17,7 @@
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;
/**
@@ -30,6 +31,10 @@
    protected Map<Integer, FuzzyResult> deviceResMap;
    TreeRoot<HierarchyData> deviceHierarchy;
    Map<String, Long> deviceProblemHazardCounts;
    Map<String, Long> deviceProblemCheckCounts;
    /**
     * 生成报告数据
@@ -241,6 +246,8 @@
            // 检查问题列:默认为问题备注,当问题备注为空时,填写问题描述(与安全报告一致)
            info.put("检查问题", StringUtils.hasText(record.getRemark()) ? record.getRemark() : record.getProblem().getDescription());
            info.put("隐患等级", record.getLevel().getDesc());
            info.put("同类隐患出现频次", getDeviceProblemHazardCount(record));
            info.put("检查频次", getDeviceProblemCheckCount(record));
            var subItem =  buildRecordDetail(record);
            subItem.put("项目级别", errorNode(record).getName());
            info.put("问题详情", subItem);
@@ -249,6 +256,30 @@
        return result;
    }
    private long getDeviceProblemHazardCount(ErrorRecord record) {
        if (deviceProblemHazardCounts == null) {
            return 0L;
        }
        return deviceProblemHazardCounts.getOrDefault(buildDeviceProblemKey(record), 0L);
    }
    private long getDeviceProblemCheckCount(ErrorRecord record) {
        if (deviceProblemCheckCounts == null) {
            return 0L;
        }
        return deviceProblemCheckCounts.getOrDefault(buildDeviceProblemKey(record), 0L);
    }
    private String buildDeviceProblemKey(ErrorRecord record) {
        Integer deviceId = record != null && record.getDevice() != null ? record.getDevice().getId() : null;
        Integer problemId = record != null && record.getProblem() != null ? record.getProblem().getId() : null;
        return buildDeviceProblemKey(deviceId, problemId);
    }
    public static String buildDeviceProblemKey(Integer deviceId, Integer problemId) {
        return Objects.toString(deviceId, "") + "::" + Objects.toString(problemId, "");
    }
    /**
     * 构建设备记录
     * @param device 设备
admin-server/src/main/java/com/estate/expert/admin/stat/report/data/SystemReportData.java
@@ -17,6 +17,7 @@
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
/**
@@ -33,6 +34,10 @@
    protected FuzzyResult sysResult;
    protected ScoreResult scoreResult;
    Map<Integer, Long> problemHazardCounts;
    Map<Integer, Long> problemCheckCounts;
    // 评估结果
    @Override
@@ -200,11 +205,29 @@
        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) {
        var problemId = record != null && record.getProblem() != null ? record.getProblem().getId() : null;
        if (problemId == null || problemCheckCounts == null) {
            return 0L;
        }
        return problemCheckCounts.getOrDefault(problemId, 0L);
    }
    /**
     * 构建错误节点名称
     * @param record 记录
admin-server/src/main/java/com/estate/expert/admin/stat/report/render/CheckInfoTablePolicy.java
@@ -93,6 +93,28 @@
                            RenderHelper.renderCell(row, info.getString("问题百分比"));
                        }
                    }break;
                    case 6: {
                        if(isErrorSummary){
                            // 问题汇总表(新增两列:同类隐患出现频次、检查频次)
                            var errors = info.getJSONArray("问题");
                            if(!CollectionUtils.isEmpty(errors)){
                                var highLevelColor = RenderHelper.highLevelColor(errors);
                                for(var error : errors){
                                    var e = (JSONObject) error;
                                    var row = table.insertNewTableRow(table.getRows().size());
                                    var errorLevel = e.getString("隐患等级");
                                    var textColor = RenderHelper.getErrorLevelColor(errorLevel);
                                    RenderHelper.renderCell(row, info.getString("类别"), highLevelColor);
                                    RenderHelper.renderCell(row, e.getString("问题部位"), textColor);
                                    RenderHelper.renderCell(row, e.getString("问题备注"), textColor);
                                    RenderHelper.renderCell(row, e.getString("隐患等级"), textColor);
                                    RenderHelper.renderCell(row, String.valueOf(e.getLongValue("同类隐患出现频次")), textColor);
                                    RenderHelper.renderCell(row, String.valueOf(e.getLongValue("检查频次")), textColor);
                                }
                            }
                        }
                    }break;
                    default:
                        break;
                }
admin-server/src/main/java/com/estate/expert/admin/stat/report/render/DeviceTablePolicy.java
@@ -20,6 +20,7 @@
    @Override
    public void render(XWPFTable table, Object data) throws Exception {
        var deviceRecords = (JSONArray) data;
        int colCnt = table.getRow(1).getTableCells().size();
        for (var d : deviceRecords) {
            var deviceInfo = (JSONObject) d;
            var records = deviceInfo.getJSONArray("问题");
@@ -34,6 +35,10 @@
                    RenderHelper.renderCell(row, name, highLevelColor);
                    RenderHelper.renderCell(row, info.getString("检查问题"), textColor);
                    RenderHelper.renderCell(row, info.getString("隐患等级"), textColor);
                    if (colCnt >= 5) {
                        RenderHelper.renderCell(row, String.valueOf(info.getLongValue("同类隐患出现频次")), textColor);
                        RenderHelper.renderCell(row, String.valueOf(info.getLongValue("检查频次")), textColor);
                    }
                }
            }
        }
admin-server/src/main/resources/templates/第三方评估报告.docx
Binary files differ
admin-server/src/main/resources/templates/设备风险评估报告.docx
Binary files differ