From 7a17662bdadf36c4e30bd53b896571612d48abbb Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期三, 09 九月 2026 11:17:38 +0800
Subject: [PATCH] fix: 4项整改——审核结果按模板双Sheet导出(仅核实型+状态筛选)/明细表格化、数据查看分组选择与隐藏三列、报表页隐藏货运旅客城市客运小表、整本预览展示货运城市客运中口径当月累计同比 + 测试报告与工作日结

---
 traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java |  114 +++++++++++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 102 insertions(+), 12 deletions(-)

diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java b/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
index 8269c27..75c05b2 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/auditengine/service/AuditEngineService.java
@@ -1403,24 +1403,29 @@
         return a;
     }
 
-    /** 瀹℃牳缁撴灉瀵煎嚭 Excel锛堝惈浼佷笟鍚�/瑙勫垯鍚�/鐘舵��/瀹℃牳鎰忚锛� */
+    /** 瀹℃牳缁撴灉瀵煎嚭 Excel锛堜袱 Sheet锛屾寜涓氬姟妯℃澘锛夛細Sheet1 瀹℃牳缁撴灉锛堥�愭潯鏄庣粏锛夛紱Sheet2 浼佷笟鍚堝苟锛堟寜浼佷笟姹囨�� + 闂鍒楋級 */
     public byte[] exportResults(String reportPeriod, String reportType) throws Exception {
+        return exportResults(reportPeriod, reportType, true, "all");
+    }
+
+    /** onlyVerify=true 鏃跺墧闄も�滄彁閱掑瀷鈥濊鍒欙紙濡� RULE_004 鐜瘮鎻愰啋锛夛紝鍙繚鐣欐牳瀹炲瀷闂锛泂tatus=all/pending/handled 涓庣晫闈⑩�滅姸鎬佲�濈瓫閫変竴鑷� */
+    public byte[] exportResults(String reportPeriod, String reportType, boolean onlyVerify, String status) throws Exception {
         List<AuditResult> results = queryResults(reportPeriod, reportType);
+        java.util.List<AuditResult> filtered = new java.util.ArrayList<>();
+        String st = status == null ? "all" : status.trim();
+        for (AuditResult res : results) {
+            if (onlyVerify && isReminderRule(res.getRuleCode())) continue;
+            if ("pending".equals(st) && !"PENDING".equals(res.getStatus())) continue;
+            if ("handled".equals(st) && (res.getStatus() == null || "PENDING".equals(res.getStatus()))) continue;
+            filtered.add(res);
+        }
         try (XSSFWorkbook wb = new XSSFWorkbook()) {
+            // ---------- Sheet1 瀹℃牳缁撴灉锛堥�愭潯锛屽垪涓庝笟鍔℃ā鏉夸竴鑷达級 ----------
             Sheet sheet = wb.createSheet("瀹℃牳缁撴灉");
             String[] headers = {"鎶ヨ〃鏈�", "浼佷笟/甯傚窞", "瑙勫垯缂栫爜", "瀹℃牳瑙勫垯", "绛夌骇", "瀹為檯鍊�", "闃堝��/鍩哄噯", "鍋忓樊璇存槑", "鐘舵��", "瀹℃牳鎰忚"};
-            Row head = sheet.createRow(0);
-            for (int i = 0; i < headers.length; i++) {
-                Cell cell = head.createCell(i);
-                cell.setCellValue(headers[i]);
-                org.apache.poi.ss.usermodel.CellStyle style = wb.createCellStyle();
-                org.apache.poi.ss.usermodel.Font font = wb.createFont();
-                font.setBold(true);
-                style.setFont(font);
-                cell.setCellStyle(style);
-            }
+            writeAuditHeader(sheet, headers);
             int r = 1;
-            for (AuditResult res : results) {
+            for (AuditResult res : filtered) {
                 Row row = sheet.createRow(r++);
                 row.createCell(0).setCellValue(valueOf(res.getReportPeriod()));
                 row.createCell(1).setCellValue(valueOf(res.getEnterpriseName()));
@@ -1437,12 +1442,97 @@
             for (int i = 0; i < widths.length; i++) {
                 sheet.setColumnWidth(i, widths[i] * 256);
             }
+
+            // ---------- Sheet2 浼佷笟鍚堝苟锛堝悓涓�浼佷笟澶氭潯瑙勫垯骞舵帓鍒楀嚭 + 闂姹囨�诲垪锛� ----------
+            Sheet ms = wb.createSheet("浼佷笟鍚堝苟");
+            String[] h2 = {"鎶ヨ〃鏈�", "浼佷笟/甯傚窞", "瀹℃牳瑙勫垯", "瀹為檯鍊�", "闃堝��/鍩哄噯", "鍋忓樊璇存槑", "闂"};
+            writeAuditHeader(ms, h2);
+            java.util.LinkedHashMap<String, java.util.List<AuditResult>> groups = new java.util.LinkedHashMap<>();
+            for (AuditResult res : filtered) {
+                String key = valueOf(res.getEnterpriseName());
+                if (key.isEmpty()) key = valueOf(res.getReportPeriod()) + "#" + valueOf(res.getActualValue());
+                groups.computeIfAbsent(key, k -> new java.util.ArrayList<>()).add(res);
+            }
+            int rowCursor = 1;
+            for (java.util.Map.Entry<String, java.util.List<AuditResult>> e : groups.entrySet()) {
+                java.util.List<AuditResult> items = e.getValue();
+                int groupStart = rowCursor;
+                StringBuilder problems = new StringBuilder();
+                int seq = 0;
+                for (AuditResult it : items) {
+                    Row row = ms.createRow(rowCursor++);
+                    if (seq == 0) {
+                        row.createCell(0).setCellValue(valueOf(it.getReportPeriod()));
+                        row.createCell(1).setCellValue(valueOf(it.getEnterpriseName()).isEmpty() ? e.getKey() : valueOf(it.getEnterpriseName()));
+                    }
+                    row.createCell(2).setCellValue(valueOf(it.getRuleName()));
+                    row.createCell(3).setCellValue(valueOf(it.getActualValue()));
+                    row.createCell(4).setCellValue(valueOf(it.getThresholdValue()));
+                    row.createCell(5).setCellValue(valueOf(it.getDeviation()));
+                    seq++;
+                    if (problems.length() > 0) problems.append("\n");
+                    problems.append(seq).append("銆�").append(issueSentence(it));
+                }
+                if (rowCursor - groupStart > 1) {
+                    ms.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(groupStart, rowCursor - 1, 1, 1));
+                    ms.addMergedRegion(new org.apache.poi.ss.util.CellRangeAddress(groupStart, rowCursor - 1, 6, 6));
+                }
+                Row first = ms.getRow(groupStart);
+                if (first.getCell(6) == null) first.createCell(6);
+                first.getCell(6).setCellValue(problems.toString());
+            }
+            int[] widths2 = {12, 30, 22, 34, 22, 34, 60};
+            for (int i = 0; i < widths2.length; i++) {
+                ms.setColumnWidth(i, widths2[i] * 256);
+            }
             ByteArrayOutputStream out = new ByteArrayOutputStream();
             wb.write(out);
             return out.toByteArray();
         }
     }
 
+    private void writeAuditHeader(Sheet sheet, String[] headers) {
+        Row head = sheet.createRow(0);
+        for (int i = 0; i < headers.length; i++) {
+            Cell cell = head.createCell(i);
+            cell.setCellValue(headers[i]);
+            org.apache.poi.ss.usermodel.CellStyle style = sheet.getWorkbook().createCellStyle();
+            org.apache.poi.ss.usermodel.Font font = sheet.getWorkbook().createFont();
+            font.setBold(true);
+            style.setFont(font);
+            cell.setCellStyle(style);
+        }
+    }
+
+    /** 鎻愰啋鍨嬭鍒欙細浠呮彁绀哄彉鍖栥�佷笉闇�浜哄伐鏍稿疄锛堝 RULE_004 璐ц繍绫诲瀷鐜瘮鎻愰啋锛� */
+    private boolean isReminderRule(String ruleCode) {
+        return "RULE_004".equals(ruleCode);
+    }
+
+    /** 浼佷笟鍚堝苟鈥滈棶棰樷�濆垪璇濇湳锛氭寜瑙勫垯绫诲瀷鐢熸垚鍙鐨勬牳瀹炴剰瑙� */
+    private String issueSentence(AuditResult res) {
+        String code = res.getRuleCode();
+        String dev = valueOf(res.getDeviation());
+        String act = valueOf(res.getActualValue());
+        String thr = valueOf(res.getThresholdValue());
+        if ("RULE_001".equals(code) || "RULE_002".equals(code)) {
+            return "浼佷笟涓婃姤杞﹁締/鍚ㄤ綅涓庤繍鏀挎暟鎹姣斿瓨鍦ㄥ樊寮傦紙" + dev + "锛夛紝璇锋牳瀹�";
+        }
+        if ("RULE_003".equals(code)) {
+            return "涓婃姤鍛ㄨ浆閲忎笌杞ㄨ抗娴嬬畻鍛ㄨ浆閲忓樊寮傛槑鏄撅紙" + dev + "锛夛紝璇峰弬鑰冭建杩规牳瀹炰紒涓氬懆杞噺";
+        }
+        if ("RULE_004".equals(code)) {
+            return "璐ц繍绫诲瀷鐜瘮鍙戠敓鍙樺寲锛岃鏍稿疄";
+        }
+        if ("RULE_005".equals(code)) {
+            return "鏃犻泦瑁呯杞︿絾瀛樺湪闆嗚绠辫揣杩愰噺锛岃鏍稿疄杞﹁締绫诲瀷涓庤揣杩愰噺濉姤";
+        }
+        if ("RULE_006".equals(code)) {
+            return "鏁磋溅鍚ㄤ綅瓒呭嚭 4~40 鍚ㄥ悎鐞嗚寖鍥达紝璇锋牳瀹炲钩鍧囧惃浣嶅~鎶�";
+        }
+        return valueOf(res.getRuleName()) + "寮傚父锛堝疄闄咃細" + act + "锛涘熀鍑嗭細" + thr + "锛�" + dev + "锛夛紝璇锋牳瀹�";
+    }
+
     private String auditStatusCn(String status) {
         if ("CONFIRMED".equals(status)) return "宸茬‘璁�";
         if ("IGNORED".equals(status)) return "宸插拷鐣�";

--
Gitblit v1.9.1