| HANDOFF.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/功能测试报告/功能测试报告_投资明细表取数修复_2026-09-22.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-22.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
HANDOFF.md
@@ -11,6 +11,13 @@ - **仿¥å·²å®æï¼è¿ç«¯æäº¤ï¼**ï¼æ°æ®æ¥çè¡¥é½ç½çº¦è½¦/个ä½å®¢è¿ãæå¸å·æ±æ»ä¸å¯¼åº Excelãæ±æ»å¤§è¡¨è¿åº¦å¼¹çªä¸ç»æè½çç¼åã - **æªå®æéç¹ä¸å**ï¼P0-2ãäº¿å æèµé¡¹ç®ãæ Q7 追åãP0-3 导åºååºæ°ä½æ£ãP0-4 2026-09 æ¯çï¼å ¶ä½è§ `docs/äº¤æ¥ææ¡£_2026-09-21.md` 第 4 ç« ã ### è¡¥å ï¼2026-09-22 ä¸åï¼æèµåæ°ä¿®å¤ç¬¬ä¸è½®ï¼ - **已修ï¼ä»£ç + é导 + åå½ï¼**ï¼â 导åºå»æ ç¹å½ä¸åå¹é ï¼èå·ï¼ï¼â¡ åååæ¡£ä¼å åå½æææ°æ®çæ¡£ï¼åå °å¿«é产ä¸åäºæï¼ï¼â¢ æªè¦çè¡éè¡ WARN ççï¼â£ å¯¼å ¥è¡¨å¤´å»æ¢è¡ï¼å¤©é¨ H/J/K ä¸å丢ï¼ï¼â¤ å¯¼å ¥æè¡¨å æ¥è¡¨æé sheetï¼**æ½æ±ä¸åæ 2018 å¹´æ°æ®å½ 2026-08**ï¼ã - **ç»æ**ï¼2026-08 ç©æµ/å®¢è¿æç»éæ ¼å·®å¼ **156 â 129**ï¼æ æ°å¢å·®å¼ï¼æªè¦çæ¸ åå·²è½èªå¨ååºï¼ç©æµæ¦æ± 6 è¡ï¼å®¢è¿é»ç³1/é»å9/æ©æ½1/仿¡1ï¼ã - **éçï¼ä¸ä¸è½®ï¼**ï¼L/D/E/F è¦çå£å¾ï¼éãå»ºè®¾é¶æ®µå½ä¸è¡¨ãï¼ãæ¦æ±ç©æµä¸é»åå®¢è¿ 8 ææºæ°æ®ãæ½æ± 2026-06/07 åå²éå¼éå¯¼ãæªè¦çæ¸ ååºæä»¶/é¡µé¢æç¤ºï¼P1-9ï¼ã - **æ¥å**ï¼`docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æèµæç»è¡¨åæ°ä¿®å¤_2026-09-22.md`ã ### è¡¥å ï¼2026-09-22 ä¸åï¼æèµæç»è¡¨æ¯å¯¹ï¼ - **已宿**ï¼è½¯ä»¶ã客è¿ç«æèµæç»è¡¨ããç©æµç«åºæèµæç»ãä¸äººå·¥çéæ ¼æ¯å¯¹ï¼156 æ ¼å·®å¼ï¼ï¼æ¥å `docs/åè½æµè¯æ¥å/æ°æ®æ¯å¯¹æ¥å_æèµæç»è¡¨è½¯ä»¶çæä¸äººå·¥ç_2026-09-22.md`ã docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Ͷ×ÊÃ÷ϸ±íÈ¡ÊýÐÞ¸´_2026-09-22.md
New file @@ -0,0 +1,91 @@ # åè½æµè¯æ¥å â æèµæç»è¡¨åæ°ä¿®å¤ï¼è½¯ä»¶çæ vs 人工ç 差弿¶æï¼ > æµè¯æ¥æï¼2026-09-22 > 被æµå¯¹è±¡ï¼æ¥è¡¨çæ â æèµã客è¿ç«æèµæç»è¡¨ããç©æµç«åºæèµæç»ãå¯¼åº + æèµææ¥ï¼å¸å·å表ï¼å¯¼å ¥ > èæ¯ï¼ãæ°æ®æ¯å¯¹æ¥å_æèµæç»è¡¨è½¯ä»¶çæä¸äººå·¥ç_2026-09-22.mdãå®ä½åº 156 æ ¼å·®å¼ä¸ 3 ç±»"ä¼éé»åºæ°"çåæ°ç¼ºé·ï¼æ¬æ¥å为第ä¸è½®ä¿®å¤ä¸åå½éªè¯ã ## ä¸ãåè½è¯´æï¼æ¬æ¬¡æ¹äºä»ä¹ï¼ ### 1. 导åºï¼`traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java` | # | æ¹å¨ | 说æ | | --- | --- | --- | | 1-1 | `normInvestName()` å½ä¸åè¡¥æ ç¹ | å¢å å/å ¨è§å¥ç¹ãé¡¿å·ãéå·ãåå·ãåå·çï¼ååªå» `·â¢âï¼_-`ï¼ãåºå 项ç®åãä¸å½ä¾é**.**å ¬å®åè´¸ç©æµåã䏿ç»è¡¨è¡åãä¸å½ä¾éå ¬å®åè´¸ç©æµåï¼å ¬å®å¿åéééé ä¸å¿ï¼ãå½ä¸åååç¼ä¸è´ â å¯å¹é | | 1-2 | æ°å¢ `preferMonthlyCandidate()` | å¹é å°çæ¡£å¨**å½ææ æ°æ®**æ¶ï¼æ¹éãå½ä¸åååä¸å½æææ°æ®ãçæ¡£ï¼å id æå¤§è ï¼ãä¿®å¤åå °ãå¿«éç©æµäº§ä¸åäºæãåå°æ§æ¡£ id=154ï¼æåº¦åªå° 7 æï¼çé®é¢ | | 1-3 | æ°å¢ `logSkippedRows()` + 客è¿/ç©æµå¯¼åºçç | æªæå½ææ°æ®è¦ççè¡**éè¡ WARN**ï¼`[æªè¦ç] 第Nè¡ å¸å· 项ç®å â åå `ï¼å¹¶ç»åºæå¸å·ç»è®¡ãå½»åºæ¶é¤"éé»ç»è½¬ä¸æå¼" | ### 2. å¯¼å ¥ï¼`traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java` | # | æ¹å¨ | 说æ | | --- | --- | --- | | 2-1 | `investHeaderKey()` å å»ç©ºç½åå¤å® | 表头åå æ ¼å¸¸å«æ¢è¡/å ¨è§ç©ºæ ¼ï¼å¤©é¨ãèªå¼å§å»º\n设累计å®\nææèµ\n(ä¸å )ãï¼ï¼åé»è¾ `v.contains("èªå¼å§å»ºè®¾")` å¹é ä¸ä¸ â H/J/K ä¸åæ å°è½å° -1 è¢«åæ 0ãæ¹ä¸º `replaceAll("[\\s\\u3000]+","")` ååå¤å® | | 2-2 | æ°å¢ `investSheetPeriodCellHit()` + è¯åå æ | å¤ sheet å岿件æ sheet åå¹é æä»½ä¼æ 2018 å¹´çãæ½æ±ï¼8æï¼ã彿 2026-08ãæ°å¢"è¡¨å æ¥è¡¨æ"å½ä¸ï¼sheet å 8 è¡ç `2026.08.24` / `2026å¹´8æ` / æ¥æåå æ ¼ï¼ï¼æé 2000000 é«äº sheet åå¹é ï¼1000000ï¼ | ## äºãæµè¯ç¯å¢ - å端ï¼`mvn spring-boot:run`ï¼8090ï¼ï¼éå¯åæ¥å¿åºç° `Started TrafficAuditApplication`ï¼å端 8080 å¨è¿è¡ - æ°æ®åºï¼`localhost:3308/traffic_audit`ï¼æ¬æºå¼ååºï¼ï¼ç»å½ `admin/123456` å JWT - 人工çåºåï¼`D:\05_æ°æ®åç±»\æèµ\8æ\8æå®¢è¿ç«æèµæç»è¡¨.xlsx`ã`8æç©æµç«åºæèµæç».xls` - ä¿®å¤å软件çï¼`D:\æ¡é¢\çææ°æ®\çæ_æéæ¥è¡¨_2026-08 (1)\â¦` - ä¿®å¤å软件çï¼`_tmp/gen_new_0922/â¦`ï¼æ¬æ¬¡éè·å¯¼åºï¼ - æ¯å¯¹èæ¬ï¼`_tmp_diff_invest_0922.py`ï¼ä¿®å¤åï¼ã`_tmp_diff_after_fix_0922.py`ï¼ä¿®å¤åï¼ ## ä¸ãæµè¯ç¨ä¾ä¸ç»æ | # | ç¨ä¾ | è¾å ¥ | 颿 | å®é | ç»è®º | | --- | --- | --- | --- | --- | --- | | 1 | 导åº-项ç®å带æ ç¹ | 2026-08 ç©æµæç»å¯¼åº | 第119/120è¡ãä¸å½ä¾éå ¬å®åè´¸ç©æµåãæåºå 彿åå ¥ | ä¿®å¤åï¼æªè¦çï¼ä¿çåºç¨¿ 7758.5/7758.5/1600.1ï¼ä¿®å¤åï¼åå ¥ **15986/15986/8227.5** 䏿ºè¡¨ä¸è´ï¼æ¥å¿ä¸ååè¯¥è¡ | â | | 2 | 导åº-åååæ¡£ | åä¸ | åãå½æææ°æ®ãçæ¡£ï¼id=181ï¼ | ä¿®å¤åï¼20081/2900/214ã竣工 2026ï¼ä¿®å¤åï¼**20377/3196/296ã竣工 2029**ï¼= åå °æºè¡¨ R71ï¼ | â | | 3 | 导åº-æªè¦çççï¼ç©æµï¼ | åä¸ | æªè¦çè¡ååºè¡å·+å¸å·+项ç®å+åå | æ¥å¿ï¼`ç©æµç«åºæèµæç» 2026-08ï¼åå ¥ 93 è¡ï¼ç»è½¬æ¯çåå¼ 6 è¡` + 6 æ¡ `[æªè¦ç] 第12è¡ æ¦æ±å¸ èªåæºæ §ç©æµå â åºå æ 2026-08 æåº¦æ°æ®`ï¼æå¸å·ç»è®¡ `{æ¦æ±å¸=6}`ï¼ | â | | 4 | 导åº-æªè¦çççï¼å®¢è¿ï¼ | åä¸ | åä¸ | `åå ¥ 37 è¡ï¼ç»è½¬æ¯çåå¼ 12 è¡ï¼å ¶ä¸åºå æé¡¹ç®ä½å½ææ æ°æ® 9 è¡ï¼` + 12 æ¡æç»ï¼é»ç³ 1 / é»å 9 / æ©æ½ 1 / 仿¡ 1ï¼ | â | | 5 | å¯¼å ¥-è¡¨å¤´å«æ¢è¡ï¼å¤©é¨ï¼ | `8æä»½ç©æµåä¸å¿å»ºè®¾é¡¹ç®(天é¨).xlsx`ï¼period=2026-08ï¼type=investmentLogistics | å ¥åº 16677.7 / 16677.7 / 500 | ä¿®å¤ååºå 0/0/0ï¼ä¿®å¤å `investment_monthly` = **16677.7 / 16677.7 / 500**ï¼æ¥å£è¿å success=1 | â | | 6 | å¯¼å ¥-åå²é¡µç¾ï¼æ½æ±ï¼ | `æ½æ±2026.08.xlsx`ï¼å« 20 个åå² sheetï¼ | é彿 sheetï¼è¡¨å æ¥è¡¨æ 2026.08.24ï¼ | ä¿®å¤åï¼å ¥åº **2018 å¹´**ãæ½æ±å¸å ¬è·¯é¡¹ç®ã5173/5173/1440ï¼éï¼ï¼ä¿®å¤åï¼å ¥åºã**ä¸å½è¾è°·å·é¾ä»å¨ç©æµå**ã11947.9/1135/0ï¼= æºè¡¨å½æ sheetï¼ï¼æ§éè¡è¢«åå¸å·åæé´æ¸ ç | â | | 7 | åå½-éæ ¼æ¯å¯¹ | ä¿®å¤åå¯¼åº vs 人工ç | 差弿°ä¸é䏿 æ°å¢å·®å¼ | 156 æ ¼ â **129 æ ¼**ï¼é 27ï¼ï¼å©ä½å·®å¼ä¸ä¿®å¤å鿡坹åºï¼æ æ°å¢ | â | | 8 | è´å-æªå¹é è¡ä¸åéå¼ | æ¦æ± 6 è¡ï¼åºå æ 2026-08 æ°æ®ï¼ | ä¿æåºç¨¿åå¼ä¸å¿ é¡»ææ¥å¿åè¦ | 6 è¡ä¿æåå¼ï¼æ¥å¿éè¡åè¦ï¼ä¸éé»ï¼ | â | ### ä¿®å¤ååé页ç¾å¯¹ç § | æä»¶ / é¡µç¾ | ä¿®å¤å | ä¿®å¤å | 说æ | | --- | --- | --- | --- | | 客è¿-æç» | 12 | 12 | æ¬æ¬¡æªå¨å®¢è¿å¹é é»è¾ï¼å·®å¼å±åæ´/ææ¬å£å¾ï¼ | | 客è¿-æ±æ» | 4 | 4 | åä¸ | | ç©æµ-æ2 | 0 | 0 | â | | ç©æµ-åé¡¹ç®æèµå®ææ åµ | 108 | **91** | èå· â10ãåå ° â5ãå¤©é¨ â2 | | ç©æµ-åå¸å·è§åå å¤é¡¹ç®å®ææ åµ | 15 | **11** | èå·ã天é¨éæç»é¡µå½ä½ | | ç©æµ-å¸å·æ±æ» | 17 | **11** | åä¸ | | **å计** | **156** | **129** | æ¶æ 27 æ ¼ | ## åãå©ä½å·®å¼ï¼129 æ ¼ï¼åç±»ä¸è´£ä»» | ç±»å« | æ ¼æ° | åå | è´£ä»»æ¹ / ä¸ä¸æ¥ | | --- | --- | --- | --- | | æ¦æ±æ´æ®µï¼æç» 24 + å计 3ï¼ | 27 | åºå **æ æ¦æ±ç©æµå½ææ°æ®**ï¼8 ææ¦æ±æ å表ï¼ï¼å¯¼åºåªè½ç»è½¬åºç¨¿ 7 æå¼ | ä¸å¡è¡¥æ¦æ±åè¡¨ï¼ææç¡®"æ¦æ±ç±äººå·¥å¡«"ï¼ç°å·²æåè¦ï¼ | | åå °æ¢çº½ 2 ä¸å å·®å¼ | 3 | 人工çç¨æ§å¼ 11047/589/0ï¼æºè¡¨ä¸åºå æ¯ 11049/591/2 | **软件对**ï¼äººå·¥çéæ´æ°ï¼å·²åå ¥å·®å¼æ¸ åï¼ | | L åï¼å»ºè®¾é¶æ®µï¼æªè¦ç | 3 | å¯¼åºæ 2026-09-18 å£å¾ä¸å Lï¼æ²¿ç¨åºç¨¿ | éãå»ºè®¾é¶æ®µå½ä¸è¡¨ãåæ¾å¼ï¼è§ç¬¬äºèï¼ | | D åï¼å»ºè®¾æ§è´¨ï¼æªè¦ç | 3 | åä¸ï¼I/L/G/D/E/F ä¸åï¼ | åä¸ | | å·¥æ E/F åæ³ï¼æ¥æ vs å¹´ä»½ï¼ | 4 | äººå·¥çæ¯æ¥æåºåå·ï¼è½¯ä»¶å年份/ææ¬ | æ ¼å¼å£å¾ï¼å»ºè®®ä»¥æºè¡¨åæ ·ä¸ºå | | åç»å°è®¡è¡ï¼6 个å¸å·ï¼ | 25 | è½¯ä»¶ææ¸ éæ±åä¸å¡«=å¸å·å计ï¼äººå·¥çç空 | å£å¾å·®å¼ï¼å»ºè®®äººå·¥çè¡¥é½ï¼è½¯ä»¶è§å䏿¦æ± R11/R16 å®å ¨ä¸è´ï¼ | | 0 ä¸ç©ºç½ | 11 | åæ³ä¸å | ç»ä¸è§åï¼æºè¡¨ç©ºâç©ºãæºè¡¨ 0â0 | | 客è¿åæ´ + ææ¬ | 16 | 人工çæååæ´ï¼203/2531/43225.9ï¼ï¼M26/M85 人工ç空ãL91 åºç¨¿æ§å¼ | 人工ç对é½ï¼L91 éå½ä¸è¡¨ | | æªè¦çè¡ï¼æ°æ®ç¼ºå£æ¸ åï¼ | 18 è¡ | ç©æµï¼æ¦æ± 6ï¼å®¢è¿ï¼é»ç³ 1ãé»å 9ãæ©æ½ 1ã仿¡ 1 | è¡¥æºæä»¶/项ç®ä¸»æ¡£åéå¯¼ï¼æ¥å¿å·²éè¡ååºï¼ | ## äºãéçé®é¢ä¸å¤ç½® 1. **ãæ°åç°ï¼å·²ä¿®+éå¯¼ãæ½æ±å¯¼å ¥ééåå²é¡µç¾**ï¼2026-08 æ¾å¯¼å ¥ 2018 å¹´ãæ½æ±å¸å ¬è·¯é¡¹ç®ãçæ°æ®ï¼å·²ä¿®å¤é页ç¾é»è¾å¹¶é导 2026-08ã - **ä»éç**ï¼æ½æ± **2026-06 / 2026-07** 两个æçæåº¦æ°æ®ä»æ¯åå² sheet éå¼ï¼éç¨ 6/7 ææºè¡¨é导ï¼ä¸è¦ç¨ 8 ææä»¶é导ï¼ä¼æ 8 ææ°åæ 7 æï¼ã 2. **ãéå£å¾ææ¿ã"å ¨éè¦ç"æªå®æ½**ï¼ç°è¡å£å¾ï¼2026-09-18 ç¡®è®¤ï¼æ¯åªå H/J/K/Mï¼I/L/G ä¸å¨ãè¥è¦ä¸äººå·¥çå®å ¨ä¸è´ï¼é确认 L/D/E/F/I æ¯å¦ä¹æå½æåï¼ä¸ L éè¦ãæºè¡¨ç¨è¯âè¾åºç¨è¯ãå½ä¸è¡¨ï¼æºè¡¨æ 䏻使½å·¥/竣工æ¶å°¾/æªå¼å·¥/æ¬å¹´æ£å¼æ½å·¥/æåæ½å·¥/åæ çï¼äººå·¥çå å¨å»º/å®å·¥/åæ/æåæ½å·¥ï¼ã 3. **ãæ°æ®ç¼ºå£ãé»åå®¢è¿ 8 ææ æºæä»¶**ï¼9 è¡ï¼ãé»ç³/æ©æ½/仿¡ 3 è¡åºå æ 对åºé¡¹ç®ä¸»æ¡£ãæ¦æ±ç©æµæ å表 ââ 导åºå·²è½èªå¨åè¦ï¼ä½æ°æ®æ¬èº«éè¦ä¸å¡æä¾ã 4. **ã对æ¯å·¥å ·åã** ç®å"æªè¦çè¡"åªè¿å端æ¥å¿ï¼å»ºè®®æ P1-9 约å®ï¼å¨å¯¼åºç»ææçæãæ ¡éªæ¥é_<å¹´æ>.xlsxãæåç«¯å¼¹çªæç¤ºï¼ç¨æ·è¦æ±"å¤±è´¥è¦æ¾ç¤ºè¡å·"ï¼æ¬æ¬¡å·²åå°æ¥å¿ççï¼é¡µé¢æç¤ºå¾ åï¼ã ## å ãç»è®º - æ¬æ¬¡ä¿®å¤åï¼**éæ ¼å·®å¼ç± 156 æ ¼éè³ 129 æ ¼**ï¼ä¸å¤"ä¼å½±åæ°å"çåæ°ç¼ºé·ï¼èå·é¡¹ç®åå¹é 失败ãåå °åååæ¡£åæ§å¼ã天é¨å¯¼å ¥ä¸¢ H/J/Kï¼å ¨é¨éç¯å¹¶éæ¡åæº¯æºæä»¶éªè¯ã - åæ¶ç«¯å°ç«¯æ´é²å¹¶ä¿®å¤äºä¸ä¸ªæ´ä¸¥éçé®é¢ï¼**æ½æ±å¯¼å ¥éå° 2018 å¹´åå²é¡µç¾**ï¼å±"ææ§å¹´ä»½æ°æ®å½å½ææ°æ®å ¥åº"ï¼ï¼æªè¦çè¡ç°å·²å¨æ¥å¿ä¸éè¡ååºï¼è¡å·+å¸å·+项ç®å+åå ï¼ï¼ä¸åéé»ã - å©ä½ 129 æ ¼å·®å¼ä¸ï¼**åªææ¦æ± 27 æ ¼å±"ç¼ºæ°æ®"ãL/D å 6 æ ¼å±"å¾ æ¾å¼å£å¾"**ï¼å ¶ä½ä¸ºå¡«è¡¨ä¹ æ¯ï¼åç»è¡/0 ä¸ç©ºç½/åæ´ï¼ä¸äººå·¥çèªèº«æ§å¼ï¼åå·²å¨ãæ°æ®æ¯å¯¹æ¥åãä¸éæ¡æ 注"以è°ä¸ºå"ã - 建议ä¸ä¸æ¥ï¼â ä¸å¡ç¡®è®¤ L/D/E/F è¦çå£å¾å¹¶åºãå»ºè®¾é¶æ®µå½ä¸è¡¨ãï¼â¡ è¡¥æ¦æ±ç©æµãé»åå®¢è¿æºæ°æ®ï¼â¢ æ P1-9 ææªè¦çæ¸ åè¾åºææ ¡éªæä»¶/é¡µé¢æç¤ºã ## ä¸ãæ¬æ¬¡æ°æ®åæ´è¯´æï¼æªå é¤ä»»ä½é¡¹ç®ä¸»æ¡£ï¼ | 表 | åæ´ | ä¿®å¤å | ä¿®å¤å | | --- | --- | --- | --- | | `investment_monthly`ï¼å¤©é¨å¸ç©æµä¸å¿å»ºè®¾é¡¹ç® 2026-08ï¼ | éå¯¼ä¿®æ£ | start_cum/year_cum/month_done = 0/0/0 | **16677.7 / 16677.7 / 500** | | `investment_monthly`ï¼æ½æ±å¸ 2026-08ï¼ | é导修æ£ï¼æ§éè¡å é¤ãæ°è¡åå ¥ï¼ | æ½æ±å¸å ¬è·¯é¡¹ç® 5173/5173/1440 | **ä¸å½è¾è°·å·é¾ä»å¨ç©æµå 11947.9/1135/0** | - æªå é¤ä»»ä½ `investment_project` 项ç®ä¸»æ¡£ï¼æªæ¹å¨å ¶ä»å¸å·ãå ¶ä»æé´æ°æ®ã - å¤ç°å½ä»¤ï¼`POST /api/import/batch?type=investmentLogistics&period=2026-08`ï¼multipartï¼å段å `files`ï¼+ `GET /api/report/export/investLogisticsDetail?period=2026-08`ï¼åé `Authorization: Bearer <JWT>`ã docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-22.md
@@ -160,3 +160,21 @@ - **å½±åéé¢**ï¼è½¯ä»¶çç©æµãèªå¼å§ç´¯è®¡ããèªå¹´å累计ãåå° **34399.2 ä¸å **ããæ¬æå®æãå° **6291.4 ä¸å **ã - **æ¥å**ï¼`docs/åè½æµè¯æ¥å/æ°æ®æ¯å¯¹æ¥å_æèµæç»è¡¨è½¯ä»¶çæä¸äººå·¥ç_2026-09-22.md`ï¼å« 156 æ ¼å ¨éæ¸ å + éæ¡æ ¸å¯¹ç»è®º + å¤ç½®å»ºè®®ï¼ã - **临æ¶èæ¬ï¼ä¿çï¼**ï¼`_tmp_diff_invest_0922.py`ã`_tmp_dump_invest_full_0922.py`ã`_tmp_diff_invest_annot_0922.py`ã`_tmp_diff_tables_0922.py`ã`_tmp_src_spotcheck_0922.py`ã`_tmp_src_spotcheck2_0922.py`ã`_tmp_db_probe*_0922.py`ã`_tmp_tpl_*_0922.py` åå¯¹åº `_*.txt` è¾åºã ## ä¸ãæèµæç»è¡¨åæ°ä¿®å¤ï¼ç¬¬ä¸è½®ï¼å·²ç¼è¯/éå¯/端å°ç«¯éªè¯ï¼ æç¬¬å èæ¯å¯¹ç»è®ºå¨æä¿®äºä¸å¤"ä¼éé»åºæ°"çåæ°ç¼ºé·ï¼å¹¶é¡ºå¸¦ç«¯å°ç«¯æ´é²+ä¿®å¤äºæ½æ±å¯¼å ¥ééåå²é¡µç¾ã - **导åº**ï¼`ReportExportService.java`ï¼ï¼ 1. `normInvestName()` å½ä¸åè¡¥æ ç¹ï¼å/å ¨è§å¥ç¹ãé¡¿å·ãåå·çï¼â èå·ãä¸å½ä¾é.å ¬å®åè´¸ç©æµåãå¯å¹é ï¼åå ¥åºå 15986/15986/8227.5ï¼ 2. æ°å¢ `preferMonthlyCandidate()`ï¼åå夿¡£ä¼å åãå½æææ°æ®ãçæ¡£ â åå °ãå¿«éç©æµäº§ä¸åäºæãæ¹å id=181ï¼åå ¥ 20377/3196/296ã竣工 2029ï¼ 3. æ°å¢ `logSkippedRows()`ï¼æªè¦çè¡éè¡ WARNï¼`[æªè¦ç] 第Nè¡ å¸å· 项ç®å â åå ` + æå¸å·ç»è®¡ï¼ï¼ä¸åéé»ç»è½¬ä¸æå¼ã - **å¯¼å ¥**ï¼`DataImportService.java`ï¼ï¼ 1. `investHeaderKey()` å å»å ¨é¨ç©ºç½ï¼å«æ¢è¡/å ¨è§ç©ºæ ¼ï¼åå¤å®å ³é®è¯ â å¤©é¨ H/J/K ä¸åæ¢å¤è¯å«ï¼2026-08 å ¥åº 16677.7/16677.7/500ï¼å为 0/0/0ï¼ï¼ 2. æ°å¢ `investSheetPeriodCellHit()` + è¯åå æ 2000000ï¼æè¡¨å æ¥è¡¨æï¼`2026.08.24`ï¼é sheetï¼ä¼å äºãsheet åå«åæãâ æ½æ±ä¸åæ **2018 å¹´**ãæ½æ±ï¼8æï¼ãå½ 2026-08ï¼é导å 2026-08 å ¥åºãä¸å½è¾è°·å·é¾ä»å¨ç©æµåã11947.9/1135/0ã - **éªè¯**ï¼`mvn -o compile` éè¿ï¼åæ§èµ·æ°å端ï¼8090 就绪ï¼ï¼æ¥å£é导 + éè· 2026-08 导åºï¼éæ ¼æ¯å¯¹**156 æ ¼ â 129 æ ¼**ï¼é 27 æ ¼ï¼ç©æµåé¡¹ç® 108â91ãåå¸å· 15â11ãå¸å·æ±æ» 17â11ï¼ï¼æ æ°å¢å·®å¼ã - **æªè¦çæ¸ åï¼æ°å¢è½åï¼æ¥èªæ¥å¿ï¼**ï¼ç©æµ 6 è¡ï¼å ¨é¨æ¦æ±ï¼åºå æ å½ææ°æ®ï¼ï¼å®¢è¿ 12 è¡ï¼é»ç³ 1ã鳿°ç»¼åå®¢è¿æ¢çº½ç«ããé»å 9ãæ©æ½ 1ãå¸ä¸°å¿åªåè¥æ 游客è¿ç«ãã仿¡ 1ã仿¡å¸æ¯å´å®¢è¿ç«ãï¼ã - **æ¥å**ï¼`docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æèµæç»è¡¨åæ°ä¿®å¤_2026-09-22.md`ã - **éçï¼éææ¿/è¡¥æ°ï¼**ï¼â L/D/E/F æ¯å¦æå½æè¦çï¼éãå»ºè®¾é¶æ®µå½ä¸è¡¨ãï¼ï¼â¡ æ¦æ±ç©æµãé»åå®¢è¿ 8 ææºæ°æ®ç¼ºå¤±ï¼â¢ æ½æ± 2026-06/07 æåº¦ä»æ¯åå² sheet éå¼ï¼éç¨ 6/7 ææºè¡¨é导ï¼**ä¸è¦**ç¨ 8 ææä»¶é导ï¼ï¼â£ æªè¦çæ¸ åç®ååªè¿æ¥å¿ï¼å»ºè®®æ P1-9 åºãæ ¡éªæ¥é_<å¹´æ>.xlsxãæé¡µé¢æç¤ºã - **æ°æ®åæ´**ï¼ä» é导修æ£äºå¤©é¨ãæ½æ±ä¸¤å¤ 2026-08 æåº¦å¼ï¼æªå é¤ä»»ä½é¡¹ç®ä¸»æ¡£ãæªå¨å ¶ä»å¸å·/æé´ï¼ä¸´æ¶èæ¬ä¸äº§ç©ä¿çï¼`_tmp_*_0922.*`ã`_tmp/gen_new_0922/`ï¼ã traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -2442,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; } /** è§£æå个å¸å·æ¥è¡¨ï¼é sheetï¼æ¥è¡¨æåä¼å + æ°æ®è¡æ°ï¼ï¼æååæ å°æå项ç®è¡ */ private void parseInvestCityWorkbook(Workbook wb, String fileName, String category, String period, Set<String> fiveYearNames, List<InvestCityRow> rows, Map<String, Object> fr) { @@ -2453,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æï¼ï¼åå²sheetå¤ä¸ºçº¯æä»½åï¼8æï¼ï¼å¸¦å¹´ä»½çä¼å String norm = sh.getSheetName() == null ? "" : sh.getSheetName().replace(" ", ""); @@ -2618,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("竣工") || 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("竣工") || 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; } traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -5781,6 +5781,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 +5794,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 +5833,7 @@ } log.info("客è¿ç«æèµæç»è¡¨ {}ï¼åå ¥ {} è¡ï¼ç»è½¬æ¯çåå¼ {} è¡ï¼å ¶ä¸åºå æé¡¹ç®ä½å½ææ æ°æ® {} è¡ï¼", period, filled, kept, dup); logSkippedRows("客è¿ç«æèµæç»è¡¨", period, skipped, skippedByCity); return toBytes(wb); } } @@ -5866,6 +5874,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 +5898,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()); // å£å¾å客è¿ç«æç»è¡¨ï¼åªè¦ç H èªå¼å§å»ºè®¾ç´¯è®¡ / J èªå¹´å累计 / K æ¬æå®æ / M 形象è¿åº¦ if (m.getStartCum() != null) putNum(row, 7, m.getStartCum()); @@ -6020,6 +6038,7 @@ log.warn("ç©æµç«åºæèµæç»å ¬å¼æ±å¼å¤±è´¥: {}", e.getMessage()); } log.info("ç©æµç«åºæèµæç» {}ï¼åå ¥ {} è¡ï¼ç»è½¬æ¯çåå¼ {} è¡", period, filled, kept); logSkippedRows("ç©æµç«åºæèµæç»", period, skipped, skippedByCity); return toBytesHssf(wb); } @@ -6314,6 +6333,40 @@ return full != null && RegionUtil.cityList().contains(full); } /** * ååï¼å½ä¸ååä¸è´ï¼å¤æ¡£æ¶ï¼ä¼å éãå½æææ°æ®ãçé£ä¸æ¡£ã * èæ¯ï¼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 +6415,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}(?:å¿|å¸|åº))", "");