3个文件已修改
5个文件已添加
753 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_导入清空按类型与按钮防误触_2026-09-10.md 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/功能测试报告/功能测试报告_数据导入清空按钮按报表期清库_2026-09-10.md 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-10.md 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/货运/【20230531】湖北省道路货物运输量统计方法(2023年)编制说明.docx 补丁 | 查看 | 原始文档 | blame | 历史
docs/货运/学习笔记_分市州道路货物运输量统计方法_2026-09-10.md 219 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java 272 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/DataImport.vue 79 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_µ¼ÈëÇå¿Õ°´ÀàÐÍÓë°´Å¥·ÀÎó´¥_2026-09-10.md
New file
@@ -0,0 +1,42 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Šï¼šæ•°æ®å¯¼å…¥é¡µâ€œæ¸…ç©ºæ•°æ®â€å¢žå¼ºï¼ˆæŒ‰ç±»åž‹æ¸…ç©º + æŒ‰é’®ç§»å‡ºåˆ·æ–°è¡Œé˜²è¯¯è§¦ï¼‰ 2026-09-10
## åŠŸèƒ½è¯´æ˜Ž
- æ•°æ®å¯¼å…¥é¡µå³ä¾§â€œå¯¼å…¥è¿›åº¦â€ä¾§æ åœ¨åŽŸâ€œåˆ·æ–°â€æ—åŽ»æŽ‰â€œæ¸…ç©ºâ€ï¼Œæ”¹ä¸ºåœ¨ä¾§æ æ ‡é¢˜è¡Œä¸‹æ–¹æ–°å¢žç‹¬ç«‹å±é™©æ“ä½œåŒºï¼ˆæµ…çº¢åº• + è¾¹æ¡†ï¼‰ï¼Œå†…含 `el-button type="danger" plain` çš„“清空数据…”按钮与说明“按报表期清库,用于整月重导”,与“刷新”物理分开,降低误触。
- æ–°å¢žæ¸…空弹窗:显示当前报表期,选择“清空该报表期全部已导入数据”或“只清空指定类型”;选类型时用 `el-select multiple filterable`,按分组列出可选类型并标注“(已导入 N è¡Œ/未导入)”;底部红色警示语说明会同步删除审核结果、已审核标记与导入批次(投资项目主档保留)且不可撤销。
- åŽç«¯ `POST /api/import/clear` å¢žåŠ å¯é€‰å‚æ•° `types`(逗号分隔):为空 = æ¸…空该报表期全部类型(原行为不变);非空 = åªæ¸…空指定数据类型,并同步清理其关联的 audit_result / audit_run / import_batch。
## æ¶‰åŠæ”¹åЍ
- åŽç«¯ `DataImportService`:`clearPeriod(period, types)` é‡è½½ï¼›æ–°å¢žé™æ€æ˜ å°„ `CLEAR_TYPE_TO_OP`(类型→数据表操作键,同表归并去重)、`CLEAR_TYPE_TO_AUDIT`(类型→审核规则类型)、`CLEAR_TYPE_TO_BATCH`(类型→importType);新增 `clearTypeData(op, period)` åˆ†æ´¾ä¸Ž `deleteInvestmentMonthly(period, category)`(投资月度按项目类别过滤,仅删本期明细,投资主档保留)。返回值新增 `scope` ä¸Ž `types`,便于前端提示清空范围。
- åŽç«¯ `DataImportController`:`clearData` å¢žåŠ  `types` å‚数解析(空串/空项忽略)。
- å‰ç«¯ `DataImport.vue`:移除 `.side-head-btns` ä¸Žæ—§ `clearPeriodData()`;新增 `.side-danger` å±é™©æ“ä½œåŒºã€æ¸…空弹窗、`openClearDialog()/clearableGroups()/confirmClear()` ä¸Ž `clearDialog/clearScope/clearTypes` çŠ¶æ€ï¼›ç¡®è®¤åŽå†èµ°ä¸€æ¬¡ `$confirm` äºŒæ¬¡ç¡®è®¤ï¼ŒæˆåŠŸæç¤ºå¸¦åˆ é™¤è¡Œæ•°ã€‚
## æµ‹è¯•环境
- åŽç«¯ï¼štraffic-audit-server 8090(含本次改动;`start-dev.ps1` å¯åŠ¨ï¼ŒPID 21884,启动时间 2026-09-10 08:54:02,加载 `target/classes` æœ€æ–°ç¼–译产物)。
- å‰ç«¯ï¼štraffic-audit-web 8080 dev,`frontend.log` æœ€è¿‘一次 `Compiled successfully in 347ms`(08:53:29),热更新已生效。
- æ•°æ®åº“:本机 MySQL `localhost:3308/traffic_audit`,mysql CLI ç›´æŸ¥æ ¸å¯¹ï¼›ç™»å½•账号 `admin/123456`。
- æµ‹è¯•数据:一次性测试期 `2099-01 / 2099-02`,使用 `docs/货运需导入的数据/货运/2026å¹´1-7月报/道路货物运输月度生产情况(2026å¹´6月).xls`(636 è¡Œï¼‰ä¸Ž 2026-07 åŸŽå¸‚公交样本;真实月份仅做回归对比,不被写入或删除。
## ç”¨ä¾‹è¡¨
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
|---|---|---|---|---|---|
| 1 | ç¼–译 | `mvn -o -q compile` | é€šè¿‡ | æ— æŠ¥é”™ | é€šè¿‡ |
| 2 | æ­£å‘-按类型清空 | `POST /import/clear?period=2099-01&types=h2032` | åªåˆ  h2032 åŠå…¶ H2032 å®¡æ ¸ç»“æžœ/批次 | dataRows=636、auditRows=31、auditRunRows=1、batchRows=1;DB æ ¸å¯¹ h2032=0、H2032 è§„则审核结果=0、audit_run(H2032)=0、批次(H2032)=0 | é€šè¿‡ |
| 3 | éš”离性-其它类型不受影响 | åŒä¸Šï¼Œæ¸… h2032 åŽæŸ¥ cityBus | cityBus æ•°æ®ä¸Žå®¡æ ¸/批次保留 | cityBus ä¸šåŠ¡ 142 è¡Œã€CITY_BUS å®¡æ ¸ 53 è¡Œã€audit_run(CITY_BUS)=1、批次(CITY_BUS)=1 å‡ä¿ç•™ | é€šè¿‡ |
| 4 | éš”离性-其它报表期不受影响 | åŒä¸Šï¼ŒæŸ¥ 2099-02 | 2099-02 æ•°æ®ä¸å—影响 | 2099-02 æ•°æ®å®Œå¥½ | é€šè¿‡ |
| 5 | è´Ÿå‘-非法类型 | `types=notAType` | æ‹’绝并提示 | HTTP 500,`清空失败: æœªæŒ‡å®šæœ‰æ•ˆçš„æ•°æ®ç±»åž‹` | é€šè¿‡ |
| 6 | è¾¹ç•Œ-有效+未知混合 | `types=cityBus,notAType` | å¿½ç•¥æœªçŸ¥ã€æŒ‰æœ‰æ•ˆç±»åž‹æ‰§è¡Œ | æˆåŠŸï¼Œè¿”å›ž `scope=types, types=[cityBus,notAType]`,删除 0 è¡Œï¼ˆè¯¥æœŸæ— æ•°æ®ï¼‰ | é€šè¿‡ |
| 7 | è¾¹ç•Œ-空类型列表 | ä¸ä¼  `types` | æŒ‰å…¨éƒ¨ç±»åž‹æ¸…空(原行为) | æˆåŠŸï¼Œ`scope=all` | é€šè¿‡ |
| 8 | æŠ•资按类别 | æ’å…¥ 2099-01 å®¢è¿ç«™åœº/物流园区测试行后分别清空 | åªåˆ å¯¹åº”类别,投资主档保留 | `types=investment` åªåˆ å®¢è¿ç«™åœºã€`types=investmentLogistics` åªåˆ ç‰©æµå›­åŒºï¼Œ`investment_project` ä¸»æ¡£ä¿ç•™ | é€šè¿‡ |
| 9 | UI-按钮位置 | æ‰“开数据导入页,展开“导入进度” | â€œåˆ·æ–°â€æ—æ— æ¸…空;清空按钮在独立红色危险区 | ä¸Žé¢„期一致(可访问性树可读到“清空数据…”按钮与提示文案) | é€šè¿‡ |
| 10 | UI-弹窗选项 | ç‚¹â€œæ¸…空数据…” | å¼¹çª—含报表期、全部/指定类型单选、类型下拉带导入状态 | é€‰ä¸­â€œé“路货物运输月度生产情况(已导入 636 è¡Œï¼‰â€ï¼Œé€‰é¡¹æ ‡ç­¾ä¸ŽçŠ¶æ€ä¸€è‡´ | é€šè¿‡ |
| 11 | UI-确认清空 | é€‰ä¸­ h2032 åŽç‚¹â€œç¡®è®¤æ¸…空” | äºŒæ¬¡ç¡®è®¤ â†’ æˆåŠŸæç¤ºå«è¡Œæ•°ã€è¿›åº¦å›žâ€œæœªå¯¼å…¥â€ | æç¤ºâ€œå·²æ¸…空 2099-01 æ•°æ®ï¼šä¸šåŠ¡æ•°æ® 636 è¡Œã€å®¡æ ¸ç»“æžœ 0 è¡Œã€å¯¼å…¥æ‰¹æ¬¡ 1 æ¡ï¼Œå¯ä»¥é‡æ–°å¯¼å…¥â€ï¼Œè¿›åº¦å›žâ€œæœªå¯¼å…¥â€ | é€šè¿‡ |
| 12 | å›žå½’-真实月份 | æ¸…空前后对比 | æ— å˜åŒ– | 2099-01 æ®‹ç•™=0;2026-09=636、2026-07=636、2025-07=664 æœªå˜ï¼›çœŸå®žæ‰¹æ¬¡æ€»æ•° 239 æœªå˜ | é€šè¿‡ |
## å‘现的问题与处置
- æ— åŠŸèƒ½æ€§ç¼ºé™·ã€‚æµ‹è¯•æœŸæ•°æ®åœ¨éªŒè¯ç»“æŸåŽå·²å…¨éƒ¨æ¸…é™¤ï¼Œæœªæ®‹ç•™ã€‚
- è¯´æ˜Žï¼ˆä¿ç•™ç‰¹æ€§ï¼‰ï¼šä¸€æ¬¡æ¸…空会删除该报表期“全部类型”的业务数据及审核结果/已审核标记/导入批次,弹窗已用红色文案提示不可撤销;只想清单一类型时使用“只清空指定类型”,未导入的类型仍可勾选但不产生删除。
- çŽ¯å¢ƒå¤‡æ³¨ï¼šæœ¬æœºåº“ `admin` å¯†ç ä¸º `123456`(`admin123` åœ¨æœ¬æœºä¸åŒ¹é…ï¼‰ã€‚
## ç»“论
- é€šè¿‡ã€‚“清空数据…”已从“刷新”旁移出并做视觉隔离,弹窗支持按整期或按类型清空,接口按范围精确删除业务数据、审核结果、已审核标记与导入批次,且对其它类型、其它报表期与真实月份零影响。
- å¾…用户在自己浏览器验收一次按钮位置与弹窗文案。
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_Êý¾Ýµ¼ÈëÇå¿Õ°´Å¥°´±¨±íÆÚÇå¿â_2026-09-10.md
New file
@@ -0,0 +1,41 @@
# åŠŸèƒ½æµ‹è¯•æŠ¥å‘Šï¼šæ•°æ®å¯¼å…¥é¡µâ€œå¯¼å…¥è¿›åº¦Â·æ¸…ç©ºâ€æŒ‰é’®ï¼ˆæŒ‰æŠ¥è¡¨æœŸæ¸…ç©ºæ•°æ®åº“ï¼‰ 2026-09-10
## åŠŸèƒ½è¯´æ˜Ž
- æ•°æ®å¯¼å…¥é¡µå³ä¾§â€œå¯¼å…¥è¿›åº¦â€ä¾§æ æ ‡é¢˜æ—æ–°å¢žçº¢è‰²â€œæ¸…空”按钮(与“刷新”并列),随侧栏展开可见。
- ä½œç”¨ï¼šä¸€é”®æ¸…空当前所选报表期在数据库中的全部已导入业务数据,并同步删除该报表期的审核结果、审核通过标记(audit_run)与导入批次记录(import_batch),用于整月重新导入;投资项目主档(investment_project)保留不动。
- äº¤äº’:点击 â†’ äºŒæ¬¡ç¡®è®¤å¼¹çª—(标题含报表期,提示不可撤销)→ ç¡®è®¤åŽè°ƒç”¨ `POST /api/import/clear?period=yyyy-MM`;清空过程中按钮进入 loading å¹¶ç¦ç”¨ï¼›æœªé€‰æŠ¥è¡¨æœŸæˆ–正在导入时按钮禁用;成功后提示“已清空 xxx æŠ¥è¡¨æœŸçš„æ•°æ®ï¼Œå¯ä»¥é‡æ–°å¯¼å…¥â€å¹¶è‡ªåŠ¨åˆ·æ–°å¯¼å…¥è¿›åº¦ã€‚
## æ¶‰åŠæ”¹åЍ
- åŽç«¯ `DataImportService.clearPeriod(period)`:`@Transactional`,先校验报表期格式,再按报表期删除 h2032/运政车辆/轨迹里程/规上规下/货运量周转量/旅客月报/个体/旅客运政/能耗/能耗运政/投资月度/投资系统/城市公交/巡游出租/出租车运政/网约车总数/网约车订单各表数据,并删除该期 audit_result、audit_run、import_batch;返回各表删除行数统计。
- åŽç«¯ `DataImportController` æ–°å¢ž `POST /api/import/clear`(参数 period)。
- å‰ç«¯ `DataImport.vue`:新增 `clearing` çŠ¶æ€ã€`clearPeriodData()` æ–¹æ³•与侧栏按钮/样式。
## æµ‹è¯•环境
- åŽç«¯ï¼štraffic-audit-server 8090(含本次改动,`start-dev.ps1` å¯åŠ¨æˆåŠŸï¼Œbackend.log å‡ºçް `Started TrafficAuditApplication`)。
- å‰ç«¯ï¼štraffic-audit-web 8080 dev(Compiled successfully),浏览器为 Codex åº”用内浏览器,`admin` ç™»å½•。
- æ•°æ®åº“:本机 MySQL `localhost:3308/traffic_audit`,用 mysql CLI ç›´æŸ¥æ ¸å¯¹ã€‚
- æµ‹è¯•数据:`docs/货运需导入的数据/货运/2026å¹´1-7月报/道路货物运输月度生产情况(2026å¹´6月).xls`(636 è¡Œï¼‰ï¼Œå¯¼å…¥åˆ°ä¸€æ¬¡æ€§æµ‹è¯•期 `2099-01`,全程不触碰任何真实月份。
## ç”¨ä¾‹è¡¨
| # | ç”¨ä¾‹ | è¾“å…¥ | é¢„期 | å®žé™… | ç»“论 |
|---|---|---|---|---|---|
| 1 | åŸºçº¿æ£€æŸ¥ | æŸ¥è¯¢ 2099-01 çš„æ‰¹æ¬¡ä¸Žå®¡æ ¸ç»“æžœ | å‡ä¸ºç©º | æ‰¹æ¬¡ 0 æ¡ã€å®¡æ ¸ç»“æžœ 0 æ¡ | é€šè¿‡ |
| 2 | æ­£å‘-导入 | ä¸Šä¼  6 æœˆè´§è¿ xls,period=2099-01 | æˆåŠŸä¸”è¡Œæ•° 636 | è¿”回“H2032月报导入成功,共 636 æ¡è®°å½•”,批次 1 æ¡ | é€šè¿‡ |
| 3 | æ­£å‘-审核 | `POST /audit/execute?period=2099-01&reportType=H2032` | ç”Ÿæˆå®¡æ ¸ç»“果与已审核标记 | ç”Ÿæˆ audit_result 31 è¡Œã€audit_run 1 è¡Œ | é€šè¿‡ |
| 4 | æ­£å‘-清空(接口) | `POST /import/clear?period=2099-01` | è¿”回删除统计,库内该期清空 | è¿”回 dataRows=636、auditRows=31、auditRunRows=1、batchRows=1;DB ç›´æŸ¥ h2032/audit_result/audit_run/import_batch å‡ä¸º 0 | é€šè¿‡ |
| 5 | æ­£å‘-清空后重导 | å†æ¬¡ä¸Šä¼ åŒä¸€æ–‡ä»¶ period=2099-01 | å¯æ­£å¸¸é‡æ–°å¯¼å…¥ | æˆåŠŸ 636 æ¡ï¼›DB h2032=636、import_batch=1 | é€šè¿‡ |
| 6 | è´Ÿå‘-非法报表期 | `period=abc` | æ‹’绝并提示格式 | code=500,“清空失败: æŠ¥è¡¨æœŸæ ¼å¼ä¸æ­£ç¡®ï¼Œåº”为 yyyy-MM” | é€šè¿‡ |
| 7 | è¾¹ç•Œ-空报表期 | `period=2098-12`(无数据) | æˆåŠŸä¸”å„é¡¹ä¸º 0 | dataRows/auditRows/auditRunRows/batchRows å‡ä¸º 0 | é€šè¿‡ |
| 8 | UI-按钮存在 | æ‰“开数据导入页,选 2099-01,展开“导入进度” | æ ‡é¢˜æ—å‡ºçŽ°â€œåˆ·æ–°/清空”,进度显示 H203-2 å·²å¯¼å…¥ 636 è¡Œ | ä¸Žé¢„期一致(可访问性树读到“清空”按钮与“已导入 636 è¡Œâ€ï¼‰ | é€šè¿‡ |
| 9 | UI-二次确认 | ç‚¹â€œæ¸…空” | å¼¹å‡ºç¡®è®¤æ¡†ï¼Œæ ‡é¢˜å«æŠ¥è¡¨æœŸ | å¼¹çª—标题“清空 2099-01 æ•°æ®â€ï¼Œæ­£æ–‡æç¤ºä¸å¯æ’¤é”€ï¼ŒæŒ‰é’®â€œå–消/确认清空” | é€šè¿‡ |
| 10 | UI-确认清空 | ç‚¹â€œç¡®è®¤æ¸…空” | æç¤ºæˆåŠŸã€è¿›åº¦å…¨éƒ¨å›žâ€œæœªå¯¼å…¥â€ã€åº“å†…æ¸…ç©º | æç¤ºâ€œå·²æ¸…空 2099-01 æŠ¥è¡¨æœŸçš„æ•°æ®ï¼Œå¯ä»¥é‡æ–°å¯¼å…¥â€ï¼›è¿›åº¦å…¨éƒ¨æœªå¯¼å…¥ï¼›DB ç›´æŸ¥å››è¡¨å‡ä¸º 0 | é€šè¿‡ |
| 11 | å›žå½’-真实月份不受影响 | æ¸…空前后对比批次分布与库内行数 | çœŸå®žæœˆä»½æ— å˜åŒ– | æ‰¹æ¬¡åˆ†å¸ƒä¸Žæ”¹åŠ¨å‰å®Œå…¨ä¸€è‡´ï¼ˆ2025 å„月 1 æ¡ã€2026-07 45 æ¡ã€2026-08 48 æ¡ã€2026-09 7 æ¡ï¼‰ï¼›h2032:2025-07=664、2026-07=636、2026-09=636 | é€šè¿‡ |
## å‘现的问题与处置
- æœªå‘现功能缺陷。
- è¯´æ˜Žï¼šä¸€æ¬¡æ¸…空会删除该报表期“全部类型”的业务数据及审核结果/已审核标记,弹窗已明确提示不可撤销;若只想清单一类型,目前需整月清空后重导,可作为后续增强(按类型清空)。
- çŽ¯å¢ƒå¤‡æ³¨ï¼šæœ¬æœºåº“ `admin` å¯†ç ä¸º `123456`(见 docs/交接文档-20260831.md,8/31 å®žæµ‹ï¼‰ï¼Œ`admin123` åœ¨æœ¬æœºä¸åŒ¹é…ã€‚
## ç»“论
- é€šè¿‡ã€‚清空按钮在界面可用、确认弹窗语义清晰,接口按报表期完整清除业务数据、审核结果、审核标记与导入批次,清空后可立即整月重导;对真实月份数据零影响。
- å¾…用户实际浏览器验收:在自己工作机上点一次“清空”(建议先确认所选报表期与备份)确认弹窗文案与预期一致。
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-10.md
New file
@@ -0,0 +1,77 @@
# å·¥ä½œæ—¥ç»“ 2026-09-10
## ä¸Šåˆï¼ˆ2026-09-10)数据导入页新增“清空(按报表期清库)”并完成端到端验证
### å®Œæˆå†…容
- æ•°æ®å¯¼å…¥é¡µå³ä¾§â€œå¯¼å…¥è¿›åº¦â€ä¾§æ æ ‡é¢˜æ—æ–°å¢žçº¢è‰²â€œæ¸…空”按钮:一键清空所选报表期在数据库中的全部已导入数据,并同步删除该期审核结果、审核通过标记(audit_run)与导入批次(import_batch),用于整月重导;投资项目主档保留。
- åŽç«¯æ–°å¢ž `DataImportService.clearPeriod(period)`(`@Transactional` + æŠ¥è¡¨æœŸæ ¼å¼æ ¡éªŒ + åˆ é™¤è¡Œæ•°ç»Ÿè®¡ï¼‰ä¸Ž `POST /api/import/clear`;覆盖 h2032/运政车辆/轨迹里程/规上规下/货运量周转量/旅客月报/个体/旅客运政/能耗/能耗运政/投资月度/投资系统/城市公交/巡游出租/出租车运政/网约车总数/网约车订单 ç­‰è¡¨ã€‚
- å‰ç«¯äº¤äº’:二次确认弹窗(标题含报表期、提示不可撤销)、清空中 loading/禁用、未选报表期或导入中禁用、成功后自动刷新导入进度。
### æµ‹è¯•结果摘要
- ä¸€æ¬¡æ€§æµ‹è¯•期 2099-01 å…¨æµç¨‹ï¼šå¯¼å…¥ 636 è¡Œ â†’ å®¡æ ¸ç”Ÿæˆ audit_result 31 è¡Œ/audit_run 1 è¡Œ â†’ ç•Œé¢ç‚¹â€œæ¸…空”确认 â†’ è¿”回 dataRows=636/auditRows=31/auditRunRows=1/batchRows=1,DB ç›´æŸ¥å››è¡¨å…¨ 0 â†’ å†å¯¼å…¥ä» 636 è¡ŒæˆåŠŸã€‚
- UI å®žæµ‹ï¼ˆCodex åº”用内浏览器,admin ç™»å½•):按钮显示正常,弹窗标题“清空 2099-01 æ•°æ®â€ï¼Œç¡®è®¤åŽæç¤ºâ€œå·²æ¸…空 2099-01 æŠ¥è¡¨æœŸçš„æ•°æ®â€ï¼Œè¿›åº¦å…¨éƒ¨å›žâ€œæœªå¯¼å…¥â€ã€‚
- åå‘用例:非法报表期 `abc` è¢«æ‹’并提示格式;空报表期 `2098-12` è¿”回全 0 æˆåŠŸã€‚
- å›žå½’:清空前后真实月份批次分布与库内行数完全一致(2025-07=664、2026-07=636、2026-09=636 ç­‰ï¼‰ï¼Œé›¶å½±å“ã€‚
- åŽç«¯ `start-dev.ps1` å¯åŠ¨å°±ç»ªï¼ˆbackend.log `Started TrafficAuditApplication`),前端 dev Compiled successfully。
- æµ‹è¯•报告:docs/功能测试报告/功能测试报告_数据导入清空按钮按报表期清库_2026-09-10.md。
### é—留问题与待办
- å¾…用户实际浏览器验收“清空”按钮(建议先确认所选报表期与备份);如需只清某一数据类型,可后续做“按类型清空”。
- æ²¿ç”¨æ˜¨æ—¥æœªåŠ¨å¾…åŠžï¼šæ±‡æ€»å¤§è¡¨ M3(网约车台账取数、货运页 FreightCalc è§„上/规下、城市客运/中口径合成页)与“9 æœˆ+无母版自动扩列”;8 æœˆä»ç¼º 4 ç±»æºæ•°æ®è¡¨è¡Œï¼ˆfreight_turnover_import、scale_split_transport、passenger_individual_monthly、网约车拆分输入)。
## ä¸‹åˆï¼ˆ2026-09-10)清空功能增强:支持按类型清空 + æ¸…空按钮移出“刷新”防误触
### å®Œæˆå†…容
- ç”¨æˆ·åé¦ˆâ€œæ¸…空放在刷新旁边怕误触”,且需要能只清某一数据类型:把清空从侧栏标题行(刷新旁)移除,改到标题行下方独立红色危险操作区(浅红底 + è¾¹æ¡†ï¼Œâ€œæ¸…空数据…”按钮 + æç¤ºâ€œæŒ‰æŠ¥è¡¨æœŸæ¸…库,用于整月重导”),与刷新物理隔开。
- æ–°å¢žæ¸…空弹窗:单选“清空全部 / åªæ¸…空指定类型”,指定类型用多选下拉并按分组列出、标签带“(已导入 N è¡Œ/未导入)”;底部红色警示说明会同步删审核结果、已审核标记、导入批次(投资项目主档保留)且不可撤销;确认前再走一次二次确认。
- åŽç«¯ `POST /api/import/clear` å¢žåŠ å¯é€‰ `types`(逗号分隔):空=整期全清(原行为不变),非空=只清指定类型,并同步清理关联 audit_result/audit_run/import_batch;返回值增加 `scope` ä¸Ž `types`。新增类型→表/审核类型/批次类型三张静态映射与 `clearTypeData` åˆ†æ´¾ï¼ŒæŠ•资月度按项目类别过滤(主档保留)。
### æµ‹è¯•结果摘要
- ç”¨ä¸€æ¬¡æ€§æµ‹è¯•期 2099-01/2099-02 éªŒè¯ï¼šæ¸… h2032 â†’ dataRows=636、auditRows=31、auditRunRows=1、batchRows=1,DB æ ¸å¯¹å››è¡¨å¯¹åº”记录全 0;同期的 cityBus ä¸šåŠ¡ 142 è¡Œã€CITY_BUS å®¡æ ¸ 53 è¡Œã€audit_run ä¸Žæ‰¹æ¬¡å‡ä¿ç•™ï¼›2099-02 æ•°æ®ä¸å—影响。
- è´Ÿå‘:`types=notAType` â†’ 500“未指定有效的数据类型”;有效+未知混合 â†’ å¿½ç•¥æœªçŸ¥æŒ‰æœ‰æ•ˆæ‰§è¡Œï¼›ä¸ä¼  types â†’ æ•´æœŸå…¨æ¸…。
- æŠ•资类别:`types=investment` åªåˆ å®¢è¿ç«™åœºã€`types=investmentLogistics` åªåˆ ç‰©æµå›­åŒºï¼ŒæŠ•资主档保留。
- UI å®žæµ‹ï¼ˆåº”用内浏览器,admin ç™»å½•):“刷新”旁已无清空;新危险区按钮与弹窗文案正常;选中“道路货物运输月度生产情况(已导入 636 è¡Œï¼‰â€ç¡®è®¤åŽæç¤ºâ€œå·²æ¸…空 2099-01 æ•°æ®ï¼šä¸šåŠ¡æ•°æ® 636 è¡Œã€å®¡æ ¸ç»“æžœ 0 è¡Œã€å¯¼å…¥æ‰¹æ¬¡ 1 æ¡ï¼Œå¯ä»¥é‡æ–°å¯¼å…¥â€ï¼Œè¿›åº¦å›žâ€œæœªå¯¼å…¥â€ã€‚
- å›žå½’:测试期无残留,真实月份 2026-09=636、2026-07=636、2025-07=664 ä¸ŽçœŸå®žæ‰¹æ¬¡æ€»æ•° 239 å‡æœªå˜ã€‚
- åŽç«¯ `mvn -o -q compile` é€šè¿‡ï¼ŒæœåŠ¡å·²é‡å¯ï¼ˆPID 21884,08:54 å¯åŠ¨ï¼‰ï¼›å‰ç«¯ dev `Compiled successfully`。
- æµ‹è¯•报告:docs/功能测试报告/功能测试报告_导入清空按类型与按钮防误触_2026-09-10.md。
### é—留问题与待办
- å¾…用户在自己浏览器验收新按钮位置与弹窗文案;如仍觉得危险区太显眼可再收进“更多操作”折叠。
- æ²¿ç”¨æœªåŠ¨å¾…åŠžï¼šæ±‡æ€»å¤§è¡¨ M3(网约车台账取数、货运页 FreightCalc è§„上/规下、城市客运/中口径合成页)与“9 æœˆ+无母版自动扩列”;8 æœˆä»ç¼º 4 ç±»æºæ•°æ®è¡¨è¡Œï¼ˆfreight_turnover_import、scale_split_transport、passenger_individual_monthly、网约车拆分输入)。
## é™„:提交
- æœ¬æ¬¡æ”¹åЍ 3 ä¸ªä»£ç æ–‡ä»¶ + åŠŸèƒ½æµ‹è¯•æŠ¥å‘Šä¸Žæ—¥ç»“ï¼ŒæŒ‰è§„èŒƒå…ˆ `git fetch gitea/origin` å¯¹æ¯”合并,再 commit å¹¶åŒç«¯æŽ¨é€ï¼ˆgitea main、个人 gitee master)。
## æ™šé—´ï¼ˆ2026-09-10)业务学习:分市州货运量统计方法编制说明归档
### å®Œæˆå†…容
- è§£æžç”¨æˆ·æä¾›çš„ `【20230531】湖北省道路货物运输量统计方法(2023年)编制说明.docx`(2023å¹´5月编制,正文约 3494 å­— + 45 å¤„ OMML å…¬å¼ï¼‰ï¼Œæ•´ç†ä¸ºå¯ç›´æŽ¥æŸ¥é˜…的学习文档:
  `docs/货运/学习笔记_分市州道路货物运输量统计方法_2026-09-10.md`
- åŽŸæ–‡ docx ä¸€å¹¶å½’档到 `docs/货运/`,便于团队后续对照。
- ç¬”记内容:规上/规下界定、基月(2021å¹´9月,逐年滚动)确定方法、高速/国省道/运力三类波动系数与 0.5/0.3/0.2 åŠ æƒã€è§„ä¸Šè§„ä¸‹åå•å¹´åº¦åˆ‡æ¢çš„åŸºæœˆåŸºæ•°è°ƒæ•´ã€ä¸Žçœçº§æ•°æ®è¡”æŽ¥ç¼©æ”¾ã€å¸‚å·žé—´å¢žé€Ÿåè°ƒæ€§è°ƒæ•´ï¼ˆ1.5σ å†…、排名不变)、按新增速反推绝对量并二次衔接,另附完整流程串联、符号对照表、常见疑问与 45 å¤„公式清单。
### æŠ€æœ¯å¤‡æ³¨
- åŽŸæ–‡å…¬å¼æ˜¯ Word å…¬å¼å¯¹è±¡ï¼ˆOMML),在 Word ä¸­æ­£æ–‡å¯¹åº”位置为空白,直接看容易漏;已用脚本把 `m:oMath` è¿˜åŽŸæˆå¯è¯»å…¬å¼ï¼ˆå«åˆ†å¼ã€ä¸Šä¸‹æ ‡ã€æ±‚å’Œç¬¦å·ï¼‰ï¼Œç¡®è®¤æœ«å¼ä¸º `H_i''' = H_i'' Ã— H / âˆ‘H_i''`。
### é—留问题与待办
- æ ¹ç›®å½•留下的解析临时文件 `doc_extract.txt`、`doc_extract2.txt`、`tmp_extract.py` æœªç»ç”¨æˆ·åŒæ„ä¸åˆ é™¤ï¼Œå¾…确认后清理。
- æ²¿ç”¨æœªåŠ¨å¾…åŠžï¼šæ±‡æ€»å¤§è¡¨ M3(网约车台账取数、货运页 FreightCalc è§„上/规下、城市客运/中口径合成页)与「9 æœˆ+无母版自动扩列」;8 æœˆä»ç¼º 4 ç±»æºæ•°æ®è¡¨è¡Œã€‚
## æ™šé—´ï¼ˆ2026-09-10)文档整理:`出版.docx` ä¿®è®¢ï¼ˆè¡¨æ ¼è¿˜åŽŸ + æœ‰è¯¯æ•°æ®ä¿®æ­£ï¼‰
### å®Œæˆå†…容
- ç”¨æˆ·æä¾›çš„ `D:\桌面\出版.docx` å­˜åœ¨ç»“构性缺陷:90 æ®µè½ã€**0 ä¸ªçœŸå®žè¡¨æ ¼**,全部表格实为 Markdown ç®¡é“符文本行(`| a | b |`),在 Word ä¸­ä¸å¯é˜…读。
- å·²é‡å»ºä¸ºè§„范文档:`D:\桌面\出版_修订_2026-09-10.docx`(46 æ®µè½ã€**8 ä¸ª Word çœŸè¡¨æ ¼**)。
  - è¡¨æ ¼ 1:市州汇总表 9 è¡Œ Ã— 9 åˆ—;表格 2-8:7 ä¸ªå¸‚州的企业明细表,各 4 è¡Œ Ã— 7 åˆ—。
  - æ ¼å¼ï¼šå››çº¿è¾¹æ¡†ï¼ˆ7F7F7F / 4pt)、表头底纹 F2F2F2、单元格水平居中、列宽按 mm æŒ‡å®šã€å­—号 8pt(市州表)/ 8.5pt(企业表)。
  - æ–°å¢ž Heading 1 æ ‡é¢˜ï¼›7 ä¸ªå¸‚州名(武汉 / é»„石 / å®œæ˜Œ / è¥„阳 / è†å·ž / é»„冈 / å’¸å®ï¼‰å¥—用 Heading 3;Heading 1/2/3 å­—体色统一为黑色。
- åŒæ­¥ä¿®æ­£ 4 å¤„有误内容:武汉 `+0.57%`->`+0.6%`;黄石"量价背离"表述改为"货量与周转量走势不同向最明显";宜昌差异覆盖率表述重写(>=30% çš„ 50 å®¶ï¼Œè¦†ç›– 100%,其中 29 å®¶ >=100%,8 æœˆå·®å¼‚率 +77.0% å±…全省第二);黄冈数字口径修正(>=30% çš„ 49 å®¶ã€>=100% çš„ 39 å®¶å  75% å…¨çœæœ€é«˜ï¼Œ8 æœˆå·®å¼‚率 +120.2%)。
- ç”Ÿæˆè„šæœ¬ `_fix_docx.py`;原文件 `D:\桌面\出版.docx` ä¿æŒä¸åŠ¨ã€‚
### æµ‹è¯•结果摘要(渲染 + è§†è§‰æ ¡éªŒï¼‰
- æœ¬æœºæ—  LibreOffice,改用 Word COM å¯¼å‡º PDF(`_render_check\publish_rev.pdf`),再用 pypdfium2 è½¬ 150 DPI PNG é€é¡µç›®æ£€ã€‚
- 6 é¡µï¼ˆpage01-page06)全部渲染正常:表格无越界、无文字裁切、无断页异常,未发现问题。
### é—留问题与待办
- å¾…用户确认 4 å¤„文字修正口径是否可接受;如还有其他"有误的部分"需再改。
- æ¸²æŸ“临时目录 `_render_check\` ä¸Žè„šæœ¬ `_fix_docx.py`、`_word2pdf.ps1` æœªç»ç”¨æˆ·åŒæ„ä¸åˆ é™¤ã€‚
- æ²¿ç”¨æœªåŠ¨å¾…åŠžï¼šæ±‡æ€»å¤§è¡¨ M3(网约车台账取数、货运页 FreightCalc è§„上/规下、城市客运/中口径合成页)与「9 æœˆ+无母版自动扩列」;8 æœˆä»ç¼º 4 ç±»æºæ•°æ®è¡¨è¡Œã€‚
docs/»õÔË/¡¾20230531¡¿ºþ±±Ê¡µÀ·»õÎïÔËÊäÁ¿Í³¼Æ·½·¨£¨2023Ä꣩±àÖÆËµÃ÷.docx
Binary files differ
docs/»õÔË/ѧϰ±Ê¼Ç_·ÖÊÐÖݵÀ·»õÎïÔËÊäÁ¿Í³¼Æ·½·¨_2026-09-10.md
New file
@@ -0,0 +1,219 @@
# å­¦ä¹ ç¬”记:湖北省道路货物运输量分市州统计方法(2023年编制说明)
- æ•´ç†æ—¥æœŸï¼š2026-09-10
- åŽŸæ–‡æ¥æºï¼š`【20230531】湖北省道路货物运输量统计方法(2023年)编制说明.docx`(2023å¹´5月编制)
- åŽŸæ–‡å‰¯æœ¬ï¼šæœ¬ç›®å½• `【20230531】湖北省道路货物运输量统计方法(2023年)编制说明.docx`
- è¯´æ˜Žï¼šåŽŸæ–‡å…¬å¼ä¸º Word å…¬å¼å¯¹è±¡ï¼ˆOMML),在 Word é‡Œæ­£æ–‡ä¸­çš„符号位置是空白的,容易看漏。本笔记已把 45 å¤„公式全部还原并附于文末。
---
## ä¸€ã€ä¸€å¥è¯ç†è§£
全省货运量是已知的(省级口径),报告要的是**分市州(17个地市)**的数据。
> è·¯å¾„是:规上企业有企业直报(真数据),规下业户没法逐一统计,就用「**基月运输量 Ã— æœ¬æœˆæ³¢åŠ¨ç³»æ•°**」推算,最后做两次全省校准 + ä¸€æ¬¡å¢žé€Ÿåè°ƒã€‚
```
道路货物运输量 = è§„上道路货物运输企业运输量(直报)+ è§„下道路货物运输经营业户运输量(推算)
```
### è§„上 / è§„下的界定
| å£å¾„ | å®šä¹‰ | æ•°æ®æ¥æº |
| --- | --- | --- |
| è§„上 | ä¸»è¥é“路货物运输、年营业收入 **1000万元以上** ä¸”拥有货运车辆 **50辆及以上** çš„道路货运法人企业 | ä¼ä¸šæ¯æœˆåœ¨ã€Œäº¤é€šè¿è¾“企业一套表联网直报系统」填报 |
| è§„下 | é™¤è§„上以外的全部经营业户(个体户、小企业等) | æ— æ³•直报,按本方案推算 |
---
## äºŒã€æ€»ä½“骨架(四条腿)
| çŽ¯èŠ‚ | ä½œç”¨ |
| --- | --- |
| â‘  åŸºæœˆï¼ˆ2021å¹´9月) | æŽ¨ç®—的「锚点」,给出各市州规下运输量的起点值 |
| â‘¡ ä¸‰ä¸ªæ³¢åŠ¨ç³»æ•° | ç”¨é«˜é€Ÿå…¬è·¯ã€å›½çœé“交通量、运力三套数据,衡量本月相对基月的涨跌 |
| â‘¢ åŠ æƒ 0.5 / 0.3 / 0.2 | ä¸‰å¥—数据合成为一个系数 |
| â‘£ ä¸¤æ¬¡å…¨çœæ ¡å‡† + ä¸€æ¬¡å¢žé€Ÿåè°ƒ | ä¿è¯ 17 ä¸ªå¸‚州加总等于全省,且增速差异可控 |
---
## ä¸‰ã€æŽ¨ç®—主流程(规下部分)
### ç¬¬ 1 æ­¥ï¼šç¡®å®šåŸºæœŸæ•°æ®ï¼ˆåŸºæœˆå€¼ï¼‰
因为一直缺乏日常分市州运输量统计,需先确定基月(2021å¹´9月)各市州运输量。方法为两个来源各占 50%:
- **来源A:2019年全国道路货物运输量专项调查数据**
  ç”¨è°ƒæŸ¥æœˆå„地市货运量/周转量计算各地市占比,乘以 2021å¹´9月全省货运量/周转量总量。
- **来源B:2021å¹´9月各地市运力数据**
  ç”¨å„地市载货汽车吨位合计数计算占比,乘以 2021å¹´9月全省总量。
```
各地市基期运输量 = åŸºäºŽä¸“项调查推算值 Ã— 0.5 + åŸºäºŽ2021å¹´9月运力推算值 Ã— 0.5
```
> åŸºæœˆæ»šåŠ¨è§„åˆ™ï¼šä»¥ 2021å¹´9月为基月,**此后每年1月起,将前1å¹´9月的运输量作为新的基月**。
### ç¬¬ 2 æ­¥ï¼šè®¡ç®—三个波动系数
| æ¥æº | æ•°æ®æä¾›æ–¹ | è´§è¿é‡ç³»æ•° | å‘¨è½¬é‡ç³»æ•° | æƒé‡ |
| --- | --- | --- | --- | --- |
| é«˜é€Ÿå…¬è·¯æ”¶è´¹æ•°æ® | æ¹–北省高速公路联网收费中心 | è½¦è´§æ€»é‡ `C` | âˆ‘(车货总重 Ã— è¡Œé©¶é‡Œç¨‹) `S` | **0.5** |
| æ™®é€šå›½çœé“交通量 | æ¹–北省公路事业发展中心 | æ—¥å‡æ–­é¢äº¤é€šé‡ `L` | åŒ `L` | **0.3** |
| è¿åŠ›ï¼ˆè¿æ”¿åº“ï¼‰ | æ¹–北省货运物流事业发展中心 | è¥è¿è´§è½¦å¨ä½æ•° `D` | åŒ `D` | **0.2** |
公式(`_d` è¡¨ç¤ºåŸºæœˆå€¼ï¼Œ`H`=货运量,`Z`=货物周转量):
```
H⁽¹⁾ = H_d Ã— C / C_d          Z⁽¹⁾ = Z_d Ã— S / S_d      ï¼ˆé«˜é€Ÿï¼‰
H⁽²⁾ = H_d Ã— L / L_d          Z⁽²⁾ = Z_d Ã— L / L_d      ï¼ˆå›½çœé“)
H⁽³⁾ = H_d Ã— D / D_d          Z⁽³⁾ = Z_d Ã— D / D_d      ï¼ˆè¿åŠ›ï¼‰
```
### ç¬¬ 3 æ­¥ï¼šåŠ æƒåˆæˆåˆæ­¥æŽ¨ç®—ç»“æžœ
```
H' = H⁽¹⁾ Ã— W⁽¹,¹⁾ + H⁽²⁾ Ã— W⁽¹,²⁾ + H⁽³⁾ Ã— W⁽¹,³⁾
Z' = Z⁽¹⁾ Ã— W⁽²,¹⁾ + Z⁽²⁾ Ã— W⁽²,²⁾ + Z⁽³⁾ Ã— W⁽²,³⁾
权重:W⁽¹,¹⁾=W⁽²,¹⁾=0.5;W⁽¹,²⁾=W⁽²,²⁾=0.3;W⁽¹,³⁾=W⁽²,³⁾=0.2
```
### ç¬¬ 4 æ­¥ï¼šè§„下基期调整(规上/规下名单年度更新)
企业规模变化导致「规上↔规下」身份变动时,按年调整基月规下基数:
```
基月规下运输量基数 = ä¸Šä¸€å¹´åŸºæœˆè§„下运输量 âˆ’ æœ¬å¹´å˜åŒ–车辆数 Ã— å•车运输量
本年变化车辆数 = æœ¬å¹´è§„上车辆数 âˆ’ ä¸Šä¸€å¹´åŸºæœˆè§„上车辆数      ï¼ˆæ¥è‡ªäº¤ä¼ç»Ÿ101表)
单车运输量     = ä¸Šä¸€å¹´åŸºæœˆè§„上运输量 Ã· ä¸Šä¸€å¹´åŸºæœˆè§„上车辆数
```
---
## å››ã€ä¸‰æ­¥ã€Œè°ƒæ•´ã€ï¼ˆæœ€å®¹æ˜“被绕晕的部分)
### è°ƒæ•´â‘  ä¸Žçœçº§æ•°æ®è¡”接(比例缩放)
各市州初步推算结果加总后与全省推算结果有差异,需按全省总量等比调整:
```
H_i' = H_i Ã— H / âˆ‘H_i
Z_i' = Z_i Ã— Z / âˆ‘Z_i
```
含义:第 i ä¸ªå¸‚州结果 Ã—(全省总量 Ã· å„市州初步推算加总)。
### è°ƒæ•´â‘¡ å¸‚州间增速协调性调整
- **背景**:货运量增速服务于季度 GDP è¯„估和行业增加值核算,对代表性、稳定性要求高;但市州一级高速收费站和国省道观测站点布局有限,直接推算精度受限。
- **目的**:避免各市州增速与周边差异过大引起争议。做法是把增速差异做线性变换,**使结果落在原增速的 1.5 å€æ ‡å‡†å·®å†…**,同时**不改变各市州增速排名**。
```
1) è®¡ç®—各市州增速 h_i
2) h_i'  = (h_i âˆ’ h_min) / (h_max âˆ’ h_min) Ã— 1.5 Ã— h_std     â† å½’一化后落到 0 ~ 1.5σ
   h_i'' = h_i' âˆ’ h̄ + h̄'                                     â† æ•´ä½“平移,使均值回到原均值
3) æŒ‰æ–°å¢žé€ŸåæŽ¨ç»å¯¹é‡ï¼Œå†æŒ‰å…¨çœæ€»é‡è°ƒæ•´ä¸€æ¬¡
```
符号:`h_i`初步推算增速、`h_max`/`h_min`各市州增速最大值/最小值、`h_std`增速标准差、`h̄`调整中间结果的增速均值、`h̄'`(原)市级运输量增速、`h_i'`调整中间结果、`h_i''`调整后增速。
### è°ƒæ•´â‘¢ æŒ‰æ–°å¢žé€ŸåæŽ¨ç»å¯¹é‡å¹¶å†æ¬¡è¡”接全省
```
H_i''  = HL_i Ã— (1 + h_i'')          ï¼ˆHL_i:上一年同期第 i ä¸ªå¸‚州的月度货运量/周转量)
H_i''' = H_i'' Ã— H / âˆ‘H_i''          ï¼ˆå†æŒ‰å…¨çœæ€»é‡ç¼©æ”¾ï¼Œå¾—到最终值)
```
`H_i'''` å³æœ€ç»ˆä¸ŠæŠ¥çš„第 i ä¸ªå¸‚州当月道路货运量(周转量)。
---
## äº”、完整流程串一遍
```
① æ¯æœˆé‡‡é›†ï¼šé«˜é€Ÿæ”¶è´¹æ•°æ® + æ™®é€šå›½çœé“交通量 + è¿æ”¿åº“运力数据
        â†“
② ä¸‰ç±»æ•°æ®å„自算「本月 Ã· åŸºæœˆã€æ³¢åŠ¨ç³»æ•°ï¼Œå¾—åˆ° H⁽¹⁾/Z⁽¹⁾、H⁽²⁾/Z⁽²⁾、H⁽³⁾/Z⁽³⁾
        â†“
③ åŠ æƒ 0.5 / 0.3 / 0.2 â†’ è§„下运输量初步推算值 H' / Z'
        â†“
④ åŠ è§„ä¸Šä¼ä¸šç›´æŠ¥å€¼ â†’ å„市州运输量
        â†“
⑤ æŒ‰å…¨çœæ€»é‡ç­‰æ¯”缩放(与省级数据衔接)
        â†“
⑥ å¸‚州间增速协调性调整(压到 1.5σ å†…,排名不变)
        â†“
⑦ æŒ‰æ–°å¢žé€ŸåæŽ¨ç»å¯¹é‡ï¼Œå†æŒ‰å…¨çœæ€»é‡ç¼©æ”¾ â†’ æœ€ç»ˆå„市州货运量 / å‘¨è½¬é‡
```
---
## å…­ã€å¸¸è§ç–‘é—®
| ç–‘é—® | è§£ç­” |
| --- | --- |
| è§„下为什么用「推算」而不是统计? | ä¸ªä½“户数量庞大且无名录,无法逐一采集,只能用行业指标的相对变化推算。 |
| ä¸ºä»€ä¹ˆå¿…须设「基月」? | ä»Žæ¥æ²¡æœ‰åˆ†å¸‚州历史绝对值,只能定一个锚点,之后看相对变化。 |
| æƒé‡ä¸ºä»€ä¹ˆæ˜¯ 0.5 / 0.3 / 0.2? | æ²¿ç”¨çœçº§æ–¹æ¡ˆï¼šé«˜é€Ÿæ•°æ®è¦†ç›–最全最准(0.5);国省道覆盖广但市州级站点有限(0.3);运力数据相关性较强但更新/口径有滞后(0.2)。 |
| ä¸ºä»€ä¹ˆã€Œå…¨çœæ ¡å‡†ã€åšä¸¤æ¬¡ï¼Ÿ | ç¬¬ä¸€æ¬¡æ˜¯åˆæ­¥æŽ¨ç®—后归口到全省;第二次是增速调整后数值又变了,需要再归口一次,保证各市州加总严格等于全省总量。 |
| ã€Œå¢žé€Ÿåè°ƒã€æ˜¯ä¸æ˜¯åœ¨æ”¹æ•°æ®ï¼Ÿ | åŽŸæ–‡å£å¾„ï¼š**排名不变**,只把市州间差距按 1.5 å€æ ‡å‡†å·®æ”¶æ•›ï¼Œé¿å…ä¸ªåˆ«å¸‚州因站点少而大起大落。 |
| é«˜é€Ÿæ•°æ®å–哪个方向? | åŽŸæ–‡è¡¨è¿°ä¸ºã€Œå£å¾„åŒ…æ‹¬å„ç«™å…¥å£æ–¹å‘çš„é€šè¡Œæ•°æ®ã€ï¼Œå³æŒ‰å…¥å£æ–¹å‘å£å¾„æ±‡æ€»ã€‚ |
---
## ä¸ƒã€ç¬¦å·å¯¹ç…§è¡¨
| ç¬¦å· | å«ä¹‰ |
| --- | --- |
| `H` / `Z` | é“路货运量 / è´§ç‰©å‘¨è½¬é‡ï¼ˆå…¨çœå½“月) |
| `H_d` / `Z_d` | åŸºæœˆæœˆåº¦è§„下道路货运量 / è´§ç‰©å‘¨è½¬é‡ |
| `H_i` / `Z_i` | ç¬¬ i ä¸ªå¸‚州当月初步推算结果 |
| `H_i'` / `Z_i'` | ç¬¬ i ä¸ªå¸‚州调整后的结果 |
| `C` / `S` | å½“月月度车货总重 / âˆ‘(车货总重 Ã— è¡Œé©¶é‡Œç¨‹) |
| `L` | æ—¥å‡æ–­é¢äº¤é€šé‡ï¼ˆæ™®é€šå›½çœé“) |
| `D` | è¥è¿è´§è½¦å¨ä½æ•°ï¼ˆè¿æ”¿åº“) |
| ä¸Šæ ‡ `(1)(2)(3)` | åˆ†åˆ«ä»£è¡¨é«˜é€Ÿã€å›½çœé“、运力三个来源 |
| `W^(m,n)` | åŠ æƒæƒé‡ï¼ˆ0.5 / 0.3 / 0.2) |
| `h_i` / `h_i'` / `h_i''` | ç¬¬ i ä¸ªå¸‚州初步推算增速 / è°ƒæ•´ä¸­é—´ç»“æžœ / è°ƒæ•´åŽå¢žé€Ÿ |
| `HL_i` | ä¸Šä¸€å¹´åŒæœŸç¬¬ i ä¸ªå¸‚州的月度货运量(周转量) |
---
## é™„:原文公式全清单(45 å¤„)
```
【基期数据】
各地市基期运输量 = åŸºäºŽä¸“项调查推算值 Ã— 0.5 + åŸºäºŽ2021å¹´9月运力推算值 Ã— 0.5
【规下基期调整】
基月规下运输量基数 = ä¸Šä¸€å¹´åŸºæœˆè§„下运输量 âˆ’ æœ¬å¹´å˜åŒ–车辆数 Ã— å•车运输量
本年变化车辆数 = æœ¬å¹´è§„上车辆数 âˆ’ ä¸Šä¸€å¹´åŸºæœˆè§„上车辆数
单车运输量 = ä¸Šä¸€å¹´åŸºæœˆè§„上运输量 Ã· ä¸Šä¸€å¹´åŸºæœˆè§„上车辆数
【高速数据推算】
H⁽¹⁾ = H_d Ã— C / C_d
Z⁽¹⁾ = Z_d Ã— S / S_d
【普通国省道交通量推算】
H⁽²⁾ = H_d Ã— L / L_d
Z⁽²⁾ = Z_d Ã— L / L_d
【运力数据推算】
H⁽³⁾ = H_d Ã— D / D_d
Z⁽³⁾ = Z_d Ã— D / D_d
【加权计算】
H' = H⁽¹⁾ Ã— W⁽¹,¹⁾ + H⁽²⁾ Ã— W⁽¹,²⁾ + H⁽³⁾ Ã— W⁽¹,³⁾
Z' = Z⁽¹⁾ Ã— W⁽²,¹⁾ + Z⁽²⁾ Ã— W⁽²,²⁾ + Z⁽³⁾ Ã— W⁽²,³⁾
W⁽¹,¹⁾=W⁽²,¹⁾=0.5,W⁽¹,²⁾=W⁽²,²⁾=0.3,W⁽¹,³⁾=W⁽²,³⁾=0.2
【与省级数据衔接调整】
H_i' = H_i Ã— H / âˆ‘H_i
Z_i' = Z_i Ã— Z / âˆ‘Z_i
【市州间增速协调性调整】
h_i'  = (h_i âˆ’ h_min) / (h_max âˆ’ h_min) Ã— 1.5 Ã— h_std
h_i'' = h_i' âˆ’ h̄ + h̄'
【按新增速反推绝对量并再次衔接】
H_i''  = HL_i Ã— (1 + h_i'')
H_i''' = H_i'' Ã— H / âˆ‘H_i''
```
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
@@ -443,4 +443,27 @@
        return Result.ok(result);
    }
    /**
     * æ¸…空指定报表期已导入数据与审核结果(数据导入页"清空数据"入口调用),便于整月重新导入。
     * types ä¸ºç©ºè¡¨ç¤ºæ¸…空该报表期全部类型;否则只清空指定数据类型(逗号分隔,如 h2032,cityBus)。
     */
    @PostMapping("/clear")
    public Result<Map<String, Object>> clearData(@RequestParam("period") String period,
                                                 @RequestParam(value = "types", required = false) String types) {
        try {
            List<String> typeList = new java.util.ArrayList<>();
            if (types != null) {
                for (String t : types.split(",")) {
                    String s = t.trim();
                    if (!s.isEmpty()) typeList.add(s);
                }
            }
            Map<String, Object> stats = importService.clearPeriod(period, typeList);
            return Result.ok(stats);
        } catch (Exception e) {
            log.error("clear period {} types {} error", period, types, e);
            return Result.error("清空失败: " + e.getMessage());
        }
    }
}
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
@@ -2,7 +2,9 @@
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.trafficaudit.auditengine.entity.AuditResult;
import com.trafficaudit.auditengine.entity.AuditRun;
import com.trafficaudit.auditengine.mapper.AuditResultMapper;
import com.trafficaudit.auditengine.mapper.AuditRunMapper;
import com.trafficaudit.common.util.RegionUtil;
import com.trafficaudit.dataimport.entity.EnergyAuthVehicle;
import com.trafficaudit.dataimport.entity.EnergyVehicleQuarterly;
@@ -56,6 +58,7 @@
import org.apache.poi.ss.usermodel.WorkbookFactory;
import cn.hutool.core.io.IoUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
@@ -142,6 +145,8 @@
    private FreightTurnoverImportMapper freightTurnoverMapper;
    @Resource
    private AuditResultMapper auditResultMapper;
    @Resource
    private AuditRunMapper auditRunMapper;
    @Resource
    private PassengerEnterpriseMonthlyMapper passengerMapper;
    @Resource
@@ -1312,6 +1317,273 @@
        }
    }
    /** æ”¯æŒâ€œæŒ‰ç±»åž‹æ¸…空”的数据类型 -> æ•°æ®è¡¨æ“ä½œé”®ï¼ˆåŒè¡¨åŒç±»åˆ«å½’并,避免重复删除) */
    private static final Map<String, String> CLEAR_TYPE_TO_OP = new LinkedHashMap<>();
    /** æ•°æ®ç±»åž‹ -> å…³è”审核规则类型(同步清除审核结果与已审核标记) */
    private static final Map<String, String[]> CLEAR_TYPE_TO_AUDIT = new HashMap<>();
    /** æ•°æ®ç±»åž‹ -> å…³è”导入批次 importType(同步清除导入批次记录) */
    private static final Map<String, String[]> CLEAR_TYPE_TO_BATCH = new HashMap<>();
    static {
        CLEAR_TYPE_TO_OP.put("h2032", "H2032");
        CLEAR_TYPE_TO_OP.put("transportAuth", "TRANSPORT_AUTH");
        CLEAR_TYPE_TO_OP.put("trackMileage", "TRACK_MILEAGE");
        CLEAR_TYPE_TO_OP.put("scaleSplit", "SCALE_SPLIT");
        CLEAR_TYPE_TO_OP.put("freightTurnover", "FREIGHT_TURNOVER");
        CLEAR_TYPE_TO_OP.put("passengerMonthly", "H2031");
        CLEAR_TYPE_TO_OP.put("passengerAuth", "PASSENGER_AUTH");
        CLEAR_TYPE_TO_OP.put("passengerIndividual", "PASSENGER_INDIVIDUAL");
        CLEAR_TYPE_TO_OP.put("energyMonthly", "H204");
        CLEAR_TYPE_TO_OP.put("energyAuth", "ENERGY_AUTH");
        CLEAR_TYPE_TO_OP.put("investment", "INVEST_MONTHLY_PASSENGER");
        CLEAR_TYPE_TO_OP.put("investCityPassenger", "INVEST_MONTHLY_PASSENGER");
        CLEAR_TYPE_TO_OP.put("investmentLogistics", "INVEST_MONTHLY_LOGISTICS");
        CLEAR_TYPE_TO_OP.put("investCityLogistics", "INVEST_MONTHLY_LOGISTICS");
        CLEAR_TYPE_TO_OP.put("investmentSystem", "INVEST_SYSTEM");
        CLEAR_TYPE_TO_OP.put("cityBus", "CITY_BUS");
        CLEAR_TYPE_TO_OP.put("cityTaxi", "CITY_TAXI");
        CLEAR_TYPE_TO_OP.put("cityTaxiAuth", "CITY_TAXI_AUTH");
        CLEAR_TYPE_TO_OP.put("wycTotal", "WYC_TOTAL");
        CLEAR_TYPE_TO_OP.put("wycOrder", "WYC_ORDER");
        CLEAR_TYPE_TO_AUDIT.put("h2032", new String[]{"H2032"});
        CLEAR_TYPE_TO_AUDIT.put("transportAuth", new String[]{"H2032"});
        CLEAR_TYPE_TO_AUDIT.put("trackMileage", new String[]{"H2032"});
        CLEAR_TYPE_TO_AUDIT.put("scaleSplit", new String[]{"H2032"});
        CLEAR_TYPE_TO_AUDIT.put("freightTurnover", new String[]{"H2032"});
        CLEAR_TYPE_TO_AUDIT.put("passengerMonthly", new String[]{"H2031"});
        CLEAR_TYPE_TO_AUDIT.put("passengerAuth", new String[]{"H2031"});
        CLEAR_TYPE_TO_AUDIT.put("passengerIndividual", new String[]{"H2031"});
        CLEAR_TYPE_TO_AUDIT.put("energyMonthly", new String[]{"H204"});
        CLEAR_TYPE_TO_AUDIT.put("energyAuth", new String[]{"H204"});
        CLEAR_TYPE_TO_AUDIT.put("investment", new String[]{"INVEST"});
        CLEAR_TYPE_TO_AUDIT.put("investmentLogistics", new String[]{"INVEST"});
        CLEAR_TYPE_TO_AUDIT.put("investCityPassenger", new String[]{"INVEST"});
        CLEAR_TYPE_TO_AUDIT.put("investCityLogistics", new String[]{"INVEST"});
        CLEAR_TYPE_TO_AUDIT.put("investmentSystem", new String[]{"INVEST"});
        CLEAR_TYPE_TO_AUDIT.put("cityBus", new String[]{"CITY_BUS"});
        CLEAR_TYPE_TO_AUDIT.put("cityTaxi", new String[]{"CITY_TAXI"});
        CLEAR_TYPE_TO_AUDIT.put("cityTaxiAuth", new String[]{"CITY_TAXI"});
        String[] investPassengerBatch = {"INVEST_客运站场", "INVEST_客运站场_CITY"};
        String[] investLogisticsBatch = {"INVEST_物流园区", "INVEST_物流园区_CITY"};
        CLEAR_TYPE_TO_BATCH.put("h2032", new String[]{"H2032"});
        CLEAR_TYPE_TO_BATCH.put("transportAuth", new String[]{"TRANSPORT_AUTH"});
        CLEAR_TYPE_TO_BATCH.put("trackMileage", new String[]{"TRACK_MILEAGE"});
        CLEAR_TYPE_TO_BATCH.put("scaleSplit", new String[]{"SCALE_SPLIT"});
        CLEAR_TYPE_TO_BATCH.put("freightTurnover", new String[]{"FREIGHT_TURNOVER"});
        CLEAR_TYPE_TO_BATCH.put("passengerMonthly", new String[]{"H2031"});
        CLEAR_TYPE_TO_BATCH.put("passengerAuth", new String[]{"PASSENGER_AUTH"});
        CLEAR_TYPE_TO_BATCH.put("passengerIndividual", new String[]{"PASSENGER_INDIVIDUAL"});
        CLEAR_TYPE_TO_BATCH.put("energyMonthly", new String[]{"H204"});
        CLEAR_TYPE_TO_BATCH.put("energyAuth", new String[]{"ENERGY_AUTH"});
        CLEAR_TYPE_TO_BATCH.put("investment", investPassengerBatch);
        CLEAR_TYPE_TO_BATCH.put("investCityPassenger", investPassengerBatch);
        CLEAR_TYPE_TO_BATCH.put("investmentLogistics", investLogisticsBatch);
        CLEAR_TYPE_TO_BATCH.put("investCityLogistics", investLogisticsBatch);
        CLEAR_TYPE_TO_BATCH.put("investmentSystem", new String[]{"INVEST_SYSTEM"});
        CLEAR_TYPE_TO_BATCH.put("cityBus", new String[]{"CITY_BUS"});
        CLEAR_TYPE_TO_BATCH.put("cityTaxi", new String[]{"CITY_TAXI"});
        CLEAR_TYPE_TO_BATCH.put("cityTaxiAuth", new String[]{"CITY_TAXI_AUTH"});
        CLEAR_TYPE_TO_BATCH.put("wycTotal", new String[]{"WYC_TOTAL"});
        CLEAR_TYPE_TO_BATCH.put("wycOrder", new String[]{"WYC_ORDER"});
    }
    /**
     * æ¸…空指定报表期已导入数据与审核结果,用于整月重导;投资项目主档保留。
     *
     * @param types éœ€æ¸…空的数据类型(前端类型键,如 h2032/cityBus);为空则清空该报表期全部类型
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> clearPeriod(String period, List<String> types) {
        if (period == null || !period.matches("\\d{4}-\\d{2}")) {
            throw new IllegalArgumentException("报表期格式不正确,应为 yyyy-MM");
        }
        Set<String> selected = new LinkedHashSet<>();
        if (types != null) {
            for (String t : types) {
                if (t != null && !t.trim().isEmpty()) selected.add(t.trim());
            }
        }
        boolean clearAll = selected.isEmpty();
        int dataRows = 0;
        int auditRows = 0;
        int auditRunRows = 0;
        int batchRows = 0;
        if (clearAll) {
        dataRows += h2032Mapper.delete(new LambdaQueryWrapper<H2032EnterpriseMonthly>()
            .eq(H2032EnterpriseMonthly::getReportPeriod, period));
        dataRows += transportAuthMapper.delete(new LambdaQueryWrapper<TransportAuthVehicle>()
            .eq(TransportAuthVehicle::getReportPeriod, period));
        dataRows += trackMileageMapper.delete(new LambdaQueryWrapper<VehicleTrackMileage>()
            .eq(VehicleTrackMileage::getReportPeriod, period));
        dataRows += scaleSplitMapper.delete(new LambdaQueryWrapper<ScaleSplitTransport>()
            .eq(ScaleSplitTransport::getReportPeriod, period));
        dataRows += freightTurnoverMapper.delete(new LambdaQueryWrapper<FreightTurnoverImport>()
            .eq(FreightTurnoverImport::getReportPeriod, period));
        dataRows += passengerMapper.delete(new LambdaQueryWrapper<PassengerEnterpriseMonthly>()
            .eq(PassengerEnterpriseMonthly::getReportPeriod, period));
        dataRows += passengerIndividualMapper.delete(new LambdaQueryWrapper<PassengerIndividualMonthly>()
            .eq(PassengerIndividualMonthly::getReportPeriod, period));
        dataRows += passengerAuthMapper.delete(new LambdaQueryWrapper<PassengerAuthVehicle>()
            .eq(PassengerAuthVehicle::getReportPeriod, period));
        dataRows += energyMapper.delete(new LambdaQueryWrapper<EnergyVehicleQuarterly>()
            .eq(EnergyVehicleQuarterly::getReportPeriod, period));
        dataRows += energyAuthMapper.delete(new LambdaQueryWrapper<EnergyAuthVehicle>()
            .eq(EnergyAuthVehicle::getReportPeriod, period));
        dataRows += investMonthlyMapper.delete(new LambdaQueryWrapper<InvestmentMonthly>()
            .eq(InvestmentMonthly::getReportPeriod, period));
        dataRows += investSystemMapper.delete(new LambdaQueryWrapper<InvestmentSystem>()
            .eq(InvestmentSystem::getReportPeriod, period));
        dataRows += cityBusMapper.delete(new LambdaQueryWrapper<CityBusMonthly>()
            .eq(CityBusMonthly::getReportPeriod, period));
        dataRows += cityTaxiMapper.delete(new LambdaQueryWrapper<CityTaxiMonthly>()
            .eq(CityTaxiMonthly::getReportPeriod, period));
        dataRows += cityTaxiAuthMapper.delete(new LambdaQueryWrapper<CityTaxiAuth>()
            .eq(CityTaxiAuth::getReportPeriod, period));
        dataRows += wycTotalMapper.delete(new LambdaQueryWrapper<WycTotalMonthly>()
            .eq(WycTotalMonthly::getReportPeriod, period));
        dataRows += wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>()
            .eq(WycOrderMonthly::getReportPeriod, period));
        auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>()
            .eq(AuditResult::getReportPeriod, period));
        auditRunRows = auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>()
            .eq(AuditRun::getReportPeriod, period));
        batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>()
            .eq(ImportBatch::getReportPeriod, period));
        } else {
            Set<String> ops = new LinkedHashSet<>();
            Set<String> auditTypes = new LinkedHashSet<>();
            Set<String> batchTypes = new LinkedHashSet<>();
            for (String t : selected) {
                String op = CLEAR_TYPE_TO_OP.get(t);
                if (op == null) {
                    log.warn("清空数据:未知数据类型 {},已忽略", t);
                    continue;
                }
                ops.add(op);
                String[] at = CLEAR_TYPE_TO_AUDIT.get(t);
                if (at != null) java.util.Collections.addAll(auditTypes, at);
                String[] bt = CLEAR_TYPE_TO_BATCH.get(t);
                if (bt != null) java.util.Collections.addAll(batchTypes, bt);
            }
            if (ops.isEmpty()) {
                throw new IllegalArgumentException("未指定有效的数据类型");
            }
            for (String op : ops) {
                dataRows += clearTypeData(op, period);
            }
            if (!auditTypes.isEmpty()) {
                List<Long> ruleIds = new ArrayList<>();
                for (com.trafficaudit.rulemanage.entity.AuditRule rule : ruleMapper.selectList(null)) {
                    if (rule.getReportType() != null && auditTypes.contains(rule.getReportType())) {
                        ruleIds.add(rule.getId());
                    }
                }
                if (!ruleIds.isEmpty()) {
                    auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>()
                        .eq(AuditResult::getReportPeriod, period)
                        .in(AuditResult::getRuleId, ruleIds));
                }
                for (String rt : auditTypes) {
                    auditRunRows += auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>()
                        .eq(AuditRun::getReportPeriod, period)
                        .eq(AuditRun::getReportType, rt));
                }
            }
            if (!batchTypes.isEmpty()) {
                batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>()
                    .eq(ImportBatch::getReportPeriod, period)
                    .in(ImportBatch::getImportType, batchTypes));
            }
        }
        Map<String, Object> stats = new LinkedHashMap<>();
        stats.put("period", period);
        stats.put("scope", clearAll ? "all" : "types");
        if (!clearAll) stats.put("types", new ArrayList<>(selected));
        stats.put("dataRows", dataRows);
        stats.put("auditRows", auditRows);
        stats.put("auditRunRows", auditRunRows);
        stats.put("batchRows", batchRows);
        log.info("清空报表期 {}({})完成:业务数据 {} è¡Œã€å®¡æ ¸ç»“æžœ {} è¡Œã€å®¡æ ¸æ ‡è®° {} è¡Œã€å¯¼å…¥æ‰¹æ¬¡ {} è¡Œ",
            period, clearAll ? "全部类型" : String.join(",", selected), dataRows, auditRows, auditRunRows, batchRows);
        return stats;
    }
    /** æŒ‰â€œæ•°æ®è¡¨æ“ä½œé”®â€æ¸…空对应业务表(投资月度按项目类别过滤),返回删除行数 */
    private int clearTypeData(String op, String period) {
        switch (op) {
            case "H2032":
                return h2032Mapper.delete(new LambdaQueryWrapper<H2032EnterpriseMonthly>()
                    .eq(H2032EnterpriseMonthly::getReportPeriod, period));
            case "TRANSPORT_AUTH":
                return transportAuthMapper.delete(new LambdaQueryWrapper<TransportAuthVehicle>()
                    .eq(TransportAuthVehicle::getReportPeriod, period));
            case "TRACK_MILEAGE":
                return trackMileageMapper.delete(new LambdaQueryWrapper<VehicleTrackMileage>()
                    .eq(VehicleTrackMileage::getReportPeriod, period));
            case "SCALE_SPLIT":
                return scaleSplitMapper.delete(new LambdaQueryWrapper<ScaleSplitTransport>()
                    .eq(ScaleSplitTransport::getReportPeriod, period));
            case "FREIGHT_TURNOVER":
                return freightTurnoverMapper.delete(new LambdaQueryWrapper<FreightTurnoverImport>()
                    .eq(FreightTurnoverImport::getReportPeriod, period));
            case "H2031":
                return passengerMapper.delete(new LambdaQueryWrapper<PassengerEnterpriseMonthly>()
                    .eq(PassengerEnterpriseMonthly::getReportPeriod, period));
            case "PASSENGER_AUTH":
                return passengerAuthMapper.delete(new LambdaQueryWrapper<PassengerAuthVehicle>()
                    .eq(PassengerAuthVehicle::getReportPeriod, period));
            case "PASSENGER_INDIVIDUAL":
                return passengerIndividualMapper.delete(new LambdaQueryWrapper<PassengerIndividualMonthly>()
                    .eq(PassengerIndividualMonthly::getReportPeriod, period));
            case "H204":
                return energyMapper.delete(new LambdaQueryWrapper<EnergyVehicleQuarterly>()
                    .eq(EnergyVehicleQuarterly::getReportPeriod, period));
            case "ENERGY_AUTH":
                return energyAuthMapper.delete(new LambdaQueryWrapper<EnergyAuthVehicle>()
                    .eq(EnergyAuthVehicle::getReportPeriod, period));
            case "INVEST_MONTHLY_PASSENGER":
                return deleteInvestmentMonthly(period, "客运站场");
            case "INVEST_MONTHLY_LOGISTICS":
                return deleteInvestmentMonthly(period, "物流园区");
            case "INVEST_SYSTEM":
                return investSystemMapper.delete(new LambdaQueryWrapper<InvestmentSystem>()
                    .eq(InvestmentSystem::getReportPeriod, period));
            case "CITY_BUS":
                return cityBusMapper.delete(new LambdaQueryWrapper<CityBusMonthly>()
                    .eq(CityBusMonthly::getReportPeriod, period));
            case "CITY_TAXI":
                return cityTaxiMapper.delete(new LambdaQueryWrapper<CityTaxiMonthly>()
                    .eq(CityTaxiMonthly::getReportPeriod, period));
            case "CITY_TAXI_AUTH":
                return cityTaxiAuthMapper.delete(new LambdaQueryWrapper<CityTaxiAuth>()
                    .eq(CityTaxiAuth::getReportPeriod, period));
            case "WYC_TOTAL":
                return wycTotalMapper.delete(new LambdaQueryWrapper<WycTotalMonthly>()
                    .eq(WycTotalMonthly::getReportPeriod, period));
            case "WYC_ORDER":
                return wycOrderMapper.delete(new LambdaQueryWrapper<WycOrderMonthly>()
                    .eq(WycOrderMonthly::getReportPeriod, period));
            default:
                log.warn("清空数据:未知数据表操作 {}", op);
                return 0;
        }
    }
    /** æŠ•资月度按项目类别清除(投资项目主档保留) */
    private int deleteInvestmentMonthly(String period, String category) {
        List<Long> projectIds = new ArrayList<>();
        for (InvestmentProject p : investProjectMapper.selectList(new LambdaQueryWrapper<InvestmentProject>()
                .eq(InvestmentProject::getCategory, category))) {
            projectIds.add(p.getId());
        }
        if (projectIds.isEmpty()) return 0;
        return investMonthlyMapper.delete(new LambdaQueryWrapper<InvestmentMonthly>()
            .eq(InvestmentMonthly::getReportPeriod, period)
            .in(InvestmentMonthly::getProjectId, projectIds));
    }
    /** æ•°æ®å˜åŒ–后删除指定报表类型指定报表期的审核结果(需重新执行审核) */
    private void deleteRuleResults(String reportType, String period) {
        List<Long> ruleIds = new ArrayList<>();
traffic-audit-web/src/views/DataImport.vue
@@ -105,6 +105,11 @@
                  <span>本月导入进度({{ period || '未选择报表期' }})</span>
                  <el-button type="text" icon="el-icon-refresh" @click="loadData">刷新</el-button>
                </div>
                <div v-if="period" class="side-danger">
                  <el-button size="mini" type="danger" plain icon="el-icon-delete"
                             :disabled="clearing || importing" @click="openClearDialog">清空数据…</el-button>
                  <span class="side-danger-tip">按报表期清库,用于整月重导</span>
                </div>
                <div v-if="!period" class="tip">请先在上方选择报表期</div>
                <div v-else class="overview-grid">
                  <div class="ov-row" v-for="g in visibleGroups" :key="g.key">
@@ -119,6 +124,32 @@
            </div>
          </div>
        </div>
        <el-dialog title="清空数据" :visible.sync="clearDialog" width="560px" append-to-body :close-on-click-modal="false">
          <div class="clear-dlg">
            <div class="clear-period">报表期:<b>{{ period }}</b></div>
            <el-radio-group v-model="clearScope">
              <el-radio label="all">清空该报表期全部已导入数据</el-radio>
              <el-radio label="types">只清空指定类型</el-radio>
            </el-radio-group>
            <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"
                             :label="t.label + '(' + overviewState(t.value).text + ')'"></el-option>
                </el-option-group>
              </el-select>
              <div class="tip" style="margin-top:6px">可多选;未导入的类型没有数据可删。</div>
            </div>
            <div class="clear-warn">
              å°†åˆ é™¤æ‰€é€‰èŒƒå›´å†…该报表期的数据库数据,并同步删除对应审核结果、已审核标记与导入批次记录(投资项目主档保留)。此操作不可撤销,请确认已有备份或准备重新导入。
            </div>
          </div>
          <span slot="footer">
            <el-button @click="clearDialog = false">取消</el-button>
            <el-button type="danger" :loading="clearing"
                       :disabled="clearScope === 'types' && !clearTypes.length" @click="confirmClear">确认清空</el-button>
          </span>
        </el-dialog>
      </el-main>
    </el-container>
  </el-container>
@@ -158,6 +189,10 @@
      period: (() => { const d = new Date(); return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') })(),
      cityDirLoading: false,
      importing: false,
      clearing: false,
      clearDialog: false,
      clearScope: 'all',
      clearTypes: [],
      sideOpen: false,
      result: '',
      error: '',
@@ -520,6 +555,44 @@
        .catch(e => { if (!e || !e._toast) this.$message.error('导入记录加载失败,请刷新重试') })
        .finally(() => { this.batchLoading = false })
    },
    openClearDialog() {
      if (!this.period) { this.$message.warning('请先选择报表期'); return }
      if (this.importing) { this.$message.warning('正在导入数据,请等待导入完成后再清空'); return }
      this.clearScope = 'all'
      this.clearTypes = []
      this.clearDialog = true
    },
    clearableGroups() {
      return this.groups.filter(g => !g.hidden)
    },
    confirmClear() {
      if (!this.period) { this.$message.warning('请先选择报表期'); return }
      if (this.clearing) return
      if (this.clearScope === 'types' && !this.clearTypes.length) { this.$message.warning('请选择要清空的数据类型'); return }
      const scopeText = this.clearScope === 'all'
        ? '该报表期全部已导入数据'
        : '以下 ' + this.clearTypes.length + ' ä¸ªç±»åž‹ï¼š' + this.clearTypes.map(t => this.typeLabel(t)).join('、')
      this.$confirm('将清空 ' + this.period + ' çš„' + scopeText + ',并同步删除对应审核结果、已审核标记与导入批次记录。此操作不可撤销,是否继续?',
        '清空确认', { type: 'warning', confirmButtonText: '确认清空', cancelButtonText: '取消' })
        .then(() => {
          this.clearing = true
          const params = { period: this.period }
          if (this.clearScope === 'types') params.types = this.clearTypes.join(',')
          return api.post('/import/clear', null, { params, timeout: 600000 })
            .then(res => {
              const d = (res && res.data) || {}
              this.$message.success('已清空 ' + this.period + ' æ•°æ®ï¼šä¸šåŠ¡æ•°æ® ' + (d.dataRows || 0) +
                ' è¡Œã€å®¡æ ¸ç»“æžœ ' + (d.auditRows || 0) + ' è¡Œã€å¯¼å…¥æ‰¹æ¬¡ ' + (d.batchRows || 0) + ' æ¡ï¼Œå¯ä»¥é‡æ–°å¯¼å…¥')
              this.clearDialog = false
              this.loadData()
            })
            .catch(e => {
              if (e && e._toast) return
              this.$message.error((e.response && e.response.data && e.response.data.message) || '清空失败,请稍后重试')
            })
            .finally(() => { this.clearing = false })
        }).catch(() => {})
    },
    batchKeyToType(k) {
      if (BATCH_TYPE_MAP[k]) return BATCH_TYPE_MAP[k]
      if (k && k.indexOf('INVEST_') === 0) {
@@ -591,6 +664,12 @@
.import-side.side-open .side-toggle-text { writing-mode: horizontal-tb; letter-spacing: normal; margin-top: 0; }
.side-content { padding: 8px 12px 12px; max-height: calc(100vh - 220px); overflow-y: auto; overscroll-behavior: contain; }
.side-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; font-weight: 600; margin-bottom: 6px; }
.side-danger { display: flex; align-items: center; gap: 8px; margin: 4px 0 10px; padding: 6px 8px; background: #FEF0F0; border: 1px solid #FDE2E2; border-radius: 4px; }
.side-danger-tip { font-size: 12px; color: #F56C6C; line-height: 1.3; }
.clear-dlg { line-height: 1.7; }
.clear-period { margin-bottom: 6px; }
.clear-types { margin-top: 10px; }
.clear-warn { margin-top: 12px; padding: 8px 10px; background: #FEF0F0; border: 1px solid #FDE2E2; border-radius: 4px; color: #F56C6C; font-size: 12px; line-height: 1.6; }
.import-side .overview-grid { display: block; }
.import-side .ov-row { display: block; margin-bottom: 6px; }
.import-side .ov-group { width: auto; }