feat: 网约车订单运行监测报告(docx)导入 + 汇总大表8月数据驱动回填与版式对齐
【用户第1项:网约车订单报告导入】
- 新增 POST /api/import/wycOrderReport(DataImportService.importWycOrderReport)
解析《网约车行业YYYY年M月运行监测情况分析报告》附件表「地市名称/订单数总数」,
取17市州订单数写入 wyc_order_monthly(F订单合计 + G-W市州列);报表期优先取报告标题年月
- 全省 pin(B-E) 该期缺失时从 wyc_total_monthly 同报表期补齐
- 误传 Excel/PDF 时原先抛 xmlbeans 英文异常,改为用户可读提示(原始错误附后)
- 前端导入界面新增「网约车订单报告」类型(模板_网约车订单.docx,限 .docx/.doc),接入按类型清空
- WycSplitCalc 网约车取数改为优先读库,库里无数据回退读 xlsx 母版
【用户第2/3/4/5项:汇总大表8月回填与版式】
- 8月当月值列(Q列)自动回填:写入当月值格数=1659,历史月不受影响
- 同比统一以汇总表2025年8月(AJ列)为分母,公式 =Q../AJ..-1(补写600格)
- 公交/出租数值不再被日期格式吞掉(按同行1月列样式套用,保留0.00)
- 班线包车、轨道轮渡「全省」行补齐合计公式(补写43格),打开即算(fullCalcOnLoad)
- 版式按用户参照件《生成_道路运输量汇总表》逐列对齐列宽/隐藏,真实差异0列,含8月扩列Q/R宽度
【修复】
- monthColumnCapacity 对货运页表头(累计周转量)恒返回默认列数导致8月列永不回填
- shiftFormulaColumns 连续组引用被拼接错(Q5AJ5O5)
- ensureMonthYoyFormulas 公式写入失败被静默吞掉,改为抛出定位异常
- setNumeric 对公式格不再覆盖,对空/日期格式格套用1月列样式
【测试】
- 2026-08 导出 4.6s/948,735字节,缺数提示为空;货运Σ17市州=全省(16888.7615)
- 网约车/公交/出租/班线包车/轨道轮渡当月与全省行全部正确
- 7月历史月与备份母版逐格比对无实质差异(差异仅「中口径排名」页09-08已按需求删除的旧左块)
- 详见 docs/功能测试报告/功能测试报告_网约车订单报告导入_2026-09-11.md、
docs/功能测试报告/功能测试报告_汇总大表8月数据回填与版式对齐_2026-09-11.md
| New file |
| | |
| | | # åè½æµè¯æ¥å_æ±æ»å¤§è¡¨8ææ°æ®åå¡«ä¸çå¼å¯¹é½_2026-09-11 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | éå¯¹ç¨æ·åé¦ç 4 个é®é¢ï¼å¯¹ãéè·¯è¿è¾éæ±æ»è¡¨ã导åºé¾è·¯åæ°æ®é©±å¨åå¡«ä¸çå¼å¯¹é½ï¼ |
| | | |
| | | 1. **8 ææ°æ®å·²å
¥åºä½æ±æ»è¡¨æ²¡æ 8 ææ°æ®** â æ±æ»å·¥ä½ç°¿å¡«å
å¨è¯å«ã彿å¼åãï¼8 æä¸º Q åï¼å¹¶åå¡«ï¼ |
| | | 2. **忝ä¸å¾ä»¥æ±æ»è¡¨ 2025 å¹´ 8 ææ°æ®ä¸ºå** â 彿忝åï¼R åï¼å
¬å¼ç»ä¸ä¸º `=Q../AJ..-1`ï¼AJ åå³ 2025 å¹´ 8 æï¼ |
| | | 3. **å
¬äº¤ãåºç§æ°æ®æ¯æ¥æå½¢å¼** â åå¡«æ°å¼æ¶æåè¡ 1 æåæ ·å¼å¥ç¨ï¼é¿å
æ°å¼è¢«å¥ä¸æ¥ææ ¼å¼ï¼æ¾ç¤ºæ 1902/1910 å¹´ï¼ï¼ |
| | | 4. **ç线å
车ã轨éè½®æ¸¡åªæåå¸å·æ²¡æå
¨çæ°æ®** â 为å
¨çè¡è¡¥é½å计å
¬å¼ï¼æ¯ç忬åªå¯¹ 1 æåæ»å
¬å¼ï¼ï¼ |
| | | 5. **çå¼å®å
¨æãçæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxã** â éåå¥ç¨åç
§ä»¶å宽/éèæ è®°ï¼**åç»æ©åï¼8 æ Q/R åï¼ä¹æåç
§ä»¶å®½åº¦**ã |
| | | |
| | | æ¹å¨èå´ï¼ |
| | | - `SummaryWorkbookFiller`ï¼`fillFreightSheet` / `fillWycSheet` éåï¼åªåå¡«ç®æ æå½æï¼æ´¾çè¡ä¿æå
¬å¼ï¼ï¼æ°å¢ `ensureMonthFormulas`ã`ensureMonthYoyFormulas`ã`monthColumnCapacity`ï¼ |
| | | - `ReportExportService`ï¼å¯¼åºæ¶è°ç¨ `ensureMonthFormulas` + æ°å¢ `applySummaryReferenceLayout`ï¼æåç
§ä»¶å¯¹é½å宽ï¼ï¼ |
| | | - `WycSplitCalc`ï¼æ±æ»è¡¨ç½çº¦è½¦åæ°ä¼å
读åºã |
| | | |
| | | å
³é®å£å¾ï¼å½æå¼åï¼0 åºï¼= `2 + 2*(m-1)`ï¼åæ¯å = å¼å + 1ï¼åæ¯åæ¯åºå®ä¸º AJ åï¼2025 å¹´ 8 æï¼ã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - å端 `http://localhost:8090`ï¼å¯¼åºæ¥å£ `GET /api/report/export/summaryWorkbook?period=YYYY-MM`ã |
| | | - æ¯çï¼`docs/çææ±æ»å¤§è¡¨/2026å¹´8æéè·¯è¿è¾éæ±æ»è¡¨.xlsx`ï¼çå¼åç
§ï¼`docs/çææ±æ»å¤§è¡¨/çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx`ã |
| | | - æµè¯æ¶é´ï¼2026-09-11ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | ### 3.1 æ£åï¼2026-08 çæä¸å½æåå¼ |
| | | |
| | | | ç¼å· | æ£æ¥é¡¹ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | |
| | | | TC-1 | å¯¼åº 2026-08 | HTTP 200ï¼æ£å¸¸äº§åºæä»¶ | 4.6 ç§è¿åï¼948,735 åè | éè¿ | |
| | | | TC-2 | å端åå¡«æ¥å¿ | æåå
¥æ ¼æ°ç»è®¡ãæ ç¼ºæ°æç¤º | åå
¥å½æå¼æ ¼æ°=1659ï¼è¡¥å彿忝å
¬å¼æ ¼æ°=600ï¼è¡¥å彿å计å
¬å¼æ ¼æ°=43ï¼å¯¹é½å宽忰=422ï¼ç¼ºæ°æç¤º=[] | éè¿ | |
| | | | TC-3 | è´§è¿é¡µå
¨çåï¼è¡5-10ï¼Q å | è§ä¸/è§ä¸è´§è¿éä¸å¨è½¬éæå¼ï¼å计è¡ä¸ºå
¬å¼ | è§ä¸è´§è¿é 3666.1401ãè§ä¸ 13222.6214ãè§ä¸å¨è½¬ 570004.4355ãè§ä¸å¨è½¬ 1700006.166ï¼Q5=`=Q7+Q9`ãQ6=`=Q8+Q10` | éè¿ | |
| | | | TC-4 | è´§è¿é¡µ Σ17å¸å· = å
¨ç | ç¸ç | Σ17å¸å·è´§è¿é = 16888.7615ï¼å
¨ç Q5 = 3666.1401 + 13222.6214 = 16888.7615 | éè¿ | |
| | | | TC-5 | è´§è¿é¡µå¸å·æ´¾çè¡ | ä¸åæ»å¼ï¼ä¿æå
¬å¼ | æ¦æ± Q14ï¼è§ä¸+è§ä¸å¨è½¬éï¼=`=Q15+Q16`ï¼è§ä¸/è§ä¸å项为æ°å¼ | éè¿ | |
| | | | TC-6 | ç½çº¦è½¦é¡µ | 17 å¸å·å½ææå¼ï¼å
¨çè¡ä¸ºå
¬å¼ | æ¦æ± Q9=1879.9049â¦ãQ10=13407.6982â¦ï¼å
¨ç Q5=`=Q9+Q13+â¦+Q73`ï¼Î£17å¸å·å®¢è¿é=4997.74ãå¨è½¬é=29166.7 | éè¿ | |
| | | | TC-7 | å
¬äº¤é¡µ | å¸å·å½ææå¼ä¸**䏿¯æ¥ææ¾ç¤º** | Q9=3856.83ï¼æ¦æ±å®¢è¿éï¼ï¼åå
æ ¼æ ¼å¼ `0.00`ï¼å
¨ç Q5 为æ±åå
¬å¼ | éè¿ | |
| | | | TC-8 | åºç§é¡µ | åä¸ | Q9=1058.95ï¼æ¦æ±å®¢è¿éï¼ï¼æ ¼å¼ `0.00`ï¼å
¨ç Q5 为æ±åå
¬å¼ | éè¿ | |
| | | | TC-9 | ç线å
车页å
¨çè¡ | æå
¨çå计ï¼åç¼ºå¤±ï¼ | Q4=`=Q8+Q10+Q14+â¦+Q56`ãQ5=`=Q9+Q11+â¦+Q57`ãQ6/Q7 个ä½å计亦为å
¬å¼ | éè¿ | |
| | | | TC-10 | 轨éã轮渡页å
¨çè¡ | æå
¨çå计ï¼åç¼ºå¤±ï¼ | 轨é å
¨ç Q4=`=SUM(Q6,Q8)`ãQ5=`=Q7+Q9`ï¼è½®æ¸¡ å
¨ç Q13=`=Q15`ãQ14=`=Q16` | éè¿ | |
| | | | TC-11 | 忝å
¬å¼æå 2025 å¹´ 8 æ | R ååæ¯ä¸º AJ å | å页表头 AJ å = `2025å¹´8æ`ï¼R åå
¬å¼å½¢å¦ `=Q9/AJ9-1`ï¼AJ åç¡®æ 2025 å¹´ 8 ææ¯çæ°å¼ï¼å¦è´§è¿ AJ7=3716.1158ï¼ | éè¿ | |
| | | | TC-12 | æå¼å³éç® | æä»¶å¸¦å
¨ééç®æ è®° | `xl/workbook.xml` å
`<calcPr calcId="191029" fullCalcOnLoad="true"/>`ï¼Excel/WPS æå¼å³ç®åºå
¨çå计 | éè¿ | |
| | | |
| | | ### 3.2 çå¼å¯¹é½ï¼ç¬¬ 5 é¡¹ï¼ |
| | | |
| | | | ç¼å· | æ£æ¥é¡¹ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | |
| | | | TC-13 | å
¨è¡¨å宽ä¸ãçæ_éè·¯è¿è¾éæ±æ»è¡¨ãæ¯å¯¹ï¼å±å¼ `<col min..max>` èå´éåæ¯å¯¹ï¼ | å®å
¨ä¸è´ | 19 个页ç¾å
¨é¨æ¯å¯¹ï¼**çå®å·®å¼ 0 å** | éè¿ | |
| | | | TC-14 | æ©åï¼8 æ Q/Rï¼å宽 | ä¸åç
§ä»¶ 8 æä¸è´ | è´§è¿ P/Q/R = 12.67/10.55/11.67ï¼åç
§ 12.67/10.56/11.67ï¼ä»
0.01 æµ®ç¹èå
¥ï¼ï¼ç½çº¦è½¦/轨é轮渡 Q/R=13.0/13.0ï¼å
¬äº¤ Q/R=11.89/13.0ï¼åºç§ Q/R=11.89/13.0ï¼ç线å
车 Q/R=10.22/9.78 ââ åä¸åç
§ä»¶ç¸å | éè¿ | |
| | | |
| | | ### 3.3 è´åä¸åå½ |
| | | |
| | | | ç¼å· | æ£æ¥é¡¹ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | |
| | | | TC-15 | å岿ï¼2026-07ï¼ä¸å¾è¢«å½æå填污æï¼ä¸ `docs/çææ±æ»å¤§è¡¨/_å¤ä»½_2026å¹´7æéè·¯è¿è¾éæ±æ»è¡¨_æ¸
çå_20260904.xlsx` éæ ¼æ¯å¯¹ | 餿¢å®æ¹é 夿 å·®å¼ | å·®å¼å
±ä¸ç±»ï¼â 426 夿µ®ç¹æ«ä½å·®ï¼æå¤§ç¸å¯¹å·® 7.26e-15ï¼å± Excel 15 ä½æææ°åæªæï¼æ å®è´¨å·®å¼ï¼ï¼â¡ 57 å¤"ææ¬ vs ç弿°å"ï¼â¢ 148 å¤å
¨é¨éä¸å¨ãä¸å£å¾æåã页 ââ è¯¥é¡µå·¦ä¾§éæ§åå·²äº 2026-09-08 æéæ±æ´åå é¤ï¼å±**颿åå**ã**æ åå½** | éè¿ | |
| | | | TC-16 | 缺ææç¤º | ç¼ºæ°æ®çæä»½ææç¤º | 2026-08 å¯¼åº `ç¼ºæ°æç¤º=[]` | éè¿ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **é®é¢ï¼å·²ä¿®å¤ï¼**ï¼`monthColumnCapacity` åå®ç°åªè®¤"å« 2026+累计"ç表头ï¼èè´§è¿é¡µè¡¨å¤´æ¯"累计å¨è½¬é"ï¼å¯¼è´å
¶æè¿åé»è®¤åæ°ã8 æåæ°¸ä¸åå¡«ã**å¤ç½®**ï¼æ¹ä¸ºã累计åãä¸ãæåä¸ä¸ªæä»½/æ¥ææ ¼å¼æåãåè¾å¤§å¼ã |
| | | 2. **é®é¢ï¼å·²ä¿®å¤ï¼**ï¼`shiftFormulaColumns` è¿ç»ç»å¼ç¨è¢«æ¼æ `Q5AJ5O5`ã**å¤ç½®**ï¼`sb.append(quoteReplacement(...))` â `m.appendReplacement(sb, quoteReplacement(...))`ã |
| | | 3. **é®é¢ï¼å·²ä¿®å¤ï¼**ï¼`ensureMonthYoyFormulas` ä¸ `setCellFormula` 失败被éé»åæã**å¤ç½®**ï¼æ¹ä¸ºæåºå«é¡µç¾/åå
æ ¼/åå¼/ç®æ å¼ç `IllegalStateException`ï¼ä¾¿äºå®ä½ã |
| | | 4. **é®é¢ï¼å·²ä¿®å¤ï¼**ï¼åå¡«ç®æ æ ¼è¥è¢«å¥ä¸æ¥ææ ¼å¼ï¼æ°å¼ä¼æ¾ç¤ºæ 1902/1910 å¹´ï¼å³ç¨æ·åé¦ç"æ¥æå½¢å¼"ï¼ã**å¤ç½®**ï¼`setNumeric` 对空/æ¥ææ ¼å¼æ ¼å¥ç¨åè¡ 1 æåæ ·å¼ï¼å¯¹å·²æå
¬å¼æ ¼ç´æ¥è·³è¿ä¸è¦çã |
| | | 5. **å·²ç¥æ 害åè¦**ï¼2026-08 å¯¼åºæ¶æ¥å¿åºç° `æ±æ»å·¥ä½ç°¿æªæ¾å°åæå¤ä»½æ¯çï¼_å¤ä»½_2026å¹´8æâ¦ï¼ï¼è¾åºå°ä¿ææ¯çç°ç¶`ãåå æ¯ 8 ææ²¡æ"æ¸
çåå¤ä»½æ¯ç"ï¼è 8 ææ¯çæ¬èº«å·²æ¯å®æ´æ¯çï¼æ éä»å¤ä»½è¿åï¼æ
ä¸å½±åè¾åºï¼å·²é项éªè¯å弿£ç¡®ï¼ã7 æå åå¨ `_å¤ä»½_2026å¹´7æâ¦` æ æ¤åè¦ã |
| | | 6. **æ§è½æ³¨æ**ï¼`applySummaryReferenceLayout` çåæ°ä¸éä¿ç `min(åç
§ä»¶å·²ç¨åæ°, ç®æ ä»¶å·²ç¨åæ° + 4)` ââ å»æè¯¥ä¸éä¼è®© POI å¨å¤§åå·ï¼è´§è¿é¡µ 147 åï¼ä¸åºç°ææ°çº§å¡é¡¿ã |
| | | |
| | | ## äºãç»è®º |
| | | 8 ææ±æ»å¤§è¡¨å·²è½ç±åºä¸æ°æ®èªå¨çæï¼è´§è¿è§ä¸/è§ä¸ãç½çº¦è½¦ãå
¬äº¤ãåºç§ãç线å
车ã轨é轮渡ç彿ååå·²åå¡«ï¼å
¨çå计ä¸åå¸å·å计ä¸è´ï¼åæ¯ç»ä¸å 2025 å¹´ 8 æï¼å
¬äº¤/åºç§ä¸åæ¾ç¤ºä¸ºæ¥æï¼ç线å
车ä¸è½¨é轮渡çå
¨çæ°æ®å·²è¡¥é½ï¼å
¬å¼ï¼æå¼å³ç®ï¼ï¼å
¨è¡¨å宽ä¸ç¨æ·æå®çãçæ_éè·¯è¿è¾éæ±æ»è¡¨ãéåä¸è´ï¼å« 8 ææ©å宽度ï¼ã7 æå岿å彿 å®è´¨å·®å¼ã |
| | | |
| | | éçï¼è¯·å°çå®çãç½çº¦è½¦è¡ä¸2026å¹´8æè¿è¡çæµæ
åµåææ¥åãéä¼ ä¸æ¬¡ï¼è¦çå½åç¨ 7 ææ¥å临æ¶å¯æ¬å¯¼å
¥ç 8 æå¸å·è®¢åæ°ã |
| | | |
| New file |
| | |
| | | # åè½æµè¯æ¥å_ç½çº¦è½¦è®¢åæ¥å导å
¥_2026-09-11 |
| | | |
| | | ## ä¸ãåè½è¯´æ |
| | | æ¯æç´æ¥ä¸ä¼ é¨çº§ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼.docxï¼ï¼ç³»ç»èªå¨è§£ææ¥åæ£æé件表ä¸ç **17 å¸å·è®¢åæ°**å¹¶åå
¥æ°æ®åº `wyc_order_monthly`ï¼F å订åå计 + G-W 17 å¸å·è®¢ååï¼ï¼ |
| | | æ±æ»å¤§è¡¨ãç½çº¦è½¦ã页忰æ¹ä¸º**ä¼å
读åº**ï¼å®ç°"ä¸ä¼ æ¥å â æ±æ»è¡¨å½æç½çº¦è½¦æ°æ®èªå¨åºç°"ã |
| | | |
| | | æ¹å¨èå´ï¼ |
| | | - å端 `DataImportService.importWycOrderReport()` / `parseWycOrderReportTables()` / `periodOfDocx()`ï¼è§£ææ¥åãå®ä½æ¥è¡¨æãè½åº `wyc_order_monthly`ï¼å¹¶å¨ç¼ºå¤±æ¶ä» `wyc_total_monthly` è¡¥é½å
¨ç pinï¼B-Eï¼ã |
| | | - å端 `DataImportController`ï¼æ°å¢ `POST /api/import/wycOrderReport`ï¼åæ° file + periodï¼ã |
| | | - å端 `WycSplitCalc.loadMonthlyInputFromDb()`ï¼æ±æ»è¡¨åæ°ä¼å
读 `wyc_order_monthly`ï¼åºé该æè®¢åå
¨ç©ºæ¶åé读 `docs/åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx`ï¼ã |
| | | - å端 `DataImport.vue`ï¼å¯¼å
¥ç±»åæ°å¢ãç½çº¦è½¦è®¢åæ¥åãï¼æ¨¡æ¿æç¤ºä¸º `åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢å.docx`ï¼æ¥å£ `/import/wycOrderReport`ï¼æä»¶ç±»åé `.docx/.doc`ã |
| | | - æ¸
空æ å°ï¼`wycOrderReport` å
³èæ¸
空 `WYC_ORDER` æ¹æ¬¡ï¼`wycOrder` ä¸ `wycOrderReport` äºä¸ºå
³èæ¸
é¤ã |
| | | |
| | | æ¥è¡¨æåå¼è§åï¼ä¼å
åæ¥åæ é¢ä¸çãç½çº¦è½¦è¡ä¸YYYYå¹´Mæãï¼åä¸å°æ¶ç¨é¡µé¢æéæ¥è¡¨æï¼ä¸¤è
é½åä¸å°åæ¥éã |
| | | |
| | | ## äºãæµè¯ç¯å¢ |
| | | - å端ï¼Spring Bootï¼`http://localhost:8090`ï¼8090 å·²çå¬ï¼ï¼å端ï¼`http://localhost:8080`ã |
| | | - æ°æ®åºï¼MySQL 5.7 `127.0.0.1:3308` / `traffic_audit`ã |
| | | - ç»å½ï¼adminï¼æµè¯æ¶é´ï¼2026-09-11ã |
| | | |
| | | ## ä¸ãç¨ä¾è¡¨ |
| | | |
| | | | ç¼å· | ç±»å | è¾å
¥ | 颿 | å®é
| ç»è®º | |
| | | | --- | --- | --- | --- | --- | --- | |
| | | | TC-1 | æ£å | ä¸ä¼ `docs/åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢å.docx`ï¼ãç½çº¦è½¦è¡ä¸2026å¹´7æè¿è¡çæµæ
åµåææ¥åãï¼ï¼period=2026-07 | è§£ææåï¼æ¥è¡¨æåæ é¢ç 2026-07ï¼17 å¸å·å
¨é¨å½ä¸ | è¿å"æ¥è¡¨æ 2026-07ï¼è®¢åå计 29,730,791 åï¼å·²åå
¥ 17 个å¸å·" | éè¿ | |
| | | | TC-2 | æ£å | åä¸ï¼æ£æ¥å端æ¥å¿ | è®°å½ period/sum/cities/missing | `WycOrderReport imported: period=2026-07 sum=2.9730791E7 cities=17 missing=[]` | éè¿ | |
| | | | TC-3 | å
¥åºæ½æ¥ | docx é件表ãå°å¸åç§° / è®¢åæ°æ»æ°ã17 è¡ï¼éé¡¹ä¸ `wyc_order_monthly` æ¯å¯¹ | 17 å¸å·éä¸ç¸çï¼å计ç¸ç | æ¦æ± 11,183,267ï¼é»ç³ 983,296ï¼åå ° 2,155,144ï¼å®æ 3,024,336ï¼è¥é³ 2,390,572ï¼éå· 321,348ï¼èé¨ 942,124ï¼åæ 1,220,812ï¼èå· 1,573,514ï¼é»å 1,125,829ï¼å¸å® 928,460ï¼éå· 528,210ï¼æ©æ½ 2,166,015ï¼ä»æ¡ 528,557ï¼æ½æ± 267,879ï¼å¤©é¨ 387,894ï¼æåº 3,534ï¼å计 29,730,791 ââ **ä¸ DB å®å
¨ä¸è´** | éè¿ | |
| | | | TC-4 | è´åï¼æä»¶ç±»åéï¼ | æ `模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx` ä¼ ç»æ¥å导å
¥æ¥å£ | ç»åºå¯è¯»æç¤ºï¼ä¸è½åº | è¿å"导å
¥å¤±è´¥: æ æ³è¯»å Word ææ¡£ï¼è¯·ä¸ä¼ .docx æ ¼å¼çãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼è¥ä¸ä¼ çå
¶å®æ¯ Excel/PDFï¼è¯·æ¹ç¨å¯¹åºæ¨¡æ¿å¯¼å
¥ãï¼åå§é误ï¼â¦ï¼" | éè¿ï¼å«ä¿®å¤ï¼è§ç¬¬åèï¼ | |
| | | | TC-5 | è´åï¼å
容ä¸ç¬¦ï¼ | ä¸ä¼ `åå¸å®¢è¿æ°æ®ä¼å.docx`ï¼éç½çº¦è½¦çæµæ¥åï¼ | æç¡®æç¤ºæªè§£æå°å¸å·è®¢åæ° | è¿å"导å
¥å¤±è´¥: æªè§£æå°ä»»ä½å¸å·è®¢åæ°ï¼è¯·ç¡®è®¤ä¸ä¼ çæ¯ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åã" | éè¿ | |
| | | | TC-6 | æ£åï¼éå¤å¯¼å
¥å¹çï¼ | åä¸ä»½ 7 ææ¥åè¿ç»å¯¼å
¥ä¸¤æ¬¡ | ç¬¬äºæ¬¡è¦çåæ¥è¡¨æè¡ï¼ä¸äº§çéå¤è¡ | ä»è¿å 17 å¸å·ï¼`wyc_order_monthly` ä¸ `2026-07` ä»
1 è¡ | éè¿ | |
| | | | TC-7 | èè° | æ¥å导å
¥åéæ°å¯¼åº `period=2026-08` æ±æ»å¤§è¡¨ | ç½çº¦è½¦é¡µå½æåï¼Q åï¼åºç°æ°å¼ï¼å
¨çè¡ä¸ºæ±åå
¬å¼ | Q å 17 å¸å·å
¨é¨æå¼ï¼Q5 èµ· 4 个å
¨çè¡ä¸º `=Q9+Q13+â¦` æ±åå
¬å¼ï¼R å忝å
¬å¼ `=Q../AJ..-1`ï¼AJ=2025å¹´8æï¼ | éè¿ï¼è¯¦è§ãåè½æµè¯æ¥å_æ±æ»å¤§è¡¨8ææ°æ®åå¡«ä¸çå¼å¯¹é½_2026-09-11.mdãï¼ | |
| | | |
| | | ## åãåç°çé®é¢ä¸å¤ç½® |
| | | |
| | | 1. **é®é¢ï¼å·²ä¿®å¤ï¼**ï¼æ Excel/PDF è¯¯ä¼ å°ãç½çº¦è½¦è®¢åæ¥åãç±»åæ¶ï¼æ¥å£è¿åçæ¯ xmlbeans çè±æææ¯å¼å¸¸ï¼`org.apache.xmlbeans.XmlException: ... is not a valid document`ï¼ï¼é¡µé¢ç¨æ·æ æ³çè§£ã |
| | | **å¤ç½®**ï¼`DataImportService.importWycOrderReport()` çè§£ææ®µç»ä¸æè·å¼å¸¸ï¼æ¹åä¸ºç¨æ·å¯è¯»æç¤ºï¼å¹¶æåå§é误以"ï¼åå§é误ï¼â¦ï¼"é卿«å°¾ä¾¿äºææ¥ãä¿®å¤å TC-4 夿µéè¿ã |
| | | 2. **éè¦ç¨æ·æä½çäºé¡¹**ï¼å½ååºä¸ `2026-08` ç**å¸å·è®¢åæ°**æ¯ç¨ 7 ææ¥åæ¹æ é¢ç临æ¶å¯æ¬ï¼`_t_wyc_aug.docx`ï¼å¯¼å
¥çï¼å
¶å¸å·å¼ä¸ 7 æç¸åï¼`pin`ï¼B-Eï¼å³å®¢è¿é/å¨è½¬éå£å¾ï¼åèª `wyc_total_monthly` ç 2026-08 è¡ï¼æ¯æ£ç¡®çã**请æçå®çãç½çº¦è½¦è¡ä¸2026å¹´8æè¿è¡çæµæ
åµåææ¥åãéæ°ä¸ä¼ 䏿¬¡**ï¼ç±»åéãç½çº¦è½¦è®¢åæ¥åãï¼æ¥è¡¨æé 2026-08ï¼ï¼å³å¯è¦ç为çå® 8 æå¸å·è®¢åæ°ã |
| | | |
| | | ## äºãç»è®º |
| | | ç½çº¦è½¦è®¢åè¿è¡çæµæ¥åï¼docxï¼å¯¼å
¥åè½å¯ç¨ï¼æ£åè§£æ 17 å¸å·è®¢åæ°åç¡®å
¥åºå¹¶ä¸æºæä»¶é项ä¸è´ï¼æä»¶ç±»åé误ãå
容ä¸ç¬¦ä¸¤ç±»è´ååºæ¯åè½ç»åºæç¡®æç¤ºï¼éå¤å¯¼å
¥å¹çï¼å¯¼å
¥åæ±æ»å¤§è¡¨å¯èªå¨åå°å½ææ°æ®ã建议å°çå® 8 ææ¥åéä¼ å忬¡å¯¼åºæ ¸å¯¹ã |
| | | |
| New file |
| | |
| | | # 工使¥ç»_2026-09-11 |
| | | |
| | | ## ä¸ãä»å¤©åäºä»ä¹ |
| | | |
| | | ### 1. åå¸å®¢è¿ï¼ç½çº¦è½¦è®¢åè¿è¡çæµæ¥åï¼docxï¼å¯¼å
¥ï¼ç¨æ·ç¬¬ 1 é¡¹ï¼ |
| | | - å端æ°å¢ `POST /api/import/wycOrderReport` ä¸ `DataImportService.importWycOrderReport()`ï¼è§£æãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãé件表ãå°å¸åç§° / è®¢åæ°æ»æ°ãï¼å 17 å¸å·è®¢åæ°åå
¥ `wyc_order_monthly`ï¼F 订åå计 + G-W å¸å·åï¼ï¼æ¥è¡¨æä¼å
åæ¥åæ é¢å¹´æã |
| | | - å
¨ç pinï¼B-Eï¼å¨è¯¥æè¡ç¼ºå¤±æ¶ï¼ä» `wyc_total_monthly` åæ¥è¡¨æè¡¥é½ã |
| | | - å端导å
¥ç颿°å¢ç±»åãç½çº¦è½¦è®¢åæ¥åãï¼ç»å® `åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢å.docx`ï¼é .docx/.docï¼ï¼å¹¶æ¥å
¥æç±»åæ¸
空ã |
| | | - æ±æ»å¤§è¡¨ç½çº¦è½¦åæ°æ¹ä¸º**ä¼å
读åº**ï¼`WycSplitCalc.loadMonthlyInputFromDb`ï¼ï¼åºéæ æ°æ®èªå¨åé读 xlsx æ¯çã |
| | | - ä¿®å¤ï¼è¯¯ä¼ Excel æ¶æåº xmlbeans è±æå¼å¸¸ â æ¹ä¸ºç¨æ·å¯è¯»æç¤ºã |
| | | |
| | | ### 2. æ±æ»å¤§è¡¨ 8 ææ°æ®åå¡«ä¸çå¼å¯¹é½ï¼ç¨æ·ç¬¬ 2/3/4/5 é¡¹ï¼ |
| | | - 8 ææºæ°æ®å·²å¨åº â å¯¼åºæ¶èªå¨å填彿å¼åï¼Q åï¼ï¼å岿ä¸å¨ã |
| | | - 忝ç»ä¸ä»¥æ±æ»è¡¨ **2025 å¹´ 8 æï¼AJ åï¼** ä¸ºåæ¯ï¼å
¬å¼ `=Q../AJ..-1`ã |
| | | - å
¬äº¤/åºç§æ°å¼ä¸åè¢«æ¥ææ ¼å¼åæï¼æåè¡ 1 æåæ ·å¼å¥ç¨ï¼`0.00`ï¼ã |
| | | - ç线å
车ã轨é轮渡ãå
¨çãè¡è¡¥é½å计å
¬å¼ï¼æ¯çååªå¯¹ 1 æåæ»å
¬å¼ï¼ã |
| | | - çå¼æç¨æ·æå®åç
§ä»¶ `docs/çææ±æ»å¤§è¡¨/çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx` éå对é½å宽/éèï¼**8 ææ©å Q/R ç宽度ä¹åèªåç
§ä»¶**ã |
| | | |
| | | ### 3. ææ¡£å½æ¡£ |
| | | - æ¨å¤©å·²å®æãæ¹åçé路货ç©è¿è¾éåå¸å·ç»è®¡æ¹æ³(2023)ç¼å¶è¯´æãå¦ä¹ ç¬è®°å½æ¡£ï¼`docs/è´§è¿/å¦ä¹ ç¬è®°_åå¸å·é路货ç©è¿è¾éç»è®¡æ¹æ³_2026-09-10.md`ï¼ï¼ä»å¤©æªåæ¹å¨ã |
| | | |
| | | ## äºãæµè¯ç»ææè¦ï¼è¯¦è§ãåè½æµè¯æ¥åãï¼ |
| | | - `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_ç½çº¦è½¦è®¢åæ¥å导å
¥_2026-09-11.md`ï¼TC-1~TC-7 å
¨é¨éè¿ï¼7 ææ¥åè§£æ 17 å¸å·ãå计 29,730,791ï¼ä¸åºä¸é项ä¸è´ï¼ä¸¤ç±»è´åç¨ä¾æç¤ºæç¡®ã |
| | | - `docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æ±æ»å¤§è¡¨8ææ°æ®åå¡«ä¸çå¼å¯¹é½_2026-09-11.md`ï¼TC-1~TC-16 å
¨é¨éè¿ã |
| | | - 2026-08 å¯¼åºæåï¼4.6s / 948,735 åèï¼ï¼åå
¥å½æå¼ 1659 æ ¼ã彿忝å
¬å¼ 600 æ ¼ã彿å计å
¬å¼ 43 æ ¼ãç¼ºæ°æç¤ºä¸ºç©ºã |
| | | - è´§è¿ Î£17 å¸å· = å
¨çï¼16888.7615ï¼ï¼ç½çº¦è½¦/å
¬äº¤/åºç§/ç线å
车/轨é轮渡å
¨çè¡ä¸å¸å·è¡åæ£ç¡®ã |
| | | - å宽ä¸åç
§ä»¶**çå®å·®å¼ 0 å**ã |
| | | - 7 æå岿åå½ï¼æ å®è´¨å·®å¼ï¼148 å¤å·®å¼å
¨é¨æ¯ãä¸å£å¾æåã页 09-08 å·²æéæ±å é¤çæ§å·¦åï¼ã |
| | | |
| | | ## ä¸ãéçé®é¢ä¸å¾
å |
| | | 1. **éç¨æ·æä½**ï¼åºä¸ `2026-08` çå¸å·è®¢åæ°ç®åæ¯ç¨ 7 ææ¥åæ¹æ é¢ç临æ¶å¯æ¬ï¼`_t_wyc_aug.docx`ï¼å¯¼å
¥çï¼å¸å·å¼ä¸ 7 æç¸åï¼è¯·æçå®ç 8 æè¿è¡çæµæ¥åéä¼ ä¸æ¬¡ï¼ç±»åãç½çº¦è½¦è®¢åæ¥åãï¼æ¥è¡¨æ 2026-08ï¼è¦çã |
| | | 2. 2026-08 导åºä¼æå°ãæªæ¾å°åæå¤ä»½æ¯çï¼_å¤ä»½_2026å¹´8æâ¦ï¼ãåè¦ï¼å±æ 害æç¤ºï¼8 ææ¯çæ¬èº«å®æ´ï¼ï¼åç»å¯èèæéæ±å³å®æ¯å¦æ¶é¤ã |
| | | 3. æ ¹ç®å½å 积è¾å¤åå²ä¸´æ¶æä»¶ï¼`_t_*.py`ã`_*.sql`ã`_gen_*.xlsx`ã`_bak_*.java`ã`_token.txt` çï¼ï¼å¾
ç¨æ·åæåé䏿¸
çã |
| | | 4. çå¼åç
§ä»¶ `docs/çææ±æ»å¤§è¡¨/çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx` ç®å为æªå
¥åºæä»¶ï¼æ¯å¦çº³å
¥çæ¬ç®¡çå¾
确认ã |
| | | |
| | | ## åãæå¤©è®¡å |
| | | 1. ç¨æ·éä¼ çå® 8 æç½çº¦è½¦æ¥ååï¼éæ°å¯¼åº 2026-08 å¹¶é项夿 ¸ç½çº¦è½¦é¡µã |
| | | 2. ç»§ç»æç¨æ·å馿 ¸å¯¹ 8 ææ±æ»å¤§è¡¨æåï¼éç¹ï¼ä¸å£å¾å页ãè´§è¿æå页ï¼ã |
| | | 3. æ¸
çä¸´æ¶æä»¶ï¼éç¨æ·ç¡®è®¤ï¼ã |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | /** ç½çº¦è½¦è®¢åè¿è¡çæµåææ¥åï¼docxï¼ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼ */ |
| | | @PostMapping("/wycOrderReport") |
| | | public Result<String> importWycOrderReport(@RequestParam("file") MultipartFile file, |
| | | @RequestParam("period") String period) { |
| | | try { |
| | | DataImportService.WycOrderReportResult r = importService.importWycOrderReport(file, period); |
| | | StringBuilder msg = new StringBuilder("ç½çº¦è½¦è®¢åæ¥å导å
¥æåï¼æ¥è¡¨æ " + r.getPeriod() |
| | | + "ï¼è®¢åå计 " + String.format("%,.0f", r.getOrderSum()) + " åï¼å·²åå
¥ " + r.getCityCount() + " 个å¸å·"); |
| | | if (!r.getMissingCities().isEmpty()) { |
| | | msg.append("ï¼ä»¥ä¸å¸å·æªå¨æ¥åä¸è§£æå°ï¼æªåå
¥ï¼").append(String.join("ã", r.getMissingCities())); |
| | | } |
| | | return Result.ok(msg.toString()); |
| | | } catch (Exception e) { |
| | | log.error("wycOrderReport import error", e); |
| | | return Result.error("导å
¥å¤±è´¥: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | /** æèµææ¥ï¼å
¨çæ±æ»å¤§è¡¨ï¼ï¼category=客è¿ç«åº/ç©æµååº */ |
| | | @PostMapping("/investment") |
| | | public Result<String> importInvestment(@RequestParam("file") MultipartFile file, |
| | |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | | import org.apache.poi.ss.usermodel.Workbook; |
| | | import org.apache.poi.ss.usermodel.WorkbookFactory; |
| | | import org.apache.poi.xwpf.usermodel.XWPFDocument; |
| | | import org.apache.poi.xwpf.usermodel.XWPFParagraph; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTable; |
| | | import org.apache.poi.xwpf.usermodel.XWPFTableRow; |
| | | import cn.hutool.core.io.IoUtil; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | |
| | | CLEAR_TYPE_TO_OP.put("cityTaxiAuth", "CITY_TAXI_AUTH"); |
| | | CLEAR_TYPE_TO_OP.put("wycTotal", "WYC_TOTAL"); |
| | | CLEAR_TYPE_TO_OP.put("wycOrder", "WYC_ORDER"); |
| | | CLEAR_TYPE_TO_OP.put("wycOrderReport", "WYC_ORDER"); |
| | | |
| | | CLEAR_TYPE_TO_AUDIT.put("h2032", new String[]{"H2032"}); |
| | | CLEAR_TYPE_TO_AUDIT.put("transportAuth", new String[]{"H2032"}); |
| | |
| | | CLEAR_TYPE_TO_BATCH.put("cityTaxi", new String[]{"CITY_TAXI"}); |
| | | CLEAR_TYPE_TO_BATCH.put("cityTaxiAuth", new String[]{"CITY_TAXI_AUTH"}); |
| | | CLEAR_TYPE_TO_BATCH.put("wycTotal", new String[]{"WYC_TOTAL"}); |
| | | CLEAR_TYPE_TO_BATCH.put("wycOrder", new String[]{"WYC_ORDER"}); |
| | | CLEAR_TYPE_TO_BATCH.put("wycOrder", new String[]{"WYC_ORDER", "WYC_ORDER_REPORT"}); |
| | | CLEAR_TYPE_TO_BATCH.put("wycOrderReport", new String[]{"WYC_ORDER_REPORT", "WYC_ORDER"}); |
| | | } |
| | | |
| | | /** |
| | |
| | | return ok; |
| | | } |
| | | |
| | | // ========== ç½çº¦è½¦è®¢åè¿è¡çæµåææ¥åï¼docxï¼å¯¼å
¥ ========== |
| | | |
| | | /** ç½çº¦è½¦è®¢åæ¥å导å
¥ç»æï¼æ¥è¡¨æ/订åå计/è¦çå¸å·æ°/缺失å¸å·ï¼ */ |
| | | public static class WycOrderReportResult { |
| | | private final String period; |
| | | private final double orderSum; |
| | | private final int cityCount; |
| | | private final List<String> missingCities; |
| | | |
| | | public WycOrderReportResult(String period, double orderSum, int cityCount, List<String> missingCities) { |
| | | this.period = period; |
| | | this.orderSum = orderSum; |
| | | this.cityCount = cityCount; |
| | | this.missingCities = missingCities; |
| | | } |
| | | |
| | | public String getPeriod() { return period; } |
| | | public double getOrderSum() { return orderSum; } |
| | | public int getCityCount() { return cityCount; } |
| | | public List<String> getMissingCities() { return missingCities; } |
| | | } |
| | | |
| | | /** |
| | | * ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼docxï¼å¯¼å
¥ï¼ |
| | | * è§£ææ¥åéä»¶ä¸ãå°å¸åç§° | ⦠| è®¢åæ°æ»æ°ã表ç 17 å¸å·è®¢åæ°ï¼åå
¥ wyc_order_monthly ç |
| | | * F 订ååè®¡ä¸ G-W 17 å¸å·è®¢ååï¼å
¨ç pinï¼B-Eï¼æ²¿ç¨è¯¥æå·²æè¡ï¼è¥æ 该æè¡åä» |
| | | * wyc_total_monthly åæ¥è¡¨æå¤å¶ãæ¥è¡¨æä¼å
åæ¥åæ é¢å¹´æï¼åä¸å°æ¶ç¨é¡µé¢æéæ¥è¡¨æã |
| | | */ |
| | | public synchronized WycOrderReportResult importWycOrderReport(MultipartFile file, String period) throws Exception { |
| | | Map<String, Double> orders = new LinkedHashMap<>(); |
| | | double[] sumHolder = new double[]{0.0}; |
| | | String docPeriod; |
| | | try (java.io.InputStream in = file.getInputStream(); |
| | | XWPFDocument doc = new XWPFDocument(in)) { |
| | | docPeriod = periodOfDocx(doc); |
| | | parseWycOrderReportTables(doc, orders, sumHolder); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("æ æ³è¯»å Word ææ¡£ï¼è¯·ä¸ä¼ .docx æ ¼å¼çãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼" |
| | | + "è¥ä¸ä¼ çå
¶å®æ¯ Excel/PDFï¼è¯·æ¹ç¨å¯¹åºæ¨¡æ¿å¯¼å
¥ãï¼åå§é误ï¼" + e.getMessage() + "ï¼"); |
| | | } |
| | | if (orders.isEmpty()) { |
| | | throw new RuntimeException("æªè§£æå°ä»»ä½å¸å·è®¢åæ°ï¼è¯·ç¡®è®¤ä¸ä¼ çæ¯ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åã"); |
| | | } |
| | | String rp = null; |
| | | if (docPeriod != null && docPeriod.matches("\\d{4}-\\d{2}")) rp = docPeriod; |
| | | else if (period != null && period.matches("\\d{4}-\\d{2}")) rp = period; |
| | | if (rp == null) { |
| | | throw new RuntimeException("æ æ³ç¡®å®æ¥è¡¨æï¼æ¥åæ 颿ªå«ãYYYYå¹´Mæãï¼ä¸é¡µé¢æªéæ©æ¥è¡¨æ"); |
| | | } |
| | | |
| | | List<String> missing = new ArrayList<>(); |
| | | double citySum = 0.0; |
| | | for (String city : RegionUtil.cityList()) { |
| | | Double v = orders.get(city); |
| | | if (v == null) missing.add(city); |
| | | else citySum += v; |
| | | } |
| | | double sum = sumHolder[0] > 0 ? sumHolder[0] : citySum; |
| | | |
| | | WycOrderMonthly it = wycOrderMapper.selectOne(new LambdaQueryWrapper<WycOrderMonthly>() |
| | | .eq(WycOrderMonthly::getReportPeriod, rp).last("LIMIT 1")); |
| | | if (it == null) it = new WycOrderMonthly(); |
| | | it.setReportPeriod(rp); |
| | | it.setOrderSum(sum > 0 ? sum : null); |
| | | it.setOrderWuhan(orderOf(orders, "æ¦æ±å¸")); |
| | | it.setOrderHuangshi(orderOf(orders, "é»ç³å¸")); |
| | | it.setOrderShiyan(orderOf(orders, "åå °å¸")); |
| | | it.setOrderYichang(orderOf(orders, "宿å¸")); |
| | | it.setOrderXiangyang(orderOf(orders, "è¥é³å¸")); |
| | | it.setOrderEzhou(orderOf(orders, "éå·å¸")); |
| | | it.setOrderJingmen(orderOf(orders, "èé¨å¸")); |
| | | it.setOrderXiaogan(orderOf(orders, "åæå¸")); |
| | | it.setOrderJingzhou(orderOf(orders, "èå·å¸")); |
| | | it.setOrderHuanggang(orderOf(orders, "é»åå¸")); |
| | | it.setOrderXianning(orderOf(orders, "å¸å®å¸")); |
| | | it.setOrderSuizhou(orderOf(orders, "éå·å¸")); |
| | | it.setOrderEnshi(orderOf(orders, "æ©æ½å·")); |
| | | it.setOrderXiantao(orderOf(orders, "仿¡å¸")); |
| | | it.setOrderQianjiang(orderOf(orders, "æ½æ±å¸")); |
| | | it.setOrderTianmen(orderOf(orders, "天é¨å¸")); |
| | | it.setOrderShennong(orderOf(orders, "ç¥åæ¶æåº")); |
| | | |
| | | if (it.getPinK() == null || it.getPinCK() == null || it.getPinZ() == null || it.getPinCZ() == null) { |
| | | WycTotalMonthly tot = wycTotalMapper.selectOne(new LambdaQueryWrapper<WycTotalMonthly>() |
| | | .eq(WycTotalMonthly::getReportPeriod, rp).last("LIMIT 1")); |
| | | if (tot != null) { |
| | | if (it.getPinK() == null) it.setPinK(tot.getPinK()); |
| | | if (it.getPinCK() == null) it.setPinCK(tot.getPinCK()); |
| | | if (it.getPinZ() == null) it.setPinZ(tot.getPinZ()); |
| | | if (it.getPinCZ() == null) it.setPinCZ(tot.getPinCZ()); |
| | | } |
| | | } |
| | | |
| | | wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>().eq(WycOrderMonthly::getReportPeriod, rp)); |
| | | wycOrderMapper.insert(it); |
| | | recordBatch(file.getOriginalFilename(), "WYC_ORDER_REPORT", rp, 1, 1, 0, null); |
| | | log.info("WycOrderReport imported: period={} sum={} cities={} missing={}", rp, sum, orders.size(), missing); |
| | | return new WycOrderReportResult(rp, sum, orders.size(), missing); |
| | | } |
| | | |
| | | /** æ¥åæ é¢ä¸çæ¥è¡¨æï¼ç½çº¦è½¦è¡ä¸2026å¹´7æ -> 2026-07ï¼åä¸å°è¿å null */ |
| | | private String periodOfDocx(XWPFDocument doc) { |
| | | java.util.regex.Pattern titlePat = java.util.regex.Pattern.compile("ç½çº¦è½¦è¡ä¸\\s*(\\d{4})\\s*å¹´\\s*(\\d{1,2})\\s*æ"); |
| | | java.util.regex.Pattern anyPat = java.util.regex.Pattern.compile("(\\d{4})\\s*å¹´\\s*(\\d{1,2})\\s*æ"); |
| | | String fallback = null; |
| | | int scanned = 0; |
| | | for (XWPFParagraph para : doc.getParagraphs()) { |
| | | String text = para.getText(); |
| | | if (text == null) continue; |
| | | String flat = text.replaceAll("\\s+", ""); |
| | | if (flat.isEmpty()) continue; |
| | | java.util.regex.Matcher m = titlePat.matcher(flat); |
| | | if (m.find()) return ymd(m.group(1), m.group(2)); |
| | | if (fallback == null && scanned < 10) { |
| | | java.util.regex.Matcher m2 = anyPat.matcher(flat); |
| | | if (m2.find()) fallback = ymd(m2.group(1), m2.group(2)); |
| | | } |
| | | scanned++; |
| | | } |
| | | return fallback; |
| | | } |
| | | |
| | | private String ymd(String y, String mo) { |
| | | try { |
| | | int month = Integer.parseInt(mo); |
| | | if (month < 1 || month > 12) return null; |
| | | return String.format("%04d-%02d", Integer.parseInt(y), month); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | /** è§£ææ¥åä¸çãå°å¸åç§° | ⦠| è®¢åæ°æ»æ°ã表ï¼orders=å¸å·è®¢åï¼sumHolder[0]=å计è¡è®¢åæ° */ |
| | | private void parseWycOrderReportTables(XWPFDocument doc, Map<String, Double> orders, double[] sumHolder) { |
| | | for (XWPFTable table : doc.getTables()) { |
| | | List<XWPFTableRow> rows = table.getRows(); |
| | | if (rows.size() < 3) continue; |
| | | int headerRow = -1; |
| | | int orderCol = -1; |
| | | for (int r = 0; r < Math.min(rows.size(), 3); r++) { |
| | | List<org.apache.poi.xwpf.usermodel.XWPFTableCell> cells = rows.get(r).getTableCells(); |
| | | for (int c = 0; c < cells.size(); c++) { |
| | | String norm = flat(cells.get(c).getText()); |
| | | if (norm.contains("è®¢åæ°æ»æ°") || "è®¢åæ°".equals(norm)) { |
| | | headerRow = r; |
| | | orderCol = c; |
| | | break; |
| | | } |
| | | } |
| | | if (headerRow >= 0) break; |
| | | } |
| | | if (headerRow < 0 || orderCol < 0) continue; |
| | | |
| | | Map<String, Double> found = new LinkedHashMap<>(); |
| | | double citySum = 0.0; |
| | | boolean hasTotal = false; |
| | | for (int r = headerRow + 1; r < rows.size(); r++) { |
| | | List<org.apache.poi.xwpf.usermodel.XWPFTableCell> cells = rows.get(r).getTableCells(); |
| | | if (orderCol >= cells.size()) continue; |
| | | String name = flat(cells.get(0).getText()); |
| | | if (name.isEmpty()) continue; |
| | | Double val = parsePlainNumber(cells.get(orderCol).getText()); |
| | | if (val == null) continue; |
| | | String city = RegionUtil.normalizeCityName(name); |
| | | if (city != null && RegionUtil.cityList().contains(city)) { |
| | | found.put(city, val); |
| | | citySum += val; |
| | | } else if (name.contains("å计") || name.contains("æ»è®¡") || name.contains("å
¨ç") || name.contains("æ¹å")) { |
| | | hasTotal = true; |
| | | sumHolder[0] = val; |
| | | } |
| | | } |
| | | if (!found.isEmpty()) { |
| | | orders.clear(); |
| | | orders.putAll(found); |
| | | if (!hasTotal) sumHolder[0] = citySum; |
| | | return; |
| | | } |
| | | } |
| | | } |
| | | |
| | | private String flat(String s) { |
| | | return s == null ? "" : s.replaceAll("\\s+", "").trim(); |
| | | } |
| | | |
| | | /** ã11,183,267 åãè¿ç±»ææ¬åæ°å¼ */ |
| | | private Double parsePlainNumber(String s) { |
| | | if (s == null) return null; |
| | | String t = s.replaceAll("[,\\s]", "").trim(); |
| | | if (t.isEmpty()) return null; |
| | | java.util.regex.Matcher m = java.util.regex.Pattern.compile("-?\\d+(?:\\.\\d+)?").matcher(t); |
| | | if (!m.find()) return null; |
| | | try { |
| | | return Double.parseDouble(m.group()); |
| | | } catch (NumberFormatException e) { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | private Double orderOf(Map<String, Double> orders, String city) { |
| | | Double v = orders.get(city); |
| | | return (v == null || v <= 0) ? null : v; |
| | | } |
| | | private String periodOfCell(Cell c) { |
| | | if (c == null) return null; |
| | | if (c.getCellType() == CellType.NUMERIC) { |
| | |
| | | case "scaleSplit": return new ImportResult(importScaleSplit(file, period), 0, new ArrayList<>()); |
| | | case "wycTotal": return new ImportResult(importWycTotal(file, period), 0, new ArrayList<>()); |
| | | case "wycOrder": return new ImportResult(importWycOrder(file, period), 0, new ArrayList<>()); |
| | | case "wycOrderReport": return new ImportResult(importWycOrderReport(file, period).getCityCount(), 0, new ArrayList<>()); |
| | | default: throw new RuntimeException("䏿¯æç导å
¥ç±»åï¼" + type); |
| | | } |
| | | } |
| | |
| | | package com.trafficaudit.reportexport.calc; |
| | | |
| | | import com.trafficaudit.common.util.RegionUtil; |
| | | import com.trafficaudit.reportexport.calc.FreightCalc.FreightMatrix; |
| | | import com.trafficaudit.reportexport.calc.FreightCalc.FreightMetrics; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.Row; |
| | | import org.apache.poi.ss.usermodel.Sheet; |
| | |
| | | private MidCalc midCalc; |
| | | @Resource |
| | | private PaxCalc paxCalc; |
| | | @Resource |
| | | private FreightCalc freightCalc; |
| | | @Resource |
| | | private WycSplitCalc wycSplitCalc; |
| | | |
| | | /** 2026 å¹´ 1 æå½æå¼åï¼0 åºï¼å³ C åï¼ */ |
| | | private static final int FIRST_MONTH_COL = 2; |
| | | |
| | | /** åå¡« 1..keepMonths æå°è´¦é¡µï¼è¿ååå
¥æ ¼æ°ï¼ç¼ºæ°æç¤ºåå
¥ problems */ |
| | | public int fillMonthlyLedger(XSSFWorkbook wb, int year, int keepMonths, List<String> problems) { |
| | | public int fillMonthlyLedger(XSSFWorkbook wb, String period, int year, int keepMonths, List<String> problems) { |
| | | if (wb == null || keepMonths <= 0) return 0; |
| | | if (problems == null) problems = new ArrayList<>(); |
| | | String yearPrefix = year + "-"; |
| | |
| | | filled += fillCityRows(wb, "å
¬äº¤", paxCalc.busMonthly(yearPrefix, keepMonths), year, keepMonths, problems, false); |
| | | filled += fillCityRows(wb, "åºç§", paxCalc.taxiMonthly(yearPrefix, keepMonths), year, keepMonths, problems, false); |
| | | filled += fillTrackFerry(wb, paxCalc.railFerryMonthly(yearPrefix, keepMonths), year, keepMonths, problems); |
| | | filled += fillFreightSheet(wb, period, keepMonths, problems); |
| | | filled += fillWycSheet(wb, period, keepMonths, problems); |
| | | return filled; |
| | | } |
| | | |
| | |
| | | } |
| | | } |
| | | return filled; |
| | | } |
| | | |
| | | /** è´§è¿é¡µåå¡«ï¼å
¨çå + 17 å¸å·åç è§ä¸/è§ä¸/å计 à 货è¿éãå¨è½¬éï¼éæç°ç®ï¼å½æå¼å=2+2*(m-1)ï¼ */ |
| | | private int fillFreightSheet(XSSFWorkbook wb, String period, int keepMonths, List<String> problems) { |
| | | Sheet sh = wb.getSheet(" è´§è¿"); |
| | | if (sh == null) sh = wb.getSheet("è´§è¿"); |
| | | if (sh == null) { |
| | | problems.add("è´§è¿é¡µä¸åå¨ï¼æ¯ç缺失该页ï¼ï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int cap = monthColumnCapacity(sh); |
| | | int mMax = Math.min(keepMonths, cap); |
| | | if (mMax <= 0) { |
| | | problems.add("è´§è¿é¡µæªè¯å«å° 2026 年累计åï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int year = periodYear(period); |
| | | // åï¼å
¨ç/å¸å·ï¼ï¼ææ é® -> è¡å· |
| | | Map<String, Map<String, Integer>> blockRows = new LinkedHashMap<>(); |
| | | String cur = null; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | String a = text(row.getCell(0)); |
| | | if (a != null && !a.trim().isEmpty()) { |
| | | String norm = RegionUtil.normalizeCityName(a.trim()); |
| | | if (FreightCalc.PROVINCE.equals(norm) || RegionUtil.cityList().contains(norm)) { |
| | | cur = norm; |
| | | blockRows.computeIfAbsent(cur, k -> new LinkedHashMap<>()); |
| | | } else { |
| | | cur = null; // æ é¢è¡ / éå
¨çéå¸å· -> è±ç¦»å |
| | | } |
| | | } |
| | | if (cur == null) continue; |
| | | String key = freightMetricKey(text(row.getCell(1))); |
| | | if (key == null) continue; |
| | | blockRows.get(cur).putIfAbsent(key, r); |
| | | } |
| | | if (blockRows.isEmpty()) { |
| | | problems.add("è´§è¿é¡µæªè¯å«å°å
¨ç/å¸å·è¡ï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int filled = 0; |
| | | // åªåå¡«ç®æ æå½æï¼1..ç®æ æ-1 çå¼ä»¥æ¯çï¼å«åæå¤ä»½æ¯çè¿åï¼ä¸ºåï¼é¿å
æ¹å已确认å£å¾ |
| | | int targetM = Math.min(periodMonth(period), mMax); |
| | | for (int m = targetM; m <= targetM; m++) { |
| | | String mp = String.format("%04d-%02d", year, m); |
| | | FreightMatrix mx; |
| | | try { |
| | | mx = freightCalc.calc(mp); |
| | | } catch (Exception e) { |
| | | problems.add("è´§è¿é¡µ " + mp + " åæ°å¤±è´¥ï¼" + e.getMessage()); |
| | | continue; |
| | | } |
| | | int col = FIRST_MONTH_COL + 2 * (m - 1); |
| | | for (Map.Entry<String, Map<String, Integer>> e : blockRows.entrySet()) { |
| | | FreightMetrics fm = mx.getMonth().get(e.getKey()); |
| | | if (fm == null) continue; |
| | | Map<String, Integer> rows = e.getValue(); |
| | | // 1 æåæ¯å
¬å¼çâæ´¾çè¡âï¼å
¨çå计 è´§è¿é/å¨è½¬éãå¸å· è§ä¸+è§ä¸å¨è½¬éï¼ä¸åå¼ï¼ |
| | | // ç± ensureMonthFormulas æå
¬å¼ææå³ç§»ï¼ä¿æä¸æ¯çä¸è´ |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("totalFreight")), col, fm.getTotalFreight()); |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("aboveFreight")), col, fm.getAboveFreight()); |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("belowFreight")), col, fm.getBelowFreight()); |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("totalTurnover")), col, fm.getTotalTurnover()); |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("aboveTurnover")), col, fm.getAboveTurnover()); |
| | | filled += setFreightCell(sh, skipIfDerived(sh, rows.get("belowTurnover")), col, fm.getBelowTurnover()); |
| | | } |
| | | } |
| | | return filled; |
| | | } |
| | | |
| | | /** è¯¥è¡ 1 æåï¼Cï¼æ¯å
¬å¼ -> æ´¾çè¡ï¼è¿å null 表示ä¸åå¡«æ°å¼ */ |
| | | private Integer skipIfDerived(Sheet sh, Integer r) { |
| | | if (r == null) return null; |
| | | Row row = sh.getRow(r); |
| | | if (row == null) return r; |
| | | Cell c = row.getCell(FIRST_MONTH_COL); |
| | | if (c != null && c.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) return null; |
| | | return r; |
| | | } |
| | | |
| | | private int setFreightCell(Sheet sh, Integer r, int col, Double v) { |
| | | if (r == null || v == null) return 0; |
| | | return setNumeric(sh, r, col, v); |
| | | } |
| | | |
| | | /** è´§è¿é¡µ B åææ ææ¡ -> ææ é®ï¼è§ä¸+è§ä¸ / è§ä¸ / è§ä¸ à 货è¿é / å¨è½¬éï¼ */ |
| | | private String freightMetricKey(String b) { |
| | | if (b == null) return null; |
| | | String s = b.replaceAll("\\s+", ""); |
| | | if (s.isEmpty()) return null; |
| | | boolean turnover = s.contains("å¨è½¬é"); |
| | | if (s.contains("è§ä¸+è§ä¸")) return turnover ? "totalTurnover" : "totalFreight"; |
| | | if (s.contains("è§ä¸")) return turnover ? "aboveTurnover" : "aboveFreight"; |
| | | if (s.contains("è§ä¸")) return turnover ? "belowTurnover" : "belowFreight"; |
| | | return turnover ? "totalTurnover" : "totalFreight"; // å
¨çåçâè´§è¿é/è´§ç©å¨è½¬éâ= å计 |
| | | } |
| | | |
| | | /** ç½çº¦è½¦é¡µåå¡«ï¼17 å¸å· ç 客è¿é/å¨è½¬é/å
¶ä¸åå¸å
客è¿é/å
¶ä¸åå¸å
å¨è½¬éï¼éæç°ç®ï¼ |
| | | * å
¨çè¡ï¼=17 å¸å·æ±åå
¬å¼ï¼ç± ensureMonthFormulas æææ©åï¼ä¸å¨æ¤å¤åå¼ã */ |
| | | private int fillWycSheet(XSSFWorkbook wb, String period, int keepMonths, List<String> problems) { |
| | | Sheet sh = wb.getSheet("ç½çº¦è½¦"); |
| | | if (sh == null) { |
| | | problems.add("ç½çº¦è½¦é¡µä¸åå¨ï¼æ¯ç缺失该页ï¼ï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int cap = monthColumnCapacity(sh); |
| | | int mMax = Math.min(keepMonths, cap); |
| | | if (mMax <= 0) { |
| | | problems.add("ç½çº¦è½¦é¡µæªè¯å«å° 2026 年累计åï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int year = periodYear(period); |
| | | Map<String, Map<String, Integer>> cityMetricRows = new LinkedHashMap<>(); |
| | | String cur = null; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | String a = text(row.getCell(0)); |
| | | if (a != null && !a.trim().isEmpty()) { |
| | | String norm = RegionUtil.normalizeCityName(a.trim()); |
| | | cur = RegionUtil.cityList().contains(norm) ? norm : null; |
| | | if (cur != null) cityMetricRows.computeIfAbsent(cur, k -> new LinkedHashMap<>()); |
| | | } |
| | | if (cur == null) continue; |
| | | String key = wycMetricKey(text(row.getCell(1))); |
| | | if (key == null) continue; |
| | | cityMetricRows.get(cur).putIfAbsent(key, r); |
| | | } |
| | | if (cityMetricRows.isEmpty()) { |
| | | problems.add("ç½çº¦è½¦é¡µæªè¯å«å°å¸å·è¡ï¼è·³è¿èªå¨åå¡«"); |
| | | return 0; |
| | | } |
| | | int filled = 0; |
| | | // åªåå¡«ç®æ æå½æï¼å岿以æ¯ç/åå²çæä»¶ä¸ºåï¼ |
| | | int targetM = Math.min(periodMonth(period), mMax); |
| | | for (int m = targetM; m <= targetM; m++) { |
| | | String mp = String.format("%04d-%02d", year, m); |
| | | WycSplitCalc.WycResult wr; |
| | | try { |
| | | wr = wycSplitCalc.calc(mp); |
| | | } catch (Exception e) { |
| | | if (m == mMax) { |
| | | problems.add("ç½çº¦è½¦é¡µ " + mp + " æºæ°æ®ç¼ºå¤±ï¼å½ææªåå¡«ï¼" + e.getMessage()); |
| | | } |
| | | continue; |
| | | } |
| | | int col = FIRST_MONTH_COL + 2 * (m - 1); |
| | | for (Map.Entry<String, Map<String, Integer>> e : cityMetricRows.entrySet()) { |
| | | WycSplitCalc.WycMetrics wm = wr.getByCity().get(e.getKey()); |
| | | if (wm == null) continue; |
| | | Map<String, Integer> rows = e.getValue(); |
| | | filled += setFreightCell(sh, rows.get("pax"), col, wm.getTotalPax()); |
| | | filled += setFreightCell(sh, rows.get("turnover"), col, wm.getTotalTurnover()); |
| | | filled += setFreightCell(sh, rows.get("cityPax"), col, wm.getCityPax()); |
| | | filled += setFreightCell(sh, rows.get("cityTurnover"), col, wm.getCityTurnover()); |
| | | } |
| | | } |
| | | return filled; |
| | | } |
| | | |
| | | /** ç½çº¦è½¦é¡µ B åææ ææ¡ -> ææ é® */ |
| | | private String wycMetricKey(String b) { |
| | | if (b == null) return null; |
| | | String s = b.replaceAll("\\s+", ""); |
| | | if (s.isEmpty()) return null; |
| | | boolean city = s.contains("åå¸å
"); |
| | | boolean turnover = s.contains("å¨è½¬é"); |
| | | if (city) return turnover ? "cityTurnover" : "cityPax"; |
| | | return turnover ? "turnover" : "pax"; |
| | | } |
| | | |
| | | /** 轨é轮渡页ï¼è½¨é=æ¦æ±/é»ç³ï¼è½®æ¸¡ä»
æ¦æ±ï¼ä¸ç¨åå¡« */ |
| | |
| | | return -1; |
| | | } |
| | | |
| | | /** åæ°å¼ï¼æ ¼ä¸åå¨åå»ºæ ¼å¹¶å¤å¶åè¡ 1 æåæ ·å¼ï¼è¿å 1 */ |
| | | /** åæ°å¼ï¼æ ¼ä¸åå¨åå»ºæ ¼ï¼æ ¼å¸¦æ¥ææ ·å¼ï¼å¦å
¬äº¤/åºç§ 8 æåç»§æ¿äºè¡¨å¤´âyyyyå¹´mæâï¼æ¶æ¹ååè¡ 1 æåçæ°å¼æ ·å¼ï¼é¿å
æ°å¼æ¾ç¤ºææ¥æ */ |
| | | private int setNumeric(Sheet sh, int r, int col, double val) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) row = sh.createRow(r); |
| | | Cell c = row.getCell(col); |
| | | if (c != null && c.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) { |
| | | return 0; // æ¯çæ¬æ¥å°±é å
¬å¼ç®çè¡ï¼å计/å页æ±åï¼ä¿æå
¬å¼ï¼äº¤ Excel éç® |
| | | } |
| | | Cell ref = row.getCell(FIRST_MONTH_COL); |
| | | boolean needStyle = false; |
| | | if (c == null) { |
| | | c = row.createCell(col); |
| | | Cell ref = row.getCell(FIRST_MONTH_COL); |
| | | if (ref != null && ref.getCellStyle() != null) c.setCellStyle(ref.getCellStyle()); |
| | | needStyle = true; |
| | | } else if (c.getCellType() == org.apache.poi.ss.usermodel.CellType.BLANK |
| | | || (c.getCellType() == org.apache.poi.ss.usermodel.CellType.NUMERIC |
| | | && org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(c))) { |
| | | // æ¯çæ 8 æåçè¡¨å¤´æ¥ææ ¼å¼å¸¦å°äºæ°æ®æ ¼ï¼æææ ¼å¼æ å¼ï¼ï¼åå¼åæ¹ååè¡ 1 æåçæ°åæ ¼å¼ |
| | | needStyle = true; |
| | | } |
| | | if (needStyle && ref != null && ref.getCellStyle() != null) { |
| | | c.setCellStyle(ref.getCellStyle()); |
| | | } |
| | | c.setCellValue(val); |
| | | return 1; |
| | |
| | | return row == null ? null : cityOf(row.getCell(0)); |
| | | } |
| | | |
| | | /** æä»½å®¹éï¼å¨è¡¨å¤´ï¼å 5 è¡ï¼æ¾â2026â¦ç´¯è®¡âåï¼å®¹é=(累计å-1 æå)/2 */ |
| | | /** |
| | | * 为第 month æè¡¥â彿å¼âåå
¬å¼ï¼ååä¸è¡æè¿ä¸ä¸ªæä»ä¸ºå
¬å¼çå¼åï¼æ´åå³ç§»è¿æ¥ |
| | | * ï¼å¦å
¬äº¤ 7 æå O ç =O9+O13+... -> 8 æå Q ç =Q9+Q13+...ï¼ã |
| | | * åªè¡¥ç©ºåå
æ ¼ï¼å·²ææ°å¼ï¼è´§è¿å
¨çå/å¸å·åç±æ°æ®åå¡«ï¼æå·²æå
¬å¼çæ ¼ä¸å¨ã |
| | | */ |
| | | public int ensureMonthFormulas(XSSFWorkbook wb, int year, int month) { |
| | | if (wb == null || month <= 1) return 0; |
| | | int targetCol = FIRST_MONTH_COL + 2 * (month - 1); |
| | | int written = 0; |
| | | for (int i = 0; i < wb.getNumberOfSheets(); i++) { |
| | | Sheet sh = wb.getSheetAt(i); |
| | | if (sh == null || !isFilledLedgerSheet(sh.getSheetName())) continue; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | if (hasContent(row.getCell(targetCol))) continue; |
| | | Cell srcCell = null; |
| | | int srcMonth = -1; |
| | | for (int s = month - 1; s >= 1; s--) { |
| | | Cell c = row.getCell(FIRST_MONTH_COL + 2 * (s - 1)); |
| | | if (c != null && c.getCellType() == org.apache.poi.ss.usermodel.CellType.FORMULA) { |
| | | srcCell = c; |
| | | srcMonth = s; |
| | | break; |
| | | } |
| | | } |
| | | if (srcCell == null) continue; |
| | | String f = srcCell.getCellFormula(); |
| | | if (f == null || f.isEmpty()) continue; |
| | | Cell target = row.getCell(targetCol); |
| | | if (target == null) target = row.createCell(targetCol); |
| | | if (srcCell.getCellStyle() != null) target.setCellStyle(srcCell.getCellStyle()); |
| | | target.setCellFormula(shiftFormulaColumns(f, 2 * (month - srcMonth))); |
| | | written++; |
| | | } |
| | | } |
| | | return written; |
| | | } |
| | | |
| | | /** è¯¥æ ¼æ¯å¦å·²æå
å®¹ï¼æ°å¼/ææ¬/å
¬å¼ï¼ï¼ä»
å¸¦æ ·å¼ç空壳ï¼å¦æ¯çéç»§æ¿è¡¨å¤´æ¥ææ ¼å¼çæ ¼åï¼è§ä¸ºç©º */ |
| | | private boolean hasContent(Cell c) { |
| | | if (c == null) return false; |
| | | switch (c.getCellType()) { |
| | | case BLANK: return false; |
| | | case STRING: return c.getStringCellValue() != null && !c.getStringCellValue().trim().isEmpty(); |
| | | default: return true; |
| | | } |
| | | } |
| | | |
| | | /** åä¸éææ°æ®åå¡«çå°è´¦é¡µï¼è´§è¿/ç线å
车/å
¬äº¤/åºç§/ç½çº¦è½¦/轨éè½®æ¸¡ï¼ */ |
| | | private boolean isFilledLedgerSheet(String name) { |
| | | if (name == null) return false; |
| | | String n = name.trim(); |
| | | return "è´§è¿".equals(n) || "ç线å
车".equals(n) || "å
¬äº¤".equals(n) |
| | | || "åºç§".equals(n) || "ç½çº¦è½¦".equals(n) || "轨éã轮渡".equals(n); |
| | | } |
| | | |
| | | /** 0 åºåå· + 1 åºè¡å· -> "Q5" */ |
| | | private String cellRef(int col0, int row1) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | int n = col0 + 1; |
| | | while (n > 0) { |
| | | int rem = (n - 1) % 26; |
| | | sb.insert(0, (char) ('A' + rem)); |
| | | n = (n - 1) / 26; |
| | | } |
| | | return sb.toString() + row1; |
| | | } |
| | | |
| | | /** ä» "2026-08" åæä»½ï¼è§£æå¤±è´¥è¿å 1ï¼ */ |
| | | private int periodMonth(String period) { |
| | | if (period != null && period.length() >= 7) { |
| | | try { return Integer.parseInt(period.substring(5, 7)); } catch (Exception ignore) { } |
| | | } |
| | | return 1; |
| | | } |
| | | |
| | | /** ä» "2026-08" å年份 */ |
| | | private int periodYear(String period) { |
| | | if (period != null && period.length() >= 4) { |
| | | try { return Integer.parseInt(period.substring(0, 4)); } catch (Exception ignore) { } |
| | | } |
| | | return 0; |
| | | } |
| | | |
| | | /** |
| | | * 为第 m æè¡¥âä¸å»å¹´åæ¯âå
¬å¼ï¼æç¬¬ m-1 æåæ¯åçå
¬å¼æ´ä½å³ç§» 2 å |
| | | * ï¼å¦å
¬äº¤ 7 æ P5 å
¬å¼ =O5/AH5-1 -> 8 æ R5 =Q5/AJ5-1ï¼ï¼ |
| | | * å æ¤åæ¯åæ¯åçå°±æ¯æ±æ»è¡¨ 2025 å¹´åæåï¼ç¨æ·å£å¾ï¼ã |
| | | */ |
| | | public int ensureMonthYoyFormulas(XSSFWorkbook wb, int year, int month) { |
| | | if (wb == null || month <= 1) return 0; |
| | | int valueCol = FIRST_MONTH_COL + 2 * (month - 1); |
| | | int yoyCol = valueCol + 1; |
| | | int prevYoyCol = yoyCol - 2; |
| | | int written = 0; |
| | | for (int i = 0; i < wb.getNumberOfSheets(); i++) { |
| | | Sheet sh = wb.getSheetAt(i); |
| | | if (sh == null) continue; |
| | | if (!isMonthLedgerSheet(sh.getSheetName())) continue; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | Cell prev = row.getCell(prevYoyCol); |
| | | if (prev == null || prev.getCellType() != org.apache.poi.ss.usermodel.CellType.FORMULA) continue; |
| | | Cell target = row.getCell(yoyCol); |
| | | 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); |
| | | if (target == null) { |
| | | target = row.createCell(yoyCol); |
| | | if (prev.getCellStyle() != null) target.setCellStyle(prev.getCellStyle()); |
| | | } |
| | | try { |
| | | target.setCellFormula(shifted); |
| | | written++; |
| | | } catch (Exception e) { |
| | | throw new IllegalStateException(String.format( |
| | | "忝å
¬å¼è¡¥å失败ï¼sheet=%s cell=%s åå¼=%s ç®æ å¼=%s", |
| | | sh.getSheetName(), cellRef(yoyCol, r + 1), f, shifted), e); |
| | | } |
| | | } |
| | | } |
| | | return written; |
| | | } |
| | | |
| | | /** éææ©åçé¿è¡¨é¡µï¼è¡¨å¤´å¨ 1..3 è¡ãæä»½ç»ä¸ºâ彿å¼+忝â交æ¿ï¼ */ |
| | | private boolean isMonthLedgerSheet(String name) { |
| | | if (name == null) return false; |
| | | String n = name.trim(); |
| | | return "è´§è¿".equals(n) || "å
¬è·¯æ»å®¢è¿".equals(n) || "ç线å
车".equals(n) || "åå¸å®¢è¿".equals(n) |
| | | || "å
¬äº¤".equals(n) || "åºç§".equals(n) || "ç½çº¦è½¦".equals(n) |
| | | || "轨éã轮渡".equals(n) || "轨é轮渡".equals(n) |
| | | || "ä¸å£å¾æç»".equals(n) || "ä¸å£å¾å®¢è¿é".equals(n); |
| | | } |
| | | |
| | | /** å
¬å¼å
ææ A1 å½¢å¼çåå¼ç¨å³ç§» delta åï¼SUM ç彿°ååæ æ°åï¼ä¸ä¼è¢«å¹é
ï¼ */ |
| | | private String shiftFormulaColumns(String formula, int delta) { |
| | | java.util.regex.Matcher m = java.util.regex.Pattern |
| | | .compile("(?<![A-Za-z0-9_$])([$]?)([A-Z]{1,3})([$]?)([0-9]+)") |
| | | .matcher(formula); |
| | | StringBuffer sb = new StringBuffer(); |
| | | while (m.find()) { |
| | | String col = m.group(2); |
| | | int idx = 0; |
| | | for (int i = 0; i < col.length(); i++) idx = idx * 26 + (col.charAt(i) - 'A' + 1); |
| | | int nidx = idx + delta; |
| | | StringBuilder nc = new StringBuilder(); |
| | | while (nidx > 0) { |
| | | int rem = (nidx - 1) % 26; |
| | | nc.insert(0, (char) ('A' + rem)); |
| | | nidx = (nidx - 1) / 26; |
| | | } |
| | | m.appendReplacement(sb, java.util.regex.Matcher.quoteReplacement(m.group(1) + nc + m.group(3) + m.group(4))); |
| | | } |
| | | m.appendTail(sb); |
| | | return sb.toString(); |
| | | } |
| | | |
| | | /** æä»½å®¹éï¼ä¼å
å表头ï¼å 5 è¡ï¼â2026â¦ç´¯è®¡âå忍ï¼è´§è¿é¡µæ è¯¥ææ¡ï¼ |
| | | * åç¨è¡¨å¤´éæåä¸ä¸ªâ2026å¹´Mæâ/æ¥ææ ¼å¼çæåå
åºï¼å¦è´§è¿ Q3=2026-08-01 -> 8ï¼ */ |
| | | private int monthColumnCapacity(Sheet sh) { |
| | | int byCumulative = 0; |
| | | int byMonthHeader = 0; |
| | | for (int r = 0; r <= 4 && r <= sh.getLastRowNum(); r++) { |
| | | Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | for (Cell c : row) { |
| | | if (c == null) continue; |
| | | int idx = c.getColumnIndex(); |
| | | if (idx <= FIRST_MONTH_COL || (idx - FIRST_MONTH_COL) % 2 != 0) continue; // åªçâ彿å¼âå |
| | | String t = text(c); |
| | | if (t != null && t.contains("2026") && t.contains("累计") && c.getColumnIndex() > FIRST_MONTH_COL) { |
| | | return (c.getColumnIndex() - FIRST_MONTH_COL) / 2; |
| | | if (byCumulative == 0 && t != null && t.contains("2026") && t.contains("累计")) { |
| | | byCumulative = (idx - FIRST_MONTH_COL) / 2; |
| | | } |
| | | if (t != null && t.contains("2026") && t.contains("æ") && !t.contains("累计") |
| | | && !t.contains("忝")) { |
| | | byMonthHeader = Math.max(byMonthHeader, (idx - FIRST_MONTH_COL) / 2 + 1); |
| | | } else if (c.getCellType() == org.apache.poi.ss.usermodel.CellType.NUMERIC |
| | | && org.apache.poi.ss.usermodel.DateUtil.isCellDateFormatted(c)) { |
| | | byMonthHeader = Math.max(byMonthHeader, (idx - FIRST_MONTH_COL) / 2 + 1); |
| | | } |
| | | } |
| | | } |
| | | return 7; |
| | | int cap = Math.max(byCumulative, byMonthHeader); |
| | | return cap > 0 ? cap : 7; |
| | | } |
| | | |
| | | private String text(Cell c) { |
| | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.trafficaudit.common.util.RegionUtil; |
| | | import com.trafficaudit.dataimport.entity.CityTaxiMonthly; |
| | | import com.trafficaudit.dataimport.entity.WycOrderMonthly; |
| | | import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper; |
| | | import com.trafficaudit.dataimport.mapper.WycOrderMonthlyMapper; |
| | | import org.apache.poi.ss.usermodel.Cell; |
| | | import org.apache.poi.ss.usermodel.CellType; |
| | | import org.apache.poi.ss.usermodel.DataFormatter; |
| | |
| | | |
| | | @Resource |
| | | private CityTaxiMonthlyMapper cityTaxiMapper; |
| | | @Resource |
| | | private WycOrderMonthlyMapper wycOrderMapper; |
| | | @Value("${city-passenger.template-dir:docs/åå¸å®¢è¿}") |
| | | private String templateDir; |
| | | |
| | |
| | | |
| | | /** 读å docs/åå¸å®¢è¿/ãç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxãï¼æ period(yyyy-MM) è¡å pin(B-E) ä¸ 17 å¸å·è®¢å(G-W) */ |
| | | private Map<String, Object> loadMonthlyInput(String period) throws Exception { |
| | | Map<String, Object> db = loadMonthlyInputFromDb(period); |
| | | if (db != null) return db; |
| | | File f = findInput(); |
| | | try (InputStream in = new FileInputStream(f); |
| | | Workbook wb = WorkbookFactory.create(in)) { |
| | |
| | | } |
| | | } |
| | | |
| | | /** ä¼å
ä»åºåæ°ï¼wyc_order_monthlyï¼ï¼åºéæ 该ææè®¢åå
¨ç©ºæ¶è¿å nullï¼åé读æ¯çæä»¶ */ |
| | | private Map<String, Object> loadMonthlyInputFromDb(String period) { |
| | | WycOrderMonthly row = wycOrderMapper.selectOne(new LambdaQueryWrapper<WycOrderMonthly>() |
| | | .eq(WycOrderMonthly::getReportPeriod, period).last("LIMIT 1")); |
| | | if (row == null) return null; |
| | | List<String> cities = RegionUtil.cityList(); |
| | | Double[] vals = { |
| | | row.getOrderWuhan(), row.getOrderHuangshi(), row.getOrderShiyan(), row.getOrderYichang(), |
| | | row.getOrderXiangyang(), row.getOrderEzhou(), row.getOrderJingmen(), row.getOrderXiaogan(), |
| | | row.getOrderJingzhou(), row.getOrderHuanggang(), row.getOrderXianning(), row.getOrderSuizhou(), |
| | | row.getOrderEnshi(), row.getOrderXiantao(), row.getOrderQianjiang(), row.getOrderTianmen(), |
| | | row.getOrderShennong() |
| | | }; |
| | | double[] orders = new double[cities.size()]; |
| | | double sum = 0.0; |
| | | for (int i = 0; i < orders.length && i < vals.length; i++) { |
| | | orders[i] = vals[i] == null ? 0.0 : vals[i]; |
| | | sum += orders[i]; |
| | | } |
| | | if (sum <= 0) return null; |
| | | double orderSum = sum; |
| | | if (row.getOrderSum() != null && row.getOrderSum() > 0) orderSum = row.getOrderSum(); |
| | | Map<String, Object> map = new LinkedHashMap<>(); |
| | | map.put("pinK", row.getPinK() == null ? 0.0 : row.getPinK()); |
| | | map.put("pinCK", row.getPinCK() == null ? 0.0 : row.getPinCK()); |
| | | map.put("pinZ", row.getPinZ() == null ? 0.0 : row.getPinZ()); |
| | | map.put("pinCZ", row.getPinCZ() == null ? 0.0 : row.getPinCZ()); |
| | | map.put("orders", orders); |
| | | map.put("orderSum", orderSum); |
| | | map.put("source", "db"); |
| | | return map; |
| | | } |
| | | private File findInput() throws Exception { |
| | | String rel = templateDir; |
| | | while (rel.startsWith("./")) rel = rel.substring(2); |
| | |
| | | cleanSummarySheetPresentation(wb); // åæ¶å页çéãè¿åéèè¡ï¼å¦åâç线å
车âç页çèµ·æ¥åç¼ºæ°æ®ï¼ |
| | | int effMonth = (toMonth != null && toMonth > 0 && toMonth < month) ? toMonth : month; |
| | | List<String> dbProblems = new ArrayList<>(); |
| | | int dbFilled = summaryWorkbookFiller.fillMonthlyLedger(wb, year, effMonth, dbProblems); |
| | | log.info("æ±æ»å·¥ä½ç°¿æ°æ®é©±å¨å填宿ï¼åå
¥å°è´¦é¡µå½æå¼æ ¼æ°={}ï¼ç¼ºæ°æç¤º={}", dbFilled, dbProblems); |
| | | String effPeriod = String.format("%04d-%02d", year, effMonth); |
| | | int dbFilled = summaryWorkbookFiller.fillMonthlyLedger(wb, effPeriod, year, effMonth, dbProblems); |
| | | int yoyFilled = summaryWorkbookFiller.ensureMonthYoyFormulas(wb, year, effMonth); |
| | | int monthFormulaFilled = summaryWorkbookFiller.ensureMonthFormulas(wb, year, effMonth); |
| | | int widthApplied = applySummaryReferenceLayout(wb); |
| | | log.info("æ±æ»å·¥ä½ç°¿æ°æ®é©±å¨å填宿ï¼åå
¥å½æå¼æ ¼æ°={}ï¼è¡¥å彿忝å
¬å¼æ ¼æ°={}ï¼è¡¥å彿å计å
¬å¼æ ¼æ°={}ï¼" |
| | | + "æãçæ_éè·¯è¿è¾éæ±æ»è¡¨ã对é½å宽忰={}ï¼ç¼ºæ°æç¤º={}", |
| | | dbFilled, yoyFilled, monthFormulaFilled, widthApplied, dbProblems); |
| | | applyTwoDecimalFormat(wb); // æ°å¼æ¾ç¤ºä¸¤ä½å°æ°ï¼ä¿çå
¨ç²¾åº¦ï¼ï¼% / æ¥æçæ¢ææ ·å¼ä¸æ¹å |
| | | if (!wb.getCTWorkbook().isSetCalcPr()) wb.getCTWorkbook().addNewCalcPr(); |
| | | wb.getCTWorkbook().getCalcPr().setFullCalcOnLoad(true); // è¿å/æ¹åå
¬å¼åæå¼å³éç® |
| | |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * çå¼å¯¹é½ï¼æ docs/çææ±æ»å¤§è¡¨/ãçæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxãï¼ç¨æ·æä¾ççå¼åç
§ï¼éåå¥ç¨å宽ä¸éèæ è®°ï¼ |
| | | * 使çæä»¶ä¸åç
§ä»¶âæ ¼å¼å®å
¨ä¸è´âï¼å¹¶è®©æ¯ç没å®ä¹å®½åº¦çâåç»æ©åâï¼å¦ 8 æåï¼ä¹æä¸ 8 æä¸è´çå宽ã |
| | | * åç
§ä»¶ç¼ºå¤±æ¶éé»è·³è¿ï¼è¿å 0ï¼ï¼ä¸å½±ååæå¯¼åºã |
| | | */ |
| | | private int applySummaryReferenceLayout(XSSFWorkbook wb) { |
| | | File ref; |
| | | try { |
| | | ref = resolveSummaryLayoutRef(); |
| | | } catch (Exception e) { |
| | | return 0; |
| | | } |
| | | if (ref == null) return 0; |
| | | double savedZipRatio = ZipSecureFile.getMinInflateRatio(); |
| | | ZipSecureFile.setMinInflateRatio(0.0001); |
| | | int applied = 0; |
| | | try (InputStream in = new FileInputStream(ref); XSSFWorkbook rwb = new XSSFWorkbook(in)) { |
| | | for (int i = 0; i < rwb.getNumberOfSheets(); i++) { |
| | | org.apache.poi.xssf.usermodel.XSSFSheet rs = rwb.getSheetAt(i); |
| | | if (rs == null) continue; |
| | | org.apache.poi.xssf.usermodel.XSSFSheet ts = wb.getSheet(rs.getSheetName()); |
| | | if (ts == null) continue; |
| | | int maxCol = Math.min(usedColumnCount(rs), usedColumnCount(ts) + 4); |
| | | if (maxCol <= 0) continue; |
| | | double[] width = new double[maxCol]; |
| | | boolean[] hasWidth = new boolean[maxCol]; |
| | | boolean[] hidden = new boolean[maxCol]; |
| | | for (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols cols : rs.getCTWorksheet().getColsArray()) { |
| | | for (org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol col : cols.getColArray()) { |
| | | long min = col.getMin(); |
| | | long max = col.getMax(); |
| | | for (long c = min; c <= max; c++) { |
| | | int idx = (int) (c - 1); |
| | | if (idx < 0 || idx >= maxCol) { |
| | | if (idx >= maxCol) break; |
| | | continue; |
| | | } |
| | | if (col.isSetWidth()) { |
| | | width[idx] = col.getWidth(); |
| | | hasWidth[idx] = true; |
| | | } |
| | | hidden[idx] = col.isSetHidden() && col.getHidden(); |
| | | } |
| | | } |
| | | } |
| | | for (int c = 0; c < maxCol; c++) { |
| | | if (hasWidth[c]) { |
| | | int w = (int) Math.round(width[c] * 256d); |
| | | if (ts.getColumnWidth(c) != w) { |
| | | ts.setColumnWidth(c, w); |
| | | applied++; |
| | | } |
| | | } |
| | | if (hidden[c] != ts.isColumnHidden(c)) ts.setColumnHidden(c, hidden[c]); |
| | | } |
| | | } |
| | | log.info("æ±æ»å·¥ä½ç°¿çå¼å¯¹é½ãçæ_éè·¯è¿è¾éæ±æ»è¡¨ã宿ï¼å¥ç¨å宽 {} åï¼åç
§ä»¶ï¼{}ï¼", applied, ref.getName()); |
| | | } catch (Exception e) { |
| | | log.warn("æ±æ»å·¥ä½ç°¿çå¼å¯¹é½å¤±è´¥ï¼å¿½ç¥ï¼ç»§ç»ææ¯ççå¼è¾åºï¼ï¼{}", e.getMessage()); |
| | | return 0; |
| | | } finally { |
| | | ZipSecureFile.setMinInflateRatio(savedZipRatio); |
| | | } |
| | | return applied; |
| | | } |
| | | |
| | | /** ä¸é¡µå·²ç¨å°çæå¤§åæ°ï¼0 åºè®¡æ°ï¼ */ |
| | | private int usedColumnCount(org.apache.poi.ss.usermodel.Sheet sh) { |
| | | int max = 0; |
| | | for (int r = sh.getFirstRowNum(); r <= sh.getLastRowNum(); r++) { |
| | | org.apache.poi.ss.usermodel.Row row = sh.getRow(r); |
| | | if (row == null) continue; |
| | | if (row.getLastCellNum() > max) max = row.getLastCellNum(); |
| | | } |
| | | return max; |
| | | } |
| | | |
| | | /** å®ä½çå¼åç
§ä»¶ docs/çææ±æ»å¤§è¡¨/çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsxï¼ä¼å
çº§åæ¯çï¼é
ç½®ç®å½ â user.dir ç¸å¯¹ â ä¸çº§ï¼ */ |
| | | private File resolveSummaryLayoutRef() { |
| | | String rel = summaryTemplateDir; |
| | | while (rel != null && rel.startsWith("./")) rel = rel.substring(2); |
| | | String[] roots = { |
| | | summaryTemplateDir, |
| | | System.getProperty("user.dir") + "/" + rel, |
| | | System.getProperty("user.dir") + "/../" + rel |
| | | }; |
| | | for (String root : roots) { |
| | | if (root == null || root.trim().isEmpty()) continue; |
| | | File f = new File(root, "çæ_éè·¯è¿è¾éæ±æ»è¡¨.xlsx"); |
| | | if (f.isFile()) return f; |
| | | } |
| | | return null; |
| | | } |
| | | |
| | | /** æ±æ»è¡¨æ¯çå®ä½ï¼ä»
精确å¹é
{year}å¹´{month}æâ¦ï¼P0-P1 éª¨æ¶æä¸å
许跨æ/跨年éé»åéï¼ |
| | | * ç®æ ææ å¯¹åºæ¯çæ¶æç¡®æ¥éï¼æä»½æ©å±è§åå¾
P0 æ¯çå®ç¨¿ååæ¾å¼ï¼ */ |
| | | private File resolveSummaryMother(String period, String mode) throws Exception { |
| | |
| | | SKIP/CHECK (0): TYPE_LABELS upper <template> |
| | | <el-container direction="vertical"> |
| | | <app-header title="交éç»è®¡æ¥è¡¨å®¡æ ¸ç³»ç» - æ°æ®å¯¼å
¥"></app-header> |
| | | <el-container> |
| | |
| | | <div v-else-if="moduleSel[g.key] && !isDirOnlyType(moduleSel[g.key])" class="module-file"> |
| | | <div class="file-name" :title="fileNamesText(moduleSel[g.key])">{{ fileNamesText(moduleSel[g.key]) || 'æªéæ©æä»¶' }}</div> |
| | | <div class="file-btns"> |
| | | <el-upload action="#" :auto-upload="false" :show-file-list="false" multiple accept=".xlsx,.xls,.et" |
| | | <el-upload action="#" :auto-upload="false" :show-file-list="false" multiple :accept="acceptOf(moduleSel[g.key])" |
| | | :ref="'up' + g.key" :on-change="f => onFilePicked(g.key, f)" style="display:inline-block"> |
| | | <el-button size="mini" type="primary" plain icon="el-icon-folder-opened" :disabled="importing">éæ©æä»¶</el-button> |
| | | </el-upload> |
| | |
| | | investCityPassenger: 'å¸å·å表ï¼å®¢è¿ç«åºï¼', investCityLogistics: 'å¸å·å表ï¼ç©æµååºï¼', |
| | | 'INVEST_客è¿ç«åº_CITY': 'å¸å·å表ï¼å®¢è¿ç«åºï¼', 'INVEST_ç©æµååº_CITY': 'å¸å·å表ï¼ç©æµååºï¼', |
| | | cityBus: 'åå¸å
¬äº¤ææ¥', cityTaxi: '巡游åºç§ææ¥', cityTaxiAuth: 'åºç§è½¦è¿æ¿è½¦è¾', |
| | | wycTotal: 'ç½çº¦è½¦æ»æ°', wycOrder: 'ç½çº¦è½¦è®¢ååå
¨çæ»é', |
| | | wycTotal: 'ç½çº¦è½¦æ»æ°', wycOrder: 'ç½çº¦è½¦è®¢ååå
¨çæ»é', wycOrderReport: 'ç½çº¦è½¦è®¢åæ¥å', |
| | | H2032: 'H203-2ææ¥', H2031: 'H203-1æ
å®¢ææ¥', H204: 'H204è½è壿¥', PASSENGER_AUTH: 'æ
å®¢è¿æ¿è½¦è¾æ°', |
| | | PASSENGER_INDIVIDUAL: '个ä½å®¢è¿é/å¨è½¬é', ENERGY_AUTH: 'è½è车è¾è¿æ¿ä¿¡æ¯', TRANSPORT_AUTH: 'è¿æ¿è½¦è¾', |
| | | TRACK_MILEAGE: '轨迹éç¨', SCALE_SPLIT: 'è§ä¸è§ä¸æå', FREIGHT_TURNOVER: 'è´§è¿éå¨è½¬é', |
| | | INVEST_SYSTEM: 'æèµç³»ç»å¯¼åº', CITY_BUS: 'åå¸å
¬äº¤ææ¥', CITY_TAXI: '巡游åºç§ææ¥', CITY_TAXI_AUTH: 'åºç§è½¦è¿æ¿è½¦è¾', WYC_TOTAL: 'ç½çº¦è½¦æ»æ°', WYC_ORDER: 'ç½çº¦è½¦è®¢ååå
¨çæ»é' |
| | | INVEST_SYSTEM: 'æèµç³»ç»å¯¼åº', CITY_BUS: 'åå¸å
¬äº¤ææ¥', CITY_TAXI: '巡游åºç§ææ¥', CITY_TAXI_AUTH: 'åºç§è½¦è¿æ¿è½¦è¾', WYC_TOTAL: 'ç½çº¦è½¦æ»æ°', WYC_ORDER: 'ç½çº¦è½¦è®¢ååå
¨çæ»é', WYC_ORDER_REPORT: 'ç½çº¦è½¦è®¢åæ¥å' |
| | | } |
| | | const BATCH_TYPE_MAP = { |
| | | H2032: 'h2032', TRANSPORT_AUTH: 'transportAuth', TRACK_MILEAGE: 'trackMileage', |
| | |
| | | H2031: 'passengerMonthly', PASSENGER_AUTH: 'passengerAuth', PASSENGER_INDIVIDUAL: 'passengerIndividual', |
| | | H204: 'energyMonthly', ENERGY_AUTH: 'energyAuth', |
| | | CITY_BUS: 'cityBus', CITY_TAXI: 'cityTaxi', CITY_TAXI_AUTH: 'cityTaxiAuth', |
| | | WYC_TOTAL: 'wycTotal', WYC_ORDER: 'wycOrder', |
| | | WYC_TOTAL: 'wycTotal', WYC_ORDER: 'wycOrder', WYC_ORDER_REPORT: 'wycOrderReport', |
| | | INVEST_SYSTEM: 'investmentSystem' |
| | | } |
| | | export default { |
| | |
| | | { value: 'cityTaxi', label: '巡游åºç§æ±½è½¦è¿è¥æå¡æ
嵿æ¥' }, |
| | | { value: 'cityTaxiAuth', label: 'åºç§è½¦è¿æ¿è½¦è¾' }, |
| | | { value: 'wycTotal', label: 'ç½çº¦è½¦æ»æ°' }, |
| | | { value: 'wycOrder', label: 'ç½çº¦è½¦è®¢ååå
¨çæ»é' } |
| | | { value: 'wycOrder', label: 'ç½çº¦è½¦è®¢ååå
¨çæ»é' }, |
| | | { value: 'wycOrderReport', label: 'ç½çº¦è½¦è®¢åæ¥å' } |
| | | ] |
| | | }, |
| | | { |
| | |
| | | cityTaxi: '导å
¥_巡游åºç§æ±½è½¦è¿è¥æå¡æ
嵿æ¥ï¼YYYYå¹´Mæï¼.xlsï¼å¸å·çº§17è¡ï¼', |
| | | cityTaxiAuth: '导å
¥æ¨¡æ¿_åºç§è½¦ä¿¡æ¯(è¿æ¿è½¦è¾ä¿¡æ¯).xlsxï¼è½¦è¾çº§æç»ï¼ç¨äºè¿è¥è½¦æ°å¯¹æ¯ï¼', |
| | | wycTotal: '模æ¿_ç½çº¦è½¦æ»æ°.xlsxï¼Aå=æä»½ï¼B-E=å
¨ç客è¿é/åå¸å
/å¨è½¬é/åå¸å
å¨è½¬éï¼', |
| | | wycOrder: '模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxï¼Aå=æä»½ï¼B-E=å
¨çpinï¼F=订åå计ï¼G-W=17å¸å·è®¢åï¼' |
| | | wycOrder: '模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsxï¼Aå=æä»½ï¼B-E=å
¨çpinï¼F=订åå计ï¼G-W=17å¸å·è®¢åï¼', |
| | | wycOrderReport: '模æ¿_ç½çº¦è½¦è®¢å.docxï¼ãç½çº¦è½¦è¡ä¸YYYYå¹´Mæè¿è¡çæµæ
åµåææ¥åãï¼èªå¨è§£æé件表ãå°å¸åç§°â¦è®¢åæ°æ»æ°ãç 17 å¸å·è®¢åï¼' |
| | | } |
| | | return map[this.importType] || '' |
| | | }, |
| | |
| | | cityTaxiAuth: 'åå¸å®¢è¿/导å
¥æ¨¡æ¿_åºç§è½¦ä¿¡æ¯(è¿æ¿è½¦è¾ä¿¡æ¯).xlsx', |
| | | wycTotal: 'åå¸å®¢è¿/模æ¿_ç½çº¦è½¦æ»æ°.xlsx', |
| | | wycOrder: 'åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢ååå
¨çæ»é.xlsx', |
| | | wycOrderReport: 'åå¸å®¢è¿/模æ¿_ç½çº¦è½¦è®¢å.docx', |
| | | investment: 'æèµ/è¾å
¥/客è¿ï¼å®¢è¿ç«ï¼/æ´æ°_7æå®¢è¿ç«æèµæç»è¡¨ï¼å¸å·æ±æ»å¤§è¡¨ï¼ç»é¢å¯¼ï¼.xlsx', |
| | | investmentLogistics: 'æèµ/è¾å
¥/ç©æµï¼ç©æµååºï¼/æ´æ°_7æç©æµç«åºæèµæç».xls', |
| | | investmentSystem: 'æèµ/模æ¿_æ¥è¯¢ç»æ(æèµç³»ç»-客è¿+ç©æµ 2026.7).xls' |
| | |
| | | cityTaxi: '/import/cityTaxi', |
| | | cityTaxiAuth: '/import/cityTaxiAuth', |
| | | wycTotal: '/import/wycTotal', |
| | | wycOrder: '/import/wycOrder' |
| | | wycOrder: '/import/wycOrder', |
| | | wycOrderReport: '/import/wycOrderReport' |
| | | } |
| | | return map[t] || '' |
| | | }, |
| | |
| | | this.$message.error((e.response && e.response.data && e.response.data.message) || 'æ¹é导å
¥å¤±è´¥') |
| | | }) |
| | | }, |
| | | acceptOf(type) { return type === 'wycOrderReport' ? '.docx,.doc' : '.xlsx,.xls,.et' }, |
| | | isCityDirType(t) { return t === 'investCityPassenger' || t === 'investCityLogistics' }, |
| | | isDirOnlyType(t) { return t === 'investCityPassenger' || t === 'investCityLogistics' }, |
| | | importCityDir(type) { |
| | |
| | | map[key] = { totalRows: r.totalRows, successRows: r.successRows, failRows: r.failRows, latestId: r.id } |
| | | } |
| | | }) |
| | | if (map.wycOrderReport && !map.wycOrder) map.wycOrder = map.wycOrderReport |
| | | this.overview = map |
| | | }) |
| | | .catch(e => { if (!e || !e._toast) this.$message.error('导å
¥è®°å½å 载失败ï¼è¯·å·æ°éè¯') }) |