From a81500724e035da22fc49128278733998cfcb9b7 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期五, 09 十月 2026 16:43:40 +0800
Subject: [PATCH] docs(流程): 提交信息对齐同事 xyc 风格(类型只用 feat/fix/docs、scope 可省、不写正文)
---
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | 181 ++++++++++++++++++++++++++++++++++++--------
1 files changed, 146 insertions(+), 35 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 bbe8df3..67a22b4 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
@@ -4085,9 +4085,8 @@
private static final int SM_WYC_CX_PAX = 16, SM_WYC_CX_TURN = 17;
private static final int SM_FREIGHT_TURN = 18;
private static final int SM_DIM = 19;
- /** 2026 骞� 1 鏈堝綋鏈堝�煎垪锛�0 鍩猴紝C 鍒楋級锛�2025 骞� 1 鏈堝綋鏈堝�煎垪锛�0 鍩猴紝V 鍒楋級 */
- private static final int SM_CUR_COL0 = 2;
- private static final int SM_LAST_COL0 = 21;
+ // 2026-10-09锛氬師鍏堝啓姝荤殑 SM_CUR_COL0=2锛�2026骞�1鏈�=C锛�/ SM_LAST_COL0=21锛�2025骞�1鏈�=V锛夊凡搴熷純锛�
+ // 鏀逛负鎸夎〃澶村姩鎬佸畾浣嶏紙瑙� smMonthCols / smYearMonthOf锛夛紝鍏煎銆屾枃鏈� / 鏃ユ湡搴忓垪鍙� / 鏃ユ湡鏍煎紡銆嶄笁绉嶈〃澶村啓娉曘��
/**
* 鍒锋柊鍥涘紶璺ㄩ〉鍚堟垚椤碉細褰撳勾绱锛�1..month 鏈堬級銆佸綋鏈堬紙month 鏈堬級鍙婂搴斿悓姣旓紱
@@ -4098,10 +4097,10 @@
int[] cumMonths = new int[month];
for (int m = 1; m <= month; m++) cumMonths[m - 1] = m;
int[] oneMonth = new int[]{month};
- Map<String, double[]> curCum = smReadLedgerMetrics(wb, true, cumMonths);
- Map<String, double[]> lastCum = smReadLedgerMetrics(wb, false, cumMonths);
- Map<String, double[]> curMon = smReadLedgerMetrics(wb, true, oneMonth);
- Map<String, double[]> lastMon = smReadLedgerMetrics(wb, false, oneMonth);
+ Map<String, double[]> curCum = smReadLedgerMetrics(wb, year, cumMonths);
+ Map<String, double[]> lastCum = smReadLedgerMetrics(wb, year - 1, cumMonths);
+ Map<String, double[]> curMon = smReadLedgerMetrics(wb, year, oneMonth);
+ Map<String, double[]> lastMon = smReadLedgerMetrics(wb, year - 1, oneMonth);
if (curCum.isEmpty()) {
log.warn("姹囨�诲ぇ琛ㄥ洓椤靛埛鏂帮細鍙拌处椤垫湭璇诲埌甯傚窞鏁版嵁锛岃烦杩囷紙淇濇寔姣嶇増鍘熷�硷級");
return 0;
@@ -4130,22 +4129,23 @@
}
/** 鍙拌处椤电疮璁″彇鏁帮細甯傚窞瑙勮寖鍚� -> 19 缁存寚鏍� */
- private Map<String, double[]> smReadLedgerMetrics(XSSFWorkbook wb, boolean curYear, int[] months) {
+ private Map<String, double[]> smReadLedgerMetrics(XSSFWorkbook wb, int blockYear, int[] months) {
Map<String, double[]> out = new LinkedHashMap<>();
- smReadCityPaxPage(wb, "鍏氦", curYear, months, out, SM_BUS_PAX, SM_BUS_TURN, SM_BUS_CX_PAX, SM_BUS_CX_TURN);
- smReadCityPaxPage(wb, "鍑虹", curYear, months, out, SM_TAXI_PAX, SM_TAXI_TURN, SM_TAXI_CX_PAX, SM_TAXI_CX_TURN);
- smReadCityPaxPage(wb, "缃戠害杞�", curYear, months, out, SM_WYC_PAX, SM_WYC_TURN, SM_WYC_CX_PAX, SM_WYC_CX_TURN);
- smReadRailFerry(wb, curYear, months, out);
- smReadBanxian(wb, curYear, months, out);
- smReadFreightTurnover(wb, curYear, months, out);
+ smReadCityPaxPage(wb, "鍏氦", blockYear, months, out, SM_BUS_PAX, SM_BUS_TURN, SM_BUS_CX_PAX, SM_BUS_CX_TURN);
+ smReadCityPaxPage(wb, "鍑虹", blockYear, months, out, SM_TAXI_PAX, SM_TAXI_TURN, SM_TAXI_CX_PAX, SM_TAXI_CX_TURN);
+ smReadCityPaxPage(wb, "缃戠害杞�", blockYear, months, out, SM_WYC_PAX, SM_WYC_TURN, SM_WYC_CX_PAX, SM_WYC_CX_TURN);
+ smReadRailFerry(wb, blockYear, months, out);
+ smReadBanxian(wb, blockYear, months, out);
+ smReadFreightTurnover(wb, blockYear, months, out);
return out;
}
/** 鍏氦/鍑虹/缃戠害杞﹂〉锛氭瘡甯傚窞 4 琛岋紙瀹㈣繍閲�/鏃呭鍛ㄨ浆閲�/鍏朵腑鍩庡競鍐呭杩愰噺/鍏朵腑鍩庡競鍐呮梾瀹㈠懆杞噺锛� */
- private void smReadCityPaxPage(XSSFWorkbook wb, String sheetName, boolean curYear, int[] months,
+ private void smReadCityPaxPage(XSSFWorkbook wb, String sheetName, int blockYear, int[] months,
Map<String, double[]> out, int paxIdx, int turnIdx, int cxPaxIdx, int cxTurnIdx) {
Sheet sh = wb.getSheet(sheetName);
if (sh == null) return;
+ Map<Integer, Integer> monthCols = smMonthCols(sh, blockYear);
int last = sh.getLastRowNum();
for (int r = sh.getFirstRowNum(); r <= last; r++) {
Row row = sh.getRow(r);
@@ -4168,10 +4168,10 @@
else if (paxRow < 0) paxRow = k;
}
}
- double totalPax = smSumMonths(sh, paxRow, curYear, months);
- double totalTurn = smSumMonths(sh, turnRow, curYear, months);
- double cityPax = smSumMonths(sh, cxPaxRow, curYear, months);
- double cityTurn = smSumMonths(sh, cxTurnRow, curYear, months);
+ double totalPax = smSumMonths(sh, paxRow, monthCols, months);
+ double totalTurn = smSumMonths(sh, turnRow, monthCols, months);
+ double cityPax = smSumMonths(sh, cxPaxRow, monthCols, months);
+ double cityTurn = smSumMonths(sh, cxTurnRow, monthCols, months);
double[] arr = out.computeIfAbsent(city, k -> new double[SM_DIM]);
arr[paxIdx] += cityPax; // 鍩庡競瀹㈣繍鍙e緞鍙栤�滃煄甯傚唴鈥�
arr[turnIdx] += cityTurn;
@@ -4181,9 +4181,10 @@
}
/** 杞ㄩ亾銆佽疆娓¢〉锛氳建閬撳潡锛堟姹�/榛勭煶锛�+ 杞浮鍧楋紙姝︽眽锛� */
- private void smReadRailFerry(XSSFWorkbook wb, boolean curYear, int[] months, Map<String, double[]> out) {
+ private void smReadRailFerry(XSSFWorkbook wb, int blockYear, int[] months, Map<String, double[]> out) {
Sheet sh = wb.getSheet("杞ㄩ亾銆佽疆娓�");
if (sh == null) return;
+ Map<Integer, Integer> monthCols = smMonthCols(sh, blockYear);
int last = sh.getLastRowNum();
int ferryTitle = -1;
for (int r = sh.getFirstRowNum(); r <= last; r++) {
@@ -4192,12 +4193,12 @@
String a = smText(row.getCell(0));
if (a != null && a.contains("杞浮瀹㈣繍閲�")) { ferryTitle = r; break; }
}
- smReadRailFerryBlock(sh, curYear, months, out, sh.getFirstRowNum(),
+ smReadRailFerryBlock(sh, monthCols, months, out, sh.getFirstRowNum(),
ferryTitle < 0 ? last : ferryTitle - 1, SM_RAIL_PAX);
- if (ferryTitle >= 0) smReadRailFerryBlock(sh, curYear, months, out, ferryTitle, last, SM_FERRY_PAX);
+ if (ferryTitle >= 0) smReadRailFerryBlock(sh, monthCols, months, out, ferryTitle, last, SM_FERRY_PAX);
}
- private void smReadRailFerryBlock(Sheet sh, boolean curYear, int[] months, Map<String, double[]> out,
+ private void smReadRailFerryBlock(Sheet sh, Map<Integer, Integer> monthCols, int[] months, Map<String, double[]> out,
int start, int end, int baseIdx) {
for (int r = start; r <= end; r++) {
Row row = sh.getRow(r);
@@ -4214,15 +4215,16 @@
else if (paxRow < 0) paxRow = k;
}
double[] arr = out.computeIfAbsent(city, k -> new double[SM_DIM]);
- arr[baseIdx] += smSumMonths(sh, paxRow, curYear, months);
- arr[baseIdx + 1] += smSumMonths(sh, turnRow, curYear, months);
+ arr[baseIdx] += smSumMonths(sh, paxRow, monthCols, months);
+ arr[baseIdx + 1] += smSumMonths(sh, turnRow, monthCols, months);
}
}
/** 鐝嚎鍖呰溅椤碉細姣忓競宸� 瀹㈣繍閲� / 鏃呭鍛ㄨ浆閲忥紙鈥滃叾涓釜浣撯�濊涓嶉噸澶嶈鍏ワ級 */
- private void smReadBanxian(XSSFWorkbook wb, boolean curYear, int[] months, Map<String, double[]> out) {
+ private void smReadBanxian(XSSFWorkbook wb, int blockYear, int[] months, Map<String, double[]> out) {
Sheet sh = wb.getSheet("鐝嚎鍖呰溅");
if (sh == null) return;
+ Map<Integer, Integer> monthCols = smMonthCols(sh, blockYear);
int last = sh.getLastRowNum();
for (int r = sh.getFirstRowNum(); r <= last; r++) {
Row row = sh.getRow(r);
@@ -4239,16 +4241,17 @@
else if (b.contains("瀹㈣繍閲�") && paxRow < 0) paxRow = k;
}
double[] arr = out.computeIfAbsent(city, k -> new double[SM_DIM]);
- arr[SM_BX_PAX] += smSumMonths(sh, paxRow, curYear, months);
- arr[SM_BX_TURN] += smSumMonths(sh, turnRow, curYear, months);
+ arr[SM_BX_PAX] += smSumMonths(sh, paxRow, monthCols, months);
+ arr[SM_BX_TURN] += smSumMonths(sh, turnRow, monthCols, months);
}
}
/** 璐ц繍椤碉細姣忓競宸� 瑙勪笂璐х墿鍛ㄨ浆閲� + 瑙勪笅璐х墿鍛ㄨ浆閲忥紙鈥滆涓�+瑙勪笅鈥濊鏈韩鏄眰鍜屽叕寮忥紝涓嶇洿鎺ュ彇锛� */
- private void smReadFreightTurnover(XSSFWorkbook wb, boolean curYear, int[] months, Map<String, double[]> out) {
+ private void smReadFreightTurnover(XSSFWorkbook wb, int blockYear, int[] months, Map<String, double[]> out) {
Sheet sh = wb.getSheet(" 璐ц繍");
if (sh == null) sh = wb.getSheet("璐ц繍");
if (sh == null) return;
+ Map<Integer, Integer> monthCols = smMonthCols(sh, blockYear);
int last = sh.getLastRowNum();
for (int r = sh.getFirstRowNum(); r <= last; r++) {
Row row = sh.getRow(r);
@@ -4265,20 +4268,74 @@
else if (b.contains("瑙勪笅璐х墿鍛ㄨ浆閲�")) { if (below < 0) below = k; }
}
double[] arr = out.computeIfAbsent(city, k -> new double[SM_DIM]);
- arr[SM_FREIGHT_TURN] += smSumMonths(sh, above, curYear, months) + smSumMonths(sh, below, curYear, months);
+ arr[SM_FREIGHT_TURN] += smSumMonths(sh, above, monthCols, months) + smSumMonths(sh, below, monthCols, months);
}
}
- private double smSumMonths(Sheet sh, int rowIdx, boolean curYear, int[] months) {
- if (sh == null || rowIdx < 0) return 0;
+ private double smSumMonths(Sheet sh, int rowIdx, Map<Integer, Integer> monthCols, int[] months) {
+ if (sh == null || rowIdx < 0 || monthCols == null) return 0;
Row row = sh.getRow(rowIdx);
if (row == null) return 0;
double s = 0;
for (int m : months) {
- int col = (curYear ? SM_CUR_COL0 : SM_LAST_COL0) + 2 * (m - 1);
+ Integer col = monthCols.get(m);
+ if (col == null) continue;
s += smNum(row.getCell(col));
}
return s;
+ }
+
+ /** 鍙拌处椤点�屾煇骞� M 鏈堛�嶇殑 0 鍩哄垪鍙凤細鎸夎〃澶村姩鎬佸畾浣嶏紙涓嶅啀鍐欐 C/V锛夛紝鍏煎鏂囨湰 / 鏃ユ湡搴忓垪鍙� / 鏃ユ湡鏍煎紡涓夌鍐欐硶 */
+ private Map<Integer, Integer> smMonthCols(Sheet sh, int wantedYear) {
+ Map<Integer, Integer> cols = new LinkedHashMap<>();
+ if (sh == null) return cols;
+ int lastRow = Math.min(sh.getLastRowNum(), sh.getFirstRowNum() + 4);
+ for (int r = sh.getFirstRowNum(); r <= lastRow; r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ int lastCol = row.getLastCellNum();
+ for (int c = row.getFirstCellNum(); c >= 0 && c < lastCol; c++) {
+ Integer ym = smYearMonthOf(row.getCell(c));
+ if (ym == null || ym / 100 != wantedYear) continue;
+ int mo = ym % 100;
+ if (!cols.containsKey(mo)) cols.put(mo, c);
+ }
+ }
+ if (cols.isEmpty()) {
+ log.warn("姹囨�诲ぇ琛ㄥ洓椤靛埛鏂帮細{} 椤垫湭璇嗗埆鍒� {} 骞寸殑鏈堜唤琛ㄥご鍒楋紙鏀寔鏂囨湰/搴忓垪鍙�/鏃ユ湡涓夌褰㈠紡锛�", sh.getSheetName(), wantedYear);
+ }
+ return cols;
+ }
+
+ /** 琛ㄥご鍗曞厓鏍� -> 骞�*100+鏈堬紱鍙銆孻YYY骞碝鏈堛�嶆枃鏈垨銆屾煇鏈� 1 鍙枫�嶇殑鏃ユ湡搴忓垪鍙凤紝鎺掗櫎绱/鍚屾瘮/鐜瘮 */
+ private Integer smYearMonthOf(Cell c) {
+ if (c == null) return null;
+ try {
+ CellType t = c.getCellType();
+ if (t == CellType.STRING) {
+ String v = c.getStringCellValue();
+ if (v == null) return null;
+ v = v.trim();
+ if (v.isEmpty() || v.contains("绱") || v.contains("鍚屾瘮") || v.contains("鐜瘮")) return null;
+ java.util.regex.Matcher m = java.util.regex.Pattern
+ .compile("^(\\d{4})\\s*骞碶\s*(\\d{1,2})\\s*鏈�$").matcher(v);
+ if (!m.matches()) return null;
+ int y = Integer.parseInt(m.group(1));
+ int mo = Integer.parseInt(m.group(2));
+ return mo >= 1 && mo <= 12 ? y * 100 + mo : null;
+ }
+ if (t == CellType.NUMERIC) {
+ double v = c.getNumericCellValue();
+ if (v < 36526 || v > 73415) return null;
+ java.util.Calendar cal = java.util.Calendar.getInstance();
+ cal.setTime(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(v));
+ if (cal.get(java.util.Calendar.DAY_OF_MONTH) != 1) return null;
+ return cal.get(java.util.Calendar.YEAR) * 100 + (cal.get(java.util.Calendar.MONTH) + 1);
+ }
+ } catch (Exception ignore) {
+ return null;
+ }
+ return null;
}
/** 鍙拌处椤靛崟鍏冩牸鍙栨暟锛堟暟瀛� / 鏁板瓧鏂囨湰 / 鍏紡缂撳瓨锛� */
@@ -5781,6 +5838,8 @@
String curCity = null;
Set<Long> used = new HashSet<>();
int filled = 0, kept = 0, dup = 0;
+ List<String> skipped = new ArrayList<>();
+ Map<String, Integer> skippedByCity = new LinkedHashMap<>();
for (int r = 8; r <= sheet.getLastRowNum(); r++) {
Row row = sheet.getRow(r);
if (row == null) continue;
@@ -5792,11 +5851,16 @@
if (!a.matches("\\d+(\\.\\d+)?")) continue;
if (b.isEmpty() || curCity == null) continue;
InvestmentProject p = matchInvest(projects, b, curCity, "瀹㈣繍绔欏満", used);
+ p = preferMonthlyCandidate(projects, p, mByProject, "瀹㈣繍绔欏満", used);
InvestmentMonthly m = p == null ? null : mByProject.get(p.getId());
if (p == null || m == null) {
kept++;
// 鏈夊簱鍐呴」鐩絾褰撴湀鏃犳暟鎹� 鈫� 璁颁负寰呮牳瀵癸紱鏃犲尮閰嶉」鐩� 鈫� 缁撹浆涓婃湀
if (p != null) dup++;
+ // 2026-09-22锛氫笉鍐嶉潤榛樼粨杞笂鏈堬紝鏈鐩栫殑琛屽繀椤荤暀鐥曪紙琛屽彿+甯傚窞+椤圭洰鍚�+鍘熷洜锛�
+ skipped.add("绗�" + (r + 1) + "琛� " + curCity + " " + b
+ + (p == null ? " 鈫� 搴撳唴鏃犲尮閰嶉」鐩�" : " 鈫� 搴撳唴鏃� " + period + " 鏈堝害鏁版嵁"));
+ skippedByCity.merge(curCity, 1, Integer::sum);
continue;
}
used.add(p.getId());
@@ -5826,6 +5890,7 @@
}
log.info("瀹㈣繍绔欐姇璧勬槑缁嗚〃 {}锛氬啓鍏� {} 琛岋紝缁撹浆姣嶇増鍘熷�� {} 琛岋紙鍏朵腑搴撳唴鏈夐」鐩絾褰撴湀鏃犳暟鎹� {} 琛岋級",
period, filled, kept, dup);
+ logSkippedRows("瀹㈣繍绔欐姇璧勬槑缁嗚〃", period, skipped, skippedByCity);
return toBytes(wb);
}
}
@@ -5866,6 +5931,8 @@
Map<String, double[]> cityStats = new LinkedHashMap<>(); // 鍏ㄥ悕 -> {鎬绘暟, 绱, 瑙勫垝鍐呮暟, 瑙勫垝鍐呯疮璁�, 瑙勫垝澶栨暟, 瑙勫垝澶栫疮璁
Set<Long> used = new HashSet<>();
int filled = 0, kept = 0;
+ List<String> skipped = new ArrayList<>();
+ Map<String, Integer> skippedByCity = new LinkedHashMap<>();
for (int i = 0; i < cityRows.size(); i++) {
int cr = cityRows.get(i);
String cityLabel = nvl(cellText(sheet.getRow(cr).getCell(0)));
@@ -5888,8 +5955,16 @@
if (!a.matches("\\d+(\\.\\d+)?")) continue;
if (b.isEmpty()) continue;
InvestmentProject p = matchInvest(projects, b, city, "鐗╂祦鍥尯", used);
+ p = preferMonthlyCandidate(projects, p, mByProject, "鐗╂祦鍥尯", used);
InvestmentMonthly m = p == null ? null : mByProject.get(p.getId());
- if (p == null || m == null) { kept++; continue; }
+ if (p == null || m == null) {
+ kept++;
+ // 2026-09-22锛氫笉鍐嶉潤榛樼粨杞笂鏈堬紝鏈鐩栫殑琛屽繀椤荤暀鐥�
+ skipped.add("绗�" + (r + 1) + "琛� " + city + " " + b
+ + (p == null ? " 鈫� 搴撳唴鏃犲尮閰嶉」鐩�" : " 鈫� 搴撳唴鏃� " + period + " 鏈堝害鏁版嵁"));
+ skippedByCity.merge(city, 1, Integer::sum);
+ continue;
+ }
used.add(p.getId());
// 鍙e緞鍚屽杩愮珯鏄庣粏琛細鍙鐩� H 鑷紑濮嬪缓璁剧疮璁� / J 鑷勾鍒濈疮璁� / K 鏈湀瀹屾垚 / M 褰㈣薄杩涘害
if (m.getStartCum() != null) putNum(row, 7, m.getStartCum());
@@ -6020,6 +6095,7 @@
log.warn("鐗╂祦绔欏満鎶曡祫鏄庣粏鍏紡姹傚�煎け璐�: {}", e.getMessage());
}
log.info("鐗╂祦绔欏満鎶曡祫鏄庣粏 {}锛氬啓鍏� {} 琛岋紝缁撹浆姣嶇増鍘熷�� {} 琛�", period, filled, kept);
+ logSkippedRows("鐗╂祦绔欏満鎶曡祫鏄庣粏", period, skipped, skippedByCity);
return toBytesHssf(wb);
}
@@ -6314,6 +6390,40 @@
return full != null && RegionUtil.cityList().contains(full);
}
+ /**
+ * 鍚屽悕锛堝綊涓�鍖栧悗涓�鑷达級澶氭。鏃讹紝浼樺厛閫夈�屽綋鏈堟湁鏁版嵁銆嶇殑閭d竴妗c��
+ * 鑳屾櫙锛�2026-09-22锛夛細鍗佸牥銆屽揩閫掔墿娴佷骇涓氬洯浜屾湡銆嶅湪搴撳唴鏈変袱妗� id=154锛堢宸� 2026锛屾湀搴﹀彧鍒� 7 鏈堬級涓�
+ * id=181锛堢宸� 2029锛屾湁 8 鏈堬級锛屾ā鏉胯鍚嶅墠缂�涓� 154 涓�鑷� 鈫� 瀵煎嚭鍙栧埌 154 鐨� 7 鏈堝�笺��
+ */
+ private InvestmentProject preferMonthlyCandidate(List<InvestmentProject> pool, InvestmentProject p,
+ Map<Long, InvestmentMonthly> mByProject,
+ String category, Set<Long> excludeIds) {
+ if (p == null || mByProject.containsKey(p.getId())) return p;
+ String norm = normInvestName(p.getProjectName());
+ if (norm.isEmpty()) return p;
+ InvestmentProject better = null;
+ for (InvestmentProject c : pool) {
+ if (c == null || c.getId().equals(p.getId())) continue;
+ if (excludeIds != null && excludeIds.contains(c.getId())) continue;
+ if (category != null && !category.equals(c.getCategory())) continue;
+ if (!mByProject.containsKey(c.getId())) continue;
+ if (!norm.equals(normInvestName(c.getProjectName()))) continue;
+ if (better == null || c.getId() > better.getId()) better = c;
+ }
+ return better != null ? better : p;
+ }
+
+ /** 鏈寜褰撴湀鏁版嵁瑕嗙洊鐨勮蹇呴』鐣欑棔锛氶�愯鍒楀嚭琛屽彿+甯傚窞+椤圭洰鍚嶏紝閬垮厤銆岄潤榛樼粨杞笂鏈熷�笺�嶅啀娆″彂鐢� */
+ private void logSkippedRows(String reportName, String period, List<String> skipped, Map<String, Integer> byCity) {
+ if (skipped == null || skipped.isEmpty()) return;
+ log.warn("{} {}锛歿} 琛屾湭鎸夊綋鏈堟暟鎹鐩栵紙缁撹浆姣嶇増鍘熷�硷級锛岄渶浜哄伐鏍稿婧愭枃浠�/搴撳唴鏁版嵁锛�",
+ reportName, period, skipped.size());
+ int limit = Math.min(skipped.size(), 50);
+ for (int i = 0; i < limit; i++) log.warn(" [鏈鐩朷 {}", skipped.get(i));
+ if (skipped.size() > limit) log.warn(" 鈥﹀彟鏈� {} 琛屾湭閫愯鍒楀嚭", skipped.size() - limit);
+ if (byCity != null && !byCity.isEmpty()) log.warn(" 鏈鐩栬鎸夊競宸炵粺璁★細{}", byCity);
+ }
+
/** 鍦ㄥ�欓�夐」鐩睜涓寜鍚嶇О鍖归厤 DB 椤圭洰锛堝彲閫� 甯傚窞/绫诲埆 杩囨护 + 鍘垮尯鍓嶇紑娑堟锛夛紝鏈懡涓繑鍥� null */
private InvestmentProject matchInvest(List<InvestmentProject> pool, String name, String cityFull, String category) {
return matchInvest(pool, name, cityFull, category, null);
@@ -6362,7 +6472,8 @@
if (name == null) return "";
String s = name.trim();
s = s.replaceAll("[锛�(]", "").replaceAll("[锛�)]", "");
- s = s.replaceAll("[路鈥⑩�旓紞_\\-]", "");
+ // 2026-09-22锛氳ˉ鍏呭崐/鍏ㄨ鍙ョ偣銆侀】鍙枫�佸垎鍙风瓑锛堝簱鍐呫�屼腑鍥戒緵閿�.鍏畨鍟嗚锤鐗╂祦鍥�嶅洜鍗婅鍙ョ偣鍖归厤涓嶄笂妯℃澘琛岋級
+ s = s.replaceAll("[路鈥⑩�旓紞_\\-锛�.銆傘�侊紝,;锛�:锛歖", "");
s = s.replaceAll("[鈪犫叀鈪⑩叄鈪も叆鈪︹収鈪ㄢ叐鈪扳叡鈪测叧鈪粹叺鈪垛叿鈪糕吂]", "I");
s = s.replaceAll("^(婀栧寳鐪亅姝︽眽甯倈榛勭煶甯倈鍗佸牥甯倈瀹滄槍甯倈瑗勯槼甯倈閯傚窞甯倈鑽嗛棬甯倈瀛濇劅甯倈鑽嗗窞甯倈榛勫唸甯倈鍜稿畞甯倈闅忓窞甯倈鎭╂柦宸瀨浠欐甯倈娼滄睙甯倈澶╅棬甯倈绁炲啘鏋舵灄鍖�)", "");
s = s.replaceAll("^(?:[\\u4e00-\\u9fa5]{2,4}(?:鍘縷甯倈鍖�))", "");
--
Gitblit v1.9.1