From ca43270a64f7c62112f3e9f36d5c97a6f149a9ce Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期三, 09 九月 2026 17:05:31 +0800
Subject: [PATCH] fix: 审核结果页选月一直转圈——isReminderRow误放computed改为methods(带参函数需在methods),含测试报告与工作日结
---
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 256 insertions(+), 0 deletions(-)
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java
new file mode 100644
index 0000000..435309b
--- /dev/null
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/SummaryWorkbookFiller.java
@@ -0,0 +1,256 @@
+package com.trafficaudit.reportexport.calc;
+
+import com.trafficaudit.common.util.RegionUtil;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 姹囨�绘暣鏈�滄暟鎹┍鍔ㄥ洖濉�濆紩鎿庯紙M2 鍙拌处灞傦紝2026-09-09 鎺ュ叆锛夈��
+ *
+ * 鐩爣锛氱敓鎴愪换鎰忔湀浠姐�婇亾璺繍杈撻噺姹囨�昏〃锛堟暣鏈級銆嬫椂涓嶅啀渚濊禆褰撴湀浜哄伐姣嶇増锛�
+ * 姣嶇増鍙綋鐗堝紡搴曠锛屽綋鏈堝�兼寜宸查獙璇佸彛寰勪粠搴撶幇绠楀啓鍏ワ紙鐝嚎鍖呰溅 2026-07 涓庝汉宸ユ瘝鐗�
+ * 350 鏍� 0 宸紓銆佸叕浜�/鍑虹/杞ㄩ亾杞浮鍚屾壒 0 宸紓锛夈��
+ *
+ * 鏈増瑕嗙洊 4 寮犲彴璐﹂〉锛氱彮绾垮寘杞︺�佸叕浜ゃ�佸嚭绉熴�佽建閬撹疆娓★紱
+ * 缃戠害杞︿緷璧栥�婄綉绾﹁溅璁㈠崟鍙婂叏鐪佹�婚噺銆嬫媶鍒嗚緭鍏ャ�佽揣杩愰〉鍦� M3 鎺ュ叆锛屽悗缁増鏈ˉ鍏呫��
+ *
+ * 鍐欏叆瑙勫垯锛�
+ * 1) 鍙啓鈥滃競宸炴槑缁嗚鈥濈殑 2026 骞� m 鏈堝綋鏈堝�煎垪锛坢 鏈堝�煎垪 = 绗� 2+2*(m-1) 鍒楋紝0 鍩猴紝鍗� C 璧凤級锛�
+ * 2) 鍏ㄧ渷琛岋紙=17 甯傚窞姹傚拰鍏紡锛変笌璺ㄩ〉鍚堟垚椤靛潎涓哄叕寮忥紝涓嶅姩锛孍xcel 鎵撳紑鑷姩閲嶇畻锛�
+ * 3) 2025 鍚屾湡鍙傜収鍒椾繚鐣欐瘝鐗堢紦瀛樺�硷紙鍚屾瘮鍏紡鑷姩寮曠敤锛夛紱
+ * 4) 婧愭暟鎹暣鏈堢己澶辨椂鏀堕泦鎻愮ず銆佷笉鍥炲~锛涘競宸炲綋鏈堝叏涓� 0 鏃朵繚鎸佹瘝鐗堢┖鍗曞厓鏍笺��
+ */
+@Service
+public class SummaryWorkbookFiller {
+
+ @Resource
+ private MidCalc midCalc;
+ @Resource
+ private PaxCalc paxCalc;
+
+ /** 2026 骞� 1 鏈堝綋鏈堝�煎垪锛�0 鍩猴紝鍗� C 鍒楋級 */
+ private static final int FIRST_MONTH_COL = 2;
+
+ /** 鍥炲~ 1..keepMonths 鏈堝彴璐﹂〉锛岃繑鍥炲啓鍏ユ牸鏁帮紱缂烘暟鎻愮ず鍐欏叆 problems */
+ public int fillMonthlyLedger(XSSFWorkbook wb, int year, int keepMonths, List<String> problems) {
+ if (wb == null || keepMonths <= 0) return 0;
+ if (problems == null) problems = new ArrayList<>();
+ String yearPrefix = year + "-";
+ int filled = 0;
+ filled += fillCityRows(wb, "鐝嚎鍖呰溅", midCalc.banxianMonthly(yearPrefix, keepMonths), year, keepMonths, problems, false);
+ filled += fillCityRows(wb, "鍏氦", paxCalc.busMonthly(yearPrefix, keepMonths), year, keepMonths, problems, false);
+ filled += fillCityRows(wb, "鍑虹", paxCalc.taxiMonthly(yearPrefix, keepMonths), year, keepMonths, problems, false);
+ filled += fillTrackFerry(wb, paxCalc.railFerryMonthly(yearPrefix, keepMonths), year, keepMonths, problems);
+ return filled;
+ }
+
+ /** 閫氱敤鍙拌处椤碉紙鐝嚎鍖呰溅/鍏氦/鍑虹锛夊洖濉細鎸夆�滃垪 A 甯傚窞鍚� + 鍒� B 鎸囨爣鏂囨鈥濆畾浣嶈锛屼笉鍐欐琛屽彿 */
+ private int fillCityRows(XSSFWorkbook wb, String sheetName,
+ Map<Integer, Map<String, double[]>> monthly,
+ int year, int keepMonths, List<String> problems, boolean wyc) {
+ Sheet sh = wb.getSheet(sheetName);
+ if (sh == null) {
+ problems.add(sheetName + "椤典笉瀛樺湪锛堟瘝鐗堢己澶辫椤碉級锛岃烦杩囪嚜鍔ㄥ洖濉�");
+ return 0;
+ }
+ int cap = monthColumnCapacity(sh);
+ int mMax = Math.min(keepMonths, cap);
+ if (mMax <= 0) {
+ problems.add(sheetName + "椤垫湭璇嗗埆鍒� 2026 骞寸疮璁″垪锛岃烦杩囪嚜鍔ㄥ洖濉�");
+ return 0;
+ }
+ // 1) 甯傚窞璧峰琛岋紙鍒� A 涓鸿鑼冨競宸炲悕锛�
+ Map<String, Integer> cityStart = new LinkedHashMap<>();
+ for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ String city = cityOf(row.getCell(0));
+ if (city != null && !cityStart.containsKey(city)) cityStart.put(city, r);
+ }
+ if (cityStart.isEmpty()) {
+ problems.add(sheetName + "椤垫湭璇嗗埆鍒板競宸炶锛岃烦杩囪嚜鍔ㄥ洖濉�");
+ return 0;
+ }
+ List<Integer> starts = new ArrayList<>(cityStart.values());
+ int filled = 0;
+ List<String> missingMonths = new ArrayList<>();
+ for (int m = 1; m <= mMax; m++) {
+ if (!monthly.containsKey(m)) missingMonths.add(m + "鏈�");
+ }
+ if (!missingMonths.isEmpty()) {
+ problems.add(sheetName + "缂� " + year + " 骞� " + String.join("銆�", missingMonths) + " 婧愭暟鎹紙鏈洖濉級");
+ }
+ for (int i = 0; i < starts.size(); i++) {
+ String city = findCityByStart(sh, starts.get(i));
+ if (city == null) continue;
+ int end = (i + 1 < starts.size()) ? starts.get(i + 1) - 1 : sh.getLastRowNum();
+ // 2) 琛屽唴鍚勬寚鏍囨墍鍦ㄨ锛圔 鍒楁枃妗� 鈫� 鎸囨爣浣� 0..3锛�
+ int[] metricRow = new int[]{-1, -1, -1, -1};
+ for (int r = starts.get(i); r <= end; r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ int idx = metricIndexOf(text(row.getCell(1)));
+ if (idx >= 0 && metricRow[idx] < 0) metricRow[idx] = r;
+ }
+ if (metricRow[0] < 0 && metricRow[1] < 0) continue;
+ for (int m = 1; m <= mMax; m++) {
+ Map<String, double[]> mm = monthly.get(m);
+ if (mm == null) continue;
+ double[] arr = mm.get(city);
+ if (arr == null || (arr[0] == 0.0 && arr[1] == 0.0)) continue;
+ int col = FIRST_MONTH_COL + 2 * (m - 1);
+ for (int idx = 0; idx < 4; idx++) {
+ if (metricRow[idx] < 0) continue;
+ double val = arr[idx];
+ if (val == 0.0) continue;
+ filled += setNumeric(sh, metricRow[idx], col, val);
+ }
+ }
+ }
+ return filled;
+ }
+
+ /** 杞ㄩ亾杞浮椤碉紙杞ㄩ亾=姝︽眽/榛勭煶锛涜疆娓′粎姝︽眽锛変笓鐢ㄥ洖濉� */
+ private int fillTrackFerry(XSSFWorkbook wb, Map<Integer, Map<String, double[]>> monthly,
+ int year, int keepMonths, List<String> problems) {
+ String sheetName = "杞ㄩ亾銆佽疆娓�";
+ Sheet sh = wb.getSheet(sheetName);
+ if (sh == null) return 0;
+ int cap = monthColumnCapacity(sh);
+ int mMax = Math.min(keepMonths, cap);
+ if (mMax <= 0) return 0;
+ // 杞ㄩ亾鍧椾笌杞浮鍧楁爣棰樿锛堝垪 A 鏂囨锛�
+ int trackTitle = -1, ferryTitle = -1;
+ for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) {
+ String a = text(sh.getRow(r) == null ? null : sh.getRow(r).getCell(0));
+ if (a == null) continue;
+ if (trackTitle < 0 && a.startsWith("杞ㄩ亾瀹㈣繍閲�")) trackTitle = r;
+ else if (ferryTitle < 0 && a.startsWith("杞浮瀹㈣繍閲�")) ferryTitle = r;
+ }
+ if (trackTitle < 0 || ferryTitle < 0) {
+ problems.add(sheetName + "椤垫湭璇嗗埆鍒拌建閬�/杞浮鍧楁爣棰橈紝璺宠繃鑷姩鍥炲~");
+ return 0;
+ }
+ int filled = 0;
+ filled += fillFerryBlock(sh, monthly, trackTitle + 3, ferryTitle - 1, 0, mMax, problems, sheetName);
+ filled += fillFerryBlock(sh, monthly, ferryTitle + 3, sh.getLastRowNum(), 2, mMax, problems, sheetName);
+ return filled;
+ }
+
+ /** 濉厖涓�娈碘�滄爣棰樿鍚庢暟鎹尯鈥濓細base 涓鸿鍧楁寚鏍囦綅鍩猴紙杞ㄩ亾 0 / 杞浮 2锛夛紱block 鍐�
+ * 姣忓競宸� 2 琛岋細瀹㈣繍閲忚锛堝垪 A=甯傚窞鍚嶏級銆佹梾瀹㈠懆杞噺琛岋紙A 绌猴紝B 鍚�滃懆杞噺鈥濓級 */
+ private int fillFerryBlock(Sheet sh, Map<Integer, Map<String, double[]>> monthly,
+ int start, int end, int base, int mMax,
+ List<String> problems, String sheetName) {
+ int filled = 0;
+ // 鏀堕泦甯傚窞瀹㈣繍閲忚
+ Map<String, Integer> paxRow = new LinkedHashMap<>();
+ for (int r = start; r <= end; r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ String city = cityOf(row.getCell(0));
+ if (city != null) paxRow.put(city, r);
+ }
+ for (Map.Entry<String, Integer> e : paxRow.entrySet()) {
+ String city = e.getKey();
+ int rp = e.getValue();
+ int rt = findTurnoverRow(sh, rp + 1, Math.min(end, rp + 6));
+ if (rt < 0) continue;
+ for (int m = 1; m <= mMax; m++) {
+ Map<String, double[]> mm = monthly.get(m);
+ if (mm == null) continue;
+ double[] arr = mm.get(city);
+ if (arr == null) continue;
+ int col = FIRST_MONTH_COL + 2 * (m - 1);
+ double pax = arr[base];
+ double turn = arr[base + 1];
+ if (pax != 0.0) filled += setNumeric(sh, rp, col, pax);
+ if (turn != 0.0) filled += setNumeric(sh, rt, col, turn);
+ }
+ }
+ return filled;
+ }
+
+ private int findTurnoverRow(Sheet sh, int from, int to) {
+ for (int r = from; r <= to; r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ String a = text(row.getCell(0));
+ if (a != null && !a.trim().isEmpty()) return -1; // 杩涘叆涓嬩竴甯傚窞鍧�
+ String b = text(row.getCell(1));
+ if (b != null && b.contains("鍛ㄨ浆閲�")) return r;
+ }
+ return -1;
+ }
+
+ /** 鍐欐暟鍊硷細鏍间笉瀛樺湪鍒欏缓鏍煎苟澶嶅埗鍚岃 1 鏈堝垪鏍峰紡锛涜繑鍥� 1 */
+ private int setNumeric(Sheet sh, int r, int col, double val) {
+ Row row = sh.getRow(r);
+ if (row == null) row = sh.createRow(r);
+ Cell c = row.getCell(col);
+ if (c == null) {
+ c = row.createCell(col);
+ Cell ref = row.getCell(FIRST_MONTH_COL);
+ if (ref != null && ref.getCellStyle() != null) c.setCellStyle(ref.getCellStyle());
+ }
+ c.setCellValue(val);
+ return 1;
+ }
+
+ /** 琛� B 鍒楁枃妗� 鈫� 鎸囨爣浣嶏細0 瀹㈣繍閲� / 1 鏃呭鍛ㄨ浆閲� / 2 鍏朵腑鍩庡競鍐呭杩愰噺鎴栧叾涓釜浣撳杩愰噺 / 3 瀵瑰簲鍛ㄨ浆閲� */
+ private int metricIndexOf(String b) {
+ if (b == null) return -1;
+ if (b.contains("鍏朵腑涓綋鏃呭鍛ㄨ浆閲�") || b.contains("鍏朵腑鍩庡競鍐呮梾瀹㈠懆杞噺")) return 3;
+ if (b.contains("鍏朵腑涓綋瀹㈣繍閲�") || b.contains("鍏朵腑鍩庡競鍐呭杩愰噺")) return 2;
+ if (b.contains("鏃呭鍛ㄨ浆閲�")) return 1;
+ if (b.contains("瀹㈣繍閲�")) return 0;
+ return -1;
+ }
+
+ /** 鍒� A 鏂囨 鈫� 瑙勮寖甯傚窞鍚嶏紙婀栧寳鐪�/鍏ㄧ渷銆侀潪甯傚窞琛岃繑鍥� null锛� */
+ private String cityOf(Cell a) {
+ String t = text(a);
+ if (t == null || t.trim().isEmpty()) return null;
+ String norm = RegionUtil.normalizeCityName(t.trim());
+ return RegionUtil.cityList().contains(norm) ? norm : null;
+ }
+
+ private String findCityByStart(Sheet sh, int startRow) {
+ Row row = sh.getRow(startRow);
+ return row == null ? null : cityOf(row.getCell(0));
+ }
+
+ /** 鏈堜唤瀹归噺锛氬湪琛ㄥご锛堝墠 5 琛岋級鎵锯��2026鈥︾疮璁♀�濆垪锛屽閲�=(绱鍒�-1 鏈堝垪)/2 */
+ private int monthColumnCapacity(Sheet sh) {
+ for (int r = 0; r <= 4 && r <= sh.getLastRowNum(); r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ for (Cell c : row) {
+ if (c == null) continue;
+ String t = text(c);
+ if (t != null && t.contains("2026") && t.contains("绱") && c.getColumnIndex() > FIRST_MONTH_COL) {
+ return (c.getColumnIndex() - FIRST_MONTH_COL) / 2;
+ }
+ }
+ }
+ return 7;
+ }
+
+ private String text(Cell c) {
+ if (c == null) return null;
+ switch (c.getCellType()) {
+ case STRING: return c.getStringCellValue();
+ case NUMERIC: return Double.toString(c.getNumericCellValue());
+ default: return null;
+ }
+ }
+}
--
Gitblit v1.9.1