From 93ccd040546983c92ecdcd906df81eec67a10ad6 Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期四, 10 九月 2026 08:44:19 +0800
Subject: [PATCH] feat: 数据导入页新增清空按钮——按报表期清空数据库业务数据/审核结果/已审核标记/导入批次,支持整月重导(含功能测试报告与工作日结)

---
 traffic-audit-web/src/views/DataImport.vue                                                          |   31 ++++++++++
 docs/功能测试报告/功能测试报告_数据导入清空按钮按报表期清库_2026-09-10.md                                                     |   41 +++++++++++++
 traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java       |   63 +++++++++++++++++++++
 docs/工作日结/工作日结_2026-09-10.md                                                                        |   23 +++++++
 traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java |   12 ++++
 5 files changed, 169 insertions(+), 1 deletions(-)

diff --git "a/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_\346\225\260\346\215\256\345\257\274\345\205\245\346\270\205\347\251\272\346\214\211\351\222\256\346\214\211\346\212\245\350\241\250\346\234\237\346\270\205\345\272\223_2026-09-10.md" "b/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_\346\225\260\346\215\256\345\257\274\345\205\245\346\270\205\347\251\272\346\214\211\351\222\256\346\214\211\346\212\245\350\241\250\346\234\237\346\270\205\345\272\223_2026-09-10.md"
new file mode 100644
index 0000000..9c8a8d2
--- /dev/null
+++ "b/docs/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212/\345\212\237\350\203\275\346\265\213\350\257\225\346\212\245\345\221\212_\346\225\260\346\215\256\345\257\274\345\205\245\346\270\205\347\251\272\346\214\211\351\222\256\346\214\211\346\212\245\350\241\250\346\234\237\346\270\205\345\272\223_2026-09-10.md"
@@ -0,0 +1,41 @@
+# 鍔熻兘娴嬭瘯鎶ュ憡锛氭暟鎹鍏ラ〉鈥滃鍏ヨ繘搴β锋竻绌衡�濇寜閽紙鎸夋姤琛ㄦ湡娓呯┖鏁版嵁搴擄級 2026-09-10
+
+## 鍔熻兘璇存槑
+- 鏁版嵁瀵煎叆椤靛彸渚р�滃鍏ヨ繘搴︹�濅晶鏍忔爣棰樻梺鏂板绾㈣壊鈥滄竻绌衡�濇寜閽紙涓庘�滃埛鏂扳�濆苟鍒楋級锛岄殢渚ф爮灞曞紑鍙銆�
+- 浣滅敤锛氫竴閿竻绌哄綋鍓嶆墍閫夋姤琛ㄦ湡鍦ㄦ暟鎹簱涓殑鍏ㄩ儴宸插鍏ヤ笟鍔℃暟鎹紝骞跺悓姝ュ垹闄よ鎶ヨ〃鏈熺殑瀹℃牳缁撴灉銆佸鏍搁�氳繃鏍囪锛坅udit_run锛変笌瀵煎叆鎵规璁板綍锛坕mport_batch锛夛紝鐢ㄤ簬鏁存湀閲嶆柊瀵煎叆锛涙姇璧勯」鐩富妗o紙investment_project锛変繚鐣欎笉鍔ㄣ��
+- 浜や簰锛氱偣鍑� 鈫� 浜屾纭寮圭獥锛堟爣棰樺惈鎶ヨ〃鏈燂紝鎻愮ず涓嶅彲鎾ら攢锛夆啋 纭鍚庤皟鐢� `POST /api/import/clear?period=yyyy-MM`锛涙竻绌鸿繃绋嬩腑鎸夐挳杩涘叆 loading 骞剁鐢紱鏈�夋姤琛ㄦ湡鎴栨鍦ㄥ鍏ユ椂鎸夐挳绂佺敤锛涙垚鍔熷悗鎻愮ず鈥滃凡娓呯┖ xxx 鎶ヨ〃鏈熺殑鏁版嵁锛屽彲浠ラ噸鏂板鍏モ�濆苟鑷姩鍒锋柊瀵煎叆杩涘害銆�
+
+## 娑夊強鏀瑰姩
+- 鍚庣 `DataImportService.clearPeriod(period)`锛歚@Transactional`锛屽厛鏍¢獙鎶ヨ〃鏈熸牸寮忥紝鍐嶆寜鎶ヨ〃鏈熷垹闄� h2032/杩愭斂杞﹁締/杞ㄨ抗閲岀▼/瑙勪笂瑙勪笅/璐ц繍閲忓懆杞噺/鏃呭鏈堟姤/涓綋/鏃呭杩愭斂/鑳借��/鑳借�楄繍鏀�/鎶曡祫鏈堝害/鎶曡祫绯荤粺/鍩庡競鍏氦/宸℃父鍑虹/鍑虹杞﹁繍鏀�/缃戠害杞︽�绘暟/缃戠害杞﹁鍗曞悇琛ㄦ暟鎹紝骞跺垹闄よ鏈� audit_result銆乤udit_run銆乮mport_batch锛涜繑鍥炲悇琛ㄥ垹闄よ鏁扮粺璁°��
+- 鍚庣 `DataImportController` 鏂板 `POST /api/import/clear`锛堝弬鏁� period锛夈��
+- 鍓嶇 `DataImport.vue`锛氭柊澧� `clearing` 鐘舵�併�乣clearPeriodData()` 鏂规硶涓庝晶鏍忔寜閽�/鏍峰紡銆�
+
+## 娴嬭瘯鐜
+- 鍚庣锛歵raffic-audit-server 8090锛堝惈鏈鏀瑰姩锛宍start-dev.ps1` 鍚姩鎴愬姛锛宐ackend.log 鍑虹幇 `Started TrafficAuditApplication`锛夈��
+- 鍓嶇锛歵raffic-audit-web 8080 dev锛圕ompiled 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 | 姝e悜-瀵煎叆 | 涓婁紶 6 鏈堣揣杩� xls锛宲eriod=2099-01 | 鎴愬姛涓旇鏁� 636 | 杩斿洖鈥淗2032鏈堟姤瀵煎叆鎴愬姛锛屽叡 636 鏉¤褰曗�濓紝鎵规 1 鏉� | 閫氳繃 |
+| 3 | 姝e悜-瀹℃牳 | `POST /audit/execute?period=2099-01&reportType=H2032` | 鐢熸垚瀹℃牳缁撴灉涓庡凡瀹℃牳鏍囪 | 鐢熸垚 audit_result 31 琛屻�乤udit_run 1 琛� | 閫氳繃 |
+| 4 | 姝e悜-娓呯┖锛堟帴鍙o級 | `POST /import/clear?period=2099-01` | 杩斿洖鍒犻櫎缁熻锛屽簱鍐呰鏈熸竻绌� | 杩斿洖 dataRows=636銆乤uditRows=31銆乤uditRunRows=1銆乥atchRows=1锛汥B 鐩存煡 h2032/audit_result/audit_run/import_batch 鍧囦负 0 | 閫氳繃 |
+| 5 | 姝e悜-娓呯┖鍚庨噸瀵� | 鍐嶆涓婁紶鍚屼竴鏂囦欢 period=2099-01 | 鍙甯搁噸鏂板鍏� | 鎴愬姛 636 鏉★紱DB h2032=636銆乮mport_batch=1 | 閫氳繃 |
+| 6 | 璐熷悜-闈炴硶鎶ヨ〃鏈� | `period=abc` | 鎷掔粷骞舵彁绀烘牸寮� | code=500锛屸�滄竻绌哄け璐�: 鎶ヨ〃鏈熸牸寮忎笉姝g‘锛屽簲涓� yyyy-MM鈥� | 閫氳繃 |
+| 7 | 杈圭晫-绌烘姤琛ㄦ湡 | `period=2098-12`锛堟棤鏁版嵁锛� | 鎴愬姛涓斿悇椤逛负 0 | dataRows/auditRows/auditRunRows/batchRows 鍧囦负 0 | 閫氳繃 |
+| 8 | UI-鎸夐挳瀛樺湪 | 鎵撳紑鏁版嵁瀵煎叆椤碉紝閫� 2099-01锛屽睍寮�鈥滃鍏ヨ繘搴︹�� | 鏍囬鏃佸嚭鐜扳�滃埛鏂�/娓呯┖鈥濓紝杩涘害鏄剧ず H203-2 宸插鍏� 636 琛� | 涓庨鏈熶竴鑷达紙鍙闂�ф爲璇诲埌鈥滄竻绌衡�濇寜閽笌鈥滃凡瀵煎叆 636 琛屸�濓級 | 閫氳繃 |
+| 9 | UI-浜屾纭 | 鐐光�滄竻绌衡�� | 寮瑰嚭纭妗嗭紝鏍囬鍚姤琛ㄦ湡 | 寮圭獥鏍囬鈥滄竻绌� 2099-01 鏁版嵁鈥濓紝姝f枃鎻愮ず涓嶅彲鎾ら攢锛屾寜閽�滃彇娑�/纭娓呯┖鈥� | 閫氳繃 |
+| 10 | UI-纭娓呯┖ | 鐐光�滅‘璁ゆ竻绌衡�� | 鎻愮ず鎴愬姛銆佽繘搴﹀叏閮ㄥ洖鈥滄湭瀵煎叆鈥濄�佸簱鍐呮竻绌� | 鎻愮ず鈥滃凡娓呯┖ 2099-01 鎶ヨ〃鏈熺殑鏁版嵁锛屽彲浠ラ噸鏂板鍏モ�濓紱杩涘害鍏ㄩ儴鏈鍏ワ紱DB 鐩存煡鍥涜〃鍧囦负 0 | 閫氳繃 |
+| 11 | 鍥炲綊-鐪熷疄鏈堜唤涓嶅彈褰卞搷 | 娓呯┖鍓嶅悗瀵规瘮鎵规鍒嗗竷涓庡簱鍐呰鏁� | 鐪熷疄鏈堜唤鏃犲彉鍖� | 鎵规鍒嗗竷涓庢敼鍔ㄥ墠瀹屽叏涓�鑷达紙2025 鍚勬湀 1 鏉°��2026-07 45 鏉°��2026-08 48 鏉°��2026-09 7 鏉★級锛沨2032锛�2025-07=664銆�2026-07=636銆�2026-09=636 | 閫氳繃 |
+
+## 鍙戠幇鐨勯棶棰樹笌澶勭疆
+- 鏈彂鐜板姛鑳界己闄枫��
+- 璇存槑锛氫竴娆℃竻绌轰細鍒犻櫎璇ユ姤琛ㄦ湡鈥滃叏閮ㄧ被鍨嬧�濈殑涓氬姟鏁版嵁鍙婂鏍哥粨鏋�/宸插鏍告爣璁帮紝寮圭獥宸叉槑纭彁绀轰笉鍙挙閿�锛涜嫢鍙兂娓呭崟涓�绫诲瀷锛岀洰鍓嶉渶鏁存湀娓呯┖鍚庨噸瀵硷紝鍙綔涓哄悗缁寮猴紙鎸夌被鍨嬫竻绌猴級銆�
+- 鐜澶囨敞锛氭湰鏈哄簱 `admin` 瀵嗙爜涓� `123456`锛堣 docs/浜ゆ帴鏂囨。-20260831.md锛�8/31 瀹炴祴锛夛紝`admin123` 鍦ㄦ湰鏈轰笉鍖归厤銆�
+
+## 缁撹
+- 閫氳繃銆傛竻绌烘寜閽湪鐣岄潰鍙敤銆佺‘璁ゅ脊绐楄涔夋竻鏅帮紝鎺ュ彛鎸夋姤琛ㄦ湡瀹屾暣娓呴櫎涓氬姟鏁版嵁銆佸鏍哥粨鏋溿�佸鏍告爣璁颁笌瀵煎叆鎵规锛屾竻绌哄悗鍙珛鍗虫暣鏈堥噸瀵硷紱瀵圭湡瀹炴湀浠芥暟鎹浂褰卞搷銆�
+- 寰呯敤鎴峰疄闄呮祻瑙堝櫒楠屾敹锛氬湪鑷繁宸ヤ綔鏈轰笂鐐逛竴娆♀�滄竻绌衡�濓紙寤鸿鍏堢‘璁ゆ墍閫夋姤琛ㄦ湡涓庡浠斤級纭寮圭獥鏂囨涓庨鏈熶竴鑷淬��
diff --git "a/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-10.md" "b/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-10.md"
new file mode 100644
index 0000000..8f3b282
--- /dev/null
+++ "b/docs/\345\267\245\344\275\234\346\227\245\347\273\223/\345\267\245\344\275\234\346\227\245\347\273\223_2026-09-10.md"
@@ -0,0 +1,23 @@
+# 宸ヤ綔鏃ョ粨 2026-09-10
+
+## 涓婂崍锛�2026-09-10锛夋暟鎹鍏ラ〉鏂板鈥滄竻绌猴紙鎸夋姤琛ㄦ湡娓呭簱锛夆�濆苟瀹屾垚绔埌绔獙璇�
+
+### 瀹屾垚鍐呭
+- 鏁版嵁瀵煎叆椤靛彸渚р�滃鍏ヨ繘搴︹�濅晶鏍忔爣棰樻梺鏂板绾㈣壊鈥滄竻绌衡�濇寜閽細涓�閿竻绌烘墍閫夋姤琛ㄦ湡鍦ㄦ暟鎹簱涓殑鍏ㄩ儴宸插鍏ユ暟鎹紝骞跺悓姝ュ垹闄よ鏈熷鏍哥粨鏋溿�佸鏍搁�氳繃鏍囪锛坅udit_run锛変笌瀵煎叆鎵规锛坕mport_batch锛夛紝鐢ㄤ簬鏁存湀閲嶅锛涙姇璧勯」鐩富妗d繚鐣欍��
+- 鍚庣鏂板 `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锛孌B 鐩存煡鍥涜〃鍏� 0 鈫� 鍐嶅鍏ヤ粛 636 琛屾垚鍔熴��
+- UI 瀹炴祴锛圕odex 搴旂敤鍐呮祻瑙堝櫒锛宎dmin 鐧诲綍锛夛細鎸夐挳鏄剧ず姝e父锛屽脊绐楁爣棰樷�滄竻绌� 2099-01 鏁版嵁鈥濓紝纭鍚庢彁绀衡�滃凡娓呯┖ 2099-01 鎶ヨ〃鏈熺殑鏁版嵁鈥濓紝杩涘害鍏ㄩ儴鍥炩�滄湭瀵煎叆鈥濄��
+- 鍙嶅悜鐢ㄤ緥锛氶潪娉曟姤琛ㄦ湡 `abc` 琚嫆骞舵彁绀烘牸寮忥紱绌烘姤琛ㄦ湡 `2098-12` 杩斿洖鍏� 0 鎴愬姛銆�
+- 鍥炲綊锛氭竻绌哄墠鍚庣湡瀹炴湀浠芥壒娆″垎甯冧笌搴撳唴琛屾暟瀹屽叏涓�鑷达紙2025-07=664銆�2026-07=636銆�2026-09=636 绛夛級锛岄浂褰卞搷銆�
+- 鍚庣 `start-dev.ps1` 鍚姩灏辩华锛坆ackend.log `Started TrafficAuditApplication`锛夛紝鍓嶇 dev Compiled successfully銆�
+- 娴嬭瘯鎶ュ憡锛歞ocs/鍔熻兘娴嬭瘯鎶ュ憡/鍔熻兘娴嬭瘯鎶ュ憡_鏁版嵁瀵煎叆娓呯┖鎸夐挳鎸夋姤琛ㄦ湡娓呭簱_2026-09-10.md銆�
+
+### 閬楃暀闂涓庡緟鍔�
+- 寰呯敤鎴峰疄闄呮祻瑙堝櫒楠屾敹鈥滄竻绌衡�濇寜閽紙寤鸿鍏堢‘璁ゆ墍閫夋姤琛ㄦ湡涓庡浠斤級锛涘闇�鍙竻鏌愪竴鏁版嵁绫诲瀷锛屽彲鍚庣画鍋氣�滄寜绫诲瀷娓呯┖鈥濄��
+- 娌跨敤鏄ㄦ棩鏈姩寰呭姙锛氭眹鎬诲ぇ琛� M3锛堢綉绾﹁溅鍙拌处鍙栨暟銆佽揣杩愰〉 FreightCalc 瑙勪笂/瑙勪笅銆佸煄甯傚杩�/涓彛寰勫悎鎴愰〉锛変笌鈥�9 鏈�+鏃犳瘝鐗堣嚜鍔ㄦ墿鍒椻�濓紱8 鏈堜粛缂� 4 绫绘簮鏁版嵁琛ㄨ锛坒reight_turnover_import銆乻cale_split_transport銆乸assenger_individual_monthly銆佺綉绾﹁溅鎷嗗垎杈撳叆锛夈��
+
+## 闄勶細鎻愪氦
+- 鏈鏀瑰姩 3 涓唬鐮佹枃浠� + 鏈姤鍛婁笌鏃ョ粨锛屾寜瑙勮寖鍏� `git fetch gitea/origin` 瀵规瘮鍚堝苟锛屽啀 commit 骞跺弻绔帹閫侊紙gitea main銆佷釜浜� gitee master锛夈��
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
index bc7e1de..d8217b5 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/controller/DataImportController.java
@@ -443,4 +443,16 @@
         return Result.ok(result);
     }
 
+    /** 娓呯┖鎸囧畾鎶ヨ〃鏈熷叏閮ㄥ凡瀵煎叆鏁版嵁涓庡鏍哥粨鏋滐紙鏁版嵁瀵煎叆椤�"娓呯┖"鎸夐挳璋冪敤锛夛紝渚夸簬鏁存湀閲嶆柊瀵煎叆 */
+    @PostMapping("/clear")
+    public Result<Map<String, Object>> clearData(@RequestParam("period") String period) {
+        try {
+            Map<String, Object> stats = importService.clearPeriod(period);
+            return Result.ok(stats);
+        } catch (Exception e) {
+            log.error("clear period {} error", period, e);
+            return Result.error("娓呯┖澶辫触: " + e.getMessage());
+        }
+    }
+
 }
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
index 0fe1227..3aa4d32 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java
+++ b/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,64 @@
         }
     }
 
+    /** 娓呯┖鎸囧畾鎶ヨ〃鏈熷叏閮ㄥ凡瀵煎叆鏁版嵁涓庡鏍哥粨鏋滐紙鍚鍏ユ壒娆°�佸鏍搁�氳繃鏍囪锛夛紝鐢ㄤ簬鏁存湀閲嶅锛涙姇璧勯」鐩富妗d繚鐣� */
+    @Transactional(rollbackFor = Exception.class)
+    public Map<String, Object> clearPeriod(String period) {
+        if (period == null || !period.matches("\\d{4}-\\d{2}")) {
+            throw new IllegalArgumentException("鎶ヨ〃鏈熸牸寮忎笉姝g‘锛屽簲涓� yyyy-MM");
+        }
+        int dataRows = 0;
+        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));
+        int auditRows = auditResultMapper.delete(new LambdaQueryWrapper<AuditResult>()
+            .eq(AuditResult::getReportPeriod, period));
+        int auditRunRows = auditRunMapper.delete(new LambdaQueryWrapper<AuditRun>()
+            .eq(AuditRun::getReportPeriod, period));
+        int batchRows = importBatchMapper.delete(new LambdaQueryWrapper<ImportBatch>()
+            .eq(ImportBatch::getReportPeriod, period));
+        Map<String, Object> stats = new LinkedHashMap<>();
+        stats.put("period", period);
+        stats.put("dataRows", dataRows);
+        stats.put("auditRows", auditRows);
+        stats.put("auditRunRows", auditRunRows);
+        stats.put("batchRows", batchRows);
+        log.info("娓呯┖鎶ヨ〃鏈� {} 瀹屾垚锛氫笟鍔℃暟鎹� {} 琛屻�佸鏍哥粨鏋� {} 琛屻�佸鏍告爣璁� {} 琛屻�佸鍏ユ壒娆� {} 琛�",
+            period, dataRows, auditRows, auditRunRows, batchRows);
+        return stats;
+    }
+
     /** 鏁版嵁鍙樺寲鍚庡垹闄ゆ寚瀹氭姤琛ㄧ被鍨嬫寚瀹氭姤琛ㄦ湡鐨勫鏍哥粨鏋滐紙闇�閲嶆柊鎵ц瀹℃牳锛� */
     private void deleteRuleResults(String reportType, String period) {
         List<Long> ruleIds = new ArrayList<>();
diff --git a/traffic-audit-web/src/views/DataImport.vue b/traffic-audit-web/src/views/DataImport.vue
index 2d77063..e496ed4 100644
--- a/traffic-audit-web/src/views/DataImport.vue
+++ b/traffic-audit-web/src/views/DataImport.vue
@@ -103,7 +103,11 @@
               <div v-show="sideOpen" class="side-content">
                 <div class="side-head">
                   <span>鏈湀瀵煎叆杩涘害锛坽{ period || '鏈�夋嫨鎶ヨ〃鏈�' }}锛�</span>
-                  <el-button type="text" icon="el-icon-refresh" @click="loadData">鍒锋柊</el-button>
+                  <span class="side-head-btns">
+                    <el-button type="text" icon="el-icon-refresh" @click="loadData">鍒锋柊</el-button>
+                    <el-button type="text" icon="el-icon-delete" style="color:#F56C6C" :loading="clearing"
+                               :disabled="!period || clearing || importing" @click="clearPeriodData">娓呯┖</el-button>
+                  </span>
                 </div>
                 <div v-if="!period" class="tip">璇峰厛鍦ㄤ笂鏂归�夋嫨鎶ヨ〃鏈�</div>
                 <div v-else class="overview-grid">
@@ -158,6 +162,7 @@
       period: (() => { const d = new Date(); return d.getFullYear() + '-' + String(d.getMonth() + 1).padStart(2, '0') })(),
       cityDirLoading: false,
       importing: false,
+      clearing: false,
       sideOpen: false,
       result: '',
       error: '',
@@ -520,6 +525,28 @@
         .catch(e => { if (!e || !e._toast) this.$message.error('瀵煎叆璁板綍鍔犺浇澶辫触锛岃鍒锋柊閲嶈瘯') })
         .finally(() => { this.batchLoading = false })
     },
+    clearPeriodData() {
+      if (!this.period) { this.$message.warning('璇峰厛閫夋嫨鎶ヨ〃鏈�'); return }
+      if (this.importing) { this.$message.warning('姝e湪瀵煎叆鏁版嵁锛岃绛夊緟瀵煎叆瀹屾垚鍚庡啀娓呯┖'); return }
+      if (this.clearing) return
+      this.$confirm(
+        '灏嗘竻绌� ' + this.period + ' 鎶ヨ〃鏈熷湪鏁版嵁搴撲腑鐨勫叏閮ㄥ凡瀵煎叆鏁版嵁锛屽悓鏃跺垹闄よ鎶ヨ〃鏈熺殑瀹℃牳缁撴灉涓庡鍏ユ壒娆¤褰曪紙渚夸簬鏁存湀閲嶆柊瀵煎叆锛夈�俓n姝ゆ搷浣滀笉鍙挙閿�锛屾槸鍚︾户缁紵',
+        '娓呯┖ ' + this.period + ' 鏁版嵁',
+        { type: 'warning', confirmButtonText: '纭娓呯┖', cancelButtonText: '鍙栨秷' }
+      ).then(() => {
+        this.clearing = true
+        api.post('/import/clear', null, { params: { period: this.period }, timeout: 600000 })
+          .then(() => {
+            this.$message.success('宸叉竻绌� ' + this.period + ' 鎶ヨ〃鏈熺殑鏁版嵁锛屽彲浠ラ噸鏂板鍏�')
+            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 +618,8 @@
 .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-head-btns { display: flex; align-items: center; gap: 2px; flex-shrink: 0; }
+.side-head-btns .el-button + .el-button { margin-left: 0; }
 .import-side .overview-grid { display: block; }
 .import-side .ov-row { display: block; margin-bottom: 6px; }
 .import-side .ov-group { width: auto; }

--
Gitblit v1.9.1