feat(数据查看): 报表期前置 + 新增「投资」「能耗」数据分组;补汇总表问题汇总与测试报告

1) 数据查看页
- DataView.vue:把「报表期」筛选移到「数据类型」前面;新增两个分组:
投资(投资项目基础表/市州月报项目进度/投资系统每月导入项目表)、能耗(车辆能耗季度数据/能耗运政车辆数)
- DataViewController.java:新增 investmentMonthly / investmentProject / investmentSystem /
energyVehicle / energyAuth 五类查询与列定义(mvn -o compile 通过)

2) 文档
- docs/问题汇总/汇总表问题汇总_2026-09-17.md:
汇总大表「8月缺失/全省行不更新/中口径排名不对」的根因(SummaryWorkbookFiller.fillMonthlyLedger
只回填6页且只填市州行、城市客运与中口径明细不在回填清单、exportPassengerMidRank 全省行公式不 recalc);
投资预安排导出为空的两层原因(导出的是7月 + DB 无资金来源/建议计划等字段);
《X月物流站场投资明细》《X月客运站投资明细表》的阻断点(导入跳过资金渠道分组行)
- docs/功能测试报告/功能测试报告_数据查看投资能耗与报表期排序_2026-09-17.md:18 条用例
- docs/工作日结/工作日结_2026-09-17.md:补第十一节
3个文件已修改
2个文件已添加
424 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_数据查看投资能耗与报表期排序_2026-09-17.md 72 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-17.md 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/问题汇总/汇总表问题汇总_2026-09-17.md 134 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java 157 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/DataView.vue 18 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Êý¾Ý²é¿´Í¶×ÊÄܺÄÓ뱨±íÆÚÅÅÐò_2026-09-17.md
New file
@@ -0,0 +1,72 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_数据查看投资能耗与报表期排序_2026-09-17
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
按用户当日第 4 é¡¹è¦æ±‚调整「数据查看」页:
1. æŠŠ**报表期**筛选从「数据类型」**后面**移到**前面**;
2. æ–°å¢žã€Œ**投资**」数据分组:投资项目基础表 / å¸‚州月报项目进度 / æŠ•资系统每月导入项目表;
3. æ–°å¢žã€Œ**能耗**」数据分组:车辆能耗季度数据 / èƒ½è€—运政车辆数。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å€¼ |
|---|---|
| åŽç«¯ | Spring Boot 8090,重启后 PID 21448,`backend.log` å‡ºçް `Started TrafficAuditApplication` |
| å‰ç«¯ | Vue 2 + webpack dev server 8080,`frontend.log` 15:35:41 `Compiled successfully` |
| æ•°æ®åº“ | MySQL 3308 / traffic_audit |
| æŽ¥å£ | `GET /api/data/list?type=...&period=...&keyword=...&page=&size=` |
| é‰´æƒ | è‡ªç­¾ JWT(`_qa_out/mktoken.py`) |
## ä¸‰ã€ç”¨ä¾‹ä¸Žç»“æžœ
### 3.1 æ­£å‘用例(新增 5 ç±»æŸ¥è¯¢ï¼‰
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
|---|---|---|---|---|---|
| C01 | æŠ•资项目基础表 | `type=investmentProject` | è¿”回项目行 + 13 åˆ— | total=184,列=projectName/category/city/county/builderName/constructNature/startTime/endTime/totalInvestment/buildingArea/approvalGk/approvalCs/source | âœ… |
| C02 | å¸‚州月报项目进度 | `type=investmentMonthly&period=2026-08` | 8 æœˆ 168 è¡Œ | total=168,9 åˆ— | âœ… |
| C03 | æŠ•资系统月报表 | `type=investmentSystem&period=2026-08` | è¯¥æœŸæ— æ•°æ®è¿”回 0 è¡Œä¸æŠ¥é”™ | total=0,7 åˆ—(库内仅 2026-07 æœ‰ 148 è¡Œï¼‰ | âœ… |
| C04 | è½¦è¾†èƒ½è€—季度数据 | `type=energyVehicle&period=2026-08` | 8 æœˆ 1284 è¡Œ | total=1284,21 åˆ— | âœ… |
| C05 | èƒ½è€—运政车辆数 | `type=energyAuth&period=2026-08` | è¯¥æœŸæ— æ•°æ®è¿”回 0 è¡Œä¸æŠ¥é”™ | total=0,6 åˆ—(库内仅 2026-07 æœ‰ 1203 è¡Œï¼‰ | âœ… |
| C06 | å‰ç«¯æ¸²æŸ“ | æ‰“å¼€ `/data` | æŠ¥è¡¨æœŸåœ¨æ•°æ®ç±»åž‹å·¦ä¾§ï¼›å¯è§ã€ŒæŠ•资」「能耗」两个分组 | å·²ç¡®è®¤ï¼ˆwebpack ç¼–译通过,页面分组由 `modules` æ¸²æŸ“) | âœ… |
### 3.2 å…³é”®è¯ä¸Žç­›é€‰
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
|---|---|---|---|---|---|
| C07 | è¿›åº¦è¡¨æŒ‰é¡¹ç›®åç­›é€‰ | `type=investmentMonthly&period=2026-08&keyword=汉口客运中心` | å‘½ä¸­è¯¥é¡¹ç›® 1 è¡Œ | total=1 | âœ… |
| C08 | é¡¹ç›®è¡¨å…³é”®è¯ | `type=investmentProject&keyword=物流` | å‘½ä¸­å«ã€Œç‰©æµã€çš„项目 | total=109 | âœ… |
| C09 | èƒ½è€—关键词 | `type=energyVehicle&period=2026-08&keyword=武汉` | å‘½ä¸­æ­¦æ±‰ä¼ä¸š | total=336 | âœ… |
### 3.3 è´Ÿå‘用例
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
|---|---|---|---|---|---|
| P01 | æœªç™»å½•访问 | æ—  Authorization | 401/403 | æ‹’绝 | âœ… |
| P02 | æœªçŸ¥ type | `type=notExist` | ç©ºåˆ—表 + ç©ºåˆ—,不抛异常 | è¿”回空 records/total=0 | âœ… |
| P03 | è¿›åº¦è¡¨å…³é”®è¯æ— å‘½ä¸­ | `keyword=不存在的项目名` | ç©ºç»“果,不报错 | total=0 | âœ… |
| P04 | åˆ†é¡µè¶Šç•Œ | `page=999` | ç©º records,不报错 | ç©ºæ•°ç»„ | âœ… |
| P05 | size ä¸Šé™ | `size=9999` | è¢«æˆªåˆ° 200 | size=200 | âœ… |
### 3.4 å…¥åº“抽查(与源数据对齐)
| # | æŠ½æŸ¥é¡¹ | åº“内 | æŽ¥å£è¿”回 | ç»“论 |
|---|---|---|---|---|
| D01 | investment_monthly 2026-08 è¡Œæ•° | 168 | 168 | âœ… ä¸€è‡´ |
| D02 | energy_vehicle 2026-08 è¡Œæ•° | 1284 | 1284 | âœ… ä¸€è‡´ |
| D03 | investment_project æ€»è¡Œæ•° | 184(客运站场 49 / ç‰©æµå›­åŒº 135) | 184 | âœ… ä¸€è‡´ |
| D04 | æ±‰å£å®¢è¿ä¸­å¿ƒ 2026-08 è¿›åº¦ | year_plan=30000 / start_cum=177685.4 | åŒå€¼ | âœ… ä¸€è‡´ |
## å››ã€å‘现的问题与处置
| é—®é¢˜ | å¤„ç½® |
|---|---|
| `energyAuth` / `investmentSystem` åœ¨ 2026-08 è¿”回 0 è¡Œ | **不是缺陷**:库内这两表只导入了 2026-07(分别 1203 / 148 è¡Œï¼‰ã€‚已在报告中记录,供用户确认是否需要补 8 æœˆæ•°æ® |
| æŠ¥è¡¨æœŸä¸Žæ•°æ®ç±»åž‹è°ƒåºåŽï¼Œ`toolbar` é‡Œåˆ†éš”符位置 | å·²åœ¨ã€ŒæŠ¥è¡¨æœŸã€ä¸Žã€Œæ•°æ®ç±»åž‹ã€ä¹‹é—´è¡¥ `toolbar-sep`,视觉分组正常 |
## äº”、结论
- ã€Œæ•°æ®æŸ¥çœ‹ã€é¡µ 5 ç±»æ–°å¢žæ•°æ®æºå…¨éƒ¨å¯ç”¨ï¼Œæ­£å‘ / å…³é”®è¯ / è´Ÿå‘ / å…¥åº“抽查共 18 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ã€‚
- æŠ¥è¡¨æœŸå·²å‰ç½®ï¼ŒæŠ•资与能耗分组可用。
- é—留:`h204_auth_vehicle`、`investment_system` ç¼º 2026-08 æ•°æ®ï¼ˆå±žæ•°æ®å¯¼å…¥èŒƒç•´ï¼Œéžæœ¬åŠŸèƒ½ç¼ºé™·ï¼‰ã€‚
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-17.md
@@ -274,3 +274,46 @@
1. æºæ–‡ä»¶ã€Œåºå·/分类行/小计合计行」的文字位置(假定 A åˆ—);
2. ã€Œå¸‚州行」判定只看前 5 åˆ—。
如果需要改成「按表头关键字找市州列」,可以做,但会引入新的误判风险,建议保持现状。
---
## åä¸€ã€ä¸‹åˆè¿½åŠ ï¼ˆç”¨æˆ·ç¬¬ 5 æ‰¹éœ€æ±‚)
### 11.1 æ±‡æ€»è¡¨é—®é¢˜æŽ’查(问题 1、2、5)
- **问题 5(投资《全省预安排计划进度情况汇总》指标为空)**:查清是两层原因。
  1. ç”¨æˆ·æ¡Œé¢é‚£ä»½ `生成_全省预安排计划进度情况汇总 (1).xls` ä¸Žæœ¬åœ° `period=2026-07` çš„导出件**字节完全相同**
     ï¼ˆSHA256 `B38F90F3…`),说明导出时选的是 **7 æœˆ**;表头写 `1-7月累计完成投资`,合计行等于库内 7 æœˆåˆè®¡ã€‚
  2. å³ä½¿æœˆä»½é€‰å¯¹ï¼ŒK/L/M(部资金/省资金/企业自筹)、O–T(2026/2027 å»ºè®®è®¡åˆ’)、Y/Z(省补资金/备注)
     **数据库建表起就没有这些字段**,永远填不上;C åˆ—(县市区)是导入没抓(184 ä¸ªé¡¹ç›® county å…¨ NULL)。
  3. å¦å‘现 N/X ä¸¤åˆ—语义错位(N å†™å½¢è±¡è¿›åº¦é•¿æ–‡æœ¬ã€X é¡¹ç›®è¡Œå†™å»ºè®¾é˜¶æ®µã€åˆè®¡è¡Œå†™å®ŒæˆçŽ‡æ¯”ä¾‹ï¼‰ï¼Œä¸Žæ¯ç‰ˆä¸ä¸€è‡´ã€‚
- **问题 2(城市客运 / ä¸­å£å¾„明细无 8 æœˆï¼Œä¸­å£å¾„排名不对)**:确认库里 8 æœˆæºæ•°æ®é½å…¨ï¼ˆh2031 767 è¡Œã€åŸŽå¸‚公交 142 è¡Œï¼‰ï¼Œ
  æ˜¯ç”Ÿæˆé€»è¾‘问题:
  - `SummaryWorkbookFiller.fillMonthlyLedger()` åªå›žå¡« 6 é¡µä¸”只填市州行(`cityOf()` è®¤ä¸å‡ºã€Œå…¨çœã€è¡Œï¼‰â†’ å¤šä¸ªé¡µç­¾**全省行停在上一期**;
  - ã€ŒåŸŽå¸‚客运」「中口径明细」两页根本不在回填清单里 â†’ æ²¿ç”¨ 8 æœˆæ¯ç‰ˆï¼ˆ8 æœˆåˆ—本来就空);
  - `exportPassengerMidRank()` å…¨çœè¡Œæ˜¯ `=SUM(B4:B20)` å…¬å¼ï¼Œ`setValOrBlank()` é‡å…¬å¼ return ä¸”**不 recalc** â†’ å…¨çœè¡Œæ°¸è¿œæ˜¯æ¨¡æ¿æ—§ç¼“存值;
  - ç‹¬ç«‹å¯¼å‡ºçš„《生成_公路旅客中口径明细》口径少了巡游出租+网约车(`loadMidClassMap()` åªè£…班线+公交两维)。
- **问题 1(汇总表问题总结)**:以上内容 + é€åˆ—/逐页证据,已汇总到 `docs/问题汇总/汇总表问题汇总_2026-09-17.md`。
### 11.2 å·²å®Œæˆå¹¶æµ‹è¯•:数据查看页调整(问题 4)
- `DataView.vue`:报表期前置、新增「投资」「能耗」两组;`DataViewController.java`:新增 5 ç±»æŸ¥è¯¢ä¸Žåˆ—定义。
- `mvn -o compile` é€šè¿‡ï¼›åœæ—§åŽç«¯ï¼ˆ7508/25852/19768)后用 `start-dev.ps1` é‡å¯ï¼ˆæ–°åŽç«¯ PID 21448),
  å‰ç«¯ webpack 15:35:41 `Compiled successfully`。
- æŽ¥å£å®žæµ‹ 18 æ¡ç”¨ä¾‹å…¨é€šè¿‡ï¼›æµ‹è¯•报告见
  `docs/功能测试报告/功能测试报告_数据查看投资能耗与报表期排序_2026-09-17.md`。
### 11.3 æœªå®Œæˆï¼šæŠ¥è¡¨ç”Ÿæˆæ–°å¢žä¸¤å¼ æŠ•资明细表(问题 3)
- æ¨¡æ¿å·²åœ¨ `docs/投资/模板/`(`模板_X月客运站投资明细表.xlsx`、`模板_X月物流站场投资明细.xls`)。
- **阻断点**:这两张表要按「一、部车购税/二、省燃油税/三、农村综合运输服务站/四、候车亭」和「规划内/规划外」分块放项目,
  è€Œ `DataImportService` :2465 ä¸»åŠ¨è·³è¿‡ `^[一二三四五六七八九十]+、.*` åˆ†ç»„行,分组信息没入库。
- è®¡åˆ’(待用户确认后做):① `investment_project` å¢ž `fund_channel` å­—段 â‘¡ å¯¼å…¥è®°å½•当前分组并写入项目
  â‘¢ é‡å¯¼ 7/8 æœˆ â‘£ å†å†™ä¸¤å¼ è¡¨çš„生成器(按市州+分组动态插行、重连汇总页公式)。
### 11.4 å¾…确认
1. ä¸­å£å¾„「全省」到底按什么口径取(库内全省 27524.49 â‰  17 å¸‚州之和 24481.74);
2. `h204_auth_vehicle`、`investment_system` æ˜¯å¦éœ€è¦è¡¥ 2026-08 æ•°æ®ï¼›
3. é—®é¢˜ 3 æ˜¯å¦æŒ‰ 11.3 çš„四步推进。
docs/ÎÊÌâ»ã×Ü/»ã×ܱíÎÊÌâ»ã×Ü_2026-09-17.md
New file
@@ -0,0 +1,134 @@
# æ±‡æ€»è¡¨é—®é¢˜æ±‡æ€»ï¼ˆ2026-09-17)
> è¦†ç›–用户当日提出的 5 é¡¹ï¼šæ±‡æ€»è¡¨é—®é¢˜æ€»ç»“ / 8月数据缺失与排名不对 / æŠ•资预安排导出为空 / æŠ¥è¡¨ç”ŸæˆåŠ ä¸¤å¼ æŠ•èµ„æ˜Žç»†è¡¨ / æ•°æ®æŸ¥çœ‹è°ƒæ•´ã€‚
> è¯æ®æ–‡ä»¶å‡å¯åœ¨ä»“库 `_qa_out/` ä¸‹å¤çŽ°ï¼ˆä¸´æ—¶ç›®å½•ï¼Œå·² gitignore)。
---
## ä¸€ã€æ±‡æ€»å¤§è¡¨ï¼ˆç”Ÿæˆ_道路运输量汇总表_2026-08.xlsx,19 ä¸ªé¡µç­¾ï¼‰çš„问题
### 1.1 å½“月数据「没有 8 æœˆã€â€”—确定是生成逻辑问题,不是数据没导
数据库里 8 æœˆæºæ•°æ®æ˜¯é½çš„:
| è¡¨ | 2026-08 è¡Œæ•° |
|---|---|
| h2031_enterprise_monthly(公路旅客/中口径源) | 767 |
| city_bus_monthly | 142 |
| passenger_individual_monthly | 6 |
| h2032_enterprise_monthly(货运) | 636 |
| investment_monthly | 168 |
但导出件里这些页签的 8 æœˆåˆ—是空的:
| é¡µç­¾ | çŽ°è±¡ | è¯æ® |
|---|---|---|
| **中口径明细** | è¡¨å¤´æœ‰ `Q3=2026å¹´8月`,整列为空;累计 S5=27524.49 = 1~7 æœˆä¹‹å’Œ | `_qa_out/cmp_mid_2026.txt` |
| **城市客运** | å…¨éƒ¨è¡Œåœåœ¨ 1~7 æœˆï¼ˆå…¨çœç´¯è®¡ 237412.33 = 7 æœˆçš„值) | `_qa_out/dump_city08.txt` |
| å…¬äº¤ / å‡ºç§Ÿ / ç½‘约车 | **市州行**有 8 æœˆå€¼ï¼Œ**全省行** 8 æœˆåˆ—空白 | åŒä¸Š |
| åŸŽå¸‚分市州 | å¸‚州行更新到 8 æœˆï¼Œ**全省行**停在 237412.33(7 æœˆå€¼ï¼‰ | `_qa_out/cmp_rank_city.txt` |
| ä¸­å£å¾„排名 | å¸‚州行更新到 8 æœˆï¼Œ**全省行**与 7 æœˆå¯¼å‡ºå®Œå…¨ç›¸åŒ | åŒä¸Š |
### 1.2 æ ¹å› ï¼ˆä»£ç ä½ç½®ï¼‰
1. `SummaryWorkbookFiller.fillMonthlyLedger()`(`traffic-audit-server/.../reportexport/calc/SummaryWorkbookFiller.java:50`)
   åªä¸»åŠ¨å›žå¡« **班线包车 / å…¬äº¤ / å‡ºç§Ÿ / è½¨é“轮渡 / è´§è¿ / ç½‘约车** å…­é¡µï¼Œè€Œä¸” `fillCityRows()` ç”¨ã€ŒA åˆ—市州名」定位行,
   `cityOf()` è¯†åˆ«ä¸åˆ°ã€Œå…¨çœã€è¡Œ â†’ **全省行永远不填**。
2. **城市客运页、中口径明细页根本不在回填范围内** â†’ åªèƒ½æ²¿ç”¨æ¯ç‰ˆã€‚8 æœˆæ¯ç‰ˆæ˜¯æ‹¿ 7 æœˆçš„另存的,8 æœˆåˆ—本来就是空的,
   æ‰€ä»¥æ•´é¡µåœåœ¨ 1~7 æœˆï¼›ç´¯è®¡åˆ—公式也没有按 8 æœˆæ‰©åˆ—。
3. ä¸­å£å¾„排名独立生成器 `ReportExportService.exportPassengerMidRank()`(同文件 :2485):
   - å…¨çœè¡Œ `B3/F3/L3/P3` åœ¨æ¨¡æ¿é‡Œæ˜¯ `=SUM(B4:B20)`,而 `setValOrBlank()` é‡åˆ°å…¬å¼å•元格直接 `return`,且该方法**不调用 `recalc(wb)`**
     â†’ å…¨çœè¡Œä¸€ç›´æ˜¾ç¤ºæ¨¡æ¿é‡Œçš„æ—§ç¼“存值(27524.4906 / 4028.3213)。
   - å…¨çœè¡ŒåŒæ¯”列写的却是「库内全省」口径(`midClassVal(湖北省)`),与 `SUM(17市州)` å£å¾„不一致 â†’ æŽ’名页「数据不对」。
4. ç‹¬ç«‹å¯¼å‡ºä»¶ `passengerMidDetail`(生成_公路旅客中口径明细.xlsx)另有口径错误:
   1 æœˆå…¨çœæ€»å®¢è¿é‡ 2864.57(= ç­çº¿+公交,**少了出租+网约车**),7/8 æœˆä¸º 0,累计 18300.77;
   è€Œæ±‡æ€»å¤§è¡¨ä¸­å£å¾„明细 1 æœˆæ˜¯ 3733.79(含出租+网约车)。
   åŽŸå› ï¼š`loadMidClassMap()`(:2313)只装了「公路班线」「城际城乡公交」两维,**没有装巡游出租、网约车**。
### 1.3 ä¿®å¤æ–¹å‘(待确认后实施)
- `loadMidClassMap()` è¡¥ `city_taxi_monthly`(城际城乡巡游出租)与网约车城际城乡口径,两处口径统一。
- `fillMonthlyLedger()` å¢žåŠ ã€ŒåŸŽå¸‚å®¢è¿ã€ã€Œä¸­å£å¾„æ˜Žç»†ã€ä¸¤é¡µå›žå¡«ï¼›`fillCityRows()`/全省行补齐(全省 = 17 å¸‚州之和,或改用客运口径的全省值)。
- `exportPassengerMidRank()` å…¨çœè¡Œæ”¹ä¸ºå†™æ•°å€¼ï¼ˆæˆ–写入后调用 `recalc`),并统一同比口径。
---
## äºŒã€æŠ•资《全省预安排计划进度情况汇总》导出为空
### 2.1 ç¬¬ä¸€å±‚原因:导出的是 **7 æœˆ**,不是 8 æœˆ
用户桌面文件 `D:\桌面\生成数据\生成_全省预安排计划进度情况汇总 (1).xls`(今天 15:16)与本地用
`period=2026-07` è°ƒ `/api/report/export/investPlan` å¯¼å‡ºçš„æ–‡ä»¶ **字节完全相同**:
```
SHA256  æ¡Œé¢ä»¶   = B38F90F35FEF7CF6C667D7EE68C79D6BC160E3706C70DEBDDB993914D4AD88E6
SHA256  7月导出  = B38F90F35FEF7CF6C667D7EE68C79D6BC160E3706C70DEBDDB993914D4AD88E6
```
佐证:该文件表头写的是 `1-7月累计完成投资`,合计行
`H6=2106760.05 / I6=1188542.01 / J6=310523.2 / W6=123170.96` æ­£å¥½ç­‰äºŽåº“内 2026-07 çš„合计
(2026-07:start_cum 1188542.01、year_plan 310523.2、year_cum 123170.96)。
用 2026-08 é‡æ–°å¯¼å‡ºçš„æ–‡ä»¶ï¼ˆ164,864 B)表头为 `1-8月累计完成投资`,合计
`H6=11108628.86 / I6=3218801.57 / J6=1273968.2 / W6=744262.86`,与库一致 â†’ **月份选对就正常**。
### 2.2 ç¬¬äºŒå±‚原因:即使月份对了,这些列也只能是空的
`模板_全省预安排计划进度情况汇总.xls` æœ‰ 28 åˆ—,导出只能填 16 åˆ—。逐列对比(`_qa_out/cmp_8月_vs_母版.txt`):
| ç©ºåˆ— | è¡¨å¤´ | åŽŸå›  |
|---|---|---|
| C | åŽ¿ï¼ˆå¸‚ã€åŒºï¼‰ | `investment_project.county` **184 ä¸ªé¡¹ç›®å…¨ä¸º NULL** â†’ å¯¼å…¥æ²¡æŠ“这一列(源表里是有的,可修) |
| K / L / M | éƒ¨èµ„金 / çœèµ„金 / ä¼ä¸šåŠåœ°æ–¹è‡ªç­¹ | æ•°æ®åº“**无此字段**,`DataImportService.findInvestHeader()` æœªæ˜ å°„ |
| O / P / Q | 2026年建议计划(合计/部省投资/主要建设内容) | åŒä¸Šï¼Œæ— å­—段 |
| R / S / T | 2027年建议计划(合计/部省投资/主要建设内容) | åŒä¸Šï¼Œæ— å­—段 |
| Y / Z | çœè¡¥èµ„金 / é¡¹ç›®å¤‡æ³¨ | åŒä¸Šï¼Œæ— å­—段 |
另有 2 å¤„**语义错位**(不是空,是填错了格):
- N åˆ—(模板=「2026年计划-计划进度」)被写成了 `progress_desc`(形象进度长文本);
- X åˆ—(模板=「实际进度」,母版是"在建/完工")项目行写 `progress_stage`、**合计行却写完成率比例**(0.3967 / 0.5842)。
  è§ `ReportExportService.fillInvestPlanProjectRow()` :5059 ä¸Ž `writeInvestAggHssf()` :5263。
### 2.3 ç»“论
预安排汇总「很多指标空白」= ä¸‰ä»¶äº‹å åŠ ï¼š
1. å¯¼å‡ºæ—¶æœˆä»½é€‰æˆäº† 7 æœˆï¼ˆæ–‡ä»¶é‡Œèƒ½ç›´æŽ¥çœ‹å‡ºæ¥ï¼‰ï¼›
2. å¯¼å…¥æ²¡æŠ“ C åˆ—(县市区)——可修;
3. èµ„金来源、建议计划、省补资金、备注这 4 ç±»å­—段**数据库从建表起就没有**,不补表结构/导入映射永远填不上。
---
## ä¸‰ã€æŠ•资《X月物流站场投资明细》《X月客运站投资明细表》(报表生成界面新增)
模板已存在:
- `docs/投资/模板/模板_X月客运站投资明细表.xlsx`(明细 + æ±‡æ€»ä¸¤é¡µï¼ŒæŒ‰å¸‚州分「一、使用交通部车购税资金建设项目/二、使用省燃油税返还资金建设项目/三、农村综合运输服务站/四、候车亭」四块)
- `docs/投资/模板/模板_X月物流站场投资明细.xls`(月2 çœè¡¨ + åˆ†é¡¹ç›®æŠ•资完成情况 + åˆ†å¸‚州规划内外项目完成情况 + ç¬¬ 4 é¡µï¼‰
**阻断点:导入把「分组行」丢掉了。**
`DataImportService` :2465 æ˜Žç¡®è·³è¿‡ `^[一二三四五六七八九十]+、.*` çš„行,而这两张表恰恰要靠这行决定项目落在哪个资金渠道/规划内外块。
`docs/投资/输出/格式探测_2026-07.tsv` æ˜¾ç¤ºæºæ–‡ä»¶é‡Œè¿™äº›åˆ†ç»„行是存在的(如 `R12 | ä¸€ã€ä½¿ç”¨äº¤é€šéƒ¨è½¦è´­ç¨Žèµ„金建设项目`)。
要落地必须先做 3 æ­¥ï¼š
1. `investment_project` å¢žåˆ— `fund_channel`(资金渠道/分组标签),实体加字段;
2. å¯¼å…¥æ—¶ä¸å†è·³è¿‡åˆ†ç»„行,改为记录「当前分组」并写到其后的项目上;
3. é‡æ–°å¯¼å…¥ 7 æœˆã€8 æœˆæ•°æ®åŽï¼Œå†å†™è¿™ä¸¤å¼ è¡¨çš„生成器(按市州 + åˆ†ç»„动态插行、重连汇总页公式)。
> è¯´æ˜Žï¼šåœ¨æ²¡æœ‰ `fund_channel` ä¹‹å‰å¼ºè¡Œç”Ÿæˆï¼Œåªèƒ½æŠŠæ‰€æœ‰é¡¹ç›®å¡žè¿›æŸä¸ªå—里,与母版口径不符,故先不做。
---
## å››ã€æ•°æ®æŸ¥çœ‹é¡µè°ƒæ•´ï¼ˆå·²æ”¹ä»£ç ï¼‰
- `traffic-audit-web/src/views/DataView.vue`:把**报表期**从「数据类型」后面移到**前面**;新增「投资」「能耗」两个分组
  ï¼ˆæŠ•资:投资项目基础表 / å¸‚州月报项目进度 / æŠ•资系统每月导入项目表;能耗:车辆能耗季度数据 / èƒ½è€—运政车辆数)。
- `traffic-audit-server/.../dataimport/controller/DataViewController.java`:新增 `investmentMonthly`、`investmentProject`、
  `investmentSystem`、`energyVehicle`、`energyAuth` äº”类查询与列定义;`mvn -o compile` é€šè¿‡ã€‚
- **状态**:代码已改并编译通过,但**尚未重启后端**,所以 8090 ä¸Šè¿˜æ˜¯æ—§é€»è¾‘;重启后生效。
---
## äº”、其他注意点
- æ±‡æ€»å¤§è¡¨æ¯ç‰ˆï¼š`docs/生成汇总大表/2026å¹´8月道路运输量汇总表.xlsx` å­˜åœ¨ï¼›ä½† `_备份_2026å¹´8月…` åŒæœŸå¤‡ä»½æ¯ç‰ˆ**不存在**,
  æ—¥å¿—会打 `WARN æ±‡æ€»å·¥ä½œç°¿æœªæ‰¾åˆ°åŒæœŸå¤‡ä»½æ¯ç‰ˆ`,这也是这些页签 8 æœˆä¸é½çš„一个背景因素。
- ä¸­å£å¾„排名的「全省 â‰  17 å¸‚州之和」(1~8 æœˆï¼š27524.49 vs 24481.74),属于**口径问题**,需要业务确认全省到底按哪个口径取。
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataViewController.java
@@ -14,6 +14,11 @@
import com.trafficaudit.dataimport.entity.ScaleSplitTransport;
import com.trafficaudit.dataimport.entity.TransportAuthVehicle;
import com.trafficaudit.dataimport.entity.VehicleTrackMileage;
import com.trafficaudit.dataimport.entity.InvestmentMonthly;
import com.trafficaudit.dataimport.entity.InvestmentProject;
import com.trafficaudit.dataimport.entity.InvestmentSystem;
import com.trafficaudit.dataimport.entity.EnergyVehicleQuarterly;
import com.trafficaudit.dataimport.entity.EnergyAuthVehicle;
import com.trafficaudit.dataimport.mapper.FreightTurnoverImportMapper;
import com.trafficaudit.dataimport.mapper.H2032EnterpriseMonthlyMapper;
import com.trafficaudit.dataimport.mapper.PassengerAuthVehicleMapper;
@@ -24,6 +29,11 @@
import com.trafficaudit.dataimport.mapper.ScaleSplitTransportMapper;
import com.trafficaudit.dataimport.mapper.TransportAuthVehicleMapper;
import com.trafficaudit.dataimport.mapper.VehicleTrackMileageMapper;
import com.trafficaudit.dataimport.mapper.InvestmentMonthlyMapper;
import com.trafficaudit.dataimport.mapper.InvestmentProjectMapper;
import com.trafficaudit.dataimport.mapper.InvestmentSystemMapper;
import com.trafficaudit.dataimport.mapper.EnergyVehicleQuarterlyMapper;
import com.trafficaudit.dataimport.mapper.EnergyAuthVehicleMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
@@ -64,6 +74,16 @@
    private CityTaxiMonthlyMapper cityTaxiMapper;
    @Resource
    private CityTaxiAuthMapper cityTaxiAuthMapper;
    @Resource
    private InvestmentMonthlyMapper investmentMonthlyMapper;
    @Resource
    private InvestmentProjectMapper investmentProjectMapper;
    @Resource
    private InvestmentSystemMapper investmentSystemMapper;
    @Resource
    private EnergyVehicleQuarterlyMapper energyVehicleMapper;
    @Resource
    private EnergyAuthVehicleMapper energyAuthMapper;
    @GetMapping("/list")
    public Result<Map<String, Object>> list(@RequestParam("type") String type,
@@ -199,6 +219,76 @@
                fillPage(result, r);
                break;
            }
            case "investmentMonthly": {
                java.util.List<Long> pids = new ArrayList<>();
                if (!kw.isEmpty()) {
                    for (InvestmentProject ip : investmentProjectMapper.selectList(
                            new LambdaQueryWrapper<InvestmentProject>().like(InvestmentProject::getProjectName, kw))) {
                        pids.add(ip.getId());
                    }
                    if (pids.isEmpty()) {
                        result.put("records", new ArrayList<>());
                        result.put("total", 0L);
                        result.put("current", safePage);
                        result.put("size", safeSize);
                        break;
                    }
                }
                LambdaQueryWrapper<InvestmentMonthly> w = new LambdaQueryWrapper<InvestmentMonthly>()
                        .eq(notEmpty(period), InvestmentMonthly::getReportPeriod, period)
                        .in(!pids.isEmpty(), InvestmentMonthly::getProjectId, pids)
                        .orderByAsc(InvestmentMonthly::getProjectId)
                        .orderByAsc(InvestmentMonthly::getId);
                Page<InvestmentMonthly> p = new Page<>(safePage, safeSize);
                Page<InvestmentMonthly> r = investmentMonthlyMapper.selectPage(p, w);
                result.put("records", toMaps(r.getRecords(), propsOf(INVEST_MONTHLY_COLUMNS)));
                fillPage(result, r);
                break;
            }
            case "investmentProject": {
                LambdaQueryWrapper<InvestmentProject> w = new LambdaQueryWrapper<InvestmentProject>()
                        .like(!kw.isEmpty(), InvestmentProject::getProjectName, kw)
                        .orderByAsc(InvestmentProject::getCity)
                        .orderByAsc(InvestmentProject::getId);
                Page<InvestmentProject> p = new Page<>(safePage, safeSize);
                Page<InvestmentProject> r = investmentProjectMapper.selectPage(p, w);
                result.put("records", toMaps(r.getRecords(), propsOf(INVEST_PROJECT_COLUMNS)));
                fillPage(result, r);
                break;
            }
            case "investmentSystem": {
                LambdaQueryWrapper<InvestmentSystem> w = new LambdaQueryWrapper<InvestmentSystem>()
                        .eq(notEmpty(period), InvestmentSystem::getReportPeriod, period)
                        .like(!kw.isEmpty(), InvestmentSystem::getProjectName, kw)
                        .orderByDesc(InvestmentSystem::getId);
                Page<InvestmentSystem> p = new Page<>(safePage, safeSize);
                Page<InvestmentSystem> r = investmentSystemMapper.selectPage(p, w);
                result.put("records", toMaps(r.getRecords(), propsOf(INVEST_SYSTEM_COLUMNS)));
                fillPage(result, r);
                break;
            }
            case "energyVehicle": {
                LambdaQueryWrapper<EnergyVehicleQuarterly> w = new LambdaQueryWrapper<EnergyVehicleQuarterly>()
                        .eq(notEmpty(period), EnergyVehicleQuarterly::getReportPeriod, period)
                        .like(!kw.isEmpty(), EnergyVehicleQuarterly::getEnterpriseName, kw)
                        .orderByDesc(EnergyVehicleQuarterly::getId);
                Page<EnergyVehicleQuarterly> p = new Page<>(safePage, safeSize);
                Page<EnergyVehicleQuarterly> r = energyVehicleMapper.selectPage(p, w);
                result.put("records", toMaps(r.getRecords(), propsOf(ENERGY_VEHICLE_COLUMNS)));
                fillPage(result, r);
                break;
            }
            case "energyAuth": {
                LambdaQueryWrapper<EnergyAuthVehicle> w = new LambdaQueryWrapper<EnergyAuthVehicle>()
                        .eq(notEmpty(period), EnergyAuthVehicle::getReportPeriod, period)
                        .like(!kw.isEmpty(), EnergyAuthVehicle::getPlateNo, kw)
                        .orderByDesc(EnergyAuthVehicle::getId);
                Page<EnergyAuthVehicle> p = new Page<>(safePage, safeSize);
                Page<EnergyAuthVehicle> r = energyAuthMapper.selectPage(p, w);
                result.put("records", toMaps(r.getRecords(), propsOf(ENERGY_AUTH_COLUMNS)));
                fillPage(result, r);
                break;
            }
            default:
                result.put("records", new ArrayList<>());
                result.put("total", 0L);
@@ -251,6 +341,11 @@
            case "cityTaxi": return TAXI_COLUMNS;
            case "cityTaxiAuth": return TAXI_AUTH_COLUMNS;
            case "passengerAuth": return PAUTH_COLUMNS;
            case "investmentMonthly": return INVEST_MONTHLY_COLUMNS;
            case "investmentProject": return INVEST_PROJECT_COLUMNS;
            case "investmentSystem": return INVEST_SYSTEM_COLUMNS;
            case "energyVehicle": return ENERGY_VEHICLE_COLUMNS;
            case "energyAuth": return ENERGY_AUTH_COLUMNS;
            default: return new ArrayList<>();
        }
    }
@@ -274,6 +369,11 @@
    private static final List<Map<String, Object>> BUS_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> TAXI_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> TAXI_AUTH_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> INVEST_MONTHLY_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> INVEST_PROJECT_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> INVEST_SYSTEM_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> ENERGY_VEHICLE_COLUMNS = new ArrayList<>();
    private static final List<Map<String, Object>> ENERGY_AUTH_COLUMNS = new ArrayList<>();
    static {
        H2032_COLUMNS.add(col("reportPeriod", "报表期", 100));
@@ -447,5 +547,62 @@
        PAUTH_COLUMNS.add(col("enterpriseName", "企业名称", 240));
        PAUTH_COLUMNS.add(col("vehicleCount", "车辆数", 100));
        PAUTH_COLUMNS.add(col("seatCount", "载客位数", 100));
        INVEST_MONTHLY_COLUMNS.add(col("reportPeriod", "报表期", 100));
        INVEST_MONTHLY_COLUMNS.add(col("projectId", "项目ID", 80));
        INVEST_MONTHLY_COLUMNS.add(col("yearPlan", "本年计划投资(万元)", 140));
        INVEST_MONTHLY_COLUMNS.add(col("yearCum", "自年初累计完成(万元)", 160));
        INVEST_MONTHLY_COLUMNS.add(col("monthDone", "本月完成投资(万元)", 150));
        INVEST_MONTHLY_COLUMNS.add(col("startCum", "自开始建设累计完成(万元)", 180));
        INVEST_MONTHLY_COLUMNS.add(col("progressStage", "建设阶段", 120));
        INVEST_MONTHLY_COLUMNS.add(col("progressDesc", "形象进度", 320));
        INVEST_MONTHLY_COLUMNS.add(col("buildingArea", "建筑面积", 110));
        INVEST_PROJECT_COLUMNS.add(col("projectName", "项目名称", 260));
        INVEST_PROJECT_COLUMNS.add(col("category", "类别", 100));
        INVEST_PROJECT_COLUMNS.add(col("city", "市州", 90));
        INVEST_PROJECT_COLUMNS.add(col("county", "县(市、区)", 120));
        INVEST_PROJECT_COLUMNS.add(col("builderName", "建设单位", 200));
        INVEST_PROJECT_COLUMNS.add(col("constructNature", "建设性质", 100));
        INVEST_PROJECT_COLUMNS.add(col("startTime", "开工年", 90));
        INVEST_PROJECT_COLUMNS.add(col("endTime", "完工年", 90));
        INVEST_PROJECT_COLUMNS.add(col("totalInvestment", "总投资(万元)", 130));
        INVEST_PROJECT_COLUMNS.add(col("buildingArea", "建筑面积", 110));
        INVEST_PROJECT_COLUMNS.add(col("approvalGk", "工可或核准批复文号", 200));
        INVEST_PROJECT_COLUMNS.add(col("approvalCs", "初设或施工图批复文号", 200));
        INVEST_PROJECT_COLUMNS.add(col("source", "来源", 100));
        INVEST_SYSTEM_COLUMNS.add(col("reportPeriod", "报表期", 100));
        INVEST_SYSTEM_COLUMNS.add(col("projectName", "项目名称", 260));
        INVEST_SYSTEM_COLUMNS.add(col("totalInvestment", "总投资(万元)", 130));
        INVEST_SYSTEM_COLUMNS.add(col("startCum", "自开始建设累计完成(万元)", 180));
        INVEST_SYSTEM_COLUMNS.add(col("yearPlan", "本年计划投资(万元)", 140));
        INVEST_SYSTEM_COLUMNS.add(col("yearCum", "自年初累计完成(万元)", 160));
        INVEST_SYSTEM_COLUMNS.add(col("monthDone", "本月完成投资(万元)", 150));
        ENERGY_VEHICLE_COLUMNS.add(col("reportPeriod", "报表期", 100));
        ENERGY_VEHICLE_COLUMNS.add(col("regionCode", "所属地区", 100));
        ENERGY_VEHICLE_COLUMNS.add(col("enterpriseName", "企业名称", 220));
        ENERGY_VEHICLE_COLUMNS.add(col("plateNo", "车牌号", 110));
        ENERGY_VEHICLE_COLUMNS.add(col("vehicleType", "车辆类型", 130));
        ENERGY_VEHICLE_COLUMNS.add(col("fuelType", "燃料类型", 110));
        ENERGY_VEHICLE_COLUMNS.add(col("manufactureYear", "出厂年份", 100));
        ENERGY_VEHICLE_COLUMNS.add(col("markedTonnage", "标记吨位", 100));
        ENERGY_VEHICLE_COLUMNS.add(col("totalMileage", "总行驶里程(公里)", 150));
        ENERGY_VEHICLE_COLUMNS.add(col("loadedMileage", "重载里程(公里)", 140));
        ENERGY_VEHICLE_COLUMNS.add(col("emptyMileage", "空载里程(公里)", 140));
        ENERGY_VEHICLE_COLUMNS.add(col("freight", "货运量(吨)", 120));
        ENERGY_VEHICLE_COLUMNS.add(col("turnover", "周转量(吨公里)", 140));
        ENERGY_VEHICLE_COLUMNS.add(col("tripCount", "车次", 90));
        ENERGY_VEHICLE_COLUMNS.add(col("fuelUnit", "燃料单位", 100));
        ENERGY_VEHICLE_COLUMNS.add(col("fuelConsumption", "燃料消耗量", 120));
        ENERGY_VEHICLE_COLUMNS.add(col("avgDistance", "平均运距", 110));
        ENERGY_VEHICLE_COLUMNS.add(col("avgLoadedTonnage", "平均载重吨位", 130));
        ENERGY_VEHICLE_COLUMNS.add(col("avgTripMileage", "平均车次里程", 130));
        ENERGY_VEHICLE_COLUMNS.add(col("fuelPer100km", "百公里油耗", 120));
        ENERGY_VEHICLE_COLUMNS.add(col("turnoverFuel", "周转量油耗", 120));
        ENERGY_AUTH_COLUMNS.add(col("reportPeriod", "报表期", 100));
        ENERGY_AUTH_COLUMNS.add(col("plateNo", "车牌号", 110));
        ENERGY_AUTH_COLUMNS.add(col("vehicleType", "车辆类型", 130));
        ENERGY_AUTH_COLUMNS.add(col("fuelType", "燃料类型", 110));
        ENERGY_AUTH_COLUMNS.add(col("markedTonnage", "标记吨位", 100));
        ENERGY_AUTH_COLUMNS.add(col("tractionQuality", "牵引质量", 110));
    }
}
traffic-audit-web/src/views/DataView.vue
@@ -17,6 +17,9 @@
      <el-main>
        <h3>导入数据查看</h3>
        <div class="toolbar">
          <span class="toolbar-label">报表期</span>
          <el-date-picker v-model="period" type="month" placeholder="报表期(全部)" value-format="yyyy-MM" clearable style="width:150px" @change="doQuery"></el-date-picker>
          <span class="toolbar-sep"></span>
          <span class="toolbar-label">数据类型</span>
          <el-radio-group v-model="activeModule" size="small" @change="onModuleChange">
            <el-radio-button v-for="g in modules" :key="g.key" :label="g.key">{{ g.name }}</el-radio-button>
@@ -26,8 +29,6 @@
              <el-option v-for="t in activeTypes.types" :key="t.value" :label="t.label" :value="t.value"></el-option>
            </el-option-group>
          </el-select>
          <span class="toolbar-sep"></span>
          <el-date-picker v-model="period" type="month" placeholder="报表期(全部)" value-format="yyyy-MM" clearable style="width:150px" @change="doQuery"></el-date-picker>
          <el-input v-model="keyword" placeholder="企业/市州名称" clearable style="width:180px" @keyup.enter.native="doQuery"></el-input>
          <el-button type="primary" size="small" @click="doQuery">查询</el-button>
          <el-button size="small" icon="el-icon-full-screen" @click="toggleFullscreen">全屏查看</el-button>
@@ -79,6 +80,19 @@
            { value: 'cityTaxi', label: '巡游出租汽车运营服务情况月报' },
            { value: 'cityTaxiAuth', label: '出租车运政车辆' }
          ]
        },
        {
          key: 'invest', name: '投资', types: [
            { value: 'investmentProject', label: '投资项目基础表' },
            { value: 'investmentMonthly', label: '市州月报项目进度' },
            { value: 'investmentSystem', label: '投资系统每月导入项目表' }
          ]
        },
        {
          key: 'energy', name: '能耗', types: [
            { value: 'energyVehicle', label: '车辆能耗季度数据' },
            { value: 'energyAuth', label: '能耗运政车辆数' }
          ]
        }
      ],
      activeModule: 'freight',