From 595b31273d583fbe367b3bfbebb6fc02e318abc0 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期二, 22 九月 2026 16:51:25 +0800
Subject: [PATCH] fix(投资): 明细表取数三处静默缺陷 + 导入两处丢数/选错页签缺陷
---
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java | 142 +++++++++++++++++++++++++++++++++++++----------
1 files changed, 111 insertions(+), 31 deletions(-)
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
index c694e75..da66293 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -1808,6 +1808,35 @@
}
}
+ /** 鎸夎〃澶村叧閿瓧瀹氫綅鍒楀彿锛氫粠绗� 1 鍒楀悜鍙虫壂锛屽懡涓换涓�鍏抽敭瀛楀嵆杩斿洖璇ュ垪锛涙湭鍛戒腑杩斿洖 -1 */
+ private int findColByKeywords(Row header, String... keywords) {
+ if (header == null) return -1;
+ for (int c = 0; c <= header.getLastCellNum(); c++) {
+ Cell cell = header.getCell(c);
+ if (cell == null) continue;
+ String h = FORMATTER.formatCellValue(cell).trim();
+ if (h.isEmpty()) continue;
+ for (String k : keywords) {
+ if (h.contains(k)) return c;
+ }
+ }
+ return -1;
+ }
+
+ /** 琛ㄥご琛屾枃鏈紙鎶ラ敊鎻愮ず鐢級锛屾渶澶氬彇 12 鍒� */
+ private String headerText(Row header) {
+ if (header == null) return "绌�";
+ StringBuilder sb = new StringBuilder();
+ for (int c = 0; c < Math.min(header.getLastCellNum(), 12); c++) {
+ Cell cell = header.getCell(c);
+ String h = cell == null ? "" : FORMATTER.formatCellValue(cell).trim();
+ if (h.isEmpty()) continue;
+ if (sb.length() > 0) sb.append(" | ");
+ sb.append(h);
+ }
+ return sb.length() == 0 ? "绌�" : sb.toString();
+ }
+
/** 鎸夎〃澶村悕绉板缓绔嬪垪鍙锋槧灏勶紝鍏煎鏂版棫妯℃澘鍒椾綅宸紓 */
private Map<String, Integer> buildHeaderMap(Row header) {
Map<String, Integer> colMap = new HashMap<>();
@@ -2413,6 +2442,41 @@
|| normDash.contains(period) || normDash.contains(period.replace("-0", "-"));
}
+ /**
+ * 鎶ヨ〃鏈熷崟鍏冩牸鍛戒腑锛氭壂鎻� sheet 鍓� 8 琛岋紝鎵惧舰濡� 2026.08 / 2026骞�8鏈� / 2026-08-24 鐨勬姤琛ㄦ湡鏂囧瓧鎴栨棩鏈熷崟鍏冩牸銆�
+ * 鑳屾櫙锛�2026-09-22锛夛細娼滄睙鍗曡〃鍚� 20 涓巻鍙� sheet锛堟綔姹燂紙1鏈堬級鈥︽綔姹燂紙8鏈堬級鈥︼級锛屾棫閫昏緫鍙寜銆�8鏈堛�嶅尮閰� sheet 鍚嶏紝
+ * 浼氭妸 2018 骞寸殑銆屾綔姹燂紙8鏈堬級銆嶅綋鎴� 2026-08锛屽鍏ユ垚 2018 骞存暟鎹紱褰撴湡 sheet 鍚嶆槸銆屾綔姹燂紙2022.3锛夈�嶏紝
+ * 鍙兘闈犺〃鍐呮姤琛ㄦ湡锛�2026.08.24锛夎瘑鍒��
+ */
+ private boolean investSheetPeriodCellHit(Sheet sh, String period) {
+ if (sh == null || period == null || !period.matches("\\d{4}-\\d{2}")) return false;
+ String year = period.substring(0, 4);
+ int month = Integer.parseInt(period.substring(5, 7));
+ int last = Math.min(sh.getLastRowNum(), 7);
+ for (int r = 0; r <= last; r++) {
+ Row row = sh.getRow(r);
+ if (row == null) continue;
+ int lastCell = Math.max(1, row.getLastCellNum());
+ for (int c = 0; c < Math.min(lastCell, 12); c++) {
+ Cell cell = row.getCell(c);
+ if (cell == null) continue;
+ if (cell.getCellType() == CellType.NUMERIC && DateUtil.isCellDateFormatted(cell)) {
+ java.time.LocalDate d = cell.getLocalDateTimeCellValue().toLocalDate();
+ if (d.getYear() == Integer.parseInt(year) && d.getMonthValue() == month) return true;
+ continue;
+ }
+ String v = cellStr(row, c);
+ if (v == null) continue;
+ String t = v.trim().replace(" ", "");
+ if (t.isEmpty() || t.length() > 30) continue;
+ java.util.regex.Matcher mm = java.util.regex.Pattern
+ .compile("(\\d{4})\\s*[骞�.\\-/]\\s*(\\d{1,2})").matcher(t);
+ if (mm.find() && year.equals(mm.group(1)) && month == Integer.parseInt(mm.group(2))) return true;
+ }
+ }
+ return false;
+ }
+
/** 瑙f瀽鍗曚釜甯傚窞鎶ヨ〃锛氶�� sheet锛堟姤琛ㄦ湡鍚嶄紭鍏� + 鏁版嵁琛屾暟锛夛紝鎸夊垪鍚嶆槧灏勬彁鍙栭」鐩 */
private void parseInvestCityWorkbook(Workbook wb, String fileName, String category, String period,
Set<String> fiveYearNames, List<InvestCityRow> rows, Map<String, Object> fr) {
@@ -2424,7 +2488,10 @@
Map<String, Integer> col = findInvestHeader(sh);
if (col == null) continue;
int cnt = countInvestRows(sh, col);
- int score = cnt + (cnt > 0 && investSheetMatchesPeriod(sh, period) ? 1000000 : 0);
+ // 2026-09-22锛氳〃鍐呮姤琛ㄦ湡锛堝崟鍏冩牸锛夊懡涓潈閲嶆渶楂樷�斺�斿巻鍙插悓鏈� sheet锛堝娼滄睙锛�8鏈堬級锛変笉鑳界洊杩囧綋鏈� sheet
+ boolean cellHit = cnt > 0 && investSheetPeriodCellHit(sh, period);
+ int score = cnt + (cnt > 0 && investSheetMatchesPeriod(sh, period) ? 1000000 : 0)
+ + (cellHit ? 2000000 : 0);
if (cnt > 0 && investSheetMatchesPeriod(sh, period)) {
// 褰撴湡鐪熷疄鎶ヨ〃 sheet 鍚嶉�氬父甯﹀勾浠斤紙濡� 2026.8/2026骞�8鏈堬級锛屽巻鍙瞫heet澶氫负绾湀浠藉悕锛�8鏈堬級锛氬甫骞翠唤鐨勪紭鍏�
String norm = sh.getSheetName() == null ? "" : sh.getSheetName().replace(" ", "");
@@ -2589,25 +2656,28 @@
/** 鍗曚釜琛ㄥご鍗曞厓鏍� -> 瀛楁閿紙null 琛ㄧず涓嶆槸琛ㄥご瀛楁锛夛紱渚涜〃澶磋鍒ゅ畾涓庡垪鏄犲皠鍏辩敤 */
private String investHeaderKey(String v) {
if (v == null) return null;
- String flat = v.replace(" ", "");
- if (v.contains("椤圭洰鍚嶇О")) return "name";
+ // 2026-09-22锛氳〃澶村崟鍏冩牸甯稿甫鎹㈣/鍏ㄨ绌烘牸锛堝澶╅棬銆岃嚜寮�濮嬪缓\n璁剧疮璁″畬\n鎴愭姇璧刓n(涓囧厓)銆嶏級锛�
+ // 缁熶竴鍘绘帀鍏ㄩ儴绌虹櫧鍚庡啀鍒ゅ畾鍏抽敭璇嶏紱鍚﹀垯 H(鑷紑濮嬪缓璁剧疮璁�)/J(鑷勾鍒濈疮璁�)/K(鏈湀瀹屾垚) 浼氬尮閰嶅け璐ワ紝
+ // 鍒楁槧灏勮惤鍒� -1 鈫� 涓変釜鏁板�艰鍐欐垚 0锛堝ぉ闂� 2026-08 灏辨槸杩欐牱涓㈢殑 16677.7/16677.7/500锛夈��
+ String flat = v.replaceAll("[\\s\\u3000]+", "");
+ if (flat.contains("椤圭洰鍚嶇О")) return "name";
// 銆屽幙锛堝競銆佸尯锛夈�嶇殑鍚勭鍐欐硶锛氬崐/鍏ㄨ鎷彿銆侀】鍙�/閫楀彿銆佹湁鏃犳嫭鍙凤紝缁熶竴褰掍竴鍖栧悗鍐嶅垽瀹�
String flatCounty = flat.replace("锛�", "(").replace("锛�", ")").replace("銆�", "").replace("锛�", "").replace(",", "");
if (flatCounty.contains("鍘�(甯傚尯)") || flatCounty.contains("鍘垮競鍖�") || flatCounty.contains("鍖哄幙")) return "county";
- if (v.contains("鎶曡祫寤鸿") || v.contains("寤鸿鍗曚綅") || v.contains("椤圭洰涓氫富")) return "builder";
- if (v.contains("寤鸿鎬ц川")) return "nature";
- if (v.contains("寮�宸�")) return "start";
- if (v.contains("绔e伐") || v.contains("寤烘垚")) return "end";
- if ((v.contains("璁″垝鎬绘姇璧�") || v.contains("鎬绘姇璧�")) && !v.contains("绱")) return "total";
- if (v.contains("鑷紑濮嬪缓璁�")) return "startcum";
- if (v.contains("鏈勾璁″垝")) return "yearplan";
- if (v.contains("鑷勾鍒濈疮璁�")) return "yearcum";
- if (v.contains("鏈湀瀹屾垚")) return "monthdone";
- if (v.contains("寤鸿闃舵")) return "stage";
- if (v.contains("褰㈣薄杩涘害") || v.contains("寤鸿杩涘睍")) return "desc";
- if (v.contains("宸ュ彲") && !v.contains("椤圭洰鍚嶇О")) return "gk";
- if (v.contains("鍒濊") && !v.contains("椤圭洰鍚嶇О")) return "cs";
- if (v.contains("寤虹瓚闈㈢Н") && !v.contains("鏂板")) return "area";
+ if (flat.contains("鎶曡祫寤鸿") || flat.contains("寤鸿鍗曚綅") || flat.contains("椤圭洰涓氫富")) return "builder";
+ if (flat.contains("寤鸿鎬ц川")) return "nature";
+ if (flat.contains("寮�宸�")) return "start";
+ if (flat.contains("绔e伐") || flat.contains("寤烘垚")) return "end";
+ if ((flat.contains("璁″垝鎬绘姇璧�") || flat.contains("鎬绘姇璧�")) && !flat.contains("绱")) return "total";
+ if (flat.contains("鑷紑濮嬪缓璁�")) return "startcum";
+ if (flat.contains("鏈勾璁″垝")) return "yearplan";
+ if (flat.contains("鑷勾鍒濈疮璁�")) return "yearcum";
+ if (flat.contains("鏈湀瀹屾垚")) return "monthdone";
+ if (flat.contains("寤鸿闃舵")) return "stage";
+ if (flat.contains("褰㈣薄杩涘害") || flat.contains("寤鸿杩涘睍")) return "desc";
+ if (flat.contains("宸ュ彲") && !flat.contains("椤圭洰鍚嶇О")) return "gk";
+ if (flat.contains("鍒濊") && !flat.contains("椤圭洰鍚嶇О")) return "cs";
+ if (flat.contains("寤虹瓚闈㈢Н") && !flat.contains("鏂板")) return "area";
return null;
}
@@ -2931,32 +3001,42 @@
this.monthly = monthly;
}
}
- /** 鎶曡祫绯荤粺瀵煎嚭瀵煎叆锛堝鏍告瘮瀵瑰熀鍑嗭級锛屽浐瀹�8鍒楋細琛屽彿/鍗曚綅/鏃舵湡/璁″垝鎬绘姇璧�/鑷紑濮嬬疮璁�/鏈勾璁″垝/鑷勾鍒濈疮璁�/褰撴湀瀹屾垚 */
- private static final int[] INVEST_SYSTEM_HEADER_COLS = {0, 1, 2, 3, 4, 5, 6, 7};
- private static final String[] INVEST_SYSTEM_HEADER_KEYWORDS =
- {"琛屽彿", "鍗曚綅", "鏃舵湡", "璁″垝鎬绘姇璧�", "鑷紑濮嬪缓璁�", "鏈勾璁″垝鎶曡祫", "鑷勾鍒�", "褰撴湀瀹屾垚鎶曡祫"};
-
+ /** 鎶曡祫绯荤粺瀵煎嚭瀵煎叆锛堝鏍告瘮瀵瑰熀鍑嗭級銆�
+ * 鍒椾綅**鎸夎〃澶村叧閿瓧瀹氫綅**锛屽吋瀹逛袱绉嶆ā鏉匡細
+ * - 鑰佹ā鏉裤�婃ā鏉縚鏌ヨ缁撴灉(鎶曡祫绯荤粺-瀹㈣繍+鐗╂祦 2026.7).xls銆嬶細琛屽彿/鍗曚綅/鏃舵湡/璁″垝鎬绘姇璧�/鑷紑濮嬪缓璁剧疮璁�/鏈勾璁″垝鎶曡祫/鑷勾鍒濈疮璁�/褰撴湀瀹屾垚鎶曡祫
+ * - 鏂版ā鏉裤��2026骞碭鏈堟姇璧勭郴缁熼」鐩槑缁�.xls銆嬶紙鐢ㄦ埛 2026-09-21 鏇存崲锛夛細琛屽彿/鎶曡祫椤圭洰/鏃舵湡/椤圭洰鎵�澶勯樁娈�/璁″垝鎬绘姇璧�/鏈勾璁″垝鎶曡祫/鑷紑濮嬪缓璁捐嚦鏈勾锛堟湀锛夊簳-绱瀹屾垚鎶曡祫/褰撴湀瀹屾垚鎶曡祫
+ * 鏂版ā鏉�**娌℃湁銆岃嚜骞村垵绱銆嶅垪** 鈫� year_cum 鐣欑┖锛堝鏍告椂鎸夈�屽熀鍑嗙己澶便�嶈烦杩囷紝涓嶅啀褰撴垚 0 鍙備笌姣斿锛夈�� */
public int importInvestmentSystem(MultipartFile file, String period) throws Exception {
List<InvestmentSystem> list = new ArrayList<>();
int failRows = 0;
try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
Sheet sheet = wb.getSheetAt(0);
- requireHeaderKeyword(sheet, "鎶曡祫绯荤粺瀵煎嚭", "椤圭洰鍚嶇О", "璁″垝鎬绘姇璧�", "鍗曚綅");
- requireHeaderLayout(sheet, "鎶曡祫绯荤粺瀵煎嚭", "妯℃澘_鏌ヨ缁撴灉(鎶曡祫绯荤粺-瀹㈣繍+鐗╂祦 2026.7).xls",
- INVEST_SYSTEM_HEADER_COLS, INVEST_SYSTEM_HEADER_KEYWORDS);
+ requireHeaderKeyword(sheet, "鎶曡祫绯荤粺瀵煎嚭", "鎶曡祫椤圭洰", "椤圭洰鍚嶇О", "鍗曚綅", "璁″垝鎬绘姇璧�");
+ Row header = sheet.getRow(0);
+ int cName = findColByKeywords(header, "鎶曡祫椤圭洰", "椤圭洰鍚嶇О", "鍗曚綅");
+ int cTotal = findColByKeywords(header, "璁″垝鎬绘姇璧�");
+ int cYearPlan = findColByKeywords(header, "鏈勾璁″垝鎶曡祫");
+ int cStartCum = findColByKeywords(header, "鑷紑濮嬪缓璁�");
+ int cYearCum = findColByKeywords(header, "鑷勾鍒�");
+ int cMonthDone = findColByKeywords(header, "褰撴湀瀹屾垚鎶曡祫");
+ if (cName < 0 || cTotal < 0 || cYearPlan < 0 || cStartCum < 0 || cMonthDone < 0) {
+ throw new RuntimeException("鎵�閫夋暟鎹被鍨嬨�愭姇璧勭郴缁熷鍑恒�戣〃澶村垪涓嶅畬鏁达細闇�瑕併�屾姇璧勯」鐩�(鎴栧崟浣�)銆佽鍒掓�绘姇璧勩�佹湰骞磋鍒掓姇璧勩��"
+ + "鑷紑濮嬪缓璁锯�︾疮璁″畬鎴愭姇璧勩�佸綋鏈堝畬鎴愭姇璧勩�嶇瓑鍒楋紝瀹為檯琛ㄥご涓恒��" + headerText(header)
+ + "銆嶃�傝浣跨敤绯荤粺妯℃澘銆�2026骞碭鏈堟姇璧勭郴缁熼」鐩槑缁嗐�嬫垨銆婃ā鏉縚鏌ヨ缁撴灉(鎶曡祫绯荤粺-瀹㈣繍+鐗╂祦)銆嬫暣鐞嗗悗鍐嶅鍏�");
+ }
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
Row row = sheet.getRow(r);
if (row == null) continue;
- String name = getString(row, 1);
+ String name = getString(row, cName);
if (name == null || name.trim().isEmpty()) continue;
InvestmentSystem sys = new InvestmentSystem();
sys.setReportPeriod(period);
sys.setProjectName(name.trim());
- sys.setTotalInvestment(getDecimal(row, 3));
- sys.setStartCum(getDecimal(row, 4));
- sys.setYearPlan(getDecimal(row, 5));
- sys.setYearCum(getDecimal(row, 6));
- sys.setMonthDone(getDecimal(row, 7));
+ sys.setTotalInvestment(getDecimal(row, cTotal));
+ sys.setStartCum(getDecimal(row, cStartCum));
+ sys.setYearPlan(getDecimal(row, cYearPlan));
+ sys.setYearCum(cYearCum < 0 ? null : getDecimal(row, cYearCum));
+ sys.setMonthDone(getDecimal(row, cMonthDone));
list.add(sys);
}
} catch (Exception e) {
--
Gitblit v1.9.1