From abf468c9946c21512ddf2093895b30910e09e536 Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期一, 21 九月 2026 11:33:54 +0800
Subject: [PATCH] fix(汇总表): 中口径排名累计同比基数改用母版2025静态列
---
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | 130 ++++++++++++++++++++++++++++++++++++++++---
1 files changed, 121 insertions(+), 9 deletions(-)
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
index d4673d6..bbe8df3 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -2681,9 +2681,19 @@
* 鐢熸垚_涓彛寰勬帓鍚�.xlsx锛氬崟鍧楃疮璁★紙閫� 1 涓湀=褰撴湀锛岄�� 1-6 鏈�=绱锛夛紝RANK/SUM 鍏紡淇濈暀銆�
*/
public byte[] exportPassengerMidRank(String period, String mode) throws Exception {
+ return exportPassengerMidRank(period, mode, null);
+ }
+
+ /**
+ * 鏂规 A锛�2026-09-21锛夛細涓彛寰勬帓鍚嶇殑绱鍚屾瘮鍩烘暟涓庘�滀腑鍙e緞鏄庣粏鈥濅繚鎸佸悓婧愩��
+ * 鏄庣粏椤电殑 2025 骞村垪鏄瘝鐗堥潤鎬佸畾绋垮�硷紝鎺掑悕椤靛師鍏堟煡搴撶幇绠楋紝涓よ�呭湪 2025-03/04 缃戠害杞︽媶鍒嗕笂涓嶅悓銆�
+ * summaryWb 闈炵┖鏃剁洿鎺ュ鐢ㄥ綋鍓嶆鍦ㄧ敓鎴愮殑姹囨�诲伐浣滅翱锛涚嫭绔嬪鍑烘椂鍐嶆墦寮�瀵瑰簲姣嶇増銆�
+ */
+ private byte[] exportPassengerMidRank(String period, String mode, XSSFWorkbook summaryWb) throws Exception {
int maxMonth = monthOf(period, mode);
int currentYear = Integer.parseInt(period.substring(0, 4));
File template = resolvePassengerTemplate("鐢熸垚_涓彛寰勬帓鍚�.xlsx");
+ Map<String, double[]> lastYearCumBase = loadMidRankStaticBase(period, mode, summaryWb, currentYear, maxMonth);
try (InputStream in = new FileInputStream(template);
XSSFWorkbook wb = new XSSFWorkbook(in)) {
Sheet sheet = wb.getSheetAt(0);
@@ -2703,8 +2713,8 @@
title.getCell(10).setCellValue(currentYear + "骞�" + maxMonth + "鏈堝叏鐪佸垎甯傚窞瀹屾垚閬撹矾瀹㈣繍鐢熶骇鎯呭喌");
}
// 鍏ㄧ渷琛� r3锛欱3/F3 涓� SUM 鍏紡淇濈暀锛汥3/H3 鍚屾瘮濉�硷紙0-based 鍒� 3/7锛�
- setValOrBlank(sheet, 2, 3, midCumYoy(mid, currentYear, "婀栧寳鐪�", maxMonth, 0, true));
- setValOrBlank(sheet, 2, 7, midCumYoy(mid, currentYear, "婀栧寳鐪�", maxMonth, 0, false));
+ setValOrBlank(sheet, 2, 3, midRankCumYoy(mid, currentYear, "婀栧寳鐪�", maxMonth, true, lastYearCumBase));
+ setValOrBlank(sheet, 2, 7, midRankCumYoy(mid, currentYear, "婀栧寳鐪�", maxMonth, false, lastYearCumBase));
// 鍙冲潡鍏ㄧ渷琛� N3/R3锛氬綋鏈堝悓姣旓紙L3/P3 涓� SUM 鍏紡淇濈暀锛�
setValOrBlank(sheet, 2, 13, midMonthYoy(mid, currentYear, maxMonth, "婀栧寳鐪�", 0, true));
setValOrBlank(sheet, 2, 17, midMonthYoy(mid, currentYear, maxMonth, "婀栧寳鐪�", 0, false));
@@ -2715,17 +2725,13 @@
int r0 = 3 + i;
double pass = midCumClass(mid, currentYear, city, maxMonth, 0, true);
double turn = midCumClass(mid, currentYear, city, maxMonth, 0, false);
- double lastPass = midCumClass(mid, currentYear - 1, city, maxMonth, 0, true);
- double lastTurn = midCumClass(mid, currentYear - 1, city, maxMonth, 0, false);
setValOrBlank(sheet, r0, 1, pass == 0 ? null : pass);
- setValOrBlank(sheet, r0, 3, midCumYoy(mid, currentYear, city, maxMonth, 0, true));
+ setValOrBlank(sheet, r0, 3, midRankCumYoy(mid, currentYear, city, maxMonth, true, lastYearCumBase));
setValOrBlank(sheet, r0, 5, turn == 0 ? null : turn);
- setValOrBlank(sheet, r0, 7, midCumYoy(mid, currentYear, city, maxMonth, 0, false));
+ setValOrBlank(sheet, r0, 7, midRankCumYoy(mid, currentYear, city, maxMonth, false, lastYearCumBase));
// 鍙冲潡褰撴湀锛歀/P 鍊笺�丯/R 褰撴湀鍚屾瘮锛圡/O/Q/S 鎺掑悕鍏紡淇濈暀锛�
double mPass = midClassVal(mid, currentYear, maxMonth, city, 0, true);
double mTurn = midClassVal(mid, currentYear, maxMonth, city, 0, false);
- double mLastPass = midClassVal(mid, currentYear - 1, maxMonth, city, 0, true);
- double mLastTurn = midClassVal(mid, currentYear - 1, maxMonth, city, 0, false);
setValOrBlank(sheet, r0, 11, mPass == 0 ? null : mPass);
setValOrBlank(sheet, r0, 13, mPass == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, city, 0, true));
setValOrBlank(sheet, r0, 15, mTurn == 0 ? null : mTurn);
@@ -2734,6 +2740,112 @@
recalc(wb);
return toBytes(wb);
}
+ }
+
+ /** 璇诲彇姣嶇増銆婁腑鍙e緞鏄庣粏銆嬬殑 2025 骞撮�愭湀闈欐�佸�硷紝姹囨�绘垚鎺掑悕椤垫墍闇�鐨勫幓骞村悓鏈熺疮璁″熀鏁般�� */
+ private Map<String, double[]> readMidDetailLastYearCumulative(XSSFWorkbook sourceWb, int currentYear, int maxMonth) {
+ Map<String, double[]> out = new LinkedHashMap<>();
+ if (sourceWb == null || maxMonth <= 0) return out;
+ Sheet sheet = sourceWb.getSheet("涓彛寰勬槑缁�");
+ if (sheet == null) return out;
+ Map<Integer, Integer> monthCols = new LinkedHashMap<>();
+ java.util.regex.Pattern monthHeader = java.util.regex.Pattern.compile("^(\\d{4})骞�(\\d{1,2})鏈�$");
+ int headerEnd = Math.min(sheet.getLastRowNum(), sheet.getFirstRowNum() + 5);
+ for (int r = sheet.getFirstRowNum(); r <= headerEnd; r++) {
+ Row row = sheet.getRow(r);
+ if (row == null) continue;
+ for (int c = row.getFirstCellNum(); c >= 0 && c < row.getLastCellNum(); c++) {
+ String text = cellText(row.getCell(c));
+ if (text == null) continue;
+ java.util.regex.Matcher matcher = monthHeader.matcher(text.trim());
+ if (!matcher.matches()) continue;
+ int y = Integer.parseInt(matcher.group(1));
+ int m = Integer.parseInt(matcher.group(2));
+ if (y == currentYear - 1 && m >= 1 && m <= maxMonth) monthCols.putIfAbsent(m, c);
+ }
+ }
+ if (monthCols.size() < maxMonth) return out;
+ for (int r = sheet.getFirstRowNum(); r <= sheet.getLastRowNum(); r++) {
+ Row row = sheet.getRow(r);
+ if (row == null) continue;
+ String city = RegionUtil.normalizeCityName(cellText(row.getCell(0)));
+ if (city == null || !RegionUtil.CITY_LIST.contains(city)) continue;
+ String metric = cellText(row.getCell(1));
+ if (metric == null) continue;
+ int idx = metric.contains("鎬绘梾瀹㈠懆杞噺") ? 1 : (metric.contains("鎬诲杩愰噺") ? 0 : -1);
+ if (idx < 0) continue;
+ double sum = 0.0;
+ boolean complete = true;
+ for (int m = 1; m <= maxMonth; m++) {
+ Cell c = row.getCell(monthCols.get(m));
+ if (c == null) { complete = false; break; }
+ if (c.getCellType() == CellType.NUMERIC) {
+ sum += c.getNumericCellValue();
+ } else if (c.getCellType() == CellType.FORMULA && c.getCachedFormulaResultType() == CellType.NUMERIC) {
+ sum += c.getNumericCellValue();
+ } else {
+ complete = false;
+ break;
+ }
+ }
+ double[] values = out.computeIfAbsent(city, k -> new double[]{Double.NaN, Double.NaN});
+ values[idx] = complete ? sum : Double.NaN;
+ }
+ double[] province = new double[2];
+ for (String city : RegionUtil.CITY_LIST) {
+ double[] values = out.get(city);
+ if (values == null || Double.isNaN(values[0]) || Double.isNaN(values[1])) return new LinkedHashMap<>();
+ province[0] += values[0];
+ province[1] += values[1];
+ }
+ out.put("婀栧寳鐪�", province);
+ return out;
+ }
+
+ /** 鐙珛瀵煎嚭鏃朵粠瀵瑰簲姹囨�绘瘝鐗堣鍙栭潤鎬佸熀鏁帮紱姹囨�诲鍑烘椂鐩存帴澶嶇敤鍐呭瓨涓殑宸ヤ綔绨匡紝閬垮厤閲嶅 I/O銆� */
+ private Map<String, double[]> loadMidRankStaticBase(String period, String mode, XSSFWorkbook summaryWb,
+ int currentYear, int maxMonth) {
+ if (summaryWb != null) {
+ Map<String, double[]> base = readMidDetailLastYearCumulative(summaryWb, currentYear, maxMonth);
+ if (!base.isEmpty()) return base;
+ log.warn("涓彛寰勬帓鍚嶏細褰撳墠姹囨�诲伐浣滅翱鐨勪腑鍙e緞鏄庣粏鏈鍒板畬鏁� 2025 闈欐�佺疮璁″熀鏁帮紝鍥為��搴撳唴鐜扮畻");
+ return null;
+ }
+ double savedZipRatio = ZipSecureFile.getMinInflateRatio();
+ ZipSecureFile.setMinInflateRatio(0.0001);
+ try {
+ File mother = resolveSummaryMother(period, mode);
+ if (mother == null || !mother.isFile()) {
+ log.warn("涓彛寰勬帓鍚嶏細鏈壘鍒� {} 鐨勬眹鎬绘瘝鐗堬紝2025 绱鍩烘暟鍥為��搴撳唴鐜扮畻", period);
+ return null;
+ }
+ try (InputStream in = new FileInputStream(mother); XSSFWorkbook wb = new XSSFWorkbook(in)) {
+ Map<String, double[]> base = readMidDetailLastYearCumulative(wb, currentYear, maxMonth);
+ if (base.isEmpty()) {
+ log.warn("涓彛寰勬帓鍚嶏細姣嶇増 {} 鐨勪腑鍙e緞鏄庣粏鏈鍒板畬鏁� 2025 闈欐�佺疮璁″熀鏁帮紝鍥為��搴撳唴鐜扮畻", mother.getName());
+ return null;
+ }
+ log.info("涓彛寰勬帓鍚嶏細2025 绱鍩烘暟鏀圭敤姣嶇増闈欐�佸垪锛坽}锛�", mother.getName());
+ return base;
+ }
+ } catch (Exception e) {
+ log.warn("涓彛寰勬帓鍚嶏細璇诲彇姣嶇増 2025 闈欐�佺疮璁″熀鏁板け璐ワ紝鍥為��搴撳唴鐜扮畻锛歿}", e.getMessage());
+ return null;
+ } finally {
+ ZipSecureFile.setMinInflateRatio(savedZipRatio);
+ }
+ }
+
+ /** 涓彛寰勬帓鍚嶇疮璁″悓姣旓細鏂规 A 鏈夐潤鎬佸熀鏁版椂涓庡叾瀵归綈锛屽惁鍒欎繚鐣欏師搴撳唴鐜扮畻閫昏緫銆� */
+ private Double midRankCumYoy(Map<Integer, Map<String, double[][]>> mid, int year, String area,
+ int monthCount, boolean volume, Map<String, double[]> staticBase) {
+ if (staticBase == null) return midCumYoy(mid, year, area, monthCount, 0, volume);
+ double[] values = staticBase.get(area);
+ if (values == null) return null;
+ double current = midCumClass(mid, year, area, monthCount, 0, volume);
+ if (current == 0.0) return null;
+ double base = volume ? values[0] : values[1];
+ return base == 0.0 ? null : yoyOf(current, base);
}
/** 鍐欐暟鍊兼垨娓呯┖锛堝叕寮忓崟鍏冩牸淇濈暀涓嶅姩锛� */
@@ -3754,7 +3866,7 @@
int n = 0;
n += copyRankValues(wb, "璐ц繍閲忔帓鍚�", exportFreightRank(period, mode), new int[][]{{0, 0}, {22, 0}});
n += copyRankValues(wb, "璐ц繍鍛ㄨ浆閲忔帓鍚�", exportTurnoverRank(period, mode), new int[][]{{0, 0}, {22, 0}});
- n += copyRankValues(wb, "涓彛寰勬帓鍚�", exportPassengerMidRank(period, mode), new int[][]{{0, 0}, {0, 10}});
+ n += copyRankValues(wb, "涓彛寰勬帓鍚�", exportPassengerMidRank(period, mode, wb), new int[][]{{0, 0}, {0, 10}});
return n;
}
--
Gitblit v1.9.1