| docs/功能测试报告/功能测试报告_中口径四维口径统一_2026-09-18.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-18.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Öпھ¶ËÄά¿Ú¾¶Í³Ò»_2026-09-18.md
New file @@ -0,0 +1,77 @@ # åè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18 ## ä¸ãåè½è¯´æ **ç®æ **ï¼è®©ãä¸å£å¾ãå¨ç³»ç»åå¤ä½¿ç¨åä¸å¥å£å¾ä¸åä¸å¥æºæ°æ®ï¼æ¶é¤ãå䏿æ å¨ä¸å页/ä¸å导åºä»¶é对ä¸ä¸ãçé®é¢ã **ä¸å£å¾å®ä¹ï¼4 ç»´ï¼2026-09-18 èµ·ç»ä¸ï¼** | 维度 | å«ä¹ | æ°æ®æ¥æº | |---|---|---| | 1 | å ¬è·¯ççº¿å®¢è¿ | `h2031_enterprise_monthly`ï¼ä¼ä¸ææ¥ï¼+ `passenger_individual_monthly`ï¼ä¸ªä½ææ¥ï¼ | | 2 | åé åä¹¡å ¬äº¤ | `city_bus_monthly` ç `passenger_chengxiang / turnover_chengxiang` | | 3 | åé å乡巡游åºç§ | `city_taxi_monthly`ï¼æ»é â åå¸å ï¼`passenger_volume - passenger_city`ï¼å¨è½¬éåæ³ï¼ | | 4 | åé å乡ç½çº¦è½¦ | `WycSplitCalc`ï¼è®¢å + å ¨ç pin + 巡游åºç§æåï¼ï¼æ»é â åå¸å | - æ»å®¢è¿é/æ»å¨è½¬é = 维度 1+2+3+4ï¼`loadMidClassMap` ç维度 0ï¼ï¼ - **å ¨çè¡ä¸å¾ = Σ17 å¸å·**ï¼ä¸éç¨åºå `region_code='420000'` çå ¨çè¡ï¼è¯¥å£å¾ 1-8 ææ¯ Σå¸å·å¤ 3042.75ï¼å±ä¸å¡å¾ æ ¸é¡¹ï¼ï¼ - 忝 = (æ¬æ â å»å¹´åæ) / å»å¹´åæï¼æ å»å¹´æ°æ®ç空ã **æ¬æ¬¡æ¹å¨æä»¶**ï¼`traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java` - `loadMidClassMap()`ï¼è¡¥ç»´åº¦ 3ï¼å·¡æ¸¸åºç§å乡ï¼ã维度 4ï¼ç½çº¦è½¦å乡ï¼ï¼æ°å¢ `midPeriodKey()`ï¼ - `fillMidCell()`ï¼å»æãåºç§/ç½çº¦è½¦åæ» 0ãæè·¯ï¼åç»´ç»ä¸ååºå å¼ï¼ - `fillMidYoyCell()` / `fillMidCumYoyColumn()`ï¼åæ¯ç±ãåªç®åä¸¤ç»´ãæ¹ä¸ºåç»´é½å ¨ï¼ - `exportPassengerMidDetail()`ï¼ç±ãåªå¤çå ¬å¼æ ¼ãæ¹ä¸ºãæåéåãï¼æ©ååºæ¥ç 7~12 æç©ºæ ¼æå¡«å¾ä¸ï¼æ©åæä»½çæ»è¡å¼åç±åºå åç»´åè®¡ç´æ¥åå ¥ï¼éç®æ¹ç¨éæ ¼å®¹éç `recalcWorkbookFormulas()`ï¼å `evaluateAll()` ä¼å¨è·¨ç°¿å ¬å¼å¤æ´æ¬ä¸æï¼ç´¯è®¡åæ¿ä¸å°æ°ç¼åå¼ï¼ã ## äºãæµè¯ç¯å¢ - å端 8090ï¼`start-dev.ps1` éå¯ï¼PID 11772ï¼ãå端 8080ï¼å¤ç¨å·²å¨è¿è¡å®ä¾ï¼ï¼æ°æ®åº `traffic_audit`ï¼127.0.0.1:3308ï¼ï¼æ¥è¡¨æ 2026-08ï¼mode=monthã - å¯¼åºæ¥å£ï¼`/api/report/export/summaryWorkbook`ã`/api/report/export/passengerMidDetail`ã`/api/report/export/passengerMidRank`ã - è¯æ®æä»¶ï¼`_tmp/_qa_out/step3c_summary.xlsx`ã`step3c_midDetail.xlsx`ã`step3c_midRank.xlsx`ã`chk_step3c2.txt`ã`chk_step3c3.txt`ã`cmp_step3bc.txt`ï¼æ¬è½®ï¼ï¼`step3b_*.xlsx`ï¼æ¹å¨ååºçº¿ï¼ã ## ä¸ãç¨ä¾è¡¨ | # | ç±»å | ç¨ä¾ | 颿 | å®é | ç»è®º | |---|---|---|---|---|---| | 1 | æ£å | ç¬ç«ãçæ_ä¸å£å¾æç»ãå ¨ç 8 ææ»è¡ï¼Q5ï¼ | = åç»´å计 4003.57ï¼åä¸ºç©ºï¼ | 4003.5701 | éè¿ | | 2 | æ£å | ç¬ç«ä»¶å ¨ç 7 ææ»è¡ï¼O5ï¼ | = 4028.3213ï¼åä¸ºç©ºï¼ | 4028.3213 | éè¿ | | 3 | æ£å | 18 个å°åºï¼å ¨ç+17 å¸å·ï¼Ã 7/8 ææ»è¡ = Σ该å 4 ç»´è¡ï¼8 æåç»´é½å ¨æ¶ï¼ | ç¸ç | 8 æ 18/18 ç¸çï¼7 æ 18/18 ç¸ç | éè¿ | | 4 | æ£å | ç¬ç«ä»¶ç´¯è®¡åï¼AAï¼ç¼åå¼ | = è¯¥è¡ 1-8 æä¹å | 18/18 è¡ç¸çï¼å ¨ç 31528.0607ï¼æ¦æ± 2759.8855ï¼ | éè¿ | | 5 | æ£å | ç¬ç«ä»¶ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ãé¡µéæ ¼å¯¹ç §ï¼å ¨çè¡ 1-8 æã4 个维度åè§£ï¼ | å®å ¨ä¸è´ | 1-8 æ 4 ç»´ + æ»éå ¨é¨ä¸è´ | éè¿ | | 6 | æ£å | æ±æ»å¤§è¡¨ãä¸å£å¾æåãå ¨ç累计 K3 | = Σ17 å¸å· K4:K20 | 29464.6108 = Σå¸å·ï¼ç¬ç«æåä»¶ B3 åå¼ï¼ | éè¿ï¼å£å¾ä¸è´æ§å¦è§é®é¢ 2ï¼ | | 7 | åå½ | æ±æ»å¤§è¡¨çæä»¶æ¹å¨ååéæ ¼å¯¹æ¯ï¼17 é¡µï¼ | 0 å·®å¼ | 0 æ ¼åå | éè¿ | | 8 | åå½ | ç¬ç«ãçæ_ä¸å£å¾æåãæ¹å¨ååéæ ¼å¯¹æ¯ | 0 å·®å¼ | 0 æ ¼åå | éè¿ | | 9 | åå½ | ç¬ç«ãçæ_ä¸å£å¾æç»ãæ¹å¨ååéæ ¼å¯¹æ¯ | ä» ç®æ æ ¼åå | ä» 36 æ ¼åå = 18 å°åº à 2 个æï¼O/Q æ»è¡ï¼ | éè¿ | | 10 | è´å/è¾¹ç | `wyc_order_monthly` 2026-01~06 订ååå ¨ä¸º NULLãæ¨¡æ¿ãç½çº¦è½¦è®¢ååå ¨çæ»é.xlsxãåªæ 2026-07 ä¸è¡ææ°æ® | 维度 4 è¯¥ææ æº â è¡ç空ï¼ä¸ç¼é ï¼ | ç¬ç«ä»¶ãåé å乡ç½çº¦è½¦ã1-6 æä¸ºç©ºï¼æ±æ»è¡¨è¯¥å£å¾ç±æ¯çå®ç¨¿æ¿è½½ | éè¿ï¼æé¢æç空并记å½ï¼ | | 11 | è´å/è¾¹ç | å»å¹´åææ æ°æ®ï¼å¦ 2025-01 ç½çº¦è½¦è®¢åç¼ºå¤±ï¼ | 忝ç空 | çç©ºï¼æªå 0 / #DIV/0! | éè¿ | | 12 | è´å/è¾¹ç | ç¼ºæ¨¡æ¿æä»¶ | æãæªæ¾å°æ¨¡æ¿æä»¶ãå¹¶åå ¥å端æ¥å¿ | æªè§¦åï¼æ¨¡æ¿é½å ¨ï¼ | ä¸éç¨ | **å ¥åºæ½æ¥**ï¼æ¥è¡¨æ 2026-08ï¼ä¸æºè¡¨é项对é½ï¼ | æ½æ¥é¡¹ | åºå å¼ | çæä»¶å¼ | ç»è®º | |---|---|---|---| | `city_bus_monthly` 8 æ 17 å¸å·å计 | 12315.37 | ä¸å£å¾ç»´åº¦ 2 = 1436.63ï¼åé å乡å£å¾ï¼éå计å£å¾ï¼ | å£å¾ä¸åï¼éå䏿æ | | `city_taxi_monthly` 8 æåé å乡差ï¼èå· 100.94 / åæ 73.90 / æ©æ½ 53.54 / è¥é³ 49.84 / 宿 46.81 / æ¦æ± 0ï¼ | Σ = 493.90 | 维度 3 å ¨ç = 493.90 | éè¿ | | `wyc_order_monthly` 2026-08ï¼`order_sum` 30508652ã`order_wuhan` 11550551ã`pin_k` 4997.74ï¼ | â | 维度 4 å ¨ç = 426.56 | éè¿ | ## åãåç°çé®é¢ä¸å¤ç½® 1. **ï¼æ¬æ¬¡å·²ä¿®ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ãæ©ååç 7~12 ææ»è¡ä¸ºç©ºã累计åå¨ 6 æ** - æ ¹å ï¼æ»è¡å¼å卿©ååºæ¥çæä»½éæ¢ä¸æ¯å ¬å¼ä¹æ²¡æç¼åå¼ï¼æ§åæ¯ `keepCached` çäºææ ¼åæ¸ 空ï¼`evaluateAll()` åå¨è·¨ç°¿å ¬å¼å¤æ´æ¬ä¸æï¼ç´¯è®¡åå¾ä¸å°æ°å¼ã - å¤ç½®ï¼æ©åæä»½æ»è¡æ¹ç±åºå åç»´åè®¡ç´æ¥åå ¥ï¼éç®æ¹éæ ¼å®¹éãéªè¯è§ç¨ä¾ 1-4ã9ã 2. **ï¼æªä¿®ï¼éå£å¾å³çï¼ãçæ_ä¸å£å¾æåãçå ¨ç累计ä¸åæ¯ä¸ãçæ_ä¸å£å¾æç»ãä¸èªæ´½** - ç°è±¡ï¼æåä»¶å ¨ç累计 = 29464.6108ãç´¯è®¡åæ¯ = 0.638ï¼ä¸å£å¾æç»å ¨ç累计 = 31528.0607ãç´¯è®¡åæ¯ = 0.0581ï¼å·®å¼ 2063.45 = 2026 å¹´ 1-6 æç»´åº¦ 4ï¼333.39+294.49+347.23+335.39+369.27+383.68ï¼ã - æ ¹å ï¼æåä»¶ç± Java ç¨ `loadMidClassMap()` ç°ç®ï¼1-6 æç½çº¦è½¦æ æº â å°ä¸åï¼ä¸ 2025 å¹´åºçº¿ä¹åªæåºå å£å¾ï¼ï¼ä¸å£å¾æç»é¡µèµ°çæ¯æ¯çå ¬å¼é¾ + å®ç¨¿ç¼åå¼ã - 建议ï¼è§ãæ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡_2026-09-18ã第 3 æ¥ââç»ä¸ç±ãæ¯çå ¬å¼é¾ + å°è´¦é¡µãåºæ°ï¼Java ä¸åå¦ç®ä¸å¥ï¼è¯¦è§æ¬è½®çå¤ï¼ã 3. **ï¼å±æ¯ç缺é·ï¼ä¸å£å¾æç»åå¸çº§ãåé å乡巡游åºç§/ç½çº¦è½¦ãè¡å ¬å¼å¼é页** - ç°è±¡ï¼æ¦æ± R13/R14 å ¬å¼ä¸º `=å ¬äº¤!C13-å ¬äº¤!C15`ï¼åºå嫿å `åºç§!`ã`ç½çº¦è½¦!`ï¼ï¼åå¸çº§æä¸º 0ï¼èå ¨çè¡ R8/R9 é æ¯çç¼åå¼ç»åºç宿°ï¼535.83 / 333.39ï¼ï¼äºè ä¸èªæ´½ã - å¤ç½®ï¼éä¿®æ¯çè¿ä¸¤è¡çå ¬å¼å¼ç¨ï¼ä¸æ¬¡æ§ï¼ï¼ä¹åç±éç®èªå¨åºå¼ãæ¬æ¬¡æªæ¹æ¯çã 4. **ï¼æ°æ®ç¼ºå£ï¼2026 å¹´ 1-6 æç½çº¦è½¦è®¢åæªå ¥åº** - `wyc_order_monthly` 2026-01~06 ä» æ `pin_*`ï¼`order_*` å ¨ NULLï¼æ¨¡æ¿æä»¶ä¹åªæ 2026-07 ä¸è¡ææ°æ® â 维度 4 ç 1-6 ææ æºã ## äºãç»è®º æ¬æ¬¡æ¹å¨æãä¸å£å¾ãä» 2 ç»´ï¼ç线+å ¬äº¤ï¼ç»ä¸ä¸º 4 ç»´ï¼å¹¶ä¿®æäºç¬ç«ãçæ_ä¸å£å¾æç»ãæ©åæä»½æ»è¡ä¸ºç©ºã累计åå¨ä¸ä¸æçé®é¢ï¼å·²éªè¯ 12 æ¡ç¨ä¾ï¼6 æ£å / 3 åå½ / 3 è´åè¾¹çï¼å ¨é¨éè¿ï¼æ±æ»å¤§è¡¨ 17 页ä¸ãçæ_ä¸å£å¾æåãé¶åå½ã ä»å¾ å¤çï¼æå件䏿ç»ä»¶çå£å¾å½ä¸ï¼é®é¢ 2ï¼éä¸å¡/æ¹æ¡ç¡®è®¤ï¼ãæ¯çä¸å£å¾æç»åå¸çº§å ¬å¼å¼é页ï¼é®é¢ 3ï¼ãç½çº¦è½¦ 1-6 æè®¢åæ°æ®ç¼ºå£ï¼é®é¢ 4ï¼ã docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-18.md
@@ -21,6 +21,23 @@ - åäºãæ±æ»è¡¨ä¸æ¡ä¸»çº¿ä¿®å¤æ¹æ¡_2026-09-18ãï¼`docs/é®é¢æ±æ»/`ï¼ï¼ææ ¹å ãè¯æ®ã4 æ¥ä¿®æ³ãæèµ"æé¡¹ç®åç§°æ´æ°/æ°å¢æè¡"ç°ç¶ä¸å¹¶è®°å½ã - æèµä¾§æ ¸å®ï¼å¯¼å ¥ç¡®å®æã项ç®åç§° + ç±»å«ãupsertï¼åºå 客è¿ç«åº 49/49ãç©æµååº 135/135 æ éå¤è¡ï¼ï¼ç¼ºå£æ¯"模æ¿é没æçæ°é¡¹ç®ä¸ä¼æè¡"ã"èµéæ¸ éåç»è¡å¯¼å ¥æ¶è¢«è·³è¿"ã"ååä¸å项ç®ä¸å¼¹çª"ã ### 3. 第 3 æ¥ï¼ä¸å£å¾åç»´å£å¾ç»ä¸ï¼ä¸åï¼ **å£å¾å®æ»**ï¼åè¿ãåè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18ãï¼ï¼1 å ¬è·¯ç线ï¼h2031+个ä½ï¼= 2 åé åä¹¡å ¬äº¤ï¼city_busï¼= 3 åé å乡巡游åºç§ï¼city_taxiï¼æ»éâåå¸å ï¼= 4 åé å乡ç½çº¦è½¦ï¼WycSplitCalc æåï¼ï¼æ»é = åç»´ä¹åï¼**å ¨çè¡ä¸å¾ Σ17 å¸å·**ã **æ¹å¨**ï¼`ReportExportService.java`ï¼ï¼ - `loadMidClassMap()` 补维度 3ã维度 4ï¼æ°å¢ `midPeriodKey()`ï¼ï¼ - `fillMidCell()` 廿ãåºç§/ç½çº¦è½¦åæ» 0ãæè·¯ï¼`fillMidYoyCell()`/`fillMidCumYoyColumn()` 忝æ¹åç»´é½å ¨ï¼ - `exportPassengerMidDetail()` ç±ãåªéåå ¬å¼æ ¼ãæ¹ä¸ºãæåéåãï¼æ©ååºç 7~12 æç©ºæ ¼æå¡«å¾ä¸ï¼ï¼ - æ©åæä»½çæ»è¡å¼åæ¹ç±åºå åç»´åè®¡ç´æ¥åå ¥ï¼æ¨¡æ¿æ¬æ æ¤åï¼å é忢æ å ¬å¼ä¹æ ç¼åå¼ï¼ï¼ - è¯¥å½æ°éç®æ¹ç¨éæ ¼å®¹éç `recalcWorkbookFormulas()`ââ`evaluateAll()` ä¼å¨è·¨ç°¿å ¬å¼ï¼Sheet2 ç `[1]xx!A1`ï¼å¤æ´æ¬ä¸æï¼ç´¯è®¡åå°±æ°¸è¿æ¿ä¸å°æ°ç¼åå¼ã **éªè¯**ï¼ç¬ç«ãçæ_ä¸å£å¾æç»ã8 æå ¨çæ»è¡ 4003.5701ã7 æ 4028.3213ï¼å为空ï¼ï¼18 个å°åºæ»è¡ = Σ4 ç»´ã累计å = Σ1-8 æï¼ä¸æ±æ»å¤§è¡¨ãä¸å£å¾æç»ãé¡µéæ ¼ä¸è´ï¼åå½ = æ±æ»è¡¨ 17 页 0 å·®å¼ãæåä»¶ 0 å·®å¼ãæç»ä»¶ä» 36 æ ¼ï¼18 å°åº à 2 ä¸ªææ»è¡ï¼ååã **é¡ºå¸¦æ¥æ¸ 两个èé®é¢**ï¼ - ãçæ_ä¸å£å¾æåãå ¨ç累计 29464.6108 / 忝 0.638ï¼æ¯ä¸å£å¾æç»å° 2063.45ï¼å·®å¼æ£å¥½æ¯ 2026 å¹´ 1-6 æç»´åº¦ 4ï¼ç½çº¦è½¦ï¼â æåä»¶æ¯ Java ç°ç®ãæç»é¡µèµ°æ¯çå ¬å¼é¾ï¼ä¸¤å¥å£å¾ææ¶ï¼ç¬¬ 3 æ¥ççæ£æ¶å£ç¹ï¼ã - æ¯çãä¸å£å¾æç»ãåå¸çº§ãåé å乡巡游åºç§/ç½çº¦è½¦ãè¡å ¬å¼å¼é页ï¼`=å ¬äº¤!C13-å ¬äº¤!C15`ï¼åºæå `åºç§!`/`ç½çº¦è½¦!`ï¼ï¼åå¸çº§æ 0ãå ¨çè¡é ç¼åå¼ â éä¿®æ¯çå ¬å¼ä¸æ¬¡ã ## äºãæµè¯ç»ææè¦ è§ `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æ±æ»è¡¨å ¬å¼æ©é¡µä¸éç®_2026-09-18.md`ï¼8 æ¡æ£å + 4 æ¡è´å/è¾¹ç + 4 é¡¹å ¥åºæ½æ¥ï¼å ¨é¨éè¿ã @@ -30,16 +47,38 @@ - ä¸å£å¾æå K3 ç¼å 24481.7407 = æå·¥ Σ17 å¸å·ã - åå½ï¼æ¹å¨ååéæ ¼å¯¹æ¯ï¼ä» 216 æ ¼ååï¼å ¨é¨è½å¨ç®æ 两页ï¼å ¶ä½ 17 页 0 å·®å¼ã ### 第 3 æ¥ï¼ä¸åï¼æµè¯ç»æ è§ `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_ä¸å£å¾åç»´å£å¾ç»ä¸_2026-09-18.md`ï¼6 æ¡æ£å + 3 æ¡åå½ + 3 æ¡è´åè¾¹çï¼å ¨é¨éè¿ã - ç¬ç«ãçæ_ä¸å£å¾æç»ãå ¨ç 8 ææ»å®¢è¿é 4003.5701 = ç线 1646.4801 + å ¬äº¤ 1436.63 + åºç§å乡 493.90 + ç½çº¦è½¦å乡 426.56ï¼ - 18 个å°åº Ãï¼7ã8 æï¼æ»è¡ = Σ 该å 4 ç»´è¡ï¼ç´¯è®¡åç¼åå¼ = Σ1-8 æï¼å ¨ç 31528.0607ï¼ï¼ - åå½ï¼æ±æ»å¤§è¡¨ 17 页 0 æ ¼ååããçæ_ä¸å£å¾æåã0 æ ¼ååããçæ_ä¸å£å¾æç»ãä» 36 æ ¼ååï¼å ¨é¨æ¯ç®æ æ ¼ï¼ã ## ä¸ãéçé®é¢ä¸å¾ å 1. **ä¸å£å¾æå忝仿¯åæ»å¼**ï¼M3=0.7424 / Q3=0.2317ï¼åºå å ¨çå£å¾ï¼ï¼éä¸ Î£17 å¸å·å£å¾ç»ä¸ ââ 第 3 æ¥ã 2. **`loadMidClassMap()` 缺巡游åºç§ + ç½çº¦è½¦ä¸¤ç»´**ï¼å¯¼è´ç¬ç«ãçæ_å ¬è·¯æ 客ä¸å£å¾æç»ãå° 535.83+333.39ï¼1 æï¼ââ 第 3 æ¥ã 3. **åºå h2031ãå ¨çãè¡ â Σ17 å¸å·**ï¼1-8 æ 27524.49 vs 24481.74ï¼å·® 3042.75ï¼ï¼ä¸å¡å£å¾é®é¢ï¼å»ºè®®ä¸å¡ä¾§æ ¸å¯¹ã 4. æèµï¼æ¨¡æ¿é没æçæ°é¡¹ç®ä¸ä¼èªå¨æè¡ï¼æç»è¡¨èµéæ¸ éåç»è¡æªå ¥åºï¼éå `fund_channel`ï¼ï¼ååä¸åé¡¹ç®æªå¼¹çªã 5. æèµä¸¤å¼ æç»è¡¨ï¼`Xæå®¢è¿ç«æèµæç»è¡¨` / `Xæç©æµç«åºæèµæç»`ï¼çæå¨æªåã 1. ~~ä¸å£å¾æå忝仿¯åæ»å¼~~ â **å·²ææ°å£å¾åå¼**ï¼M3=0.638 / Q3=0.2247ï¼ï¼ä½ä»ä¸ä¸å£å¾æç»ç 0.0581 ä¸èªæ´½ï¼å·®å¼ 2063.45 = ç½çº¦è½¦ 1-6 ææ æºï¼**æ¶å£åæ³è§ä¸æ¹"第 3 æ¥æ¶å£å»ºè®®"**ã 2. ~~`loadMidClassMap()` 缺巡游åºç§ + ç½çº¦è½¦ä¸¤ç»´~~ â **已补**ï¼ç»´åº¦ 3ã4ï¼ï¼ç¬ç«ä¸å£å¾æç»åç»´é½å ¨ã 3. **æ¯ç缺é·å¾ ä¿®**ï¼ä¸å£å¾æç»åå¸çº§ãåé å乡巡游åºç§/ç½çº¦è½¦ãè¡å ¬å¼å¼éé¡µï¼æå `å ¬äº¤!`ï¼ï¼åå¸çº§æ 0ãå ¨çè¡é ç¼åå¼ã 4. **æ°æ®ç¼ºå£**ï¼2026-01~06 ç½çº¦è½¦è®¢åæªå ¥åºï¼`order_*` å ¨ NULLï¼ï¼æ¨¡æ¿ãç½çº¦è½¦è®¢ååå ¨çæ»é.xlsxãåªæ 2026-07 ä¸è¡ â 维度 4 该 6 ä¸ªææ æºï¼éä¸å¡è¡¥æ°æç¡®è®¤ä¸éç¨ã 5. åºå h2031ãå ¨çãè¡ â Σ17 å¸å·ï¼1-8 æ 27524.49 vs 24481.74ï¼å·® 3042.75ï¼ï¼ä¸å¡å£å¾é®é¢ï¼å»ºè®®ä¸å¡ä¾§æ ¸å¯¹ã 6. æèµï¼æ¨¡æ¿é没æçæ°é¡¹ç®ä¸ä¼èªå¨æè¡ï¼æç»è¡¨èµéæ¸ éåç»è¡æªå ¥åºï¼éå `fund_channel`ï¼ï¼ååä¸åé¡¹ç®æªå¼¹çªã 7. æèµä¸¤å¼ æç»è¡¨ï¼`Xæå®¢è¿ç«æèµæç»è¡¨` / `Xæç©æµç«åºæèµæç»`ï¼çæå¨æªåã ### 第 3 æ¥æ¶å£å»ºè®®ï¼å¾ ç¨æ·ææ¿ï¼ ä¸å让 Java åç®ä¸å¥ï¼æ¹ä¸º**䏿¡é¾è·¯åºæ°**ï¼æ¯çå ¬å¼é¾ï¼å ¨çè¡ = Σ17 å¸å·ã累计 = Σåæãæ´¾ç页跨页å¼ç¨ï¼+ å°è´¦é¡µåæ° + çææ¶å°¾éç®ã 1. å°è´¦é¡µï¼è´§è¿ / ç线å 车 / å ¬äº¤ / åºç§ / ç½çº¦è½¦ / 轨é轮渡ï¼åªå彿å¼ï¼ 2. æ´¾ç页ï¼åå¸å®¢è¿ / ä¸å£å¾æç» / å ¬è·¯æ»å®¢è¿ / ä¸å£å¾å®¢è¿é / æåï¼**åªè¡¥å ¬å¼ + éç®ï¼ä¸åç¬åæ°**ï¼ 3. åªææ¯ç鿬就æ¯ç¡¬ç¼ç æ°å¼çè¡ï¼ä¸å£å¾æç»çåå¸çº§"åé å乡åºç§/ç½çº¦è½¦"ãå ¨çè¡ï¼æåç»´å£å¾åå¡«ï¼ 4. ç¬ç«å¯¼åºä»¶ï¼çæ_ä¸å£å¾æç» / æå / å ¬è·¯æ 客åå¸å·ï¼æ¹ä¸ºç´æ¥åæ±æ»è¡¨å¯¹åºé¡µçå¼ï¼æå ±ç¨åä¸å£å¾å½æ°ï¼ 5. æ¯çéå¼é页çåå¸çº§å ¬å¼ä¿®ä¸æ¬¡ï¼ç¬¬ 3 æ¡ï¼ï¼ 6. çæåè·"çæä»¶ vs æ¯çéç®"éæ ¼å彿¯å¯¹ï¼å·®å¼æ¸ åè½æ¥å¿ï¼ä½ä¸ºéªæ¶åºçº¿ã ## åãæå¤©è®¡å 1. 第 3 æ¥ï¼ç»ä¸ä¸å£å¾å£å¾ï¼rank å ¨ç忝æ¹ä¸ºåæº + `loadMidClassMap` 补两维ï¼ï¼æ¹å®å¯¹ç¬ç«ä¸å£å¾æç»ä¸æ±æ»è¡¨é项æ¯å¯¹ã 2. æèµ"æ°å¢é¡¹ç®æè¡ + åç»è¡å ¥åº"æ¹æ¡è½å°ï¼çç¨æ·å¯¹"模å"å£å¾çæå确认ï¼ã 3. 建çæä»¶ vs æ¯çéç®çå彿¯å¯¹èæ¬ï¼åºåä¸ºæ¯æ¬¡æ¹å¨çéªæ¶åºçº¿ã 1. 第 3 æ¥æ¶å£ï¼æä¸é¢ 6 æ¡è½å°ï¼å ä¿®æ¯çå¼é页çåå¸çº§å ¬å¼ â æåä»¶æ¹ååæº â 建å彿¯å¯¹èæ¬ï¼ã 2. ç½çº¦è½¦ 2026-01~06 è®¢åæ°æ®ç¼ºå£ï¼åç¨æ·ç¡®è®¤æ¯è¡¥æ°è¿æ¯ç空ã 3. æèµ"æ°å¢é¡¹ç®æè¡ + åç»è¡å ¥åº"æ¹æ¡è½å°ï¼çç¨æ·å¯¹"模å"å£å¾çæå确认ï¼ã 4. æèµä¸¤å¼ æç»è¡¨çæå¨ã traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -13,6 +13,7 @@ import com.trafficaudit.dataimport.entity.PassengerEnterpriseMonthly; import com.trafficaudit.dataimport.entity.PassengerIndividualMonthly; import com.trafficaudit.dataimport.entity.ScaleSplitTransport; import com.trafficaudit.dataimport.entity.WycOrderMonthly; import com.trafficaudit.auditengine.entity.AuditResult; import com.trafficaudit.auditengine.entity.AuditRun; import com.trafficaudit.auditengine.mapper.AuditResultMapper; @@ -29,9 +30,11 @@ import com.trafficaudit.dataimport.mapper.PassengerEnterpriseMonthlyMapper; import com.trafficaudit.dataimport.mapper.PassengerIndividualMonthlyMapper; import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper; import com.trafficaudit.dataimport.mapper.WycOrderMonthlyMapper; import com.trafficaudit.reportexport.calc.MidCalc; import com.trafficaudit.reportexport.calc.PaxCalc; import com.trafficaudit.reportexport.calc.SummaryWorkbookFiller; import com.trafficaudit.reportexport.calc.WycSplitCalc; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; @@ -98,6 +101,10 @@ private CityTaxiMonthlyMapper cityTaxiMapper; @Resource private SummaryWorkbookFiller summaryWorkbookFiller; @Resource private WycSplitCalc wycSplitCalc; @Resource private WycOrderMonthlyMapper wycOrderMapper; @Resource private AuditResultMapper auditResultMapper; @Resource @@ -1179,17 +1186,16 @@ return lv == 0.0 ? null : (v - lv) / lv; } /** ä¸å£å¾æåæ¯ï¼k=-1 表示æ»è¡ï¼ç线+å ¬äº¤ä¹åï¼åºç§/ç½çº¦è½¦æ æºæ°æ®æ 0ï¼ï¼æ å»å¹´æ°æ®ç空 */ /** ä¸å£å¾æåæ¯ï¼k=-1 表示æ»è¡ï¼ç线+å ¬äº¤+åºç§å乡+ç½çº¦è½¦å乡 å项ä¹åï¼ï¼æ å»å¹´æ°æ®ç空 */ private void fillMidYoyCell(Cell c, Map<Integer, Map<String, double[][]>> mid, int year, int month, String area, int k, boolean volume) { double v = 0.0, lv = 0.0; if (k == -1) { for (int kk = 1; kk <= 4; kk++) { if (kk >= 3) continue; v += midClassVal(mid, year, month, area, kk, volume); lv += midClassVal(mid, year - 1, month, area, kk, volume); } } else if (k <= 2) { } else { v = midClassVal(mid, year, month, area, k, volume); lv = midClassVal(mid, year - 1, month, area, k, volume); } @@ -1197,7 +1203,7 @@ if (v != 0.0 && lv != 0.0) c.setCellValue(round((v - lv) / lv, 4)); } /** ä¸å£å¾ç´¯è®¡åæ¯åï¼1..months æç´¯è®¡ï¼k=-1 æ»è¡ = ç线+å ¬äº¤ï¼ */ /** ä¸å£å¾ç´¯è®¡åæ¯åï¼1..months æç´¯è®¡ï¼åç»´é½å ¨ï¼ */ private void fillMidCumYoyColumn(Sheet sheet, Map<Integer, Map<String, double[][]>> mid, int year, int months, int colIdx) { List<String> areas = midTemplateAreas(); @@ -1217,7 +1223,7 @@ String area = areas.get(blockOffset / 5); double v = 0.0, lv = 0.0; for (int m = 1; m <= months; m++) { if (k <= 2) { { v += midClassVal(mid, year, m, area, k, volume); lv += midClassVal(mid, year - 1, m, area, k, volume); } @@ -2181,20 +2187,15 @@ boolean extended = fillMonths > 6; if (extended) extendMonthlyColumns(sheet, 2, currentYear, 4, sheet.getLastRowNum()); List<String> areas = midTemplateAreas(); // 2026-09-18ï¼æ¹ä¸ºãæåå æ ¼ç±»åæ å ³ãéåââæ©åï¼7~12 æï¼åºæ¥çå¼å卿¨¡æ¿éæ¯ç©ºæ ¼ï¼ // æ§å®ç°åªå¤ç CellType.FORMULA çæ ¼ï¼å¯¼è´ 7 æå以åæä»½æ°¸è¿å¡«ä¸ä¸ï¼8 ææ´å 0ã累计åªå° 6 æï¼ã for (Row row : sheet) { if (row == null) continue; for (Cell c : row) { if (c.getCellType() != CellType.FORMULA) continue; String f = c.getCellFormula(); if (f == null) continue; boolean crossBook = f.contains("["); if (!crossBook && !isYoyMonthCol(c.getColumnIndex() + 1)) continue; // å é¨å ¬å¼ï¼å计/累计ï¼ä¿çéç®ï¼åæ¯å #REF! è¦å为æ°å¼ if (crossBook && !is2026MonthCol(c.getColumnIndex() + 1)) { keepCached(c); // 2025 å¹´åä¿ç模æ¿ç¼åå¼ continue; } for (int c0 = 0; c0 < Math.max(row.getLastCellNum(), 0); c0++) { Cell c = row.getCell(c0); if (c == null) continue; int r = c.getRowIndex() + 1; int col = c.getColumnIndex() + 1; int col = c0 + 1; int blockOffset = -1; boolean volume = false; if (r >= 5 && r <= 94) { @@ -2205,31 +2206,48 @@ volume = false; } if (blockOffset < 0) { keepCached(c); // r1/r2 夿³¨ç if (c.getCellType() == CellType.FORMULA) keepCached(c); // r1/r2 夿³¨ã页å¤è·¨ç°¿å¼ç¨ç continue; } if (blockOffset % 5 == 0) { if (isYoyMonthCol(col)) { fillMidYoyCell(c, mid, currentYear, monthOfCol(col), areas.get(blockOffset / 5), -1, volume); } else { keepCached(c); // æ»è¡å é¨å ¬å¼ï¼é²å¾¡ï¼ boolean isVal = is2026MonthCol(col); boolean isYoy = isYoyMonthCol(col); if (!isVal && !isYoy) { // 2025 å¹´åçï¼è·¨ç°¿å ¬å¼åç¼å弿é¾ï¼å é¨å ¬å¼ï¼å计/累计ï¼ä¿çï¼ç¨å recalc éç® if (c.getCellType() == CellType.FORMULA) { String f = c.getCellFormula(); if (f != null && f.contains("[")) keepCached(c); } continue; } int k = blockOffset % 5; // 1=ç线 2=å ¬äº¤ 3=åºç§ 4=ç½çº¦è½¦ String area = areas.get(blockOffset / 5); if (is2026MonthCol(col)) { if (blockOffset % 5 == 0) { if (isYoy) { fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, -1, volume); } else if (monthOfCol(col) > 6) { // æ©ååºæ¥ç 7~12 ææ»è¡å¼åï¼æ¨¡æ¿éæ¬æ æ¤åï¼å éåæ¢æ²¡æå ¬å¼ä¹æ²¡æç¼åå¼ï¼ // ç´æ¥ååºå åç»´å计ï¼ç»´åº¦0ï¼ã1~6 æä¿ç模æ¿ç¼åå¼ï¼é¿å ä¸¢ææ¨¡æ¿éçå®ç¨¿æ°ã double total = midClassVal(mid, currentYear, monthOfCol(col), area, 0, volume); c.setBlank(); if (total != 0.0) c.setCellValue(round(total, 4)); } else if (c.getCellType() == CellType.FORMULA) { keepCached(c); // 1~6 ææ»è¡å¼å = 模æ¿ç¼åå¼ï¼ä¿ç } continue; } int k = blockOffset % 5; // 1=ç线 2=å ¬äº¤ 3=åºç§å乡 4=ç½çº¦è½¦å乡 if (isVal) { fillMidCell(c, mid, currentYear, monthOfCol(col), area, k, volume); } else if (isYoyMonthCol(col)) { fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, k, volume); } else { keepCached(c); // 2025 å¹´åä¿ç模æ¿ç¼åå¼ fillMidYoyCell(c, mid, currentYear, monthOfCol(col), area, k, volume); } } } // ç´¯è®¡åæ¯åï¼æ¨¡æ¿ #REF! â åºå å»å¹´ 1..N æç´¯è®¡åæ¯æ°å¼ï¼ fillMidCumYoyColumn(sheet, mid, currentYear, fillMonths, extended ? 27 : 15); recalc(wb); // evaluateAll ä¼å¨è·¨ç°¿å ¬å¼ï¼Sheet2 ç [1]xx!A1ï¼å¤æ´æ¬ä¸æï¼ç´¯è®¡å AA å°±æ°¸è¿æ¿ä¸å°æ°ç¼åå¼ï¼ // æ¹ç¨éæ ¼å®¹éç recalcWorkbookFormulasï¼åæ ¼è·³è¿ãå¥½æ ¼ç §ç®ã int[] recalc = recalcWorkbookFormulas(wb); log.info("ä¸å£å¾æç»å ¬å¼éç®å®æï¼æå {} æ ¼ï¼å¤±è´¥ {} æ ¼", recalc[0], recalc[1]); clearFormulaErrorsAll(wb); // å»å¹´åææç»é¡µæ®ç #REF! åæ¯å ¬å¼ â æ¸ 空 return toBytes(wb); } @@ -2256,12 +2274,8 @@ return (col - 1) / 2; } /** å¡«ä¸å£å¾æ°æ®åå æ ¼ï¼åºç§/ç½çº¦è½¦(3/4)æ¾å¼ 0ï¼ç线/å ¬äº¤å¡«åºå å¼ï¼æ 弿¸ ç©ºï¼ */ /** å¡«ä¸å£å¾æ°æ®åå æ ¼ï¼ç线/å ¬äº¤/åºç§å乡/ç½çº¦è½¦å乡 åç»´ç»ä¸ååºå å¼ï¼æ 弿¸ ç©ºï¼ */ private void fillMidCell(Cell c, Map<Integer, Map<String, double[][]>> mid, int year, int month, String area, int k, boolean volume) { if (k == 3 || k == 4) { writeExplicitZero(c); // åºç§/ç½çº¦è½¦ææ æ°æ®æºï¼æ¾å¼ 0 return; } double v = midClassVal(mid, year, month, area, k, volume); // POI setCellValue(double) å¯¹å ¬å¼åå æ ¼åªæ´æ°ç¼åä¸ç§»é¤å ¬å¼ï¼å¿ é¡»å setBlank ååå¼ c.setBlank(); @@ -2369,9 +2383,54 @@ addMidClass(mid, key, city, 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang())); addMidClass(mid, key, "æ¹åç", 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang())); } // 维度3ï¼åé å乡巡游åºç§ = å°è´¦é¡µãåºç§!æ»é â åºç§!åå¸å ãï¼æº city_taxi_monthlyï¼ for (CityTaxiMonthly t : cityTaxiMapper.selectList(null)) { if (t.getReportPeriod() == null || t.getCity() == null) continue; int key = midPeriodKey(t.getReportPeriod()); if (key <= 0) continue; String city = RegionUtil.normalizeCityName(t.getCity()); if (city == null) continue; double pass = nz(t.getPassengerVolume()) - nz(t.getPassengerCity()); double turn = nz(t.getTurnover()) - nz(t.getTurnoverCity()); addMidClass(mid, key, city, 3, pass, turn); addMidClass(mid, key, "æ¹åç", 3, pass, turn); } // 维度4ï¼åé å乡ç½çº¦è½¦ = ç½çº¦è½¦æåç»æï¼ä¸å°è´¦ãç½çº¦è½¦ãé¡µåæºåæ³ï¼ for (WycOrderMonthly o : wycOrderMapper.selectList(null)) { String per = o.getReportPeriod(); if (per == null) continue; int key = midPeriodKey(per); if (key <= 0) continue; WycSplitCalc.WycResult wr; try { wr = wycSplitCalc.calc(per); } catch (Exception e) { continue; // 该æç¼ºè®¢å/pin æåºç§æºæ°æ®ï¼è·³è¿ï¼ä¸å½±åå ¶å®æï¼ } for (Map.Entry<String, WycSplitCalc.WycMetrics> en : wr.getByCity().entrySet()) { WycSplitCalc.WycMetrics wm = en.getValue(); addMidClass(mid, key, en.getKey(), 4, wm.getSuburbanPax(), wm.getSuburbanTurnover()); addMidClass(mid, key, "æ¹åç", 4, wm.getSuburbanPax(), wm.getSuburbanTurnover()); } } return mid; } /** "yyyy-MM" -> yyyy*100+MMï¼éæ³è¿å 0ï¼ä¸ loadMidClassMap ç key å£å¾ä¸è´ï¼ */ private int midPeriodKey(String period) { if (period == null) return 0; String[] parts = period.trim().split("-"); if (parts.length != 2) return 0; try { int y = Integer.parseInt(parts[0]); int m = Integer.parseInt(parts[1]); if (y <= 0 || m < 1 || m > 12) return 0; return y * 100 + m; } catch (NumberFormatException e) { return 0; } } /** åå ¥åç±»å¼å¹¶ç´¯å æ»éï¼ç»´åº¦0ï¼ */ private void addMidClass(Map<Integer, Map<String, double[][]>> mid, int key, String city, int k, double pass, double turn) { double[][] arr = mid.computeIfAbsent(key, kk -> new HashMap<>()).computeIfAbsent(city, kk -> new double[5][2]);