| New file |
| | |
| | | # åè½æµè¯æ¥å_å
¨ç²¾åº¦åå¨ä¸ä¸¤ä½å°æ°æ¾ç¤º_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | **éæ±ï¼ç¨æ· 2026-09-20 æä»¤ï¼**ï¼ææçæ°æ®é½å
¨é¨å
¨ç²¾åº¦ä¿çï¼è®¡ç®å¾å°çç»ææ¾ç¤ºä¸¤ä½å°æ°ã |
| | | |
| | | **æ¹åé®é¢**ï¼ |
| | | |
| | | 1. å端å¨**ååå
æ ¼ä¹å**å°±åäºåèäºå
¥ï¼åºå±åå¨å¼è¢«æåæªæï¼ |
| | | - `round(v, 4)`ï¼è´§è¿è§ä¸/è§ä¸/忝ã累计ä¸å½æãä¸å£å¾æå/åæã`÷10000` å使¢ç®ãæèµè¿åº¦ãç©æµå æ¯ãæèµè®¡åä¸å¨ï¼ |
| | | - `round(v, 2)`ï¼éç¨æ°æ®æ ¼ `setDataCell`ãå¹³åè¿è·å
åºã客è¿è½¬è¿åå
¥ï¼ |
| | | - `round(v, 1)`ï¼æåé¡µå æ¯ï¼`setFreightShare`ãè´§è¿éæå/å¨è½¬éæååï¼ã |
| | | 误差è½å°ï¼ä½å±äºã计ç®å£å¾è¢«åæ»ãï¼ä¸äººå·¥ç¨å
¨ç²¾åº¦éç®çç»æå¤©ç¶å¯¹ä¸ä¸ï¼æ£æ¯ 09-19 ä¸å£å¾å·®å¼é®é¢çåæºé£é©ï¼ã |
| | | 2. æ¯çä¸ªå«æ ¼èªå¸¦ 3~4 ä½å°æ°**æ¾ç¤ºæ ¼å¼**ï¼`0.0000_);[Red]\(0.0000\)`ã`0.000_ `ï¼ï¼å±ç¤ºä½æ°ä¸ç»ä¸ã |
| | | |
| | | **æ¹åå®ç°**ï¼ |
| | | |
| | | 1. **å
¨ç²¾åº¦**ï¼åæ¶ææåå
¥/è¿ç®åçé¢èå
¥ï¼æ°å¼ä»¥ `double` åå¼åä¸è¿ç®å¹¶åå
¥ï¼`/10000`ãå æ¯ã忝ãå¹³åè¿è·å
åºçä¸å¾ä¸æªæã |
| | | 2. **两ä½å°æ°å±ç¤º**ï¼ç±åå
æ ¼æ°åæ ¼å¼æ¿æ
ãéå `applyTwoDecimalFormat()`ï¼ |
| | | - æ°å¼æ ¼æ ¼å¼ç»ä¸ä¸º `0.00`ï¼`cloneStyleFrom` ä¿çè¾¹æ¡/åä½/对é½ï¼åªæ¢æ°åæ ¼å¼ï¼`;[Red]\(...\)` çååç¼åæ ·ä¿çï¼ï¼ |
| | | - **3 ä½å以ä¸å°æ°çæ ¼å¼**ï¼`0.000_ `ã`0.0000_);[Red]\(0.0000\)`ï¼ç¨æ£å `\.0{3,}` æ¶æä¸º `.00`ï¼ |
| | | - ç¾åæ¯ï¼`%`ï¼ãç§å¦è®¡æ°ï¼`E`ï¼ãææ¬ï¼`@`ï¼ãæ¥ææ ¼å¼**ä¸å¨**ï¼ |
| | | - æ´æ°å¼æ ¼æ²¿ç¨æ¢æçº¦å®ä¸æ¾ç¤º `.00`ï¼å¦å¹´ä»½ãæåï¼ã |
| | | 3. æ§å¶å°/æ¥å£è¿åç**é¢è§æè¦**éç `round`ï¼`addSum(...)`ï¼ä¿çï¼å®ä¸è¿æ¥è¡¨æ°æ®ã |
| | | |
| | | **æ¹å¨æä»¶**ï¼ |
| | | |
| | | | æä»¶ | æ¹å¨ | |
| | | | --- | --- | |
| | | | `traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java` | å»é¤ 40 å¤é¢èå
¥ï¼éå `applyTwoDecimalFormat()`ï¼æ°å¢ `DEC_MORE_THAN_TWO` æ£å常éï¼ | |
| | | | `traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/WycSplitCalc.java` | å¹³åè¿è·å
åºæ¹å
¨ç²¾åº¦ï¼å é¤å·²æ å¼ç¨çç§æ `round(double,int)` | |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | | 项 | å
容 | |
| | | | --- | --- | |
| | | | å端 | Spring Boot `localhost:8090`ï¼`mvn -q -o compile` éè¿åç± `start-dev.ps1` éå¯ï¼PID 15568ï¼ | |
| | | | å端 | Vue `localhost:8080`ï¼PID 28608ï¼ï¼ä¸å端ä¸å¹¶éå¯ | |
| | | | æ°æ®åº | MySQL `localhost:3308/traffic_audit` | |
| | | | æ¥è¡¨æ | 2026-08ï¼1-8 æç´¯è®¡å + 8 æåæåï¼ | |
| | | | 对ç
§ä»¶ | æ¹åçæä»¶ `_after_busfix_2026-08.xlsx`ï¼09-19 å£å¾ä¿®å¤åãæ¬æ¬¡æ¹é åï¼ | |
| | | | æ¹åçæä»¶ | `_after_precision_2026-08.xlsx`ã`_after_precision_midrank/midana/middetail.xlsx`ï¼ä»¥å `_out_precision\` ä¸ 22 个æ¥å£äº§ç© | |
| | | | åè¯èæ¬ | `_qa_prec_*.py`ã`_regen_precision.ps1`ã`_regen_all.ps1` | |
| | | |
| | | ## ä¸ãç¨ä¾ä¸ç»æ |
| | | |
| | | | ç¼å· | ç±»å | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T1 | æ£å | `mvn -q -o compile` | ç¼è¯éè¿ | exit=0ï¼æ åè¦ | éè¿ | |
| | | | T2 | æ£å | 22 ä¸ªå¯¼åºæ¥å£ï¼period=2026-08ï¼ | å
¨é¨ 200 ä¸é空 | 21 个 OKï¼`wycSplit` 500ï¼ç¼ºè¾å
¥æä»¶ï¼è§ãå-5ãï¼ | éè¿ | |
| | | | T3 | æ£å | æ¹å/æ¹åãéè·¯è¿è¾éæ±æ»è¡¨ãéæ ¼æ°å¼å¯¹æ¯ï¼66205 个å
±ææ°å¼æ ¼ï¼ | ä»
ç®æ æ ¼åºç°å·®å¼ | å®é
åå **249 æ ¼**ï¼å
¨é¨è½å¨ãè´§è¿éæåã107 +ãä¸å£å¾æåã142 | éè¿ | |
| | | | T4 | æ£å | æå¤§ååé | åªåºæ¯å»æèå
¥å¸¦æ¥çå°¾æ°å·® | **0.00022 ä¸äººå
¬é**ï¼=2 人å
¬éï¼ï¼ä½ç½®ãä¸å£å¾æåãå
¨çè¡ O3 | éè¿ | |
| | | | T5 | æ£å | æ¦æ±ç´¯è®¡å¨è½¬é | å
¨ç²¾åº¦ä¿çï¼4 ä½å°æ°ä½ä»ä¸º 8912 | ä¸å£å¾æç» S104 = 152330.89119999998ï¼æå页 O4 / éè·¯è¿è¾å¨è½¬é Q5 = 152330.8912 | éè¿ | |
| | | | T6 | æ£å | åæç´¯è®¡å¨è½¬é | ä¸åæªæå° 64429.9445 | 64429.944543113306ï¼æå页䏿ç»é¡µéä½ä¸è´ï¼ | éè¿ | |
| | | | T7 | æ£å | ãä¸å£å¾æåãæ¹å/æ¹åæä¸¤ä½å°æ°å¯¹æ¯ | å®å
¨ä¸è´ï¼ä¸åºæ¹åå¯è§ç»æï¼ | ä¸ä¸è´æ ¼ **0** | éè¿ | |
| | | | T8 | æ£å | å
¨çè¡ `=SUM(O4:O20)` éå | ç¼åå¼ = 17 å¸å·å
¨ç²¾åº¦æ±å | 1227147.4890200002ï¼**å·® 0.0**ï¼09-19 ç 0.0002 æ®çå·²æ¶é¤ï¼ | éè¿ | |
| | | | T9 | æ£å | æ±æ»å¤§è¡¨ãæå¼æ°å¼/å
¬å¼æ ¼ãç 3 ä½ä»¥ä¸å°æ°æ ¼å¼ | 0 æ ¼ | æ¹å 108 æ ¼ â æ¹å **0 æ ¼** | éè¿ | |
| | | | T10 | æ£å | ä¸å£å¾æç»ï¼ç¬ç«ä»¶ï¼`0.000_ ` æ ¼å¼æ ¼ | æ¶æä¸ºä¸¤ä½ | æ¹å 134 æ ¼ â æ¹å **0 æ ¼**ï¼C19 å¼ 13.599765541547498 ä¸åï¼æ ¼å¼å `0.00_ ` | éè¿ | |
| | | | T11 | æ£å | 22 个产ç©ç 3 ä½ä»¥ä¸å°æ°æ ¼å¼æ±æ» | å
¨ä¸º 0 | 15 个å¯è§£æäº§ç©å计 **0 æ ¼** | éè¿ | |
| | | | T12 | åå½ | 表å
é误å¼ï¼`#DIV/0!`/`#VALUE!`/`#REF!`ï¼æ°é | 䏿°å¢ | æ¹å 589 = æ¹å 589ï¼åå¸é项ç¸åï¼ | éè¿ | |
| | | | T13 | åå½ | ç¾åæ¯æ ¼ / 两ä½å°æ°æ ¼æ°é | ä¸åå½±å | 25665 / 39552ï¼ä¸æ¹åä¸è´ | éè¿ | |
| | | | T14 | åå½ | ç¬ç«ä»¶ `passengerMidRank`ã`passengerMidAnalysis` | æ 3 ä½ä»¥ä¸å°æ°æ ¼å¼ | 0 æ ¼ï¼æ¹åæ¬å°± 0ï¼ | éè¿ | |
| | | | T15 | è¾¹ç | ç©ºå¼æ ¼ãææ¬æ ¼ï¼å¦æä»½ææ¬ã2023å¹´4æãï¼ | ä¸å¨ | ä»å¸¦ 4 ä½å°æ°æ ¼å¼ 274 æ ¼ï¼260 ç©ºå¼ + 14 ææ¬ï¼ï¼æ æ¾ç¤ºå¼ï¼ä¸å¤ç | éè¿ | |
| | | | T16 | è¾¹ç | æ´æ°å¼æ ¼ï¼å¹´ä»½/æåï¼ | 䏿¾ç¤º `.00` | æ²¿ç¨æ¢æãæ´æ°ä¸æ¾ç¤º .00ãä¿æ¤ï¼æªè¢«æ¬æ¬¡æ¹å¨ç ´å | éè¿ | |
| | | | T17 | è¾¹ç | ä¸ `round(æ¹å,4)` ä¸ä¸è´ç 30 æ ¼ | å±äºé¶éç®èéé误 | 忝åç±å
¨ç²¾åº¦åå忝éç®ï¼é级 1e-9~1e-8ï¼å¦ 0.0712378390 â 0.0712378363ï¼ | éè¿ | |
| | | | T18 | è´å | æ¯çæå页 Q åå
¬å¼ `=ROUND(B/L*10,1)` | æ¬æ¬¡ä¸æ¹æ¯ç | ä»ä¿çï¼36Ã2 æ ¼ï¼ï¼Excel æå¼ä¼æå
¬å¼éç®å° 1 ä½ååæ `0.00` å±ç¤º | è§ãå-4ãå¾
ææ¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **æ¯ç带 4 ä½å°æ°æ ¼å¼çæå¼æ ¼ 108 个**ï¼`è´§è¿!EO90/EO93/EO108/EO111` ç SUM å
¬å¼æ ¼ã`å
¬è·¯æ»å®¢è¿!DE2` çï¼â å·²ç±æ ¼å¼å½ä¸å¤ç为 `0.00`ï¼å©ä½å¸¦è¯¥æ ¼å¼ç 274 æ ¼å为空å¼/ææ¬æ ¼ï¼æ æ¾ç¤ºå¼ã |
| | | 2. **ãæ´æ°ä¸æ¾ç¤º .00ãä¿æ¤å
æå
¬å¼æ ¼è·³è¿äº**ï¼é¦è½®æ¹é å `è´§è¿!EO90/EO93/EO108/EO111` 仿¯ `0.0000`ï¼ç¼åå¼ä¸º 0ï¼è¢«å¤å®ä¸ºæ´æ°èè·³è¿ï¼ãå·²æã3 ä½ä»¥ä¸å°æ°æ ¼å¼å½ä¸ãç夿**æå°æ´æ°ä¿æ¤ä¹å**ââè¿ç±»æ ¼æ¬æ¥å°±èµ°æ°å¼æ ¼å¼å±ç¤ºï¼ä¸ãGeneral çæ´æ°å¼ä¸æ¾ç¤º .00ãä¸å²çªã |
| | | 3. **3 ä½å°æ°æ ¼å¼æªè¢«è¯å«**ï¼`0.000_ `ï¼ï¼åå¤æç¨ `f.contains("0.00")` 认为已æ¯ä¸¤ä½ï¼è `0.000_ ` æ°å¥½å
å«å串 `0.00` è被跳è¿ï¼å¯¼è´ä¸å£å¾æç» 134 æ ¼æ¼æ¹ãå·²æ¹ä¸ºæ£å `\.0{3,}` ç»ä¸æ¶æã |
| | | 4. **æ¯çæå页 Q å仿¯ `=ROUND(B/L*10,1)`**ï¼è´§è¿éæå Q4:Q42ãè´§è¿å¨è½¬éæå Q5:Q44ï¼å
± 72 æ ¼ï¼ï¼ |
| | | ç¨åºå¯¹å
¬å¼æ ¼ä¸å¾ä¸è¦åï¼ä¿çæ¯çå
¬å¼è®¾è®¡ï¼ï¼Excel/WPS æå¼æ¶ä¼æå
¬å¼éç®å 1 ä½å°æ°å以 `0.00` æ ¼å¼å±ç¤ºã |
| | | è¥è¦è¿è¿ 72 æ ¼ä¹å
¨ç²¾åº¦ï¼éè¦æä¸ä¸ªæ¯ççå
¬å¼æ¹æ `=B/L*10`ï¼å¹¶åæ¥ R å `=10-Q`ï¼ââ**å¾
ç¨æ·ç¡®è®¤åå卿¯ç**ã |
| | | 5. **`wycSplit` æ¥å£ 500**ï¼`loadWycMonthlyInput()` æãæªæ¾å°ç½ç»çº¦è½¦ï¼å
¨çï¼æ±æ».xlsxï¼è¯·æ¾å° docs/ç½ç»å®¢è¿ ç®å½ãï¼è `docs\ç½ç»å®¢è¿` ç®å½å½åä¸åå¨ââå±**缺è¾å
¥æ°æ®çæ¢æç°è±¡**ï¼ä¸æ¬æ¬¡æ¹é æ å
³ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | - æ¥è¡¨æ°å¼å·²å
¨é¨æ¹ä¸º**å
¨ç²¾åº¦åå
¥/è¿ç®**ï¼å±ç¤ºä½æ°ç»ä¸ç±åå
æ ¼æ ¼å¼æ¿æ
ï¼ä¸¤ä½å°æ°ï¼ç¾åæ¯ãæ¥æãææ¬æ ¼å¼ä¸åï¼ã |
| | | - éæ ¼å¯¹æ¯è¯å®ï¼æ¹å䏿¹åçå¯è§ç»æï¼ä¸¤ä½å°æ°å£å¾ï¼**å®å
¨ä¸è´**ï¼å·®å¼ä»
åºç°å¨è¢«å»æèå
¥çå°¾æ°ä½ï¼æå¤§ 0.00022 ä¸äººå
¬éã |
| | | - 顺带æ¶é¤äº 09-19 éççãå
¨çè¡ 0.0002 ä¸äººå
¬éãï¼åå¸å·æ¹ä¸ºå
¨ç²¾åº¦åï¼æ¯çå
¬å¼ `=SUM(O4:O20)` 䏿ç»å
¨ç²¾åº¦æ±å**éä½éå**ã |
| | | - 22 ä¸ªå¯¼åºæ¥å£åå½éè¿ï¼`wycSplit` ä¸ºæ¢æç¼ºæ°æ®é®é¢ï¼ï¼éè¯¯å¼æ°éãç¾åæ¯æ ¼æ°éåæ ååã |
| | | - éçä¸é¡¹å¾
ææ¿ï¼æ¯çæå页 Q/R å æ¯å
¬å¼ç `ROUND(...,1)`ã |
| | | |
| | | æµè¯äººï¼Codexï¼AIï¼ãæµè¯æ¥æï¼2026-09-20 |
| New file |
| | |
| | | # åè½æµè¯æ¥å_åå¸å®¢è¿æåº¦ä¸ç´¯è®¡åæ¯_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | ç¨æ·ä¸æ¥ï¼æ±æ»å¤§è¡¨ãåå¸å®¢è¿ã页 8 æåæ¯ãç´¯è®¡åæ¯ææ¾ä¸å¯¹ï¼å
¨ç客è¿é 8 æåæ¯ â86.5%ãç´¯è®¡åæ¯ â43.5%ï¼ï¼ |
| | | ä¸ã2025å¹´1-7æç´¯è®¡ãè¿ä¸è¾
å©åææå·²å¨æ¯çå é¤å´ä»åºç°å¨çæè¡¨éã |
| | | |
| | | æ¬æ¬¡ä¿®å¤ä¸ä»¶äºï¼ |
| | | |
| | | 1. **æ¯çç»æå½ä¸**ï¼æã2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãåå¸å®¢è¿é¡µå¤åºç AJ åï¼`2025å¹´1-7æç´¯è®¡` è¾
å©åï¼çæ£å é¤ï¼ |
| | | 使 2025 åæåæ¢å¤çè·ï¼2025å¹´8æåå° AJï¼ï¼ä¸çå¼åç
§ä»¶ãçæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxãä¸è´ã |
| | | 2. **ç¨åºä¾§æè¡¨å¤´å®ä½æä»½å**ï¼`SummaryWorkbookFiller.ensureMonthYoyFormulas()` ä¸åæ èãå
¬å¼æ´ä½å³ç§» 2 åãï¼ |
| | | æ¹ä¸ºæè¡¨å¤´ (å¹´,æ) æå
¬å¼éçæä»½åå¼ç¨é¡ºå»¶ä¸ä¸ªæãå
¶ä½å¼ç¨å³ç§» 2 åï¼å¹¶æ°å¢ |
| | | `repairCumulativeYoyFormulas()` å
åºéååæçç´¯è®¡åæ¯åæ¯ï¼åæ¯=å»å¹´ 1..彿åæå¼åä¹åï¼ã |
| | | 3. **æ¥è¡¨çæé¡µé¢è§è¡¥é½å
¨ææ 忝**ï¼`ReportExport.vue` çé¢è§è¡å®ä¹åªæ å°äºå¨è½¬é䏤项忝ï¼è¡¥ä¸è´§è¿é/åå¸å®¢è¿/ä¸å£å¾å
± 8 é¡¹ï¼ |
| | | å¹¶ä¿®æ£ãå½æè´§ç©å¨è½¬é(ä¸å¨)ãåä½ç¬è¯¯ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 Spring Boot 8090ï¼`Started TrafficAuditApplication`ï¼ãå端 Vue 8080ï¼`Compiled successfully`ï¼ |
| | | - æ°æ®åº MySQL localhost:3308/traffic_audit |
| | | - æ¥è¡¨æï¼2026-08ï¼ææ¥ï¼ |
| | | - æ¯çï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼Excel 16.0 COM å ååä¿åï¼ |
| | | - æ¯çå¤ä»½ï¼`docs/çææ±æ»å¤§è¡¨/_bak_202608æ¯çå é¤AJåå_20260920.xlsx` |
| | | - 对æ¯åºåä»¶ï¼`_before_citypaxfix_2026-08.xlsx`ï¼æ¹å¨å 11:37 çï¼ã`_after_ajdel_2026-08.xlsx`ï¼æ¬æ¬¡ä¿®å¤åï¼ |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T01 | 8 æåæ¯åå忝 | å¯¼åº 2026-08 æ±æ»å¤§è¡¨ï¼è¯» åå¸å®¢è¿!R4 å
¬å¼ | `=Q4/AJ4-1`ï¼Q=2026å¹´8æãAJ=2025å¹´8æï¼ | `=Q4/AJ4-1` | éè¿ | |
| | | | T02 | å
¨ç客è¿é 8 æåæ¯ç¼åå¼ | åä¸ï¼è¯»ç¼å | 约 +4.44%ï¼32215.74 / 30846.31 â 1ï¼ | +4.4395% | éè¿ | |
| | | | T03 | ç´¯è®¡åæ¯åæ¯ | 读 åå¸å®¢è¿!T4 å
¬å¼ | `=S4/(V4+X4+Z4+AB4+AD4+AF4+AH4+AJ4)-1` | åå·¦ï¼ä¸ä¸åæ¯ `#REF!` | éè¿ | |
| | | | T04 | å
¨ç客è¿éç´¯è®¡åæ¯ç¼åå¼ | 读ç¼å | 约 +0.117%ï¼269628.07 / 269312.48 â 1ï¼ | +0.1172% | éè¿ | |
| | | | T05 | è¾
å©åæ¯å¦å½»åºæ¶å¤± | å
¨è¡¨æç´¢ `2025å¹´1-7æç´¯è®¡` | 0 å¤ | 0 å¤ï¼åå¸å®¢è¿ç»´åº¦ç± A1:BV40 æ¶ä¸º A1:BU40 | éè¿ | |
| | | | T06 | æ¯çå ååå¼ç¨èªå¨è°æ´ | 读æ¯ç åå¸å®¢è¿!W4ï¼2025å¹´1æåæ¯ï¼ | `=V4/AW4-1`ï¼2024 åºåéå å左移ä¸åï¼ | `=V4/AW4-1` | éè¿ | |
| | | | T07 | æ¯çæ®çé误å
¬å¼ | æ«ææ¯ç åå¸å®¢è¿é¡µå« `#REF!` çå
¬å¼ | 0 å¤ï¼å å产çç 36 å¤ `#REF!` å·²è¿å为 AJï¼ | 0 å¤ | éè¿ | |
| | | | T08 | å
¨è¡¨å¾ªç¯å¼ç¨ | æ«æçæè¡¨ç¼åå¼ `~CIRCULAR~REF~` | 0 å¤ | 0 å¤ï¼ä¿®å¤å 360 å¤ï¼ | éè¿ | |
| | | | T09 | å
¶å®å°è´¦é¡µ 8 æåæ¯ | 读 è´§è¿/ç½çº¦è½¦/ä¸å£å¾æç» R5 | `=Q5/AJ5-1` ä¸ç¼å为ç¾åæ¯ | ä¸é¡µå为 `=Q5/AJ5-1`ï¼è´§è¿ +5.16%ãç½çº¦è½¦ +63.72%ãä¸å£å¾æç» â0.67% | éè¿ | |
| | | | T10 | éåå¸å®¢è¿é¡µåå½ | éæ ¼å¯¹æ¯æ¹å¨ååé¤åå¸å®¢è¿å¤ç 18 ä¸ªé¡µç¾ | é¤ T09 çä¿®å¤å¤ä¸åºæå·®å¼ | ä»
è´§è¿/ç½çº¦è½¦/ä¸å£å¾æç» ç R åç±å¾ªç¯å¼ç¨å为æ£ç¡®å
¬å¼ï¼å
¶å®é¡µä¸è´ | éè¿ | |
| | | | T11 | åºæ°ç¼ºæ ¼çè¾¹ç | ä¸å£å¾æç» R13/R14/R107/R108ï¼åé
å乡巡游åºç§/ç½çº¦è½¦ï¼2025å¹´8æåºæ°=0ï¼ | æ¾ç¤º `#DIV/0!`ï¼ä¸å¯æ¯ï¼ | `#DIV/0!`ï¼ä¿®å¤åæ¯æ æä¹ç循ç¯å¼ç¨ï¼ | éè¿ï¼é¢æï¼ | |
| | | | T12 | é¢è§æ¥å£åæ¯ææ | `GET /api/report/preview?period=2026-08&mode=month&types=summaryWorkbook` | 24 é¡¹ææ ï¼å« 8 项忝 | 24 项ï¼å
¶ä¸åæ¯ 8 项ï¼è´§è¿é +5.2/+1.9ãå¨è½¬é +4.8/+0.0ãåå¸å®¢è¿é â1.5/â3.1ãåå¸å®¢è¿å¨è½¬é â0.6/â3.5ãä¸å£å¾å®¢è¿é â7.1/â7.6ãä¸å£å¾å¨è½¬é +0.9/â1.1ï¼ï¼èæ¶ 1.03 ç§ | éè¿ | |
| | | | T13 | å端é¢è§æ¸²æ | æ¥è¡¨çæé¡µé¢è§å¼¹çª | 8 è¡é½æåæ¯åæ°å¼ï¼å使£ç¡® | æ å°å·²è¡¥é½ï¼`ReportExport.vue`ï¼ï¼å端 `Compiled successfully` | éè¿ | |
| | | | T14 | è´åï¼æ¯ç缺å/ååºå¼å¸¸ | 代ç å
åºï¼`usableMonthCols` å¤å®è¡¨å¤´ä¸å
¨æ¶éåæ´ä½å³ç§» 2 åï¼ | ä¸åºæå¼å¸¸ãä¸åºæ¹åå
¶å®é¡µ | å
¶å® 8 个å°è´¦é¡µå
¬å¼ä¸æ§çä¸è´ | éè¿ | |
| | | | T15 | 导åºèæ¶ | ä¸è½½ 2026-08 æ±æ»å¤§è¡¨ | 坿¥åï¼å½å 10~20 ç§çº§ï¼ | 14 ç§ï¼æ¯ç读å+åå¡« 6.5sãå
¬å¼éç® 4.1sãåçä¸ä¼ è¾çº¦ 3.4sï¼ | éè¿ï¼è§éçé¡¹ï¼ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **æ¯çä¸¤æ¬æ··æ·**ï¼ç¨æ·ä¹åå¨ã2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãéå äº AJ åï¼è 8 æå¯¼åºç¨çæ¯ |
| | | ã2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼åè
ä»å¸¦è¯¥è¾
å©åã |
| | | â å·²ç¨ Excel 16.0 COM å¨ 8 ææ¯çæ´åå é¤ AJï¼å¼ç¨ç± Excel èªå¨è°æ´ï¼ï¼å¹¶æå å导è´ç 36 å¤ `#REF!` ç´¯è®¡åæ¯å
¬å¼è¿å为 `AJ`ã |
| | | 2. **åå·åºåéä½ï¼æ¬æ¬¡ 8 æåæ¯ç®éçç´æ¥åå ï¼**ï¼æ°åç `colIndexOf()` è¿å 1 åºåå·ï¼è POI ç |
| | | `Cell.getColumnIndex()` æ¯ 0 åºï¼å¯¼è´ãæä»½åæ¥è¡¨ãå
¨é¨è½ç©ºãéåæ `åå·+2`ï¼äºæ¯ |
| | | `=O5/AH5-1` è¢«ç®æ `=R5/AK5-1`ï¼èªå¼ç¨â循ç¯å¼ç¨ï¼ãâ å·²æ¹ä¸ºè¿å 0 åºåå·ï¼ |
| | | åæ¶ä¿®æ è´§è¿/ç½çº¦è½¦/ä¸å£å¾æç» ä¸é¡µç 360 æ ¼å¾ªç¯å¼ç¨ã |
| | | 3. **POI `setCellFormula` 䏿¥å带 `=` åç¼çå
¬å¼ä¸²**ï¼æ `FormulaParseException`ï¼è该å¼å¸¸åå
被 |
| | | `catch (Exception ignore)` éé»åæï¼å¯¼è´ãç´¯è®¡åæ¯åæ¯ä¿®æ£æ ¼æ°=0ãèçä¸åºåå ã |
| | | â 廿å
¬å¼ä¸²åç¼ `=`ï¼å¹¶æ catch æ¹ä¸ºå WARN æ¥å¿ï¼ä¿çä¸é»å¡å¯¼åºççç¥ï¼ã |
| | | 4. **表头è¯å«æ¼å¤**ï¼æ¯çåå¸å®¢è¿é¡µ 3~8 æè¡¨å¤´æ¯ `46235` è¿ç±»è£¸æ¥æåºåä¸åå
æ ¼æ ¼å¼ä¸º Generalï¼ |
| | | åæ `isCellDateFormatted` å¤å®ä¼æ¼æãâ æ¹ä¸ºãæ°å¼å¨ 1..200000 䏿¢ç®åæ¯å½æ 1 å·ãå¤å®ã |
| | | 5. **é¢è§åæ¯å缺失ï¼å端å®ä¹é®é¢ï¼éæ°æ®é®é¢ï¼**ï¼å端ä¸ç´è¿å 8 é¡¹åæ¯ï¼ |
| | | ä½ `ReportExport.vue` çé¢è§è¡å®ä¹åªç»ä¸¤é¡¹å¨è½¬éé
äºåæ¯åãâ å·²è¡¥é½ 8 é¡¹å¹¶æ¹æ `ä¸å¨` ç¬è¯¯ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | 15 æ¡ç¨ä¾å
¨é¨éè¿ï¼å
¶ä¸ T11 ä¸ºé¢æå
ç `#DIV/0!`ãT15 为æ§è½ç°ç¶è¯´æï¼ã |
| | | åå¸å®¢è¿ 8 æåæ¯ä¸ç´¯è®¡åæ¯å·²æ¢å¤æ£ç¡®å£å¾ï¼è¾
å©å卿¯çä¸çæè¡¨ä¸åå·²æ¶å¤±ï¼ |
| | | åæ¶ä¿®å¤äºå¦ä¸å¼ å°è´¦é¡µé¿æåå¨ç循ç¯å¼ç¨éè¯¯ï¼æ¥è¡¨çæé¡µé¢è§å¯æ¾ç¤ºå
¨é¨ 8 项忝ã |
| | | éçï¼å¯¼åºä¸ºåæ¥è¯·æ±ãå½å约 14 ç§ï¼è¯¦è§å·¥ä½æ¥ç»å¾
åï¼ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_å¸å·ç»ä¸å¡«æ¥æ¨¡æ¿ä¸å¿ï¼å¸ãåºï¼è§£æ_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | | åè½ | 说æ | |
| | | | --- | --- | |
| | | | å¸å·å¡«æ¥æ¨¡æ¿ | æ°å¢ä¸¤ä»½å¸å·ææ¥æ¨¡æ¿ï¼`docs/æèµ/模æ¿/模æ¿_å¸å·ææ¥_客è¿ç«åº.xlsx`ã`docs/æèµ/模æ¿/模æ¿_å¸å·ææ¥_ç©æµååº.xlsx`ï¼å页ç¾ãææ¥ã17 ååè¡è¡¨å¤´ + ãå¡«æ¥è¯´æã页 | |
| | | | å¿ï¼å¸ãåºï¼åè§£æ | å¸å·å表导å
¥æ°å¢å¯¹ãå¿ï¼å¸ãåºï¼ãåçè¯å«ï¼åå
¥é¡¹ç®ä¸»æ¡£ `county`ï¼åå
ä»
æèµç³»ç»å¯¼åºä¼åï¼ | |
| | | | 表头è¡å¤å®æ¶ç´§ | `findInvestHeader` å¢å ç»ä¸çå
³é®è¯å¤å® `investHeaderKey`ï¼å¹¶è¦æ±è¡¨å¤´è¡åæ¶æ»¡è¶³ãå«é¡¹ç®åç§°ã+ãè³å° 2 个çè¡¨å¤´åæ®µï¼â¤20 åï¼ãï¼é¿å
æãå¡«æ¥è¯´æã页çé¿å¥å½ä½æ°æ®è¡¨ | |
| | | |
| | | æ¹å¨æä»¶ï¼`traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java` |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 Spring Boot 8090ï¼éå¯åå¯å¨æ¶é´ 2026-09-20 16:06:48ï¼ï¼å端 8080ï¼MySQL 3308 / åº `traffic_audit` |
| | | - æµè¯æ°æ®ï¼ä»¥ã模æ¿_å¸å·ææ¥_客è¿ç«åº.xlsxã为åºç¨¿çæ `æ¦æ±å¸_2026-09_客è¿ç«åºææ¥.xlsx`ï¼2 æ¡æµè¯é¡¹ç®ï¼ |
| | | - è°ç¨æ¹å¼ï¼`POST /api/import/investCityBatch?period=2026-09&category=客è¿ç«åº`ï¼æ¬å°èªç¾ JWTï¼ |
| | | - å
¥åºæ½æ¥ï¼`investment_project` / `investment_monthly` éåæ®µä¸æºæä»¶æ¯å¯¹ |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | # | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T01 | 模æ¿ç»æï¼å®¢è¿ç«åºï¼ | æå¼æ¨¡æ¿ | ãææ¥ã页第 4 è¡ 17 å表头ï¼E å建设æ§è´¨ä¸æï¼ç¬¬äºä¸ªé¡µç¾ä¸ºå¡«æ¥è¯´æä¸å« 11 æ¡è¦æ± | ä¸é¢æä¸è´ | éè¿ | |
| | | | T02 | 模æ¿ç»æï¼ç©æµååºï¼ | æå¼æ¨¡æ¿ | å T01ï¼æ é¢ä¸ºã交éç©æµï¼ç©æµååºï¼ã | ä¸é¢æä¸è´ | éè¿ | |
| | | | T03 | æ£å导å
¥ï¼2 æ¡é¡¹ç®ï¼ | ææ¨¡æ¿å¡«æ¥ 2 æ¡é¡¹ç®ï¼å«å¿åºãæ¹æå·ï¼ | total=2ãsuccess=2ãcity=æ¦æ±å¸ | total=2ãsuccess=2ãfail=0ãcity=æ¦æ±å¸ | éè¿ | |
| | | | T04 | å
¥åºæ½æ¥-主档 | åä¸ | 8 ä¸ªä¸»æ¡£åæ®µé项çäºæºå¼ | æ±å²¸åº/æµè¯å»ºè®¾åä½A/æ°å»º/2026/2027/12345.67/æµè¯å·¥å¯A/æµè¯å设Aï¼æ´ªå±±åº/æµè¯å»ºè®¾åä½B/ç»å»º/2024/2026/20000/æµè¯å·¥å¯B/å设为空 | éè¿ | |
| | | | T05 | å
¥åºæ½æ¥-æåº¦æ° | åä¸ | 6 个æåº¦å段é项çäºæºå¼ãæ¥è¡¨ææ£ç¡® | æ¥åæ 2026-09ï¼1000/5000/1200/300/å¨å»º/æµè¯å½¢è±¡è¿åº¦Aï¼15000/8000/6000/1500/å®å·¥/æµè¯å½¢è±¡è¿åº¦B | éè¿ | |
| | | | T06 | è´åï¼è¯´æé¡µè¢«å½æ°æ®è¡¨ï¼ä¿®å¤åï¼ | æ¨¡æ¿æä»¶ï¼å«å¡«æ¥è¯´æé¡µï¼ | åªè§£æãææ¥ã页 | **失败**ï¼è¯¯è§£æ 8 æ¡è¯´æé¡µé¿å¥ä¸ºé¡¹ç®ï¼id 233~240ï¼ï¼city 被æä»¶åå
åºä¸ºãæ¦æ±å¸ã | 已修å¤ï¼è§ T07ï¼ | |
| | | | T07 | è´åï¼è¯´æé¡µè¢«å½æ°æ®è¡¨ï¼ä¿®å¤åï¼ | å T06 | 说æé¡µä¸å被è¯å«ä¸ºæ°æ®è¡¨ | åä¸æä»¶ç± 8 æ¡é为 2 æ¡æ£ç¡®è®°å½ï¼è¯´æé¡µ 0 æ¡ | éè¿ | |
| | | | T08 | è´åï¼å¿åºååæ³åä½ | 表头ãå¿(å¸ãåº)ããå¿ï¼å¸ãåºï¼ããå¿å¸åºã | åè¯å«ä¸ºå¿åºå | å½ä¸åå¹é
åä¸ç§åæ³åå½ä¸ï¼ä¿®å¤ååæãå¿ï¼å¸,åºï¼ã带éå·ï¼åä¸å½ä¸ï¼ | éè¿ | |
| | | | T09 | åå½ï¼8 æçå®å¸å·æä»¶é导 | 8 æå®¢è¿ 9 份ãç©æµ 16 份åå§ææ¥ | è§£ææ¡æ°ä¸å岿¹æ¬¡ä¸è´ãæ æ¥é | å®¢è¿ 39 æ¡ãç©æµ 128 æ¡ï¼å fail=0ï¼ä¸ 09-19 æ¹æ¬¡ 531/532 ä¸è´ï¼ | éè¿ | |
| | | | T10 | åå½ï¼8 ææåº¦æ°é弿¯å¯¹ | é导å 136 è¡ vs é导å 136 è¡ | éå¼ä¸è´ | å»ä¸»é®åéè¡æ¯å¯¹ï¼**IDENTICAL** | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | | # | é®é¢ | å¤ç½® | |
| | | | --- | --- | --- | |
| | | | P1 | ãå¡«æ¥è¯´æã页éå«ã项ç®åç§°ãçé¿å¥è¢«å½ä½è¡¨å¤´è¡ï¼æ´é¡µ 8 æ¡è¢«è¯¯å»ºæé¡¹ç® | 已修ï¼è¡¨å¤´è¡å¤å®è¦æ±ãå«é¡¹ç®åç§°ã+ãè³å° 2 个çè¡¨å¤´åæ®µï¼â¤20 åï¼ãï¼æµè¯æ°æ®å·²ä»åºä¸æ¸
é¤ | |
| | | | P2 | å¿åºåå
³é®è¯åæ `å¿ï¼å¸,åºï¼`ï¼éå·ï¼ï¼å®é
è¡¨å¤´æ¯ `å¿ï¼å¸ãåºï¼`ï¼é¡¿å·ï¼ï¼å¯¼è´ county åä¸å° | 已修ï¼å
å½ä¸åï¼å
¨/åè§æ¬å·ãé¡¿å·ãéå·å
¨é¨å»æï¼åå¹é
ãå¿(å¸åº)ããå¿å¸åºããåºå¿ã | |
| | | | P3 | **åå½é导 8 æç©æµæ¶ï¼ãæ¹åçåå °äº¤éç©æµåºç¡è®¾æ½æèµç»è®¡æ±æ»è¡¨ï¼ææ¥ï¼ã忬¡å¸¦åºéåå °çæ¦æ± 27 + é»ç³ 4 = 31 个项ç®** | 已忬¡æ¸
é¤ï¼`investment_project` 152 / `investment_monthly` 284 æ¢å¤åç¶ï¼ï¼æ ¹æ²»éæ¸
ç 8 ææºæä»¶ï¼**å¾
ç¨æ·ç¡®è®¤æ¯å¦ç±æä»£å** | |
| | | | P4 | çå®å¸å·ææ¥è¡¨å¤´é**没æ**ãå¿ï¼å¸ãåºï¼ãåï¼æ½æ¥ 8 æ 25 份æä»¶ï¼0 份å«è¯¥åï¼ | 屿£å¸¸ï¼å岿°æ® county ä¸ºç©ºæ¯æ°æ®æºéå¶ï¼9 æèµ·æç»ä¸æ¨¡æ¿å¡«æ¥åè¯¥åææå¼ | |
| | | | P5 | æµè¯ç¨çä¸´æ¶æä»¶ä¸ä¸´æ¶æ°æ® | æµè¯æä»¶ `docs/æèµ/è¾å
¥/客è¿ï¼å®¢è¿ç«ï¼/9æ/æ¦æ±å¸_2026-09_客è¿ç«åºææ¥.xlsx`ãæµè¯é¡¹ç® A/Bã2026-09 导å
¥æ¹æ¬¡å·²å
¨é¨å é¤ | |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | - 两份å¸å·å¡«æ¥æ¨¡æ¿å¯ç¨ï¼æ£åé¾è·¯ï¼æ¨¡æ¿ â è§£æ â 主档 + æåº¦æ°ï¼éåæ®µå¯¹é½ï¼ |
| | | - 表头å¤å®æ¶ç´§åï¼æ¨¡æ¿èªå¸¦çãå¡«æ¥è¯´æã页ä¸åè¢«è¯¯å½æ°æ®è¡¨ï¼è´åç¨ä¾ T06/T07ï¼ï¼ |
| | | - 8 æçå®å¸å·æ°æ®é导å彿 åä¾ï¼æ¡æ°ä¸åå²ä¸è´ï¼æåº¦æ°éå¼ä¸è´ï¼ |
| | | - éçï¼8 æåå °æ±æ»è¡¨æºæä»¶çéåå °æ®µæªæ¸
çï¼P3ï¼ï¼éç¨æ·ç¡®è®¤æ¸
çæ¹å¼ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æèµæç»è¡¨å°±ç»ªä¸é¢è§ç±»åè¡¥é½_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | **é®é¢**ï¼æ¥è¡¨çæé¡µé¢ä¸ï¼ã客è¿ç«æèµæç»è¡¨ããç©æµç«åºæèµæç»ãæ¾ç¤º |
| | | `æªç¥æ¥è¡¨ç±»åï¼investPassengerDetail / investLogisticsDetail`ï¼æ æ³é¢è§/导åºã |
| | | |
| | | **æ ¹å **ï¼ä¸æ¯æ°æ®é®é¢ï¼8 æå®¢è¿/ç©æµæèµææ¥å·²å¨åºï¼å®¢è¿ 39 è¡ãç©æµ 128 è¡ï¼ã |
| | | ä¸ä¸æ¥åªæè¿ä¸¤ä¸ªç±»åæ¥è¿äº**导åº**é¾è·¯ï¼`exportSelected` switchã`REPORT_FILE_NAMES`ãå端å表ãä¸¤ä¸ªå¯¼åºæ¥å£ï¼ï¼ |
| | | æ¼äº**导åºåçå°±ç»ªæ ¡éªä¸é¢è§**é¾è·¯ï¼ |
| | | |
| | | 1. `checkExportReady()` ç `switch (t)` 没æè¿ä¸¤ä¸ª case â è½å° `default`ï¼`rows=0` + `notes.add("æªç¥æ¥è¡¨ç±»åï¼" + t)`ï¼äºæ¯ `ready=false`ï¼ |
| | | 2. `isInvestType(t)` æªæ¶å½è¿ä¸¤ä¸ªç±»å â é¢è§å¾ªç¯æ¢ä¸å½å
¥æèµåæ¯ï¼ä¹æ¿ä¸å°æåº¦è¦çä¸æèµæè¦ã |
| | | |
| | | **å¤ç½®**ï¼ |
| | | - `checkExportReady()` æ°å¢ä¸¤ä¸ª caseï¼æç±»å«ï¼å®¢è¿ç«åº / ç©æµååºï¼ç»è®¡ `investment_monthly` 该æè¡æ°ï¼ |
| | | å¹¶æ ¡éª `docs/æèµ/模æ¿/` ä¸å¯¹åºæ¯çæ¯å¦åå¨ï¼ç¼ºæ¯çåæç¤ºï¼ï¼ |
| | | - `isInvestType()` æ¶å½ä¸¤ä¸ªç±»åï¼æåº¦è¦ç + é®é¢æ¸
å纳å
¥æèµåæ¯ï¼ï¼ |
| | | - `investPreview()` å¢å æç±»å«è¿æ»¤çéè½½ï¼`category != null` æ¶åªç»è®¡è¯¥ç±»å«é¡¹ç®ï¼ï¼ |
| | | ä½¿ä¸¤å¼ æç»è¡¨çæè¦ä¸åæ··å
¥å¦ä¸ç±»å«çå计ï¼åæ åéè½½ä¿çãè¡ä¸ºä¸åã |
| | | - æªç¥ç±»åçå
åºæ¥é**ä¿ç**ï¼æªè¢«åå¼±ï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | | 项 | å¼ | |
| | | | --- | --- | |
| | | | æ¥æ | 2026-09-20 10:4x | |
| | | | å端 | Spring Boot 8090ï¼éå¯å è½½ï¼`Started TrafficAuditApplication` 10:49:51ï¼ | |
| | | | å端 | Vue 8080ï¼HTTP 200ï¼ | |
| | | | æ°æ®åº | MySQL 127.0.0.1:3308 `traffic_audit` | |
| | | | æ¥è¡¨æ | 2026-08ï¼mode=monthï¼ | |
| | | | æ¥å£ | `GET /api/report/ready`ã`GET /api/report/preview`ï¼`types` éå·åéï¼ | |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T01 | å°±ç»ªæ ¡éªï¼æ£åï¼ | `types=investPassengerDetail,investLogisticsDetail` | ä¸ååºç°ãæªç¥æ¥è¡¨ç±»åãï¼ready=true | 两项å `ready=true`ã`note` 为空ï¼`rows` = 39ï¼å®¢è¿ï¼/ 128ï¼ç©æµï¼ | â
éè¿ | |
| | | | T02 | é¢è§ï¼æ£åï¼ | åä¸ï¼è° `/api/report/preview` | ææåº¦è¦çãæè¦ä¸é®é¢æ¸
å | è¦ç `[8]`ã`problems` ä¸ºç©ºï¼æè¦ï¼å®¢è¿ã39 é¡¹ç® / æ¬æ 2048.1 / èªå¹´å 38648.16 / èªå¼å§ 550929.76 ä¸å
ãï¼ç©æµã128 é¡¹ç® / æ¬æ 90185.9 / èªå¹´å 704107.7 / èªå¼å§ 2656354.31 ä¸å
ã | â
éè¿ | |
| | | | T03 | æè¦ä¸åºå
é项对é½ï¼å
¥åºæ½æ¥ï¼ | ä¸è¿°æè¦ vs SQL èå | å®å
¨ä¸è´ | SQLï¼å®¢è¿ `2048.1 / 38648.16 / 550929.76`ãç©æµ `90185.9 / 704107.7 / 2656354.31`ï¼**é项ä¸è´** | â
éè¿ | |
| | | | T04 | åç±»å«è¿æ»¤ï¼æ£åï¼ | ä¸¤å¼ è¡¨æç»æè¦ | ä¸åºæ··å
¥å¦ä¸ç±»å«æ°æ® | å®¢è¿ 39 è¡ãç©æµ 128 è¡ï¼æ°å¥½çäº 39+128=167ï¼`investPlan` çå
¨ç±»å«ç±»åä»è¿å 167ï¼ï¼è¯´ææç»è¡¨å·²æç±»å«æ¶æ | â
éè¿ | |
| | | | T05 | 导åºåå½ï¼æ£åï¼ | è° `/api/report/export/investPassengerDetail`ã`.../investLogisticsDetail` | ä»è½æ£å¸¸åºè¡¨ | çæ `gen_pax_inv.xlsx`ï¼29462 åèï¼ã`gen_log_inv.xls`ï¼134144 åèï¼ï¼æ¤åå·²éªè¯å®¢è¿æ±æ»é¡µä¸å®ç¨¿ 0 å·®å¼ | â
éè¿ | |
| | | | T06 | åææèµç±»ååå½ï¼æ£åï¼ | `types=investPlan,investBillion,investCounty,investFiveYearLogistics` | è¡ä¸ºä¸å | å项å `ready=true`ã`rows=167`ãæ note | â
éè¿ | |
| | | | T07 | æªç¥ç±»åä»è¢«æ¦æªï¼è´åï¼ | `types=foo` | ä»æç¤ºæªç¥ç±»åä¸ä¸å°±ç»ª | `ready=false`ã`rows=0`ã`note=æªç¥æ¥è¡¨ç±»åï¼foo` | â
éè¿ | |
| | | | T08 | 缺æ¯çæç¤ºï¼è´å·设计è¦çï¼ | 移走æ¯ç | æç¤ºãdocs/æèµ/æ¨¡æ¿ ä¸ç¼ºå°ãâ¦ãã | æªå®æµï¼æªä¸´æ¶ç§»å¨ç¨æ·æ¯çæä»¶ï¼ï¼ä»£ç è·¯å¾ä¸ `summaryWorkbook` 缺æ¯çå¤å®åæ | â æªæ§è¡ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | | ç¼å· | é®é¢ | æ ¹å | å¤ç½® | |
| | | | --- | --- | --- | --- | |
| | | | P01 | ä¸¤å¼ æèµæç»è¡¨å¨æ¥è¡¨çæé¡µæ¾ç¤ºãæªç¥æ¥è¡¨ç±»åï¼invest*Detailã | åªæ¥äºå¯¼åºé¾è·¯ï¼æ¼äºå°±ç»ªæ ¡éª `switch` ä¸ `isInvestType` | è¡¥é½ `checkExportReady` 两个 case + `isInvestType` æ¶å½ï¼è§ä¸ | |
| | | | P02 | æç»è¡¨æè¦è¥æ²¿ç¨å `investPreview` 伿··å
¥å¦ä¸ç±»å« | åæ¹æ³åªææ¥è¡¨æèåå
¨é¨æèµææ¥ | æ°å¢å¸¦ `category` çéè½½ï¼æç±»å«è¿æ»¤é¡¹ç® idï¼åéè½½ä¿ç | |
| | | | P03 | ãåããã计ãè¡å
¥åºä¼èå¢å计ï¼åä¸æä¿®å¤çè¿å¸¦å½±åï¼ | æºè¡¨å计è¡è¢«å½æé¡¹ç® | 已修å¤ï¼æ¬æ¬¡æ ¸å¯¹ï¼å®¢è¿æ¬æå®æç±å«å计è¡ç 2130.1 æ¶æä¸º **2048.1**ï¼ä¸ SQL é项ä¸è´ï¼æ éçå«ã计ãç项ç®è¡ | |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | 7 æ¡ç¨ä¾éè¿ã1 æ¡ï¼ç¼ºæ¯çæç¤ºï¼æªå®æµï¼ |
| | | æ¥è¡¨çæé¡µä¸¤å¼ æèµæç»è¡¨ç就绪/é¢è§å·²æ¢å¤æ£å¸¸ï¼æè¦æç±»å«è¿æ»¤ä¸ä¸åºå
SQL é项ä¸è´ï¼ |
| | | 导åºä¸å
¶å®æèµæ¥è¡¨ç±»ååæ åå½ï¼æªç¥ç±»åå
åºæ¦æªä»ç¶ææã |
| | | æ¤åãæªç¥æ¥è¡¨ç±»åã纯å±**ä»£ç æ¼é
**ï¼ä¸ 8 ææèµææ¥æ¯å¦å¯¼å
¥æ å
³ ââ æ°æ®ä¸ç´å¨åºï¼å®¢è¿ 39 / ç©æµ 128ï¼ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æèµé¢å®ææ±æ»è¡¥è®¡ä¸å¯¼å
¥å¼¹çª_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | 1. **æ¸
餿®çæ°æ®**ï¼å é¤ãæ¹åçåå °äº¤éç©æµåºç¡è®¾æ½æèµç»è®¡æ±æ»è¡¨ï¼ææ¥ï¼ãï¼5/7/8 æçï¼æå¸å·å带è¿åºç**éåå °é¡¹ç® 31 个**ï¼æ¦æ± 27 + é»ç³ 4ï¼ï¼ |
| | | 以åè§£ææ¶æãå计ãè¡è¯¯å»ºæé¡¹ç®ç**ä¼ªé¡¹ç® 1 个**ï¼å¸å®å¸å®¢è¿ç«åºï¼13727 ä¸å
ï¼ãå é¤åå
¨éå¤ä»½ã |
| | | 2. **é¢å®ææ±æ»è¡¨å°è®¡è¡¥è®¡**ï¼`investPlan`ï¼çæ_å
¨çé¢å®æè®¡åè¿åº¦æ
嵿±æ».xlsï¼ç**å¸å·å°èè¡ / ååè®¡è¡ / å
¨çå计è¡**ï¼ |
| | | 卿 `investment_monthly` ç´¯å ä¹å¤ï¼æ°å¢ã**æ¬ææ æåº¦æ°ãä½é¡¹ç®ä¸»æ¡£ææ»æèµ**ãç项ç®ï¼åªè¡¥è®¡ãæ»æèµãä¸å |
| | | ï¼å
¶ä½ä¸åæ ä¸»æ¡£æ°æ®æºï¼ç空ï¼ã |
| | | 3. **导å
¥ç»æå¼¹çªæ¹é **ï¼æ°æ®å¯¼å
¥é¡µç导å
¥ç»æ/失败/ä¸ä¸è´æç¤ºï¼ç± Element `$alert` æ¢æèªå®ä¹ `el-dialog`ââ |
| | | æ 颿 坿å¨ãå
å®¹åºæ»å¨ï¼åºé¨æé®åºå®å¯è§ï¼ãåè§ï¼å¹¶æ¯æãå¯¼åºæç»ãä¸è½½ CSVã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端ï¼`mvn -q compile` éè¿ï¼`start-dev.ps1` éå¯ï¼backend.log `14:47:45 Started TrafficAuditApplication`ã`Tomcat started on port(s): 8090`ã |
| | | - å端ï¼frontend.log `14:47:45 DONE Compiled successfully in 4986ms`ï¼App running at http://localhost:8080ã |
| | | - æ°æ®åºï¼MySQL `127.0.0.1:3308` åº `traffic_audit`ã |
| | | - éªè¯æ¥å£ï¼`/api/report/ready`ã`/api/report/export/{type}`ï¼èªç¾ JWTï¼ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥/æä½ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T01 | æ®ç项ç®åºåº | `investment_project` ç©æµååºè®¡æ° | 135 â 31 = 104 | 104 | éè¿ | |
| | | | T02 | æ®çæåº¦æ°åºåº | 被å 31 个项ç®ç `investment_monthly` | 0 | 0 | éè¿ | |
| | | | T03 | å¤ä»½å¯è¿½æº¯ | `docs/æèµ/è¾åº/æ¸
çæ®ç_åå °æ±æ»è¡¨å¸¦åºçéåå °é¡¹ç®_2026-09-20.tsv` | å« 31 ä¸ªé¡¹ç® + 39 æ¡æåº¦æ° + 1 æ¡ä¼ªé¡¹ç® | 77 è¡ï¼å«åèæ é¢/è¡¨å¤´ï¼ | éè¿ | |
| | | | T04 | æ¦æ±ç©æµæ®µè¡æ° | å¯¼åº investPlanï¼2026-08 å½æï¼ | 33 â 6 | 6ï¼èªåæºæ
§ç©æµå/ä¸é/é³é»æ¸¯éæ°´èè¿/æå
/åä¸åå¦å/è¿ç¿è¾¾ï¼ | éè¿ | |
| | | | T05 | æ¦æ±ç©æµå°è®¡ï¼è¡¥è®¡æ°é»è¾ï¼ | åä¸ï¼æ¦æ±å°èè¡ c8 | = 6 ä¸ªé¡¹ç®æ»æèµ 69876+38400+12200+65000+22000+65000 = 272476 | c8=272476ï¼c9/c10/c23 空ï¼è¯¥å¸æªæ¥é 8 æï¼ | éè¿ | |
| | | | T06 | é»ç³ç©æµå°è®¡ | åä¸ | 729375.69 â 614991.69ï¼= èªæ¥ 8 个项ç®ï¼ | 614991.69 | éè¿ | |
| | | | T07 | åå计 = ä¸»æ¡£æ»æèµå计 | ç©æµååè®¡è¡ c8 | `SUM(total_investment)=5889737.36` | 5889737.36 | éè¿ | |
| | | | T08 | å
¨çå计 | åè®¡è¡ c8 | å®¢è¿ 763632.2 + ç©æµ 5889737.36 = 6653369.56 | 6653369.56 | éè¿ | |
| | | | T09 | 补计ä¸å½±åç´¯è®¡å®ææèµ | åè®¡è¡ c23 | 744262.86 â 10306.8ï¼è¢«å 31 ä¸ªé¡¹ç® year_cum ä¹åï¼= 733956.06 | 733956.06 | éè¿ | |
| | | | T10 | 伪项ç®å½±å | å¸å®ï¼å®¢è¿ï¼å°èè¡ c8 | 27454 â 13727 | 13727 | éè¿ | |
| | | | T11 | çæè¡¨æ»è¡æ° | å¯¼åºæä»¶è¡æ° | 313 â 281ï¼å 31 + 1 è¡ï¼ | 281 | éè¿ | |
| | | | T12 | å
¶å®æèµæ¥è¡¨åå½ | `/ready` + éä¸ªå¯¼åº | å
¨é¨ readyãå¯å¯¼åº | rowsï¼investPlan 136 / investBillion 136 / investCounty 136 / investFiveYearLogistics 136 / investPassengerDetail 39 / investLogisticsDetail 97ï¼å¯¼åºåè 162304 / 47104 / 55808 / 82944 / 29462 / 134144 | éè¿ | |
| | | | T13 | è´åï¼æªç¥ç±»å | `types=foo` | ready=falseï¼note=æªç¥æ¥è¡¨ç±»åï¼foo | ä¸è´ï¼å
åºæªåå¼±ï¼ | éè¿ | |
| | | | T14 | å¼¹çªäº¤äº | å端代ç + ç¼è¯ | å¯æå¨ / å
容æ»å¨ / åºé¨æé®åºå® / å¯¼åº CSV | 代ç éææ ¸å¯¹éè¿ãå端ç¼è¯éè¿ï¼**ç¹å»çº§éªæ¶æªå**ï¼é触åçå®å¯¼å
¥æä¼å¼¹ï¼ | é¨åéè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **伪项ç®ãåããã计ã**ï¼id=229ï¼å¸å®å¸å®¢è¿ç«åºï¼13727 ä¸å
ï¼æ æåº¦æ°ï¼ï¼æ¥èª 2026-09-16 15:07 ç 8 æå®¢è¿å¯¼å
¥æ¹æ¬¡ã |
| | | è§£æç«¯çãå计/å°è®¡ãå¤å®æ¤å已修为å»ç©ºç½å¹é
ï¼æ¤æ¡å±æ§æ¹æ¬¡éçï¼æ¬æ¬¡ä¸å¹¶æ¸
é¤ï¼å¤ä»½åä¸ TSV æä»¶ï¼ã |
| | | 2. **8 æçåå °æ±æ»è¡¨æªæ¸
ç**ï¼ç¨æ·å·²æãæ¹åçåå °â¦ï¼2026å¹´7æï¼.xlsãééåå °å
å®¹å æï¼108032 â 90112 åèï¼mtime 2026-09-20 14:34ï¼ï¼ |
| | | ä½**8 æçï¼mtime 2026-08-20ï¼éä»å«æ¦æ± 27 + é»ç³ 4 段**ãè¥å次导å
¥è¯¥æä»¶ï¼å é¤ç 31 个项ç®ä¼éæ°å»ºæ¡£ â é导åéåæ ·æ¸
çã |
| | | 3. **æ ¹å **ï¼è¿ç±»ãä¸ä»½æä»¶å«å
¨çåå¸å·ãççæ±æ»è¡¨è¢«å½ä½ãå¸å·å表ãæåå
¥åºï¼ç³æ¥åä½ååå °ãå®é
æ¶å
¨çï¼ã |
| | | ç¨åºä¾§å
åºæ¹æ¡ï¼å¯¼å
¥æ¶è¯å«å¤å¸å·åå¹¶æç¤ºï¼å¾
ç¨æ·ç¡®è®¤æ¯å¦è¦åã |
| | | 4. **补计å£å¾**ï¼åªè¡¥ãæ»æèµãï¼ä¸è¡¥èªå¼å§å»ºè®¾ç´¯è®¡/æ¬å¹´è®¡å/æ¬æå®æââè¿ä¸å没æé¡¹ç®ä¸»æ¡£æ°æ®æºï¼ç¬¦åç¨æ·ç¡®è®¤çå£å¾ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | é¤ T14 çç¹å»çº§éªæ¶å¤å
¨é¨éè¿ï¼æ®çæ°æ®å·²æ¸
é¤å¹¶çæ¡£å¤ä»½ï¼é¢å®ææ±æ»è¡¨å°è®¡/å计å£å¾å·²æç¨æ·ç¡®è®¤è°æ´ï¼ |
| | | å
¶å®æèµæ¥è¡¨ï¼äº¿å
/ç»æµå¼ºå¿/åäºäºç©æµ/ä¸¤å¼ æç»è¡¨ï¼å彿£å¸¸ã |
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ±æ»å¤§è¡¨å¼æ¥å¯¼åºä¸ç¼å_2026-09-20 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | |
| | | ç¨æ·ä¸æ¥ï¼é®é¢ 3ï¼ï¼**ãæ±æ»å¤§è¡¨ç¹ä¸è½½åè¦è¿ä¸ä¼æååºä¸è½½ï¼ç°å¨æ°æ®åºçæ°æ®è¿ä¸æ¯å¾å¤ï¼é£æ°æ®åºçæ°æ®å¤äºè¿ä¸ªç¨åºä¼å¡æ»åï¼ã** |
| | | |
| | | èæ¯ï¼æ±æ»å¤§è¡¨å¯¼åºæ¯**åæ¥è¯·æ±**ââç¹å»åæµè§å¨è¦ç 10~20 ç§ææ¿å°æä»¶ï¼æ¯ç读å+åå¡« 6.5sãæ´æ¬çº¦ 4 䏿 ¼å
¬å¼éç® 4.1sãåçä¼ è¾ 3.4sï¼ï¼æé´é¡µé¢æ ä»»ä½åé¦ï¼ |
| | | ä¸çæè¿ç¨ä¸ç´å ç HTTP 请æ±çº¿ç¨ï¼å¤äººåæ¶ç¹ä¼è®©å®¹å¨çº¿ç¨æ± 被é¿ä»»å¡å 满ã |
| | | |
| | | æ¬æ¬¡æ¹é ï¼ç¨æ·ç¡®è®¤ãå¯ä»¥ãï¼ï¼ |
| | | |
| | | 1. **弿¥ä»»å¡å**ï¼æ°å¢ `ReportExportTaskService`ï¼åºå® 1 çº¿ç¨æ± `report-export-task`ï¼daemonï¼ã |
| | | å端æäº¤åç«å³æ¿å°ãä»»å¡å·ãï¼åæ 700ms 轮询è¿åº¦ï¼æ¥éª¤ + ç¾åæ¯ + å·²ç¨æ¶é¿ï¼ï¼å®æååç¬ä¸è½½æä»¶ã |
| | | 2. **ç»æç¼å**ï¼å䏿¥è¡¨æ 10 åéå
çæåç»æç´æ¥å¤ç¨ï¼`fromCache=true`ï¼ï¼è·³è¿æ¯ç读åä¸å
¬å¼éç®ï¼ |
| | | ç¼å带**æ°æ®çæ¬å®å«**ââæ°æ®çæ¬å `SELECT IFNULL(MAX(id),0) FROM import_batch`ï¼æé´åªè¦ææ°å¯¼å
¥å°±èªå¨å¤±æï¼åä¸å°çæ¬æ¶ç¦ç¨ç¼åï¼ã |
| | | 3. **å»é䏿é**ï¼å䏿¥è¡¨æå·²æä»»å¡å¨è·æ¶ç´æ¥å¤ç¨è¯¥ä»»å¡ï¼ä¸ä¼é夿ééç®ã |
| | | 4. **å端è¿åº¦å¼¹çª**ï¼è¿åº¦æ¡ + æ¥éª¤ææ¡ + å·²ç¨æ¶é¿ + ç¼åæ¥æºæ¶é´ + 失败åå ï¼çæä¸å¯ãåå°è¿è¡ãï¼æ¶å¼¹çªï¼å®æåä»èªå¨ä¸è½½ï¼ï¼å®æåå¯ãä¿åæä»¶ / éæ°çæ / å
³éãã |
| | | 5. **è¿åº¦ç¹**ï¼2% æ ¡éªæ¯ç â 6% è¯»åæ¯ç â 12% è¿åæåº¦å â 22% åå¡«å½ææ°æ® â 45% å·æ°æå页ä¸è·¨é¡µåæé¡µ â 70% éç®æ´æ¬å
¬å¼ â 95% ååºæä»¶ â 100% 宿ã |
| | | |
| | | åçç¨æ·çé®ï¼**æ°æ®éå¢å¤§ä¸»è¦æ¯ SQL èååæ
¢ï¼ä¸ä¼ã塿»ã**ï¼æ¹é åçæèµ°åå°çº¿ç¨ãåæ¥è¡¨æç»æå¯å¤ç¨ãåæ¥è¡¨æå¹¶åèªå¨å»éï¼ |
| | | å³ä½¿å¤äººåæ¶ç¹ä¹åªæ¯æéï¼å¼¹çªæ¾ç¤ºãæéä¸ãï¼ï¼ä¸ä¼å 满 Web 线ç¨ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | |
| | | - å端 Spring Boot 8090ï¼`Started TrafficAuditApplication` 15:10:53ï¼ãå端 Vue 8080ï¼`Compiled successfully`ï¼ |
| | | - æ°æ®åº MySQL localhost:3308/traffic_audit |
| | | - æ¥è¡¨æï¼2026-08ï¼ææ¥ï¼æ£å¸¸ç¨ä¾ï¼/ 2025-01ï¼æ æ°æ®ï¼è´åç¨ä¾ï¼ |
| | | - æ¥å£èæ¬ï¼`_qa_task.ps1`ã`_qa_task2.ps1`ã`_qa_task3.ps1`ï¼ä¿çæªå ï¼ |
| | | - æµè§å¨å®æµï¼Playwright 1.57 + æ¬æº Chromeï¼æ 头ï¼ï¼çå®ç¹å»ãæ¥è¡¨çæã页æé® |
| | | - è¯æ®æªå¾ï¼`docs/åè½æµè¯æ¥å/æ±æ»å¤§è¡¨å¼æ¥å¯¼åºè¿åº¦å¼¹çª_2026-09-20.png` |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | ### 3.1 æ¥å£å± |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | T-A1 | æäº¤å¼æ¥ä»»å¡ | `GET /api/report/exportTask/summaryWorkbook?period=2026-08&mode=month` | ç«å³è¿å taskIdï¼ä¸é»å¡ | æäº¤èæ¶ **0.07s**ï¼è¿åº¦ 6â22â45â70â95â100ï¼ç»æ DONEï¼**14.4s** | éè¿ | |
| | | | T-A2 | ä¸è½½ä»»å¡æä»¶ | `GET /api/report/exportTask/{id}/file` | è¿å xlsx | 1,325,109 åèï¼**1.27s** | éè¿ | |
| | | | T-A3 | 10 åéå
åæ¥è¡¨æå¤ç¨ | 忬¡æäº¤ååæ° | fromCache=trueãå taskIdãè¿ä¹ç¬æ¶ | fromCache=trueï¼**0.01s**ï¼taskId ç¸å | éè¿ | |
| | | | T-A4 | 强å¶éç® | æäº¤ `refresh=true` | æ°ä»»å¡å·ãçå®éç® | æ° taskIdï¼14.2s éç®å®æ | éè¿ | |
| | | | T-A5 | è¿è¡ä¸å¹¶åå»é | è¿å两次 `refresh=true` | è¿ååä¸ taskId | åä¸ taskIdï¼11.1s | éè¿ | |
| | | | T-A6 | æ°å¢å¯¼å
¥ä½¿ç¼å失æ | ä¸´æ¶æå
¥ä¸æ¡ `import_batch`ï¼id 533â534ï¼åæäº¤ | fromCache=falseï¼éæ°çæ | fromCache=falseï¼11.4s éç®ï¼**æµè¯åå·² DELETE æ¸
å id=533** | éè¿ | |
| | | | T-A7 | è´åï¼ä¸åå¨ç taskId | `GET /exportTask/notexist123` / `.../file` | è¿åæç¡®é误 | ç¶ææ¥å£ `code=500`ã导åºä»»å¡ä¸åå¨æå·²è¿æï¼çæç»æä¿ç 30 åéï¼ãï¼æä»¶æ¥å£ HTTP 500 + åæç¤º | éè¿ | |
| | | | T-A8 | è´åï¼æªå®æå°±ä¸è½½ | ä»»å¡ RUNNING æ¶è¯·æ± `/file` | æç»å¹¶è¯´æ | æã导åºä»»å¡å°æªå®æï¼å½åç¶æï¼RUNNINGï¼ã | éè¿ | |
| | | |
| | | ### 3.2 æµè§å¨å®æµï¼çå®ç¹å»ï¼ |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | UI-1 | è¿åº¦å¼¹çª | æ¥è¡¨çæ â æ±æ»å¤§è¡¨ â 2026-08 â ç¹ã导åºã | ç«å³å¼¹çªå¹¶éæ¡£æ¨è¿ | å¼¹çªå³æ¶åºç°ï¼å®æµéæ ·ï¼0.7s è¯»åæ¯çå·¥ä½ç°¿(6%) â 1.5s åå¡«å½ææ°æ®(22%) â 2.2s å·æ°æå页ä¸è·¨é¡µåæé¡µ(45%) â 7.2s éç®æ´æ¬å
¬å¼ï¼çº¦ 4 䏿 ¼ï¼(70%) â 10.1s ååºæä»¶(95%) â 11.6s 宿(100%) | éè¿ | |
| | | | UI-2 | 宿åèªå¨ä¸è½½ | åä¸ | èªå¨è§¦åä¿å | ä¸è½½ `çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsx`ï¼**1,325,109 åè**ï¼ä¸æ¥å£äº§ç©ååå¸ | éè¿ | |
| | | | UI-3 | ç¼åå½ä¸æç¤º | å
³éå忬¡ç¹ã导åºã | æç¤ºæ¥æºæ¶é´ + ãä¸è½½ãæé® | ã䏿¬¡çæç¨æ¶ 11.3 ç§ããæ¬æ¬¡ç´æ¥ä½¿ç¨ 2026-09-20 15:43:50 çæçç»æï¼10 åéå
䏿鴿²¡ææ°å¯¼å
¥æ°æ®ï¼ãï¼æé®åãä¸è½½ãï¼ç§çº§å®æ | éè¿ | |
| | | | UI-4 | ãéæ°çæã | ç¼åæç¹ãéæ°çæã | çå®éç® | è¿åº¦ä» 0 éæ°æ¨è¿ï¼ãå·²ç¨ 2.1 ç§ãï¼ï¼æé®åºååãä¿åæä»¶/éæ°çæ/åå°è¿è¡ãï¼23.4s å
宿并èªå¨ä¸è½½ | éè¿ | |
| | | | UI-5 | ãåå°è¿è¡ã | çæä¸ç¹ãåå°è¿è¡ã | æ¶èµ·å¼¹çªãä»»å¡ç»§ç»ã宿ä»èªå¨ä¸è½½ | å¼¹çªæ¶èµ· + æç¤ºã已转å
¥åå°çæï¼å®æåä¼èªå¨ä¸è½½ãï¼éåèªå¨ä¸è½½ 1,325,109 åè | éè¿ | |
| | | | UI-6 | è´åï¼æ æ°æ®æ¥è¡¨æ | é 2025-01 â å¯¼åº â 确认ãä»è¦å¯¼åºã | æ¾ç¤ºå¤±è´¥åå ãå¯å
³éãä¸å¯ä¿å | å¼¹çªæ¾ç¤ºãçæå¤±è´¥ï½æªæ¾å°æ¨¡æ¿æä»¶: 2025å¹´1æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼X å¯å
³éï¼ãä¿åæä»¶ãç¦ç¨ï¼ãéæ°çæãå¯ç¨ | éè¿ | |
| | | | UI-7 | 产ç©ä¸è´æ§ | å·å¯å¨ä»¶ vs å·æ°éç®ä»¶ | æ°æ®ä¸è´ | 两次产ç©è§£å
å**éæ¡ç®ä¸è´**ï¼æ 差弿¡ç®ï¼ï¼ä¸ä»½ç¼åä¸è½½ä»¶ SHA256 å®å
¨ç¸å | éè¿ | |
| | | |
| | | ### 3.3 顺æå¤éªï¼ç¨æ·é®é¢ 2ï¼ |
| | | |
| | | | ç¼å· | ç¨ä¾ | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | P-1 | é¢è§åæ¯é¡¹æ¯å¦è¡¥å
¨ | æ±æ»å¤§è¡¨é¢è§å¼¹çª | 8 项忝é½å¨ | 12 è¡ï¼è´§è¿/åå¸å®¢è¿/ä¸å£å¾ Ã å½æÂ·ç´¯è®¡ à é·å¨è½¬ï¼ï¼åæ¯åé½å
¨ | éè¿ | |
| | | | P-2 | ã累计货ç©å¨è½¬éÂ·ç´¯è®¡åæ¯ 0%ãæ¯å¦ä¸º bug | æ¥åº `scale_split_transport` | åºä¸ºåæ°æºæ¬èº«çå¼ | åºå
`total_yoy=0.00000346`ï¼çº¦ 0.0003%ï¼â ä¸ä½å°æ°åèäºå
¥å³ **0%**ï¼é计ç®é误 | éè¿ï¼é缺é·ï¼ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **`ReportExport.vue` åºç°éå¤ç `computed` é®ï¼æ¬æ¬¡æµè§å¨å®æµåç°ï¼å±ä¸¥éåå½ï¼** |
| | | æ°å¢ç弿¥å¯¼åºè®¡ç®å±æ§ï¼taskRunning/taskDone/taskCacheTimeï¼å¦èµ·äºä¸ä¸ª `computed: {`ï¼ |
| | | JS 对象åé¢é**ååé®åè
è¦çåè
**ï¼å¯¼è´åæç `username / realName / myModules / visibleModules` 计ç®å±æ§å
¨é¨ä¸¢å¤±ï¼ |
| | | ãæ¥è¡¨çæã页 `created()` ç´æ¥æ `Cannot read properties of undefined (reading 'filter')`ï¼**æ´é¡µç½å±ä¸å¯ç¨**ã |
| | | â å·²æ 4 个计ç®å±æ§å¹¶å
¥å `computed` åï¼å¹¶å 注é说æä¸å¯å¦èµ·åå keyï¼ï¼ç¼è¯éè¿å¹¶æµè§å¨å¤éªæ£å¸¸ã |
| | | ï¼æ¥å£å±æµè¯æ æ³åç°æ¤ç±»é®é¢ï¼è¿ä¹æ¯æ¬æ¬¡åæåæµè§å¨ç¹å»å®æµçåå ãï¼ |
| | | 2. **æäº¤/轮询失败æ¶å¼¹çªä¼ç©ºè½¬**ï¼å端ç»ä¸è¿å `Result`ï¼éè¯¯æ¶ HTTP ä» 200ã`data` 为空ï¼ï¼ |
| | | å代ç ç´æ¥ `this.taskInfo = res.data || {}` ä¼å¾å°ä¸ä¸ªç©ºå¯¹è±¡ â è¿åº¦åå¨ 0% ä¸ä¸ç»æç¤ºã |
| | | â æäº¤ä¸è½®è¯¢é½æ¹ä¸ºå
å¤ `res.code !== 200 || !res.data`ï¼æäº¤å¤±è´¥ç«å³æ¾ç¤ºå¤±è´¥åå ï¼è½®è¯¢å¤ä¸ºãä»»å¡å·²å¤±æãå¹¶åæ¢è½®è¯¢ã |
| | | 3. **çæä¸å¼¹çªæ åºå£**ï¼åãå
³éãæé® `:disabled="!taskDone"`ï¼çæä¸ä¸ä¸ªæé®å
¨ç°ãå³ä¸è§ X ä¹éèï¼ç¨æ·è¢«éå¨å¼¹çªéç 10~20 ç§ã |
| | | â æ¹ä¸ºçæä¸æ¾ç¤ºãåå°è¿è¡ãï¼æ¶å¼¹çªãç»§ç»çæã宿èªå¨ä¸è½½ï¼ï¼ç»æåææ¾ç¤ºãå
³éãï¼X 卿åæå¤±è´¥ååå¯è§ã |
| | | 4. **ç¼åæææ¡æ§ä¹**ï¼å½ä¸ç¼åæ¶å
ä¿¡æ¯ä»åãå·²ç¨ 11.3 ç§ãï¼å
¶å®æ¯ä¸æ¬¡çæèæ¶ï¼ã |
| | | â ç¼åææ¹ä¸ºã䏿¬¡çæç¨æ¶ãï¼é¿å
è¯¯ä»¥ä¸ºæ¬æ¬¡ä¹ç®äº 11.3 ç§ã |
| | | |
| | | ## äºãç»è®º |
| | | |
| | | - æ¥å£ç¨ä¾ 8 æ¡ãæµè§å¨å®æµ 7 æ¡ãå¤éª 2 æ¡ï¼**å
¨é¨éè¿**ï¼æ éçæªéªè¯é¡¹ã |
| | | - æ±æ»å¤§è¡¨å¯¼åºç°å¨æ¯ãç¹å»å³åé¦ â è¿åº¦å¯è§ â 宿å³ä¸è½½ãï¼ç¼åå½ä¸æ¶ç§çº§è¿åï¼å䏿¥è¡¨æå¹¶åèªå¨å»éï¼çæä¸å Web 线ç¨ã |
| | | - é带修å¤äºä¼å¯¼è´æ¥è¡¨çæé¡µæ´é¡µç½å±çéå¤ `computed` åå½ï¼è¯¥é®é¢å¨æ¥å£æµè¯ä¸ä¸å¯è§ï¼ã |
| New file |
| | |
| | | # 工使¥ç»_2026-09-20 |
| | | |
| | | ## ä¸ãä»å¤©åäºä»ä¹ |
| | | |
| | | ### 1.1 ä¿®å¤ï¼æ¥è¡¨çæé¡µä¸¤å¼ æèµæç»è¡¨æ¥ãæªç¥æ¥è¡¨ç±»åã |
| | | |
| | | - **ç°è±¡**ï¼æ¥è¡¨çæé¡µã客è¿ç«æèµæç»è¡¨ããç©æµç«åºæèµæç»ãæ¾ç¤º |
| | | `æªç¥æ¥è¡¨ç±»åï¼investPassengerDetail / investLogisticsDetail`ï¼æ æ³é¢è§/导åºã |
| | | - **å®ä½**ï¼æ¥éæ¥èª `ReportExportService.checkExportReady()` ç `switch (t)` å
åºåæ¯ï¼`ReportExportService.java:231`ï¼ã |
| | | åä¸æåªæè¿ä¸¤ä¸ªç±»åæ¥è¿**导åº**é¾è·¯ï¼`exportSelected` switchã`REPORT_FILE_NAMES`ã`ReportExportController` 两个æ¥å£ã`ReportExport.vue` 两项ï¼ï¼ |
| | | æ¼äº**å°±ç»ªæ ¡éªä¸é¢è§**é¾è·¯ï¼`isInvestType()` 乿²¡æ¶å½è¿ä¸¤ä¸ªç±»åã |
| | | - **䏿°æ®æ å
³**ï¼8 ææèµææ¥ä¸ç´å¨åºï¼å®¢è¿ç«åº 39 è¡ãç©æµååº 128 è¡ï¼ã |
| | | - **ä¿®å¤**ï¼ |
| | | 1. `checkExportReady()` æ°å¢ä¸¤ä¸ª caseï¼æç±»å«ç»è®¡ `investment_monthly` 该æè¡æ° + æ ¡éª `docs/æèµ/模æ¿/` æ¯çæ¯å¦åå¨ï¼ç¼ºæ¯çç»æç¤ºï¼ï¼ |
| | | 2. `isInvestType()` æ¶å½ä¸¤ä¸ªç±»åï¼çº³å
¥æèµåæ¯çæåº¦è¦çä¸é®é¢æ¸
åï¼ï¼ |
| | | 3. `investPreview()` å¢å æç±»å«è¿æ»¤éè½½ `(period, mode, category, summary, problems)`ï¼åæ åéè½½ä¿çï¼ |
| | | 4. é¢è§å¾ªç¯æç±»ååæ´¾å°å¯¹åºç±»å«ï¼æªç¥ç±»åå
åºæ¥éä¿æä¸åã |
| | | |
| | | ### 1.2 å
¶å® |
| | | |
| | | - éå¯åå端å è½½æ°ä»£ç ï¼å端 `Started TrafficAuditApplication` 10:49:51ï¼ã |
| | | - é¡ºææ ¸å¯¹ï¼å䏿ãå计è¡è¢«å½é¡¹ç®ãä¿®å¤åï¼å®¢è¿æ¬æå®ææèµç±å«å计è¡ç 2130.1 æ¶æä¸º **2048.1**ï¼ä¸ SQL é项ä¸è´ï¼åºå
å·²æ å«ã计ãç伪项ç®è¡ã |
| | | |
| | | ### 1.3 ä¿®å¤ï¼æ±æ»å¤§è¡¨ãåå¸å®¢è¿ã8 æåæ¯ / ç´¯è®¡åæ¯ç®éï¼æ¯çå AJ è¾
å©å + ç¨åºæè¡¨å¤´åæ°ï¼ |
| | | |
| | | - **ç°è±¡**ï¼ç¨æ·ä¸æ¥çæè¡¨åå¸å®¢è¿ 8 æåæ¯ â86.5%ãç´¯è®¡åæ¯ â43.5%ï¼ä¸ã2025å¹´1-7æç´¯è®¡ãå卿¯çå è¿å´ä»å¨çæè¡¨éã |
| | | - **æ ¹å ï¼3 个ï¼**ï¼ |
| | | 1. æ¯çæ**两æ¬**ââç¨æ·å çæ¯ã2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼è 8 æå¯¼åºç¨çæ¯ã2026å¹´8æâ¦ãï¼ |
| | | åè
åå¸å®¢è¿é¡µ 2025 年段æäº AJ åã2025å¹´1-7æç´¯è®¡ãï¼æ 2025å¹´8æåæ¤å° AKï¼ |
| | | 8 æåæ¯ `=Q4/AJ4-1` å®é
æ¯ã8æå¼ ÷ 2025å¹´1-7æç´¯è®¡ãï¼ç´¯è®¡åæ¯åæ¯åæ 1-6 æéå¤è®¡ã8 ææ¼è®¡ã |
| | | 2. æ°åçåå·æ¢ç® `colIndexOf()` è¿å 1 åºåå·ï¼è POI åå·æ¯ 0 åº â æä»½åæ¥è¡¨å
¨è½ç©ºãéåæã+2 åãï¼ |
| | | `=O5/AH5-1` è¢«ç®æ `=R5/AK5-1`ï¼èªå¼ç¨ï¼â è´§è¿/ç½çº¦è½¦/ä¸å£å¾æç» å
± 360 æ ¼å¾ªç¯å¼ç¨ã |
| | | 3. POI `setCellFormula` 䏿¥å带 `=` åç¼çå
¬å¼ä¸²ï¼å¼å¸¸å被 `catch (Exception ignore)` åæï¼ |
| | | ç´¯è®¡åæ¯åæ¯ä¿®æ£ä¸ç´éé»å¤±è´¥ï¼æ¥å¿åªæ¾ç¤ºãä¿®æ£æ ¼æ°=0ãï¼ï¼å¦æ¯ç 3~8 æè¡¨å¤´æ¯ 46235 è¿ç±»è£¸åºå + General æ ¼å¼ï¼ |
| | | åæ `isCellDateFormatted` å¤å®ä¼æ¼å¤ã |
| | | - **å¤ç½®**ï¼ |
| | | 1. æ¯çï¼ç¨ Excel 16.0 COM å¨ã2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãåå¸å®¢è¿é¡µæ´åå é¤ AJï¼å¼ç¨ç± Excel èªå¨è°æ´ï¼ |
| | | å¦ `W4` â `=V4/AW4-1`ï¼ï¼åæå å产çç 36 å¤ `#REF!` ç´¯è®¡åæ¯å
¬å¼è¿å为 `AJ`ï¼ |
| | | å¤ä»½ `_bak_202608æ¯çå é¤AJåå_20260920.xlsx`ï¼å å忝çä¸çå¼åç
§ä»¶ãçæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxãåç»æä¸è´ã |
| | | 2. 代ç ï¼`colIndexOf` æ¹ 0 åºï¼`setCellFormula` 廿 `=` åç¼å¹¶æ catch æ¹æ WARN æ¥å¿ï¼ |
| | | `yearMonthOf` æ¯æè£¸æ¥æåºåï¼`repairCumulativeYoyFormulas()` ä¿ç使¯çå
åºã |
| | | 3. å端ï¼`ReportExport.vue` é¢è§è¡¥é½è´§è¿é/åå¸å®¢è¿/ä¸å£å¾å
± 8 项忝æ å°ï¼ä¿®æ£ãå½æè´§ç©å¨è½¬é(ä¸å¨)ãåä½ã |
| | | |
| | | ### 1.4 æ¸
é¤ãåå °æ±æ»è¡¨ã带åºçéåå °æ®çï¼ç¨æ·è¦æ±ï¼ |
| | | |
| | | - **èæ¯**ï¼ç¨æ·æ ¸å¯¹ `D:\æ¡é¢\çææ°æ®\çæ_å
¨çé¢å®æè®¡åè¿åº¦æ
嵿±æ» (2).xls` åç°æ¦æ±ç©æµæ®µå¤åº 27 个项ç®ï¼é«æ¡¥è´§è¿ç«â¦è¶æµ·åä¸ä¾åºé¾æ»é¨åºå°ï¼å¼å·¥å¹´ 2006-2016ï¼ã |
| | | - **溯æº**ï¼è¿ 27 个ï¼+é»ç³ 4 ä¸ªï¼æ¥èªãæ¹åçåå °äº¤éç©æµåºç¡è®¾æ½æèµç»è®¡æ±æ»è¡¨ï¼ææ¥ï¼ãââæä»¶å/å¡«æ¥å使¯åå °ï¼ |
| | | ä½ä¸ä¸ªé¡µç¾éæ¶äºå
¨çåå¸å·ï¼2026-08-26 11:57 éãå¸å·å表æ¹é导å
¥ï¼ç©æµï¼ç©æµååºï¼/7æï¼ãæå¸å·åå
¥åºï¼batch 17/25ï¼ã |
| | | äº¤åæ ¸å¯¹ï¼è¿ 31 个项ç®åç§°å¨å
¶å®ä»»ä½å¸å·æºæä»¶éé½**æ¥ä¸å°**ï¼ç¡®è®¤ä¸ºè¯¥æä»¶å¸¦åºçæ®çã |
| | | - **导åºä¸ºä½ä¼æ¾ç¤º**ï¼`investPlan` æ¯ãæ¯çå使¿æ¢ + 卿æè¡ãââæ¯çæ¦æ±ç©æµåªé¢ç 7 è¡ï¼åºéå¤åºçé¡¹ç®æãå¸å·+ç±»å«ãèªå¨è¡¥æå°å°èæ«å°¾ |
| | | ï¼`ReportExportService.java` 卿æè¡æ®µï¼ãæä»¥åºéæå¤å°é¡¹ç®ï¼çæè¡¨å°±åºå¤å°è¡ã |
| | | - **å¤ç½®**ï¼å
¨éå¤ä»½å° `docs/æèµ/è¾åº/æ¸
çæ®ç_åå °æ±æ»è¡¨å¸¦åºçéåå °é¡¹ç®_2026-09-20.tsv`ï¼31 ä¸ªé¡¹ç® + 39 æ¡æåº¦æ°ï¼åå é¤ï¼ |
| | | 顺带åç°å¹¶æ¸
é¤è§£æãå计ãè¡è¯¯å»ºç伪项ç®ï¼id=229 å¸å®å¸å®¢è¿ç«åºãåããã计ãï¼13727 ä¸å
ï¼ã |
| | | ç»æï¼ç©æµååºé¡¹ç® 135 â 104ï¼2026-08 æåº¦æ° 167 â 136ï¼å®¢è¿ç«åºé¡¹ç® 49 â 48ã |
| | | |
| | | ### 1.5 é¢å®ææ±æ»è¡¨ï¼å°è®¡/åè®¡è¡¥è®¡ãææ»æèµãæ æ¬ææåº¦æ°ãç项ç®ï¼ç¨æ·ç¡®è®¤ãå¯ä»¥ãï¼ |
| | | |
| | | - åºæ¯ï¼æ¦æ± 8 æç©æµæ²¡æå表æ¥éï¼`docs/æèµ/è¾å
¥/ç©æµï¼ç©æµååºï¼/8æ` éæ²¡ææ¦æ±æä»¶ï¼ï¼6 个æ°é¡¹ç®å¨åºé没æ 2026-08 æåº¦æ°ï¼ |
| | | 忥å°è®¡åªç´¯å æåº¦æ°æ® â æ¦æ±ç©æµæ´ååªæ¾ç¤ºé¡¹ç®è¡ãå°è®¡ç©ºç½ã |
| | | - æ¹å¨ï¼`ReportExportService.investPlan()` æ°å¢ `addProjectsWithoutMonthly(...)`ï¼å¨**å¸å·å°è/åå计/å
¨çå计**ä¸å¤ç´¯å åï¼ |
| | | æãæ¬ææ æåº¦è®°å½ä½ä¸»æ¡£ææ»æèµãçé¡¹ç®æç±»å«/å¸å·è¡¥è¿ **æ»æèµ** ä¸åï¼å
¶ä½åæ ä¸»æ¡£æ°æ®æºï¼ä¿æç©ºç½ï¼ã |
| | | - ææï¼æ¦æ±ç©æµå°è®¡ = 272476ï¼6 ä¸ªé¡¹ç®æ»æèµåï¼ï¼åå计/å
¨çå计 = åºå
åç±»é¡¹ç®æ»æèµä¹åï¼å¯é项对 SQL æ ¸å¯¹ï¼ã |
| | | |
| | | ### 1.6 导å
¥ç»æå¼¹çªæ¹é ï¼ç¨æ·ï¼å¼¹çªå¤ªé¿ãç¹ä¸å°ç¡®è®¤ãä¸è½ç§»å¨ï¼ |
| | | |
| | | - 忥ç¨çæ¯ Element `$alert`ï¼MessageBoxï¼æ¿è½½å¯¼å
¥ç»æ HTMLï¼å
容ä¸é¿å°±æãç¡®è®¤ãæ¤åºå±å¹ï¼ä¸ä¸è½æå¨ã |
| | | - æ¹ä¸ºèªå®ä¹ `el-dialog`ï¼`v-dialog-drag` æ 颿 æå¨ã`custom-class="import-result-dialog"`ï¼å
¨å±æ ·å¼ï¼åè§ + å
å®¹åº `max-height` æ»å¨ + åºé¨æé®åºå®ï¼ï¼ |
| | | å¹¶æ°å¢ãå¯¼åºæç»ãæé®ï¼CSVï¼å¸¦ BOMï¼å¯ç´æ¥ Excel æå¼ï¼ï¼ç¨äºç¨æ·èªè¡æ ¸å¯¹/ä¿®æ¹ä¸ä¸è´å
容ã |
| | | - è¦ç 4 å¤ï¼æ¹é导å
¥ç»æãå¸å·å表æ¹é导å
¥ç»æãåæä»¶å¯¼å
¥å¤±è´¥ãæèµä¸æèµç³»ç»ä¸ä¸è´æ¸
åã |
| | | |
| | | ### 1.7 æ±æ»å¤§è¡¨å¯¼åºå¼æ¥å + ç»æç¼åï¼ç¨æ·æé®ãç¹ä¸è½½è¦çä¸ä¼ï¼æ°æ®å¤äºä¼ä¸ä¼å¡æ»ãï¼ |
| | | |
| | | - **ç°è±¡**ï¼æ±æ»å¤§è¡¨ç¹ã导åºãåè¦ç 10~20 ç§æè§¦åä¸è½½ï¼æé´é¡µé¢æ ä»»ä½åé¦ï¼åæ¥è¯·æ±ä¸ç´å ç Web 线ç¨ã |
| | | - **å®ä½**ï¼14 ç§éæ¯ç读å+åå¡« 6.5sãæ´æ¬çº¦ 4 䏿 ¼å
¬å¼éç® 4.1sãåçä¼ è¾ 3.4sââèæ¶æ¥èª Excel å¤çï¼**䏿°æ®åºè¡æ°å
³ç³»ä¸å¤§**ï¼æ°æ®å¤äºä¸»è¦æ¯ SQL èååæ
¢ï¼ä¸ä¼ã塿»ãã |
| | | - **æ¹å¨**ï¼ |
| | | 1. æ°å¢ `ReportExportTaskService`ï¼åºå® 1 çº¿ç¨æ± daemonï¼ï¼æäº¤å³è¿å taskIdï¼å端 700ms è½®è¯¢ãæ¥éª¤ + ç¾åæ¯ + å·²ç¨æ¶é¿ãï¼ç»æä¿ç 30 åéï¼å
åæï¼è¿ç¨éå¯å¤±æï¼ã |
| | | 2. **ç»æç¼å 10 åé + æ°æ®çæ¬å®å«**ï¼çæ¬å `SELECT IFNULL(MAX(id),0) FROM import_batch`ï¼æé´åªè¦ææ°å¯¼å
¥å°±èªå¨å¤±æï¼åä¸å°çæ¬æ¶ç¦ç¨ç¼åï¼ï¼å䏿¥è¡¨æå¹¶åæäº¤èªå¨å»éãå¤ç¨åä¸ä»»å¡ã |
| | | 3. `ReportExportService` æ°å¢å¸¦è¿åº¦åè°ç `exportSummaryWorkbook(period, mode, toMonth, progress)` éè½½ï¼å两个éè½½å§æå®ï¼ï¼è¿åº¦ç¹ 2%/6%/12%/22%/45%/70%/95%ã |
| | | 4. `ReportExportController` æ°å¢ 3 个æ¥å£ï¼`/exportTask/summaryWorkbook`ï¼æäº¤ï¼ã`/exportTask/{taskId}`ï¼è¿åº¦ï¼ã`/exportTask/{taskId}/file`ï¼ä¸è½½ï¼ï¼å忥æ¥å£ä¿çå
¼å®¹ã |
| | | 5. å端 `ReportExport.vue` è¿åº¦å¼¹çªï¼è¿åº¦æ¡ + æ¥éª¤ + ç¨æ¶ + ç¼åæ¥æºæ¶é´ + 失败åå ï¼ä»¥åãä¿åæä»¶ / éæ°çæ / åå°è¿è¡ / å
³éãã |
| | | - **宿µ**ï¼æäº¤ 0.07sï¼è¿åº¦ 6â22â45â70â95â100ã14.4s 宿ï¼ç¼åå½ä¸ 0.01sï¼`refresh=true` çå®éç®ï¼ä¸´æ¶æä¸æ¡å¯¼å
¥åç¼åèªå¨å¤±æã |
| | | - **åæ¶ä¿®æä¸ä¸ªä¸¥éåå½**ï¼æ¬æ¬¡æ°å¢ç `computed` 䏿件ä¸å·²æ `computed` **ååéå¤**ï¼JS 对象åè
è¦çåè
â `username/myModules/visibleModules` å
¨é¨ä¸¢å¤±ï¼ |
| | | ãæ¥è¡¨çæã页 `created()` ç´æ¥æéã**æ´é¡µç½å±**ãæ¥å£æµè¯åç°ä¸äºï¼æ¯æµè§å¨å®æµææ´é²çï¼è¯¦è§æµè¯æ¥å第åèï¼ã |
| | | |
| | | ### 1.8 å¸å·ç»ä¸å¡«æ¥æ¨¡æ¿ï¼ç¨æ·æé®ãæåªä¸ªæ ¼å¼æ¥æå¥½ï¼è¦ä¸è¦çæä¸¤ä¸ªæ¨¡æ¿ãï¼ |
| | | |
| | | - **èæ¯**ï¼ç¨æ·æåºãè¿å ä¸ªè¡¨çæ´æ°å
¶å®å¾ç®åââæé¡¹ç®åç§°æ´æ°æ±æ»è¡¨ææ ãæ°å¢é¡¹ç®å°±æ°å¢å°æç»è¡¨ï¼ |
| | | é¢å®ææ±æ»è¡¨åæç»è¡¨æ¹å¼ä¸æ ·ï¼å©ä¸ä¸å¼ 表项ç®åºå®åªæ´æ°ææ ââ为ä»ä¹ç°å¨å¼å¾æç¹å¤æãã |
| | | - **æ ¸å¯¹**ï¼éæ±ææ¡£ãæèµææ¥æ°æ®å¤çä¸å¤è¡¨æ´æ°éæ±è¯´æãStep1/2/3 ä¸ç¨æ·æè¿°å®å
¨ä¸è´ï¼ç¨åºé»è¾ä¹æ¯è¿ä¹å®ç°çã |
| | | - **ç»è®º**ï¼å¤æä¸å¨ã表ãï¼å¨ãæºãââçå¼ä¸ç»ä¸ï¼27 份é 7 份æå·®å¼ï¼ãä¸ä¸ªæä»¶æ··å¤ä¸ªå¸å·ã没æå¿åºåãåä½ç½®é å
åºã |
| | | - **产åº**ï¼ |
| | | 1. æ°å¢ä¸¤ä»½å¸å·å¡«æ¥æ¨¡æ¿ `模æ¿_å¸å·ææ¥_客è¿ç«åº.xlsx` / `模æ¿_å¸å·ææ¥_ç©æµååº.xlsx` |
| | | ï¼ãææ¥ã页 17 ååè¡è¡¨å¤´ + 建设æ§è´¨ä¸æ + ãå¡«æ¥è¯´æã页 11 æ¡è¦æ±ï¼ï¼ |
| | | 2. å£å¾è¯´æææ¡£ `docs/æèµ/å¡«æ¥å£å¾ä¸ç»ä¸æ¨¡æ¿_2026-09-20.md`ï¼æ¨¡æ¿å段å»åãå¤æåº¦æ¥æºãå¾
宿»ç 3 ä»¶äºãè¿æ¸¡å®æï¼ã |
| | | - **é
å¥è§£ææ¹å¨**ï¼æ°å¢ãå¿ï¼å¸ãåºï¼ãåè§£æï¼åå
¥ä¸»æ¡£ `county`ï¼ï¼è¡¨å¤´è¡å¤å®æ¶ç´§ä¸º |
| | | ãå«é¡¹ç®åç§° + è³å° 2 个çè¡¨å¤´åæ®µãï¼é¿å
ææ¨¡æ¿èªå¸¦çãå¡«æ¥è¯´æã页彿°æ®è¡¨ã |
| | | |
| | | ## äºãæµè¯ç»ææè¦ |
| | | |
| | | ãåè½æµè¯æ¥å_æèµæç»è¡¨å°±ç»ªä¸é¢è§ç±»åè¡¥é½_2026-09-20.mdãï¼**7 æ¡ç¨ä¾éè¿ï¼1 æ¡æªå®æµ**ï¼ç¼ºæ¯çæç¤ºï¼æªä¸´æ¶ç§»å¨ç¨æ·æ¯çæä»¶ï¼ã |
| | | |
| | | | æ ¡éªé¡¹ | ç»æ | |
| | | | --- | --- | |
| | | | `/api/report/ready`ï¼ä¸¤æ°ç±»åï¼ | ready=trueï¼rows=39 / 128ï¼note 为空 | |
| | | | `/api/report/preview`ï¼ä¸¤æ°ç±»åï¼ | è¦ç [8]ï¼problems 为空 | |
| | | | æè¦ vs SQL éé¡¹å¯¹é½ | å®¢è¿ `2048.1 / 38648.16 / 550929.76`ãç©æµ `90185.9 / 704107.7 / 2656354.31`ï¼**ä¸è´** | |
| | | | åç±»å«è¿æ»¤ | å®¢è¿ 39 + ç©æµ 128 = 167ï¼å
¨ç±»å«ç±»åä» 167ï¼æªä¸²ç±»ï¼ | |
| | | | 导åºåå½ | ä¸¤å¼ æç»è¡¨ä»å¯å¯¼åºï¼29462 / 134144 åèï¼ | |
| | | | åææèµç±»ååå½ | investPlan / investBillion / investCounty / investFiveYearLogistics å ready=trueï¼rows=167 | |
| | | | æªç¥ç±»åè´å | `foo` â ready=falseãnote=æªç¥æ¥è¡¨ç±»åï¼fooï¼å
åºä»ææï¼ | |
| | | |
| | | ãåè½æµè¯æ¥å_åå¸å®¢è¿æåº¦ä¸ç´¯è®¡åæ¯_2026-09-20.mdãï¼**15 æ¡ç¨ä¾éè¿**ã |
| | | |
| | | | æ ¡éªé¡¹ | ç»æ | |
| | | | --- | --- | |
| | | | åå¸å®¢è¿ R4 / T4 å
¬å¼ | `=Q4/AJ4-1`ã`=S4/(V4+X4+Z4+AB4+AD4+AF4+AH4+AJ4)-1`ï¼ä¸åæ¯ `#REF!`ï¼ | |
| | | | å
¨ç客è¿é 8 æåæ¯ / ç´¯è®¡åæ¯ | **+4.44% / +0.117%**ï¼ä¿®å¤å â86.5% / â43.5%ï¼ | |
| | | | è¾
å©å | çæè¡¨ä¸æ¯çåæ ã2025å¹´1-7æç´¯è®¡ãï¼åå¸å®¢è¿é¡µ BVâBU | |
| | | | 循ç¯å¼ç¨ | å
¨è¡¨ 0 å¤ï¼ä¿®å¤å 360 å¤ï¼å«è´§è¿/ç½çº¦è½¦/ä¸å£å¾æç» R åï¼ | |
| | | | å
¶å® 18 个页ç¾åå½ | é¤ä¸è¿° R åä¿®å¤å¤éæ ¼ä¸è´ | |
| | | | é¢è§æ¥å£ | 24 é¡¹ææ å« 8 项忝ï¼1.03 ç§ | |
| | | | 导åºèæ¶ | 14 ç§ï¼æ¯ç读å+åå¡« 6.5sãå
¬å¼éç® 4.1sãåçä¼ è¾ 3.4sï¼ | |
| | | |
| | | ãåè½æµè¯æ¥å_æèµé¢å®ææ±æ»è¡¥è®¡ä¸å¯¼å
¥å¼¹çª_2026-09-20.mdãï¼**14 æ¡ç¨ä¾éè¿ï¼1 æ¡ä¸ºéæ/ç¼è¯çº§éªè¯ï¼ç¹å»çº§éªæ¶å¾
ç¨æ·å®æµï¼**ã |
| | | |
| | | | æ ¡éªé¡¹ | ç»æ | |
| | | | --- | --- | |
| | | | æ®çåºåº | ç©æµé¡¹ç® 135â104ãæåº¦æ° 167â136ï¼å¤ä»½ TSV 77 è¡ | |
| | | | çæè¡¨æ¦æ±ç©æµæ®µ | 33 è¡ â 6 è¡ï¼èªå/ä¸é/é³é»æ¸¯/æå
/åä¸åå¦å/è¿ç¿è¾¾ï¼ | |
| | | | æ¦æ±ç©æµå°è®¡ï¼è¡¥è®¡ï¼ | c8=272476ï¼6 ä¸ªé¡¹ç®æ»æèµåï¼ï¼å
¶ä½å空 | |
| | | | é»ç³ç©æµå°è®¡ | 729375.69 â 614991.69 | |
| | | | åå计/å
¨çå计 | ç©æµ 5889737.36ãå®¢è¿ 763632.2ãå
¨ç 6653369.56ï¼ä¸ SQL ä¸è´ | |
| | | | 1-8æç´¯è®¡ï¼c23ï¼ | 744262.86 â 733956.06ï¼å·®é¢ = 被å é¡¹ç® year_cum ä¹åï¼è¡¥è®¡æªæ±¡æè¯¥å | |
| | | | ä¼ªé¡¹ç®æ¸
é¤ | å¸å®å®¢è¿å°è®¡ 27454 â 13727 | |
| | | | çæè¡¨è¡æ° | 313 â 281 | |
| | | | å
¶å®æèµæ¥è¡¨åå½ | investBillion/County/FiveYearLogistics å 136 è¡ãä¸¤å¼ æç»è¡¨ 39/97 è¡ï¼ready=trueï¼åå¯å¯¼åº | |
| | | | è´å | `types=foo` â ready=falseï¼noteãæªç¥æ¥è¡¨ç±»åï¼fooã | |
| | | |
| | | ãåè½æµè¯æ¥å_æ±æ»å¤§è¡¨å¼æ¥å¯¼åºä¸ç¼å_2026-09-20.mdãï¼**17 æ¡ç¨ä¾éè¿ï¼æ¥å£ 8 + æµè§å¨å®æµ 7 + å¤éª 2ï¼**ã |
| | | |
| | | | æ ¡éªé¡¹ | ç»æ | |
| | | | --- | --- | |
| | | | æäº¤å¼æ¥ä»»å¡ | 0.07s è¿å taskIdï¼è¿åº¦ 6â22â45â70â95â100ï¼14.4s 宿 | |
| | | | 任塿件ä¸è½½ | 1,325,109 åèï¼1.27s | |
| | | | 10 åéå
ç¼åå¤ç¨ | fromCache=trueãå taskIdã0.01s | |
| | | | refresh=true 强å¶éç® | æ°ä»»å¡å·ï¼çå®éç® 14.2s | |
| | | | è¿è¡ä¸å¹¶åå»é | 两次æäº¤è¿ååä¸ taskIdï¼11.1sï¼ | |
| | | | æ°å¢å¯¼å
¥ä½¿ç¼å失æ | import_batch id 533â534 å fromCache=falseï¼æµè¯åå·² DELETE æ¸
å 533ï¼ | |
| | | | è´åï¼ä¸åå¨ / æªå®æ taskId | ã导åºä»»å¡ä¸åå¨æå·²è¿æããå°æªå®æï¼å½åç¶æï¼RUNNINGï¼ã | |
| | | | æµè§å¨å®æµ | è¿åº¦å¼¹çªéæ ·ãèªå¨ä¸è½½ãç¼åæç¤ºãéæ°çæãåå°è¿è¡ã失败æç¤º 6 项å
¨éè¿ | |
| | | | 产ç©ä¸è´æ§ | ç¼åä»¶ä¸éç®ä»¶è§£å
åéæ¡ç®ä¸è´ï¼ä¸ä»½ç¼åä»¶ SHA256 ç¸å | |
| | | | éå¸¦ä¿®å¤ | `computed` éå¤é®å¯¼è´æ¥è¡¨çæé¡µæ´é¡µç½å±ï¼å·²ä¿®å¤å¹¶æµè§å¨å¤éªï¼ | |
| | | | å¤éªï¼ç¨æ·é®é¢ 2ï¼ | é¢è§åæ¯ 12 è¡é½å
¨ï¼ã累计货ç©å¨è½¬é 0%ãç»æ¥åºä¸ºåæ°æºæ¬èº« `total_yoy=0.00000346`ï¼éç¼ºé· | |
| | | |
| | | ãåè½æµè¯æ¥å_å¸å·ç»ä¸å¡«æ¥æ¨¡æ¿ä¸å¿å¸åºè§£æ_2026-09-20.mdãï¼**10 æ¡ç¨ä¾éè¿ï¼æ£å 5 + è´å 3 + åå½ 2ï¼**ã |
| | | |
| | | | æ ¡éªé¡¹ | ç»æ | |
| | | | --- | --- | |
| | | | 模æ¿ç»æ | 两份模æ¿åä¸ºãææ¥ã17 å表头 + 建设æ§è´¨ä¸æ + å¡«æ¥è¯´æ 11 æ¡ | |
| | | | æ£å导å
¥ï¼æ¨¡æ¿å¡«æ¥ï¼ | total=2ãsuccess=2ãcity=æ¦æ±å¸ | |
| | | | 主档éåæ®µ | å¿åºï¼æ±å²¸åº/洪山åºï¼ã建设åä½ãæ§è´¨ãå¼å·¥/ç«£å·¥å¹´ãæ»æèµãå·¥å¯/å设å
¨é¨å¯¹é½ | |
| | | | æåº¦æ°éåæ®µ | èªå¼å§ç´¯è®¡/æ¬å¹´è®¡å/èªå¹´å累计/æ¬æå®æ/å»ºè®¾é¶æ®µ/形象è¿åº¦å
¨é¨å¯¹é½ï¼æ¥è¡¨æ 2026-09 | |
| | | | è´åï¼è¯´æé¡µè¢«å½æ°æ®è¡¨ | ä¿®å¤å 8 æ¡è¯¯è§£æï¼id 233~240ï¼â ä¿®å¤å 0 æ¡ | |
| | | | è´åï¼å¿åºååæ³åä½ | ãå¿ï¼å¸ãåºï¼/å¿(å¸ãåº)/å¿å¸åºãå½ä¸åååå½ä¸ | |
| | | | åå½ï¼8 æçå®å¸å·é导 | å®¢è¿ 39ãç©æµ 128ï¼ä¸ 09-19 æ¹æ¬¡ä¸è´ï¼fail=0 | |
| | | | åå½ï¼8 ææåº¦æ°æ¯å¯¹ | é导åå 136 è¡éå¼ **IDENTICAL** | |
| | | | æ°æ®æ¸
ç | æµè¯é¡¹ç® A/Bã2026-09 æ¹æ¬¡ãæµè¯æä»¶åå·²å é¤ | |
| | | |
| | | ## ä¸ãéçé®é¢ä¸å¾
å |
| | | |
| | | 1. æ¦æ±ç©æµé¡¹ç®æ¸
åå£å¾ï¼å·²ç¡®è®¤å¿½ç¥ï¼ã |
| | | 2. 天é¨ç©æµæºæä»¶ H/J/K 为空 â å¾
ç¨æ·æ¾åäºè¦æ°æ®å导å
¥ã |
| | | 3. èå·/é»ç³ãè§åå
/è§åå¤ãæåå£å¾ â å¾
ç¨æ·ååäºç¡®è®¤ã |
| | | 4. ~~C ç»ï¼åå¸å®¢è¿é¡µç»æå½ä¸ï¼éç¨æ·å
å¨ WPS æ´åå é¤ AJ åï¼~~ **已宿**ï¼æ¹ç¨ Excel COM æ´åå é¤ + å
¬å¼è¿åï¼ï¼ |
| | | D ç»ï¼å¢éæåæªè¾ï¼ï¼B4ï¼å¯¼åºååºæ°ä½æ£ + å¼¹çª + ãæ°æ®ç¼ºå¤±æ¸
åã页ï¼å¾
ææã |
| | | 5. 缺æ¯çæç¤ºï¼T08ï¼æªå®æµï¼å¯å¨ææµè¯å¯æ¬æ¶è¡¥æµã |
| | | 6. ~~æ±æ»å¤§è¡¨å¯¼åºæ¯åæ¥è¯·æ±ï¼å»ºè®®åæå¼æ¥ä»»å¡ + è¿åº¦æç¤º~~ **已宿**ï¼è§ 1.7ï¼ãç¼åæ¯å
åæï¼è¿ç¨éå¯å³å¤±æï¼å¦éè·¨éå¯/å¤äººå
±ç¨çã导åºè®°å½ã页å¯åè¡¥ã |
| | | 7. é¨ç½²å
`deploy/traffic-audit-deploy-20260913/backend/docs/çææ±æ»å¤§è¡¨/` ä¸ `_deploytest/` ä¸ä»æ¯**带 AJ åçæ§æ¯ç** ââ |
| | | ç¨æ· 2026-09-20 æç¡®ãé¨ç½²å
å
ä¸ç®¡ãï¼**æä¸å¤ç**ï¼å¾
è¦åå
æ¶å忥ï¼ã |
| | | 8. ä¸å£å¾æç» 4 æ ¼ï¼åé
å乡巡游åºç§/ç½çº¦è½¦ï¼å 2025å¹´8æåºæ°ä¸º 0ï¼åæ¯æ¾ç¤º `#DIV/0!`ï¼ä¸å¯æ¯ï¼ï¼å¦éæ¹ç©ºç½éç¨æ·ç¡®è®¤å£å¾ã |
| | | |
| | | ## åãææ¥è®¡å |
| | | |
| | | 1. ç天鍿ºæ°æ® / èå·é»ç³å£å¾ç¡®è®¤å补导并å¤éªã |
| | | 2. æ¨è¿ C/D ç»ä¸ B4ã |
| | | 3. ä¸ç¨æ·ç¡®è®¤æ¯å¦æ 09-18 å¤é´èµ·çæ¬å°æäº¤ä¸å¹¶æ¨éå°å
¬å¸ giteaï¼ç¨æ· 09-19 æ¾è¦æ±ãä»å¤©å
䏿¨å
¬å¸ãï¼ã |
| | | 4. ~~è¯ä¼°æ±æ»å¤§è¡¨å¯¼åºå¼æ¥å~~ **已宿**ï¼è§ 1.7ï¼å¼æ¥ä»»å¡ + è¿åº¦å¼¹çª + 10 åéç»æç¼å + æ°æ®çæ¬å®å«ï¼ï¼é¨ç½²å
æ¯çæç¨æ·è¦æ±æä¸å¤çã |
| | | |
| | | 9. **8 æçåå °æ±æ»è¡¨æªæ¸
ç**ï¼ç¨æ·åªæ¸
äº 7 æçï¼108032â90112 åèï¼ï¼8 æçï¼mtime 2026-08-20ï¼ä»å«æ¦æ± 27 + é»ç³ 4 æ®µï¼ |
| | | è¥é导 8 æç©æµï¼å·²å é¤ç 31 个项ç®ä¼éæ°å»ºæ¡£ â é导åéåæ ·æ¸
çï¼æç±æä»£åï¼å¾
ç¨æ·ç¡®è®¤ï¼ã |
| | | **2026-09-20 ä¸åååå½é导æ¶å·²å®æµå¤ç°**ï¼8 æç©æµé导å +31 ä¸ªé¡¹ç® / +31 æ¡æåº¦æ°ï¼ï¼å·²å次æ¸
é¤ï¼åºåå° 152 ä¸ªé¡¹ç® / 284 æ¡æåº¦æ°ï¼2026-08 æåº¦æ°éå¼ä¸é导åä¸è´ã |
| | | 10. å¸å·å表导å
¥ç**å¤å¸å·åå
åºæç¤º**ï¼è¯å«ä¸ä»½æä»¶å«å¤ä¸ªå¸å·åå¹¶æç¤º/è·³è¿ï¼å¾
ç¨æ·ç¡®è®¤æ¯å¦è¦åã |
| | | 11. çæè¡¨æ¦æ±ç©æµå°è®¡ç°å¨åªæãæ»æèµãï¼ç¼º 8 æçèªå¼å§ç´¯è®¡/æ¬å¹´è®¡å/æå®æ â éæ¦æ± 8 æç©æµåè¡¨ï¼æçå
å£å¾ï¼æè½è¡¥é½ã |
| | | 12. 两份å¸å·å¡«æ¥æ¨¡æ¿å¾
ç¨æ·è¿ç®åä¸åå¸å·ï¼å»ºè®® 9 æèµ·æ§è¡ï¼ï¼å¦éãæ¨¡æ¿ä½æ£ + 表头ä¸ç¬¦å¼¹çªãï¼å¾
ç¨æ·ç¡®è®¤åææã |
| | | 13. 8 æåå °ç©æµæ±æ»è¡¨æºæä»¶ï¼å«æ¦æ± 27 + é»ç³ 4ï¼æ¯å¦ç±æä»£åæ¸
çï¼å¾
ç¨æ·ç¡®è®¤ï¼è§ 1.8 / æµè¯æ¥å P3ï¼ã |
| New file |
| | |
| | | # å¸å·ææ¥å¡«æ¥å£å¾ä¸ç»ä¸æ¨¡æ¿ï¼2026-09-20ï¼ |
| | | |
| | | > èµ·å ï¼ç¨æ·æé®ãä»ä»¬å¯¼å
¥çæ°æ®æåªä¸ªæ ¼å¼æ¥æå¥½ï¼è¦ä¸è¦çæä¸¤ä¸ªæ¨¡æ¿ï¼å®¢è¿ç«ä¸ä¸ªãç©æµåä¸ä¸ªï¼ï¼ |
| | | > è¿å ä¸ªè¡¨çæ´æ°å
¶å®å¾ç®åââæé¡¹ç®åç§°æ´æ°æ±æ»è¡¨æå®ææ ãæ°å¢é¡¹ç®å°±æ°å¢å°æç»è¡¨ï¼ |
| | | > é¢å®ææ±æ»è¡¨åæç»è¡¨æ¹å¼ä¸æ ·ï¼å©ä¸ä¸å¼ 表项ç®åºå®åªæ´æ°ææ ââ为ä»ä¹ç°å¨å¼å¾æç¹å¤æäºï¼ã |
| | | |
| | | ## ä¸ãç»è®ºå
说 |
| | | |
| | | 1. **ä½ çå¿æºæ¨¡åæ¯å¯¹ç**ï¼èä¸å°±æ¯éæ±ææ¡£ãæèµææ¥æ°æ®å¤çä¸å¤è¡¨æ´æ°éæ±è¯´æãéåç䏿¥ï¼ |
| | | - Step1 ææ¥ â ä¸¤å¼ æç»è¡¨ï¼ä»¥**项ç®åç§°**为é®ï¼å·²æâæ´æ° 5 åï¼æ²¡æâæ°å¢æ´è¡ï¼ |
| | | - Step2 æç»è¡¨ â å
¨çé¢å®æè®¡åè¿åº¦æ
嵿±æ»ï¼ååæ´æ° 4 é¡¹ï¼æ²¡æçæ°å¢ï¼æ¯çæèææ¥æ²¡æçä¿æåå¼ï¼ |
| | | - Step3 æç»è¡¨ â ä¸å¼ åºå®é¡¹ç®è¡¨ï¼åäºäºè§åç©æµ / 亿å
æèµé¡¹ç® / ç»æµå¼ºå¿ï¼ï¼é¡¹ç®æ¸
åä¸å¨ï¼åªæ´æ° 3 é¡¹ææ ã |
| | | 2. **夿ä¸å¨ã表ãï¼å¨ãæºã**ãç¨åºä¾§è¦å¤çç麻ç¦å
¨é¨æ¥èªå¸å·æ¥ä¸æ¥çåå§è¡¨æ ¼æ ¼å¼ä¸ç»ä¸ï¼ä¸æ¥èªæ±æ»è§åæ¬èº«ã |
| | | 3. **å»ºè®®ä» 9 æèµ·ç»ä¸ç¨ä¸¤ä»½æ¨¡æ¿**ï¼å®¢è¿ç«åºãç©æµååºåä¸ä»½ï¼ã模æ¿å·²ç»åå¥½ï¼ |
| | | - `docs/æèµ/模æ¿/模æ¿_å¸å·ææ¥_客è¿ç«åº.xlsx` |
| | | - `docs/æèµ/模æ¿/模æ¿_å¸å·ææ¥_ç©æµååº.xlsx` |
| | | |
| | | ## äºã两份模æ¿é¿ä»ä¹æ · |
| | | |
| | | åªæä¸ä¸ªæ°æ®é¡µãææ¥ã+ ä¸ä¸ªãå¡«æ¥è¯´æã页ã第 4 è¡æ¯è¡¨å¤´ï¼ä¸è¡ä¸æ¡é¡¹ç®ï¼å
± 17 åï¼ |
| | | |
| | | | å | 表头 | ç¨åºéçå»å | |
| | | | --- | --- | --- | |
| | | | A | åºå· | ä»
ç¨äºè¯å«å¸å·å°èè¡/å计è¡ï¼ä¸åä¸å¹é
| |
| | | | B | å¿ï¼å¸ãåºï¼ | 项ç®ä¸»æ¡£ `county`ï¼å
¨çæ±æ»è¡¨è¦æ¾ç¤ºè¿ä¸åï¼ | |
| | | | C | **项ç®åç§°åç«çº§** | **å¹é
é®**ï¼å¸å· + ç±»å« + 项ç®åç§°ï¼ | |
| | | | D | æèµå»ºè®¾åä½åç§° | 主档 `builder_name` | |
| | | | E | 建设æ§è´¨ | 主档 `construct_nature`ï¼ä¸æï¼æ°å»º/ç»å»º/æ¹æ©å»º/æ¹å»ºï¼ | |
| | | | F | å¼å·¥å¹´ | 主档 `start_time` | |
| | | | G | 竣工年 | 主档 `end_time` | |
| | | | H | è®¡åæ»æèµï¼ä¸å
ï¼ | 主档 `total_investment` | |
| | | | I | èªå¼å§å»ºè®¾ç´¯è®¡å®ææèµï¼ä¸å
ï¼ | **彿æåº¦æ°** | |
| | | | J | æ¬å¹´è®¡åæèµï¼ä¸å
ï¼ | **彿æåº¦æ°** | |
| | | | K | èªå¹´åç´¯è®¡å®ææèµï¼ä¸å
ï¼ | **彿æåº¦æ°** | |
| | | | L | å
¶ä¸ï¼æ¬æå®ææèµï¼ä¸å
ï¼ | **彿æåº¦æ°** | |
| | | | M | å»ºè®¾é¶æ®µ | **彿æåº¦æ°** | |
| | | | N | 形象è¿åº¦ | **彿æåº¦æ°** | |
| | | | O | 工坿¹å¤æå· | 主档 `approval_gk` | |
| | | | P | å设/æ½å·¥å¾æ¹å¤æå· | 主档 `approval_cs` | |
| | | | Q | 夿³¨ | ä¸åæ° | |
| | | |
| | | - **主档åï¼AãBãDãEãFãGãHãOãPï¼**ï¼ç¬¬ä¸æ¬¡å»ºæ¡£æ¶åå
¥ï¼ä¹ååªè¦é¡¹ç®åä¸åå°±ä¸å¨ï¼ |
| | | - **æåº¦æ°ï¼IãJãKãLãMãNï¼**ï¼æ¯ä¸ªææ¥å¤å°åå¤å°ï¼åä¸ï¼é¡¹ç®ï¼æ¥è¡¨æï¼è¦çå¼éå»ºï¼ |
| | | - **ã项ç®åç§°åç«çº§ãæ¯å¯ä¸å¹é
é®**ï¼æ¹ä¸ä¸ªå = æ°å»ºä¸ä¸ªé¡¹ç®ï¼æä»¥è¦æ±ä¸æ¹å¤åç§°ä¸åä¸å·®ï¼ |
| | | - ãå¡«æ¥è¯´æã页åäº 11 æ¡è¦æ±ï¼ä¸ä»½æä»¶åªæ¾æ¬å¸å·ãæä»¶å带å¸å·åãæ°å¼ä¸å¸¦å符ã |
| | | å¿ï¼å¸ãåºï¼å¿
å¡«ã建设æ§è´¨åªè½åéä¸ãæ°å¢é¡¹ç®ç´æ¥å è¡ãéèè¡ä¸æ¾æ°æ®ãå计è¡å¯ä¸å¡«çï¼ã |
| | | |
| | | ## ä¸ã为ä»ä¹ç°å¨æè§å¤æï¼4 个çå®åå ï¼é½å¨è¾å
¥ä¾§ï¼ |
| | | |
| | | 1. **çå¼ä¸ç»ä¸**ï¼27 份å¸å·ææ¥éï¼20 份ä¸çç»ä¸æ¨¡æ¿ä¸è´ï¼7 份æå·®å¼ââ |
| | | éå·å¤ä¸ä¸ª Sheet2ãç¥åæ¶/æ½æ±/è¥é³ææå¤ä¸ªåæé¡µç¾ãè¥é³æ´ä½å³ç§» 1 åã |
| | | æ©æ½/é»ç³åå¹¶è¡¨å¤´ãæ¦æ±ï¼åå±±/æ±å£ï¼åªæ¥ä¸¤ä¸ªé¡¹ç®çç®è¡¨ãè¯¦è§ |
| | | `docs/æèµ/è¾åº/å¸å·ææ¥æ ¼å¼å·®å¼æ¥å_2026-07.md`ãç¨åºä¸ºäºè¯»å
¨ï¼åªè½ä¸ä¸ªçå¼ä¸ä¸ªå
åºåæ¯ã |
| | | 2. **ä¸ä¸ªæä»¶éæ··å¤ä¸ªå¸å·**ï¼ãæ¹åçåå °äº¤éç©æµåºç¡è®¾æ½æèµç»è®¡æ±æ»è¡¨ï¼ææ¥ï¼ãä¸ä¸ªé¡µç¾æ¶äºå
¨çï¼ |
| | | 2026 å¹´ 8 æè¿ä»½ 38 è¡éåªæ **7 è¡æ¯åå °**ï¼å¦å¤ **27 è¡æ¦æ± + 4 è¡é»ç³**ã |
| | | ç¨åºæ¯ææãå°èè¡ã忢å¸å·ï¼è¿æ¯ææåçåè½ï¼ï¼æä»¥è½è¯»è¿æ¥ï¼ä½ä»£ä»·æ¯ï¼ |
| | | **åªè¦é导 8 æç©æµï¼è¿ 31 个项ç®å°±ä¼éæ°å»ºå°æ¦æ±/é»ç³åä¸**ï¼ä»å¤©ååå½é导æ¶å¤ç°ï¼å·²å次æ¸
é¤ï¼è§æµè¯æ¥å P3ï¼ã |
| | | 3. **é¡¹ç®æ¸
åæä¸¤ä¸ªæ¥æº**ï¼ä¸æ¯å¸å·å½ææ¥ä¸æ¥çï¼äºæ¯æ¯ç/åºéå·²ç»æçï¼å¦é¢å®ææ¯çéçæ¦æ±ç©æµè¡ï¼ã |
| | | äºæ¯äº§çãææ»æèµãæ²¡ææ¬ææåº¦æ°ãç项ç®ï¼è¦ä¸è¦è¡¥è¿å°è®¡/å计就æäºè¦åç¬å³ççäºã |
| | | 4. **åä½ç½®é å
åº**ï¼æ©æå®ç°æãèªå¹´å累计 = èªå¼å§å»ºè®¾ç´¯è®¡ + 2 åãè¿ç±»ååºæ¨ç®ï¼ |
| | | å¸å·ä¸æªåå°±å¾åå 䏿¡å
åºââè¿æ¯ãçãåºæ¥çå¤æåº¦ï¼ä¸æ¯ä¸å¡å¤æåº¦ã |
| | | |
| | | ## åãæ¢æç»ä¸æ¨¡æ¿åï¼è¿è¦å®æ» 3 ä»¶äº |
| | | |
| | | 模æ¿è§£å³çæ¯ãæä¹è¯»ããä¸é¢ 3 ä»¶äºå®ä¸æ¥ï¼æ´æ¡é¾å°±æ²¡ææ§ä¹äºï¼ |
| | | |
| | | | # | å¾
å®äºé¡¹ | 建议 | |
| | | | --- | --- | --- | |
| | | | 1 | å¹´åº¦é¡¹ç®æ¸
å以è°ä¸ºåï¼åºéæä»ä¹å°±åºä»ä¹ï¼è¿æ¯ä»¥ã年度é¢å®æè®¡å表ã为åï¼ | 以年度é¢å®æè®¡å表为åï¼éæ¯çä¸åæåç¬å»ºä¸å¼ ã年度é¢å®æè®¡åã表ï¼ï¼æ¯æåªæ´æ°ææ | |
| | | | 2 | æå¸å·å½æ**没æ¥**æä¹åï¼ | 该å¸å·ææ ç空 + 导åºåå¼¹çªååºãæªæ¥éå¸å·ãï¼ä¸é»æå¯¼åº | |
| | | | 3 | å¸å·**æ°å¢**çé¡¹ç®æå°åªï¼ | æå°è¯¥å¸å·ãé¢å®æè®¡åå
ãå°èæ«å°¾ï¼è®¡åå¤çåç¬æ 注ï¼å¯¼åä¸ä»åºä½ææ¾åºå«äºè®¡åå
| |
| | | |
| | | ## äºãè¿æ¸¡å®æä¸ä¸ä¸æ¥ |
| | | |
| | | - **8 æå以å**ï¼å·²ææ§æ ¼å¼å¯¼å
¥å®æ¯ï¼ç¨åºç»§ç»å
¼å®¹æ§çå¼ï¼**䏿¹ãä¸é导**ï¼8 æåå °æºæä»¶æ¸
çå¦è¡ç¡®è®¤ï¼ã |
| | | - **9 æèµ·**ï¼å¸å·æç»ä¸æ¨¡æ¿å¡«æ¥ï¼å»ºè®®åå ä¸ä¸ªã模æ¿ä½æ£ãââ导å
¥æ¶æ ¡éªè¡¨å¤´æ¯å¦ä¸ºæ¬æ¨¡æ¿ 17 åï¼ |
| | | æ¯åèµ°ãæè¡¨å¤´åæ°ãçç´è·¯ï¼ä¸æ¯å**å¼¹çªæç¤º**ï¼åªä¸å对ä¸ä¸ï¼ï¼è䏿¯ç»§ç»çåä½ç½®ã |
| | | - è¿æ ·è§£æé»è¾å¯ä»¥éåæãæè¡¨å¤´ååå¼ãï¼ç°æé£äºå®¹éå
åºåæ¯å¯ä»¥éæ¥ä¸çº¿ï¼å¤æåº¦èªç¶å°±é䏿¥äºã |
| New file |
| | |
| | | ## å¤ä»½æ¶é´ 2026-09-20 åå ï¼åå °æ±æ»è¡¨(2026å¹´5/7/8æç)å
嫿¦æ±27个+é»ç³4个éåå °è项ç®ï¼2026-08-26 11:57 éãå¸å·å表æ¹é导å
¥ãå
¥åºï¼ç°æç¨æ·è¦æ±æ¸
é¤ |
| | | |
| | | ## investment_project |
| | | id project_name category city county builder_name construct_nature start_time end_time total_investment is_billion is_county is_five_year source import_batch_id created_at updated_at |
| | | 122 髿¡¥è´§è¿ç« ç©æµååº æ¦æ±å¸ NULL æ¦æ±ä¸è¥¿æ¹ä¿ç¨ç©æµæèµæéå
¬å¸ ç»å»º 2006 2020 45482 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 16:37:31 |
| | | 123 èç°ç©æµåºå° ç©æµååº æ¦æ±å¸ NULL æ¦æ±èç°ç©æµåºå°è¡ä»½æéå
¬å¸ ç»å»º 2011 2015 110000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 124 æ±å£åå½é
å¤å¼èè¿ç©æµæ¸¯ ç©æµååº æ¦æ±å¸ NULL æ¹åç交éæèµæéå
¬å¸ æ°å»º 2016 2020 300000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 125 æ¦æ±æ¦æ¹åå¸é
éä¸å¿ ç©æµååº æ¦æ±å¸ NULL æ¹åèå
å产åå·é¾ç©æµå
¬å¸ æ°å»º 2015 2017 30000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 126 æ¦æ±æ·å©éè¾¾ç°ä»£ç©æµ ç©æµååº æ¦æ±å¸ NULL æ¦æ±æ·å©éè¾¾ç©æµæéå
¬å¸ ç»å»º 2013 2016 50000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 127 æ¦æ±éè£
ç®±å
¬è·¯ä¸è½¬ä¸å¿ ç©æµååº æ¦æ±å¸ NULL æ¹åçæ¸¯åéå¢ æ°å»º 2016 2020 75000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 128 æ¦æ±ä¸è¥¿æ¹ç©æµåºå° ç©æµååº æ¦æ±å¸ NULL æ±éç½®ä¸è¡ä»½æéå
¬å¸ æ°å»º 2012 2016 130000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 129 æ¦æ±ç©æµäº¤ææï¼æ»é¨ï¼ ç©æµååº æ¦æ±å¸ NULL æ¦æ±äº¤æç©æµäº¤æä¸å¿æéå
¬å¸ æ°å»º 2016 2020 270000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 130 æ¦æ±ç¾å®ç°ä»£ç©æµå ç©æµååº æ¦æ±å¸ NULL æ¦æ±ç¾å®å¨è¿æéå
¬å¸ æ°å»º 2014 2016 110000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 131 åå°é港ä¸å¿ ç©æµååº æ¦æ±å¸ NULL åå°é港ä¸å¿æèµæéå
¬å¸ æ°å»º 2014 2017 400000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 132 æ¦æ±æ°æ¸¯é³é»æ¸¯å£ç©æµå ç©æµååº æ¦æ±å¸ NULL æ¦æ±æ°æ¸¯é³é»ä¿ç¨ååºç®¡çæéå
¬å¸ æ°å»º 2014 2017 108994 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 133 æµ·åæå½é
绿è²å港 ç©æµååº æ¦æ±å¸ NULL æ¦æ±åå¸åæµ·åæå产åç©æµæéå
¬å¸ æ°å»º 2014 2020 800000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 134 æ¦æ±ï¼æ±å¤ï¼å¾·é¦ç©æµäº§ä¸å ç©æµååº æ¦æ±å¸ NULL å¾·é¦ç©æµ æ°å»º 2015 2017 137000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 135 æ¦æ±åè¿è¾¾ç©æµåºå°é¡¹ç® ç©æµååº æ¦æ±å¸ NULL æ¦æ±åè¿è¾¾ç©æµæéå
¬å¸ æ°å»º 2015 2017 30000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 136 鿏¯æ°åºæ±½è½¦ç©æµå ç©æµååº æ¦æ±å¸ NULL æ¦æ±æ°é¸¿çç©æµæéå
¬å¸ æ°å»º 2015 2017 64000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 137 顺丰é鿦æ±çµååå¡ç©æµä¸å¿ ç©æµååº æ¦æ±å¸ NULL æ¦æ±ä¸°æ³°çµå产ä¸å管çæéå
¬å¸ æ°å»º 2015 2017 100000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 138 å´å®¶å±±éè·¯ç©æµå ç©æµååº æ¦æ±å¸ NULL æ¦æ±éè·¯å± æ°å»º 2015 2018 35000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 139 æåºè¾¾é«åå·¥ç©æµ ç©æµååº æ¦æ±å¸ NULL æ¹åéè
¾å
´æéå
¬å¸ æ°å»º 2013 2018 204000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 140 䏿¹ç»¼åä¿ç¨åºé£åä¿ç¨ç©æµå ç©æµååº æ¦æ±å¸ NULL æ¦æ±éå®ç»¼åä¿ç¨å屿éå
¬å¸ æ°å»º 2015 2017 124000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 141 京ä¸åååä¸åºåæ»é¨ ç©æµååº æ¦æ±å¸ NULL å京京ä¸ä¸çºªè´¸ææéå
¬å¸ æ°å»º 2014 2018 700000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 142 äºèç½+ç©æµä¿¡æ¯äº¤æå¹³å° ç©æµååº æ¦æ±å¸ NULL æ¦æ±æ·å©ç©æµæéå
¬å¸ æ°å»º 2015 2016 31792 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 143 é»ç³æ°å°çµååå¡ç©æµä¸å¿ ç©æµååº æ¦æ±å¸ NULL æ¦æ±é«æ¡¥æ°å°ç©æµæéå
¬å¸ æ°å»º 2015 2016 200000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 144 æ±å£åå
¬éèè¿ä¸å¿ ç©æµååº æ¦æ±å¸ NULL çäº¤æ æ°å»º 2016 2018 200000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 145 æ±å£å髿°ç©æµç¤ºèåï¼æ¦æ¹è´§è¿ç«ï¼ ç©æµååº æ¦æ±å¸ NULL æ¹åçæ±½è½¦è¿è¾æ»å
¬å¸ æ°å»º 2012 2017 114500 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 146 å山货è¿ç« ç©æµååº æ¦æ±å¸ NULL æ¦æ±å®æ¹¾å½é
ç©æµæéå
¬å¸ æ°å»º 2013 2015 102000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 147 æ±å£åéè·¯ç©æµä¸å¿ï¼2æï¼ ç©æµååº æ¦æ±å¸ NULL æ¦æ±ä¸åç©æµæéå
¬å¸ æ°å»º 2015 2017 88500 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 148 è¶æµ·åä¸ä¾åºé¾æ»é¨åºå° ç©æµååº æ¦æ±å¸ NULL æ·±å³å¸è¶æµ·å
¨çç©æµæéå
¬å¸ æ°å»º 2015 2018 150000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-01 15:54:17 |
| | | 149 é»ç³ç½æ¡¥ç©æµå ç©æµååº é»ç³å¸ NULL æ¹å天海çè¾¾ç©æµæéå
¬å¸ æ°å»º 2012 2017 39119 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-19 00:11:41 |
| | | 150 é»ç³è±æ¹ç©æµä¸å¿ ç©æµååº é»ç³å¸ NULL æ¹å广åç©æµæéå
¬å¸ æ°å»º 2012 2016 23586 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-19 00:11:41 |
| | | 151 é»ç³æ£ç洲综åç©æµåä¸æï¼æ£çæ´²ä¿ç¨ç©æµä¸å¿ï¼ ç©æµååº é»ç³å¸ NULL é»ç³æ¸¯éç©æµå屿éå
¬å¸ æ°å»º 2013 2018 28679 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-19 00:11:41 |
| | | 152 鳿°å¿ç©æµä¸å¿ ç©æµååº é»ç³å¸ NULL 鳿°å¿äº¤éæèµå
¬å¸ æ°å»º 2015 2018 23000 0 0 0 å¸å·å表 NULL 2026-08-26 11:57:10 2026-09-19 00:11:41 |
| | | |
| | | ## investment_monthly |
| | | id report_period project_id project_name year_plan year_cum month_done start_cum progress_stage LEFT(m.progress_desc,60) building_area created_at |
| | | 3000 2026-08 122 髿¡¥è´§è¿ç« 0 0 0 40148 NULL 䏿è§åä¸ NULL 2026-09-19 00:20:08 |
| | | 3001 2026-08 123 èç°ç©æµåºå° 1500 500 500 89608 NULL åå¸é
éä¸å¿å»ºè®¾å·²å®æè³100%ï¼ç¸å
³å¸æ¿é
å¥å·¥ç¨å®æ100%ãç°å ä¸ç¯çº¿è¾
é徿¶æè¿äºå®è´ä½¿è¯ä»¶åçå·¥ä½å»¶æåå¾ç®äºæ NULL 2026-09-19 00:20:08 |
| | | 3002 2026-08 124 æ±å£åå½é
å¤å¼èè¿ç©æµæ¸¯ 1000 0 0 0 NULL æ´½è°ä¸ NULL 2026-09-19 00:20:08 |
| | | 3003 2026-08 125 æ¦æ±æ¦æ¹åå¸é
éä¸å¿ 6000 0 0 13000 NULL ä»åºå¨å»ºä¸ NULL 2026-09-19 00:20:08 |
| | | 3004 2026-08 126 æ¦æ±æ·å©éè¾¾ç°ä»£ç©æµ 14000 1100 1100 26000 NULL ç®åäºæå¨åçå¼å·¥åæç»ï¼å·²å®æåºååå°æè¿ãå¹³æ´å·¥ä½ã NULL 2026-09-19 00:20:08 |
| | | 3005 2026-08 127 æ¦æ±éè£
ç®±å
¬è·¯ä¸è½¬ä¸å¿ 1000 0 0 0 NULL ç±æ¦æ±æ°æ¸¯å§çµå¤´æ¦æ±æ°æ¸¯ç©ºæ¸¯ç»¼åä¿ç¨åºæ©å¤§èå´ç认è¯é®é¢ï¼å¯¹æ¥æ±åéè·¯äºæå»ºè®¾ï¼æ¯ææ°æ¸¯ä¼ä¸åå±çãç°å·²æ£å¼å¯å¨è¯¥é¡¹ç®ç NULL 2026-09-19 00:20:08 |
| | | 3006 2026-08 128 æ¦æ±ä¸è¥¿æ¹ç©æµåºå° 12000 1000 1000 71657 NULL åæåºåç7#楼å°é¡¶ã6#楼äºå±ç»æã5#楼å°ä¸å®¤å°é¡¶ã4#楼æ£è´é¶ï¼å车åºBåºæ½å·¥ã NULL 2026-09-19 00:20:08 |
| | | 3007 2026-08 129 æ¦æ±ç©æµäº¤ææï¼æ»é¨ï¼ 20000 0 0 1000 NULL 项ç®å¯è¡æ§ç ç©¶æ¥ååå»ºçæ¹æ¡è®¾è®¡æ£å¨ç¼å¶ä¸ NULL 2026-09-19 00:20:08 |
| | | 3008 2026-08 130 æ¦æ±ç¾å®ç°ä»£ç©æµå 0 0 0 30156 NULL 2#楼å
é¨è£
ä¿®å®æ¯ï¼å·²å¼å§è¯è¿è¥ï¼1#楼å¼å§ææ¡©ï¼ç©æµå°åå·²å¼å§è®¾è®¡ï¼å
´å»ºåè½¦åº NULL 2026-09-19 00:20:08 |
| | | 3009 2026-08 131 åå°é港ä¸å¿ 20000 400 400 51900 NULL æ£å¨è¿è¡ååºéè·¯éºè®¾ï¼å´ç½å·¥ç¨ NULL 2026-09-19 00:20:08 |
| | | 3010 2026-08 132 æ¦æ±æ°æ¸¯é³é»æ¸¯å£ç©æµå 30000 865.6 865.6 44157 NULL 宿ååºåå°å¹³æ´ãå°ä¸è®¾æ½ãååºéè·¯ãæ¡©åºåå´ç½çåºç¡æ½å·¥ NULL 2026-09-19 00:20:08 |
| | | 3011 2026-08 133 æµ·åæå½é
绿è²å港 36000 2865.2 2865.2 66092.26 NULL 21æ è¬è交æå¤§å
ãé
奿¥¼Aæ åçµåä¸å¿å·¥ç¨ç«£å·¥äº¤ä»å¹¶å¼ä¸ãç°å·²å¯å¨äºæå»ºè®¾ NULL 2026-09-19 00:20:08 |
| | | 3012 2026-08 134 æ¦æ±ï¼æ±å¤ï¼å¾·é¦ç©æµäº§ä¸å 1000 0 0 0 NULL æå
³æç»å·²åé½ï¼å·²å®æåå°æææå·¥ä½ NULL 2026-09-19 00:20:08 |
| | | 3013 2026-08 135 æ¦æ±åè¿è¾¾ç©æµåºå°é¡¹ç® 0 0 0 5000 NULL ç®åå·²åå¾åå°149.9亩ï¼åå°è¯æ£å¨åçä¸ï¼å¼å±åºå¹³å·¥ä½ NULL 2026-09-19 00:20:08 |
| | | 3014 2026-08 136 鿏¯æ°åºæ±½è½¦ç©æµå 0 0 0 0 NULL 已宿å°è´¨åå¯ NULL 2026-09-19 00:20:08 |
| | | 3015 2026-08 137 顺丰é鿦æ±çµååå¡ç©æµä¸å¿ 0 0 0 10000 NULL 1ã项ç®ç¨å°å·²è·æ¹åï¼è¿å
¥ä¸è¥¿æ¹åºåå°å¨å¤ä¸å¿ï¼åâæææâåæåå¤ã NULL 2026-09-19 00:20:08 |
| | | 3016 2026-08 138 å´å®¶å±±éè·¯ç©æµå 0 0 0 5000 NULL 宿ååºé路建设ï¼äºå±åå
¬æ¥¼å°é¡¶ NULL 2026-09-19 00:20:08 |
| | | 3017 2026-08 139 æåºè¾¾é«åå·¥ç©æµ 0 0 0 25888 NULL è¯è¿è¥ NULL 2026-09-19 00:20:08 |
| | | 3018 2026-08 140 䏿¹ç»¼åä¿ç¨åºé£åä¿ç¨ç©æµå 0 0 0 59000 NULL å
³å
241亩ç¨å°å·²å¼å·¥å»ºè®¾ NULL 2026-09-19 00:20:08 |
| | | 3019 2026-08 141 京ä¸åååä¸åºåæ»é¨ 20000 0 0 87800 NULL 已宿1-6#åæ¿ä¸»ä½é¢ç»æå®è£
ï¼è®¾å¤å®è£
è°è¯ï¼1#ã4#åæ¿å´æ¤ç»æå®è£
ï¼é£å å°é¡¶ï¼å®¿è1#楼æ½å·¥å®æ5å±ï¼å®¿èå°ä¸å®¤ NULL 2026-09-19 00:20:08 |
| | | 3020 2026-08 142 äºèç½+ç©æµä¿¡æ¯äº¤æå¹³å° 0 0 0 8000 NULL 已建æ1000ä½åº§å¸åæå
¥6000ä¸å
NULL 2026-09-19 00:20:08 |
| | | 3021 2026-08 143 é»ç³æ°å°çµååå¡ç©æµä¸å¿ 0 2000 2000 2000 NULL æ£å¨è¿è¡æè¿ãåºå¹³ãæ¸
æ·¤æ¢å¡«ãæ¸
é¤èæ¤åçåºå¹³å·¥ä½ NULL 2026-09-19 00:20:08 |
| | | 3022 2026-08 144 æ±å£åå
¬éèè¿ä¸å¿ 20000 0 0 0 NULL æ´½è°ä¸ NULL 2026-09-19 00:20:08 |
| | | 3023 2026-08 145 æ±å£å髿°ç©æµç¤ºèåï¼æ¦æ¹è´§è¿ç«ï¼ 15000 0 0 11629 NULL å®æåæ 1.25ä¸å¹³æ¹ç±³ä¸»ä½å·¥ç¨ï¼å
¶ä½é¡¹ç®ç¨å°æ£å¨è½å®ä¸ NULL 2026-09-19 00:20:08 |
| | | 3024 2026-08 146 å山货è¿ç« 1000 0 0 59050 NULL ä¼ä¸è¿åºè¯è¿è¥ NULL 2026-09-19 00:20:08 |
| | | 3025 2026-08 147 æ±å£åéè·¯ç©æµä¸å¿ï¼2æï¼ 30000 0 0 0 NULL æ£å¨è¿è¡äºææ½å·¥è®¾è®¡åæ½å·¥æææ å·¥ä½ NULL 2026-09-19 00:20:08 |
| | | 3026 2026-08 148 è¶æµ·åä¸ä¾åºé¾æ»é¨åºå° 30000 0 0 0 NULL åºå¹³å
¨é¨å®æ NULL 2026-09-19 00:20:08 |
| | | 1624 2026-06 149 é»ç³ç½æ¡¥ç©æµå 11200 69 69 18202 NULL éè£
箱设å¤å®è£
NULL 2026-08-26 12:25:57 |
| | | 1998 2026-07 149 é»ç³ç½æ¡¥ç©æµå 11200 69 69 18202 NULL éè£
箱设å¤å®è£
NULL 2026-09-01 16:37:32 |
| | | 3027 2026-08 149 é»ç³ç½æ¡¥ç©æµå 11200 69 69 18202 NULL éè£
箱设å¤å®è£
NULL 2026-09-19 00:20:08 |
| | | 1625 2026-06 150 é»ç³è±æ¹ç©æµä¸å¿ 1700 0 0 20300 NULL åºæ¬å»ºæï¼æ£å¨è¿è¡äºæç»¼å楼å¤å¢è£
ä¿® NULL 2026-08-26 12:25:57 |
| | | 1999 2026-07 150 é»ç³è±æ¹ç©æµä¸å¿ 1700 0 0 20300 NULL åºæ¬å»ºæï¼æ£å¨è¿è¡äºæç»¼å楼å¤å¢è£
ä¿® NULL 2026-09-01 16:37:32 |
| | | 3028 2026-08 150 é»ç³è±æ¹ç©æµä¸å¿ 1700 0 0 20300 NULL åºæ¬å»ºæï¼æ£å¨è¿è¡äºæç»¼å楼å¤å¢è£
ä¿® NULL 2026-09-19 00:20:08 |
| | | 1626 2026-06 151 é»ç³æ£ç洲综åç©æµåä¸æï¼æ£çæ´²ä¿ç¨ç©æµä¸å¿ï¼ 5000 0 0 23730 NULL ä¿ç¨ç©æµä¸å¿éè¿å½å®¶éªæ¶ NULL 2026-08-26 12:25:57 |
| | | 2000 2026-07 151 é»ç³æ£ç洲综åç©æµåä¸æï¼æ£çæ´²ä¿ç¨ç©æµä¸å¿ï¼ 5000 0 0 23730 NULL ä¿ç¨ç©æµä¸å¿éè¿å½å®¶éªæ¶ NULL 2026-09-01 16:37:32 |
| | | 3029 2026-08 151 é»ç³æ£ç洲综åç©æµåä¸æï¼æ£çæ´²ä¿ç¨ç©æµä¸å¿ï¼ 5000 0 0 23730 NULL ä¿ç¨ç©æµä¸å¿éè¿å½å®¶éªæ¶ NULL 2026-09-19 00:20:08 |
| | | 1627 2026-06 152 鳿°å¿ç©æµä¸å¿ 1000 0 0 1332 NULL åæå·¥ä½ NULL 2026-08-26 12:25:57 |
| | | 2001 2026-07 152 鳿°å¿ç©æµä¸å¿ 1000 0 0 1332 NULL åæå·¥ä½ NULL 2026-09-01 16:37:32 |
| | | 3030 2026-08 152 鳿°å¿ç©æµä¸å¿ 1000 0 0 1332 NULL åæå·¥ä½ NULL 2026-09-19 00:20:08 |
| | | |
| | | ## 追å ï¼ä¼ªé¡¹ç®ãåããã计ã(å¸å®å¸å®¢è¿ç«åº, id=229, è§£æåè®¡è¡æ¶è¯¯å»º, æ æåº¦æ°) |
| | | id project_name city category source total_investment created_at |
| | | 229 å 计 å¸å®å¸ 客è¿ç«åº å¸å·å表 13727 2026-09-16 15:07:54 |
| | |
| | | project.setProjectName(nt); |
| | | project.setCategory(category); |
| | | project.setCity(currentCity); |
| | | String countyCell = cellStr(row, col.get("county")); |
| | | if (countyCell != null && !countyCell.trim().isEmpty()) project.setCounty(countyCell.trim()); |
| | | project.setBuilderName(cellStr(row, col.get("builder"))); |
| | | project.setConstructNature(cellStr(row, col.get("nature"))); |
| | | project.setStartTime(investTime(cellStr(row, col.get("start")))); |
| | |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | boolean hasName = false; |
| | | int headerCells = 0; |
| | | for (int c = 0; c <= row.getLastCellNum(); c++) { |
| | | String v = cellStr(row, c); |
| | | if (v != null && v.contains("项ç®åç§°")) { hasName = true; break; } |
| | | if (v == null) continue; |
| | | String t = v.trim(); |
| | | if (t.isEmpty() || t.length() > 20) continue; // è¯´ææ§é¿å¥ä¸ç®è¡¨å¤´å段 |
| | | String k = investHeaderKey(t); |
| | | if (k == null) continue; |
| | | headerCells++; |
| | | if ("name".equals(k)) hasName = true; |
| | | } |
| | | if (!hasName) continue; |
| | | // ç表头è¡è³å°æ 2 个çè¡¨å¤´åæ®µï¼åªæä¸æ ¼é¿å¥å«ã项ç®åç§°ãç说æé¡µä¼è¢«æé¤ |
| | | if (!hasName || headerCells < 2) continue; |
| | | Map<Integer, String> colTexts = new HashMap<>(); |
| | | int scanEnd = investHeaderScanEnd(sh, r, row); |
| | | for (int rr = r; rr <= scanEnd; rr++) { |
| | |
| | | } |
| | | Map<String, Integer> col = new HashMap<>(); |
| | | for (Map.Entry<Integer, String> e : colTexts.entrySet()) { |
| | | int c = e.getKey(); |
| | | String v = e.getValue(); |
| | | if (v.contains("项ç®åç§°")) col.putIfAbsent("name", c); |
| | | else if (v.contains("æèµå»ºè®¾") || v.contains("建设åä½") || v.contains("项ç®ä¸ä¸»")) col.putIfAbsent("builder", c); |
| | | else if (v.contains("建设æ§è´¨")) col.putIfAbsent("nature", c); |
| | | else if (v.contains("å¼å·¥")) col.putIfAbsent("start", c); |
| | | else if (v.contains("竣工") || v.contains("建æ")) col.putIfAbsent("end", c); |
| | | else if ((v.contains("è®¡åæ»æèµ") || v.contains("æ»æèµ")) && !v.contains("累计")) col.putIfAbsent("total", c); |
| | | else if (v.contains("èªå¼å§å»ºè®¾")) col.putIfAbsent("startcum", c); |
| | | else if (v.contains("æ¬å¹´è®¡å")) col.putIfAbsent("yearplan", c); |
| | | else if (v.contains("èªå¹´å累计")) col.putIfAbsent("yearcum", c); |
| | | else if (v.contains("æ¬æå®æ")) col.putIfAbsent("monthdone", c); |
| | | else if (v.contains("å»ºè®¾é¶æ®µ")) col.putIfAbsent("stage", c); |
| | | else if (v.contains("形象è¿åº¦") || v.contains("建设è¿å±")) col.putIfAbsent("desc", c); |
| | | else if (v.contains("å·¥å¯") && !v.contains("项ç®åç§°")) col.putIfAbsent("gk", c); |
| | | else if (v.contains("å设") && !v.contains("项ç®åç§°")) col.putIfAbsent("cs", c); |
| | | else if (v.contains("建çé¢ç§¯") && !v.contains("æ°å¢")) col.putIfAbsent("area", c); |
| | | String k = investHeaderKey(e.getValue()); |
| | | if (k != null) col.putIfAbsent(k, e.getKey()); |
| | | } |
| | | if (!col.containsKey("name")) continue; |
| | | for (int c = 0; c <= row.getLastCellNum(); c++) { |
| | |
| | | if (dc <= row.getLastCellNum()) col.put("desc", dc); |
| | | } |
| | | for (String k : new String[]{"builder", "nature", "start", "end", "total", "startcum", |
| | | "yearplan", "yearcum", "monthdone", "stage", "desc", "gk", "cs", "area"}) { |
| | | "yearplan", "yearcum", "monthdone", "stage", "desc", "gk", "cs", "area", "county"}) { |
| | | col.putIfAbsent(k, -1); |
| | | } |
| | | col.put("headerRow", r); |
| | |
| | | return null; |
| | | } |
| | | |
| | | /** å个表头åå
æ ¼ -> åæ®µé®ï¼null è¡¨ç¤ºä¸æ¯è¡¨å¤´å段ï¼ï¼ä¾è¡¨å¤´è¡å¤å®ä¸åæ å°å
±ç¨ */ |
| | | private String investHeaderKey(String v) { |
| | | if (v == null) return null; |
| | | String flat = v.replace(" ", ""); |
| | | if (v.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"; |
| | | return null; |
| | | } |
| | | |
| | | /** è¡¨å¤´ææ¬æ«æä¸çï¼é»è®¤è¡¨å¤´è¡ +3ï¼è¥ã项ç®åç§°ãåé¦ä¸ªæ°æ®è¡æ´é ä¸ï¼åæ©å±å°æ°æ®è¡åä¸è¡ï¼ä¸é +12ï¼ã |
| | | * èæ¯ï¼å¸å®/åå °çå¸å·æãå»ºè®¾é¶æ®µ/形象è¿åº¦ãæ ç¾åå¨è¡¨å¤´ä¸ç¬¬ 4~8 è¡ï¼åºå® +3 伿¼åï¼å½¢è±¡è¿åº¦è¯»ä¸å°ï¼ã */ |
| | | private int investHeaderScanEnd(Sheet sh, int headerRow, Row headerRowObj) { |
| | |
| | | if (target != null && target.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) continue; |
| | | String f = prev.getCellFormula(); |
| | | if (f == null || f.isEmpty()) continue; |
| | | String shifted = shiftFormulaColumns(f, 2); |
| | | String shifted = shiftFormulaToNextMonth(sh, f, year, month); |
| | | if (target == null) target = row.createCell(yoyCol); |
| | | // æ¯çææ°æä»½ç忝ååæäºæ®éæ°å¼æ ¼å¼ï¼æ¾ç¤ºæå°æ°ï¼ï¼ç»ä¸æ²¿ç¨ä¸æåæ¯åçæ ·å¼ï¼ç¾åæ°ï¼ |
| | | if (prev.getCellStyle() != null) target.setCellStyle(prev.getCellStyle()); |
| | |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** å
¬å¼å
A1 åå¼ç¨å¹é
ï¼SUM ç彿°ååæ æ°åï¼ä¸ä¼è¢«å¹é
ï¼ */ |
| | | private static final java.util.regex.Pattern A1_REF = |
| | | java.util.regex.Pattern.compile("(?<![A-Za-z0-9_$])([$]?)([A-Z]{1,3})([$]?)([0-9]+)"); |
| | | /** â2025å¹´8æâ è¿ç§åæè¡¨å¤´ */ |
| | | private static final java.util.regex.Pattern YM_HEADER = |
| | | java.util.regex.Pattern.compile("^(\\d{4})å¹´(\\d{1,2})æ$"); |
| | | /** â2025å¹´1-7æç´¯è®¡â è¿ç§åºé´ç´¯è®¡è¾
å©åï¼ä¸å±äºä»»ä½åæï¼ */ |
| | | private static final java.util.regex.Pattern YM_RANGE_CUM = |
| | | java.util.regex.Pattern.compile("^\\d{4}å¹´\\d{1,2}-\\d{1,2}æç´¯è®¡$"); |
| | | |
| | | /** A1 å忝 -> 0 åºåå·ï¼ä¸ POI ç Cell.getColumnIndex() 对é½ï¼A=0ãAJ=35ï¼ */ |
| | | private int colIndexOf(String letters) { |
| | | int idx = 0; |
| | | for (int i = 0; i < letters.length(); i++) idx = idx * 26 + (letters.charAt(i) - 'A' + 1); |
| | | return idx - 1; |
| | | } |
| | | |
| | | /** 0 åºåå· -> "Q" */ |
| | | private String colLettersOf(int idx0) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | int n = idx0 + 1; |
| | | while (n > 0) { |
| | | int rem = (n - 1) % 26; |
| | | sb.insert(0, (char) ('A' + rem)); |
| | | n = (n - 1) / 26; |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** 表头ï¼å 5 è¡ï¼å»ºç« (å¹´*100+æ) -> åå·ï¼0 åºï¼ï¼è¯å« â2025å¹´8æâ ææ¬æ ¼ä¸ 2025-08-01 è¿ç±»æ¥ææ ¼ï¼ |
| | | * åä¸ (å¹´,æ) åæå·¦ä¸åï¼â2025å¹´1-7æç´¯è®¡â è¿ç±»åºé´ç´¯è®¡è¾
å©åä¸å±äºä»»ä½åæï¼ä¸å䏿 å° */ |
| | | private Map<Integer, Integer> yearMonthCols(Sheet sh, int year) { |
| | | Map<Integer, Integer> m = new LinkedHashMap<>(); |
| | | if (sh == null) return m; |
| | | int last = Math.min(sh.getLastRowNum(), sh.getFirstRowNum() + 4); |
| | | for (int r = sh.getFirstRowNum(); r <= last; r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | for (int c = row.getFirstCellNum(); c >= 0 && c < row.getLastCellNum(); c++) { |
| | | Integer ym = yearMonthOf(row.getCell(c), year); |
| | | if (ym != null && !m.containsKey(ym)) m.put(ym, c); |
| | | } |
| | | } |
| | | return m; |
| | | } |
| | | |
| | | /** |
| | | * å个æä»½è¡¨å¤´ -> å¹´*100+æï¼åªè®¤ä»å¹´/å»å¹´ï¼å
¶ä½ä¸å¾ä¸è®¤ï¼é¿å
æ 2024/2023 对æ¯åãææ ¼å½æä»½åï¼ã |
| | | * 两ç§åæ³ï¼ææ¬ â2026å¹´8æâï¼æ°å¼æ¥æåºåï¼æ¯çåå¸å®¢è¿é¡µ 3..8 æçè¡¨å¤´æ¯ 46235 è¿ç§è£¸åºåã |
| | | * æ°åæ ¼å¼è¿æ¯ Generalï¼åªæâ彿 1 å·â夿ï¼ä¸è½ä¾èµ isCellDateFormattedï¼ã |
| | | */ |
| | | private Integer yearMonthOf(Cell cell, int year) { |
| | | if (cell == null) return null; |
| | | org.apache.poi.ss.usermodel.CellType t = cell.getCellType(); |
| | | if (t == org.apache.poi.ss.usermodel.CellType.STRING) { |
| | | String v = cell.getStringCellValue(); |
| | | if (v == null || v.isEmpty()) return null; |
| | | v = v.trim(); |
| | | if (v.contains("累计") || v.contains("忝")) return null; |
| | | java.util.regex.Matcher m = YM_HEADER.matcher(v); |
| | | if (!m.matches()) return null; |
| | | int y = Integer.parseInt(m.group(1)); |
| | | if (y != year && y != year - 1) return null; |
| | | return y * 100 + Integer.parseInt(m.group(2)); |
| | | } |
| | | if (t == org.apache.poi.ss.usermodel.CellType.NUMERIC) { |
| | | double v = cell.getNumericCellValue(); |
| | | if (v < 1 || v > 200000) return null; |
| | | try { |
| | | 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; |
| | | int y = cal.get(java.util.Calendar.YEAR); |
| | | if (y != year && y != year - 1) return null; |
| | | return y * 100 + (cal.get(java.util.Calendar.MONTH) + 1); |
| | | } catch (Exception ignore) { |
| | | return null; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** 表头é â20XXå¹´a-bæç´¯è®¡â è¿ç±»åºé´ç´¯è®¡è¾
å©åç 0 åºåå·éå */ |
| | | private java.util.Set<Integer> cumulativeHelperCols(Sheet sh) { |
| | | java.util.Set<Integer> set = new java.util.HashSet<>(); |
| | | if (sh == null) return set; |
| | | int last = Math.min(sh.getLastRowNum(), sh.getFirstRowNum() + 4); |
| | | for (int r = sh.getFirstRowNum(); r <= last; r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | for (int c = row.getFirstCellNum(); c >= 0 && c < row.getLastCellNum(); c++) { |
| | | Cell cell = row.getCell(c); |
| | | if (cell == null || cell.getCellType() != org.apache.poi.ss.usermodel.CellType.STRING) continue; |
| | | String v = cell.getStringCellValue(); |
| | | if (v != null && YM_RANGE_CUM.matcher(v.trim()).matches()) set.add(c); |
| | | } |
| | | } |
| | | return set; |
| | | } |
| | | |
| | | /** æä»½æ å°çå¯ç¨æ§å®å«ï¼å»å¹´ä¸ä»å¹´ 1..month åæåå¿
é¡»é½å
¨ä¸åå·ä¸¥æ ¼éå¢ï¼ |
| | | * ä»»ä¸ä¸æ»¡è¶³ï¼è¡¨å¤´æ²¡åæä»½ãææå°ææ ¼ï¼å°±è¿å空表ï¼è°ç¨æ¹éåãæ´ä½å³ç§» 2 åãçæ§è¡ä¸º */ |
| | | private Map<Integer, Integer> usableMonthCols(Sheet sh, int year, int month) { |
| | | Map<Integer, Integer> usable = new LinkedHashMap<>(); |
| | | Map<Integer, Integer> all = yearMonthCols(sh, year); |
| | | int prevLy = -1, prevCy = -1; |
| | | for (int m = 1; m <= month; m++) { |
| | | Integer ly = all.get((year - 1) * 100 + m); |
| | | Integer cy = all.get(year * 100 + m); |
| | | if (ly == null || cy == null || ly <= prevLy || cy <= prevCy) return new LinkedHashMap<>(); |
| | | prevLy = ly; |
| | | prevCy = cy; |
| | | usable.put((year - 1) * 100 + m, ly); |
| | | usable.put(year * 100 + m, cy); |
| | | } |
| | | return usable; |
| | | } |
| | | |
| | | /** |
| | | * ã䏿忝ãå
¬å¼ â ãæ¬æåæ¯ãå
¬å¼ï¼å
¬å¼éå¼ç¨å°æä»½åçå¼ç¨æè¡¨å¤´ (å¹´,æ) 顺延ä¸ä¸ªæï¼ |
| | | * å
¶ä½å¼ç¨éåãæ´ä½å³ç§» 2 åãã |
| | | * |
| | | * 为ä»ä¹ä¸è½ä¸å¾å³ç§» 2 åï¼æ¯çãåå¸å®¢è¿ãé¡µå¨ 2025 年段æäºä¸åã2025å¹´1-7æç´¯è®¡ãè¾
å©åï¼ |
| | | * 2025 åæåä» 8 æèµ·ä¸åçè·ï¼2025å¹´8æå¨ AKãä¸å¨ AJï¼ï¼å³ç§» 2 åä¼è½å°è¾
å©åä¸ï¼ |
| | | * äºæ¯ 8 æåæ¯è¢«ç®æã8æå¼ ÷ 2025å¹´1-7æç´¯è®¡ â 1ãï¼2026-09-20 ç¨æ·ä¸æ¥çé®é¢ï¼ã |
| | | */ |
| | | private String shiftFormulaToNextMonth(Sheet sh, String formula, int year, int month) { |
| | | if (formula == null || formula.isEmpty()) return formula; |
| | | Map<Integer, Integer> cols = usableMonthCols(sh, year, month); |
| | | if (cols.isEmpty()) return shiftFormulaColumns(formula, 2); |
| | | Map<Integer, Integer> colToYm = new LinkedHashMap<>(); |
| | | for (Map.Entry<Integer, Integer> e : cols.entrySet()) colToYm.put(e.getValue(), e.getKey()); |
| | | java.util.regex.Matcher m = A1_REF.matcher(formula); |
| | | StringBuffer sb = new StringBuffer(); |
| | | while (m.find()) { |
| | | int idx = colIndexOf(m.group(2)); |
| | | Integer ym = colToYm.get(idx); |
| | | Integer next = null; |
| | | if (ym != null) { |
| | | next = cols.get((ym / 100) * 100 + (ym % 100) + 1); |
| | | } |
| | | m.appendReplacement(sb, java.util.regex.Matcher.quoteReplacement( |
| | | m.group(1) + colLettersOf(next != null ? next : idx + 2) + m.group(3) + m.group(4))); |
| | | } |
| | | m.appendTail(sb); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** |
| | | * ä¿®æ£ãç´¯è®¡åæ¯ãåæ¯ãæ¯çãåå¸å®¢è¿ã页æ 2025 å¹´ 1..M æåæå**å**å®ä»¬ç |
| | | * ã2025å¹´1-Mæç´¯è®¡ãè¾
å©åä¸èµ·åè¿åæ¯ï¼1..M-1 æéå¤è®¡ä¸æ¬¡ã彿æ¼è®¡ï¼ï¼ |
| | | * 妿卿¯çéå æè¾
å©ååæ®ç #REF! çæ
å½¢ï¼ä¸¤ç§é½ä¼è®©ç´¯è®¡åæ¯ä¸¥é失ç |
| | | * ï¼2026-09-20 ç¨æ·ä¸æ¥ï¼åå¸å®¢è¿ 8 æåæ¯ â86.5%ãç´¯è®¡åæ¯ â43.5%ï¼ã |
| | | * ç»ä¸æè¡¨å¤´æåæ¯éå为ãå»å¹´ 1..彿 åæå¼åä¹åãã |
| | | * |
| | | * 2026-09-20 å·²å¨ã2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãæ¯çéå æè¯¥è¾
å©åï¼å¤ä»½è§ |
| | | * docs/çææ±æ»å¤§è¡¨/_bak_202608æ¯çå é¤AJåå_20260920.xlsxï¼ï¼æ£å¸¸æ
嵿¬æ¹æ³å½ä¸ 0 æ ¼ï¼ |
| | | * ä¿ç宿¯ä¸ºäºå
ä½ãåæå¤ä»½æ¯ç / åå²é¨ç½²å
/ ä¹ååæäºè¾
å©åçæ¯çãè¿ç±»æ
åµã |
| | | */ |
| | | public int repairCumulativeYoyFormulas(XSSFWorkbook wb, int year, int month) { |
| | | if (wb == null || month < 1) return 0; |
| | | int fixed = 0; |
| | | for (int i = 0; i < wb.getNumberOfSheets(); i++) { |
| | | Sheet sh = wb.getSheetAt(i); |
| | | if (sh == null || !isMonthLedgerSheet(sh.getSheetName())) continue; |
| | | int[] cum = cumulativeCols(sh, year); |
| | | if (cum == null) continue; |
| | | java.util.Set<Integer> helperCols = cumulativeHelperCols(sh); |
| | | Map<Integer, Integer> all = yearMonthCols(sh, year); |
| | | List<Integer> lastYearValueCols = new ArrayList<>(); |
| | | int prev = -1; |
| | | for (int m = 1; m <= month; m++) { |
| | | Integer c = all.get((year - 1) * 100 + m); |
| | | if (c == null || c <= prev) { |
| | | lastYearValueCols.clear(); |
| | | break; |
| | | } |
| | | prev = c; |
| | | lastYearValueCols.add(c); |
| | | } |
| | | if (lastYearValueCols.isEmpty()) continue; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | Cell cc = row.getCell(cum[1]); |
| | | if (cc == null || cc.getCellType() != org.apache.poi.ss.usermodel.CellType.FORMULA) continue; |
| | | String f = cc.getCellFormula(); |
| | | if (f == null || !cumulativeYoyBroken(f, helperCols)) continue; |
| | | // 注æï¼POI ç setCellFormula 䏿¥å以 "=" å¼å¤´çå
¬å¼ä¸²ï¼ä¼æ FormulaParseExceptionï¼ |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append(cellRef(cum[0], r + 1)).append("/("); |
| | | for (int k = 0; k < lastYearValueCols.size(); k++) { |
| | | if (k > 0) sb.append('+'); |
| | | sb.append(cellRef(lastYearValueCols.get(k), r + 1)); |
| | | } |
| | | sb.append(")-1"); |
| | | try { |
| | | cc.setCellFormula(sb.toString()); |
| | | fixed++; |
| | | } catch (Exception ex) { |
| | | // 个å«å
¬å¼æ¹å失败ä¸é»å¡å¯¼åºï¼æå¼æ¶ä»æåå
¬å¼éç®ï¼ |
| | | if (log != null) log.warn("ç´¯è®¡åæ¯å
¬å¼æ¹å失败ï¼sheet={} cell={} åå¼={} æ°å¼={}ï¼{}ï¼", |
| | | sh.getSheetName(), cellRef(cum[1], r + 1), f, sb, ex.toString()); |
| | | } |
| | | } |
| | | } |
| | | if (fixed > 0 && log != null) { |
| | | log.info("æ±æ»å·¥ä½ç°¿ï¼ç´¯è®¡åæ¯åæ¯ä¿®æ£ {} æ ¼ï¼ç¬¬ {} æï¼åæ¯åå»å¹´ 1..{} æåæå¼åï¼", fixed, month, month); |
| | | } |
| | | return fixed; |
| | | } |
| | | |
| | | /** ç´¯è®¡åæ¯å
¬å¼æ¯å¦âåäºâï¼å« #REF!ï¼æåæ¯å¼ç¨äºåºé´ç´¯è®¡è¾
å©åï¼ä¸åæåéå¤è®¡å
¥ï¼ */ |
| | | private boolean cumulativeYoyBroken(String formula, java.util.Set<Integer> helperCols) { |
| | | if (formula.contains("#REF!")) return true; |
| | | java.util.regex.Matcher m = A1_REF.matcher(formula); |
| | | while (m.find()) { |
| | | if (helperCols.contains(colIndexOf(m.group(2)))) return true; |
| | | } |
| | | return false; |
| | | } |
| | | |
| | | /** 该页ã累计 / ç´¯è®¡åæ¯ã两åï¼0 åºï¼ï¼æè¡¨å¤´å 5 è¡æ¾ âç´¯è®¡â æ â{year}年累计âï¼ä¸å
¶å³åå« â忝â */ |
| | | private int[] cumulativeCols(Sheet sh, int year) { |
| | | int last = Math.min(sh.getLastRowNum(), sh.getFirstRowNum() + 4); |
| | | for (int r = sh.getFirstRowNum(); r <= last; r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | for (int c = row.getFirstCellNum(); c >= 0 && c < row.getLastCellNum(); c++) { |
| | | Cell cell = row.getCell(c); |
| | | if (cell == null || cell.getCellType() != org.apache.poi.ss.usermodel.CellType.STRING) continue; |
| | | String v = cell.getStringCellValue(); |
| | | if (v == null) continue; |
| | | v = v.trim(); |
| | | if (!"累计".equals(v) && !(year + "年累计").equals(v)) continue; |
| | | Cell nxt = row.getCell(c + 1); |
| | | if (nxt == null || nxt.getCellType() != org.apache.poi.ss.usermodel.CellType.STRING) continue; |
| | | String nt = nxt.getStringCellValue(); |
| | | if (nt != null && nt.contains("忝")) return new int[]{c, c + 1}; |
| | | } |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** æä»½å®¹éï¼ä¼å
å表头ï¼å 5 è¡ï¼â2026â¦ç´¯è®¡âå忍ï¼è´§è¿é¡µæ è¯¥ææ¡ï¼ |
| | | * åç¨è¡¨å¤´éæåä¸ä¸ªâ2026å¹´Mæâ/æ¥ææ ¼å¼çæåå
åºï¼å¦è´§è¿ Q3=2026-08-01 -> 8ï¼ */ |
| | | private int monthColumnCapacity(Sheet sh) { |
| | |
| | | if (r.getAvgDistanceCity() != null && r.getAvgDistanceCity() > 0) a[5] = r.getAvgDistanceCity(); |
| | | } |
| | | for (double[] a : map.values()) { |
| | | if (a[4] <= 0 && a[0] > 0) a[4] = round(a[1] / a[0], 2); |
| | | if (a[5] <= 0 && a[2] > 0) a[5] = round(a[3] / a[2], 2); |
| | | // å¹³åè¿è·å
åºï¼å
¨ç²¾åº¦ä¿çï¼å±ç¤ºä½æ°äº¤ç»åå
æ ¼æ ¼å¼ |
| | | if (a[4] <= 0 && a[0] > 0) a[4] = a[1] / a[0]; |
| | | if (a[5] <= 0 && a[2] > 0) a[5] = a[3] / a[2]; |
| | | } |
| | | return map; |
| | | } |
| | |
| | | |
| | | private double nz(Double v) { return v == null ? 0.0 : v; } |
| | | |
| | | private double round(double v, int scale) { |
| | | double factor = Math.pow(10, scale); |
| | | return Math.round(v * factor) / factor; |
| | | } |
| | | } |
| | |
| | | |
| | | import com.trafficaudit.common.Result; |
| | | import com.trafficaudit.reportexport.service.ReportExportService; |
| | | import com.trafficaudit.reportexport.service.ReportExportTaskService; |
| | | import com.trafficaudit.system.service.OperationLogService; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.http.HttpHeaders; |
| | | import org.springframework.http.MediaType; |
| | | import org.springframework.http.ResponseEntity; |
| | | import org.springframework.web.bind.annotation.GetMapping; |
| | | import org.springframework.web.bind.annotation.PathVariable; |
| | | import org.springframework.web.bind.annotation.RequestMapping; |
| | | import org.springframework.web.bind.annotation.RequestParam; |
| | | import org.springframework.web.bind.annotation.RestController; |
| | |
| | | |
| | | @Resource |
| | | private ReportExportService reportService; |
| | | @Resource |
| | | private ReportExportTaskService exportTaskService; |
| | | @Resource |
| | | private OperationLogService operationLogService; |
| | | |
| | |
| | | @RequestParam(value = "toMonth", required = false) Integer toMonth) throws Exception { |
| | | logExport("éè·¯è¿è¾éæ±æ»è¡¨.xlsx", period); |
| | | return buildResponse(reportService.exportSummaryWorkbook(period, mode, toMonth), String.format("çæ_éè·¯è¿è¾éæ±æ»è¡¨_%s.xlsx", period)); |
| | | } |
| | | |
| | | /** |
| | | * æ±æ»å¤§è¡¨å¼æ¥å¯¼åºï¼ç«å³è¿åä»»å¡å·ï¼å端轮询è¿åº¦ã宿ååä¸è½½æä»¶ã |
| | | * çæä¸æ¬¡çº¦ 10~20 ç§ï¼èµ°å¼æ¥å¯é¿å
ç¹å»åé¿æ¶é´æ ååºï¼åæ¥è¡¨æ 10 åéå
çç»æç´æ¥å¤ç¨ï¼æé´æå¯¼å
¥åèªå¨å¤±æï¼ï¼ |
| | | * refresh=true å¯å¼ºå¶éæ°çæã |
| | | */ |
| | | @GetMapping("/exportTask/summaryWorkbook") |
| | | public Result<java.util.Map<String, Object>> submitSummaryWorkbookTask(@RequestParam("period") String period, |
| | | @RequestParam(value = "mode", defaultValue = "month") String mode, |
| | | @RequestParam(value = "toMonth", required = false) Integer toMonth, |
| | | @RequestParam(value = "refresh", defaultValue = "false") boolean refresh) { |
| | | ReportExportTaskService.Task task = exportTaskService.submit( |
| | | ReportExportTaskService.TYPE_SUMMARY_WORKBOOK, period, mode, toMonth, refresh); |
| | | if (!task.isFromCache()) { |
| | | logExport("éè·¯è¿è¾éæ±æ»è¡¨.xlsx", period); |
| | | } |
| | | return Result.ok(task.toView()); |
| | | } |
| | | |
| | | /** æ¥è¯¢å¼æ¥å¯¼åºä»»å¡è¿åº¦ï¼ç»æä¿ç 30 åéï¼ */ |
| | | @GetMapping("/exportTask/{taskId}") |
| | | public Result<java.util.Map<String, Object>> exportTaskStatus(@PathVariable("taskId") String taskId) { |
| | | ReportExportTaskService.Task task = exportTaskService.get(taskId); |
| | | if (task == null) { |
| | | return Result.error("导åºä»»å¡ä¸åå¨æå·²è¿æï¼çæç»æä¿ç 30 åéï¼"); |
| | | } |
| | | return Result.ok(task.toView()); |
| | | } |
| | | |
| | | /** ä¸è½½å¼æ¥å¯¼åºä»»å¡å·²çæçæä»¶ */ |
| | | @GetMapping("/exportTask/{taskId}/file") |
| | | public ResponseEntity<byte[]> exportTaskFile(@PathVariable("taskId") String taskId) throws Exception { |
| | | ReportExportTaskService.Task task = exportTaskService.get(taskId); |
| | | if (task == null) { |
| | | throw new RuntimeException("导åºä»»å¡ä¸åå¨æå·²è¿æï¼çæç»æä¿ç 30 åéï¼"); |
| | | } |
| | | if (!task.isDone()) { |
| | | throw new RuntimeException("导åºä»»å¡å°æªå®æï¼å½åç¶æï¼" + task.getStatus() + "ï¼ï¼è¯·ç¨ååè¯"); |
| | | } |
| | | return buildResponse(task.getData(), task.getFileName()); |
| | | } |
| | | |
| | | /** çæ_ç½çº¦è½¦å®¢è¿éæå表.xlsxï¼æåº¦ï¼è®¢åéä»¶1 + å
¨ç pin + 巡游åºç§ææ¥ï¼ */ |
| | |
| | | .body(data); |
| | | } |
| | | } |
| | | |
| | |
| | | } |
| | | break; |
| | | } |
| | | case "investPassengerDetail": |
| | | case "investLogisticsDetail": { |
| | | boolean paxDetail = "investPassengerDetail".equals(t); |
| | | String catName = paxDetail ? "客è¿ç«åº" : "ç©æµååº"; |
| | | String catLabel = paxDetail ? "客è¿ç«åºæèµææ¥" : "ç©æµååºæèµææ¥"; |
| | | List<InvestmentProject> catProjects = investProjectMapper.selectList( |
| | | new LambdaQueryWrapper<InvestmentProject>().eq(InvestmentProject::getCategory, catName)); |
| | | final List<Long> catIds = new ArrayList<>(); |
| | | for (InvestmentProject cp : catProjects) catIds.add(cp.getId()); |
| | | if (catIds.isEmpty()) { |
| | | rows = 0; |
| | | notes.add("ç¼ºæ°æ®ï¼" + catLabel); |
| | | } else { |
| | | rows = addReadyCount(() -> investMonthlyMapper.selectCount( |
| | | periodQw(period, mode, InvestmentMonthly::getReportPeriod) |
| | | .in(InvestmentMonthly::getProjectId, catIds)), catLabel, notes); |
| | | } |
| | | String detTpl = paxDetail ? "模æ¿_Xæå®¢è¿ç«æèµæç»è¡¨.xlsx" : "模æ¿_Xæç©æµç«åºæèµæç».xls"; |
| | | try { |
| | | if (resolveAnyTemplate(investTemplateDir, detTpl) == null) { |
| | | rows = 0; |
| | | notes.add("docs/æèµ/æ¨¡æ¿ ä¸ç¼ºå°ã" + detTpl + "ã"); |
| | | } |
| | | } catch (Exception ex) { |
| | | rows = 0; |
| | | notes.add("æ¯çå®ä½å¤±è´¥ï¼" + ex.getMessage()); |
| | | } |
| | | auditTypes.add("INVEST"); |
| | | break; |
| | | } |
| | | default: |
| | | rows = 0; |
| | | notes.add("æªç¥æ¥è¡¨ç±»åï¼" + t); |
| | |
| | | coverage.addAll(investCover); |
| | | // æèµä¸ºå½ææ¥è¡¨ï¼æ 1..N 累计å£å¾ï¼ï¼åªæç¤ºå½æç¼ºå¤± |
| | | if (!investCover.contains(month)) missing.add(month); |
| | | investPreview(period, mode, summary, problems); |
| | | if ("investPassengerDetail".equals(t)) investPreview(period, mode, "客è¿ç«åº", summary, problems); |
| | | else if ("investLogisticsDetail".equals(t)) investPreview(period, mode, "ç©æµååº", summary, problems); |
| | | else investPreview(period, mode, summary, problems); |
| | | } else if ("energySummary".equals(t)) { |
| | | Long ec = energyMapper.selectCount(periodQw(period, mode, EnergyVehicleQuarterly::getReportPeriod)); |
| | | if (ec != null && ec > 0) coverage.add(month); |
| | |
| | | } |
| | | |
| | | private boolean isInvestType(String t) { |
| | | return "investPlan".equals(t) || "investFiveYearLogistics".equals(t) || "investBillion".equals(t) || "investCounty".equals(t); |
| | | return "investPlan".equals(t) || "investFiveYearLogistics".equals(t) || "investBillion".equals(t) || "investCounty".equals(t) |
| | | || "investPassengerDetail".equals(t) || "investLogisticsDetail".equals(t); |
| | | } |
| | | |
| | | private boolean isEnergyType(String t) { |
| | |
| | | if (allZero) problems.add("å
¨ç累计å¼å
¨ä¸º 0ï¼å
¬äº¤/åºç§ææ¥å¯è½æªå¯¼å
¥ï¼"); |
| | | } |
| | | |
| | | /** æèµæè¦ï¼é¡¹ç®æ° + æ¬æå®æ/èªå¹´å/èªå¼å§ç´¯è®¡ */ |
| | | /** æèµæè¦ï¼é¡¹ç®æ° + æ¬æå®æ/èªå¹´å/èªå¼å§ç´¯è®¡ï¼å
¨æèµææ¥å计ï¼ä¸åç±»å«ï¼ */ |
| | | private void investPreview(String period, String mode, List<Map<String, Object>> summary, List<String> problems) { |
| | | List<InvestmentMonthly> list = investMonthlyMapper.selectList(periodQw(period, mode, InvestmentMonthly::getReportPeriod)); |
| | | investPreview(period, mode, null, summary, problems); |
| | | } |
| | | |
| | | /** æèµæè¦ï¼category é空æ¶åªç»è®¡è¯¥ç±»å«ï¼å¦å®¢è¿ç«åº/ç©æµååºæèµæç»è¡¨ï¼ */ |
| | | private void investPreview(String period, String mode, String category, List<Map<String, Object>> summary, List<String> problems) { |
| | | LambdaQueryWrapper<InvestmentMonthly> qw = periodQw(period, mode, InvestmentMonthly::getReportPeriod); |
| | | if (category != null) { |
| | | List<InvestmentProject> ps = investProjectMapper.selectList( |
| | | new LambdaQueryWrapper<InvestmentProject>().eq(InvestmentProject::getCategory, category)); |
| | | List<Long> ids = new ArrayList<>(); |
| | | for (InvestmentProject p : ps) ids.add(p.getId()); |
| | | if (ids.isEmpty()) { problems.add("ç¼ºæ°æ®ï¼åºå
没æã" + category + "ã项ç®ä¸»æ¡£"); return; } |
| | | qw.in(InvestmentMonthly::getProjectId, ids); |
| | | } |
| | | List<InvestmentMonthly> list = investMonthlyMapper.selectList(qw); |
| | | Set<Long> proj = new HashSet<>(); |
| | | double monthDone = 0.0, yearCum = 0.0, startCum = 0.0; |
| | | for (InvestmentMonthly m : list) { |
| | |
| | | for (Double v : h2032FreightCum.values()) { |
| | | if (v != null) provAbove += v; |
| | | } |
| | | Double provAboveWan = round(provAbove / 10000.0, 4); |
| | | Double provAboveWan = provAbove / 10000.0; |
| | | Double provTotal = freightCum(ftMap.get("æ¹åç"), month); |
| | | Double provBelow = provTotal == null ? null : round(provTotal - provAboveWan, 4); |
| | | Double provBelow = provTotal == null ? null : provTotal - provAboveWan; |
| | | Double provTotalYoy = freightCumYoy(ftMap.get("æ¹åç"), month); |
| | | double provAboveLast = 0.0; |
| | | for (Double v : h2032FreightCumLast.values()) { |
| | | if (v != null) provAboveLast += v; |
| | | } |
| | | Double provAboveYoy = provAboveLast == 0.0 ? null : round((provAbove - provAboveLast) / provAboveLast, 4); |
| | | Double provAboveYoy = provAboveLast == 0.0 ? null : (provAbove - provAboveLast) / provAboveLast; |
| | | Double provTotalLast = lastFreightCum(ftMap.get("æ¹åç"), month); |
| | | Double provBelowLast = provTotalLast == null ? null : round(provTotalLast - provAboveLast / 10000.0, 4); |
| | | Double provBelowLast = provTotalLast == null ? null : provTotalLast - provAboveLast / 10000.0; |
| | | Double provBelowYoy = provBelowLast == null || provBelowLast == 0.0 ? null |
| | | : round((provBelow - provBelowLast) / provBelowLast, 4); |
| | | : (provBelow - provBelowLast) / provBelowLast; |
| | | |
| | | for (String city : RegionUtil.cityList()) { |
| | | Double a = h2032FreightCum.get(city); |
| | | double aWan = a == null ? 0.0 : round(a / 10000.0, 4); |
| | | double aWan = a == null ? 0.0 : a / 10000.0; |
| | | Double t = freightCum(ftMap.get(city), month); |
| | | above.put(city, aWan); |
| | | total.put(city, t); |
| | | below.put(city, t == null ? null : round(t - aWan, 4)); |
| | | below.put(city, t == null ? null : t - aWan); |
| | | aboveYoy.put(city, h2032FreightYoy.get(city)); |
| | | // è§ä¸åæ¯ = (è§ä¸ä»å¹´ - è§ä¸å»å¹´) / è§ä¸å»å¹´ï¼è§ä¸å»å¹´ = 模æ¿å»å¹´å计 - H2032å»å¹´è§ä¸ |
| | | Double tLast = lastFreightCum(ftMap.get(city), month); |
| | | Double aLast = h2032FreightCumLast.get(city); |
| | | double aLastWan = aLast == null ? 0.0 : round(aLast / 10000.0, 4); |
| | | Double belowLast = tLast == null ? null : round(tLast - aLastWan, 4); |
| | | double aLastWan = aLast == null ? 0.0 : aLast / 10000.0; |
| | | Double belowLast = tLast == null ? null : tLast - aLastWan; |
| | | Double b = below.get(city); |
| | | belowYoy.put(city, belowLast == null || belowLast == 0.0 || b == null |
| | | ? null : round((b - belowLast) / belowLast, 4)); |
| | | ? null : (b - belowLast) / belowLast); |
| | | totalYoy.put(city, freightCumYoy(ftMap.get(city), month)); |
| | | } |
| | | |
| | |
| | | if (maLast != null) provMonthAboveLast += maLast; |
| | | monthAbove.put(city, ma); |
| | | monthTotal.put(city, mt); |
| | | monthBelow.put(city, mt == null ? null : round(mt - (ma == null ? 0.0 : ma), 4)); |
| | | monthBelow.put(city, mt == null ? null : mt - (ma == null ? 0.0 : ma)); |
| | | monthAboveYoy.put(city, growthYoy(ma, maLast)); |
| | | Double mb = monthBelow.get(city); |
| | | Double mbLast = mtLast == null ? null : round(mtLast - (maLast == null ? 0.0 : maLast), 4); |
| | | Double mbLast = mtLast == null ? null : mtLast - (maLast == null ? 0.0 : maLast); |
| | | monthBelowYoy.put(city, growthYoy(mb, mbLast)); |
| | | monthTotalYoy.put(city, freightYoy(ftMap.get(city), month)); |
| | | } |
| | | Double provMonthAboveWan = provMonthAbove == 0.0 ? null : round(provMonthAbove, 4); |
| | | Double provMonthAboveWan = provMonthAbove == 0.0 ? null : provMonthAbove; |
| | | Double provMonthTotal = freightMonth(ftMap.get("æ¹åç"), month); |
| | | Double provMonthBelow = provMonthTotal == null ? null : round(provMonthTotal - provMonthAbove, 4); |
| | | Double provMonthBelow = provMonthTotal == null ? null : provMonthTotal - provMonthAbove; |
| | | Double provMonthAboveYoy = growthYoy(provMonthAbove == 0.0 ? null : provMonthAbove, provMonthAboveLast); |
| | | Double provMonthTotalLast = lastFreightMonth(ftMap.get("æ¹åç"), month); |
| | | Double provMonthBelowLast = provMonthTotalLast == null ? null |
| | | : round(provMonthTotalLast - provMonthAboveLast, 4); |
| | | : provMonthTotalLast - provMonthAboveLast; |
| | | Double provMonthBelowYoy = growthYoy(provMonthBelow, provMonthBelowLast); |
| | | Double provMonthTotalYoy = freightYoy(ftMap.get("æ¹åç"), month); |
| | | |
| | |
| | | private Double monthFreightWan(Map<String, Map<Integer, Double>> byCityMonth, String city, int month) { |
| | | Map<Integer, Double> byMonth = byCityMonth == null ? null : byCityMonth.get(city); |
| | | Double v = byMonth == null ? null : byMonth.get(month); |
| | | return v == null ? null : round(v / 10000.0, 4); |
| | | return v == null ? null : v / 10000.0; |
| | | } |
| | | |
| | | /** 忝 = (æ¬æ-åºæ)/åºæï¼ä»»ä¸æç¼ºå¤±æåºæä¸º 0 è¿å null */ |
| | |
| | | } |
| | | } |
| | | |
| | | /** å¨è½¬éæå Q/R å æ¯ï¼æ¨¡æ¿ä¸ºç¼åå¼ï¼ææ°æ°æ®éç®ï¼è§ä¸å æ¯ 1 ä½å°æ°ï¼ */ |
| | | /** å¨è½¬éæå Q/R å æ¯ï¼æ¨¡æ¿ä¸ºç¼åå¼ï¼ææ°æ°æ®éç®ï¼å
¨ç²¾åº¦åå
¥ï¼ä¸¤ä½å°æ°å±ç¤ºäº¤ç»åå
æ ¼æ ¼å¼ï¼ */ |
| | | private void setFreightShare(Row row, Double above, Double total) { |
| | | if (total != null && total > 0 && above != null) { |
| | | double share = round(above * 10.0 / total, 1); |
| | | double share = above * 10.0 / total; |
| | | setFreightCell(row, 16, share); |
| | | setFreightCell(row, 17, round(10.0 - share, 1)); |
| | | setFreightCell(row, 17, 10.0 - share); |
| | | } else { |
| | | setFreightCell(row, 16, (Double) null); |
| | | setFreightCell(row, 17, (Double) null); |
| | |
| | | setNumeric(row, 15, isProvince ? null : yoyRankOfMap(totalYoy, city)); |
| | | |
| | | if (t != null && t > 0 && a != null) { |
| | | double share = round(a * 10.0 / t, 1); |
| | | double share = a * 10.0 / t; |
| | | setNumeric(row, 16, share); |
| | | setNumeric(row, 17, round(10.0 - share, 1)); |
| | | setNumeric(row, 17, 10.0 - share); |
| | | } |
| | | return rowIdx + 1; |
| | | } |
| | |
| | | setNumeric(row, 15, isProvince || cum == null ? null : yoyRankOfTurnover(cumMap, city, 2)); |
| | | |
| | | if (total != null && total > 0 && above != null) { |
| | | double share = round(above * 10.0 / total, 1); |
| | | double share = above * 10.0 / total; |
| | | setNumeric(row, 16, share); |
| | | setNumeric(row, 17, round(10.0 - share, 1)); |
| | | setNumeric(row, 17, 10.0 - share); |
| | | } |
| | | return rowIdx + 1; |
| | | } |
| | |
| | | Double v = byMonth == null ? null : byMonth.get(month); |
| | | if (v != null) sum += v; |
| | | } |
| | | return round(sum / 10000.0, 4); |
| | | return sum / 10000.0; |
| | | } |
| | | Double total = freightMonth(ft, month); |
| | | Double above = getProvinceMonthValue(provinceMonthMap, ft, month, "freight", "above", h2032Freight); |
| | |
| | | for (Double v : h2032FreightCum.values()) { |
| | | if (v != null) sum += v; |
| | | } |
| | | return round(sum / 10000.0, 4); |
| | | return sum / 10000.0; |
| | | } |
| | | Double total = freightCum(ft, monthCount); |
| | | Double above = getProvinceCumValue(provinceCum, ft, "freight", "above", h2032FreightCum, monthCount); |
| | |
| | | if ("above".equals(scale)) { |
| | | Map<Integer, Double> byMonth = h2032Freight.get(city); |
| | | Double v = byMonth == null ? null : byMonth.get(month); |
| | | return v == null ? 0.0 : round(v / 10000.0, 4); |
| | | return v == null ? 0.0 : v / 10000.0; |
| | | } |
| | | Double total = freightMonth(ft, month); |
| | | Double above = getCityMonthValue(monthData, ft, city, month, "freight", "above", h2032Freight); |
| | |
| | | if ("total".equals(scale)) return freightCum(ft, monthCount); |
| | | if ("above".equals(scale)) { |
| | | Double v = h2032FreightCum.get(city); |
| | | return v == null ? 0.0 : round(v / 10000.0, 4); |
| | | return v == null ? 0.0 : v / 10000.0; |
| | | } |
| | | Double total = freightCum(ft, monthCount); |
| | | Double above = getCityCumValue(cum, ft, "freight", "above", h2032FreightCum, city, monthCount); |
| | |
| | | double v = passengerMonthVal(data, indi, currentYear, m, region, metricIdx); |
| | | if (!keepFormula) { |
| | | if (c == null) c = row.createCell(col); |
| | | if (v == 0.0) c.setBlank(); else c.setCellValue(round(v, 4)); |
| | | if (v == 0.0) c.setBlank(); else c.setCellValue(v); |
| | | } |
| | | // 忝åï¼åºå
å»å¹´åæåæ¯ï¼æ¨¡æ¿ #REF! å
¬å¼æ¿æ¢ä¸ºæ°å¼ï¼å
¬å¼è¡ä¹è¦åï¼ |
| | | double lv = passengerMonthVal(data, indi, currentYear - 1, m, region, metricIdx); |
| | | Cell yc = row.getCell(col + 1); |
| | | if (yc == null) yc = row.createCell(col + 1); |
| | | if (v == 0.0 || lv == 0.0) yc.setBlank(); else yc.setCellValue(round((v - lv) / lv, 4)); |
| | | if (v == 0.0 || lv == 0.0) yc.setBlank(); else yc.setCellValue((v - lv) / lv); |
| | | } |
| | | // ç´¯è®¡åæ¯åï¼æ¨¡æ¿ #REF! â åºå
å»å¹´ 1..N æç´¯è®¡åæ¯æ°å¼ï¼ |
| | | int cumCol = extended ? 26 : 14; |
| | | Double cumYoy = passengerCumYoy(data, indi, currentYear, fillMonths, region, metricIdx); |
| | | Cell yc2 = row.getCell(cumCol + 1); |
| | | if (yc2 == null) yc2 = row.createCell(cumCol + 1); |
| | | if (cumYoy == null) yc2.setBlank(); else yc2.setCellValue(round(cumYoy, 4)); |
| | | if (cumYoy == null) yc2.setBlank(); else yc2.setCellValue(cumYoy); |
| | | } |
| | | recalc(wb); |
| | | return toBytes(wb); |
| | |
| | | |
| | | private Double yoy(Double cur, Double base) { |
| | | if (cur == null || base == null || base == 0.0) return null; |
| | | return round((cur - base) / base, 4); |
| | | return (cur - base) / base; |
| | | } |
| | | |
| | | /** ææ åå¼ï¼å·²æ¢ç®ä¸ºä¸äºº/ä¸äººå
¬é/å
¬éï¼æ æ°æ®è¿å nullï¼ */ |
| | |
| | | if (v == 0.0) return; // åºå
æ æºï¼ä¿çæ¯ç/å®ç¨¿åå¼ï¼ç¼ºæ°æ®ä¸è¦ç |
| | | // POI setCellValue(double) 对å
¬å¼åå
æ ¼åªæ´æ°ç¼åä¸ç§»é¤å
¬å¼ï¼å¿
é¡»å
setBlank ååå¼ |
| | | c.setBlank(); |
| | | c.setCellValue(round(v, 4)); |
| | | c.setCellValue(v); |
| | | } |
| | | |
| | | /** æ¾å¼åå
¥ 0ï¼POI setCellValue(0.0) ä¼è½¬ blankï¼éæä½åºå± XMLï¼ */ |
| | |
| | | int monthCount = (y == currentYear) ? maxMonth : 12; |
| | | for (int m = 1; m <= monthCount; m++) { |
| | | Double cur = midMetricValue(aggOf(data, y, m, region), i, volume); |
| | | setNumeric(row, col++, cur == null ? null : round(cur, 4)); |
| | | setNumeric(row, col++, cur); |
| | | Double base = midMetricValue(aggOf(data, y - 1, m, region), i, volume); |
| | | setNumeric(row, col++, yoy(cur, base)); |
| | | } |
| | | Double cum = midCumOf(data, y, region, monthCount, i, volume); |
| | | setNumeric(row, col++, cum == null ? null : round(cum, 4)); |
| | | setNumeric(row, col++, cum); |
| | | Double cumBase = midCumOf(data, y - 1, region, monthCount, i, volume); |
| | | setNumeric(row, col++, yoy(cum, cumBase)); |
| | | } |
| | |
| | | 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 : round(pass, 4)); |
| | | setValOrBlank(sheet, r0, 1, pass == 0 ? null : pass); |
| | | setValOrBlank(sheet, r0, 3, midCumYoy(mid, currentYear, city, maxMonth, 0, true)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : round(turn, 4)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : turn); |
| | | setValOrBlank(sheet, r0, 7, midCumYoy(mid, currentYear, city, maxMonth, 0, false)); |
| | | // å³å彿ï¼L/P å¼ãN/R 彿忝ï¼M/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 : round(mPass, 4)); |
| | | 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 : round(mTurn, 4)); |
| | | setValOrBlank(sheet, r0, 15, mTurn == 0 ? null : mTurn); |
| | | setValOrBlank(sheet, r0, 17, mTurn == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, city, 0, false)); |
| | | } |
| | | recalc(wb); |
| | |
| | | |
| | | private Double yoyOf(double cur, double base) { |
| | | if (base == 0.0) return null; |
| | | return round((cur - base) / base, 4); |
| | | return (cur - base) / base; |
| | | } |
| | | |
| | | /** ä¸å£å¾å类累计ï¼1..monthCount ææ±åï¼ */ |
| | |
| | | double turn = midCumClass(mid, currentYear, "æ¹åç", maxMonth, dims[i], false); |
| | | double lastPass = midCumClass(mid, currentYear - 1, "æ¹åç", maxMonth, dims[i], true); |
| | | double lastTurn = midCumClass(mid, currentYear - 1, "æ¹åç", maxMonth, dims[i], false); |
| | | setValOrBlank(sheet, r0, 1, pass == 0 ? null : round(pass, 4)); |
| | | setValOrBlank(sheet, r0, 1, pass == 0 ? null : pass); |
| | | setValOrBlank(sheet, r0, 2, midCumYoy(mid, currentYear, "æ¹åç", maxMonth, dims[i], true)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : round(turn, 4)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : turn); |
| | | setValOrBlank(sheet, r0, 6, midCumYoy(mid, currentYear, "æ¹åç", maxMonth, dims[i], false)); |
| | | } |
| | | // ä¸ååï¼å½æï¼ï¼æ é¢è¡9ãæ°æ®è¡11-15ï¼0-based 8ã10-14ï¼ |
| | |
| | | double turn = midClassVal(mid, currentYear, maxMonth, "æ¹åç", dims[i], false); |
| | | double lastPass = midClassVal(mid, currentYear - 1, maxMonth, "æ¹åç", dims[i], true); |
| | | double lastTurn = midClassVal(mid, currentYear - 1, maxMonth, "æ¹åç", dims[i], false); |
| | | setValOrBlank(sheet, r0, 1, pass == 0 ? null : round(pass, 4)); |
| | | setValOrBlank(sheet, r0, 1, pass == 0 ? null : pass); |
| | | setValOrBlank(sheet, r0, 2, pass == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, "æ¹åç", dims[i], true)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : round(turn, 4)); |
| | | setValOrBlank(sheet, r0, 5, turn == 0 ? null : turn); |
| | | setValOrBlank(sheet, r0, 6, turn == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, "æ¹åç", dims[i], false)); |
| | | } |
| | | // ä¸ååå æ¯å
¬å¼ç±æ ·ä¾æåä¸ååï¼B$3/F$3ï¼ï¼æ¹å为æ¬åæ»è¡ï¼B$11/F$11ï¼ï¼è¡12-15 |
| | |
| | | Cell c = row.getCell(colIdx); |
| | | if (c != null && c.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) return; |
| | | if (c == null) c = row.createCell(colIdx); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(round(v, 2)); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(v); |
| | | } |
| | | |
| | | /** æ¾å¼åå
¥ 0ï¼setDataCell 对 0 ç½®ç©ºï¼æ±æ»è¡¨ç½çº¦è½¦è¡éè¦æ¾ç¤º 0ï¼ */ |
| | |
| | | * ä¿çå
¨é¨é¡µç¾/çå¼/å
¬å¼/2025 å¹´ç¼åå¼ï¼ä»
æè¡¨å¤´å¹´ä»½å¨æåä¸ºç®æ å¹´ï¼æ°æ®å¡«å
æ P2 èµ·éæ¥æ¥å
¥ã |
| | | */ |
| | | public byte[] exportSummaryWorkbook(String period, String mode) throws Exception { |
| | | return exportSummaryWorkbook(period, mode, null); |
| | | return exportSummaryWorkbook(period, mode, null, null); |
| | | } |
| | | |
| | | /** çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxï¼P0-P1 骨æ¶ï¼æ¯æ toMonth è£åªï¼ï¼ |
| | |
| | | * toMonth é空ä¸å°äº M æ¶ï¼æ 8 个å°è´¦/åæé¡µè£å° toMonth æï¼toMonth+1..M ç彿å¼/忝忏
空ãä¿çè¡¨å¤´ï¼ |
| | | * 累计ä¸ç´¯è®¡åæ¯å
¬å¼æ¹ä¸ºæ toMonth æéç®ï¼ï¼ç¨äºâå
çæ 1-6 æã1-7 ææ©åâéªè¯ã */ |
| | | public byte[] exportSummaryWorkbook(String period, String mode, Integer toMonth) throws Exception { |
| | | return exportSummaryWorkbook(period, mode, toMonth, null); |
| | | } |
| | | |
| | | /** åä¸ï¼é¢å¤éè¿ progress åè°æ¥åè¿åº¦ï¼å¼æ¥å¯¼åºä»»å¡ç¨ï¼æ¥éª¤ç¾åæ¯ + æ¥éª¤ææ¡ï¼ */ |
| | | public byte[] exportSummaryWorkbook(String period, String mode, Integer toMonth, |
| | | java.util.function.BiConsumer<Integer, String> progress) throws Exception { |
| | | reportProgress(progress, 2, "æ ¡éªæ¥è¡¨æä¸æ¯ç"); |
| | | int year = Integer.parseInt(period.contains("-") ? period.split("-")[0] : period); |
| | | int month = period.contains("-") ? monthOf(period, mode) : 12; |
| | | File template = resolveSummaryMother(period, mode); |
| | |
| | | throw new RuntimeException("æªæ¾å°æ±æ»è¡¨æ¯çã" + year + "å¹´" + month + "æéè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼docs/çææ±æ»å¤§è¡¨ï¼"); |
| | | } |
| | | double savedZipRatio = ZipSecureFile.getMinInflateRatio(); |
| | | reportProgress(progress, 6, "è¯»åæ¯çå·¥ä½ç°¿"); |
| | | ZipSecureFile.setMinInflateRatio(0.0001); // æ°çæ¯ç styles.xml ç± openpyxl é«å缩ï¼0.0099<0.01ï¼è§¦å POI Zip-bomb 误æ¥ï¼è¯»ååè¿å |
| | | try (InputStream in = new FileInputStream(template); |
| | | XSSFWorkbook wb = new XSSFWorkbook(in)) { |
| | | reportProgress(progress, 12, "è¿ååææåº¦å"); |
| | | File donor = resolveSummaryDonor(year, month); |
| | | if (donor != null) { |
| | | try (InputStream din = new FileInputStream(donor); XSSFWorkbook dwb = new XSSFWorkbook(din)) { |
| | |
| | | int effMonth = (toMonth != null && toMonth > 0 && toMonth < month) ? toMonth : month; |
| | | List<String> dbProblems = new ArrayList<>(); |
| | | String effPeriod = String.format("%04d-%02d", year, effMonth); |
| | | reportProgress(progress, 22, "åå¡«å½ææ°æ®"); |
| | | int dbFilled = summaryWorkbookFiller.fillMonthlyLedger(wb, effPeriod, year, effMonth, dbProblems); |
| | | int yoyFilled = summaryWorkbookFiller.ensureMonthYoyFormulas(wb, year, effMonth); |
| | | int monthFormulaFilled = summaryWorkbookFiller.ensureMonthFormulas(wb, year, effMonth); |
| | | // ç´¯è®¡åæ¯åæ¯ä¿®æ£ï¼æ¯çæãå»å¹´åæãä¸ãå»å¹´1-Mæç´¯è®¡ãè¾
å©ååæ¶è®¡å
¥ï¼éå¤è®¡/æ¼å½æï¼ |
| | | int cumYoyFixed = summaryWorkbookFiller.repairCumulativeYoyFormulas(wb, year, effMonth); |
| | | reportProgress(progress, 45, "å·æ°æå页ä¸è·¨é¡µåæé¡µ"); |
| | | int rankRefreshed = refreshSummaryRankSheets(wb, effPeriod, "month"); |
| | | int cumulativeRefreshed = refreshSummaryCumulativeSheets(wb, year, effMonth); // åå¼ è·¨é¡µåæé¡µéæ¥è¡¨æå·æ° |
| | | int widthApplied = applySummaryReferenceLayout(wb); |
| | | log.info("æ±æ»å·¥ä½ç°¿æ°æ®é©±å¨å填宿ï¼åå
¥å½æå¼æ ¼æ°={}ï¼è¡¥å彿忝å
¬å¼æ ¼æ°={}ï¼è¡¥å彿å计å
¬å¼æ ¼æ°={}ï¼" |
| | | + "å·æ°æå页æ°å¼æ ¼æ°={}ï¼å·æ°å页ï¼å叿±æ»/åå¸åå¸å·/ä¸å£å¾åæ/éè·¯è¿è¾å¨è½¬éï¼æ°å¼æ ¼æ°={}ï¼" |
| | | + "ä¿®æ£ç´¯è®¡åæ¯åæ¯æ ¼æ°={}ï¼å·æ°æå页æ°å¼æ ¼æ°={}ï¼å·æ°å页ï¼å叿±æ»/åå¸åå¸å·/ä¸å£å¾åæ/éè·¯è¿è¾å¨è½¬éï¼æ°å¼æ ¼æ°={}ï¼" |
| | | + "æãçæ_éè·¯è¿è¾éæ±æ»è¡¨ã对é½å宽忰={}ï¼ç¼ºæ°æç¤º={}", |
| | | dbFilled, yoyFilled, monthFormulaFilled, rankRefreshed, cumulativeRefreshed, widthApplied, dbProblems); |
| | | dbFilled, yoyFilled, monthFormulaFilled, cumYoyFixed, rankRefreshed, cumulativeRefreshed, widthApplied, dbProblems); |
| | | applyTwoDecimalFormat(wb); // æ°å¼æ¾ç¤ºä¸¤ä½å°æ°ï¼ä¿çå
¨ç²¾åº¦ï¼ï¼% / æ¥æçæ¢ææ ·å¼ä¸æ¹å |
| | | int inlineFixed = normalizeStaleInlineStrings(wb); // æ¸
æãé inlineStr å´æ®ç <is>ãçéæ³æ ¼ï¼å¦å Excel æç»æå¼ |
| | | if (inlineFixed > 0) log.warn("æ±æ»å·¥ä½ç°¿æ¸
ææ®ç inlineStr éæ³æ ¼ {} ä¸ªï¼æ¯çç± openpyxl ååºæ¶çå
¸åé®é¢ï¼", inlineFixed); |
| | | reportProgress(progress, 70, "éç®æ´æ¬å
¬å¼ï¼çº¦ 4 䏿 ¼ï¼"); |
| | | int[] recalc = recalcWorkbookFormulas(wb); // å
¬å¼éç®å¹¶ååç¼åå¼ï¼å
¨çè¡(Σå¸å·)/累计å/æå SUM æè½è¢«é¢è§ä¸äºæ¬¡å¤çè¯»å° |
| | | log.info("æ±æ»å·¥ä½ç°¿å
¬å¼éç®å®æï¼æå {} æ ¼ï¼å¤±è´¥ {} æ ¼ï¼å¤±è´¥æ ¼ä¿çæ¯çæ§ç¼åå¼ï¼æå¼æ¶æ fullCalcOnLoad éç®ï¼", recalc[0], recalc[1]); |
| | | if (!wb.getCTWorkbook().isSetCalcPr()) wb.getCTWorkbook().addNewCalcPr(); |
| | | wb.getCTWorkbook().getCalcPr().setFullCalcOnLoad(true); // è¿å/æ¹åå
¬å¼åæå¼å³éç® |
| | | reportProgress(progress, 95, "ååºæä»¶"); |
| | | return toBytes(wb); |
| | | } finally { |
| | | ZipSecureFile.setMinInflateRatio(savedZipRatio); |
| | | } |
| | | } |
| | | |
| | | /** 导åºè¿åº¦åè°ï¼å¼æ¥å¯¼åºä»»å¡ç¨ï¼ï¼åè°èªèº«å¼å¸¸ä¸å½±åå¯¼åº */ |
| | | private static void reportProgress(java.util.function.BiConsumer<Integer, String> progress, int percent, String step) { |
| | | if (progress == null) return; |
| | | try { |
| | | progress.accept(percent, step); |
| | | } catch (Exception ignore) { |
| | | // è¿åº¦åè°å¤±è´¥ä¸å½±åå¯¼åº |
| | | } |
| | | } |
| | | |
| | |
| | | if (r.getAvgDistanceCity() != null && r.getAvgDistanceCity() > 0) a[5] = r.getAvgDistanceCity(); |
| | | } |
| | | for (double[] a : map.values()) { |
| | | if (a[4] <= 0 && a[0] > 0) a[4] = round(a[1] / a[0], 2); |
| | | if (a[5] <= 0 && a[2] > 0) a[5] = round(a[3] / a[2], 2); |
| | | if (a[4] <= 0 && a[0] > 0) a[4] = a[1] / a[0]; |
| | | if (a[5] <= 0 && a[2] > 0) a[5] = a[3] / a[2]; |
| | | } |
| | | return map; |
| | | } |
| | |
| | | Row row = sheet.getRow(rowIdx); |
| | | if (row == null) row = sheet.createRow(rowIdx); |
| | | if (a > 0) { |
| | | // 2026å¹´ 1..N æï¼åºå
æå¼åå¡«ï¼2ä½å°æ°ï¼ï¼æ 弿¸
ç©ºæ¨¡æ¿æ ·ä¾ |
| | | // 2026å¹´ 1..N æï¼åºå
æå¼åå¡«ï¼å
¨ç²¾åº¦åå
¥ï¼ä¸¤ä½å°æ°ç±åå
æ ¼æ ¼å¼å±ç¤ºï¼ï¼æ 弿¸
ç©ºæ¨¡æ¿æ ·ä¾ |
| | | for (int m = 1; m <= month; m++) { |
| | | double v = cityVal(monthCity, area, m, k); |
| | | Cell c = row.getCell(2 + (m - 1) * 2); |
| | | if (c == null) c = row.createCell(2 + (m - 1) * 2); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(round(v, 2)); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(v); |
| | | } |
| | | // 2025å¹´ 1..12 æï¼åºå
æå»å¹´æ°æ®åå¡«ï¼å¦åæ¸
ç©ºæ¨¡æ¿æ ·ä¾ |
| | | for (int m = 1; m <= 12; m++) { |
| | | double v = cityVal(lastYearMonthCity, area, m, k); |
| | | Cell c = row.getCell(19 + (m - 1) * 2); |
| | | if (c == null) c = row.createCell(19 + (m - 1) * 2); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(round(v, 2)); |
| | | if (v == 0) c.setBlank(); else c.setCellValue(v); |
| | | } |
| | | } |
| | | rowIdx++; |
| | |
| | | hssfText(row, 0, "å计"); |
| | | InvestAgg prov = new InvestAgg(); |
| | | for (InvestmentMonthly m : monthlies) prov.add(m, pmap.get(m.getProjectId())); |
| | | addProjectsWithoutMonthly(prov, projects, mByProject, null, null); |
| | | writeInvestAggHssf(row, prov); |
| | | continue; |
| | | } |
| | |
| | | InvestmentProject p = pmap.get(m.getProjectId()); |
| | | if (p != null && blockCategory.equals(p.getCategory())) agg.add(m, p); |
| | | } |
| | | addProjectsWithoutMonthly(agg, projects, mByProject, blockCategory, null); |
| | | writeInvestAggHssf(row, agg); |
| | | seq = 0; |
| | | continue; |
| | |
| | | if (p != null && city.equals(p.getCity()) |
| | | && (blockCategory == null || blockCategory.equals(p.getCategory()))) agg.add(m, p); |
| | | } |
| | | addProjectsWithoutMonthly(agg, projects, mByProject, blockCategory, city); |
| | | writeInvestAggHssf(row, agg); |
| | | continue; |
| | | } |
| | |
| | | hssfNum(row, 8, agg.startCum == 0 ? null : agg.startCum); |
| | | hssfNum(row, 9, agg.yearPlan == 0 ? null : agg.yearPlan); |
| | | hssfNum(row, 22, agg.yearCum == 0 ? null : agg.yearCum); |
| | | if (agg.yearPlan > 0) hssfNum(row, 23, round(agg.yearCum / agg.yearPlan, 4)); |
| | | if (agg.yearPlan > 0) hssfNum(row, 23, agg.yearCum / agg.yearPlan); |
| | | } |
| | | |
| | | /** |
| | | * è¡¥è®¡ãæ¬ææ²¡ææåº¦è®°å½ãä½é¡¹ç®ä¸»æ¡£ææ»æèµãç项ç®ï¼åªè®¡æ»æèµè¿ä¸åï¼ã |
| | | * åºæ¯ï¼æå¸å·æ¬ææªæ¥éå表ï¼å¦æ¦æ± 8 æç©æµï¼ï¼ä¸»æ¡£é项ç®ä»å¨ï¼è¥ä¸è¡¥è®¡ï¼è¯¥å¸å·å°è®¡/åè®¡ä¼æ´å为空ã |
| | | * |
| | | * @param category åç±»å«ï¼å®¢è¿ç«åº/ç©æµååºï¼ï¼null 表示ä¸é |
| | | * @param city å¸å·å
¨ç§°ï¼å¦ æ¦æ±å¸ï¼ï¼null 表示ä¸é |
| | | */ |
| | | private void addProjectsWithoutMonthly(InvestAgg agg, List<InvestmentProject> projects, |
| | | Map<Long, InvestmentMonthly> mByProject, |
| | | String category, String city) { |
| | | for (InvestmentProject p : projects) { |
| | | if (p == null || mByProject.containsKey(p.getId())) continue; |
| | | if (category != null && !category.equals(p.getCategory())) continue; |
| | | if (city != null && !city.equals(p.getCity())) continue; |
| | | if (p.getTotalInvestment() != null) agg.total += p.getTotalInvestment(); |
| | | } |
| | | } |
| | | |
| | | |
| | |
| | | putNum(row, 2, s[3] == 0 ? null : s[3]); |
| | | putNum(row, 3, s[4] == 0 ? null : s[4]); |
| | | double b = numOf(row.getCell(1)); |
| | | putNum(row, 4, b > 0 ? round(s[3] / b * 100, 4) : null); |
| | | putNum(row, 4, b > 0 ? s[3] / b * 100 : null); |
| | | cT += s[3]; |
| | | dT += s[4]; |
| | | } |
| | |
| | | putNum(tot, 2, cT == 0 ? null : cT); |
| | | putNum(tot, 3, dT == 0 ? null : dT); |
| | | double b = numOf(tot.getCell(1)); |
| | | putNum(tot, 4, b > 0 ? round(cT / b * 100, 4) : null); |
| | | putNum(tot, 4, b > 0 ? cT / b * 100 : null); |
| | | } |
| | | } |
| | | try { |
| | |
| | | for (InvestmentMonthly m : monthlies) provinceYearPlan += nz(m.getYearPlan()); |
| | | HSSFRow rowOther = s1.getRow(9); |
| | | for (int c = 1; c <= 5; c++) hssfNum(rowOther, c, null); |
| | | hssfNum(rowOther, 5, provinceYearPlan == 0 ? null : round(provinceYearPlan / 10000, 2)); |
| | | hssfNum(rowOther, 5, provinceYearPlan == 0 ? null : provinceYearPlan / 10000); |
| | | // ---- sheet2 è§ä¸é¡¹ç®è¡¨ï¼è¡¨å¤´å¹´ä»½ + å计 + 项ç®è¡ ---- |
| | | HSSFSheet s2 = wb.getSheetAt(1); |
| | | hssfText(s2.getRow(0), 0, year + "年交é建设项ç®å¨å¤æ
åµï¼è§æ¨¡ä»¥ä¸é¡¹ç®ï¼"); |
| | |
| | | private double nz(Double v) { |
| | | return v == null ? 0.0 : v; |
| | | } |
| | | /** æ°å¼æ ¼å¼é 3 ä½å以ä¸çå°æ°é¨åï¼å¦ 0.0000 / 0.000_ ï¼ */ |
| | | private static final java.util.regex.Pattern DEC_MORE_THAN_TWO = java.util.regex.Pattern.compile("\\.0{3,}"); |
| | | /** çæè¡¨æ°å¼åç»ä¸æ ·å¼ï¼ä¿çå
¨ç²¾åº¦æ°å¼ï¼æ¾ç¤ºä¸¤ä½å°æ°ï¼æ´æ°å¼ä¸ %/æ¥æ/ç§å¦è®¡æ°çæ¢ææ ·å¼ä¸æ¹å */ |
| | | private void applyTwoDecimalFormat(org.apache.poi.ss.usermodel.Workbook wb) { |
| | | if (wb == null) return; |
| | |
| | | CellType ct = cell.getCellType(); |
| | | if (ct != CellType.NUMERIC && ct != CellType.FORMULA) continue; |
| | | if (org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(cell)) continue; |
| | | boolean integral = false; |
| | | if (ct == CellType.NUMERIC) { |
| | | integral = Math.rint(cell.getNumericCellValue()) == cell.getNumericCellValue(); |
| | | } else if (cell.getCachedFormulaResultType() == CellType.NUMERIC) { |
| | | integral = Math.rint(cell.getNumericCellValue()) == cell.getNumericCellValue(); |
| | | } |
| | | if (integral) continue; // æ´æ°ä¸æ¾ç¤º .00ï¼å«å
¬å¼ç»æä¸ºæ´æ°çæ ¼ï¼ |
| | | org.apache.poi.ss.usermodel.CellStyle cs = cell.getCellStyle(); |
| | | if (cs == null) continue; |
| | | String f = cs.getDataFormatString(); |
| | | if (f == null) f = ""; |
| | | if (f.contains("%") || f.contains("E") || f.contains("0.00")) continue; |
| | | boolean plain = f.isEmpty() || "General".equals(f) || "general".equals(f) |
| | | || "0".equals(f) || "#,##0".equals(f) || "0.0".equals(f) || "#,##0.0".equals(f); |
| | | if (!plain) continue; |
| | | if (f.contains("%") || f.contains("E") || f.contains("@")) continue; |
| | | String normalized = null; |
| | | if (DEC_MORE_THAN_TWO.matcher(f).find()) { |
| | | // æ¯çä¸ªå«æ ¼å¸¦ 3~4 ä½å°æ°æ ¼å¼ï¼å¦ 0.000_ ã0.0000_);[Red]\(0.0000\)ï¼ï¼æ°å¼ä»å
¨ç²¾åº¦ï¼ |
| | | // å±ç¤ºç»ä¸æ¶æå°ä¸¤ä½ãè¿ç±»æ ¼æ¬å°±ææ°å¼æ ¼å¼å±ç¤ºï¼æ
ä¸åãæ´æ°ä¸æ¾ç¤º .00ãä¿æ¤å½±åã |
| | | normalized = DEC_MORE_THAN_TWO.matcher(f).replaceAll(".00"); |
| | | } else { |
| | | boolean integral = false; |
| | | if (ct == CellType.NUMERIC) { |
| | | integral = Math.rint(cell.getNumericCellValue()) == cell.getNumericCellValue(); |
| | | } else if (cell.getCachedFormulaResultType() == CellType.NUMERIC) { |
| | | integral = Math.rint(cell.getNumericCellValue()) == cell.getNumericCellValue(); |
| | | } |
| | | if (integral) continue; // æ´æ°ä¸æ¾ç¤º .00ï¼å«å
¬å¼ç»æä¸ºæ´æ°çæ ¼ï¼ |
| | | if (f.contains("0.00")) continue; |
| | | boolean plain = f.isEmpty() || "General".equals(f) || "general".equals(f) |
| | | || "0".equals(f) || "#,##0".equals(f) || "0.0".equals(f) || "#,##0.0".equals(f); |
| | | if (!plain) continue; |
| | | } |
| | | org.apache.poi.ss.usermodel.CellStyle ns = wb.createCellStyle(); |
| | | ns.cloneStyleFrom(cs); |
| | | ns.setDataFormat(fmtTwo); |
| | | ns.setDataFormat(normalized == null ? fmtTwo : df.getFormat(normalized)); |
| | | cell.setCellStyle(ns); |
| | | } catch (Exception ignore) { |
| | | // 个å«åå
æ ¼æ ¼å¼å¼å¸¸ä¸é»å¡å¯¼åº |
| New file |
| | |
| | | package com.trafficaudit.reportexport.service; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.trafficaudit.dataimport.entity.ImportBatch; |
| | | import com.trafficaudit.dataimport.mapper.ImportBatchMapper; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import javax.annotation.PreDestroy; |
| | | import javax.annotation.Resource; |
| | | import java.util.Date; |
| | | import java.util.Iterator; |
| | | import java.util.LinkedHashMap; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.UUID; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.ExecutorService; |
| | | import java.util.concurrent.Executors; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * æ¥è¡¨å¯¼åºå¼æ¥ä»»å¡ï¼æèæ¶åå ç§çãçæ_éè·¯è¿è¾éæ±æ»è¡¨ãçææªå°åå°çº¿ç¨ï¼ |
| | | * åç«¯åªæ¿ãä»»å¡å· + è¿åº¦ï¼æ¥éª¤/ç¾åæ¯ï¼ãï¼å®æååç¬ä¸è½½æä»¶ã |
| | | * |
| | | * ç®çï¼2026-09-20 ç¨æ·ä¸æ¥ãç¹ä¸è½½è¦çä¸ä¼ï¼æ°æ®å¤äºä¼ä¸ä¼å¡æ»ãï¼ï¼ |
| | | * 1) ç¹å»åç«å»æåé¦ï¼ä¸åé¿æ¶é´æ ååºï¼ |
| | | * 2) çæè¿ç¨ä¸å ç¨ HTTP 请æ±çº¿ç¨ï¼é¿å
å¤äººåæ¶ç¹æå®¹å¨ææ»ï¼å·¥ä½çº¿ç¨åºå® 1 个ï¼å¤ä½è¯·æ±æ¾ç¤ºãæéä¸ãï¼ï¼ |
| | | * 3) å䏿¥è¡¨æ 10 åéå
çç»æå¯å¤ç¨ï¼é¿å
æ¯æ¬¡éç®æ´æ¬çº¦ 4 䏿 ¼å
¬å¼ã |
| | | * |
| | | * ç¼åæ£ç¡®æ§å®å«ï¼åªæå½ãè·ä¸æ¬¡çæä¸è¶
è¿ TTLãä¸ãæé´æ²¡æä»»ä½æ°çæ°æ®å¯¼å
¥ï¼import_batch æå¤§ id æªåï¼ã |
| | | * æ¶æå¤ç¨ï¼å¯¼å
¥å³å¤±æï¼é¿å
æè¿ææ¥è¡¨ç»ç¨æ·ãåç«¯ä»æä¾ãéæ°çæã强å¶å·æ°ã |
| | | */ |
| | | @Slf4j |
| | | @Service |
| | | public class ReportExportTaskService { |
| | | |
| | | /** æ±æ»å·¥ä½ç°¿å¯¼åºä»»å¡ç±»å */ |
| | | public static final String TYPE_SUMMARY_WORKBOOK = "summaryWorkbook"; |
| | | |
| | | /** çæç»æä¿çæ¶é¿ï¼æé´å¯åå¤ä¸è½½ï¼è¿åèªå¨æ¸
ç */ |
| | | private static final long RESULT_TTL_MS = 30 * 60 * 1000L; |
| | | /** å䏿¥è¡¨æç»æå¤ç¨æ¶é¿ï¼ä¸æé´æ æ°å¯¼å
¥æ¶æå¤ç¨ï¼ */ |
| | | private static final long CACHE_TTL_MS = 10 * 60 * 1000L; |
| | | |
| | | @Resource |
| | | private ReportExportService reportService; |
| | | @Resource |
| | | private ImportBatchMapper importBatchMapper; |
| | | |
| | | private final Map<String, Task> tasks = new ConcurrentHashMap<>(); |
| | | /** åæ¥è¡¨ææè¿ä¸æ¬¡æåç»æï¼key -> task */ |
| | | private final Map<String, Task> cache = new ConcurrentHashMap<>(); |
| | | private final ExecutorService pool = Executors.newFixedThreadPool(1, r -> { |
| | | Thread t = new Thread(r, "report-export-task"); |
| | | t.setDaemon(true); |
| | | return t; |
| | | }); |
| | | |
| | | /** 䏿¬¡å¯¼åºä»»å¡ï¼å
åæï¼è¿ç¨éå¯å³å¤±æï¼ */ |
| | | public static class Task { |
| | | private final String id = UUID.randomUUID().toString().replace("-", ""); |
| | | private final String type; |
| | | private final String period; |
| | | private final String mode; |
| | | private final Integer toMonth; |
| | | private final long createdAt = System.currentTimeMillis(); |
| | | /** çææ¶çæ°æ®çæ¬ï¼import_batch æå¤§ idï¼ï¼ç¨äºå¤æç¼åæ¯å¦è¿æ */ |
| | | private final long importVersion; |
| | | private volatile String status = "PENDING"; // PENDING/RUNNING/DONE/FAILED |
| | | private volatile int percent = 0; |
| | | private volatile String step = "æéä¸"; |
| | | private volatile String error; |
| | | private volatile byte[] data; |
| | | private volatile String fileName; |
| | | private volatile boolean fromCache; |
| | | private volatile long finishedAt; |
| | | |
| | | Task(String type, String period, String mode, Integer toMonth, long importVersion) { |
| | | this.type = type; |
| | | this.period = period; |
| | | this.mode = mode; |
| | | this.toMonth = toMonth; |
| | | this.importVersion = importVersion; |
| | | } |
| | | |
| | | void progress(int pct, String stepText) { |
| | | if (pct > this.percent) this.percent = Math.min(pct, 99); |
| | | if (stepText != null) this.step = stepText; |
| | | } |
| | | |
| | | public String getId() { return id; } |
| | | |
| | | public String getStatus() { return status; } |
| | | |
| | | public boolean isDone() { return "DONE".equals(status) && data != null; } |
| | | |
| | | public boolean isFromCache() { return fromCache; } |
| | | |
| | | public byte[] getData() { return data; } |
| | | |
| | | public String getFileName() { return fileName; } |
| | | |
| | | public String getError() { return error; } |
| | | |
| | | public Map<String, Object> toView() { |
| | | Map<String, Object> m = new LinkedHashMap<>(); |
| | | m.put("taskId", id); |
| | | m.put("type", type); |
| | | m.put("period", period); |
| | | m.put("mode", mode); |
| | | m.put("toMonth", toMonth); |
| | | m.put("status", status); |
| | | m.put("percent", "DONE".equals(status) ? 100 : percent); |
| | | m.put("step", step); |
| | | m.put("fromCache", fromCache); |
| | | m.put("fileName", fileName); |
| | | m.put("error", error); |
| | | long end = finishedAt > 0 ? finishedAt : System.currentTimeMillis(); |
| | | m.put("elapsedMs", end - createdAt); |
| | | m.put("finishedAt", finishedAt > 0 ? new Date(finishedAt) : null); |
| | | return m; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æäº¤å¯¼åºä»»å¡ãforceRefresh=true æ¶å¿½ç¥ç¼åéæ°çæï¼ |
| | | * å¦åå¨ãå䏿¥è¡¨æã10 åéå
ãæé´æ æ°å¯¼å
¥ãçåæä¸ç´æ¥å¤ç¨ä¸æ¬¡ç»æã |
| | | * å䏿¥è¡¨æå·²æä»»å¡å¨è·æ¶ç´æ¥è¿å该任å¡ï¼é¿å
é夿éã |
| | | */ |
| | | public Task submit(String type, String period, String mode, Integer toMonth, boolean forceRefresh) { |
| | | cleanupExpired(); |
| | | String key = cacheKey(type, period, mode, toMonth); |
| | | if (!forceRefresh) { |
| | | Task hit = cache.get(key); |
| | | if (cacheUsable(hit)) { |
| | | hit.fromCache = true; |
| | | log.info("æ¥è¡¨å¯¼åºä»»å¡å½ä¸ç¼åï¼{} {}ï¼çæäº {}ï¼", type, period, new Date(hit.finishedAt)); |
| | | return hit; |
| | | } |
| | | } |
| | | Task running = findRunning(key); |
| | | if (running != null) { |
| | | log.info("æ¥è¡¨å¯¼åºä»»å¡å·²å¨æ§è¡ï¼å¤ç¨è¿è¡ä¸çä»»å¡ï¼{} {}ï¼{}ï¼", type, period, running.id); |
| | | return running; |
| | | } |
| | | Task task = new Task(type, period, mode, toMonth, importVersion()); |
| | | tasks.put(task.id, task); |
| | | pool.submit(() -> run(task)); |
| | | return task; |
| | | } |
| | | |
| | | public Task get(String taskId) { |
| | | if (taskId == null) return null; |
| | | cleanupExpired(); |
| | | return tasks.get(taskId); |
| | | } |
| | | |
| | | private void run(Task t) { |
| | | t.status = "RUNNING"; |
| | | t.step = "å¼å§çæ"; |
| | | long start = System.currentTimeMillis(); |
| | | try { |
| | | byte[] data = reportService.exportSummaryWorkbook(t.period, t.mode, t.toMonth, t::progress); |
| | | t.data = data; |
| | | t.fileName = "çæ_éè·¯è¿è¾éæ±æ»è¡¨_" + t.period + ".xlsx"; |
| | | t.step = "宿"; |
| | | t.status = "DONE"; |
| | | t.finishedAt = System.currentTimeMillis(); |
| | | cache.put(cacheKey(t.type, t.period, t.mode, t.toMonth), t); |
| | | log.info("æ¥è¡¨å¯¼åºä»»å¡å®æï¼{} {} ç¨æ¶ {} msï¼{} åè", t.type, t.period, t.finishedAt - start, data.length); |
| | | } catch (Throwable e) { |
| | | t.status = "FAILED"; |
| | | t.error = e.getMessage() == null ? e.toString() : e.getMessage(); |
| | | t.step = "çæå¤±è´¥"; |
| | | t.finishedAt = System.currentTimeMillis(); |
| | | log.error("æ¥è¡¨å¯¼åºä»»å¡å¤±è´¥ï¼{} {}ï¼ç¨æ¶ {} msï¼", t.type, t.period, t.finishedAt - start, e); |
| | | } |
| | | } |
| | | |
| | | private Task findRunning(String key) { |
| | | for (Task t : tasks.values()) { |
| | | if (!key.equals(cacheKey(t.type, t.period, t.mode, t.toMonth))) continue; |
| | | if ("PENDING".equals(t.status) || "RUNNING".equals(t.status)) return t; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | private boolean cacheUsable(Task t) { |
| | | if (t == null || !"DONE".equals(t.status) || t.data == null) return false; |
| | | if (System.currentTimeMillis() - t.finishedAt > CACHE_TTL_MS) return false; |
| | | long now = importVersion(); |
| | | if (now < 0 || t.importVersion < 0) return false; // åä¸å°æ°æ®çæ¬æ¶ä¸åé£é©å¤ç¨ |
| | | return now == t.importVersion; |
| | | } |
| | | |
| | | /** æ°æ®çæ¬ï¼import_batch æå¤§ idï¼ä»»ä½ä¸æ¬¡å¯¼å
¥é½ä¼è®©å®ååï¼åä¸å°è¿å -1ï¼æ¤æ¶ç¦ç¨ç¼åï¼ */ |
| | | private long importVersion() { |
| | | try { |
| | | List<Object> v = importBatchMapper.selectObjs(new QueryWrapper<ImportBatch>().select("IFNULL(MAX(id),0)")); |
| | | if (v == null || v.isEmpty() || v.get(0) == null) return 0L; |
| | | return ((Number) v.get(0)).longValue(); |
| | | } catch (Exception e) { |
| | | log.warn("读å导å
¥æ°æ®çæ¬å¤±è´¥ï¼æ¬æ¬¡ç¦ç¨å¯¼åºç¼åï¼{}", e.getMessage()); |
| | | return -1L; |
| | | } |
| | | } |
| | | |
| | | private String cacheKey(String type, String period, String mode, Integer toMonth) { |
| | | return type + "|" + period + "|" + mode + "|" + (toMonth == null ? "" : toMonth); |
| | | } |
| | | |
| | | private void cleanupExpired() { |
| | | long now = System.currentTimeMillis(); |
| | | for (Iterator<Map.Entry<String, Task>> it = tasks.entrySet().iterator(); it.hasNext(); ) { |
| | | Task t = it.next().getValue(); |
| | | if (t.finishedAt > 0 && now - t.finishedAt > RESULT_TTL_MS) it.remove(); |
| | | } |
| | | for (Iterator<Map.Entry<String, Task>> it = cache.entrySet().iterator(); it.hasNext(); ) { |
| | | Task t = it.next().getValue(); |
| | | if (t.finishedAt <= 0 || now - t.finishedAt > CACHE_TTL_MS) it.remove(); |
| | | } |
| | | } |
| | | |
| | | @PreDestroy |
| | | public void shutdown() { |
| | | pool.shutdownNow(); |
| | | try { |
| | | pool.awaitTermination(3, TimeUnit.SECONDS); |
| | | } catch (InterruptedException e) { |
| | | Thread.currentThread().interrupt(); |
| | | } |
| | | } |
| | | } |
| | |
| | | :disabled="clearScope === 'types' && !clearTypes.length" @click="confirmClear">确认æ¸
空</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | <!-- 导å
¥ç»æå¼¹çªï¼å¯æå¨ãå
å®¹åºæ»å¨ãåºé¨æé®åºå®å¯è§ï¼å $alert å
å®¹é¿æ¶åºé¨æé®ä¼è¢«æ¤åºå±å¹ï¼ --> |
| | | <el-dialog :title="resultDialog.title" :visible.sync="resultDialog.visible" width="860px" top="5vh" |
| | | append-to-body :close-on-click-modal="false" custom-class="import-result-dialog" v-dialog-drag> |
| | | <div v-if="resultDialog.level" class="ird-level" :class="'ird-' + resultDialog.level"> |
| | | {{ resultDialog.level === 'error' ? '导å
¥å¤±è´¥' : (resultDialog.level === 'warning' ? 'åå¨éè¦ç¡®è®¤çå
容' : '导å
¥æå') }} |
| | | </div> |
| | | <div class="ird-body" v-html="resultDialog.html"></div> |
| | | <span slot="footer"> |
| | | <el-button v-if="resultDialog.rows.length" size="small" icon="el-icon-download" |
| | | @click="exportResultDialog">å¯¼åºæç»</el-button> |
| | | <el-button type="primary" @click="resultDialog.visible = false">确认</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | </el-main> |
| | | </el-container> |
| | | </el-container> |
| | |
| | | clearDialog: false, |
| | | clearScope: 'all', |
| | | clearTypes: [], |
| | | resultDialog: { visible: false, title: '', html: '', rows: [], columns: [], fileName: '', level: '' }, |
| | | sideOpen: false, |
| | | result: '', |
| | | error: '', |
| | |
| | | (f.city ? 'ï¼' + f.city + 'ï¼' : '') + 'ï¼è§£æ ' + (f.success || 0) + ' æ¡' + |
| | | (f.error ? ' <span style="color:#F56C6C">' + f.error + '</span>' : '') + '</div>' |
| | | ).join('') |
| | | this.$alert(html, (label || type) + ' æ¹é导å
¥å®æï¼å
± ' + d.total + ' 个æä»¶' + |
| | | (d.fail > 0 ? 'ï¼å¤±è´¥ ' + d.fail + ' æ¡' : '') + 'ï¼æå ' + d.success + ' æ¡ï¼', { |
| | | dangerouslyUseHTMLString: true, |
| | | type: errCount > 0 ? 'warning' : 'success', |
| | | confirmButtonText: 'ç¥éäº' |
| | | this.showResultDialog({ |
| | | title: (label || type) + ' æ¹é导å
¥å®æï¼å
± ' + d.total + ' 个æä»¶' + |
| | | (d.fail > 0 ? 'ï¼å¤±è´¥ ' + d.fail + ' æ¡' : '') + 'ï¼æå ' + d.success + ' æ¡ï¼', |
| | | html: html, |
| | | level: errCount > 0 ? 'warning' : 'success', |
| | | columns: [{ key: 'fileName', label: 'æä»¶å' }, { key: 'city', label: 'å¸å·' }, |
| | | { key: 'success', label: 'è§£ææ¡æ°' }, { key: 'error', label: 'é误' }], |
| | | rows: files.map(f => ({ fileName: f.fileName || '', city: f.city || '', success: f.success || 0, error: f.error || '' })), |
| | | fileName: (label || 'æ¹é导å
¥') + '_' + this.period + '_导å
¥ç»æ' |
| | | }) |
| | | if (type === 'investment' || type === 'investmentLogistics') { |
| | | this.checkInvest(this.period) |
| | |
| | | (f.city ? 'ï¼' + f.city + 'ï¼' : '') + 'ï¼è§£æ ' + (f.success || 0) + ' 个项ç®' + |
| | | (f.error ? ' <span style="color:#F56C6C">' + f.error + '</span>' : '') + '</div>' |
| | | ).join('') |
| | | this.$alert(html, 'å¸å·å表æ¹é导å
¥å®æï¼å
± ' + d.total + ' æ¡ï¼æå ' + d.success + ' æ¡' + |
| | | (d.fail > 0 ? 'ï¼å¤±è´¥ ' + d.fail + ' æ¡' : '') + |
| | | 'ï¼åäºäºé¡¹ç®å¹é
' + d.fiveYearMatched + '/' + d.fiveYearTemplateProjects + 'ï¼', { |
| | | dangerouslyUseHTMLString: true, |
| | | type: errCount > 0 ? 'warning' : 'success', |
| | | confirmButtonText: 'ç¥éäº' |
| | | this.showResultDialog({ |
| | | title: 'å¸å·å表æ¹é导å
¥å®æï¼å
± ' + d.total + ' æ¡ï¼æå ' + d.success + ' æ¡' + |
| | | (d.fail > 0 ? 'ï¼å¤±è´¥ ' + d.fail + ' æ¡' : '') + |
| | | 'ï¼åäºäºé¡¹ç®å¹é
' + d.fiveYearMatched + '/' + d.fiveYearTemplateProjects + 'ï¼', |
| | | html: html, |
| | | level: errCount > 0 ? 'warning' : 'success', |
| | | columns: [{ key: 'fileName', label: 'æä»¶å' }, { key: 'city', label: 'å¸å·' }, |
| | | { key: 'success', label: 'è§£æé¡¹ç®æ°' }, { key: 'error', label: 'é误' }], |
| | | rows: files.map(f => ({ fileName: f.fileName || '', city: f.city || '', success: f.success || 0, error: f.error || '' })), |
| | | fileName: 'å¸å·å表导å
¥ç»æ_' + this.period |
| | | }) |
| | | this.afterImport() |
| | | }) |
| | |
| | | const text = (msg && msg.indexOf('导å
¥') !== -1) ? msg : 'æ°æ®å¯¼å
¥æå' |
| | | this.$message({ message: text, type: 'success', duration: 5000 }) |
| | | } else { |
| | | this.$alert((msg || 'æ°æ®å¯¼å
¥å¤±è´¥ï¼è¯¦è§ä¸æ¹å¤±è´¥è®°å½').replace(/\n/g, '<br>'), 'æ°æ®å¯¼å
¥å¤±è´¥', { |
| | | dangerouslyUseHTMLString: true, |
| | | type: 'error', |
| | | confirmButtonText: 'ç¥éäº' |
| | | this.showResultDialog({ |
| | | title: 'æ°æ®å¯¼å
¥å¤±è´¥', |
| | | html: (msg || 'æ°æ®å¯¼å
¥å¤±è´¥ï¼è¯¦è§ä¸æ¹å¤±è´¥è®°å½').replace(/\n/g, '<br>'), |
| | | level: 'error' |
| | | }) |
| | | } |
| | | }, |
| | |
| | | '<br/>å®é
ï¼' + (x.actualValue || '') + 'ãåºåï¼' + (x.thresholdValue || '') + |
| | | '<br/>å·®å¼ï¼' + (x.deviation || '') + '</div>' |
| | | }).join('') |
| | | this.$alert(html, 'æèµæ°æ®ä¸æèµç³»ç»ä¸ä¸è´ï¼' + pending.length + ' æ¡ï¼', { |
| | | dangerouslyUseHTMLString: true, type: 'warning', confirmButtonText: 'ç¥éäº' |
| | | this.showResultDialog({ |
| | | title: 'æèµæ°æ®ä¸æèµç³»ç»ä¸ä¸è´ï¼' + pending.length + ' æ¡ï¼', |
| | | html: html, |
| | | level: 'warning', |
| | | columns: [{ key: 'rule', label: 'è§å' }, { key: 'name', label: '项ç®/ä¼ä¸' }, |
| | | { key: 'actual', label: 'å®é
å¼' }, { key: 'base', label: 'åºåå¼' }, { key: 'dev', label: 'å·®å¼' }], |
| | | rows: pending.map(x => ({ |
| | | rule: x.ruleName || '', |
| | | name: x.enterpriseName || x.actualValue || '', |
| | | actual: x.actualValue || '', |
| | | base: x.thresholdValue || '', |
| | | dev: x.deviation || '' |
| | | })), |
| | | fileName: 'æèµæ°æ®ä¸æèµç³»ç»ä¸ä¸è´_' + this.period |
| | | }) |
| | | } else { |
| | | this.$message.success('已䏿èµç³»ç»æ ¸å¯¹ï¼æ¬ææ°æ®ä¸è´') |
| | | } |
| | | }) |
| | | .catch(() => {}) |
| | | }, |
| | | showResultDialog(opts) { |
| | | const o = opts || {} |
| | | this.resultDialog = { |
| | | visible: true, |
| | | title: o.title || '导å
¥ç»æ', |
| | | html: o.html || '', |
| | | level: o.level || '', |
| | | rows: o.rows || [], |
| | | columns: o.columns || [], |
| | | fileName: o.fileName || ('导å
¥ç»æ_' + (this.period || '')) |
| | | } |
| | | }, |
| | | exportResultDialog() { |
| | | const cols = this.resultDialog.columns || [] |
| | | const rows = this.resultDialog.rows || [] |
| | | if (!cols.length || !rows.length) { this.$message.warning('没æå¯å¯¼åºçæç»'); return } |
| | | const esc = v => '"' + String(v === null || v === undefined ? '' : v).replace(/"/g, '""') + '"' |
| | | const lines = [cols.map(c => esc(c.label)).join(',')] |
| | | rows.forEach(r => lines.push(cols.map(c => esc(r[c.key])).join(','))) |
| | | const blob = new Blob(['\ufeff' + lines.join('\r\n')], { type: 'text/csv;charset=utf-8' }) |
| | | const url = URL.createObjectURL(blob) |
| | | const a = document.createElement('a') |
| | | a.href = url |
| | | a.download = this.resultDialog.fileName + '.csv' |
| | | document.body.appendChild(a) |
| | | a.click() |
| | | document.body.removeChild(a) |
| | | URL.revokeObjectURL(url) |
| | | }, |
| | | parseFailDetails(row) { |
| | | if (!row || !row.errorDetail) return [] |
| | |
| | | .module-tabs-head { margin-bottom: 10px; } |
| | | .module-tab-pane { min-height: 120px; } |
| | | </style> |
| | | |
| | | <style> |
| | | /* 导å
¥ç»æå¼¹çªï¼el-dialog é»è®¤ append-to-bodyï¼DOM æå¨ body ä¸ï¼scoped éæ©å¨å¹é
ä¸å°ï¼å¿
é¡»åå
¨å± */ |
| | | .import-result-dialog { border-radius: 10px; overflow: hidden; } |
| | | .import-result-dialog .el-dialog__header { cursor: move; user-select: none; -webkit-user-select: none; } |
| | | .import-result-dialog .el-dialog__headerbtn { cursor: pointer; } |
| | | .import-result-dialog .el-dialog__body { max-height: calc(100vh - 210px); overflow-y: auto; overscroll-behavior: contain; padding: 12px 20px; } |
| | | .import-result-dialog .el-dialog__footer { border-top: 1px solid #EBEEF5; padding: 10px 20px; } |
| | | .import-result-dialog .ird-body { line-height: 1.7; font-size: 13px; color: #303133; } |
| | | .import-result-dialog .ird-level { margin-bottom: 8px; font-weight: 600; } |
| | | .import-result-dialog .ird-success { color: #67C23A; } |
| | | .import-result-dialog .ird-warning { color: #E6A23C; } |
| | | .import-result-dialog .ird-error { color: #F56C6C; } |
| | | </style> |
| | |
| | | <el-button size="small" type="primary" @click="saveNote">ä¿å</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | |
| | | <!-- æ±æ»å¤§è¡¨å¼æ¥çæè¿åº¦ï¼çæä¸æ¬¡çº¦ 10~20 ç§ï¼é¿å
ç¹å»åé¿æ¶é´æ ååºï¼ --> |
| | | <el-dialog title="æ£å¨çææ±æ»å¤§è¡¨" :visible.sync="taskVisible" width="460px" |
| | | :close-on-click-modal="false" :show-close="taskFinished"> |
| | | <div class="task-body"> |
| | | <el-progress :percentage="taskInfo.percent || 0" :status="taskInfo.status === 'FAILED' ? 'exception' : (taskDone ? 'success' : null)" |
| | | :stroke-width="14"></el-progress> |
| | | <p class="task-step">{{ taskInfo.step || 'æéä¸' }}</p> |
| | | <p class="task-meta" v-if="taskInfo.period">æ¥è¡¨æ {{ taskInfo.period }}ã{{ taskInfo.fromCache ? '䏿¬¡çæç¨æ¶' : 'å·²ç¨' }} {{ (taskInfo.elapsedMs / 1000).toFixed(1) }} ç§</p> |
| | | <p class="task-meta" v-if="taskInfo.fromCache">æ¬æ¬¡ç´æ¥ä½¿ç¨ {{ taskCacheTime }} çæçç»æï¼10 åéå
䏿鴿²¡ææ°å¯¼å
¥æ°æ®ï¼ãå¦éæææ°æ°æ®éç®ï¼è¯·ç¹ãéæ°çæãã</p> |
| | | <p class="task-error" v-if="taskInfo.status === 'FAILED'">{{ taskInfo.error }}</p> |
| | | </div> |
| | | <span slot="footer"> |
| | | <el-button size="small" type="primary" :disabled="!taskDone" @click="downloadTaskFile">{{ taskInfo.fromCache ? 'ä¸è½½' : 'ä¿åæä»¶' }}</el-button> |
| | | <el-button size="small" :disabled="taskRunning" @click="restartTask">éæ°çæ</el-button> |
| | | <el-button size="small" v-if="taskRunning" @click="minimizeTask">åå°è¿è¡</el-button> |
| | | <el-button size="small" v-else @click="closeTask">å
³é</el-button> |
| | | </span> |
| | | </el-dialog> |
| | | </el-main> |
| | | </el-container> |
| | | </el-container> |
| | |
| | | noteDialogVisible: false, |
| | | noteEditingKey: '', |
| | | noteDraft: '', |
| | | // æ±æ»å¤§è¡¨å¼æ¥çæä»»å¡ |
| | | taskVisible: false, |
| | | taskInfo: {}, |
| | | taskTimer: null, |
| | | taskKey: 'summaryWorkbook', |
| | | modules: [ |
| | | { |
| | | key: 'summary', title: 'æ±æ»å¤§è¡¨', items: [ |
| | |
| | | options: months.map(mo => ({ label: y + 'å¹´' + mo + 'æ', value: y + '-' + String(mo).padStart(2, '0') })) |
| | | })) |
| | | }, |
| | | // ===== 以ä¸ä¸ºæ±æ»å¤§è¡¨å¼æ¥çæå¼¹çªçæ´¾çç¶æï¼å¿
须并å
¥åä¸ä¸ª computedï¼å¦èµ·åå key ä¼è¦çæä¸é¢ç计ç®å±æ§ï¼===== |
| | | taskRunning() { |
| | | const s = this.taskInfo && this.taskInfo.status |
| | | return s === 'PENDING' || s === 'RUNNING' |
| | | }, |
| | | taskDone() { |
| | | return this.taskInfo && this.taskInfo.status === 'DONE' |
| | | }, |
| | | // çæç»æï¼æåæå¤±è´¥ï¼åæå
许æ¶èµ·å¼¹çª |
| | | taskFinished() { |
| | | const s = this.taskInfo && this.taskInfo.status |
| | | return s === 'DONE' || s === 'FAILED' |
| | | }, |
| | | taskCacheTime() { |
| | | const t = this.taskInfo && this.taskInfo.finishedAt |
| | | if (!t) return '䏿¬¡' |
| | | const d = new Date(t) |
| | | const p = (n) => String(n).padStart(2, '0') |
| | | return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds()) |
| | | } |
| | | }, |
| | | watch: { |
| | | activeKey() { |
| | |
| | | this.activeKey = (mine.length ? mine : this.visibleModules.map(m => m.key))[0] |
| | | this.ensureCycle() |
| | | this.refreshAll() |
| | | }, methods: { |
| | | }, |
| | | beforeDestroy() { |
| | | this.stopTaskPolling() |
| | | }, |
| | | methods: { |
| | | moduleTitle(key) { |
| | | const m = this.modules.find(x => x.key === key) |
| | | return m ? m.title : key |
| | |
| | | { |
| | | name: 'é路货è¿', |
| | | rows: mk([ |
| | | ['å½æè´§è¿é(ä¸å¨)', 'å
¨çè´§è¿éÂ·å½æ'], |
| | | ['å½æè´§ç©å¨è½¬é(ä¸å¨)', 'å
¨çè´§ç©å¨è½¬éÂ·å½æ', 'å
¨çè´§ç©å¨è½¬éÂ·å½æåæ¯'], |
| | | ['累计货è¿é(ä¸å¨)', 'å
¨çè´§è¿é·累计'], |
| | | ['å½æè´§è¿é(ä¸å¨)', 'å
¨çè´§è¿éÂ·å½æ', 'å
¨çè´§è¿éÂ·å½æåæ¯'], |
| | | ['å½æè´§ç©å¨è½¬é(ä¸å¨å
¬é)', 'å
¨çè´§ç©å¨è½¬éÂ·å½æ', 'å
¨çè´§ç©å¨è½¬éÂ·å½æåæ¯'], |
| | | ['累计货è¿é(ä¸å¨)', 'å
¨çè´§è¿é·累计', 'å
¨çè´§è¿éÂ·ç´¯è®¡åæ¯'], |
| | | ['累计货ç©å¨è½¬é(ä¸å¨å
¬é)', 'å
¨çè´§ç©å¨è½¬é·累计', 'å
¨çè´§ç©å¨è½¬éÂ·ç´¯è®¡åæ¯'] |
| | | ]) |
| | | }, |
| | | { |
| | | name: 'åå¸å®¢è¿', |
| | | rows: mk([ |
| | | ['彿åå¸å®¢è¿é:', 'åå¸å®¢è¿éÂ·å½æ'], |
| | | ['彿åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬éÂ·å½æ'], |
| | | ['累计åå¸å®¢è¿é:', 'åå¸å®¢è¿é·累计'], |
| | | ['累计åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬é·累计'] |
| | | ['彿åå¸å®¢è¿é', 'åå¸å®¢è¿éÂ·å½æ', 'åå¸å®¢è¿éÂ·å½æåæ¯'], |
| | | ['彿åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬éÂ·å½æ', 'åå¸å®¢è¿å¨è½¬éÂ·å½æåæ¯'], |
| | | ['累计åå¸å®¢è¿é', 'åå¸å®¢è¿é·累计', 'åå¸å®¢è¿éÂ·ç´¯è®¡åæ¯'], |
| | | ['累计åå¸å®¢è¿å¨è½¬é', 'åå¸å®¢è¿å¨è½¬é·累计', 'åå¸å®¢è¿å¨è½¬éÂ·ç´¯è®¡åæ¯'] |
| | | ]) |
| | | }, |
| | | { |
| | | name: 'ä¸å£å¾', |
| | | rows: mk([ |
| | | ['彿ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿éÂ·å½æ'], |
| | | ['彿ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬éÂ·å½æ'], |
| | | ['累计ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿é·累计'], |
| | | ['累计ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬é·累计'] |
| | | ['彿ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿éÂ·å½æ', 'ä¸å£å¾å®¢è¿éÂ·å½æåæ¯'], |
| | | ['彿ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬éÂ·å½æ', 'ä¸å£å¾å¨è½¬éÂ·å½æåæ¯'], |
| | | ['累计ä¸å£å¾å®¢è¿é', 'ä¸å£å¾å®¢è¿é·累计', 'ä¸å£å¾å®¢è¿éÂ·ç´¯è®¡åæ¯'], |
| | | ['累计ä¸å£å¾å¨è½¬é', 'ä¸å£å¾å¨è½¬é·累计', 'ä¸å£å¾å¨è½¬éÂ·ç´¯è®¡åæ¯'] |
| | | ]) |
| | | } |
| | | ] |
| | |
| | | if (continuous) return '1~' + cov[cov.length - 1] + 'æåææ°æ®' |
| | | return cov.map(x => x + 'æ').join('ã') + ' ææ°æ®' |
| | | }, |
| | | // ==================== æ±æ»å¤§è¡¨å¼æ¥çæï¼è¿åº¦å¼¹çªï¼ ==================== |
| | | // å端 ReportExportTaskServiceï¼æäº¤ä»»å¡ -> 轮询è¿åº¦ -> 宿åä¸è½½æä»¶ã |
| | | // åæ¥è¡¨æ 10 åéå
䏿鴿²¡ææ°å¯¼å
¥æ°æ®æ¶ï¼åç«¯ç´æ¥è¿å䏿¬¡ç»æï¼å¼¹çªå
ä¼è¯´ææ¥æºæ¶é´ï¼ã |
| | | startSummaryTask(refresh) { |
| | | if (!this.period) { this.$message.warning('请å
鿩卿åæä»½'); return } |
| | | this.stopTaskPolling() |
| | | this.taskInfo = { status: 'PENDING', percent: 0, step: 'æäº¤ä»»å¡', period: this.period, elapsedMs: 0 } |
| | | this.taskVisible = true |
| | | this.loading = 'gen-' + this.curModule.key |
| | | const params = Object.assign({}, this.buildParams(), { refresh: refresh ? 'true' : 'false' }) |
| | | api.get('/report/exportTask/summaryWorkbook', { params, timeout: 60000 }) |
| | | .then(res => { |
| | | // å端ç»ä¸è¿å Resultï¼code é 200 æ¶ data 为空ï¼å¿
é¡»æç¤ºè䏿¯ç©ºè½¬ |
| | | if (!res || res.code !== 200 || !res.data || !res.data.taskId) { |
| | | this.taskInfo = { status: 'FAILED', percent: 0, step: 'æäº¤å¤±è´¥', period: this.period, elapsedMs: 0, |
| | | error: (res && res.message) || 'å端æªè¿åä»»å¡å·' } |
| | | this.loading = '' |
| | | return |
| | | } |
| | | this.taskInfo = res.data |
| | | if (this.taskInfo.status === 'DONE') { this.loading = ''; this.downloadTaskFile(); return } |
| | | if (this.taskInfo.status === 'FAILED') { this.loading = ''; return } |
| | | this.pollTask() |
| | | }) |
| | | .catch(err => { |
| | | this.stopTaskPolling() |
| | | this.loading = '' |
| | | this.taskVisible = false |
| | | this.failWith(err, 'çæ') |
| | | }) |
| | | }, |
| | | pollTask() { |
| | | this.stopTaskPolling() |
| | | const id = this.taskInfo && this.taskInfo.taskId |
| | | if (!id) return |
| | | this.taskTimer = setInterval(() => { |
| | | api.get('/report/exportTask/' + id, { timeout: 30000 }) |
| | | .then(res => { |
| | | if (!res || res.code !== 200 || !res.data) { |
| | | // ä»»å¡è¢«æ¸
ç/è¿æï¼åæ¢è½®è¯¢å¹¶ç»åºåå ï¼ä¸è®©å¼¹çªä¸ç´ç©ºè½¬ |
| | | this.stopTaskPolling() |
| | | this.loading = '' |
| | | this.taskInfo = Object.assign({}, this.taskInfo, { |
| | | status: 'FAILED', step: 'ä»»å¡å·²å¤±æ', |
| | | error: (res && res.message) || '导åºä»»å¡å·²å¤±æï¼è¯·éæ°çæ' |
| | | }) |
| | | return |
| | | } |
| | | this.taskInfo = res.data |
| | | if (this.taskInfo.status === 'DONE') { |
| | | this.stopTaskPolling() |
| | | this.loading = '' |
| | | this.downloadTaskFile() |
| | | } else if (this.taskInfo.status === 'FAILED') { |
| | | this.stopTaskPolling() |
| | | this.loading = '' |
| | | if (!this.taskVisible) this.$message.error('æ±æ»å¤§è¡¨çæå¤±è´¥ï¼' + (this.taskInfo.error || 'æªç¥åå ')) |
| | | } |
| | | }) |
| | | .catch(() => { /* 忬¡è½®è¯¢å¤±è´¥å¿½ç¥ï¼ä¸ä¸è½®ç»§ç» */ }) |
| | | }, 700) |
| | | }, |
| | | stopTaskPolling() { |
| | | if (this.taskTimer) { clearInterval(this.taskTimer); this.taskTimer = null } |
| | | }, |
| | | downloadTaskFile() { |
| | | const id = this.taskInfo && this.taskInfo.taskId |
| | | if (!id) return |
| | | const name = this.taskInfo.fileName || ('çæ_éè·¯è¿è¾éæ±æ»è¡¨_' + this.period + '.xlsx') |
| | | api.get('/report/exportTask/' + id + '/file', { responseType: 'blob', timeout: 120000 }) |
| | | .then(res => { this.downloadBlob(res, name); this.$message.success('æ¥è¡¨å¯¼åºæå') }) |
| | | .catch(err => this.failWith(err)) |
| | | }, |
| | | restartTask() { this.startSummaryTask(true) }, |
| | | closeTask() { this.taskVisible = false; this.stopTaskPolling(); this.loading = '' }, |
| | | // çæä¸æ¶èµ·å¼¹çªï¼ä»»å¡ç»§ç»å¨åå°æ§è¡ï¼å®æåä»ä¼èªå¨ä¸è½½ï¼ä¸åæ¥åæ¥å¯¼åºçãç¹å®å³ä¸è½½ãä¸è´ï¼ |
| | | minimizeTask() { |
| | | this.taskVisible = false |
| | | this.$message.info('已转å
¥åå°çæï¼å®æåä¼èªå¨ä¸è½½') |
| | | }, |
| | | exportChecked(itemList) { |
| | | const m = this.curModule |
| | | if (!this.period) { this.$message.warning('请å
鿩卿åæä»½'); return } |
| | |
| | | const params = this.buildParams() |
| | | const doExport = () => { |
| | | if (items.length === 1) { |
| | | // æ±æ»å¤§è¡¨çæä¸æ¬¡çº¦ 10~20 ç§ï¼èµ°å¼æ¥ä»»å¡ï¼è¿åº¦å¼¹çªï¼ï¼é¿å
ç¹å»åé¿æ¶é´æ ååº |
| | | if (items[0].key === 'summaryWorkbook') { this.startSummaryTask(false); return } |
| | | api.get('/report/export/' + items[0].key, { params, responseType: 'blob', timeout: 120000 }) |
| | | .then(res => { this.downloadBlob(res, this.fileNameOf(items[0])); this.$message.success('æ¥è¡¨å¯¼åºæå'); this.loading = '' }) |
| | | .catch(err => this.failWith(err)) |
| | |
| | | .wb-yoy { text-align:right; color:#606266; } |
| | | .wb-yoy.yoy-empty { color:#C0C4CC; } |
| | | .wb-note { color:#E6A23C; font-size:12px; margin:2px 0 8px; } |
| | | /* 弿¥çæè¿åº¦å¼¹çª */ |
| | | .task-body { padding: 4px 2px; } |
| | | .task-step { margin: 12px 0 4px; font-size: 14px; color:#303133; } |
| | | .task-meta { margin: 2px 0; font-size: 12px; color:#909399; line-height: 1.6; } |
| | | .task-error { margin: 8px 0 0; font-size: 13px; color:#F56C6C; word-break: break-all; } |
| | | </style> |
| | | |
| | | <style> |
| | |
| | | .pv-dialog { border-radius: 10px; overflow: hidden; } |
| | | .pv-dialog .el-dialog__header { cursor: move; user-select: none; -webkit-user-select: none; } |
| | | .pv-dialog .el-dialog__headerbtn { cursor: pointer; } |
| | | </style> |
| | | </style> |