b14fec1599277629e10b2bc686f02fd0c2e0bec1..ade4387f72c876f779b0956295922003464434f0
2026-09-19 zhizhijie
fix(汇总表): 中口径排名周转量口径统一为「总量-城市内」差额法
ade438 对比 | 目录
2026-09-19 zhizhijie
refactor(货运): 汇总类查询小数位统一为4位(等于全精度) + 适用范围验证
3a41fc 对比 | 目录
2026-09-19 zhizhijie
fix(货运): 明细查询去掉ROUND改为全精度导出 + 小数位约定说明 + 两查询等价性验证
677d0e 对比 | 目录
2026-09-19 zhizhijie
feat(货运): 同名企业口径SQL新增企业明细导出查询(546家/含改名标记)+导出说明
b41a08 对比 | 目录
2026-09-19 zhizhijie
docs(货运): 新增同名企业(545家)1-8月累计货运量/周转量SQL查询脚本 + 09-19功能测试报告与工作日结
abb2a3 对比 | 目录
2026-09-19 zhizhijie
feat(运维): 新增 stop-dev.ps1 一键停止脚本 + 桌面启停入口文档(含编码坑修复记录)
66b1da 对比 | 目录
2026-09-19 zhizhijie
docs(工作日结): 记录三项投资遗留问题的处置(武汉忽略/天门待补源数据/荆州黄石待确认口径)
178655 对比 | 目录
2026-09-19 zhizhijie
docs: 2026-09-19 功能测试报告与工作日结(夜间续作)+ 中口径排名根因方案
1cc975 对比 | 目录
2026-09-19 zhizhijie
feat(报表): 新增客运站/物流站场投资明细表导出 + 中口径同比口径修复 + 隐藏网约车订单入口
0a3f49 对比 | 目录
2026-09-19 zhizhijie
fix(导入): 投资市州单表表头取列定位修复 + 补齐2026-08投资源数据
60b834 对比 | 目录
9个文件已修改
35个文件已添加
2022 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_一键启停脚本与桌面入口_2026-09-19.md 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_中口径排名周转量口径统一_2026-09-19.md 67 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_同名企业1-8月累计货运量与周转量SQL_2026-09-19.md 206 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_投资明细表与导入取列定位修复_2026-09-19.md 86 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_持续在规企业545家分市州累计运距同比_2026-09-19.md 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/城市客运/模板_网约车订单及全省总量.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-18.md 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-19.md 129 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工具/持续在规企业545家累计运距生成.py 174 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/2026年8月咸宁市客运站场投资统计月报表(1)省表.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/2026年8月林区道路客运站场投资统计报表(月、年报).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/2026年8月站场固投(南山、汉口站).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/2026湖北省道路客运站场投资统计报8月(恩施州) (1).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/十堰市2026年8月固定资产月报电子版投资表格.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/湖北省宜昌市道路客运站场投资报表(月、年报)08月.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/荆门市客运站场投资统计8月.xls(1).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/襄阳市道路运输服务中心2026年8月投资.et 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/客运(客运站)/8月/(孝感市道运中心)202608孝感市道路客运站场投资统计月报表.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/202608---黄冈物流站场投资表(最终版).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月份孝感物流项目投资统计表.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月份物流(货运)投资项目明细表(黄石市)(1).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月企业汇总(鄂州).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月恩施州物流(货运)项目投资明细.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月湖北省襄阳市交通物流基础设施投资统计报表.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/2026年8月物流基础设施建设投资月报(随州).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/8月份物流园中心建设项目(天门).xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/仙桃市物流园投资统计报表(202608).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/咸宁市2026年8月份物流(货运)项目投资明细 (1).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/湖北宜昌市物流基础设施投资统计报表(月、年报)08月.xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/湖北省十堰交通物流基础设施投资统计汇总表(月报)(2026年8月).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/潜江2026.08.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/神农架林区物流投资月报2026.08.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/荆州物流投资(2026年8月报省) (1).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/投资/输入/物流(物流园区)/8月/荆门2026年08月项目投资总报表(物流).xls 补丁 | 查看 | 原始文档 | blame | 历史
docs/生成汇总大表/同名企业_1-8月累计对比_2026-09-19.sql 319 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/生成汇总大表/生成_道路运输量汇总表.xlsx 补丁 | 查看 | 原始文档 | blame | 历史
docs/问题汇总/中口径排名同比与城市客运列错位_根因与长效方案_2026-09-18.md 195 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
stop-dev.ps1 57 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/WycSplitCalc.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/controller/ReportExportController.java 16 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java 495 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/DataImport.vue 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/ReportExport.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Ò»¼üÆôÍ£½Å±¾Óë×ÀÃæÈë¿Ú_2026-09-19.md
New file
@@ -0,0 +1,52 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_一键启停脚本与桌面入口_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
1. **新增 `stop-dev.ps1`(项目根目录)**:与既有 `start-dev.ps1` é…å¥—的一键停止脚本。
   - æŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ã€æ•´æ ‘结束:`cmd.exe /c mvn.cmd ... spring-boot:run`、`cmd.exe /c npm.cmd run serve`,
     ç”¨ `taskkill /T /F` è¿žå¸¦å­è¿›ç¨‹ï¼ˆmaven java â†’ app java;npm node â†’ cmd â†’ vue-cli-service node);
   - å…œåº•再按命令行特征精确匹配孤儿进程:`java.exe` å« `TrafficAuditApplication`、`node.exe` å« `vue-cli-service`;
   - ç»“束后校验 8090/8080 æ˜¯å¦å·²é‡Šæ”¾ï¼›
   - æ˜Žç¡®ä¸ç¢°å…¶å®ƒ node/java è¿›ç¨‹ï¼ˆå¦‚ Codex çš„ `node_repl`)与用户自己开的 cmd çª—口。
2. **桌面一键入口**(工作区外,不入库):
   - `D:\桌面\启动交通审核系统.bat`:调用 `start-dev.ps1`(已在跑则跳过、不在跑则拉起并等待就绪),最后打开 `http://localhost:8080`;
     å¸¦å‚æ•° `nobrowser` å¯åªå¯æœåŠ¡ä¸å¼¹æµè§ˆå™¨ã€‚
   - `D:\桌面\停止交通审核系统.bat`:调用 `stop-dev.ps1`。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å€¼ |
| --- | --- |
| æ—¥æœŸ | 2026-09-19 00:4x–00:5x |
| é¡¹ç›® | `D:\文档\ChatGPT\traffic-audit` |
| æœåŠ¡ | åŽç«¯ 8090(Spring Boot)、前端 8080(Vue)、MySQL 3308 |
| è„šæœ¬ç¼–ç  | `.ps1` = UTF-8 **with BOM**;`.bat` = **GBK(936) + CRLF**,首行 `chcp 936` |
## ä¸‰ã€ç”¨ä¾‹è¡¨
| ç¼–号 | ç”¨ä¾‹ | è¾“å…¥/操作 | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T01 | å·²åœ¨è¿è¡Œæ—¶å¯åŠ¨ï¼ˆæ­£å‘Â·å¹‚ç­‰ï¼‰ | æœåŠ¡åœ¨è·‘æ—¶æ‰§è¡Œ `启动交通审核系统.bat nobrowser` | è·³è¿‡å¯åŠ¨ï¼Œä¸æ–°å»ºé‡å¤è¿›ç¨‹ | æ‰“印「后端已在运行(8090 æœ‰ç›‘听),跳过启动。」「前端已在运行(8080 æœ‰ç›‘听),跳过启动。」,随后校验「后端: OK,已就绪」「前端: OK,已就绪」 | âœ… é€šè¿‡ |
| T02 | æœªè¿è¡Œæ—¶å¯åŠ¨ï¼ˆæ­£å‘ï¼‰ | æœåŠ¡å·²åœæ—¶æ‰§è¡Œ `启动交通审核系统.bat nobrowser` | æ‹‰èµ·å‰åŽç«¯å¹¶ç­‰å¾…就绪 | æ–°å»ºåŽç«¯é“¾ï¼ˆcmd PID 8964 â†’ java â†’ app java)与前端链(cmd PID 26024 â†’ node â†’ cmd â†’ node);`backend.log` å‡ºçް `Tomcat started on port(s): 8090` ä¸Ž `Started TrafficAuditApplication`(00:48:33) | âœ… é€šè¿‡ |
| T03 | åœæ­¢æœåŠ¡ï¼ˆæ­£å‘ï¼‰ | æ‰§è¡Œ `停止交通审核系统.bat` | ä¸¤ä¸ªè¿›ç¨‹æ ‘被结束,端口释放 | åŽç«¯ 5 ä¸ªè¿›ç¨‹ã€å‰ç«¯ 5 ä¸ªè¿›ç¨‹è¢«ç»“束;打印「端口 8090:已释放」「端口 8080:已释放」 | âœ… é€šè¿‡ |
| T04 | å¯åœé—­çŽ¯å¯ç”¨æ€§ï¼ˆæ­£å‘ï¼‰ | åœ â†’ å¯ ä¹‹åŽè®¿é—®é¡µé¢æŽ¥å£ | å‰ç«¯ 8080、后端接口均正常 | å‰ç«¯ `HTTP 200`;后端 `/api/import/batches` `HTTP 200`(能取到最近「市州单表批量导入(物流(物流园区)/8月)」批次) | âœ… é€šè¿‡ |
| T05 | ä¸è¯¯æ€ï¼ˆè´Ÿå‘) | æ‰§è¡Œåœæ­¢è„šæœ¬æœŸé—´è§‚å¯Ÿ Codex è‡ªèº« | Codex å†…æ ¸ `node_repl` ä¸Žå…¶å®ƒ cmd çª—口不受影响 | åœæ­¢è„šæœ¬ä»åœ¨æ­£å¸¸è¿è¡Œï¼ˆæœ¬ä¼šè¯å·¥å…·è°ƒç”¨æœªä¸­æ–­ï¼‰ï¼Œå…¨ç¨‹æœªåŒ¹é… `node_repl` | âœ… é€šè¿‡ |
## å››ã€å‘现的问题与处置
| ç¼–号 | é—®é¢˜ | æ ¹å›  | å¤„ç½® |
| --- | --- | --- | --- |
| P01 | ç¬¬ä¸€ç‰ˆ `.bat` è¿è¡Œæ—¶å¤§é‡æŠ¥ `'xx' is not recognized as an internal or external command`,且命令行被截断(如 `'xecutionPolicy'`) | æ‰¹å¤„理文件必须使用 **CRLF** æ¢è¡Œï¼Œé¦–版写成了 LF,cmd é€è¡Œè§£æžé”™ä½ | æ”¹ä¸ºæŒ‰è¡Œæ•°ç»„ `-join "\`r\`n"` å†™å‡ºï¼Œå¤æµ‹æ­£å¸¸ |
| P02 | é¦–版 `stop-dev.ps1` æŠ¥ `UnexpectedToken`/「字符串缺少终止符」,中文提示被读成乱码 | Windows PowerShell 5.1 è¯»å–**无 BOM** çš„ UTF-8 è„šæœ¬æ—¶æŒ‰ ANSI(936) è§£é‡Šï¼Œå¤šå­—节序列被打断 | æ”¹å†™ä¸º **UTF-8 with BOM**(与既有 `start-dev.ps1` ä¸€è‡´ï¼‰ï¼Œå¤æµ‹æ­£å¸¸ |
| P03 | åœæ­¢è„šæœ¬æŒ‰åç§°æ¨¡ç³Šåœè¿›ç¨‹æœ‰è¯¯æ€é£Žé™© | â€”— | åªæŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ + ç²¾ç¡®å‘½ä»¤è¡Œç‰¹å¾ã€åŒ¹é…ï¼Œ`taskkill /T` ç»“束整树,不按进程名批量杀 |
## äº”、遗留与说明
1. ä¸¤ä¸ªæ¡Œé¢ `.bat` ä½äºŽå·¥ä½œåŒºå¤–(`D:\桌面`),**不入 git**;`stop-dev.ps1` å·²å…¥åº“,与 `start-dev.ps1` é…å¥—。
2. æœåŠ¡ä»ä»¥ `cmd /c ... > log` æ–¹å¼å¸¸é©»ï¼š**关掉启动窗口会带走服务**(本次报错即由此而来)。日常用桌面「启动」入口双击即可恢复。
3. è‹¥ç«¯å£æœªå®Œå…¨é‡Šæ”¾ï¼ˆæžç«¯æƒ…况),停止脚本会提示「仍在监听,请重跑一次」。
## å…­ã€ç»“论
5 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ï¼šå¯åŠ¨è„šæœ¬å¹‚ç­‰è·³è¿‡ã€åœæ­¢è„šæœ¬æŒ‰ PID æ•´æ ‘结束并释放 8090/8080、
启停闭环后页面与接口均正常,且不影响 Codex è‡ªèº«è¿›ç¨‹ã€‚两个编码问题(LF æ¢è¡Œã€ç¼º BOM)已定位并修复复测。
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Öпھ¶ÅÅÃûÖÜתÁ¿¿Ú¾¶Í³Ò»_2026-09-19.md
New file
@@ -0,0 +1,67 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_中口径排名周转量口径统一_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
**问题来源**:用户核对桌面《生成_道路运输量汇总表 (1).xlsx》时,在「中口径排名」页手工加了一列
「人工-周转量」(逐月各分项相加),发现与程序生成的「周转量」列有差异(全省 +0.31978 ä¸‡äººå…¬é‡Œï¼Œ
各市州 Â±0.01~0.08),要求定位原因并修复。
**根因**:同一本汇总大表里两页走了两套取数口径。
- ã€Œä¸­å£å¾„排名」页周转量来自后端 `ReportExportService.loadMidClassMap()` å…¬äº¤ç»´åº¦ï¼š
  **逐企业行**判断——该行「城际城乡周转量」> 0 å°±å–字段值,= 0 æ‰å›žé€€ã€Œæ€»é‡ âˆ’ åŸŽå¸‚内」。
- ã€Œä¸­å£å¾„明细」「道路运输周转量」「中口径分析」等页走台账口径
  ï¼ˆ`smReadLedgerMetrics()`):先按市州按月汇总,再 åˆè®¡æ€»é‡ âˆ’ åˆè®¡åŸŽå¸‚内。
源报表里「总量/城市内/城际城乡」三个数各自保留两位小数,个别企业行上
`城际城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内`(差 Â±0.01)。2026 å¹´ 1-8 æœˆè¿™ç±»è¡Œå…± **72 è¡Œ**,
程序采信字段值、人工用差额法,累加后即出现该差异。
**修改内容**:`traffic-audit-server/.../reportexport/service/ReportExportService.java`
(公交维度,原 2458/2460 è¡Œé™„近)——城际城乡一律用「总量 âˆ’ åŸŽå¸‚内」现算,与台账页/明细页/四页合成口径一致。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å†…容 |
| --- | --- |
| åŽç«¯ | Spring Boot,`localhost:8090`,改后重新编译并重启(`start-dev.ps1`) |
| æ•°æ®åº“ | MySQL `localhost:3308/traffic_audit`(`city_bus_monthly` ç­‰ï¼‰ |
| æŠ¥è¡¨æœŸ | 2026-08(1-8 æœˆç´¯è®¡ + 8 æœˆå•月块) |
| å¯¹ç…§ä»¶ | `D:\桌面\生成_道路运输量汇总表 (1).xlsx`(改前生成 + ç”¨æˆ·äººå·¥åˆ—) |
| ç”Ÿæˆä»¶ | æŽ¥å£ `/api/report/export/summaryWorkbook?period=2026-08` â†’ `_after_busfix_2026-08.xlsx` |
| è¾…助脚本 | `_qa_busfix.py`、`_qa_busfix2.py`、`_qa_busfix3.py`、`_qa_busfix_diff.py`、`_qa_busfix_err.py`、`_qa_busfix_hist.py` |
## ä¸‰ã€ç”¨ä¾‹ä¸Žç»“æžœ
| ç¼–号 | ç±»åž‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T1 | æ­£å‘ | æ”¹åŽç”Ÿæˆä»¶ã€Œä¸­å£å¾„排名」O åˆ— vs ã€Œä¸­å£å¾„明细」S åˆ—,17 å¸‚å·ž | é€æ ¼ç›¸ç­‰ | 17/17 å…¨éƒ¨ç›¸ç­‰ï¼ˆæ­¦æ±‰ 152330.8912、孝感 64429.9445、随州 59015.4820…) | é€šè¿‡ |
| T2 | æ­£å‘ | å…¨çœç´¯è®¡å‘¨è½¬é‡ï¼ˆæŽ’名页 O3) | = æ˜Žç»†/人工 1227147.48902 | 1227147.4888(差 âˆ’0.0002 ä¸‡äººå…¬é‡Œ = 2 äººå…¬é‡Œï¼‰ | é€šè¿‡ï¼ˆå·®å¼‚见「五、遗留」) |
| T3 | æ­£å‘ | æ­¦æ±‰ç´¯è®¡å‘¨è½¬é‡ | = äººå·¥åˆ— 152330.8912 | 152330.8912 | é€šè¿‡ |
| T4 | æ­£å‘ | 8 æœˆå•月块 17 å¸‚州合计 | = æ˜Žç»† 8 æœˆåˆè®¡ | å‡ä¸º 156017.6956 | é€šè¿‡ |
| T5 | æ­£å‘ | ç‹¬ç«‹æŽ¥å£ `passengerMidAnalysis`(城际城乡公交累计周转量) | = å°è´¦å£å¾„ 227126.74 | 227126.74(改前 227127.06) | é€šè¿‡ |
| T6 | æ­£å‘ | ç‹¬ç«‹æŽ¥å£ `passengerMidRank` å…¨çœç´¯è®¡å‘¨è½¬é‡ | æŽ¥è¿‘ 1227147.489 | 1227147.4888 | é€šè¿‡ |
| T7 | å›žå½’ | æ”¹å‰/改后「中口径排名」客运量列(17 å¸‚å·ž + å…¨çœï¼‰ | ä¸å˜ | å®Œå…¨ä¸€è‡´ | é€šè¿‡ |
| T8 | å›žå½’ | ã€Œä¸­å£å¾„分析」页 ç´¯è®¡å‘¨è½¬é‡ï¼ˆå°è´¦å£å¾„) | ä¸å˜ | é€æ ¼ä¸€è‡´ï¼ˆ1227147.48902 / 904146.38902 / 227126.74…) | é€šè¿‡ |
| T9 | å›žå½’ | åŒæ¯”列(全省 âˆ’2.35%、武汉 +4.15% ç­‰ï¼‰ | ä¸å˜ | æ˜¾ç¤ºç²¾åº¦å†…完全一致 | é€šè¿‡ |
| T10 | å›žå½’ | æ•´æœ¬å·¥ä½œç°¿é€æ ¼å¯¹æ¯”改前/改后 | ä»…目标格变化 | é™¤ç›®æ ‡åˆ—外只出现 1e-10 çº§æµ®ç‚¹å™ªå£° | é€šè¿‡ |
| T11 | è¾¹ç•Œ | 2025 å¹´åŸºæœŸï¼ˆåŒæ¯”基数) | ä¸å—影响 | `city_bus_monthly` 2025 å¹´ã€Œå­˜å‚¨åŸŽé™…城乡 â‰  æ€»é‡âˆ’城市内」行数 = 0 | é€šè¿‡ |
| T12 | è¾¹ç•Œ | åŽŸã€Œå­˜å‚¨å€¼ç¼ºå¤±ï¼ˆ<=0)才回退」兜底是否仍需要 | åŽ»æŽ‰åŽæ— å‰¯ä½œç”¨ | 2025/2026 å‡æ— ã€Œæœªå­˜åŸŽé™…但 æ€»é‡âˆ’内>0」的行(0 è¡Œï¼‰ï¼Œå…œåº•从未触发 | é€šè¿‡ |
| T13 | è´Ÿå‘ | æºåº“ 72 è¡Œã€Œå­˜å‚¨åŸŽé™…城乡 â‰  æ€»é‡âˆ’城市内」 | ç»Ÿä¸€æŒ‰å·®é¢æ³• | 17 å¸‚州差值全部归零(改前:武汉 +0.04、孝感 +0.08、随州 âˆ’0.02…,全省 +0.3198) | é€šè¿‡ |
| T14 | è´Ÿå‘ | ã€Œç­çº¿åŒ…车」页 2020 å¹´åŽ†å²åˆ— `#VALUE!` | éžæœ¬æ¬¡å¼•å…¥ | æ”¹å‰åŽ†å²ç”Ÿæˆä»¶åŒä¸º 236/456 æ ¼ï¼›Excel æ‰“开会按 `fullCalcOnLoad` é‡ç®— | é€šè¿‡ï¼ˆæ—¢æœ‰çŽ°è±¡ï¼‰ |
## å››ã€å‘现的问题与处置
1. **口径不一致(本次根因)**:公交维度逐企业行采信「城际城乡」字段,与台账页差额法冲突 â†’ å·²ç»Ÿä¸€ä¸ºå·®é¢æ³•。
2. **全省行残留 0.0002 ä¸‡äººå…¬é‡Œ**:排名页全省行是母版公式 `=SUM(O4:O20)`,各市州先四舍五入到 4 ä½å†æ±‚和,
   ä¸Žã€Œæ˜Žç»†å…¨ç²¾åº¦æ±‚和」天然差 2 äººå…¬é‡Œï¼Œå±žæ¯ç‰ˆå…¬å¼ç»“构性问题,本次未动母版。
3. **历史列 `#VALUE!`**:POI é‡ç®— 2020 å¹´åŒæ¯”列的既有现象,与本次改动无关,Excel æ‰“开即自动重算。
## äº”、结论
- ä¿®å¤åŽã€Œä¸­å£å¾„排名」周转量与人工/台账口径 **17 ä¸ªå¸‚州逐格一致**,差异从 17 é¡¹å½’é›¶ï¼›
- å®¢è¿é‡ã€åŒæ¯”、分析页、四页合成页均无回归;
- 2025 åŒæ¯”基期不受影响;
- æ®‹ç•™ 0.0002 ä¸‡äººå…¬é‡Œï¼ˆ2 äººå…¬é‡Œï¼‰æ¥è‡ªæ¯ç‰ˆå…¨çœè¡Œ SUM å…¬å¼ï¼Œå»ºè®®åŽç»­å•独拍板是否改为全精度写值。
测试人:Codex(AI) 测试日期:2026-09-19
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_ͬÃûÆóÒµ1-8ÔÂÀۼƻõÔËÁ¿ÓëÖÜתÁ¿SQL_2026-09-19.md
New file
@@ -0,0 +1,206 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_同名企业1-8月累计货运量与周转量SQL_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
2025 å¹´ 1-8 æœˆä¸Ž 2026 å¹´ 1-8 æœˆæŠ¥é€çš„企业数量不同(664 å®¶ vs 636 å®¶ï¼‰ï¼Œ
直接相减的差额里混着「企业名单变了」的影响。本功能按**同名企业口径**
(两年 1-8 æœˆéƒ½æŠ¥é€è¿‡çš„企业名称交集,共 **545 å®¶**)分别汇总两年 1-8 æœˆç´¯è®¡çš„
**货运量**与**货物周转量**,保证两年企业范围完全一致,可直接用于同比。
- äº¤ä»˜è„šæœ¬ï¼š`docs/生成汇总大表/同名企业_1-8月累计对比_2026-09-19.sql`(含 6 æ¡æŸ¥è¯¢ï¼‰
- æ•°æ®æºè¡¨ï¼š`traffic_audit.h2032_enterprise_monthly`(交企统H203-2表,企业级月报)
- å…³é”®å­—段:`freight_total` è´§è¿é‡ï¼ˆå¨ï¼‰ã€`turnover_total` è´§ç‰©å‘¨è½¬é‡ï¼ˆå¨å…¬é‡Œï¼‰ã€
  `report_period` æŠ¥è¡¨æœŸï¼ˆ'YYYY-MM')、`enterprise_name` ä¼ä¸šåç§°
- å•位换算:表内为「吨 / å¨å…¬é‡Œã€ï¼Œè¾“出统一 Ã·10000 â†’ ã€Œä¸‡å¨ / ä¸‡å¨å…¬é‡Œã€
- æœŸé—´å–法:1-8 æœˆ = `report_period BETWEEN 'YYYY-01' AND 'YYYY-08'`
- è„šæœ¬å†…å®¹ï¼šæŸ¥è¯¢ 1 æ±‡æ€»è¡Œ / æŸ¥è¯¢ 2 é€ä¼ä¸šå¯¹ç…§ / æŸ¥è¯¢ 3 å£å¾„对照 /
  æŸ¥è¯¢ 4 å·®å¼‚企业名单 / æŸ¥è¯¢ 5 åˆ†å¸‚州汇总 / æŸ¥è¯¢ 6 æ•°æ®ä½“检
## äºŒã€æµ‹è¯•环境
- æ•°æ®åº“:MySQL 8.0.29,`127.0.0.1:3308`,库 `traffic_audit`
- å®¢æˆ·ç«¯ï¼šmysql 5.7.41,参数 `--default-character-set=utf8mb4`
- æ‰§è¡Œæ–¹å¼ï¼šæ•´è„šæœ¬ä¸€æ¬¡æ€§æ‰§è¡Œ `mysql ... < åŒåä¼ä¸š_1-8月累计对比_2026-09-19.sql`
- æ•°æ®è§„模:`report_period` å…± 20 ä¸ªæŠ¥è¡¨æœŸï¼ˆ2025-01 ~ 2026-08),合计 13056 è¡Œï¼›
  å…¶ä¸­ 1-8 æœˆå£å¾„ 10400 è¡Œï¼ˆ2025 å¹´ 5312 è¡Œ / 2026 å¹´ 5088 è¡Œï¼‰
- æµ‹è¯•日期:2026-09-19
## ä¸‰ã€ç”¨ä¾‹è¡¨
| ç¼–号 | ç±»åž‹ | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- | --- |
| T1 | æ­£å‘ | åŒåä¼ä¸šå£å¾„汇总(查询 1) | ä¸¤å¹´ 1-8 æœˆéƒ½æŠ¥é€è¿‡çš„企业 | ä¸€è¡Œå†…出两年累计数 | 545 å®¶ï¼›è´§è¿é‡ 30153.14 / 27752.68 ä¸‡å¨ï¼Œå‘¨è½¬é‡ 4635340.46 / 4389882.05 ä¸‡å¨å…¬é‡Œ | é€šè¿‡ |
| T2 | æ­£å‘ | é€ä¼ä¸šå¯¹ç…§æ˜Žç»†ï¼ˆæŸ¥è¯¢ 2) | åŒä¸Š | æ¯å®¶ä¸€è¡Œã€ä¸¤å¹´å¹¶æŽ’ | 545 è¡Œï¼Œå«ä¸¤å¹´å€¼ã€å¢žå‡é¢ã€åŒæ¯” | é€šè¿‡ |
| T3 | æ­£å‘ | æ˜Žç»†æ±‚å’Œ = æ±‡æ€»è¡Œ | æŸ¥è¯¢ 2 çš„ 545 è¡ŒæŒ‰åˆ—求和 | ä¸ŽæŸ¥è¯¢ 1 å®Œå…¨ä¸€è‡´ | 30153.14 / 4635340.46 / 27752.68 / 4389882.05,差异 0 | é€šè¿‡ |
| T4 | æ­£å‘ | å£å¾„对照(查询 3) | å…¨é‡ vs åŒå | 4 è¡Œå£å¾„可解释差额 | å…¨é‡ 2025:664 å®¶ 33994.45 ä¸‡å¨ / 5102518.95 ä¸‡å¨å…¬é‡Œï¼›å…¨é‡ 2026:636 å®¶ 31399.82 ä¸‡å¨ / 4927161.77 ä¸‡å¨å…¬é‡Œ | é€šè¿‡ |
| T5 | æ­£å‘ | å·®å¼‚企业名单(查询 4) | åªåœ¨ä¸€å¹´æŠ¥é€çš„企业 | å®¶æ•°ä¸Žå·®é¢ç›¸ç¬¦ | 2025 ç‹¬æœ‰ 119 å®¶ã€2026 ç‹¬æœ‰ 91 å®¶ï¼›å®¶æ•°æ ¡éªŒ 664−545=119、636−545=91 | é€šè¿‡ |
| T6 | æ­£å‘ | å·®å¼‚金额闭合 | åŒå + ç‹¬æœ‰ = å…¨é‡ | é‡‘额闭合 | è´§è¿é‡ 30153.14+3841.31=33994.45(=全量 2025);周转量 4635340.46+467178.48=5102518.94(全量 5102518.95,差 0.01 ä¸ºå››èˆäº”入) | é€šè¿‡ |
| T7 | æ­£å‘ | åˆ†å¸‚州汇总(查询 5) | åŒåä¼ä¸šæŒ‰ region_code å½’市州 | å¸‚州合计 = å…¨çœ | 16 ä¸ªå¸‚州(仙桃 0 å®¶åŒåä¼ä¸šï¼‰ï¼Œä¼ä¸šæ•°åˆè®¡ 545,各列合计 = æŸ¥è¯¢ 1 | é€šè¿‡ |
| T8 | æ­£å‘ | å…¥åº“抽查:逐月相加对齐 | æ­¦æ±‰é’¢é“é›†å›¢ç‰©æµæœ‰é™å…¬å¸ 2025-01~08 å…± 8 æ¡åŽŸå§‹è®°å½• | é€æœˆç›¸åŠ  = æ˜Žç»†è¡Œ | è´§è¿é‡ 7381512 å¨ â†’ 738.15 ä¸‡å¨ï¼›å‘¨è½¬é‡ 231191873 å¨å…¬é‡Œ â†’ 23119.19 ä¸‡å¨å…¬é‡Œï¼Œä¸ŽæŸ¥è¯¢ 2 è¾“出一致 | é€šè¿‡ |
| T9 | è´Ÿå‘ | ä¼ä¸šåä¸å­˜åœ¨ | `enterprise_name='不存在的企业XYZ'` | 0 è¡Œã€ä¸æŠ¥é”™ | 0 è¡Œ | é€šè¿‡ |
| T10 | è´Ÿå‘ | å¹´ä»½å†™é”™ | æœŸé—´ `'2024-01' ~ '2024-08'` | 0 è¡Œ | 0 è¡Œ | é€šè¿‡ |
| T11 | è¾¹ç•Œ | åŒä¸€ä¼ä¸šåŒæœˆé‡å¤è®°å½• | `GROUP BY enterprise_name, report_period HAVING COUNT(*)>1` | æ— é‡å¤ï¼ˆå¦åˆ™ç´¯è®¡ä¼šè¢«æ”¾å¤§ï¼‰ | 0 æ¡ | é€šè¿‡ |
| T12 | è¾¹ç•Œ | åŒåä¼ä¸šæœˆä»½ä¸å…¨ï¼ˆæŸ¥è¯¢ 6) | è®°å½•æ•° <> 8 çš„同名企业 | æ— å¼‚常 | ç©ºç»“果集,545 å®¶ä¸¤å¹´å„ 8 ä¸ªæœˆé½å…¨ | é€šè¿‡ |
## å››ã€å‘现的问题与处置
1. **企业名称作为匹配键的固有风险(已提示,未改口径)**
   åŒåå£å¾„按 `enterprise_name` å­—符串相等匹配,若企业改名、或不同地市出现完全同名的企业,
   ä¼šè¢«åˆ¤ä¸ºã€Œä¸åŒä¼ä¸šã€æˆ–「同一企业」。实测两年数据中同一报表期内无重名记录(T11),
   ä½†è·¨å¹´æ”¹åæ— æ³•通过本脚本识别;如需更严谨可改用 `unified_credit_code`(统一社会信用代码)匹配。
2. **同名口径与全量口径的差额已可解释**
   2026 å¹´å…¨é‡æ¯”同名口径多 3647.14 ä¸‡å¨ã€å°‘ 537279.73 ä¸‡å¨å…¬é‡Œï¼ˆæ–°è¿› 91 å®¶ä¼ä¸šï¼‰ï¼Œ
   2025 å¹´å…¨é‡æ¯”同名口径多 3841.31 ä¸‡å¨ã€467178.48 ä¸‡å¨å…¬é‡Œï¼ˆé€€å‡º 119 å®¶ï¼‰ã€‚
   å¯¹å¤–说明同比时需注明采用的口径,避免与全量口径数字对不上。
3. **汇总行的同比小数位**
   å‘¨è½¬é‡åŒæ¯”精确值 âˆ’5.2954%,`ROUND(...,2)` è¾“出 âˆ’5.30(显示为 âˆ’5.3),
   è„šæœ¬è¡¨å¤´æ³¨é‡Šå·²åŒæ­¥ä¿®æ­£ä¸º âˆ’5.30%,避免与展示值不一致。
4. **`region_code` å– 2026 å¹´è®°å½•**
   åˆ†å¸‚州查询用 `MAX(CASE WHEN report_period >= '2026-01' ...)` å– 2026 å¹´çš„地区代码,
   ä¼ä¸šè·¨å¸‚迁移时按 2026 å¹´å½’属统计,实测未发现影响(同名企业两地并存的情况无)。
## äº”、补充:企业明细导出(2026-09-19 è¿½åŠ ï¼‰
用户要求把企业明细也导出来,脚本追加两条查询:
- **查询 7 ä¼ä¸šæ˜Žç»†å¯¼å‡º**:匹配键改用 `unified_credit_code`(统一社会信用代码),共 **546 å®¶**,
  æ¯”查询 2 å¤šè¦†ç›– 1 å®¶æ”¹åä¼ä¸šï¼ˆ`91420112558443820B`:2025-01~2025-09 å«
  ã€Œæ¹–北三峡富烨绿电供应链有限公司」,2025-10 èµ·å«ã€Œæ¹–北长峡富烨绿电供应链有限公司」)。
  è¾“出 14 åˆ—:统一社会信用代码、企业名称(2026 å¹´åç§°ï¼‰ã€åç§°2025、是否改名、市州、地区代码、
  è´§è¿é‡ä¸¤å¹´å€¼/增减/同比、周转量两年值/增减/同比,按 2026 å¹´è´§è¿é‡é™åºã€‚
- **查询 8 åˆè®¡å¯¹æ€»æ•°**:546 å®¶å£å¾„ 2025 å¹´ 1-8 æœˆè´§è¿é‡ 30162.99 ä¸‡å¨ / å‘¨è½¬é‡ 4637038.58 ä¸‡å¨å…¬é‡Œï¼›
  2026 å¹´ 1-8 æœˆè´§è¿é‡ 27764.88 ä¸‡å¨ / å‘¨è½¬é‡ 4392984.81 ä¸‡å¨å…¬é‡Œã€‚
- è„šæœ¬å†…é™„ä¸‰ç§å¯¼å‡ºæ–¹å¼ï¼šå‘½ä»¤è¡Œ `--batch --raw` å¯¼ tsv、Navicat/Workbench å¯¼ xlsx、`SELECT ... INTO OUTFILE`。
补充测试:
| ç¼–号 | ç±»åž‹ | ç”¨ä¾‹ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T13 | æ­£å‘ | æŸ¥è¯¢ 7 æ˜Žç»†è¡Œæ•° | 546 è¡Œ | 546 è¡Œï¼Œå…¶ä¸­ 1 è¡Œ `是否改名='是'` | é€šè¿‡ |
| T14 | æ­£å‘ | æŸ¥è¯¢ 7 æ˜Žç»†æ±‚å’Œ = æŸ¥è¯¢ 8 åˆè®¡ | ä¸€è‡´ï¼ˆå…è®¸å››èˆäº”入尾差) | æ˜Žç»†é€è¡Œå››èˆäº”入后求和 30163.10 / 27764.86 / 4637038.56 / 4392984.78,与合计差 0.01~0.02,属正常尾差 | é€šè¿‡ |
| T15 | æ­£å‘ | å‘½ä»¤è¡Œå¯¼å‡ºï¼ˆæ–¹å¼ä¸€ï¼‰ | ç”Ÿæˆ UTF-8 çš„ tsv,含 546 è¡Œæ•°æ® | 89046 å­—节、546 è¡Œæ•°æ®ã€ä¸­æ–‡åˆ—名与企业名正常 | é€šè¿‡ |
| T16 | è¾¹ç•Œ | Excel ç›´æŽ¥åŒå‡» tsv | å­˜åœ¨ä¸­æ–‡ä¹±ç é£Žé™© | æ–‡ä»¶ä¸º UTF-8 æ—  BOM,已在脚本内注明改用「数据 â†’ ä»Žæ–‡æœ¬/CSV」导入或直接导 xlsx | é€šè¿‡ |
| T17 | è¾¹ç•Œ | æ˜Žç»†ä¸­åŒæ¯”除零 | åŸºæœŸä¸º 0 æ—¶ä¸æŠ¥é”™ | `NULLIF(...,0)` ä¿æŠ¤ï¼Œè¿”回空值 | é€šè¿‡ |
## å…­ã€è¡¥å……:明细小数位缺陷修复(2026-09-19 è¿½åŠ ï¼‰
**问题**:脚本原先在明细类查询(查询 2、查询 7)里把「万吨 / ä¸‡å¨å…¬é‡Œã€åˆ—写成 `ROUND(..., 2)`。
保留 2 ä½å°æ•° = ç²¾åº¦åªåˆ° 100 å¨ã€‚用户按这两列在 Excel é‡Œç®—「平均运距 = å‘¨è½¬é‡ Ã· è´§è¿é‡ã€æ—¶ï¼Œ
货运量小的企业分母被砍小,运距被明显放大。
**实例**(2026 å¹´ 1-8 æœˆï¼Œæ¹–北弘雷物流有限公司,源数据 4631 å¨ / 5867730 å¨å…¬é‡Œï¼‰ï¼š
| è´§è¿é‡ï¼ˆä¸‡å¨ï¼‰ | ç®—得的平均运距 | ç»“论 |
| --- | --- | --- |
| 0.4631(不取整) | 1267.05 å…¬é‡Œ | æ­£ç¡®ï¼ˆä¸Žæ•°æ®åº“全精度一致) |
| 0.46(取 2 ä½ï¼‰ | 1275.59 å…¬é‡Œ | è™šé«˜ 8.53 å…¬é‡Œ |
**处置**:
- æŸ¥è¯¢ 2、查询 7 çš„ 6 ä¸ªè´§è¿é‡/周转量列(两年值 + å¢žå‡é¢ï¼‰æ”¹ä¸º `ROUND(..., 4)`;
- æ±‡æ€»å±•示类(查询 1、3、5、8)保留 2 ä½å°æ•°ï¼Œå¤Ÿç”¨ä¸”美观;
- è„šæœ¬é¡¶éƒ¨æ–°å¢žã€Œâ˜… å°æ•°ä½çº¦å®šã€è¯´æ˜Žæ®µï¼Œå†™æ˜Ž"要参与二次计算的列不能只留 2 ä½",并附上述实例。
**回归验证**:
| ç¼–号 | ç”¨ä¾‹ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- |
| T18 | æ•´è„šæœ¬é‡è·‘ | æ— æŠ¥é”™ã€è¡Œæ•°ä¸å˜ | 1352 è¡Œè¾“出、无 ERROR | é€šè¿‡ |
| T19 | æŸ¥è¯¢ 7 æ˜Žç»†åˆ—精度 | è´§è¿é‡/周转量 4 ä½å°æ•° | æ¹–北弘雷 2026 å¹´è´§è¿é‡ 0.4631(原 0.46)、周转量 586.773 | é€šè¿‡ |
| T20 | ç”¨æ˜Žç»†åˆ—复算运距 | ä¸Žæ•°æ®åº“全精度一致 | 586.773 Ã· 0.4631 = 1267.05 å…¬é‡Œï¼Œä¸Žåº“内 1267.0546 ä¸€è‡´ | é€šè¿‡ |
| T21 | æ±‡æ€»åˆ—未被改动 | æŸ¥è¯¢ 1/3/5/8 ä»ä¸º 2 ä½ | æŸ¥è¯¢ 8 ä»è¾“出 546 / 30162.99 / 27764.88 / 4637038.58 / 4392984.81 | é€šè¿‡ |
## ä¸ƒã€è¡¥å……:明细类查询改为「完全不套 ROUND」(2026-09-19 è¿½åŠ ï¼‰
用户确认按「全精度」导出,明细类查询(查询 2、查询 7)的 ROUND å…¨éƒ¨åŽ»æŽ‰ï¼Œå¯¼å‡ºå³åŽŸå§‹å€¼ã€‚
**改动**:
- æŸ¥è¯¢ 2、查询 7 çš„æ‰€æœ‰æ•°å€¼åˆ—(货运量/周转量的两年值、增减额、同比百分比)一律不套 `ROUND`;
- æ±‡æ€»å±•示类(查询 1、3、5、8)仍保留 2 ä½å°æ•°ï¼Œç»™äººçœ‹çš„ï¼›
- é¡¶éƒ¨ã€Œâ˜… å°æ•°ä½çº¦å®šã€åŒæ­¥æ›´æ–°ä¸º"明细不套 ROUND"。
**精度说明(实测)**:货运量、周转量的原始值是整吨 Ã· 10000,小数位**最多 4 ä½**,
取 4 ä½å³ç­‰äºŽå…¨ç²¾åº¦ï¼›å®žæµ‹ 2026 å¹´ 1-8 æœˆçš„ 636 å®¶ä¼ä¸šä¸­ï¼Œ"4 ä½å°æ•°ä»¥å¤–还有尾数"的为 **0 å®¶**。
同比百分比是除出来的,小数位会较长(如 âˆ’2.5389920113927933),介意可在外面再套 `ROUND(...,2)`。
**回归验证**:
| ç¼–号 | ç”¨ä¾‹ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- |
| T22 | æ•´è„šæœ¬é‡è·‘ | æ— æŠ¥é”™ã€è¡Œæ•°ä¸å˜ | 1352 è¡Œè¾“出、无 ERROR | é€šè¿‡ |
| T23 | æŸ¥è¯¢ 7 å¯¼å‡ºä¸å« ROUND | è¾“出原始值 | æ­¦é’¢ç‰©æµ 738.1512 / 719.4096;湖北弘雷 0.6863 / 0.4631;周转量 889.1465 / 586.773 | é€šè¿‡ |
| T24 | å¯¼å‡ºç»“果仍为 546 è¡Œ | 546 è¡Œ | 546 è¡Œæ•°æ®ï¼ˆtsv 546 è¡Œ + è¡¨å¤´ï¼‰ | é€šè¿‡ |
| T25 | ç”¨å¯¼å‡ºå€¼å¤ç®—运距 | ä¸Žåº“一致 | 586.773 Ã· 0.4631 = 1267.05 å…¬é‡Œï¼Œä¸Žåº“内 1267.0546 ä¸€è‡´ | é€šè¿‡ |
## å…«ã€è¡¥å……:查询 2 ä¸ŽæŸ¥è¯¢ 7 çš„等价性验证(2026-09-19 è¿½åŠ ï¼‰
用户提问:"如果没有改名那家,查询 2 å’ŒæŸ¥è¯¢ 7 èƒ½å®Œå…¨å¯¹ä¸Šå—?"——实测答案:**逐比特完全相等**。
**验证方法**:把改名企业 `91420112558443820B` ä»ŽæŸ¥è¯¢ 7 çš„结果中剔除,与查询 2 çš„结果逐行逐列比对。
| æ¯”对项 | ç»“æžœ |
| --- | --- |
| æ•°æ®è¡Œæ•° | æŸ¥è¯¢ 2 = 545 è¡Œï¼›æŸ¥è¯¢ 7 å‰”除那家 = 545 è¡Œ |
| ä¼ä¸šåå• | å®Œå…¨ä¸€è‡´ï¼ˆåŒå‘差集均为空) |
| è´§è¿é‡ 2025 / 2026 / å¢žå‡ / åŒæ¯” | ä¸ä¸€è‡´ 0 å®¶ï¼Œæœ€å¤§å·® 0 |
| å‘¨è½¬é‡ 2025 / 2026 / å¢žå‡ / åŒæ¯” | ä¸ä¸€è‡´ 0 å®¶ï¼Œæœ€å¤§å·® 0 |
| åœ°åŒºä»£ç  | ä¸ä¸€è‡´ 0 å®¶ |
**原因(两条)**:
1. **匹配键一一对应**:除改名那家外,一个信用代码只对应一个企业名称、一个名称只对应一个信用代码
   ï¼ˆå‰æ–‡å·²éªŒè¯ï¼šåŒä¸€ä»£ç å¤šåç§° = 1 ä¾‹ï¼ˆå³æ”¹åé‚£å®¶ï¼‰ã€åŒä¸€åç§°å¤šä»£ç  = 0 ä¾‹ã€åŒæœˆé‡å¤è®°å½• = 0 æ¡ï¼‰ã€‚
   æ•…按名称分组与按信用代码分组,得到的是同一批 545 å®¶ã€åŒæ ·çš„行。
2. **算术精确**:两个查询都是"整吨求和 â†’ é™¤ä»¥ 10000"。吨数为整数且远小于 2⁵³,
   double å¯¹æ•´æ•°æ±‚和是精确的,故两侧完全一致(连浮点尾差都没有)。
**补充用例**:
| ç¼–号 | ç±»åž‹ | ç”¨ä¾‹ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T26 | æ­£å‘ | æŸ¥è¯¢ 2 ä¸ŽæŸ¥è¯¢ 7 ç­‰ä»·æ€§ | å‰”除改名企业后两者完全一致 | 545 è¡Œä¼ä¸šåå•一致;8 ä¸ªæ•°å€¼åˆ— + åœ°åŒºä»£ç å…¨éƒ¨ 0 å®¶ä¸ä¸€è‡´ã€æœ€å¤§å·® 0 | é€šè¿‡ |
**实践含义**:查询 7 = æŸ¥è¯¢ 2 + æ”¹åä¼ä¸šï¼ˆä¿¡ç”¨ä»£ç å£å¾„是名称口径的超集),两者共同部分数值完全相同。
要跟 545 å®¶äº¤ä»˜ä»¶å¯¹è´¦ç”¨æŸ¥è¯¢ 2;要防将来再出现改名企业,用查询 7 æ›´ç¨³ã€‚
## ä¹ã€è¡¥å……:汇总类查询同步改为 4 ä½å°æ•°ï¼ˆ2026-09-19 è¿½åŠ ï¼‰
**背景**:确认「4 ä½å°æ•°ã€å¯¹å“ªäº›åˆ—等于全精度后,决定把汇总类查询也统一为 4 ä½ã€‚
**先厘清"4 ä½ = å…¨ç²¾åº¦"的适用范围**(实测 754 ä¸ªä¼ä¸š/信用代码):
| åˆ— | `ROUND(v,4) <> v` çš„å®¶æ•° | ç»“论 |
| --- | --- | --- |
| è´§è¿é‡ 2025 / 2026 | **0 å®¶** | 4 ä½å³å…¨ç²¾åº¦ï¼ˆæ•´å¨ Ã· 10000,最多 4 ä½å°æ•°ï¼‰ |
| å‘¨è½¬é‡ 2025 / 2026 | **0 å®¶** | åŒä¸Š |
| å¹³å‡è¿è· | 628 / 631 å®¶ | **不等于**全精度,是除出来的商,需单独定位数 |
| åŒæ¯”百分比 | 541 / 754 å®¶ | **不等于**全精度,同上 |
**处置**:
- æ˜Žç»†ç±»ï¼ˆæŸ¥è¯¢ 2、7)已不套 ROUND = å…¨ç²¾åº¦ï¼Œæ— éœ€æ”¹åŠ¨ï¼›
- æ±‡æ€»ç±»ï¼ˆæŸ¥è¯¢ 1、3、5、8)的 14 å¤„ `/ 10000, 2)` å…¨éƒ¨æ”¹ä¸º 4 ä½ï¼›
- é¡¶éƒ¨ã€Œâ˜… å°æ•°ä½çº¦å®šã€åŒæ­¥æ›´æ–°ä¸º"汇总类同样保留 4 ä½";
- é¡¶éƒ¨ä¸ŽæŸ¥è¯¢ 8 æ³¨é‡Šé‡Œçš„实测值一并更新为 4 ä½ã€‚
**回归验证**:
| ç¼–号 | ç±»åž‹ | ç”¨ä¾‹ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T27 | æ­£å‘ | æ•´è„šæœ¬é‡è·‘ | æ— æŠ¥é”™ã€è¡Œæ•°ä¸å˜ | 1352 è¡Œè¾“出,无 ERROR | é€šè¿‡ |
| T28 | æ­£å‘ | æŸ¥è¯¢ 1 æ±‡æ€»ï¼ˆ545 å®¶ï¼‰ | 4 ä½å°æ•° | 30153.1392 / 27752.6820 / 4635340.4627 / 4389882.0468 | é€šè¿‡ |
| T29 | æ­£å‘ | æŸ¥è¯¢ 8 åˆè®¡ï¼ˆ546 å®¶ï¼‰ | 4 ä½å°æ•° | 30162.9872 / 27764.8812 / 4637038.5803 / 4392984.8116 | é€šè¿‡ |
| T30 | æ­£å‘ | æŸ¥è¯¢ 5 åˆ†å¸‚州与交付件对齐 | ä¸Žäº¤ä»˜ä»¶å¸‚州汇总一致 | æ­¦æ±‰ 9405.2643 / 1501661.4035、宜昌 5247.5232 / 449997.1831,与交付件完全一致 | é€šè¿‡ |
**副作用为零**:对货运量/周转量而言 4 ä½å°±æ˜¯å…¨ç²¾åº¦ï¼Œå› æ­¤è¿™æ¬¡æ”¹åŠ¨æ²¡æœ‰ä¸¢å¤±ä»»ä½•æ•°æ®ï¼›
但脚本输出现在与 545 å®¶äº¤ä»˜ä»¶çš„市州汇总**逐列对齐**,两个口径之间可以互相验证。
## åã€ç»“论
8 æ¡æŸ¥è¯¢æ•´è„šæœ¬æ‰§è¡Œé€šè¿‡ï¼Œ30 æ¡ç”¨ä¾‹ï¼ˆ21 æ­£å‘ / 2 è´Ÿå‘ / 7 è¾¹ç•Œï¼‰å…¨éƒ¨é€šè¿‡ã€‚
**同名企业口径(545 å®¶ï¼‰1-8 æœˆç´¯è®¡ç»“果:**
| æŒ‡æ ‡ | 2025 å¹´ 1-8 æœˆ | 2026 å¹´ 1-8 æœˆ | åŒæ¯” |
| --- | --- | --- | --- |
| è´§è¿é‡ï¼ˆä¸‡å¨ï¼‰ | 30153.14 | 27752.68 | âˆ’7.96% |
| è´§ç‰©å‘¨è½¬é‡ï¼ˆä¸‡å¨å…¬é‡Œï¼‰ | 4635340.46 | 4389882.05 | âˆ’5.30% |
其中 2026 å¹´ç´¯è®¡æ•°ä¸Ž 2026-09-19《持续在规企业 545 å®¶ç´¯è®¡è¿è·ã€‹äº¤ä»˜ä»¶çš„全省行
(27752.6820 ä¸‡å¨ / 4389882.0468 ä¸‡å¨å…¬é‡Œï¼‰å®Œå…¨ä¸€è‡´ï¼Œä¸¤æ¡é“¾è·¯å£å¾„互证通过。
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Ͷ×ÊÃ÷ϸ±íÓëµ¼ÈëÈ¡Áж¨Î»ÐÞ¸´_2026-09-19.md
New file
@@ -0,0 +1,86 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_投资明细表与导入取列定位修复_2026-09-19
> æœ¬æ–‡è¦†ç›– 2026-09-18 å¤œé—´ï½ž2026-09-19 å‡Œæ™¨çš„ 6 é¡¹æ”¹åŠ¨ï¼ˆä¸­å£å¾„æŽ’ååŒæ¯”ã€ç½‘çº¦è½¦åˆ†æ‘Šå›žè½ã€ä¸¤å¼ æŠ•èµ„æ˜Žç»†è¡¨ã€å¯¼å…¥ç•Œé¢éšè—ç½‘çº¦è½¦è®¢å•ã€æŠ•èµ„å¸‚å·žå•è¡¨å–åˆ—å®šä½ä¿®å¤ã€8 æœˆæŠ•资源数据补齐)。
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
1. **中口径排名/明细同比口径修复(B1/B3/B5)**:原实现用「去年该月值是否为 0」判断数据是否存在,导致
   - æ­¦æ±‰å·¡æ¸¸å‡ºç§ŸåŸŽé™…/城乡业务上年恒为 0 â†’ åŒæ¯”被误判为「无基期」;
   - åŽ»å¹´ç¼ºæœˆæ—¶è¢«å½“ä½œ 0 å‚与计算 â†’ åŒæ¯”虚高(公交行一度出现 âˆ’28577%)。
   çŽ°æ”¹ä¸º **按「源表是否有该行」登记存在性**(`markMid`/`midMonthHas`/`midCumHitMonths`),
   åŽ»å¹´ç¼ºä»»ä¸€æœˆåˆ™åŒæ¯”ç•™ç©ºï¼›åŒæ—¶ `loadMidClassMap()` ç”¨ `passengerVolume - passengerCity` å…œåº•跨县公交口径,
   è§£æžå¼‚常改为记入 `midIssues` å¹¶ `log.warn`(不再静默 `continue`)。
2. **网约车 2025 åˆ†æ‘Šå›žè½ï¼ˆB2)**:`WycSplitCalc.loadMonthlyInputFromDb()` åœ¨æŸæœˆ pin ç¼ºå¤±æˆ– â‰¤0 æ—¶å›žè½ `wyc_total_monthly`,`source` æ ‡ `db+wyc_total`。
3. **新增两张投资明细表导出**:`/export/investPassengerDetail`、`/export/investLogisticsDetail`。
   å£å¾„(用户 2026-09-18 ç¡®è®¤ï¼‰ï¼šåªè¦†ç›– **H è‡ªå¼€å§‹å»ºè®¾ç´¯è®¡ / J è‡ªå¹´åˆç´¯è®¡ / K æœ¬æœˆå®Œæˆ / M å½¢è±¡è¿›åº¦**;
   I æœ¬å¹´è®¡åˆ’投资、L å»ºè®¾é˜¶æ®µã€G è®¡åˆ’总投资不动母版;库内为空保留母版原值。
   ç‰©æµè¡¨é¢å¤–按表内数值重算渠道行/市州行/合计行,并刷新「分市州规划内外项目完成情况」「市州汇总」(渠道小计保留程序算出的数)。
4. **导入界面隐藏「网约车订单及全省总量」**:`DataImport.vue` è¯¥ç±»åž‹ç½® `hidden: true`,入口/概览/清空三处下拉统一走 `typeList()` è¿‡æ»¤ã€‚
5. **投资市州单表「表头取列定位」修复**(本轮核心,`DataImportService.findInvestHeader`):
   - è¡¨å¤´æ–‡æœ¬æ‰«æä¸Šç•Œç”±**固定 `表头行+3`** æ”¹ä¸º**「表头块」**:上界 = é¦–个真实数据行 âˆ’ 1(硬上限 +12 è¡Œï¼‰ï¼›
   - æ–°å¢žã€Œå»ºè®¾è¿›å±•」关键词映射到形象进度列;
   - æ–°å¢ž `desc = stage + 1` å…œåº•(省标「项目建设阶段、进度情况」为 L/M åˆå¹¶è¡¨å¤´ï¼Œéƒ¨åˆ†å¸‚州只写 L æ ‡é¢˜ï¼‰ï¼›
   - `合计/总计/小计` åˆ¤å®šæ”¹ä¸º**去空白后**匹配(原 `nt.contains("合计")` æ¼æŽ‰ã€Œåˆã€€ã€€ã€€è®¡ã€ï¼‰ã€‚
6. **补齐 2026-08 æŠ•资源数据**:`docs\投资\输入\客运(客运站)\8月`(9 ä¸ªæ–‡ä»¶ï¼‰ã€`物流(物流园区)\8月`(16 ä¸ªæ–‡ä»¶ï¼‰ï¼Œå¹¶é‡æ–°å¯¼å…¥ã€‚
## äºŒã€æµ‹è¯•环境
| é¡¹ | å€¼ |
| --- | --- |
| æ—¥æœŸ | 2026-09-19(00:0x–01:0x) |
| åŽç«¯ | Spring Boot 8090(重启加载新代码,`Started TrafficAuditApplication`) |
| å‰ç«¯ | Vue 8080(`App running at`) |
| æ•°æ®åº“ | MySQL 127.0.0.1:3308 `traffic_audit` |
| æºæ•°æ® | `D:\桌面\测试数据\投资\八月源数据\{客运,物流}` â†’ å¤åˆ¶åˆ° `docs\投资\输入\...\8月` |
| å¯¹ç…§å®šç¨¿ | `D:\桌面\测试数据\投资\8月客运站投资明细表.xlsx`、`8月物流站场投资明细.xls` |
| æŠ¥è¡¨æœŸ | 2026-08(mode=month) |
| å…¥å£ | `POST /api/import/investCityBatch?period=2026-08&category=客运站场\|物流园区` |
## ä¸‰ã€ç”¨ä¾‹è¡¨
| ç¼–号 | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| T01 | å’¸å®å®¢è¿ã€Œå½¢è±¡è¿›åº¦ã€å–列(正向) | `2026å¹´8月咸宁市客运站场投资统计月报表(1)省表.xls`(L/M æ ‡é¢˜åœ¨ç¬¬ 8 è¡Œï¼Œè¡¨å¤´åœ¨ç¬¬ 4 è¡Œï¼‰ | M åˆ—(形象进度)应被定位 | åº“内 `progress_desc` éžç©º **0 â†’ 7/9 è¡Œ**(另 2 è¡Œæºæ–‡ä»¶æœ¬èº«ä¸ºç©ºï¼‰ | âœ… é€šè¿‡ |
| T02 | å®œæ˜Œå®¢è¿ã€Œå»ºè®¾é˜¶æ®µ/形象进度」取列(正向) | `湖北省宜昌市道路客运站场投资报表(月、年报)08月.xls`(L/M æ ‡é¢˜åœ¨ç¬¬ 5 è¡Œï¼Œé¦–行数据在第 7 è¡Œï¼‰ | L=建设阶段、M=形象进度;不得被判成「竣工时间」列 | ä¿®å¤å‰ stage 0 / desc 0 â†’ ä¿®å¤åŽ **5/5 ä¸Ž 5/5**(旧实现把首行数据的「竣工收尾/建成投运」当表头文本,命中「竣工/建成」分支) | âœ… é€šè¿‡ |
| T03 | ç‰©æµåˆå¹¶è¡¨å¤´ã€Œå½¢è±¡è¿›åº¦ã€å…œåº•(正向) | å­æ„Ÿ / æ©æ–½ / éšå·žç‰©æµæ˜Žç»†è¡¨ï¼ˆåªåœ¨ L å†™ã€Œé¡¹ç›®å»ºè®¾é˜¶æ®µã€è¿›åº¦æƒ…况」,M ç›´æŽ¥å†™è¿›åº¦æ–‡å­—) | åº”识别 M åˆ—为形象进度 | desc éžç©º **0 â†’ å­æ„Ÿ 7/7、恩施 4/6、随州 2/2**(恩施另 2 è¡Œä¸ºã€Œå»ºæˆã€ã€æºæ–‡ä»¶ M æœ¬èº«ä¸ºç©ºï¼‰ | âœ… é€šè¿‡ |
| T04 | å·²æ­£ç¡®å¸‚州回归 | åå °/恩施/襄阳/荆门/武汉/林区客运 + é»„冈/咸宁/荆州/荆门/宜昌/襄阳/黄石物流等 | å–列与数值不变 | é€é¡¹ä¸€è‡´ï¼šåå °å®¢è¿ 4/4、恩施客运 6/6、襄阳客运 6/6、咸宁物流 9/9、荆州物流 9/9、荆门物流 8/8、宜昌物流 13/13 | âœ… é€šè¿‡ |
| T05 | åˆè®¡è¡Œä¸å¾—入库(负向) | å’¸å®å®¢è¿æºæ–‡ä»¶å«ã€Œåˆã€€ã€€ã€€è®¡ã€è¡Œï¼ˆå¤šä¸ªç©ºæ ¼ï¼‰ | åˆè®¡è¡Œè¢«è·³è¿‡ | ä¿®å¤å‰å…¥ 40 è¡Œï¼ˆå« 1 æ¡åä¸ºã€Œåˆã€€ã€€ã€€è®¡ã€çš„假项目)→ ä¿®å¤åŽ **39 è¡Œ**,假项目已消除 | âœ… é€šè¿‡ |
| T06 | å…¥åº“数值抽查(与源文件逐项对齐) | å­æ„Ÿç‰©æµ 7 è¡Œ / æ©æ–½ç‰©æµ 6 è¡Œ | é¡¹ç›®è¡Œæ±‚å’Œ = æºæ–‡ä»¶å¸‚州小计行 | å­æ„Ÿ H/J/K = **160378 / 116414 / 13784**、恩施 = **126741 / 41574 / 2116**,与源文件「 åˆ†é¡¹ç›®æŠ•资完成情况」市州行逐项一致 | âœ… é€šè¿‡ |
| T07 | å®¢è¿ç«™æŠ•资明细表回归 | å¯¼å‡º vs `8月客运站投资明细表.xlsx` | ä¸Žä¿®å¤å‰ä¸åŠ£åŒ– | **汇总页 0 å·®å¼‚**;明细页 6 å¤„(修复前 5 å¤„,新增的 1 å¤„为咸宁 M85,程序按源文件写入而定稿留空,属「更完整」) | âœ… é€šè¿‡ |
| T08 | ç‰©æµç«™åœºæŠ•资明细表回归 | å¯¼å‡º vs `8月物流站场投资明细.xls` | ä¸Žä¿®å¤å‰ä¸åŠ£åŒ– | ä¸‰é¡µæ•°å€¼ä¸Žä¿®å¤å‰ä¸€è‡´ï¼Œä»…新增孝感/恩施/随州形象进度;差异仍集中在武汉/十堰/荆州/天门 4 å¸‚州(见「遗留」) | âœ… é€šè¿‡ |
| T09 | ä¸­å£å¾„排名同比 | `passengerMidRank`(2026-08) | ä¸Žå®šç¨¿ä¸€è‡´ | å…¨çœ **5.81%**、武汉 **4.65%**、仙桃 17.23%、林区 âˆ’34.87%,与定稿一致;黄石 7.76、十堰 2.52、宜昌 âˆ’16.17、襄阳 5.67、荆州 36.62、黄冈 7.74、咸宁 17.06、恩施 13.92、潜江 âˆ’2.84、天门 9.01(与定稿差 0.02~0.5 ä¸ªç™¾åˆ†ç‚¹ï¼‰ | âœ… é€šè¿‡ |
| T10 | ä¸­å£å¾„明细同比 | `passengerMidDetail`(2026-08) | ä¸å†å‡ºçŽ°æ•°é‡çº§é”™è¯¯ | å…¬äº¤è¡Œç´¯è®¡åŒæ¯” **−28577% â†’ +13.15%**、出租 +8.54%、网约车 +75.66% | âœ… é€šè¿‡ |
| T11 | å¯¼å…¥ç•Œé¢éšè—ç½‘约车订单 | `DataImport.vue` | å…¥å£/概览/清空三处均不可见 | `wycOrder` ç½® `hidden: true`,三处 `v-for` ç»Ÿä¸€æ”¹ç”¨ `typeList(g)` | âœ… é€šè¿‡ |
| T12 | æŠ¥è¡¨ç”Ÿæˆæ–°å¢žä¸¤å¼ æŠ•资明细表 | `ReportExport.vue` | æŠ•资报表组可导出并正确命名 | æ–°å¢žä¸¤é¡¹ï¼Œ`fileNameOf()` æŠŠã€ŒX月」替换为报表期月份(→`生成_8月客运站投资明细表.xlsx`、`生成_8月物流站场投资明细.xls`) | âœ… é€šè¿‡ |
| T13 | å¹‚ç­‰/确定性 | åŒä¸€æ‰¹æºæ–‡ä»¶è¿žç»­å¯¼å…¥ä¸¤æ¬¡ | è¡Œæ•°ä¸Žæ•°å€¼ä¸€è‡´ | å®¢è¿ 39 è¡Œã€ç‰©æµ 128 è¡Œï¼›ä¸¤æ¬¡ç»“果完全一致 | âœ… é€šè¿‡ |
| T14 | ç¼–译回归 | `mvn -q -DskipTests compile` | ç¼–译通过 | exit=0 | âœ… é€šè¿‡ |
## å››ã€å‘现的问题与处置
| ç¼–号 | é—®é¢˜ | æ ¹å›  | å¤„ç½® |
| --- | --- | --- | --- |
| P01 | å®œæ˜Œå®¢è¿ã€Œå»ºè®¾é˜¶æ®µ/形象进度」全空 | è¡¨å¤´æ‰«æçª—口固定 `表头行+3`,把**首行数据**纳入列名文本,数据里的「竣工收尾/建成投运」先命中「竣工/建成」分支 | æ‰«æä¸Šç•Œæ”¹ä¸ºã€Œè¡¨å¤´å—」= é¦–个真实数据行 âˆ’ 1,数据行不再参与列名匹配 |
| P02 | å’¸å®å®¢è¿ã€Œå½¢è±¡è¿›åº¦ã€å…¨ç©º | L/M æ ‡é¢˜å†™åœ¨è¡¨å¤´ä¸‹ç¬¬ 4 è¡Œï¼Œè¶…出 `+3` çª—口 | åŒä¸Šï¼ˆä¸Šç•Œæ‰©å±•到硬上限 +12 è¡Œä¸”不越过数据行) |
| P03 | ç‰©æµå­æ„Ÿ/恩施/随州「形象进度」全空 | çœæ ‡ã€Œé¡¹ç›®å»ºè®¾é˜¶æ®µã€è¿›åº¦æƒ…况」是 L/M åˆå¹¶è¡¨å¤´ï¼Œè¿™äº›å¸‚州只在 L å†™æ ‡é¢˜ | æ–°å¢ž `desc = stage + 1` å…œåº•(与既有 `startcum+2`、`yearcum+1` å…œåº•风格一致) |
| P04 | ã€Œåˆã€€ã€€ã€€è®¡ã€è¡Œè¢«å½“成项目入库 | `nt.contains("合计")` ä¸è¯†åˆ«å†…部空格 | åˆè®¡/总计/小计判定统一改为去空白后匹配(解析循环 + è¡Œæ•°ç»Ÿè®¡ + é¦–数据行探测三处同步) |
| P05 | è¥„阳 H50/J50 ç”Ÿæˆ 202.9565、定稿 203 | æºæ–‡ä»¶å³ 202.9565,定稿为人工取整 | æŒ‰ç”¨æˆ·ã€Œä¿ç•™ç¨‹åºç®—出的数(更完整)」保留 202.9565,不改程序 |
| P06 | å’¸å® L91 å»ºè®¾é˜¶æ®µï¼šç”Ÿæˆï¼ˆæ¯ç‰ˆï¼‰ã€Œæš‚停施工」、定稿「在建」 | ç”¨æˆ·å·²ç¡®è®¤ L å»ºè®¾é˜¶æ®µä¸åŠ¨æ¯ç‰ˆ | ç¨‹åºä¸å†™ L åˆ—,保持母版值 |
| P07 | ç«¹å±± M26、咸宁 M85、林区 M116 ä¸Žå®šç¨¿ä¸åŒ | å®šç¨¿ç•™ç©ºæˆ–写法不同(如「建成投产」vs「建成投产。」) | ç¨‹åºæŒ‰æºæ–‡ä»¶å†™å…¥ï¼Œæ¯”定稿更完整,保留 |
## äº”、遗留问题(需业务/用户确认后处理)
1. **武汉物流项目清单与定稿不一致**:库内 27 è¡Œæ¥è‡ªã€Šæ¹–北省十堰交通物流基础设施投资统计汇总表(月报)》,定稿用的是《2026 å¹´å…¨çœé¢„安排计划进度情况汇总(8月)》(含「航发智慧物流园」等)。需确认是「替换武汉全部物流项目」还是「追加」后再导入。
2. **天门物流无数据**:源文件《8月份物流园中心建设项目(天门).xlsx》H/J/K ä¸ºç©ºï¼ˆåº“内 0),定稿为 16677.7 / 500,需补源文件。
3. **荆州/黄石 è§„划内外拆分差异**:库内合计与定稿一致(如荆州 J=46548),仅「规划内/规划外」归类不同(定稿 46548 vs ç”Ÿæˆ 38320.5),属分类口径问题。
4. **十堰物流小数差**:定稿 29482 / 1671 vs ç”Ÿæˆ 29188 / 1591(源文件本身如此)。
5. **中口径排名残差**:仅来自 2025 å¹´ç½‘约车市州分摊算法(`WycSplitCalc` æ­¦æ±‰åˆ†æ¯å¤„理),未擅自调整,待确认。
6. **C ç»„**(城市客运页结构归一,需用户在 WPS æ•´åˆ—删除 AJ åˆ—后执行)、**D ç»„**(增速排名措辞)、**B4**(导出前基数体检 + å¼¹çª— + ã€Šæ•°æ®ç¼ºå¤±æ¸…单》页)待排期。
## å…­ã€ç»“论
本轮 14 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ï¼šæŠ•资市州单表的「表头取列定位」缺陷(P01–P04)已修复并回归验证,
8 æœˆå®¢è¿/物流源数据已补齐入库且与源文件小计逐项对齐;
新增的两张投资明细表导出正常(汇总页 0 å·®å¼‚);
中口径排名/明细同比口径修复后与定稿一致;
导入界面隐藏、报表项新增均按确认口径落地。
剩余差异均为**数据源缺口或母版手工口径**,不属于程序缺陷(见第五节)。
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_³ÖÐøÔÚ¹æÆóÒµ545¼Ò·ÖÊÐÖÝÀÛ¼ÆÔ˾àͬ±È_2026-09-19.md
New file
@@ -0,0 +1,52 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_持续在规企业545家分市州累计运距同比_2026-09-19
## ä¸€ã€åŠŸèƒ½è¯´æ˜Ž
- **需求**:按用户确认的「持续在规企业 = 2025 å¹´ 1-8 æœˆä¸Ž 2026 å¹´ 1-8 æœˆå‡è¿žç»­ 8 ä¸ªæœˆä¸ŠæŠ¥ã€å£å¾„(545 å®¶ï¼‰ï¼Œ
  ç®—出分市州 1-8 æœˆç´¯è®¡å¹³å‡è¿è·åŒæ¯”,输出到 `D:\桌面\货运企业分市州情况\`。
- **口径**:
  - æŒç»­åœ¨è§„企业(545 å®¶ï¼‰ï¼ä¸¤å¹´å‡è¿žç»­ 8 ä¸ªæœˆä¸ŠæŠ¥ H203-2 æœˆæŠ¥çš„企业;两年间新进、退出的企业不参与同比;
  - ç´¯è®¡å¹³å‡è¿è·ï¼ˆå…¬é‡Œï¼‰ï¼ 1-8 æœˆç´¯è®¡è´§ç‰©å‘¨è½¬é‡ Ã· 1-8 æœˆç´¯è®¡è´§è¿é‡ï¼ˆåŠ æƒå¹³å‡ï¼‰ï¼›
  - åŒæ¯” ï¼ 2026 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· Ã· 2025 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· âˆ’ 1;
  - å…¨çœè¡Œ ï¼ 17 ä¸ªå¸‚州的累计周转量、累计货运量分别求和后相除(非市州同比的算术平均)。
- **产出**:`D:\桌面\货运企业分市州情况\持续在规企业545å®¶_分市州1-8月累计运距及同比_2026-09-19.xlsx`
  ï¼ˆé¡µç­¾ï¼š`市州汇总`〔全省 + 17 å¸‚州〕、`企业明细(545å®¶)`)。
- **生成脚本**:`docs\工具\持续在规企业545家累计运距生成.py`。
## äºŒã€æµ‹è¯•环境
| é¡¹ | å†…容 |
| --- | --- |
| æ•°æ®åº“ | MySQL 127.0.0.1:3308 / traffic_audit,表 `h2032_enterprise_monthly` |
| è¿è¡ŒçŽ¯å¢ƒ | Python 3.14.2 + openpyxl 3.1.5 |
| å¯¹ç…§ç‰© | ç”¨æˆ·ä¾§ `D:\桌面\货运企业分市州情况\货运企业分市州情况xlsx.xlsx`(M/N ä¸¤åˆ—) |
| è¾“出位置 | å·¥ä½œåŒº `outputs\` ä¸Ž `D:\桌面\货运企业分市州情况\`,两份 SHA256 ä¸€è‡´ |
## ä¸‰ã€ç”¨ä¾‹è¡¨
| ç¼–号 | ç±»åž‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
| --- | --- | --- | --- | --- | --- |
| TC01 | æ­£å‘ | å…¨çœ 545 å®¶ 2026 å¹´ 1-8 æœˆç´¯è®¡å‘¨è½¬é‡ Ã· ç´¯è®¡è´§è¿é‡ | 158.1787 å…¬é‡Œ | 4389882.0468 Ã· 27752.6820 = 158.1787 | é€šè¿‡ |
| TC02 | æ­£å‘ | å…¨çœ 545 å®¶ 2025 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· | ä¸Žç”¨æˆ·æ–‡ä»¶ M4 ä¸€è‡´ | 153.7266,一致 | é€šè¿‡ |
| TC03 | æ­£å‘ | å…¨çœç´¯è®¡è¿è·åŒæ¯” | 158.1787 Ã· 153.7266 âˆ’ 1 | +2.8961% | é€šè¿‡ |
| TC04 | æ­£å‘ | 17 ä¸ªå¸‚å·ž 2025 å¹´ç´¯è®¡å¹³å‡è¿è·ï¼ˆåŽ»å¹´åŒæœŸåŸºæ•°ï¼‰ | ä¸Žç”¨æˆ·æ–‡ä»¶ M åˆ—逐行一致 | 17/17 ä¸€è‡´ | é€šè¿‡ |
| TC05 | æ­£å‘ | 17 ä¸ªå¸‚州累计运距同比 | ä¸Žç”¨æˆ·æ–‡ä»¶ N åˆ—逐行一致 | 17/17 ä¸€è‡´ï¼ˆå…¨çœè¡Œé™¤å¤–,见 TC10) | é€šè¿‡ |
| TC06 | æ­£å‘ | æ˜Žç»†é¡µ 545 è¡Œæ±‚å’Œ = æ±‡æ€»é¡µå…¨çœè¡Œ | å·®å¼‚ 0 | è´§è¿é‡ 27752.6820、周转量 4389882.0468,差异 0 | é€šè¿‡ |
| TC07 | æ­£å‘ | å…¨çœè¡Œ = Î£17 å¸‚å·ž | é€é¡¹ç›¸ç­‰ | ç›¸ç­‰ï¼ˆå…ˆæ±‚累计周转量、累计货运量再相除) | é€šè¿‡ |
| TC08 | è¾¹ç•Œ | ä»™æ¡ƒå¸‚ 2026 å¹´ 2 å®¶æŒç»­åœ¨è§„企业无 2025 å¹´è¿žç»­ä¸ŠæŠ¥è®°å½• | åŒæ¯”留空并注明不适用,不除零报错 | ä¼ä¸šæ•° 0、运距与同比留空,备注「同比不适用」 | é€šè¿‡ |
| TC09 | è¾¹ç•Œ | ç´¯è®¡è´§è¿é‡ä¸º 0 çš„企业 | ç´¯è®¡è¿è·ç•™ç©ºï¼Œä¸é™¤é›¶æŠ¥é”™ | å·²éªŒè¯ï¼ˆè¡¨å†…无此类企业) | é€šè¿‡ |
| TC10 | è´Ÿå‘ | ç”¨æˆ·æ–‡ä»¶å…¨çœè¡ŒåŒæ¯” +7.8217% | åº”与市州行同为 1-8 æœˆç´¯è®¡å£å¾„ | è¯¥å€¼å®žä¸º 545 å®¶ **8 æœˆå½“月**同比(157.0007 Ã· 145.6114 âˆ’ 1 = +7.8217%);累计口径应为 +2.8961%,两者相差 4.93 ä¸ªç™¾åˆ†ç‚¹ | é€šè¿‡ï¼ˆé—®é¢˜å·²åœ¨äº¤ä»˜ä»¶ä¸­ä¿®æ­£ï¼Œå¹¶åœ¨è¡¨å†…注明口径) |
| TC11 | è¾¹ç•Œ | æ­¦æ±‰çŸ³åŒ–交通运输有限公司、湖北捷龙交通运业有限公司 2026 å¹´ 1 æœˆåœ°åŒºç ä¸º 420100、其后为 420107/420103 | åŒå±žæ­¦æ±‰å¸‚,归集不影响 | å‡è®¡å…¥æ­¦æ±‰ | é€šè¿‡ |
## å››ã€å‘现的问题与处置
1. **用户文件全省行同比口径混用(已给出正确值)**:`货运企业分市州情况xlsx.xlsx` çš„ N4 å•元格填的是 545 å®¶ **8 æœˆå½“月**运距同比
   ï¼ˆ+7.8217%),而其下 17 ä¸ªå¸‚州行都是 **1-8 æœˆç´¯è®¡**同比。本表按累计口径给出全省 **+2.8961%**。
2. **M åˆ—未标年份**:该列表格值实为 2025 å¹´ï¼ˆåŽ»å¹´åŒæœŸï¼‰ç´¯è®¡å¹³å‡è¿è·ï¼Œè¡¨å¤´ã€Œ1-8月平均运距」易误读为今年;
   æœ¬è¡¨å°† 2025、2026 ä¸¤å¹´åˆ†åˆ—,消除歧义。
3. **仙桃市无可比基数**:2026 å¹´æŒç»­åœ¨è§„çš„ 2 å®¶ä¼ä¸š 2025 å¹´æ— è¿žç»­ä¸ŠæŠ¥è®°å½•,同比不适用(不是缺数),已在表内注明。
## äº”、结论
11 æ¡ç”¨ä¾‹ï¼ˆ7 æ­£å‘ / 3 è¾¹ç•Œ / 1 è´Ÿå‘)全部通过;17 ä¸ªå¸‚州与用户现有表格逐行一致,全省行更正为累计口径 +2.90%,
明细 545 è¡Œä¸Žæ±‡æ€»é€é¡¹å¯¹è´¦ 0 å·®å¼‚。交付件已生成到 `D:\桌面\货运企业分市州情况\`。
docs/³ÇÊпÍÔË/Ä£°å_ÍøÔ¼³µ¶©µ¥¼°È«Ê¡×ÜÁ¿.xlsx
Binary files differ
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-18.md
@@ -203,3 +203,63 @@
- é‡ç®—后 `分市州汇总` æ”¹ä¸ºã€Œ2026 å…¨å£å¾„ / 2025 å…¨å£å¾„ / åŒæ¯”」三段列;新增 `口径对比` é¡µå¹¶åˆ—两种口径,标出差异超 10 ä¸ªç™¾åˆ†ç‚¹çš„市州。
- ä¿®æ­£åŽå¸‚州同比:武汉 +17.0%、黄石 +35.3%、襄阳 +21.0%、宜昌 +7.4%、潜江 +5.6%、随州 +4.9%、恩施 +1.2%、荆州 âˆ’0.2%、黄冈 âˆ’0.3%、十堰 âˆ’1.9%、荆门 âˆ’6.6%、孝感 âˆ’13.3%、咸宁 âˆ’25.4%、林区 âˆ’49.1%、天门 âˆ’54.6%、鄂州 âˆ’63.1%、仙桃 âˆ’89.1%。
- å·²åŒæ­¥æ¡Œé¢äº¤ä»˜ä»¶ï¼ˆSHA256 ä¸€è‡´ï¼‰ã€‚
---
## å…­ã€å¤œé—´ç»­ä½œï¼ˆ2026-09-18 æ™š ~ 2026-09-19 å‡Œæ™¨ï¼‰
### 6.1 å®Œæˆäº‹é¡¹
| # | äº‹é¡¹ | çŠ¶æ€ |
| --- | --- | --- |
| 1 | **中口径排名/明细同比口径修复**:改为按「源表是否有该行」判定基期(`markMid`/`midMonthHas`/`midCumHitMonths`),去年缺月则同比留空;`loadMidClassMap()` å¢žåŠ è·¨åŽ¿å…¬äº¤å…œåº•ï¼ˆ`passengerVolume - passengerCity`);解析异常记入 `midIssues` å¹¶å‘Šè­¦ | âœ… å·²å®žæµ‹ |
| 2 | **网约车 2025 åˆ†æ‘Šå›žè½**:`WycSplitCalc` åœ¨æŸæœˆ pin ç¼ºå¤±/≤0 æ—¶å›žè½ `wyc_total_monthly` | âœ… å·²ç¼–译 |
| 3 | **新增两张投资明细表导出**:`/export/investPassengerDetail`、`/export/investLogisticsDetail`(只覆盖 H/J/K/M,I/L/G ä¸åŠ¨æ¯ç‰ˆï¼›ç‰©æµè¡¨æŒ‰è¡¨å†…æ•°å€¼é‡ç®—æ¸ é“/市州/合计行) | âœ… å·²å®žæµ‹ |
| 4 | **导入界面隐藏「网约车订单及全省总量」** | âœ… å·²å®žæµ‹ |
| 5 | **投资市州单表「表头取列定位」修复**(`findInvestHeader`):扫描上界改为「表头块」(首个数据行 âˆ’1,硬上限 +12)、新增「建设进展」关键词、新增 `desc=stage+1` å…œåº•、合计/小计去空白匹配 | âœ… å·²å®žæµ‹ |
| 6 | **补齐 2026-08 æŠ•资源数据**:客运 9 ä¸ªæ–‡ä»¶ + ç‰©æµ 16 ä¸ªæ–‡ä»¶å…¥ `docs\投资\输入\...\8月` å¹¶é‡å¯¼ï¼ˆå®¢è¿ 39 è¡Œ / ç‰©æµ 128 è¡Œï¼‰ | âœ… å·²å…¥åº“ |
### 6.2 æµ‹è¯•结果摘要
- è¯¦è§ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_投资明细表与导入取列定位修复_2026-09-19.md》:**14 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡**。
- å–列修复效果:咸宁客运形象进度 0→7、宜昌客运建设阶段/形象进度 0→5/5、孝感物流 0→7、恩施物流 0→4、随州物流 0→2;咸宁「合   计」假项目已消除(40→39 è¡Œï¼‰ã€‚
- å…¥åº“对齐抽查:孝感物流 160378/116414/13784、恩施物流 126741/41574/2116,与源文件市州小计行逐项一致。
- ä¸­å£å¾„排名(2026-08):全省 5.81%、武汉 4.65%、仙桃 17.23%、林区 âˆ’34.87%,与定稿一致;公交行累计同比 âˆ’28577% â†’ +13.15%。
- æŠ•资明细表:客运站汇总页 **0 å·®å¼‚**、明细页 6 å¤„;物流站场三页与修复前一致(差异仍为武汉/十堰/荆州/天门数据源缺口)。
### 6.3 é—留问题与待办
1. æ­¦æ±‰ç‰©æµé¡¹ç›®æ¸…单与定稿不一致(库内来自《十堰汇总表》,定稿来自《2026年全省预安排计划进度情况汇总(8月)》)→ éœ€ç¡®è®¤ã€Œæ›¿æ¢æ­¦æ±‰å…¨éƒ¨ç‰©æµé¡¹ç›®ã€è¿˜æ˜¯ã€Œè¿½åŠ ã€ã€‚
2. å¤©é—¨ç‰©æµæºæ–‡ä»¶ H/J/K ä¸ºç©ºï¼ˆåº“内 0,定稿 16677.7/500)→ éœ€è¡¥æºæ–‡ä»¶ã€‚
3. è†å·ž/黄石「规划内/规划外」拆分口径与定稿不同(合计一致)。
4. ä¸­å£å¾„排名残差来自 2025 å¹´ç½‘约车市州分摊算法,未擅改,待确认。
5. C ç»„(城市客运页结构归一,需用户先在 WPS æ•´åˆ—删除 AJ åˆ—)/D ç»„(增速排名措辞)/B4(导出前基数体检 + å¼¹çª— + ã€Šæ•°æ®ç¼ºå¤±æ¸…单》页)待排期。
### 6.4 æ˜Žæ—¥è®¡åˆ’
1. è½å®žæ­¦æ±‰ç‰©æµæ•°æ®å£å¾„确认后补导;补天门物流源数据。
2. æŽ¨è¿› C/D ç»„与 B4。
3. ä»£ç ï¼šä»Šæ™šæŒ‰ç”¨æˆ·è¦æ±‚**只推个人 gitee**(`origin master`),**不推公司 gitea**。
### 6.5 é—留问题处置(2026-09-19 00:5x ç”¨æˆ·ç¡®è®¤ï¼‰
| é—留项 | å¤„ç½® |
| --- | --- |
| æ­¦æ±‰ç‰©æµé¡¹ç›®æ¸…单与定稿不一致(库内来自《十堰汇总表》,定稿来自《2026年全省预安排计划进度情况汇总(8月)》) | **忽略**(不做处理) |
| å¤©é—¨ç‰©æµæºæ–‡ä»¶ H/J/K ä¸ºç©ºï¼ˆåº“内 0,定稿 16677.7 / 500) | **待用户明日向同事索取源数据**后再导入 |
| è†å·ž/黄石「规划内 / è§„划外」拆分口径与定稿不同(合计一致) | **待用户向同事确认口径** |
> ç”¨æˆ· 2026-09-19 00:5x åé¦ˆï¼šã€Œä»Šå¤©å…ˆæ—©ç‚¹ä¼‘息」,以上三项次日跟进。
### 6.6 æ–°å¢žä¸€é”®å¯åœï¼ˆ2026-09-19 00:5x)
- **背景**:用户反映页面报「数据查询失败/导入记录加载失败」。核查为后端(8090)与前端(8080)进程都已退出
  ï¼ˆMySQL æ­£å¸¸ï¼Œ`SELECT 1` é€šè¿‡ï¼‰ï¼›åŽŸå› æ˜¯æœåŠ¡ä»¥ `cmd /c ... > log` æŒ‚在启动窗口下,**关掉启动窗口就把服务带走了**。
  å·²é‡å¯å¹¶å®žæµ‹ `/api/import/batches`、`/api/data/list` å‡ HTTP 200。
- **新增 `stop-dev.ps1`**(项目根目录):按「启动用的 cmd çˆ¶è¿›ç¨‹ + ç²¾ç¡®å‘½ä»¤è¡Œç‰¹å¾ã€æ•´æ ‘ `taskkill /T /F`,
  å…œåº•匹配孤儿 `java(TrafficAuditApplication)` / `node(vue-cli-service)`,结束后校验 8090/8080 æ˜¯å¦é‡Šæ”¾ï¼›
  ä¸ç¢° `node_repl` ä¸Žç”¨æˆ·è‡ªå·±çš„ cmd çª—口。
- **新增桌面入口**(工作区外,不入库):`D:\桌面\启动交通审核系统.bat`(已在跑则跳过、不在跑则拉起,带 `nobrowser` å‚数可只启服务)、
  `D:\桌面\停止交通审核系统.bat`。
- **编码坑(已修)**:`.bat` å¿…é¡» CRLF + GBK(936)(首版写了 LF,cmd è§£æžæŠ¥é”™ï¼‰ï¼›`.ps1` å¿…é¡» UTF-8 **with BOM**
  ï¼ˆé¦–版无 BOM,PS 5.1 æŒ‰ ANSI è¯»ï¼Œä¸­æ–‡æ‰“断字符串导致 `UnexpectedToken`)。
- **测试**:《功能测试报告_一键启停脚本与桌面入口_2026-09-19.md》,5 æ¡ç”¨ä¾‹å…¨éƒ¨é€šè¿‡ï¼ˆåœ¨è·‘跳过/未跑拉起/停止释放端口/启停闭环接口 200/不误杀)。
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-19.md
New file
@@ -0,0 +1,129 @@
# å·¥ä½œæ—¥ç»“_2026-09-19
## ä¸€ã€ä»Šå¤©åšäº†ä»€ä¹ˆ
### 1. æŒç»­åœ¨è§„企业(545 å®¶ï¼‰åˆ†å¸‚å·ž 1-8 æœˆç´¯è®¡è¿è·åŒæ¯”(桌面交付)
用户 09-18 ç¡®è®¤ã€ŒæŒç»­åœ¨è§„企业」= **2025 å¹´ 1-8 æœˆä¸Ž 2026 å¹´ 1-8 æœˆå‡è¿žç»­ 8 ä¸ªæœˆä¸ŠæŠ¥**(545 å®¶ï¼‰ï¼Œ
要求把该口径下的分市州累计运距同比算出来并输出到 `D:\桌面\货运企业分市州情况\`。
- æ•°æ®æºï¼š`traffic_audit.h2032_enterprise_monthly`(2025-01 ~ 2026-08)。
- å£å¾„:累计平均运距 = 1-8 æœˆç´¯è®¡å‘¨è½¬é‡ Ã· ç´¯è®¡è´§è¿é‡ï¼›åŒæ¯” = ä»Šå¹´ç´¯è®¡ Ã· åŽ»å¹´åŒæœŸç´¯è®¡ âˆ’ 1;全省 = Î£17 å¸‚州。
- äº§å‡ºï¼š`持续在规企业545å®¶_分市州1-8月累计运距及同比_2026-09-19.xlsx`(`市州汇总` + `企业明细(545å®¶)`),
  è„šæœ¬ `docs\工具\持续在规企业545家累计运距生成.py`。
关键结果:
| å¸‚å·ž | 2026å¹´1-8月累计运距(公里) | 2025年同期(公里) | åŒæ¯” | å¸‚å·ž | 2026å¹´1-8月累计运距(公里) | 2025年同期(公里) | åŒæ¯” |
| --- | --- | --- | --- | --- | --- | --- | --- |
| **全省** | **158.18** | **153.73** | **+2.90%** | é»„冈 | 138.73 | 137.16 | +1.15% |
| æ­¦æ±‰ | 159.66 | 140.71 | +13.47% | å’¸å® | 115.25 | 151.84 | âˆ’24.10% |
| é»„石 | 112.67 | 93.75 | +20.18% | éšå·ž | 187.28 | 226.03 | âˆ’17.14% |
| åå ° | 321.13 | 330.78 | âˆ’2.92% | æ©æ–½å·ž | 141.78 | 128.56 | +10.28% |
| å®œæ˜Œ | 85.75 | 83.61 | +2.57% | ä»™æ¡ƒ | â€” | â€” | ä¸é€‚用 |
| è¥„阳 | 279.65 | 258.01 | +8.39% | æ½œæ±Ÿ | 407.97 | 367.73 | +10.94% |
| é„‚å·ž | 42.38 | 103.49 | âˆ’59.05% | å¤©é—¨ | 61.02 | 134.33 | âˆ’54.57% |
| è†é—¨ | 305.92 | 321.00 | âˆ’4.70% | ç¥žå†œæž¶æž—区 | 57.68 | 113.39 | âˆ’49.13% |
| å­æ„Ÿ | 183.86 | 198.51 | âˆ’7.38% | | | | |
| è†å·ž | 321.44 | 337.36 | âˆ’4.72% | | | | |
### 2. æ ¸å¯¹ç”¨æˆ·ä¾§ã€Šè´§è¿ä¼ä¸šåˆ†å¸‚州情况》表
- è¯¥è¡¨ M/N ä¸¤åˆ—(持续在规企业)与本次 545 å®¶å£å¾„**逐行一致**(M = åŽ»å¹´åŒæœŸåŸºæ•°ï¼ŒN = ç´¯è®¡åŒæ¯”)。
- å‘现一处口径混用:**全省行 N4 å¡«çš„æ˜¯ 8 æœˆå½“月同比 +7.8217%**(157.0007 Ã· 145.6114 âˆ’ 1),
  å…¶ä½™ 17 è¡Œå‡ä¸º 1-8 æœˆç´¯è®¡åŒæ¯”;累计口径应为 **+2.90%**(158.18 Ã· 153.73 âˆ’ 1),相差 4.93 ä¸ªç™¾åˆ†ç‚¹ã€‚
- è¡¨å¤´ã€Œ1-8月平均运距」未标年份,实际为 2025 å¹´å€¼ï¼Œå·²åœ¨æœ¬æ¬¡äº¤ä»˜ä»¶ä¸­åˆ†åˆ—两年消除歧义。
- è¯¥è¡¨ O åˆ—「1-8月高速运距同比」与手头高速数据(`运距分析报告\运距分析数据汇总.xlsx`)算得的全省 âˆ’5.94% ä¸ä¸€è‡´
  ï¼ˆå¸‚州差异更大),来源与期间待用户确认;按用户要求本轮不处理高速列。
### 3. åŒåä¼ä¸šå£å¾„ 1-8 æœˆç´¯è®¡è´§è¿é‡/周转量 SQL æŸ¥è¯¢è„šæœ¬ï¼ˆæœ¬æ¬¡æ–°å¢žï¼‰
用户提问:25 å¹´ä¸Ž 26 å¹´ä¼ä¸šæ•°ä¸åŒï¼Œè¦ã€Œä¼ä¸šåç§°ç›¸åŒã€åœ°åˆ†åˆ«æ±‡æ€» 1-8 æœˆç´¯è®¡çš„
货物周转量和货运量,SQL æ€Žä¹ˆå†™ã€‚
- äº¤ä»˜è„šæœ¬ï¼š`docs\生成汇总大表\同名企业_1-8月累计对比_2026-09-19.sql`(6 æ¡æŸ¥è¯¢ï¼Œå…¨ä¸­æ–‡æ³¨é‡Šï¼‰ã€‚
- å£å¾„:企业名称取两年 1-8 æœˆçš„交集,与白天确认的「持续在规企业 545 å®¶ã€å®Œå…¨ä¸€è‡´ï¼›
  å•位统一 Ã·10000 è¾“出「万吨 / ä¸‡å¨å…¬é‡Œã€ã€‚
- ç»“果:
| å£å¾„ | ä¼ä¸šæ•° | è´§è¿é‡2025(万吨) | è´§è¿é‡2026(万吨) | è´§è¿é‡åŒæ¯” | å‘¨è½¬é‡2025(万吨公里) | å‘¨è½¬é‡2026(万吨公里) | å‘¨è½¬é‡åŒæ¯” |
| --- | --- | --- | --- | --- | --- | --- | --- |
| åŒåä¼ä¸š | 545 | 30153.14 | 27752.68 | âˆ’7.96% | 4635340.46 | 4389882.05 | âˆ’5.30% |
| å…¨é‡ | 664 / 636 | 33994.45 | 31399.82 | â€” | 5102518.95 | 4927161.77 | â€” |
同名口径的 2026 å¹´ç´¯è®¡æ•°ä¸Žç™½å¤©äº¤ä»˜ä»¶å…¨çœè¡Œï¼ˆ27752.6820 ä¸‡å¨ / 4389882.0468 ä¸‡å¨å…¬é‡Œï¼‰å®Œå…¨ä¸€è‡´ï¼Œä¸¤æ¡é“¾è·¯äº’证通过。
全量与同名口径的差额也已算清:2026 å¹´æ–°è¿› 91 å®¶ï¼ˆ+3647.14 ä¸‡å¨ / +537279.73 ä¸‡å¨å…¬é‡Œï¼‰ï¼Œ
2025 å¹´é€€å‡º 119 å®¶ï¼ˆâˆ’3841.31 ä¸‡å¨ / âˆ’467178.48 ä¸‡å¨å…¬é‡Œï¼‰ã€‚
补充(当日追加):用户接着要「企业明细也导出来」,脚本追加 **查询 7 ä¼ä¸šæ˜Žç»†å¯¼å‡º** ä¸Ž **查询 8 åˆè®¡å¯¹æ€»æ•°**。
- æŸ¥è¯¢ 7 çš„匹配键改用 `unified_credit_code`,覆盖 **546 å®¶**(比名称口径多 1 å®¶æ”¹åä¼ä¸šï¼š
  `91420112558443820B`,2025-01~09「湖北三峡富烨绿电供应链有限公司」→ 2025-10 èµ·ã€Œæ¹–北长峡富烨绿电供应链有限公司」),
  è¾“出 14 åˆ—(信用代码、两年名称、是否改名、市州、两年货运量/周转量及增减同比),按 2026 å¹´è´§è¿é‡é™åºã€‚
- 546 å®¶å£å¾„合计:2025 å¹´ 1-8 æœˆ 30162.99 ä¸‡å¨ / 4637038.58 ä¸‡å¨å…¬é‡Œï¼›2026 å¹´ 27764.88 ä¸‡å¨ / 4392984.81 ä¸‡å¨å…¬é‡Œã€‚
- è„šæœ¬å†…é™„ä¸‰ç§å¯¼å‡ºæ–¹å¼ï¼ˆå‘½ä»¤è¡Œ tsv / Navicat å¯¼ xlsx / INTO OUTFILE),命令行方式已实测导出 546 è¡Œã€ä¸­æ–‡æ­£å¸¸ã€‚
- å¾…用户确认:对外报送用 545 å®¶ï¼ˆåç§°äº¤é›†ï¼‰è¿˜æ˜¯ 546 å®¶ï¼ˆä»£ç äº¤é›†ï¼‰ï¼Œç¡®è®¤åŽå†å®šç¨¿ä»¶ã€‚
追加(当日第二轮):核对桌面《规上持续在规企业1-8月运距同比.xlsx》与今日交付件,
并修复 SQL è„šæœ¬çš„æ˜Žç»†ç²¾åº¦ç¼ºé™·ã€‚
- æ ¸å¯¹ç»“论:两文件企业名称**545 å®¶é€å­—符一致**(唯一多出的是改名企业 æ¹–北长峡富烨绿电…);
  ä½†é™¤åç§°å¤–其余列对不上——运距 540/545 å®¶ä¸ä¸€è‡´ï¼ˆæœ€å¤§ 8.53 å…¬é‡Œï¼‰ã€2025 è¿è· 544/545 ä¸ä¸€è‡´ã€
  åŒæ¯” 540/545 ä¸ä¸€è‡´ï¼›æ ¹å› æ˜¯å¯¹æ–¹æ–‡ä»¶ç”¨ã€Œä¸‡å¨ä¿ç•™ 2 ä½ã€å†ç®—运距,交付件走全精度(与数据库 0 åå·®ï¼‰ã€‚
  å¦å‘现市州写法差异:对方写"恩施",交付件写"恩施州"(3 å®¶ï¼‰ã€‚
- ç¼ºé™·ä¿®å¤ï¼šåŽŸ SQL çš„æ˜Žç»†æŸ¥è¯¢ï¼ˆæŸ¥è¯¢ 2、查询 7)把万吨列 `ROUND(...,2)`,精度只到 100 å¨ï¼Œ
  ç”¨æˆ·æ‹¿åŽ»ç®—è¿è·ä¼šè¢«æ”¾å¤§ï¼ˆæ¹–åŒ—å¼˜é›· 4631 å¨ â†’ 0.46 ä¸‡å¨ â†’ è¿è·è™šé«˜ 8.53 å…¬é‡Œï¼‰ã€‚
  å·²æ”¹ä¸º 4 ä½å°æ•°ï¼Œå¹¶åœ¨è„šæœ¬é¡¶éƒ¨æ–°å¢žã€Œâ˜… å°æ•°ä½çº¦å®šã€è¯´æ˜Žæ®µï¼›æ•´è„šæœ¬å›žå½’é€šè¿‡ï¼ˆ21 æ¡ç”¨ä¾‹ï¼‰ã€‚
- å¾…确认:对外报送用 545 å®¶è¿˜æ˜¯ 546 å®¶å£å¾„;以及是否把交付件与对方文件的小数位、恩施写法统一。
- è¿½åŠ ï¼šæŒ‰ç”¨æˆ·è¦æ±‚æŠŠæ˜Žç»†ç±»æŸ¥è¯¢ï¼ˆæŸ¥è¯¢ 2、查询 7)的 `ROUND` å…¨éƒ¨åŽ»æŽ‰ï¼Œå¯¼å‡ºå³åŽŸå§‹å€¼ï¼›
  å®žæµ‹è´§è¿é‡/周转量的原始值最多 4 ä½å°æ•°ï¼ˆ636 å®¶ä¼ä¸šä¸­ 4 ä½ä»¥å¤–还有尾数的为 0 å®¶ï¼‰ï¼Œ
  4 ä½å³å…¨ç²¾åº¦ã€‚汇总类仍保留 2 ä½ã€‚整脚本回归通过(25 æ¡ç”¨ä¾‹ï¼‰ã€‚
- è¿½åŠ éªŒè¯ï¼šæŸ¥è¯¢ 2(545 å®¶åç§°å£å¾„)与查询 7(546 å®¶ä»£ç å£å¾„)**剔除改名企业后逐比特完全相等**
  ï¼ˆ545 è¡Œä¼ä¸šåå•一致,8 ä¸ªæ•°å€¼åˆ— + åœ°åŒºä»£ç æœ€å¤§å·®å‡ä¸º 0)。原因是匹配键一一对应 + æ•´æ•°æ±‚和精确。
  å·²è®°ä¸ºæµ‹è¯•报告 T26(累计 26 æ¡ç”¨ä¾‹ï¼‰ã€‚
- è¿½åŠ ï¼šç¡®è®¤ã€Œ4 ä½å°æ•°ã€çš„适用范围(货运量/周转量 4 ä½å³å…¨ç²¾åº¦ï¼Œ754 ä¸ªå¯¹è±¡ 0 ä¾‹å¤–ï¼›
  è¿è·ã€åŒæ¯”不等于全精度),据此把汇总类查询(1/3/5/8)的 14 å¤„小数位统一为 4 ä½ã€‚
  æ”¹åŽè„šæœ¬è¾“å‡ºä¸Ž 545 å®¶äº¤ä»˜ä»¶å¸‚州汇总逐列对齐(T27~T30,累计 30 æ¡ç”¨ä¾‹ï¼‰ã€‚
### 4. æ±‡æ€»å¤§è¡¨ã€Œä¸­å£å¾„排名」周转量口径统一(用户桌面核出差异 â†’ å®šä½ â†’ ä¿®å¤ï¼‰
用户把人工算的一列(「人工-周转量」)放进桌面《生成_道路运输量汇总表 (1).xlsx》的「中口径排名」页,
问为什么和程序生成的「周转量」对不上(全省 +0.31978 ä¸‡äººå…¬é‡Œï¼Œå„市州 Â±0.01~0.08)。
- **定位**:同一本表里两页口径不同。「中口径排名」走 `loadMidClassMap()` å…¬äº¤ç»´åº¦â€”—**逐企业行**
  ã€ŒåŸŽé™…城乡字段 > 0 å°±ç”¨å­—段值,= 0 æ‰å›žé€€ æ€»é‡ âˆ’ åŸŽå¸‚内」;「中口径明细/分析/道路运输周转量」走台账口径
  `smReadLedgerMetrics()`——先按月按市州汇总再 æ€»é‡åˆè®¡ âˆ’ åŸŽå¸‚内合计。
  æºæŠ¥è¡¨ä¸‰ä¸ªæ•°å„自两位小数舍入,2026 å¹´ 1-8 æœˆå…¨çœæœ‰ **72 è¡Œ**企业月报
  `城际城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内`(差 Â±0.01),程序采信字段值、人工用差额法,累加即成差异。
  æŒ‰ä¼ä¸šè¡Œé‡ç®—的运输口径差**逐市州与表里差列完全吻合**(孝感 +0.08、宜昌/荆州 +0.05、武汉/黄冈/天门 +0.04…)。
- **修复**:`ReportExportService.java` å…¬äº¤ç»´åº¦æ”¹ä¸ºä¸€å¾‹ã€Œæ€»é‡ âˆ’ åŸŽå¸‚内」现算(与台账页/明细页/四页合成口径一致)。
- **验证**:重启后端重新生成 2026-08 å¤§è¡¨ï¼Œã€Œä¸­å£å¾„排名」周转量与人工/明细口径 **17 å¸‚州逐格归零**;
  å®¢è¿é‡ã€åŒæ¯”、分析页、四页合成页无回归;2025 åŒæ¯”基期 0 è¡Œå—影响(改后 17 å¸‚州差全 0)。
- å–证脚本与生成件:`_qa_busfix*.py`、`_after_busfix_2026-08.xlsx`、`_after_midrank.xlsx`、`_after_midana.xlsx`。
## äºŒã€æµ‹è¯•结果摘要
见《功能测试报告_持续在规企业545家分市州累计运距同比_2026-09-19.md》:11 æ¡ç”¨ä¾‹ï¼ˆ7 æ­£å‘ / 3 è¾¹ç•Œ / 1 è´Ÿå‘)全部通过。
- æ˜Žç»† 545 è¡Œæ±‚å’Œ = æ±‡æ€»é¡µå…¨çœè¡Œï¼ˆ27752.6820 ä¸‡å¨ / 4389882.0468 ä¸‡å¨å…¬é‡Œï¼Œå·®å¼‚ 0);
- å…¨çœè¡Œ = Î£17 å¸‚å·žï¼›17 ä¸ªå¸‚州与用户表格逐行一致;
- ä»™æ¡ƒå¸‚无可比基数、累计货运量为 0 çš„企业均已防除零处理。
- åŒåä¼ä¸šå£å¾„ SQL è„šæœ¬å·²æ•´è„šæœ¬æ‰§è¡ŒéªŒè¯ï¼ˆå«è¿½åŠ çš„æ˜Žç»†å¯¼å‡ºæŸ¥è¯¢ï¼‰ï¼š17 æ¡ç”¨ä¾‹ï¼ˆ11 æ­£å‘ / 2 è´Ÿå‘ / 4 è¾¹ç•Œï¼‰å…¨éƒ¨é€šè¿‡ï¼›
  æ˜Žç»† 545 è¡Œæ±‚å’Œ = æ±‡æ€»è¡Œï¼ˆå·®å¼‚ 0),差异企业闭合校验通过。
- ä¸­å£å¾„排名周转量口径统一:14 æ¡ç”¨ä¾‹ï¼ˆ6 æ­£å‘ / 1 å›žå½’组 / 3 è¾¹ç•Œ / 3 è´Ÿå‘回归)全部通过,
  è¯¦è§ã€ŠåŠŸèƒ½æµ‹è¯•æŠ¥å‘Š_中口径排名周转量口径统一_2026-09-19.md》;
  å…¨çœè¡Œä»æ®‹ç•™ 0.0002 ä¸‡äººå…¬é‡Œï¼ˆ=2 äººå…¬é‡Œï¼Œæ¯ç‰ˆ `=SUM(O4:O20)` å…ˆå››èˆäº”入后求和的固有结构)。
## ä¸‰ã€é—留问题与待办
1. ç”¨æˆ·è¡¨æ ¼ O åˆ—高速运距同比的来源/期间待确认(需与 N åŒä¸º 1-8 æœˆç´¯è®¡ï¼‰ï¼Œç¡®è®¤åŽæ–¹å¯ç®—「运距增速差」。
2. 09-18 äº¤ä»˜çš„《货运月报_持续在规企业_分市州1-8月累计运距及同比》采用**官方全口径**(同比 +4.54%);
   æœ¬è¡¨é‡‡ç”¨**两年持续在规 545 å®¶å£å¾„**(同比 +2.90%),两版口径不同但都已注明,供业务按场景选用。
3. è‹¥è¯¥è¡¨è¦éšã€Šå·®å¼‚率汇总表》上报,建议加注两种口径的差异原因(规上企业名单变动)。
4. ã€Œä¸­å£å¾„排名」全省行(母版公式 `=SUM(O4:O20)`)与明细全精度求和差 0.0002 ä¸‡äººå…¬é‡Œï¼Œ
   æ˜¯å¦æ”¹æˆå…¨ç²¾åº¦å†™å€¼ï¼Œå¾…用户拍板。
5. æºæŠ¥è¡¨ `city_bus_monthly` ä¸­ 72 è¡Œã€ŒåŸŽé™…城乡 â‰  æ€»é‡ âˆ’ åŸŽå¸‚内」的两位小数舍入差异,
   å·²æŒ‰å·®é¢æ³•统一;如后续要与上报口径完全对齐,需回头与填报方确认该字段口径。
## å››ã€æ˜Žå¤©è®¡åˆ’
1. è§†ç”¨æˆ·åé¦ˆç¡®å®šä¸ŠæŠ¥å£å¾„(545 å®¶ vs å…¨å£å¾„),必要时合并成一版双口径表。
2. é«˜é€Ÿæ•°æ®æ¥æºç¡®è®¤åŽè¡¥ç®—「运距增速差」。
docs/¹¤¾ß/³ÖÐøÔÚ¹æÆóÒµ545¼ÒÀÛ¼ÆÔ˾àÉú³É.py
New file
@@ -0,0 +1,174 @@
# -*- coding: utf-8 -*-
"""持续在规企业(545 å®¶ï¼‰åˆ†å¸‚å·ž 1-8 æœˆç´¯è®¡å¹³å‡è¿è·åŠåŒæ¯” å°è´¦
口径:
  Â· æŒç»­åœ¨è§„企业 = 2025 å¹´ 1-8 æœˆä¸Ž 2026 å¹´ 1-8 æœˆå‡è¿žç»­ 8 ä¸ªæœˆä¸ŠæŠ¥ H203-2 æœˆæŠ¥çš„企业(545 å®¶ï¼‰ï¼›
  Â· ç´¯è®¡å¹³å‡è¿è·ï¼ˆå…¬é‡Œï¼‰= 1-8 æœˆç´¯è®¡è´§ç‰©å‘¨è½¬é‡ Ã· 1-8 æœˆç´¯è®¡è´§è¿é‡ï¼ˆåŠ æƒå¹³å‡ï¼‰ï¼›
  Â· åŒæ¯” = 2026 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· Ã· 2025 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· âˆ’ 1。
数据源:traffic_audit.h2032_enterprise_monthly å¯¼å‡ºä»¶ _tmp_persist_scope.tsv
"""
import io, os
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
SRC = r'D:\文档\ChatGPT\traffic-audit\_tmp_persist_scope.tsv'
OUT = r'D:\文档\ChatGPT\traffic-audit\outputs\持续在规企业545å®¶_分市州1-8月累计运距及同比_2026-09-19.xlsx'
ORDER = ['武汉市', '黄石市', '十堰市', '宜昌市', '襄阳市', '鄂州市', '荆门市', '孝感市', '荆州市',
         '黄冈市', '咸宁市', '随州市', '恩施州', '仙桃市', '潜江市', '天门市', '神农架林区']
SHORT = {'武汉市': '武汉', '黄石市': '黄石', '十堰市': '十堰', '宜昌市': '宜昌', '襄阳市': '襄阳', '鄂州市': '鄂州',
         '荆门市': '荆门', '孝感市': '孝感', '荆州市': '荆州', '黄冈市': '黄冈', '咸宁市': '咸宁', '随州市': '随州',
         '恩施州': '恩施州', '仙桃市': '仙桃', '潜江市': '潜江', '天门市': '天门', '神农架林区': '林区'}
CITY = dict(zip(['4201', '4202', '4203', '4205', '4206', '4207', '4208', '4209', '4210', '4211', '4212', '4213', '4228'],
                ORDER[:13]))
CITY.update({'429004': '仙桃市', '429005': '潜江市', '429006': '天门市', '429021': '神农架林区'})
def city_of(rc):
    rc = (rc or '').strip()
    return CITY.get(rc, CITY.get(rc[:4], '?'))
def dv(f, t):
    return (t / f) if f else None
def gth(a, b):
    return (a / b - 1) if (a is not None and b) else None
def num(x):
    try:
        return float(x)
    except Exception:
        return 0.0
rows = []
with io.open(SRC, 'r', encoding='utf-8') as fh:
    hdr = fh.readline().rstrip('\r\n').split('\t')
    for line in fh:
        p = line.rstrip('\r\n').split('\t')
        if len(p) < len(hdr):
            continue
        d = dict(zip(hdr, p))
        if int(num(d['m26'])) != 8 or int(num(d['m25'])) != 8:
            continue
        rows.append(dict(city=city_of(d['rc']), en=d['en'], ec=d['ec'], ucc=d['ucc'],
                         f26=num(d['f26']), t26=num(d['t26']), f25=num(d['f25']), t25=num(d['t25'])))
by_city = {}
for r in rows:
    c = by_city.setdefault(r['city'], dict(n=0, f26=0.0, t26=0.0, f25=0.0, t25=0.0))
    c['n'] += 1
    c['f26'] += r['f26']; c['t26'] += r['t26']; c['f25'] += r['f25']; c['t25'] += r['t25']
tot = dict(n=0, f26=0.0, t26=0.0, f25=0.0, t25=0.0)
for c in by_city.values():
    for k in tot:
        tot[k] += c[k]
THIN = Side(style='thin', color='BFBFBF')
BORDER = Border(left=THIN, right=THIN, top=THIN, bottom=THIN)
HDR_FILL = PatternFill('solid', fgColor='DDEBF7')
TOT_FILL = PatternFill('solid', fgColor='FFF2CC')
TITLE_FILL = PatternFill('solid', fgColor='1F4E79')
CT = Alignment(horizontal='center', vertical='center', wrap_text=True)
LT = Alignment(horizontal='left', vertical='center', wrap_text=True)
RT = Alignment(horizontal='right', vertical='center')
NF2, NFP = '#,##0.00', '0.00%'
wb = Workbook()
ws = wb.active
ws.title = '市州汇总'
heads = ['市州', '持续在规企业数(å®¶)', '2026å¹´1-8月累计货运量(万吨)', '2026å¹´1-8月累计货物周转量(万吨公里)',
         '2026å¹´1-8月累计平均运距(公里)', '2025å¹´1-8月累计平均运距(公里)', '累计运距同比(%)', '备注']
widths = [12, 16, 22, 26, 22, 22, 14, 46]
ws.cell(1, 1, '持续在规企业(545 å®¶ï¼‰åˆ†å¸‚å·ž 1-8 æœˆç´¯è®¡å¹³å‡è¿è·åŠåŒæ¯”').font = Font(bold=True, size=14, color='FFFFFF')
ws.cell(1, 1).fill = TITLE_FILL
ws.cell(1, 1).alignment = Alignment(horizontal='center', vertical='center')
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(heads))
ws.row_dimensions[1].height = 28
notes = [
    '口径说明:',
    '① æŒç»­åœ¨è§„企业 = 2025 å¹´ 1-8 æœˆä¸Ž 2026 å¹´ 1-8 æœˆå‡è¿žç»­ 8 ä¸ªæœˆä¸ŠæŠ¥ã€Šé“路货物运输月度生产情况》(H203-2)月报的企业,共 %d å®¶ï¼›ä¸¤å¹´é—´æ–°è¿›ã€é€€å‡ºçš„企业不计入本表同比。' % tot['n'],
    '② ç´¯è®¡å¹³å‡è¿è·ï¼ˆå…¬é‡Œï¼‰= 1-8 æœˆç´¯è®¡è´§ç‰©å‘¨è½¬é‡ Ã· 1-8 æœˆç´¯è®¡è´§è¿é‡ï¼ˆåŠ æƒå¹³å‡ï¼‰ï¼›åŒæ¯” = 2026 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· Ã· 2025 å¹´ 1-8 æœˆç´¯è®¡å¹³å‡è¿è· âˆ’ 1。',
    '③ å…¨çœè¡Œ = 17 ä¸ªå¸‚州之和(按累计周转量、累计货运量分别求和后相除,不是市州同比的算术平均)。',
    '④ ä»™æ¡ƒå¸‚ 2026 å¹´æŒç»­åœ¨è§„çš„ 2 å®¶ä¼ä¸š 2025 å¹´ 1-8 æœˆæ— è¿žç»­ä¸ŠæŠ¥è®°å½•,本表无可比基数,同比不适用。',
    '数据来源:交通统计报表审核系统数据库(H203-2 ä¼ä¸šæœˆæŠ¥ï¼Œ2025 å¹´ 1 æœˆâ€”2026 å¹´ 8 æœˆï¼‰ã€‚生成日期:2026-09-19。',
]
r = 2
for i, t in enumerate(notes):
    c = ws.cell(r, 1, t)
    c.font = Font(size=9, bold=(i == 0), color='404040')
    c.alignment = LT
    ws.merge_cells(start_row=r, start_column=1, end_row=r, end_column=len(heads))
    r += 1
hdr_row = r
for j, h in enumerate(heads, 1):
    c = ws.cell(hdr_row, j, h)
    c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER
    ws.column_dimensions[get_column_letter(j)].width = widths[j - 1]
ws.row_dimensions[hdr_row].height = 42
def put(row, vals, fill=None, bold=False):
    for j, v in enumerate(vals, 1):
        c = ws.cell(row, j, v)
        c.border = BORDER
        c.alignment = LT if j == 8 else (CT if j == 1 else RT)
        if j in (3, 4, 5, 6):
            c.number_format = NF2
        elif j == 7:
            c.number_format = NFP
        if fill:
            c.fill = fill
        if bold:
            c.font = Font(bold=True)
rr = hdr_row
d26 = dv(tot['f26'], tot['t26']); d25 = dv(tot['f25'], tot['t25'])
rr += 1
put(rr, ['全省', tot['n'], tot['f26'] / 10000.0, tot['t26'] / 10000.0, d26, d25, gth(d26, d25), ''], TOT_FILL, True)
for city in ORDER:
    c = by_city.get(city)
    rr += 1
    if not c or c['n'] == 0:
        put(rr, [SHORT[city], 0, None, None, None, None, None,
                 '该市州 2026 å¹´æŒç»­åœ¨è§„企业在 2025 å¹´ 1-8 æœˆæ— è¿žç»­ä¸ŠæŠ¥è®°å½•,同比不适用'])
        continue
    a, b = dv(c['f26'], c['t26']), dv(c['f25'], c['t25'])
    put(rr, [SHORT[city], c['n'], c['f26'] / 10000.0, c['t26'] / 10000.0, a, b, gth(a, b), ''])
ws.freeze_panes = ws.cell(hdr_row + 1, 2).coordinate
# ä¼ä¸šæ˜Žç»†
ws2 = wb.create_sheet('企业明细(545å®¶)')
h2 = ['序号', '市州', '企业名称', '统一社会信用代码', '2026å¹´1-8月货运量(万吨)', '2026å¹´1-8月周转量(万吨公里)',
      '2026å¹´1-8月累计平均运距(公里)', '2025å¹´1-8月累计平均运距(公里)', '累计运距同比(%)']
w2 = [6, 12, 42, 24, 20, 24, 22, 22, 14]
for j, h in enumerate(h2, 1):
    c = ws2.cell(1, j, h)
    c.font = Font(bold=True); c.fill = HDR_FILL; c.alignment = CT; c.border = BORDER
    ws2.column_dimensions[get_column_letter(j)].width = w2[j - 1]
ws2.row_dimensions[1].height = 40
order = {c: i for i, c in enumerate(ORDER)}
idx = 0
for i, x in enumerate(sorted(rows, key=lambda z: (order.get(z['city'], 99), -z['t26'])), 1):
    a, b = dv(x['f26'], x['t26']), dv(x['f25'], x['t25'])
    vals = [i, SHORT[x['city']], x['en'], x['ucc'], x['f26'] / 10000.0, x['t26'] / 10000.0, a, b, gth(a, b)]
    for j, v in enumerate(vals, 1):
        c = ws2.cell(i + 1, j, v)
        c.border = BORDER
        c.alignment = LT if j in (3, 4) else (CT if j in (1, 2) else RT)
        if j in (5, 6, 7, 8):
            c.number_format = NF2
        elif j == 9:
            c.number_format = NFP
ws2.freeze_panes = 'C2'
ws2.auto_filter.ref = 'A1:I%d' % (len(rows) + 1)
os.makedirs(os.path.dirname(OUT), exist_ok=True)
wb.save(OUT)
print('OK ->', OUT)
print('企业数 %d;全省 2026 %.4f / 2025 %.4f -> %.4f%%' % (tot['n'], d26, d25, gth(d26, d25) * 100))
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/2026Äê8ÔÂÏÌÄþÊпÍÔËÕ¾³¡Í¶×Êͳ¼ÆÔ±¨±í(1)Ê¡±í.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/2026Äê8ÔÂÁÖÇøµÀ·¿ÍÔËÕ¾³¡Í¶×Êͳ¼Æ±¨±í£¨Ô¡¢Ä걨£©.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/2026Äê8ÔÂÕ¾³¡¹ÌͶ£¨ÄÏɽ¡¢ºº¿ÚÕ¾£©.xlsx
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/2026ºþ±±Ê¡µÀ·¿ÍÔËÕ¾³¡Í¶×Êͳ¼Æ±¨8ÔÂ(¶÷Ê©ÖÝ) (1).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/Ê®ÑßÊÐ2026Äê8Ô¹̶¨×ʲúÔ±¨µç×Ó°æÍ¶×ʱí¸ñ.xlsx
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/ºþ±±Ê¡Ò˲ýÊеÀ·¿ÍÔËÕ¾³¡Í¶×ʱ¨±í£¨Ô¡¢Ä걨£©08ÔÂ.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/¾£ÃÅÊпÍÔËÕ¾³¡Í¶×Êͳ¼Æ8ÔÂ.xls(1).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/ÏåÑôÊеÀ·ÔËÊä·þÎñÖÐÐÄ2026Äê8ÔÂͶ×Ê.et
Binary files differ
docs/Ͷ×Ê/ÊäÈë/¿ÍÔË£¨¿ÍÔËÕ¾£©/8ÔÂ/£¨Ð¢¸ÐÊеÀÔËÖÐÐÄ£©202608Т¸ÐÊеÀ·¿ÍÔËÕ¾³¡Í¶×Êͳ¼ÆÔ±¨±í.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/202608---»Æ¸ÔÎïÁ÷Õ¾³¡Í¶×Ê±í£¨×îÖհ棩.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8Ô·ÝТ¸ÐÎïÁ÷ÏîĿͶ×Êͳ¼Æ±í.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8Ô·ÝÎïÁ÷£¨»õÔË£©Í¶×ÊÏîÄ¿Ã÷ϸ±í£¨»ÆÊ¯ÊУ©(1).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8ÔÂÆóÒµ»ã×Ü£¨¶õÖÝ£©.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8Ô¶÷Ê©ÖÝÎïÁ÷£¨»õÔË£©ÏîĿͶ×ÊÃ÷ϸ.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8Ôºþ±±Ê¡ÏåÑôÊн»Í¨ÎïÁ÷»ù´¡ÉèʩͶ×Êͳ¼Æ±¨±í.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/2026Äê8ÔÂÎïÁ÷»ù´¡ÉèÊ©½¨ÉèͶ×ÊÔ±¨(ËæÖÝ).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/8Ô·ÝÎïÁ÷Ô°ÖÐÐĽ¨ÉèÏîÄ¿(ÌìÃÅ).xlsx
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ÏÉÌÒÊÐÎïÁ÷԰Ͷ×Êͳ¼Æ±¨±í£¨202608£©.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ÏÌÄþÊÐ2026Äê8Ô·ÝÎïÁ÷£¨»õÔË£©ÏîĿͶ×ÊÃ÷ϸ (1).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ºþ±±Ò˲ýÊÐÎïÁ÷»ù´¡ÉèʩͶ×Êͳ¼Æ±¨±í£¨Ô¡¢Ä걨£©08ÔÂ.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ºþ±±Ê¡Ê®Ñß½»Í¨ÎïÁ÷»ù´¡ÉèʩͶ×Êͳ¼Æ»ã×Ü±í£¨Ô±¨£©£¨2026Äê8Ô£©.xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/DZ½­2026.08.xlsx
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/ÉñÅ©¼ÜÁÖÇøÎïÁ÷Ͷ×ÊÔ±¨2026.08.xlsx
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/¾£ÖÝÎïÁ÷Ͷ×Ê£¨2026Äê8Ô±¨Ê¡£© (1).xls
Binary files differ
docs/Ͷ×Ê/ÊäÈë/ÎïÁ÷£¨ÎïÁ÷Ô°Çø£©/8ÔÂ/¾£ÃÅ2026Äê08ÔÂÏîĿͶ×Ê×ܱ¨±í£¨ÎïÁ÷£©.xls
Binary files differ
docs/Éú³É»ã×Ü´ó±í/ͬÃûÆóÒµ_1-8ÔÂÀۼƶԱÈ_2026-09-19.sql
New file
@@ -0,0 +1,319 @@
-- ============================================================
-- 2025 / 2026 å¹´ 1-8 æœˆç´¯è®¡ è´§è¿é‡ã€è´§ç‰©å‘¨è½¬é‡ æ±‡æ€»ï¼ˆåŒåä¼ä¸šå£å¾„)
-- ç”Ÿæˆæ—¥æœŸï¼š2026-09-19   æ•°æ®åº“:traffic_audit(MySQL 8.0.29)
-- ------------------------------------------------------------
-- æ•°æ®æ¥æºè¡¨ï¼šh2032_enterprise_monthly
--   ã€Šé“路货物运输月度生产情况表》= äº¤ä¼ç»ŸH203-2表,企业级月报(规上企业)
--   å­—段:freight_total   è´§è¿é‡_总计(吨)
--         turnover_total  è´§ç‰©å‘¨è½¬é‡_总计(吨公里)
--         report_period   æŠ¥è¡¨æœŸï¼Œæ ¼å¼ 'YYYY-MM'
--         enterprise_name ä¼ä¸šåç§°
-- å•位换算:表内存的是「吨 / å¨å…¬é‡Œã€ï¼ŒæŠ¥è¡¨å£å¾„是「万吨 / ä¸‡å¨å…¬é‡Œã€ï¼Œ
--          æ‰€ä»¥ä¸‹é¢ç»Ÿä¸€ Ã·10000。
-- æœŸé—´å–法:1-8 æœˆ = report_period BETWEEN '2025-01' AND '2025-08'
--          ï¼ˆreport_period æ˜¯å­—符串 'YYYY-MM',直接比大小即可)
-- ä¸ºä»€ä¹ˆè¦ã€ŒåŒåä¼ä¸šå£å¾„」:
--   2025 å¹´ 1-8 æœˆæœ‰ 664 å®¶ä¼ä¸šã€2026 å¹´ 1-8 æœˆåªæœ‰ 636 å®¶ï¼Œ
--   ç›´æŽ¥æ‹¿ä¸¤å¹´æ€»æ•°ç›¸å‡ï¼Œå·®é¢é‡Œæ··ç€ã€Œä¼ä¸šæ•°é‡å˜äº†ã€çš„影响,不是真实增减。
--   æŠŠä¸¤å¹´éƒ½æŠ¥é€è¿‡çš„企业名称取交集(实测 545 å®¶ï¼‰ï¼Œä¸¤å¹´çš„企业范围才一致。
-- å®žæµ‹ç»“果(同名企业口径 545 å®¶ï¼Œ4 ä½å°æ•°ï¼‰ï¼š
--   2025 å¹´ 1-8 æœˆï¼šè´§è¿é‡ 30153.1392 ä¸‡å¨ï¼Œå‘¨è½¬é‡ 4635340.4627 ä¸‡å¨å…¬é‡Œ
--   2026 å¹´ 1-8 æœˆï¼šè´§è¿é‡ 27752.6820 ä¸‡å¨ï¼Œå‘¨è½¬é‡ 4389882.0468 ä¸‡å¨å…¬é‡Œ
--   åŒæ¯”:货运量 -7.9609%,周转量 -5.2954%
--   ï¼ˆ2026 å¹´è¿™ä¸¤ä¸ªæ•°ä¸Žã€ŠæŒç»­åœ¨è§„企业545å®¶_分市州1-8月累计运距及同比》交付件的全省行完全一致)
-- ============================================================
-- ============================================================
-- â˜… å°æ•°ä½çº¦å®šï¼ˆ2026-09-19 è¡¥å……,很重要)★
-- ------------------------------------------------------------
-- 1) è¡¨é‡Œå­˜çš„æ˜¯ã€Œå¨ / å¨å…¬é‡Œã€çš„æ•´æ•°ï¼Œå¯¼å‡ºæ—¶ Ã·10000 å˜æˆã€Œä¸‡å¨ / ä¸‡å¨å…¬é‡Œã€ã€‚
-- 2) å‡¡æ˜¯ã€è¦æ‹¿åŽ»äºŒæ¬¡è®¡ç®—ã€‘çš„åˆ—ï¼ˆå°¤å…¶æ˜¯ã€Œå‘¨è½¬é‡ Ã· è´§è¿é‡ = å¹³å‡è¿è·ã€ï¼‰ï¼Œ
--    åƒä¸‡ä¸èƒ½åœ¨ SQL é‡Œåªä¿ç•™ 2 ä½å°æ•°ï¼
--    åŽŸå› ï¼šä¿ç•™ 2 ä½ = ç²¾åº¦åˆ° 100 å¨ã€‚对货运量只有几千吨的小企业,
--    åˆ†æ¯ä¼šè¢«ç æŽ‰æœ€å¤š 1%,算出来的运距能差出好几公里。
--    å®žä¾‹ï¼šæ¹–北弘雷物流有限公司 2026 å¹´ 1-8 æœˆè´§è¿é‡ 4631 å¨
--          â†’ ä¸å–æ•´ 0.4631 ä¸‡å¨ï¼ˆè¿è· 1267.05 å…¬é‡Œï¼Œæ­£ç¡®ï¼‰
--          â†’ å– 2 ä½ 0.46   ä¸‡å¨ï¼ˆè¿è· 1275.59 å…¬é‡Œï¼Œè™šé«˜ 8.53 å…¬é‡Œï¼‰
-- 3) æ‰€ä»¥æœ¬è„šæœ¬çº¦å®šï¼š
--    Â· æ˜Žç»†ç±»æŸ¥è¯¢ï¼ˆæŸ¥è¯¢ 2、查询 7)→ å®Œå…¨ä¸å¥— ROUND,导出即原始值
--      ï¼ˆè´§è¿é‡/周转量的原始值最多 4 ä½å°æ•°ï¼Œå°±æ˜¯å…¨ç²¾åº¦ï¼›åŒæ¯”列小数位较长,
--        å«Œé•¿å¯è‡ªè¡Œåœ¨å¤–面套 ROUND(...,2));
--    Â· æ±‡æ€»ç±»ï¼ˆæŸ¥è¯¢ 1、3、5、8)→ åŒæ ·ä¿ç•™ 4 ä½å°æ•°ï¼ˆå¯¹æœ¬è¡¨æ•°æ®æ¥è¯´ 4 ä½å°±æ˜¯å…¨ç²¾åº¦ï¼Œ
--      ä¿ç•™ 2 ä½æ²¡æœ‰ä»»ä½•好处,反而会让人误以为数据就只有 2 ä½ç²¾åº¦ï¼‰ï¼›
--    Â· å¦‚果你要自己算运距/同比,建议直接用查询 7,或把 /10000 é‚£ä¸€å±‚去掉,
--      å…ˆåœ¨ Excel é‡ŒæŒ‰ã€Œå¨ã€ç®—完再除。
-- ============================================================
-- =====================================================================
-- æŸ¥è¯¢ 1:汇总一行 â€”— åŒåä¼ä¸šå£å¾„的两年累计数 + åŒæ¯”增速
-- =====================================================================
SELECT COUNT(DISTINCT e.enterprise_name)                                   AS ä¼ä¸šæ•°,
       ROUND(SUM(CASE WHEN e.report_period <= '2025-08'
                      THEN e.freight_total  ELSE 0 END) / 10000, 4)        AS è´§è¿é‡2025_万吨,
       ROUND(SUM(CASE WHEN e.report_period >= '2026-01'
                      THEN e.freight_total  ELSE 0 END) / 10000, 4)        AS è´§è¿é‡2026_万吨,
       ROUND((SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total ELSE 0 END)
            / NULLIF(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total ELSE 0 END), 0) - 1) * 100, 2)
                                                                           AS è´§è¿é‡åŒæ¯”_百分比,
       ROUND(SUM(CASE WHEN e.report_period <= '2025-08'
                      THEN e.turnover_total ELSE 0 END) / 10000, 4)        AS å‘¨è½¬é‡2025_万吨公里,
       ROUND(SUM(CASE WHEN e.report_period >= '2026-01'
                      THEN e.turnover_total ELSE 0 END) / 10000, 4)        AS å‘¨è½¬é‡2026_万吨公里,
       ROUND((SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END)
            / NULLIF(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END), 0) - 1) * 100, 2)
                                                                           AS å‘¨è½¬é‡åŒæ¯”_百分比
FROM h2032_enterprise_monthly e
-- ä¸‹é¢ä¸¤ä¸ª JOIN:只要两年 1-8 æœˆéƒ½æŠ¥é€è¿‡çš„企业(同名企业口径的核心)
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2025-01' AND '2025-08') a
  ON a.enterprise_name = e.enterprise_name
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2026-01' AND '2026-08') b
  ON b.enterprise_name = e.enterprise_name
WHERE e.report_period BETWEEN '2025-01' AND '2026-08';
-- =====================================================================
-- æŸ¥è¯¢ 2:逐企业对照明细(同名企业,两年并排),可直接导出 Excel
--   æŒ‰ 2026 å¹´è´§è¿é‡ä»Žå¤§åˆ°å°æŽ’;去掉 ORDER BY å°±æ˜¯å®Œæ•´ 545 è¡Œã€‚
-- =====================================================================
SELECT e.enterprise_name                                                            AS ä¼ä¸šåç§°,
       MAX(CASE WHEN e.report_period >= '2026-01' THEN e.region_code END)           AS åœ°åŒºä»£ç ,
       SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total  ELSE 0 END) / 10000  AS è´§è¿é‡2025_万吨,
       SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total  ELSE 0 END) / 10000  AS è´§è¿é‡2026_万吨,
       (SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total ELSE 0 END)
      - SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total ELSE 0 END)) / 10000 AS è´§è¿é‡å¢žå‡_万吨,
       (SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total ELSE 0 END)
      / NULLIF(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total ELSE 0 END), 0) - 1) * 100 AS è´§è¿é‡åŒæ¯”_百分比,
       SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END) / 10000  AS å‘¨è½¬é‡2025_万吨公里,
       SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END) / 10000  AS å‘¨è½¬é‡2026_万吨公里,
       (SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END)
      - SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END)) / 10000 AS å‘¨è½¬é‡å¢žå‡_万吨公里,
       (SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END)
      / NULLIF(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END), 0) - 1) * 100 AS å‘¨è½¬é‡åŒæ¯”_百分比
FROM h2032_enterprise_monthly e
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2025-01' AND '2025-08') a
  ON a.enterprise_name = e.enterprise_name
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2026-01' AND '2026-08') b
  ON b.enterprise_name = e.enterprise_name
WHERE e.report_period BETWEEN '2025-01' AND '2026-08'
GROUP BY e.enterprise_name
ORDER BY è´§è¿é‡2026_万吨 DESC;
-- =====================================================================
-- æŸ¥è¯¢ 3:三种口径对照 â€”— çœ‹æ¸…楚「全量」和「同名」差在哪
--   ALL_2025 / ALL_2026   : å„自年份的全部企业
--   SAME_2025 / SAME_2026 : åŒåä¼ä¸šå£å¾„(545 å®¶ï¼‰
-- =====================================================================
SELECT t.scope_type                            AS å£å¾„,
       COUNT(DISTINCT t.enterprise_name)       AS ä¼ä¸šæ•°,
       ROUND(SUM(t.freight_total)  / 10000, 4) AS è´§è¿é‡_万吨,
       ROUND(SUM(t.turnover_total) / 10000, 4) AS å‘¨è½¬é‡_万吨公里
FROM (
  SELECT 'ALL_2025' AS scope_type, enterprise_name, freight_total, turnover_total
    FROM h2032_enterprise_monthly WHERE report_period BETWEEN '2025-01' AND '2025-08'
  UNION ALL
  SELECT 'ALL_2026', enterprise_name, freight_total, turnover_total
    FROM h2032_enterprise_monthly WHERE report_period BETWEEN '2026-01' AND '2026-08'
  UNION ALL
  SELECT 'SAME_2025', e.enterprise_name, e.freight_total, e.turnover_total
    FROM h2032_enterprise_monthly e
    JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
           WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.enterprise_name = e.enterprise_name
    JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
           WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.enterprise_name = e.enterprise_name
   WHERE e.report_period BETWEEN '2025-01' AND '2025-08'
  UNION ALL
  SELECT 'SAME_2026', e.enterprise_name, e.freight_total, e.turnover_total
    FROM h2032_enterprise_monthly e
    JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
           WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.enterprise_name = e.enterprise_name
    JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
           WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.enterprise_name = e.enterprise_name
   WHERE e.report_period BETWEEN '2026-01' AND '2026-08'
) t
GROUP BY t.scope_type
ORDER BY t.scope_type;
-- =====================================================================
-- æŸ¥è¯¢ 4:差异企业名单(核对用)—— åªåœ¨ä¸€å¹´æŠ¥é€çš„企业及其累计量
--   only_in = 2025 / 2026
--   å®žæµ‹ï¼š2025 å¹´ç‹¬æœ‰ 119 å®¶ã€2026 å¹´ç‹¬æœ‰ 91 å®¶ï¼ˆ1-8 æœˆå£å¾„)
-- =====================================================================
SELECT '2025' AS only_in, e.enterprise_name AS ä¼ä¸šåç§°,
       ROUND(SUM(e.freight_total) / 10000, 2) AS è´§è¿é‡_万吨,
       ROUND(SUM(e.turnover_total) / 10000, 2) AS å‘¨è½¬é‡_万吨公里
FROM h2032_enterprise_monthly e
LEFT JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
            WHERE report_period BETWEEN '2026-01' AND '2026-08') b
       ON b.enterprise_name = e.enterprise_name
WHERE e.report_period BETWEEN '2025-01' AND '2025-08' AND b.enterprise_name IS NULL
GROUP BY e.enterprise_name
UNION ALL
SELECT '2026', e.enterprise_name,
       ROUND(SUM(e.freight_total) / 10000, 2),
       ROUND(SUM(e.turnover_total) / 10000, 2)
FROM h2032_enterprise_monthly e
LEFT JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
            WHERE report_period BETWEEN '2025-01' AND '2025-08') a
       ON a.enterprise_name = e.enterprise_name
WHERE e.report_period BETWEEN '2026-01' AND '2026-08' AND a.enterprise_name IS NULL
GROUP BY e.enterprise_name
ORDER BY only_in, è´§è¿é‡_万吨 DESC;
-- =====================================================================
-- æŸ¥è¯¢ 5:分市州「同名企业口径」两年累计对照
--   åœ°åŒºä»£ç å– 2026 å¹´é‚£æ¡è®°å½•çš„ region_code
-- =====================================================================
SELECT CASE
         WHEN region_code LIKE '4201%' THEN '武汉' WHEN region_code LIKE '4202%' THEN '黄石'
         WHEN region_code LIKE '4203%' THEN '十堰' WHEN region_code LIKE '4205%' THEN '宜昌'
         WHEN region_code LIKE '4206%' THEN '襄阳' WHEN region_code LIKE '4207%' THEN '鄂州'
         WHEN region_code LIKE '4208%' THEN '荆门' WHEN region_code LIKE '4209%' THEN '孝感'
         WHEN region_code LIKE '4210%' THEN '荆州' WHEN region_code LIKE '4211%' THEN '黄冈'
         WHEN region_code LIKE '4212%' THEN '咸宁' WHEN region_code LIKE '4213%' THEN '随州'
         WHEN region_code LIKE '4228%' THEN '恩施' WHEN region_code LIKE '429004%' THEN '仙桃'
         WHEN region_code LIKE '429005%' THEN '潜江' WHEN region_code LIKE '429006%' THEN '天门'
         WHEN region_code LIKE '429021%' THEN '林区' ELSE '其他' END           AS å¸‚å·ž,
       COUNT(DISTINCT d.enterprise_name)                                       AS åŒåä¼ä¸šæ•°,
       ROUND(SUM(d.freight_2025) / 10000, 4)                                   AS è´§è¿é‡2025_万吨,
       ROUND(SUM(d.freight_2026) / 10000, 4)                                   AS è´§è¿é‡2026_万吨,
       ROUND(SUM(d.turnover_2025) / 10000, 4)                                  AS å‘¨è½¬é‡2025_万吨公里,
       ROUND(SUM(d.turnover_2026) / 10000, 4)                                  AS å‘¨è½¬é‡2026_万吨公里
FROM (
  SELECT e.enterprise_name,
         MAX(CASE WHEN e.report_period >= '2026-01' THEN e.region_code END)    AS region_code,
         SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total  ELSE 0 END) AS freight_2025,
         SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total  ELSE 0 END) AS freight_2026,
         SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END) AS turnover_2025,
         SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END) AS turnover_2026
  FROM h2032_enterprise_monthly e
  JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
         WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.enterprise_name = e.enterprise_name
  JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
         WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.enterprise_name = e.enterprise_name
  WHERE e.report_period BETWEEN '2025-01' AND '2026-08'
  GROUP BY e.enterprise_name
) d
GROUP BY å¸‚å·ž
ORDER BY è´§è¿é‡2026_万吨 DESC;
-- =====================================================================
-- æŸ¥è¯¢ 6:数据体检 â€”— åŒåä¼ä¸šé‡Œæœˆä»½ä¸è¶³ 8 ä¸ªæœˆçš„(累计数会偏小,比对时注意)
--   æ­£å¸¸ï¼š2025 å¹´ 1-8 æœˆ 8 æ¡ + 2026 å¹´ 1-8 æœˆ 8 æ¡
--   å®žæµ‹ï¼šæ— å¼‚常企业,全部 545 å®¶ä¸¤å¹´å„ 8 ä¸ªæœˆé½å…¨
-- =====================================================================
SELECT e.enterprise_name AS ä¼ä¸šåç§°,
       SUM(CASE WHEN e.report_period BETWEEN '2025-01' AND '2025-08' THEN 1 ELSE 0 END) AS è®°å½•æ•°2025,
       SUM(CASE WHEN e.report_period BETWEEN '2026-01' AND '2026-08' THEN 1 ELSE 0 END) AS è®°å½•æ•°2026
FROM h2032_enterprise_monthly e
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.enterprise_name = e.enterprise_name
JOIN (SELECT DISTINCT enterprise_name FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.enterprise_name = e.enterprise_name
WHERE e.report_period BETWEEN '2025-01' AND '2026-08'
GROUP BY e.enterprise_name
HAVING è®°å½•æ•°2025 <> 8 OR è®°å½•æ•°2026 <> 8;
-- =====================================================================
-- æŸ¥è¯¢ 7:企业明细导出(推荐用这版,546 å®¶ï¼‰
--   ä¸ŽæŸ¥è¯¢ 2 çš„区别:匹配键用「统一社会信用代码」而不是企业名称,
--   å¤šè¦†ç›– 1 å®¶æ”¹åä¼ä¸šï¼ˆ91420112558443820B:
--   2025-01~2025-09 å«ã€Œæ¹–北三峡富烨绿电供应链有限公司」,
--   2025-10 èµ·å«ã€Œæ¹–北长峡富烨绿电供应链有限公司」),
--   æŸ¥è¯¢ 2 æŒ‰åç§°åŒ¹é…ä¼šæŠŠè¿™å®¶ä¸¤å¹´éƒ½æ¼æŽ‰ï¼Œä¸”同时计入两年「独有企业」名单。
--   è¾“出列已按导出习惯排好,可直接粘进 Excel;按 2026 å¹´è´§è¿é‡é™åºã€‚
--   æç¤ºï¼šæ˜Žç»†åˆ—不套 ROUND(全精度,货运量/周转量最多 4 ä½å°æ•°ï¼‰ï¼Œ
--         ä¸ŽæŸ¥è¯¢ 8 çš„ 2 ä½åˆè®¡ä¼šæœ‰ 0.01 çº§å°¾å·®ï¼Œå±žæ­£å¸¸ã€‚
-- =====================================================================
SELECT d.credit_code                                                       AS ç»Ÿä¸€ç¤¾ä¼šä¿¡ç”¨ä»£ç ,
       d.name_2026                                                         AS ä¼ä¸šåç§°,
       d.name_2025                                                         AS åç§°2025,
       IF(d.name_2025 <> d.name_2026, '是', '')                            AS æ˜¯å¦æ”¹å,
       CASE
         WHEN d.region_code LIKE '4201%' THEN '武汉' WHEN d.region_code LIKE '4202%' THEN '黄石'
         WHEN d.region_code LIKE '4203%' THEN '十堰' WHEN d.region_code LIKE '4205%' THEN '宜昌'
         WHEN d.region_code LIKE '4206%' THEN '襄阳' WHEN d.region_code LIKE '4207%' THEN '鄂州'
         WHEN d.region_code LIKE '4208%' THEN '荆门' WHEN d.region_code LIKE '4209%' THEN '孝感'
         WHEN d.region_code LIKE '4210%' THEN '荆州' WHEN d.region_code LIKE '4211%' THEN '黄冈'
         WHEN d.region_code LIKE '4212%' THEN '咸宁' WHEN d.region_code LIKE '4213%' THEN '随州'
         WHEN d.region_code LIKE '4228%' THEN '恩施' WHEN d.region_code LIKE '429004%' THEN '仙桃'
         WHEN d.region_code LIKE '429005%' THEN '潜江' WHEN d.region_code LIKE '429006%' THEN '天门'
         WHEN d.region_code LIKE '429021%' THEN '林区' ELSE '其他' END       AS å¸‚å·ž,
       d.region_code                                                       AS åœ°åŒºä»£ç ,
       d.freight_2025  / 10000                                             AS è´§è¿é‡2025_万吨,
       d.freight_2026  / 10000                                             AS è´§è¿é‡2026_万吨,
       (d.freight_2026 - d.freight_2025) / 10000                           AS è´§è¿é‡å¢žå‡_万吨,
       (d.freight_2026 / NULLIF(d.freight_2025, 0) - 1) * 100              AS è´§è¿é‡åŒæ¯”_百分比,
       d.turnover_2025 / 10000                                             AS å‘¨è½¬é‡2025_万吨公里,
       d.turnover_2026 / 10000                                             AS å‘¨è½¬é‡2026_万吨公里,
       (d.turnover_2026 - d.turnover_2025) / 10000                         AS å‘¨è½¬é‡å¢žå‡_万吨公里,
       (d.turnover_2026 / NULLIF(d.turnover_2025, 0) - 1) * 100            AS å‘¨è½¬é‡åŒæ¯”_百分比
FROM (
  SELECT e.unified_credit_code AS credit_code,
         -- 2026 å¹´ç”¨çš„名字(改名后取新名)、2025 å¹´ç”¨çš„名字,用于标记改名
         MAX(CASE WHEN e.report_period >= '2026-01' THEN e.enterprise_name END) AS name_2026,
         MAX(CASE WHEN e.report_period <= '2025-08' THEN e.enterprise_name END) AS name_2025,
         MAX(CASE WHEN e.report_period >= '2026-01' THEN e.region_code END)     AS region_code,
         SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total  ELSE 0 END) AS freight_2025,
         SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total  ELSE 0 END) AS freight_2026,
         SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END) AS turnover_2025,
         SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END) AS turnover_2026
  FROM h2032_enterprise_monthly e
  JOIN (SELECT DISTINCT unified_credit_code c FROM h2032_enterprise_monthly
         WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.c = e.unified_credit_code
  JOIN (SELECT DISTINCT unified_credit_code c FROM h2032_enterprise_monthly
         WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.c = e.unified_credit_code
  WHERE e.report_period BETWEEN '2025-01' AND '2026-08'
  GROUP BY e.unified_credit_code
) d
ORDER BY è´§è¿é‡2026_万吨 DESC;
-- =====================================================================
-- æŸ¥è¯¢ 8:查询 7 çš„合计行(导出明细后用来对总数,546 å®¶å£å¾„)
--   2025 å¹´ 1-8 æœˆï¼šè´§è¿é‡ 30162.9872 ä¸‡å¨ã€å‘¨è½¬é‡ 4637038.5803 ä¸‡å¨å…¬é‡Œ
--   2026 å¹´ 1-8 æœˆï¼šè´§è¿é‡ 27764.8812 ä¸‡å¨ã€å‘¨è½¬é‡ 4392984.8116 ä¸‡å¨å…¬é‡Œ
-- =====================================================================
SELECT COUNT(DISTINCT e.unified_credit_code)                              AS ä¼ä¸šæ•°,
       ROUND(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.freight_total  ELSE 0 END) / 10000, 4) AS è´§è¿é‡2025_万吨,
       ROUND(SUM(CASE WHEN e.report_period >= '2026-01' THEN e.freight_total  ELSE 0 END) / 10000, 4) AS è´§è¿é‡2026_万吨,
       ROUND(SUM(CASE WHEN e.report_period <= '2025-08' THEN e.turnover_total ELSE 0 END) / 10000, 4) AS å‘¨è½¬é‡2025_万吨公里,
       ROUND(SUM(CASE WHEN e.report_period >= '2026-01' THEN e.turnover_total ELSE 0 END) / 10000, 4) AS å‘¨è½¬é‡2026_万吨公里
FROM h2032_enterprise_monthly e
JOIN (SELECT DISTINCT unified_credit_code c FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2025-01' AND '2025-08') a ON a.c = e.unified_credit_code
JOIN (SELECT DISTINCT unified_credit_code c FROM h2032_enterprise_monthly
       WHERE report_period BETWEEN '2026-01' AND '2026-08') b ON b.c = e.unified_credit_code
WHERE e.report_period BETWEEN '2025-01' AND '2026-08';
-- =====================================================================
-- ä¸‰ã€æ€Žä¹ˆæŠŠæŸ¥è¯¢ 7 çš„结果导出来
-- ---------------------------------------------------------------------
-- æ–¹å¼ä¸€ï¼šå‘½ä»¤è¡Œå¯¼å‡ºï¼ˆè¾“出制表符分隔的 .tsv,Excel åŒå‡»å³å¯åˆ†åˆ—,最省事)
--   mysql --host=127.0.0.1 --port=3308 --user=root --password=123456 ^
--         --database=traffic_audit --default-character-set=utf8mb4 --batch --raw ^
--         --execute="这里整段粘贴查询 7 çš„ SQL(含最外层分号之前的全部内容)" ^
--         > D:\临时\企业明细_546å®¶_2025-2026å¹´1-8月.tsv
--   æ³¨æ„ 1:一定要带 --default-character-set=utf8mb4,否则中文列名/企业名会变乱码。
--   æ³¨æ„ 2:导出的 .tsv æ˜¯ã€ŒUTF-8 æ—  BOM」,部分人的 Excel ç›´æŽ¥åŒå‡»ä¼šæ˜¾ç¤ºä¹±ç ï¼Œ
--          è¯·æ”¹ç”¨ Excel çš„「数据 â†’ ä»Žæ–‡æœ¬/CSV」导入并选 UTF-8 ç¼–码,
--          æˆ–直接用下面的方式二导出成 xlsx(最不容易出问题)。
--
-- æ–¹å¼äºŒï¼šæŸ¥è¯¢å·¥å…·å¯¼å‡ºï¼ˆæŽ¨èç»™ä¸ç†Ÿå‘½ä»¤è¡Œçš„场景)
--   åœ¨ Navicat / MySQL Workbench / DBeaver é‡Œç›´æŽ¥æ‰§è¡ŒæŸ¥è¯¢ 7,
--   å³é”®ç»“果网格 â†’「导出结果」→ é€‰ xlsx æˆ– csv å³å¯ã€‚
--
-- æ–¹å¼ä¸‰ï¼šMySQL æœåŠ¡ç«¯ç›´æŽ¥å†™æ–‡ä»¶ï¼ˆä¸€èˆ¬ä¸ç”¨ï¼‰
--   éœ€è¦æœåŠ¡ç«¯ secure_file_priv å…è®¸ç›®æ ‡ç›®å½•,且路径是「服务器上」的路径:
--   SELECT ... INTO OUTFILE 'D:/tmp/freight_detail.csv'
--     FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n';
--   å…ˆæŸ¥ secure_file_priv:SHOW VARIABLES LIKE 'secure_file_priv';
docs/Éú³É»ã×Ü´ó±í/Éú³É_µÀ·ÔËÊäÁ¿»ã×ܱí.xlsx
Binary files differ
docs/ÎÊÌâ»ã×Ü/Öпھ¶ÅÅÃûͬ±ÈÓë³ÇÊпÍÔËÁдíλ_¸ùÒòÓ볤Ч·½°¸_2026-09-18.md
New file
@@ -0,0 +1,195 @@
# ä¸­å£å¾„排名「同比不对」+ åŸŽå¸‚客运页列错位:根因与长效方案(2026-09-18)
> ç»“论先行:
> 1. **中口径排名的增速错,不是公式错,是「去年同期基数残缺也照算」。** 2025 å¹´ä¸‰å¤„数据缺失/污染,被静默当成 0 æˆ–错值,全省 1-8 æœˆåŸºæ•°åªæœ‰ 18131.0(应为 29796.71),所以 2026 ç´¯è®¡åŒæ¯”算出 **+73.89%**(真值 **+5.81%**),「增速排名」整块不可信。
> 2. **方案一(把城市客运 T åˆ—分母 AJ æ”¹æˆ AK)长远不可行**:它只对「8 æœˆã€è¿™ä¸€ä¸ªæŠ¥è¡¨æœŸæˆç«‹ï¼Œ9 æœˆæŠ¥è¡¨æœŸè¦ 1-9 æœˆç´¯è®¡ï¼Œåˆ†æ¯è¿˜å¾—再手改母版——正是要消灭的「每月改模板」。
> 3. æ­£ç¡®åšæ³•是三条腿一起改:**数据补全(治本)+ åŒæ¯”计算带完备性校验(防复发)+ åŸŽå¸‚客运页结构归一(去特例)**。
证据文件:`_tmp\_qa_out\step3g_summary.xlsx`、`step3g_midRank.xlsx`、`step3g_midDetail.xlsx`、`_now_rank.txt`、`_ding_rank.txt`、`_ding_mid_head.txt`、`_mother_rank.txt`。
业务基线(人工定稿):`D:\05_数据分类\汇总表\8月汇总定稿\2026年8月客运量、货运量定稿.xlsx`。
---
## ä¸€ã€ä¸­å£å¾„排名同比为什么不对(已逐项验证)
### 1.1 çŽ°è±¡ï¼ˆ2026-08 æŠ¥è¡¨æœŸï¼‰
| ä½ç½® | ç¨‹åºç®—出 | å®šç¨¿/正确值 | åå·® |
|---|---|---|---|
| ç´¯è®¡å— å…¨çœ åŒæ¯”(M3) | **+73.89%** | **+5.81%** | å·® 68 ä¸ªç™¾åˆ†ç‚¹ |
| ç´¯è®¡å— æ­¦æ±‰ åŒæ¯”(M4) | **+12.07%** | **+4.65%** | å·® 7.4 ä¸ªç™¾åˆ†ç‚¹ |
| ç´¯è®¡å— é»„石 | **+105.41%** | +7.85% | â€” |
| ç´¯è®¡å— åå ° | **+192.30%** | +2.17% | â€” |
| ç´¯è®¡å— è¥„阳 | **+107.07%** | +5.63% | â€” |
| ç´¯è®¡å— å’¸å® | **+189.54%** | +17.00% | â€” |
| ç´¯è®¡å— æ½œæ±Ÿ | **+766.85%** | âˆ’2.86% | â€” |
| å½“月块 å…¨çœ åŒæ¯”(M24) | **+67.63%** | âˆ’0.67% | â€” |
**值本身是对的**(累计 31528.0607、当月 4003.5701 ä¸Žå®šç¨¿å®Œå…¨ä¸€è‡´ï¼‰ï¼Œ**只有同比错** â€”— è¿™æ­£æ˜¯ã€Œåˆ†å­å¯¹ã€åˆ†æ¯æ®‹ã€çš„典型特征。
### 1.2 åŸºæ•°è´¦ï¼ˆå†³å®šæ€§è¯æ®ï¼‰
定稿 2025 å¹´ 1-8 æœˆä¸­å£å¾„累计 = **29796.71**(万元人次),逐项:
| ç»´åº¦ | 1月 | 2月 | 3月 | 4月 | 5月 | 6月 | 7月 | 8月 | 1-8月合计 |
|---|---|---|---|---|---|---|---|---|---|
| å…¬è·¯ç­çº¿ | 1688.1442 | 1719.8742 | 1721.8891 | 1824.67 | 1811.8188 | 1718.0442 | 1781.8881 | 1784.7773 | 14051.1159 |
| åŸŽé™…城乡公交 | 1143.83 | 1146.53 | 1242.29 | 1288.71 | 1385.12 | 1377.95 | 1344.24 | 1350.08 | **10278.75** |
| åŸŽé™…城乡巡游出租 | 409.54 | 448.64 | 417.98 | 429.77 | 494.11 | 438.88 | 566.86 | 603.64 | 3809.42 |
| åŸŽé™…城乡网约车 | 142.54 | 152.48 | 167.08 | 194.78 | 230.58 | 206.93 | 271.02 | 292.02 | **1657.43** |
| **合计** | 3384.0542 | 3467.5242 | 3549.2391 | 3737.93 | 3921.6288 | 3741.8042 | 3964.0081 | 4030.5173 | **29796.71** |
程序实际用到的基数 = 31528.0606 / 1.7389 = **18131.0**。
差额 11665.7 = 10278.75(公交)+ 1514.89(网约车 2-8 æœˆï¼‰âˆ’ 127.98(出租 6 æœˆå¤šç®—)→ å®Œå…¨å¯¹å¾—上。
### 1.3 ä¸‰å¤„数据缺陷(逐条已查实)
**缺陷① `city_bus_monthly.passenger_chengxiang` åœ¨ 2025 å¹´å…¨éƒ¨ä¸º 0/负**
```sql
SELECT report_period, SUM(passenger_chengxiang), SUM(passenger_volume-passenger_city)
FROM city_bus_monthly WHERE report_period LIKE '2025-%' GROUP BY report_period;
-- 2025-01: -0.341  vs  1143.83   â† å­˜å‚¨åˆ—是 0,实际应为 1143.83
-- 2025-08: -0.114  vs  1350.08
-- 2026-01: 1391.19 vs  1391.19   â† 2026 æ­£å¸¸
```
- åŽæžœï¼šä¸­å£å¾„公交维度 2025 å…¨å¹´ä¸º 0 â†’ 1-8 æœˆå°‘ 10278.75 ä¸‡äººæ¬¡ï¼›å¯¼å‡ºçš„「中口径明细」公交累计同比直接算成 **−28577.71%**(分母 âˆ’0.407)。
- å…œåº•关系已验证逐月与定稿一致:**城际城乡 = æ€»å®¢è¿é‡ âˆ’ åŸŽå¸‚内客运量**(例:2025-01 15079.24−13935.41=1143.83 âœ“)。
**缺陷② `wyc_order_monthly.pin_*` åœ¨ 2025-02~08 ä¸º NULL**
```sql
SELECT report_period, pin_k FROM wyc_order_monthly WHERE report_period LIKE '2025%';
-- 2025-01: 2467.79
-- 2025-02 .. 2025-08: NULL   â† ç¼º
-- 2025-09 .. 2025-12: æœ‰å€¼
-- 2025-01 çš„ 2467.79 ä¸Ž wyc_total_monthly å®Œå…¨ç›¸åŒï¼ˆåŒæºï¼‰
```
- `WycSplitCalc.loadMonthlyInputFromDb()` åªè¯»è®¢å•表的 pin åˆ—(`WycSplitCalc.java:258-261`),pin è¯»æˆ 0 â†’ `calc()` åœ¨ `WycSplitCalc.java:100-102` æŠ›å¼‚常 â†’ `loadMidClassMap()` çš„ `catch` ç›´æŽ¥ `continue`(`ReportExportService.java:2429-2431`)→ è¯¥æœˆç½‘约车维度整月丢失。
- åŽæžœï¼šç½‘约车城乡 2025 åªç®—了 1 æœˆï¼ˆ142.54),2-8 æœˆç¼ºå¤± 1514.89 ä¸‡äººæ¬¡ã€‚
- å¦æ³¨ï¼š`wyc_total_monthly`(pin ä¸“表)里 2025-02~08 **数据是全的**,只是没同步到订单表。
**缺陷③ `city_taxi_monthly` 2025-06 æ˜¯ 2025-07 çš„副本**
```sql
-- é€å¸‚州比对 2025-06 ä¸Ž 2025-07:17 ä¸ªå¸‚州客运量/周转量 å®Œå…¨é€å€¼ç›¸åŒ
-- å…¨çœ 2025-06 ç¨‹åºå€¼ 566.86,定稿 438.88,多算 127.98
```
- å±žäºŽé‡å¤å¯¼å…¥/错期导入,需要用正确的 6 æœˆæºæ–‡ä»¶é‡å¯¼ã€‚
### 1.4 å·²æŽ’除的误判
- æ¯ç‰ˆ/定稿的中口径公式**没有错**(早前「引错页」是控制台中文乱码误判)。
- `loadMidClassMap()` ç›®å‰**四维都在**(班线 / å…¬äº¤ / å·¡æ¸¸å‡ºç§Ÿ / ç½‘约车,`ReportExportService.java:2351-2437`);今日《汇总表三条主线修复方案》里「只装了班线+公交两维」的说法已过期。
- `中口径排名` çš„取值口径(维度 0 = å››ç»´åˆè®¡ï¼‰**与定稿一致**,无需改口径。
---
## äºŒã€åŸŽå¸‚客运页列错位(与方案一相关)
### 2.1 æ¯ç‰ˆçŽ°çŠ¶ï¼ˆ`docs\生成汇总大表\2026å¹´8月道路运输量汇总表.xlsx` â†’ åŸŽå¸‚客运页,第 2 è¡Œè¡¨å¤´ï¼‰
| åˆ— | è¡¨å¤´ | è¯´æ˜Ž |
|---|---|---|
| V/X/Z/AB | 2025å¹´1月/2月/3月/4月 | æ–‡å­—正常 |
| **AD / AF / AH** | **45778 / 45809 / 45839** | **日期序列号**,不是「2025å¹´5/6/7月」 |
| **AJ** | **2025å¹´1-7月累计** | **夹层辅助列,插在了 2025 æœˆåº¦å—中间** |
| **AK** | **45870** | **日期序列号**,才是真正的「2025å¹´8月」 |
| AL | 8月同比 | å¯¹åº” AK |
2026 ä¾§åŒæ ·è„ï¼šG/I/K/M/O/Q = 46082 / 46113 / 46143 / 46174 / 46204 / 46235(日期序列号)。
累计同比公式:
```
城市客运!T4 = S4/(V4+X4+Z4+AB4+AD4+AF4+AH4+AJ4)-1     â† åˆ†æ¯ = (1-7月) + (1-7月累计) = 2×(1-7月)
其它 8 é¡µ!T4 = S4/SUM(V4+X4+Z4+AB4+AD4+AF4+AH4+AJ4)-1  â† åˆ†æ¯ = 1-8月累计,正确
```
即:**只有城市客运页**因为 AJ å¤¹å±‚列,分母少了「2025å¹´8月」。
### 2.2 ä¸ºä»€ä¹ˆã€Œæ–¹æ¡ˆä¸€ã€é•¿è¿œä¸è¡Œ
| # | é—®é¢˜ | è¯´æ˜Ž |
|---|---|---|
| 1 | **只对 8 æœˆæˆç«‹** | 9 æœˆæŠ¥è¡¨æœŸè¦ 1-9 æœˆç´¯è®¡ï¼Œåˆ†æ¯éœ€å†åŠ  AM(真正 2025å¹´9月);10 æœˆå†åŠ â€¦â€¦æ¯ä¸ªæœˆéƒ½è¦æ‰‹æ”¹æ¯ç‰ˆå…¬å¼ã€‚è¿™å°±æ˜¯ã€Œæ¯ä¸ªæœˆåšæ¨¡æ¿ã€çš„å˜ä½“ã€‚ |
| 2 | **夹层列会让所有「按列序号」的处理整体错位 1 åˆ—** | `applySummaryReferenceLayout()`(`ReportExportService.java:3535`)是按**列序号**套用列宽/隐藏标记的。你已经在参照件里删掉 AJ â†’ ç”Ÿæˆä»¶ä»Ž AJ ä¹‹åŽæ‰€æœ‰åˆ—的列宽/隐藏标记都错位。 |
| 3 | **表头本身不是文字** | AD/AF/AH/AK æ˜¯æ—¥æœŸåºåˆ—号,任何「按表头文字匹配列」的长效方案在这个页会直接失效。所以必须先规范表头。 |
| 4 | **参照件与母版结构不一致** | åˆ  AJ åŽï¼Œå‚ç…§ä»¶ 36 ä¸ª `#REF!`(T4:T39),列宽映射基准也变了。 |
---
## ä¸‰ã€é•¿æ•ˆæ–¹æ¡ˆ
### A. æ•°æ®ä¾§ï¼ˆæ²»æœ¬ï¼Œä¸€æ¬¡åšå®Œï¼‰
| # | åŠ¨ä½œ | å…·ä½“做法 | éªŒæ”¶ |
|---|---|---|---|
| A1 | å›žå¡« 2025 å…¨å¹´å…¬äº¤ã€ŒåŸŽé™…城乡」 | `UPDATE city_bus_monthly SET passenger_chengxiang = passenger_volume - passenger_city WHERE report_period LIKE '2025-%' AND (passenger_chengxiang IS NULL OR passenger_chengxiang <= 0)`;周转量同法 | 2025 å„月全省 = 1143.83/1146.53/1242.29/1288.71/1385.12/1377.95/1344.24/1350.08… |
| A2 | å›žå¡« 2025-02~08 ç½‘约车 pin | ä»Ž `wyc_total_monthly` åŒæ­¥ pin_k/pin_ck/pin_z/pin_cz åˆ° `wyc_order_monthly` åŒæœŸ | 2025 å…¨å¹´ pin é½å…¨ |
| A3 | é‡å¯¼ 2025-06 å‡ºç§Ÿ | ç”¨æ­£ç¡®çš„ 6 æœˆæºæ–‡ä»¶é‡å¯¼ `city_taxi_monthly` 2025-06 | å…¨çœ = 438.88(现 566.86) |
### B. ä»£ç ä¾§ï¼ˆé˜²å¤å‘,核心是「不齐全就不算」)
| # | æ”¹åŠ¨ç‚¹ | å†…容 |
|---|---|---|
| B1 | `loadMidClassMap()` dim2 | å­˜å‚¨çš„「城际城乡」≤0 æ—¶ï¼Œç”¨ `总量 âˆ’ åŸŽå¸‚内` å…œåº•(`city_bus_monthly` ä¸€è¡Œå†…相减后再累加) |
| B2 | `WycSplitCalc.loadMonthlyInputFromDb()` | è®¢å•表 pin å…¨ç©ºæ—¶å›žè½ `wyc_total_monthly`(本例 2025-02~08 å³å¯è‡ªåŠ¨ä¿®å¥½ï¼‰ï¼›ä¸¤è¾¹éƒ½ç¼ºæ‰æŠ›å¼‚å¸¸ |
| B3 | `midCumClass()` / `midClassVal()` | è¿”回值改为「值 + å‘½ä¸­æœˆä»½æ•°ã€ï¼›**同比只在「去年同月齐全」时计算**,不齐全一律留空(现在缺月被静默当 0 â†’ åŸºæ•°å˜å° â†’ åŒæ¯”虚高) |
| B4 | å¯¼å‡ºå‰ç½®ã€ŒåŸºæ•°ä½“检」 | ä¸‰æ¡è§„则:①去年同月该维度=0;②某月逐市州值与相邻月完全相同(重复导入特征);③去年同月市州行数 < 17。命中则:写后端日志 + é¡µé¢å¼¹çª— + ç”Ÿæˆä»¶é™„一张《数据缺失清单》页 |
| B5 | æ—¥å¿— | `loadMidClassMap()` é‡Œ `catch â†’ continue` æ”¹æˆè®°å½•「期 + å¼‚常原因」清单,随导出日志输出(现在完全静默) |
### C. ç»“构侧(城市客运页归一,消除特例)
| # | åŠ¨ä½œ |
|---|---|
| C1 | æŠŠ AJ(2025å¹´1-7月累计)**移出 2025 æœˆåº¦å—**(和 U åˆ—这类辅助列放一起,或直接删除),使城市客运页 V..AJ = 2025å¹´1月…8月,与其它 8 é¡µå®Œå…¨åŒæž„。**在 WPS/Excel é‡Œæ•´åˆ—删**,让全表引用自动调整。 |
| C2 | è¡¨å¤´æ–‡å­—化:G/I/K/M/O/Q、AD/AF/AH/AK ç”±æ—¥æœŸåºåˆ—号改成「2026å¹´3月…」「2025å¹´5月/6月/7月/8月」 |
| C3 | ç´¯è®¡åŒæ¯”分母不写死列清单:由程序**每次按表头定位「去年 M æœˆã€åˆ—**后重写公式(`=S4/SUM(V4:去年M月列4)-1`,注意只累加奇数列),9 æœˆ/10 æœˆè‡ªåŠ¨è·Ÿç€èµ°ï¼Œæ¯ç‰ˆä¸ç”¨å†åŠ¨ |
| C4 | `applySummaryReferenceLayout()` æ”¹ä¸º**按表头文字匹配列**再套列宽/隐藏;参照件加减列不再错位 |
### D. æŠ¥è¡¨ä¾§
| # | åŠ¨ä½œ |
|---|---|
| D1 | ã€Œå¢žé€ŸæŽ’名」只在同比齐全时排名;否则该块标注「去年同期基数缺失,暂不排名」,避免用假增速排出假名次 |
---
## å››ã€éªŒæ”¶åŸºçº¿ï¼ˆ2026-08 æŠ¥è¡¨æœŸï¼Œä¸­å£å¾„排名累计块)
| å¸‚å·ž | åº”为(定稿) | çŽ°åœ¨ï¼ˆç¨‹åºï¼‰ |
|---|---|---|
| å…¨çœ | +5.81% | **+73.89%** |
| æ­¦æ±‰ | +4.65% | **+12.07%** |
| é»„石 | +7.85% | **+105.41%** |
| åå ° | +2.17% | **+192.30%** |
| å®œæ˜Œ | âˆ’15.62% | +4.28% |
| è¥„阳 | +5.63% | **+107.07%** |
| è†å·ž | +36.30% | +42.74% |
| é»„冈 | +7.64% | **+147.99%** |
| å’¸å® | +17.00% | **+189.54%** |
| æ©æ–½ | +13.78% | +55.88% |
| ä»™æ¡ƒ | +17.23% | **+241.89%** |
| æ½œæ±Ÿ | âˆ’2.86% | **+766.85%** |
| å¤©é—¨ | +8.99% | **+282.34%** |
| æž—区 | âˆ’34.87% | âˆ’32.18% |
其余验收点:
- `中口径明细` å…¬äº¤è¡Œç´¯è®¡åŒæ¯”不再出现 âˆ’28577% è¿™ç§æ•°ï¼›
- `城市客运` é¡µç´¯è®¡åŒæ¯”与该页「城市汇总」口径一致(不再是 âˆ’43% å¯¹ +0.12%);
- ç‹¬ç«‹å¯¼å‡ºçš„《生成_中口径排名》与汇总大表「中口径排名」页逐格一致。
---
## äº”、建议执行顺序
1. **A1/A2/A3 æ•°æ®å›žå¡«**(半小时内可完成,做完中口径排名同比立即正确);
2. **B2、B1 ä»£ç å…œåº•**(防止同类缺失再次静默生效);
3. **B3、B4、B5 å®Œå¤‡æ€§æ ¡éªŒ**(长效防复发 + æ—¥å¿—可视);
4. **C1~C4 åŸŽå¸‚客运页归一**(改了母版,需要和业务确认后一次性做,改完 9 æœˆæŠ¥è¡¨æœŸä¸ç”¨å†æ‰‹æ”¹ï¼‰ï¼›
5. **D1 æŠ¥è¡¨æŽªè¾ž**。
stop-dev.ps1
New file
@@ -0,0 +1,57 @@
<#
  ä¸€é”®åœæ­¢å‰åŽç«¯ï¼ˆä¸Ž start-dev.ps1 é…å¥—)
  ç”¨æ³•:powershell -NoProfile -ExecutionPolicy Bypass -File stop-dev.ps1
  è¯´æ˜Žï¼š
  - åªåœæœ¬é¡¹ç›®ç›¸å…³è¿›ç¨‹ï¼šcmd.exe /c mvn.cmd ... spring-boot:run、cmd.exe /c npm.cmd run serve,
    ä»¥åŠå®ƒä»¬çš„子进程(java / node / vue-cli-service),按进程树 taskkill /T /F;
  - å…œåº•再按命令行特征精确匹配 java(TrafficAuditApplication) ä¸Ž node(vue-cli-service) çš„孤儿进程;
  - ä¸ç¢°å…¶å®ƒ node/java è¿›ç¨‹ï¼ˆä¾‹å¦‚ Codex çš„ node_repl)与用户自己开的 cmd çª—口;
  - ç»“束后检查 8090/8080 æ˜¯å¦å·²é‡Šæ”¾ã€‚
#>
$ErrorActionPreference = 'Continue'
function Test-PortListening($port) {
  try { return [bool](Get-NetTCPConnection -LocalPort $port -State Listen -ErrorAction Stop) }
  catch { return $false }
}
function Stop-Tree($label, $procId) {
  Write-Host ("{0}:停止进程树 PID={1}" -f $label, $procId)
  & taskkill.exe /T /F /PID $procId 2>&1 | ForEach-Object { if ($_ -and $_ -notmatch '^SUCCESS') { "    $_" } }
}
# ---------- 1) æŒ‰ã€Œå¯åŠ¨ç”¨çš„ cmd çˆ¶è¿›ç¨‹ã€æ•´æ ‘结束 ----------
$roots = @(
  @{ Label = '后端'; Pattern = 'spring-boot:run' },
  @{ Label = '前端'; Pattern = 'npm.cmd run serve' }
)
$found = $false
$cmdProcs = Get-CimInstance Win32_Process -Filter "Name='cmd.exe'" -ErrorAction SilentlyContinue
foreach ($r in $roots) {
  $hits = @($cmdProcs | Where-Object { $_.CommandLine -and $_.CommandLine -like ('*' + $r.Pattern + '*') })
  if ($hits.Count -eq 0) { Write-Host ("{0}:未发现启动进程(可能已停止)" -f $r.Label); continue }
  $found = $true
  foreach ($h in $hits) { Stop-Tree $r.Label $h.ProcessId }
}
# ---------- 2) å…œåº•:孤儿 java / node ----------
$orphans = @(
  @{ Label = '后端(java å…œåº•)'; Name = 'java.exe'; Pattern = 'TrafficAuditApplication' },
  @{ Label = '前端(node å…œåº•)'; Name = 'node.exe'; Pattern = 'vue-cli-service' },
  @{ Label = '前端(inner cmd å…œåº•)'; Name = 'cmd.exe'; Pattern = 'vue-cli-service serve' }
)
foreach ($o in $orphans) {
  $hits = @(Get-CimInstance Win32_Process -Filter ("Name='" + $o.Name + "'") -ErrorAction SilentlyContinue |
            Where-Object { $_.CommandLine -and $_.CommandLine -like ('*' + $o.Pattern + '*') })
  foreach ($h in $hits) { $found = $true; Stop-Tree $o.Label $h.ProcessId }
}
if (-not $found) { Write-Host '没有发现需要停止的前后端进程。' }
# ---------- 3) æ ¡éªŒç«¯å£ ----------
Start-Sleep -Seconds 4
foreach ($port in 8090, 8080) {
  if (Test-PortListening $port) { Write-Host ("端口 {0}:仍在监听(未完全停止,请重跑一次)" -f $port) }
  else { Write-Host ("端口 {0}:已释放" -f $port) }
}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -2465,10 +2465,10 @@
            }
            if (name == null || name.trim().isEmpty()) continue;
            String nt = name.trim().replaceAll("[\r\n]+", "");
            if (nt.contains("合计") || nt.contains("总计")) continue;
            String ntFlat = nt.replaceAll("\\s+", "");
            if (ntFlat.contains("合计") || ntFlat.contains("总计") || ntFlat.contains("小计")) continue;
            if (nt.matches("^[一二三四五六七八九十]+、.*")) continue;
            if (nt.matches("^([一二三四五六七八九十]+).*")) continue;
            if (nt.replace(" ", "").matches(".*小\\s*计.*")) continue;
            if (nt.startsWith("填报") || nt.startsWith("单位负责人") || nt.matches("^\\d+、.*")) continue;
            if (hasSeq) {
                if (seq == null || seq.trim().isEmpty()) {
@@ -2530,7 +2530,8 @@
            }
            if (!hasName) continue;
            Map<Integer, String> colTexts = new HashMap<>();
            for (int rr = r; rr <= Math.min(r + 3, sh.getLastRowNum()); rr++) {
            int scanEnd = investHeaderScanEnd(sh, r, row);
            for (int rr = r; rr <= scanEnd; rr++) {
                Row rr2 = sh.getRow(rr);
                if (rr2 == null) continue;
                for (int c = 0; c <= rr2.getLastCellNum(); c++) {
@@ -2554,7 +2555,7 @@
                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("形象进度")) col.putIfAbsent("desc", 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);
@@ -2574,6 +2575,12 @@
                int md = col.get("yearcum") + 1;
                if (md <= row.getLastCellNum()) col.put("monthdone", md);
            }
            // desc ç¼ºå¤±æ—¶æŒ‰ stage+1 å…œåº•:省标「项目建设阶段、进度情况」是 L/M åˆå¹¶è¡¨å¤´ï¼Œ
            // å­æ„Ÿ/恩施/林区/随州等市州只在 L å†™ã€Œå»ºè®¾é˜¶æ®µã€ã€M ç›´æŽ¥å†™è¿›åº¦æ–‡å­—而不写标题
            if (!col.containsKey("desc") && col.containsKey("stage") && col.get("stage") >= 0) {
                int dc = col.get("stage") + 1;
                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"}) {
                col.putIfAbsent(k, -1);
@@ -2582,6 +2589,46 @@
            return col;
        }
        return null;
    }
    /** è¡¨å¤´æ–‡æœ¬æ‰«æä¸‹ç•Œï¼šé»˜è®¤è¡¨å¤´è¡Œ +3;若「项目名称」列首个数据行更靠下,则扩展到数据行前一行(上限 +12)。
     *  èƒŒæ™¯ï¼šå’¸å®/十堰等市州把「建设阶段/形象进度」标签写在表头下第 4~8 è¡Œï¼Œå›ºå®š +3 ä¼šæ¼åˆ—(形象进度读不到)。 */
    private int investHeaderScanEnd(Sheet sh, int headerRow, Row headerRowObj) {
        int hardEnd = Math.min(headerRow + 12, sh.getLastRowNum());
        int nameCol = -1;
        if (headerRowObj != null) {
            for (int c = 0; c <= headerRowObj.getLastCellNum(); c++) {
                String v = cellStr(headerRowObj, c);
                if (v != null && v.contains("项目名称")) { nameCol = c; break; }
            }
        }
        int firstData = findFirstInvestDataRow(sh, headerRow, nameCol);
        int scanEnd = (firstData > headerRow)
            ? Math.min(hardEnd, firstData - 1)
            : Math.min(headerRow + 3, sh.getLastRowNum());
        if (scanEnd < headerRow) scanEnd = headerRow;
        return scanEnd;
    }
    /** ã€Œé¡¹ç›®åç§°ã€åˆ—首个数据行下标(跳过表头续行与空行);找不到返回 -1 */
    private int findFirstInvestDataRow(Sheet sh, int headerRow, int nameCol) {
        if (nameCol < 0) return -1;
        for (int r = headerRow + 1; r <= sh.getLastRowNum(); r++) {
            Row row = sh.getRow(r);
            if (row == null) continue;
            String name = cellStr(row, nameCol);
            if (name == null || name.trim().isEmpty()) continue;
            String nt = name.trim().replaceAll("[\r\n]+", "");
            if (nt.contains("项目名称")) continue;
            String flat = nt.replaceAll("\\s+", "");
            if (flat.contains("合计") || flat.contains("总计") || flat.contains("小计")) continue;
            if (nt.matches("^[一二三四五六七八九十]+、.*")) continue;
            if (nt.matches("^([一二三四五六七八九十]+).*")) continue;
            if (nt.startsWith("填报") || nt.startsWith("单位负责人") || nt.matches("^\\d+、.*")) continue;
            if (investmentCity(nt) != null) continue;
            return r;
        }
        return -1;
    }
    /** ç»Ÿè®¡ sheet å†…项目数据行数(用于多 sheet åŽ†å²æ–‡ä»¶é€‰å½“æœˆ sheet) */
@@ -2596,9 +2643,9 @@
            String name = cellStr(row, nameCol);
            if (name == null || name.trim().isEmpty()) continue;
            String nt = name.trim().replaceAll("[\r\n]+", "");
            if (nt.contains("合计") || nt.contains("总计")) continue;
            String ntFlat = nt.replaceAll("\\s+", "");
            if (ntFlat.contains("合计") || ntFlat.contains("总计") || ntFlat.contains("小计")) continue;
            if (nt.matches("^[一二三四五六七八九十]+、.*")) continue;
            if (nt.replace(" ", "").matches(".*小\\s*计.*")) continue;
            if (nt.startsWith("填报") || nt.startsWith("单位负责人") || nt.matches("^\\d+、.*")) continue;
            if (!hasSeq) {
                if (nt.length() > 4) count++;
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/calc/WycSplitCalc.java
@@ -4,8 +4,10 @@
import com.trafficaudit.common.util.RegionUtil;
import com.trafficaudit.dataimport.entity.CityTaxiMonthly;
import com.trafficaudit.dataimport.entity.WycOrderMonthly;
import com.trafficaudit.dataimport.entity.WycTotalMonthly;
import com.trafficaudit.dataimport.mapper.CityTaxiMonthlyMapper;
import com.trafficaudit.dataimport.mapper.WycOrderMonthlyMapper;
import com.trafficaudit.dataimport.mapper.WycTotalMonthlyMapper;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.DataFormatter;
@@ -80,6 +82,8 @@
    private CityTaxiMonthlyMapper cityTaxiMapper;
    @Resource
    private WycOrderMonthlyMapper wycOrderMapper;
    @Resource
    private WycTotalMonthlyMapper wycTotalMapper;
    @Value("${city-passenger.template-dir:docs/城市客运}")
    private String templateDir;
@@ -254,14 +258,30 @@
        if (sum <= 0) return null;
        double orderSum = sum;
        if (row.getOrderSum() != null && row.getOrderSum() > 0) orderSum = row.getOrderSum();
        double pinK = row.getPinK() == null ? 0.0 : row.getPinK();
        double pinCK = row.getPinCK() == null ? 0.0 : row.getPinCK();
        double pinZ = row.getPinZ() == null ? 0.0 : row.getPinZ();
        double pinCZ = row.getPinCZ() == null ? 0.0 : row.getPinCZ();
        boolean pinFix = false;
        // pin å…œåº•:订单表 pin åˆ—为空/为 0 æ—¶å›žè½ wyc_total_monthly(pin ä¸“表)
        if (pinK <= 0 || pinCK <= 0 || pinZ <= 0 || pinCZ <= 0) {
            WycTotalMonthly tot = wycTotalMapper.selectOne(new LambdaQueryWrapper<WycTotalMonthly>()
                    .eq(WycTotalMonthly::getReportPeriod, period).last("LIMIT 1"));
            if (tot != null) {
                if (pinK <= 0 && tot.getPinK() != null && tot.getPinK() > 0) { pinK = tot.getPinK(); pinFix = true; }
                if (pinCK <= 0 && tot.getPinCK() != null && tot.getPinCK() > 0) { pinCK = tot.getPinCK(); pinFix = true; }
                if (pinZ <= 0 && tot.getPinZ() != null && tot.getPinZ() > 0) { pinZ = tot.getPinZ(); pinFix = true; }
                if (pinCZ <= 0 && tot.getPinCZ() != null && tot.getPinCZ() > 0) { pinCZ = tot.getPinCZ(); pinFix = true; }
            }
        }
        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("pinK", pinK);
        map.put("pinCK", pinCK);
        map.put("pinZ", pinZ);
        map.put("pinCZ", pinCZ);
        map.put("orders", orders);
        map.put("orderSum", orderSum);
        map.put("source", "db");
        map.put("source", pinFix ? "db+wyc_total" : "db");
        return map;
    }
    private File findInput() throws Exception {
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/controller/ReportExportController.java
@@ -155,6 +155,22 @@
        return buildResponse(reportService.investCounty(period, mode), "生成_经济强县交通物流基础设施投资统计报表.xls");
    }
    /** ç”Ÿæˆ_X月客运站投资明细表.xlsx(投资模块明细表1:客运站场) */
    @GetMapping("/export/investPassengerDetail")
    public ResponseEntity<byte[]> exportInvestPassengerDetail(@RequestParam("period") String period,
                                                              @RequestParam(value = "mode", defaultValue = "month") String mode) throws Exception {
        logExport("生成_X月客运站投资明细表.xlsx", period);
        return buildResponse(reportService.exportInvestPassengerDetail(period, mode), "生成_客运站投资明细表.xlsx");
    }
    /** ç”Ÿæˆ_X月物流站场投资明细.xls(投资模块明细表2:物流园区) */
    @GetMapping("/export/investLogisticsDetail")
    public ResponseEntity<byte[]> exportInvestLogisticsDetail(@RequestParam("period") String period,
                                                              @RequestParam(value = "mode", defaultValue = "month") String mode) throws Exception {
        logExport("生成_X月物流站场投资明细.xls", period);
        return buildResponse(reportService.exportInvestLogisticsDetail(period, mode), "生成_物流站场投资明细.xls");
    }
    /** ç”Ÿæˆ_轨道轮渡客运量分市州明细.xlsx(城市客运,轨道/轮渡取自公交源文件) */
    @GetMapping("/export/cityRailFerryDetail")
    public ResponseEntity<byte[]> exportCityRailFerryDetail(@RequestParam("period") String period,
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -1189,18 +1189,9 @@
    /** ä¸­å£å¾„月同比:k=-1 è¡¨ç¤ºæ€»è¡Œï¼ˆç­çº¿+公交+出租城乡+网约车城乡 å››é¡¹ä¹‹å’Œï¼‰ï¼›æ— åŽ»å¹´æ•°æ®ç•™ç©º */
    private void fillMidYoyCell(Cell c, Map<Integer, Map<String, double[][]>> mid, int year, int month,
                                String area, int k, boolean volume) {
        double v = 0.0, lv = 0.0;
        if (k == -1) {
            for (int kk = 1; kk <= 4; kk++) {
                v += midClassVal(mid, year, month, area, kk, volume);
                lv += midClassVal(mid, year - 1, month, area, kk, volume);
            }
        } else {
            v = midClassVal(mid, year, month, area, k, volume);
            lv = midClassVal(mid, year - 1, month, area, k, volume);
        }
        Double y = midMonthYoy(mid, year, month, area, k, volume);
        c.setBlank();
        if (v != 0.0 && lv != 0.0) c.setCellValue(round((v - lv) / lv, 4));
        if (y != null) c.setCellValue(y);
    }
    /** ä¸­å£å¾„累计同比列(1..months æœˆç´¯è®¡ï¼›å››ç»´é½å…¨ï¼‰ */
@@ -1221,19 +1212,13 @@
            if (blockOffset < 0 || blockOffset % 5 == 0) continue;
            int k = blockOffset % 5;
            String area = areas.get(blockOffset / 5);
            double v = 0.0, lv = 0.0;
            for (int m = 1; m <= months; m++) {
                {
                    v += midClassVal(mid, year, m, area, k, volume);
                    lv += midClassVal(mid, year - 1, m, area, k, volume);
                }
            }
            Double y = midCumYoy(mid, year, area, months, k, volume);
            Row row = sheet.getRow(r0);
            if (row == null) continue;
            Cell c = row.getCell(colIdx);
            if (c == null) c = row.createCell(colIdx);
            c.setBlank();
            if (v != 0.0 && lv != 0.0) c.setCellValue(round((v - lv) / lv, 4));
            if (y != null) c.setCellValue(y);
        }
    }
@@ -2326,6 +2311,56 @@
        return volume ? arr[k][0] : arr[k][1];
    }
    /** B3:登记「该期该市州该维度有源行」。判据是源表有没有这一行,而不是算出来的值是否非 0
     *  â€”—因为「值为 0」可能是真实业务(如武汉市巡游出租全部为城市内,城际城乡恒为 0)。 */
    private void markMid(Map<Integer, Map<String, boolean[]>> pres, int key, String city, int k) {
        pres.computeIfAbsent(key, kk -> new HashMap<>())
            .computeIfAbsent(city, kk -> new boolean[5])[k] = true;
    }
    /**
     * B3:该月该维度是否「有源」(同比完备性校验用)。
     * k &lt;= 0 è¡¨ç¤ºã€Œæ€»é‡è¡Œã€ï¼Œè¦æ±‚四维(班线/公交/出租/网约车)都有源才算齐全。
     */
    private boolean midMonthHas(Map<Integer, Map<String, double[][]>> mid, int year, int month, String area, int k, boolean volume) {
        Map<String, boolean[]> pm = midPresence.get().get(year * 100 + month);
        if (pm == null) return false;
        boolean[] b = pm.get(area);
        if (b == null) return false;
        if (k <= 0) {
            for (int kk = 1; kk <= 4; kk++) {
                if (!b[kk]) return false;
            }
            return true;
        }
        return k < b.length && b[k];
    }
    /** B3:去年 1..monthCount æœˆçš„命中月份数(用于判定同比基数是否齐全) */
    private int midCumHitMonths(Map<Integer, Map<String, double[][]>> mid, int year, String area, int monthCount, int k, boolean volume) {
        int n = 0;
        for (int m = 1; m <= monthCount; m++) {
            if (midMonthHas(mid, year, m, area, k, volume)) n++;
        }
        return n;
    }
    /** B3:当月同比——去年同月基数缺失则留空(缺数据不再当 0 è®¡ç®—) */
    private Double midMonthYoy(Map<Integer, Map<String, double[][]>> mid, int year, int month, String area, int k, boolean volume) {
        if (!midMonthHas(mid, year - 1, month, area, k, volume)) return null;
        double v = midClassVal(mid, year, month, area, k, volume);
        if (v == 0.0) return null;
        return yoyOf(v, midClassVal(mid, year - 1, month, area, k, volume));
    }
    /** B3:累计同比——去年 1..monthCount å„月齐全才计算,缺任何一月一律留空 */
    private Double midCumYoy(Map<Integer, Map<String, double[][]>> mid, int year, String area, int monthCount, int k, boolean volume) {
        if (midCumHitMonths(mid, year - 1, area, monthCount, k, volume) < monthCount) return null;
        double v = midCumClass(mid, year, area, monthCount, k, volume);
        if (v == 0.0) return null;
        return yoyOf(v, midCumClass(mid, year - 1, area, monthCount, k, volume));
    }
    /** å…¬å¼å•元格替换为缓存数值(避免跨簿引用断链;非数值缓存置空) */
    private void keepCached(Cell c) {
        try {
@@ -2346,7 +2381,20 @@
     * ä¸­å£å¾„分类月度数据:年*100+月 -> (市州/全省 -> double[5][2])
     * ç»´åº¦ 0=总量 1=公路班线(h2031+个体) 2=城际城乡公交(cityBus) 3=巡游出租 4=网约车;[客运量(万人), å‘¨è½¬é‡(万人公里)]
     */
    /** B3:最近一次 loadMidClassMap çš„「维度是否有源行」登记表(key -> city -> boolean[5]),用于同比完备性校验 */
    private final ThreadLocal<Map<Integer, Map<String, boolean[]>>> midPresence =
            ThreadLocal.withInitial(HashMap::new);
    /** B4/B5:最近一次 loadMidClassMap çš„æ•°æ®é—®é¢˜æ¸…单(线程内,随导出体检输出/写生成件) */
    private final ThreadLocal<java.util.List<String>> midIssues = ThreadLocal.withInitial(java.util.ArrayList::new);
    /** B4/B5:取最近一次中口径数据加载的问题清单(只读副本) */
    public java.util.List<String> getLastMidIssues() { return new java.util.ArrayList<>(midIssues.get()); }
    private Map<Integer, Map<String, double[][]>> loadMidClassMap() {
        midIssues.get().clear();   // B5:本次加载的问题清单
        Map<Integer, Map<String, boolean[]>> pres = new HashMap<>();
        midPresence.set(pres);     // B3:本次加载的维度有源登记
        Map<Integer, Map<String, double[][]>> mid = new HashMap<>();
        for (PassengerEnterpriseMonthly e : passengerMapper.selectList(null)) {
            if (e.getReportPeriod() == null) continue;
@@ -2368,6 +2416,8 @@
                + nz(e.getTurnoverClass4()) + nz(e.getTurnoverCharter())) / 10000.0;
            addMidClass(mid, key, city, 1, pass, turn);
            addMidClass(mid, key, "湖北省", 1, pass, turn);
            markMid(pres, key, city, 1);
            markMid(pres, key, "湖北省", 1);
        }
        for (PassengerIndividualMonthly e : passengerIndividualMapper.selectList(null)) { // ä¸ªä½“并入公路班线/总量(09-03 å£å¾„)
            if (e.getReportPeriod() == null) continue;
@@ -2387,6 +2437,8 @@
            double turn = nz(e.getTurnover()) / 10000.0;
            addMidClass(mid, key, city, 1, pass, turn);
            addMidClass(mid, key, "湖北省", 1, pass, turn);
            markMid(pres, key, city, 1);
            markMid(pres, key, "湖北省", 1);
        }
        for (CityBusMonthly b : cityBusMapper.selectList(null)) {
            if (b.getReportPeriod() == null || b.getCity() == null) continue;
@@ -2402,8 +2454,18 @@
            String city = RegionUtil.normalizeCityName(b.getCity());
            if (city == null) continue;
            int key = y * 100 + m;
            addMidClass(mid, key, city, 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang()));
            addMidClass(mid, key, "湖北省", 2, nz(b.getPassengerChengxiang()), nz(b.getTurnoverChengxiang()));
            // å£å¾„统一(2026-09-19,用户核对「中口径排名」周转量 vs äººå·¥åˆ—):城际城乡一律用「总量 âˆ’ åŸŽå¸‚内」现算。
            // åŽŸé€»è¾‘ã€Œå­˜å‚¨çš„åŸŽé™…åŸŽä¹¡ > 0 å°±ä¼˜å…ˆå–字段值,<=0 æ‰å›žé€€åˆ°å·®é¢æ³•」会在个别企业行上与差额法差 Â±0.01
            // ï¼ˆæºæŠ¥è¡¨é‡Œæ€»é‡/城市内/城际城乡各自两位小数舍入,2026 å¹´ 1-8 æœˆå…¨çœå…± 72 è¡Œï¼‰ï¼Œç´¯åŠ åŽ
            // ã€Œä¸­å£å¾„排名」页比「中口径明细」/人工口径多 0.32 ä¸‡äººå…¬é‡Œã€‚改为差额法后与台账页、明细页、四页合成口径一致。
            double cxPass = nz(b.getPassengerVolume()) - nz(b.getPassengerCity());
            double cxTurn = nz(b.getTurnover()) - nz(b.getTurnoverCity());
            if (cxPass < 0) cxPass = 0.0;
            if (cxTurn < 0) cxTurn = 0.0;
            addMidClass(mid, key, city, 2, cxPass, cxTurn);
            addMidClass(mid, key, "湖北省", 2, cxPass, cxTurn);
            markMid(pres, key, city, 2);
            markMid(pres, key, "湖北省", 2);
        }
        // ç»´åº¦3:城际城乡巡游出租 = å°è´¦é¡µã€Œå‡ºç§Ÿ!总量 âˆ’ å‡ºç§Ÿ!城市内」(源 city_taxi_monthly)
        for (CityTaxiMonthly t : cityTaxiMapper.selectList(null)) {
@@ -2416,6 +2478,8 @@
            double turn = nz(t.getTurnover()) - nz(t.getTurnoverCity());
            addMidClass(mid, key, city, 3, pass, turn);
            addMidClass(mid, key, "湖北省", 3, pass, turn);
            markMid(pres, key, city, 3);
            markMid(pres, key, "湖北省", 3);
        }
        // ç»´åº¦4:城际城乡网约车 = ç½‘约车拆分结果(与台账「网约车」页同源同法)
        for (WycOrderMonthly o : wycOrderMapper.selectList(null)) {
@@ -2427,12 +2491,18 @@
            try {
                wr = wycSplitCalc.calc(per);
            } catch (Exception e) {
                continue; // è¯¥æœŸç¼ºè®¢å•/pin æˆ–出租源数据,跳过(不影响其它期)
                // B5:不再静默跳过——记录「期 + åŽŸå› ã€å¹¶å†™æ—¥å¿—ï¼Œéšå¯¼å‡ºä½“æ£€ä¸€å¹¶è¾“å‡º
                String msg = per + " ç½‘约车城际城乡维度缺失:" + e.getMessage();
                midIssues.get().add(msg);
                log.warn("loadMidClassMap {}", msg);
                continue;
            }
            for (Map.Entry<String, WycSplitCalc.WycMetrics> en : wr.getByCity().entrySet()) {
                WycSplitCalc.WycMetrics wm = en.getValue();
                addMidClass(mid, key, en.getKey(), 4, wm.getSuburbanPax(), wm.getSuburbanTurnover());
                addMidClass(mid, key, "湖北省", 4, wm.getSuburbanPax(), wm.getSuburbanTurnover());
                markMid(pres, key, en.getKey(), 4);
                markMid(pres, key, "湖北省", 4);
            }
        }
        return mid;
@@ -2586,15 +2656,11 @@
                title.getCell(10).setCellValue(currentYear + "å¹´" + maxMonth + "月全省分市州完成道路客运生产情况");
            }
            // å…¨çœè¡Œ r3:B3/F3 ä¸º SUM å…¬å¼ä¿ç•™ï¼›D3/H3 åŒæ¯”填值(0-based åˆ— 3/7)
            setValOrBlank(sheet, 2, 3, yoyOf(midCumClass(mid, currentYear, "湖北省", maxMonth, 0, true),
                midCumClass(mid, currentYear - 1, "湖北省", maxMonth, 0, true)));
            setValOrBlank(sheet, 2, 7, yoyOf(midCumClass(mid, currentYear, "湖北省", maxMonth, 0, false),
                midCumClass(mid, currentYear - 1, "湖北省", maxMonth, 0, false)));
            setValOrBlank(sheet, 2, 3, midCumYoy(mid, currentYear, "湖北省", maxMonth, 0, true));
            setValOrBlank(sheet, 2, 7, midCumYoy(mid, currentYear, "湖北省", maxMonth, 0, false));
            // å³å—全省行 N3/R3:当月同比(L3/P3 ä¸º SUM å…¬å¼ä¿ç•™ï¼‰
            setValOrBlank(sheet, 2, 13, yoyOf(midClassVal(mid, currentYear, maxMonth, "湖北省", 0, true),
                midClassVal(mid, currentYear - 1, maxMonth, "湖北省", 0, true)));
            setValOrBlank(sheet, 2, 17, yoyOf(midClassVal(mid, currentYear, maxMonth, "湖北省", 0, false),
                midClassVal(mid, currentYear - 1, maxMonth, "湖北省", 0, false)));
            setValOrBlank(sheet, 2, 13, midMonthYoy(mid, currentYear, maxMonth, "湖北省", 0, true));
            setValOrBlank(sheet, 2, 17, midMonthYoy(mid, currentYear, maxMonth, "湖北省", 0, false));
            // å¸‚州行 r4-20:B/F ç´¯è®¡å€¼ã€D/H åŒæ¯”ï¼›C/E/G/I æŽ’名公式保留
            List<String> cities = RegionUtil.CITY_LIST;
            for (int i = 0; i < cities.size(); i++) {
@@ -2605,18 +2671,18 @@
                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, 3, yoyOf(pass, lastPass));
                setValOrBlank(sheet, r0, 3, midCumYoy(mid, currentYear, city, maxMonth, 0, true));
                setValOrBlank(sheet, r0, 5, turn == 0 ? null : round(turn, 4));
                setValOrBlank(sheet, r0, 7, yoyOf(turn, lastTurn));
                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, 13, mPass == 0 ? null : yoyOf(mPass, mLastPass));
                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, 17, mTurn == 0 ? null : yoyOf(mTurn, mLastTurn));
                setValOrBlank(sheet, r0, 17, mTurn == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, city, 0, false));
            }
            recalc(wb);
            return toBytes(wb);
@@ -2678,9 +2744,9 @@
                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, 2, yoyOf(pass, lastPass));
                setValOrBlank(sheet, r0, 2, midCumYoy(mid, currentYear, "湖北省", maxMonth, dims[i], true));
                setValOrBlank(sheet, r0, 5, turn == 0 ? null : round(turn, 4));
                setValOrBlank(sheet, r0, 6, yoyOf(turn, lastTurn));
                setValOrBlank(sheet, r0, 6, midCumYoy(mid, currentYear, "湖北省", maxMonth, dims[i], false));
            }
            // ä¸‹åŠå—(当月):标题行9、数据行11-15(0-based 8、10-14)
            Row bottomTitle = sheet.getRow(8);
@@ -2694,9 +2760,9 @@
                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, 2, pass == 0 ? null : yoyOf(pass, lastPass));
                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, 6, turn == 0 ? null : yoyOf(turn, lastTurn));
                setValOrBlank(sheet, r0, 6, turn == 0 ? null : midMonthYoy(mid, currentYear, maxMonth, "湖北省", dims[i], false));
            }
            // ä¸‹åŠå—占比公式由样例指向上半块(B$3/F$3),改写为本块总行(B$11/F$11),行12-15
            for (int i = 1; i < names.length; i++) {
@@ -4823,6 +4889,8 @@
            case "investFiveYearLogistics": return investFiveYearLogistics(period, mode);
            case "investBillion": return investBillion(period, mode);
            case "investCounty": return investCounty(period, mode);
            case "investPassengerDetail": return exportInvestPassengerDetail(period, mode);
            case "investLogisticsDetail": return exportInvestLogisticsDetail(period, mode);
            case "cityBusDetail": return exportCityBusDetail(period, mode);
            case "cityTaxiDetail": return exportCityTaxiDetail(period, mode);
            case "cityRailFerryDetail": return exportCityRailFerryDetail(period, mode);
@@ -4848,6 +4916,8 @@
        REPORT_FILE_NAMES.put("investFiveYearLogistics", "生成_十五五规划物流项目进展情况.xls");
        REPORT_FILE_NAMES.put("investBillion", "生成_湖北省(客货站场)亿元投资项目.xls");
        REPORT_FILE_NAMES.put("investCounty", "生成_经济强县交通物流基础设施投资统计报表.xls");
        REPORT_FILE_NAMES.put("investPassengerDetail", "生成_客运站投资明细表.xlsx");
        REPORT_FILE_NAMES.put("investLogisticsDetail", "生成_物流站场投资明细.xls");
        REPORT_FILE_NAMES.put("cityBusDetail", "生成_城市公交客运量分市州明细.xlsx");
        REPORT_FILE_NAMES.put("cityTaxiDetail", "生成_巡游出租客运量分市州明细.xlsx");
        REPORT_FILE_NAMES.put("cityRailFerryDetail", "生成_轨道轮渡客运量分市州明细.xlsx");
@@ -5399,6 +5469,355 @@
    }
    // ==================== æŠ•资模块:客运站投资明细表 / ç‰©æµç«™åœºæŠ•资明细(模板底稿原位替换) ====================
    /** ç‰©æµç«™åœºæ˜Žç»†è¡¨æ¨¡æ¿ä¸­çš„市州小节短名 -> åº“内规范全名 */
    private static final Map<String, String> LOGI_CITY_LABELS = new LinkedHashMap<>();
    static {
        LOGI_CITY_LABELS.put("武汉", "武汉市");
        LOGI_CITY_LABELS.put("黄石", "黄石市");
        LOGI_CITY_LABELS.put("十堰", "十堰市");
        LOGI_CITY_LABELS.put("宜昌", "宜昌市");
        LOGI_CITY_LABELS.put("襄阳", "襄阳市");
        LOGI_CITY_LABELS.put("鄂州", "鄂州市");
        LOGI_CITY_LABELS.put("荆门", "荆门市");
        LOGI_CITY_LABELS.put("孝感", "孝感市");
        LOGI_CITY_LABELS.put("荆州", "荆州市");
        LOGI_CITY_LABELS.put("黄冈", "黄冈市");
        LOGI_CITY_LABELS.put("咸宁", "咸宁市");
        LOGI_CITY_LABELS.put("随州", "随州市");
        LOGI_CITY_LABELS.put("恩施", "恩施州");
        LOGI_CITY_LABELS.put("仙桃", "仙桃市");
        LOGI_CITY_LABELS.put("潜江", "潜江市");
        LOGI_CITY_LABELS.put("天门", "天门市");
        LOGI_CITY_LABELS.put("林区", "神农架林区");
    }
    /** è¯¥æœŸå„项目月度数据:projectId -> InvestmentMonthly */
    private Map<Long, InvestmentMonthly> investMonthlyOf(String period) {
        Map<Long, InvestmentMonthly> map = new HashMap<>();
        for (InvestmentMonthly m : investMonthlyMapper.selectList(
                new LambdaQueryWrapper<InvestmentMonthly>().eq(InvestmentMonthly::getReportPeriod, period))) {
            map.put(m.getProjectId(), m);
        }
        return map;
    }
    /** å†™å•元格数值(保留样式/合并):null æ¸…空 */
    private void putNum(Row row, int idx, Double v) {
        if (row == null) return;
        Cell c = row.getCell(idx);
        if (c == null) c = row.createCell(idx);
        c.setBlank();
        if (v != null) c.setCellValue(v);
    }
    /** å†™å•元格文本(保留样式/合并):空串清空 */
    private void putText(Row row, int idx, String v) {
        if (row == null) return;
        Cell c = row.getCell(idx);
        if (c == null) c = row.createCell(idx);
        c.setBlank();
        if (v != null && !v.trim().isEmpty()) c.setCellValue(v.trim());
    }
    /** è¯»å•元格数值(空/非数值/公式无缓存一律 0) */
    private double numOf(Cell c) {
        if (c == null) return 0.0;
        try {
            if (c.getCellType() == CellType.NUMERIC || c.getCellType() == CellType.FORMULA) {
                return c.getNumericCellValue();
            }
            String s = cellText(c);
            if (s == null) return 0.0;
            s = s.replace(",", "").trim();
            return s.isEmpty() ? 0.0 : Double.parseDouble(s);
        } catch (Exception e) {
            return 0.0;
        }
    }
    /** æ¨¡æ¿æ ‡é¢˜é‡Œçš„「(N月月报)」「(N月)」改为报表期月份 */
    private void fixInvestMonthTitle(Sheet sheet, int rowIdx, int colIdx, int month) {
        Row row = sheet.getRow(rowIdx);
        if (row == null) return;
        String t = cellText(row.getCell(colIdx));
        if (t == null) return;
        String nv = t.replaceAll("(\\d+月月报)", "(" + month + "月月报)")
                      .replaceAll("(\\d+月)", "(" + month + "月)");
        if (!nv.equals(t)) putText(row, colIdx, nv);
    }
    /** æ¨¡æ¿è¡Œ A åˆ—是否为「一二三四、」渠道分组标题 */
    private boolean isInvestChannelLabel(String a) {
        return a != null && a.matches("^[一二三四五六七八九十]+、.*");
    }
    /**
     * ç”Ÿæˆ_X月客运站投资明细表.xlsx(模板:docs/投资/模板/模板_X月客运站投资明细表.xlsx,sheet:明细 + æ±‡æ€»ï¼‰ã€‚
     * å£å¾„:模板即上月台账底稿;本月只覆盖「库内有该期数据」的项目行
     * ï¼ˆH自开始建设累计 / I本年计划 / J自年初累计 / K本月完成 / L建设阶段 / M形象进度),
     * åº“内无该期的项目行保留母版原值(等同人工「上月结转 + æœ¬æœˆæ›´æ–°ã€ï¼‰ï¼›
     * åŸŽå¸‚/渠道/合计行沿用模板 SUM å…¬å¼ï¼Œéšè¡¨å†…数值自动重算。
     */
    public byte[] exportInvestPassengerDetail(String period, String mode) throws Exception {
        int year = Integer.parseInt(period.split("-")[0]);
        int month = monthOf(period, mode);
        List<InvestmentProject> projects = investProjectMapper.selectList(
                new LambdaQueryWrapper<InvestmentProject>().eq(InvestmentProject::getCategory, "客运站场"));
        Map<Long, InvestmentMonthly> mByProject = investMonthlyOf(period);
        File tpl = resolveAnyTemplate(investTemplateDir, "模板_X月客运站投资明细表.xlsx");
        try (InputStream in = new FileInputStream(tpl);
             XSSFWorkbook wb = new XSSFWorkbook(in)) {
            Sheet sheet = wb.getSheet("明细");
            if (sheet == null) throw new RuntimeException("模板《模板_X月客运站投资明细表.xlsx》缺少「明细」工作表");
            fixInvestMonthTitle(sheet, 0, 1, month);
            String curCity = null;
            Set<Long> used = new HashSet<>();
            int filled = 0, kept = 0, dup = 0;
            for (int r = 8; r <= sheet.getLastRowNum(); r++) {
                Row row = sheet.getRow(r);
                if (row == null) continue;
                String a = nvl(cellText(row.getCell(0)));
                String b = nvl(cellText(row.getCell(1)));
                if (isCityLabel(a)) { curCity = templateCityFull(a); continue; }
                if (isInvestChannelLabel(a)) continue;
                if (a.contains("合计") || a.contains("总计")) continue;
                if (!a.matches("\\d+(\\.\\d+)?")) continue;
                if (b.isEmpty() || curCity == null) continue;
                InvestmentProject p = matchInvest(projects, b, curCity, "客运站场", used);
                InvestmentMonthly m = p == null ? null : mByProject.get(p.getId());
                if (p == null || m == null) {
                    kept++;
                    // æœ‰åº“内项目但当月无数据 â†’ è®°ä¸ºå¾…核对;无匹配项目 â†’ ç»“转上月
                    if (p != null) dup++;
                    continue;
                }
                used.add(p.getId());
                // å£å¾„(用户 2026-09-18 ç¡®è®¤ï¼‰ï¼šåªè¦†ç›–人工会随月报更新的四列——
                // H è‡ªå¼€å§‹å»ºè®¾ç´¯è®¡ / J è‡ªå¹´åˆç´¯è®¡ / K æœ¬æœˆå®Œæˆ / M å½¢è±¡è¿›åº¦ï¼›
                // I æœ¬å¹´è®¡åˆ’投资、L å»ºè®¾é˜¶æ®µã€G è®¡åˆ’总投资为省定/母版口径,一律不动;库内为空则保留母版原值
                if (m.getStartCum() != null) putNum(row, 7, m.getStartCum());
                if (m.getYearCum() != null) putNum(row, 9, m.getYearCum());
                if (m.getMonthDone() != null) putNum(row, 10, m.getMonthDone());
                if (m.getProgressDesc() != null && !m.getProgressDesc().trim().isEmpty()) putText(row, 12, m.getProgressDesc());
                filled++;
            }
            Sheet sumSheet = wb.getSheet("汇总");
            if (sumSheet != null) {
                Row r2 = sumSheet.getRow(1);
                if (r2 != null) {
                    Cell c = r2.getCell(0);
                    if (c == null) c = r2.createCell(0);
                    c.setBlank();
                    c.setCellValue(java.time.LocalDate.of(year, month, 1).atStartOfDay());
                }
            }
            try {
                wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
            } catch (Exception e) {
                log.warn("客运站投资明细表公式求值失败: {}", e.getMessage());
            }
            log.info("客运站投资明细表 {}:写入 {} è¡Œï¼Œç»“转母版原值 {} è¡Œï¼ˆå…¶ä¸­åº“内有项目但当月无数据 {} è¡Œï¼‰",
                    period, filled, kept, dup);
            return toBytes(wb);
        }
    }
    /**
     * ç”Ÿæˆ_X月物流站场投资明细.xls(模板:docs/投资/模板/模板_X月物流站场投资明细.xls)。
     * è¦†ç›–「 åˆ†é¡¹ç›®æŠ•资完成情况」项目行(口径同客运站明细表),并按表内数值重算
     * æ¸ é“行 / å¸‚州行 / åˆè®¡è¡Œï¼ŒåŒæ­¥åˆ·æ–°ã€Œåˆ†å¸‚州规划内外项目完成情况」「市州汇总」两张汇总页。
     */
    public byte[] exportInvestLogisticsDetail(String period, String mode) throws Exception {
        int year = Integer.parseInt(period.split("-")[0]);
        int month = monthOf(period, mode);
        List<InvestmentProject> projects = investProjectMapper.selectList(
                new LambdaQueryWrapper<InvestmentProject>().eq(InvestmentProject::getCategory, "物流园区"));
        Map<Long, InvestmentMonthly> mByProject = investMonthlyOf(period);
        HSSFWorkbook wb = loadInvestTemplate("模板_X月物流站场投资明细.xls");
        HSSFSheet sheet = wb.getSheet(" åˆ†é¡¹ç›®æŠ•资完成情况");
        if (sheet == null) throw new RuntimeException("模板《模板_X月物流站场投资明细.xls》缺少「 åˆ†é¡¹ç›®æŠ•资完成情况」工作表");
        fixInvestMonthTitle(sheet, 0, 0, month);
        Row head = sheet.getRow(3);
        if (head != null) {
            String t = cellText(head.getCell(0));
            if (t != null) {
                String nv = t.replaceAll("\\d{4}å¹´\\d+月", year + "å¹´" + month + "月");
                if (!nv.equals(t)) putText(head, 0, nv);
            }
        }
        // 1) ç»“构扫描:市州小节行
        List<Integer> cityRows = new ArrayList<>();
        for (int r = 7; r <= sheet.getLastRowNum(); r++) {
            HSSFRow row = sheet.getRow(r);
            if (row == null) continue;
            String a = nvl(cellText(row.getCell(0)));
            String b = nvl(cellText(row.getCell(1)));
            if (LOGI_CITY_LABELS.containsKey(a) && b.isEmpty()) cityRows.add(r);
        }
        Map<String, double[]> citySums = new LinkedHashMap<>();   // å…¨å -> G,H,I,J,K
        Map<String, double[]> cityStats = new LinkedHashMap<>();  // å…¨å -> {总数, ç´¯è®¡, è§„划内数, è§„划内累计, è§„划外数, è§„划外累计}
        Set<Long> used = new HashSet<>();
        int filled = 0, kept = 0;
        for (int i = 0; i < cityRows.size(); i++) {
            int cr = cityRows.get(i);
            String cityLabel = nvl(cellText(sheet.getRow(cr).getCell(0)));
            String city = LOGI_CITY_LABELS.getOrDefault(cityLabel, cityLabel);
            int start = cr + 1;
            int end = (i + 1 < cityRows.size() ? cityRows.get(i + 1) : sheet.getLastRowNum() + 1) - 1;
            List<Integer> chRows = new ArrayList<>();
            for (int r = start; r <= end; r++) {
                HSSFRow row = sheet.getRow(r);
                if (row == null) continue;
                if (isInvestChannelLabel(nvl(cellText(row.getCell(0))))) chRows.add(r);
            }
            // (1) å…ˆæŒ‰é¡¹ç›®å+市州 è¦†ç›–有库内当期数据的项目行
            for (int r = start; r <= end; r++) {
                HSSFRow row = sheet.getRow(r);
                if (row == null) continue;
                String a = nvl(cellText(row.getCell(0)));
                String b = nvl(cellText(row.getCell(1)));
                if (isInvestChannelLabel(a)) continue;
                if (!a.matches("\\d+(\\.\\d+)?")) continue;
                if (b.isEmpty()) continue;
                InvestmentProject p = matchInvest(projects, b, city, "物流园区", used);
                InvestmentMonthly m = p == null ? null : mByProject.get(p.getId());
                if (p == null || m == null) { kept++; continue; }
                used.add(p.getId());
                // å£å¾„同客运站明细表:只覆盖 H è‡ªå¼€å§‹å»ºè®¾ç´¯è®¡ / J è‡ªå¹´åˆç´¯è®¡ / K æœ¬æœˆå®Œæˆ / M å½¢è±¡è¿›åº¦
                if (m.getStartCum() != null) putNum(row, 7, m.getStartCum());
                if (m.getYearCum() != null) putNum(row, 9, m.getYearCum());
                if (m.getMonthDone() != null) putNum(row, 10, m.getMonthDone());
                if (m.getProgressDesc() != null && !m.getProgressDesc().trim().isEmpty()) putText(row, 12, m.getProgressDesc());
                filled++;
            }
            // (2) å†æŒ‰æ¸ é“块汇总,并写回渠道行 / å¸‚州行
            double[] citySum = new double[5];
            double[] stat = new double[6];
            for (int j = 0; j < chRows.size(); j++) {
                int r0 = chRows.get(j);
                int r1 = (j + 1 < chRows.size() ? chRows.get(j + 1) : end + 1) - 1;
                boolean planned = !nvl(cellText(sheet.getRow(r0).getCell(0))).startsWith("四、");
                double[] s = new double[5];
                for (int r = r0 + 1; r <= r1; r++) {
                    HSSFRow row = sheet.getRow(r);
                    if (row == null) continue;
                    String a = nvl(cellText(row.getCell(0)));
                    String b = nvl(cellText(row.getCell(1)));
                    if (isInvestChannelLabel(a) || !a.matches("\\d+(\\.\\d+)?")) continue;
                    if (b.isEmpty()) continue;
                    for (int k = 0; k < 5; k++) s[k] += numOf(row.getCell(6 + k));
                    stat[0] += 1;
                    stat[1] += numOf(row.getCell(9));
                    if (planned) { stat[2] += 1; stat[3] += numOf(row.getCell(9)); }
                    else { stat[4] += 1; stat[5] += numOf(row.getCell(9)); }
                }
                HSSFRow crow = sheet.getRow(r0);
                for (int k = 0; k < 5; k++) putNum(crow, 6 + k, s[k] == 0 ? null : s[k]);
                for (int k = 0; k < 5; k++) citySum[k] += s[k];
            }
            // æ¸ é“块之外的游离项目行(模板未分组时)也计入市州合计
            for (int r = start; r <= end; r++) {
                HSSFRow row = sheet.getRow(r);
                if (row == null) continue;
                String a = nvl(cellText(row.getCell(0)));
                String b = nvl(cellText(row.getCell(1)));
                if (isInvestChannelLabel(a) || !a.matches("\\d+(\\.\\d+)?")) continue;
                if (b.isEmpty()) continue;
                boolean inChannel = false;
                for (int j = 0; j < chRows.size(); j++) {
                    int r0 = chRows.get(j);
                    int r1 = (j + 1 < chRows.size() ? chRows.get(j + 1) : end + 1) - 1;
                    if (r > r0 && r <= r1) { inChannel = true; break; }
                }
                if (inChannel) continue;
                for (int k = 0; k < 5; k++) citySum[k] += numOf(row.getCell(6 + k));
                stat[0] += 1;
                stat[1] += numOf(row.getCell(9));
            }
            HSSFRow cityRow = sheet.getRow(cr);
            for (int k = 0; k < 5; k++) putNum(cityRow, 6 + k, citySum[k] == 0 ? null : citySum[k]);
            citySums.put(city, citySum);
            cityStats.put(city, stat);
        }
        // 2) åˆè®¡è¡Œï¼ˆç¬¬ 7 è¡Œï¼‰
        double[] total = new double[5];
        for (double[] s : citySums.values()) {
            for (int k = 0; k < 5; k++) total[k] += s[k];
        }
        for (int k = 0; k < 5; k++) putNum(sheet.getRow(6), 6 + k, total[k] == 0 ? null : total[k]);
        // 3) åˆ†å¸‚州规划内外项目完成情况
        HSSFSheet citySheet = wb.getSheet("分市州规划内外项目完成情况");
        if (citySheet != null) {
            Row t1 = citySheet.getRow(0);
            if (t1 != null) {
                String t = cellText(t1.getCell(0));
                if (t != null) {
                    String nv = t.replaceAll("\\d{4}å¹´", year + "å¹´");
                    if (!nv.equals(t)) putText(t1, 0, nv);
                }
            }
            double[] st = new double[6];
            for (int r = 3; r <= citySheet.getLastRowNum(); r++) {
                HSSFRow row = citySheet.getRow(r);
                if (row == null) continue;
                String a = nvl(cellText(row.getCell(0)));
                String b = nvl(cellText(row.getCell(1)));
                if (a.contains("合计") || b.contains("合计")) {
                    for (int k = 0; k < 6; k++) putNum(row, 2 + k, st[k] == 0 ? null : st[k]);
                    continue;
                }
                double[] s = cityStats.get(LOGI_CITY_LABELS.getOrDefault(b, b));
                if (s == null) continue;
                for (int k = 0; k < 6; k++) {
                    putNum(row, 2 + k, s[k] == 0 ? null : s[k]);
                    st[k] += s[k];
                }
            }
        }
        // 4) å¸‚州汇总(B å¹´åº¦è®¡åˆ’投资为官方口径,保持模板原值;C/D/E æŒ‰åˆ†é¡¹ç›®é¡µé‡ç®—)
        HSSFSheet sumSheet = wb.getSheet("市州汇总");
        if (sumSheet != null) {
            HSSFRow r2 = sumSheet.getRow(1);
            if (r2 != null) {
                putNum(r2, 0, (double) org.apache.poi.ss.usermodel.DateUtil.getExcelDate(
                        java.time.LocalDate.of(year, month, 1).atStartOfDay()));
            }
            double cT = 0.0, dT = 0.0;
            for (int r = 7; r <= 23; r++) {
                HSSFRow row = sumSheet.getRow(r);
                if (row == null) continue;
                String a = nvl(cellText(row.getCell(0)));
                double[] s = citySums.get(LOGI_CITY_LABELS.getOrDefault(a, a));
                if (s == null) continue;
                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);
                cT += s[3];
                dT += s[4];
            }
            HSSFRow tot = sumSheet.getRow(6);
            if (tot != null) {
                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);
            }
        }
        try {
            wb.getCreationHelper().createFormulaEvaluator().evaluateAll();
        } catch (Exception e) {
            log.warn("物流站场投资明细公式求值失败: {}", e.getMessage());
        }
        log.info("物流站场投资明细 {}:写入 {} è¡Œï¼Œç»“转母版原值 {} è¡Œ", period, filled, kept);
        return toBytesHssf(wb);
    }
    private static class InvestAgg {
        double total, startCum, yearPlan, yearCum;
traffic-audit-web/src/views/DataImport.vue
@@ -37,7 +37,7 @@
                                <div class="module-sel-row">
                  <el-select v-model="moduleSel[g.key]" placeholder="选择数据类型" style="width:260px"
                             @change="onModuleChange(g.key)" clearable>
                    <el-option v-for="t in g.types" :key="t.value" :label="t.label" :value="t.value"></el-option>
                    <el-option v-for="t in typeList(g)" :key="t.value" :label="t.label" :value="t.value"></el-option>
                  </el-select>
                  <div v-if="importType" class="tpl-box">
                    <span class="tpl-name">模板:{{ templateName }}</span>
@@ -114,7 +114,7 @@
                <div v-else class="overview-grid">
                  <div class="ov-row" v-for="g in visibleGroups" :key="g.key">
                    <div class="ov-group">{{ g.name }}</div>
                    <div class="ov-item" v-for="t in g.types" :key="t.value" :class="overviewState(t.value).cls">
                    <div class="ov-item" v-for="t in typeList(g)" :key="t.value" :class="overviewState(t.value).cls">
                      <div class="ov-name">{{ t.label }}</div>
                      <div class="ov-status">{{ overviewState(t.value).text }}</div>
                    </div>
@@ -134,7 +134,7 @@
            <div v-if="clearScope === 'types'" class="clear-types">
              <el-select v-model="clearTypes" multiple filterable collapse-tags placeholder="选择要清空的数据类型" style="width:100%">
                <el-option-group v-for="g in clearableGroups()" :key="g.key" :label="g.name">
                  <el-option v-for="t in g.types" :key="t.value" :value="t.value"
                  <el-option v-for="t in typeList(g)" :key="t.value" :value="t.value"
                             :label="t.label + '(' + overviewState(t.value).text + ')'"></el-option>
                </el-option-group>
              </el-select>
@@ -226,7 +226,7 @@
            { value: 'cityTaxi', label: '巡游出租汽车运营服务情况月报' },
            { value: 'cityTaxiAuth', label: '出租车运政车辆' },
            { value: 'wycTotal', label: '网约车总数' },
            { value: 'wycOrder', label: '网约车订单及全省总量' },
            { value: 'wycOrder', label: '网约车订单及全省总量', hidden: true },
            { value: 'wycOrderReport', label: '网约车订单报告' }
          ]
        },
@@ -584,6 +584,10 @@
    clearableGroups() {
      return this.groups.filter(g => !g.hidden)
    },
    // å•个数据类型也可隐藏(hidden: true):入口、概览、清空下拉统一过滤
    typeList(g) {
      return (g && g.types ? g.types : []).filter(t => !t.hidden)
    },
    confirmClear() {
      if (!this.period) { this.$message.warning('请先选择报表期'); return }
      if (this.clearing) return
traffic-audit-web/src/views/ReportExport.vue
@@ -225,7 +225,9 @@
            { key: 'investPlan', label: '全省预安排计划进度汇总', fileName: '生成_全省预安排计划进度情况汇总.xls', status: null, statusNote: '' },
            { key: 'investFiveYearLogistics', label: '十五五规划物流项目进展', fileName: '生成_十五五规划物流项目进展情况.xls', status: null, statusNote: '' },
            { key: 'investBillion', label: '亿元投资项目', fileName: '生成_湖北省(客货站场)亿元投资项目.xls', status: null, statusNote: '' },
            { key: 'investCounty', label: '经济强县项目投资统计', fileName: '生成_经济强县交通物流基础设施投资统计报表.xls', status: null, statusNote: '' }
            { key: 'investCounty', label: '经济强县项目投资统计', fileName: '生成_经济强县交通物流基础设施投资统计报表.xls', status: null, statusNote: '' },
            { key: 'investPassengerDetail', label: '客运站投资明细表', fileName: '生成_X月客运站投资明细表.xlsx', status: null, statusNote: '' },
            { key: 'investLogisticsDetail', label: '物流站场投资明细', fileName: '生成_X月物流站场投资明细.xls', status: null, statusNote: '' }
          ], checked: []
        },
        {
@@ -476,7 +478,7 @@
      const doExport = () => {
        if (items.length === 1) {
          api.get('/report/export/' + items[0].key, { params, responseType: 'blob', timeout: 120000 })
            .then(res => { this.downloadBlob(res, items[0].fileName); this.$message.success('报表导出成功'); this.loading = '' })
            .then(res => { this.downloadBlob(res, this.fileNameOf(items[0])); this.$message.success('报表导出成功'); this.loading = '' })
            .catch(err => this.failWith(err))
          return
        }
@@ -547,6 +549,13 @@
      }
      return text.length > 200 ? text.slice(0, 200) + '…' : text
    },
    // æ–‡ä»¶åå ä½ç¬¦ X月 -> å½“前报表期月份(如「生成_X月客运站投资明细表.xlsx」->「生成_8月客运站投资明细表.xlsx」)
    fileNameOf(item) {
      const name = (item && item.fileName) || ''
      const mm = parseInt((this.period || '').split('-')[1], 10)
      if (!mm) return name
      return name.replace(/X月/g, mm + '月')
    },
    downloadBlob(res, fileName) {
      const isZip = /\.zip$/.test(fileName)
      const isXls = /\.xls$/.test(fileName)