From 0548cc15e54656285baf36b3494f9456b16f975f Mon Sep 17 00:00:00 2001
From: zhizhijie <zhizhijie@users.noreply.gitee.com>
Date: 星期二, 08 九月 2026 17:14:40 +0800
Subject: [PATCH] fix: 8条整改落地——数据查看滚动加载/规则阈值联动通用化/旅客运政导入兼容.xls/审核月报弹窗删企业解释列/汇总大表导出无筛选自适应/报表Tab重组/筛选栏与月份年份顺序 + 测试报告与工作日结
---
traffic-audit-server/src/main/java/com/trafficaudit/rulemanage/controller/RuleManageController.java | 91 +++++++-
traffic-audit-web/src/views/ReportExport.vue | 12
/dev/null | 0
docs/功能测试报告/功能测试报告_整改8项回归验证_2026-09-08.md | 40 ++++
traffic-audit-web/src/views/DataImport.vue | 4
docs/公路旅客/模板_公路旅客运政车辆数.xls | 0
traffic-audit-server/src/main/java/com/trafficaudit/dataimport/service/DataImportService.java | 47 ++++
traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java | 24 ++
docs/工作日结/工作日结_2026-09-08.md | 19 +
traffic-audit-web/src/views/DataView.vue | 36 +++
traffic-audit-web/src/views/AuditResult.vue | 268 +++++++++++++++++++++-----
11 files changed, 459 insertions(+), 82 deletions(-)
diff --git "a/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xls" "b/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xls"
new file mode 100644
index 0000000..d1b459a
--- /dev/null
+++ "b/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xls"
Binary files differ
diff --git "a/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xlsx" "b/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xlsx"
deleted file mode 100644
index 069aab1..0000000
--- "a/docs/\345\205\254\350\267\257\346\227\205\345\256\242/\346\250\241\346\235\277_\345\205\254\350\267\257\346\227\205\345\256\242\350\277\220\346\224\277\350\275\246\350\276\206\346\225\260.xlsx"
+++ /dev/null
Binary files differ
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\264\346\224\2718\351\241\271\345\233\236\345\275\222\351\252\214\350\257\201_2026-09-08.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\264\346\224\2718\351\241\271\345\233\236\345\275\222\351\252\214\350\257\201_2026-09-08.md"
new file mode 100644
index 0000000..219bc89
--- /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\264\346\224\2718\351\241\271\345\233\236\345\275\222\351\252\214\350\257\201_2026-09-08.md"
@@ -0,0 +1,40 @@
+# 鍔熻兘娴嬭瘯鎶ュ憡_鏁存敼8椤瑰洖褰掗獙璇乢2026-09-08
+
+## 鍔熻兘璇存槑
+閽堝鐢ㄦ埛 2026-09-08 鎻愬嚭鐨� 8 鏉$晫闈笌鍔熻兘鏁存敼锛堚�滀笂娆¤鏀圭殑娌℃敼鈥濓級閫愭潯钀藉湴骞跺洖褰掞細
+1. 鏁版嵁鏌ョ湅椤垫粴鍔ㄥ埌搴曡嚜鍔ㄥ姞杞芥洿澶氭暟鎹锛堜笉鍐嶅彧鏄剧ず涓�椤碉級锛�
+2. 瀹℃牳瑙勫垯闃堝�兼敼鍔ㄥ悗锛岃鍒欏悕绉�/瑙勫垯璇存槑涓殑鐧惧垎姣旈殢闃堝�艰仈鍔紙濡� 卤10%鈫捖�20%鈫捖�30%鈫掑洖閫�锛夛紝骞跺鍏ㄩ儴瑙勫垯鐢熸晥銆佹寔涔呭寲锛�
+3. 鍏矾鏃呭鈥滆繍鏀胯溅杈嗘暟鈥濆鍏ュ吋瀹规柊鐗堣繍鏀垮簱瀵煎嚭鏂囦欢锛�.xls锛岃〃澶� OWNERNAME/鎬昏溅杈嗘暟/瀹綅鏁帮紝鏃犱紒涓氫唬鐮佸垪锛夛紝鍚屾椂鍏煎鏃т腑鏂囧洓鍒楄〃澶达紱
+4. 瀹℃牳缁撴灉锛氬垹闄も�滀紒涓氳В閲娾�濆垪鍙婅В閲婅緭鍏ユ锛涚偣鍑烩�滄暟鎹�濆脊鍑鸿浼佷笟璇ユ姤琛ㄦ湡鐨勬湀鎶ユ牱寮忔煡鐪嬶紱
+5. 鐢熸垚姹囨�诲ぇ琛紙鏁存湰锛夛細瀵煎嚭鏃跺彇娑堝叏閮ㄩ〉绛涢�夛紙鐝嚎鍖呰溅绛夐〉涓嶅啀鍍忕己鏁版嵁锛夈�佽繕鍘熼殣钘忚銆佹寜鏁版嵁鑷姩鍔犲鍒楀銆佹暟鍊间繚鐣欎袱浣嶅皬鏁版樉绀猴紙涓嶄涪澶卞叏绮惧害锛夈�佸叕寮忎繚鐣欎笖鎵撳紑鑷姩閲嶇畻锛�
+6. 鎶ヨ〃鐢熸垚椤碉細鍩庡競瀹㈣繍鎶ヨ〃鏍囩涓嬬殑 tag 鍒犻櫎銆佸悕绉颁笌鍏跺畠涓�鑷达紱鈥滈亾璺繍杈撻噺姹囨�昏〃锛堟暣鏈級鈥濈Щ鍏ラ涓嫭绔� Tab鈥滄眹鎬诲ぇ琛ㄢ�濓紱
+7. 瀹℃牳缁撴灉椤电瓫閫夋爮椤哄簭锛氭姤琛ㄦ湡鍦ㄦ姤琛ㄧ被鍨嬪乏杈癸紱
+8. 鎶ヨ〃鐢熸垚鏈堜唤涓嬫媺锛氶粯璁ゆ渶鍏堝睍绀哄綋鍓嶅勾浠斤紙2026 骞� 1鈥�12 鏈堬級锛屽啀灞曠ず 2025 骞翠笌 2027 骞淬��
+
+## 娴嬭瘯鐜
+- 鏈満锛歐indows锛屽悗绔� Spring Boot :8090锛屽墠绔� Vue2 :8080锛堥〉闈㈢粡閲嶆柊缂栬瘧鍔犺浇鏈�鏂颁唬鐮侊紝鍚庣宸查噸鍚級銆�
+- 鐧诲綍锛歛dmin锛坅pp.captcha.required=false 娴嬭瘯妯″紡锛夈��
+- 鏁版嵁搴擄細鏈満 traffic-audit 寮�鍙戝簱锛堝惈 2026-08 璐ц繍鏈堟姤 13056 鏉$瓑鏃㈡湁鏁版嵁锛夈��
+- 鏃ユ湡锛�2026-09-08銆�
+
+## 鐢ㄤ緥琛紙杈撳叆 / 棰勬湡 / 瀹為檯 / 缁撹锛�
+
+| # | 杈撳叆 | 棰勬湡 | 瀹為檯 | 缁撹 |
+|---|------|------|------|------|
+| 1 | 鏁版嵁鏌ョ湅椤碉紙H203-2锛屽叡 13056 鏉★級锛屽皢琛ㄦ牸绔栧悜婊氬姩鍒板簳 | 鑷姩杩藉姞涓嬩竴椤碉紝琛屾暟 20鈫�40锛岄〉绛句粠鈥滅 1 椤碘�濆彉鈥滅 2 椤碘�� | 鍒濆 20 琛岋紙瀹瑰櫒楂� 299銆佸唴瀹归珮 796锛夛紱婊氬姩鍚� 40 琛岋紙鍐呭楂� 1592锛宻crollTop 496.8锛夛紝鈥滃叡 13056 鏉¤褰曪紝褰撳墠绗� 2 椤碘�� | 閫氳繃 |
+| 2 | 瑙勫垯绠$悊锛氬皢 P005 闃堝�� 20鈫�30鈫�20 鍙嶅淇濆瓨 | 鍚嶇О/璇存槑涓殑 卤N% 闅忓姩锛埪�20%鈫斅�30%锛夛紝鍏跺畠鏃犲叧鏁板瓧涓嶅姩锛岄噸寮�椤甸潰浠嶄竴鑷� | P005 浠ュ強 B001锛堝閫燂級銆丒005锛埪�%锛夈�丷ULE_003锛堥珮鍑�%锛夈�乀001锛堝樊璺�%锛夊潎瀹炴祴閫氳繃锛屾樉寮忥紙0.2鈫�0.1锛変笌姣斿�硷紙1.3鈫�1.5锛夊彛寰勫潎姝g‘骞舵寔涔呭寲 | 閫氳繃 |
+| 3 | 瀵煎叆 2026-08 鍏矾鏃呭杩愭斂杞﹁締鏁帮紙鏂� .xls锛歄WNERNAME/鎬昏溅杈嗘暟/瀹綅鏁帮級 | 750 瀹朵紒涓氬叏閮ㄥ叆搴撱�佹娊鏍锋暟鍊间笌婧愭枃浠朵竴鑷达紱鏃т腑鏂囪〃澶存枃浠朵粛鍙鍏� | 鏂版ā鏉挎斁鍏� docs/鍏矾鏃呭/妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xls 瀵煎叆鎴愬姛锛涙娊鏌ョЛ褰掑幙蹇楀皻 5/35銆佸畨闄嗗競娑㈠畨 26/668 涓庢簮鏂囦欢涓�鑷达紱浼佷笟浠g爜鍒椾负绌哄睘姝e父锛堟柊妯℃澘鏃犳鍒楋級 | 閫氳繃 |
+| 4 | 瀹℃牳缁撴灉椤碉細鈶犳鏌ヨ鍐呮搷浣滃垪锛涒憽鐐瑰嚮鈥滄暟鎹�� | 鈶� 鏃犫�滀紒涓氳В閲娾�濆垪/杈撳叆妗嗭紝鍙湁 鏁版嵁/纭/蹇界暐锛涒憽 寮瑰嚭璇ヤ紒涓氳鎶ヨ〃鏈熺殑鏈堟姤鏍峰紡锛堟爣棰�=浼佷笟鍚�+鎶ヨ〃鏈� 鏈堟姤鏁版嵁锛涘垎鍖�=杩愬姏鎯呭喌鈫掕繍杈撶敓浜ф儏鍐碘啋骞冲潎鎸囨爣鈫掑~鎶ヤ汉淇℃伅锛涘簳閮ㄥ叧闂彲鐢級 | 瀹炴祴鏃� 4 鍒椻�滀紒涓氳В閲娾�濇畫鐣欙紱鈥滄暟鎹�濆脊绐楀唴瀹逛笌鍒嗗尯椤哄簭绗﹀悎棰勬湡锛屽叧闂甯� | 閫氳繃 |
+| 5 | 瀵煎嚭鈥滈亾璺繍杈撻噺姹囨�昏〃锛堟暣鏈級鈥�2026-08 骞惰剼鏈牎楠� 19 涓� sheet | 鍏ㄩ儴椤垫棤 autoFilter銆佹棤闅愯棌琛岋紱鏁板�煎崟鍏冩牸淇濈暀涓や綅灏忔暟鏄剧ず涓庡叏绮惧害锛涚郴缁熸眰鍜�/鍚屾瘮鍏紡淇濈暀锛涙墦寮�鍗抽噸绠� | 鏍¢獙鏂囦欢锛歞ocs/鐢熸垚姹囨�诲ぇ琛�/杈撳嚭/鐢熸垚_閬撹矾杩愯緭閲忔眹鎬昏〃_2026-08_娓呯悊楠岃瘉.xlsx锛�19 椤� filter=None銆乭idden=[]锛孋4/D4 绛夐暱姹傚拰涓庡悓姣斿叕寮忎繚鐣� | 閫氳繃 |
+| 6 | 鎶ヨ〃鐢熸垚椤垫鏌� Tab 涓庢爣绛� | 椤哄簭锛氭眹鎬诲ぇ琛ㄢ啋璐ц繍鎶ヨ〃鈫掓梾瀹㈡姤琛ㄢ啋鍩庡競瀹㈣繍鎶ヨ〃鈫掓姇璧勬姤琛ㄢ啋鑳借�楁姤琛紱鍩庡競瀹㈣繍鏃� tag锛涙暣鏈粠鍩庡競瀹㈣繍绉诲嚭 | 姹囨�诲ぇ琛ㄧ嫭绔嬩负棣栫粍锛涘煄甯傚杩愭爣绛炬棤鈥滃叕浜�/鍑虹/杞ㄩ亾杞浮/姹囨�烩�漷ag | 閫氳繃 |
+| 7 | 瀹℃牳缁撴灉椤电瓫閫夋爮 | 鎶ヨ〃鏈熷湪鎶ヨ〃绫诲瀷宸﹁竟 | 绛涢�夋爮椤哄簭涓衡�滄姤琛ㄦ湡 鈫� 鎶ヨ〃绫诲瀷 鈫� 鎵ц瀹℃牳鎸夐挳鈥� | 閫氳繃 |
+| 8 | 鎶ヨ〃鐢熸垚椤电偣寮�鏈堜唤涓嬫媺 | 榛樿灞曞紑褰撳墠骞翠唤 2026 骞� 1鈥�12 鏈堬紝鍏舵 2025 骞达紝鍐嶆 2027 骞� | 瀹炴祴涓嬫媺椤哄簭锛�2026骞�1鏈堚��2026骞�12鏈堛��2025骞�1鏈堚��2025骞�12鏈堛��2027骞�1鏈堚��2027骞�12鏈� | 閫氳繃 |
+
+## 鍙戠幇鐨勯棶棰樹笌澶勭疆
+- 鍘嗗彶闂锛氳鍒欏悕绉�/璇存槑閲岄櫎闃堝�煎杩樻贩鏈変笌闃堝�兼棤鍏崇殑鏁板瓧锛堝杩愯窛鍖洪棿 [10,3000]锛夛紝鏃у疄鐜颁細璇敼銆傛湰杞敼涓衡�滄寜鏃ч槇鍊煎尮閰嶅寰椾笂鐨勭櫨鍒嗘瘮鐗囨鎵嶆浛鎹⑩�濓紝骞跺璇诲垪琛ㄥ仛骞傜瓑鑷剤锛屽疄娴嬫湭鍐嶈浼ゆ棤鍏虫暟瀛椼��
+- 鍘嗗彶闂锛氭眹鎬诲ぇ琛ㄦ瘝鐗堟湰韬甫绛涢�変笌闅愯棌琛岋紝鏃у鍑轰細鍘熸牱甯﹀嚭锛岀湅璧锋潵鍍忕己鏁版嵁銆傛湰杞鍑哄墠缁熶竴娓呯悊骞堕獙璇� 19 椤靛叏骞插噣銆�
+- 鍘嗗彶闂锛氬叕璺梾瀹㈣繍鏀垮鍏ユ鍓嶅彧璁も�滀紒涓氫唬鐮�/浼佷笟鍚嶇О/杞﹁締鏁�/杞藉浣嶆暟鈥濅腑鏂囧洓鍒楋紝鍚屼簨涓嬭浇鐨勬柊妯℃澘灏戜袱鍒楀鑷村涓嶈繘鍘汇�傛湰杞寜鍒悕+琛ㄥご澶у啓鍏煎鏂版棫涓ょ缁撴瀯銆�
+- 澶囨敞锛歞ocs/瀹℃牳鐣岄潰鏈堟姤妯℃澘/HTML_瀹℃牳缁撴灉_Aug_2026.html 涓烘湰娆″鏍哥粨鏋滈〉涓庡脊绐楅獙璇佺暀妗c��
+
+## 缁撹
+8 鏉℃暣鏀瑰叏閮ㄥ畬鎴愬苟閫氳繃鍥炲綊楠岃瘉锛涚浉鍏虫敼鍔ㄨ浠g爜鎻愪氦锛圖ataImportService/ReportExportService/RuleManageController/AuditResult.vue/DataView.vue/ReportExport.vue/DataImport.vue锛夈��
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-08.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-08.md"
index 77f966a..38b8749 100644
--- "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-08.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-08.md"
@@ -73,4 +73,21 @@
- 璇﹁銆婂姛鑳芥祴璇曟姤鍛奯姹囨�诲ぇ琛ㄦ棩鏈熸牸寮忎笌瑙勫垯鑱斿姩鍙婃暟鎹煡鐪嬫粴鍔ㄥ姞杞絖2026-09-08.md銆嬨��
- `mvn` 缂栬瘧閫氳繃锛堝墠涓�浜ゆ帴宸插畬鎴愶級锛涘墠绔儹缂栬瘧 3 娆℃垚鍔燂紙15:19/15:24锛夈��
### 閬楃暀涓庝笅涓�姝�
-- 8 鏈堝綋鏈堟暟鎹鍏ュ悗 M2/M3 濉�煎楠岋紱涓存椂鑴氭湰 `_verify_*.py/.sql`銆乣_do_patch1.py` 涓嶅垹涓嶅叆搴撱��
\ No newline at end of file
+- 8 鏈堝綋鏈堟暟鎹鍏ュ悗 M2/M3 濉�煎楠岋紱涓存椂鑴氭湰 `_verify_*.py/.sql`銆乣_do_patch1.py` 涓嶅垹涓嶅叆搴撱��
+---
+
+## 琛ュ厖锛�2026-09-08 鍌嶆櫄锛屽悓涓�浼氳瘽缁級锛氱敤鎴� 8 鏉℃暣鏀瑰叏閮ㄨ惤鍦板苟鍥炲綊
+### 浠婃棩鏂板
+1. **鏁版嵁鏌ョ湅婊氬姩鍔犺浇锛堢湡鏈哄娴嬶級**锛氳〃鏍煎浐瀹氶珮搴︺�佹粴鍔ㄥ鍣ㄧ粦瀹氬埌 el-table 鍐呴儴 body-wrapper锛涘疄娴� 20鈫�40 琛岃拷鍔犮�侀〉绛剧1椤碘啋绗�2椤碉紙13056 鏉℃�绘暟涓嶅彉锛夈��
+2. **瑙勫垯闃堝�艰仈鍔ㄦ櫘鍙婂埌鍏ㄩ儴瑙勫垯**锛歚RuleManageController.syncThresholdText` 鏀逛负鎸夆�滄棫闃堝�煎搴旂墖娈碘�濇浛鎹紙鏀寔 卤N%銆�>N%銆�0.5鈫�50%銆�1.3鈫掗珮鍑�30% 绛夊彛寰勶級锛岃鍒楄〃骞傜瓑鑷剤锛涘疄娴� P005/B001/E005/RULE_003/T001 鏄惧紡涓庢瘮鍊煎彛寰勫潎姝g‘骞舵寔涔呭寲锛岃鏄庝腑涓庨槇鍊兼棤鍏崇殑鏁板瓧涓嶅啀琚鏀广��
+3. **鍏矾鏃呭杩愭斂杞﹁締鏁板鍏ュ吋瀹规柊妯℃澘**锛氬悓浜嬩笅杞界殑杩愭斂搴撳鍑� .xls锛堣〃澶� OWNERNAME/鎬昏溅杈嗘暟/瀹綅鏁般�佹棤浼佷笟浠g爜鍒楋級涓庢棫涓枃鍥涘垪鍧囧彲瀵煎叆锛沗docs/鍏矾鏃呭/妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xlsx` 鎹负 `.xls`锛�2026-08 鍏� 750 瀹跺叆搴撱�佹娊鏍蜂笌婧愭枃浠朵竴鑷淬��
+4. **瀹℃牳缁撴灉鈥滄暟鎹�濇敼鏈堟姤鏍峰紡寮圭獥 + 鍒犻櫎浼佷笟瑙i噴鍒�**锛氳鍐呬粎鍓� 鏁版嵁/纭/蹇界暐锛涘脊绐楁寜 杩愬姏鎯呭喌鈫掕繍杈撶敓浜ф儏鍐碘啋骞冲潎鎸囨爣鈫掑~鎶ヤ汉淇℃伅 鍒嗗尯锛屾爣棰�=浼佷笟鍚�+鎶ヨ〃鏈熴��
+5. **姹囨�诲ぇ琛ㄥ鍑烘竻鐞�**锛歚cleanSummarySheetPresentation` 鍙栨秷鍚勯〉绛涢�夊苟杩樺師闅愯棌琛岋紙鐝嚎鍖呰溅绛夐〉涓嶅啀鍍忕己鏁版嵁锛夛紝淇濈暀涓や綅灏忔暟鏄剧ず/鍏ㄧ簿搴︺�佸叕寮忎笌鎵撳紑鑷姩閲嶇畻锛屾寜鍐呭鑷姩鍔犲鍒楀锛堝彧鍔犲涓嶇缉绐勩�佽烦杩囧悎骞舵爣棰橈級锛�19 椤靛鍑鸿剼鏈牎楠岄�氳繃銆�
+6. **鎶ヨ〃鐢熸垚 Tab 閲嶇粍**锛氣�滄眹鎬诲ぇ琛紙鏁存湰锛夆�濈嫭绔嬩负棣栦釜 Tab锛涘煄甯傚杩愭姤琛ㄥ幓鎺� tag銆佸懡鍚嶄笌鍏跺畠涓�鑷淬��
+7. **瀹℃牳椤电瓫閫夋爮椤哄簭**锛氭姤琛ㄦ湡绉诲埌鎶ヨ〃绫诲瀷宸﹁竟銆�
+8. **鏈堜唤涓嬫媺骞翠唤椤哄簭**锛氶粯璁ゅ綋鍓嶅勾 2026 鍦ㄦ渶鍓嶏紝鍏跺悗 2025銆�2027銆�
+### 娴嬭瘯缁撴灉鎽樿
+- 璇﹁銆婂姛鑳芥祴璇曟姤鍛奯鏁存敼8椤瑰洖褰掗獙璇乢2026-09-08.md銆嬶紝8/8 閫氳繃锛涘墠绔凡閲嶆柊缂栬瘧銆佸悗绔凡閲嶅惎鍔犺浇鏂颁唬鐮併��
+### 閬楃暀涓庝笅涓�姝�
+- 8 鏈堝綋鏈堟暟鎹� M2/M3 濉�煎楠岋紱9 鏈堣捣鐨勯�愭湀瀵煎叆鈫掓墿鍒椻啋瀹℃牳鈫掔敓鎴愬畬鏁撮摼寰呬笟鍔℃暟鎹埌浣嶅悗缁х画銆�
+- 鏈湴涓存椂鏂囦欢锛坃*.ps1/_*.sql/*.bak/docs.zip/鐢熸垚浜х墿xlsx 绛夛級鏈叆搴擄紝寰呮暣鐞嗘竻鐞嗐��
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 894487e..0fe1227 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
@@ -558,24 +558,30 @@
}
}
- /** 鍏矾鏃呭杩愭斂杞﹁締鏁帮紙鐙珛妯℃澘锛氫紒涓氫唬鐮�/浼佷笟鍚嶇О/杞﹁締鏁�/杞藉浣嶆暟锛� */
+ /** 鍏矾鏃呭杩愭斂杞﹁締鏁帮紙鍏煎涓ょ琛ㄥご锛氣憼 浼佷笟浠g爜/浼佷笟鍚嶇О/杞﹁締鏁�/杞藉浣嶆暟锛涒憽 杩愭斂搴撳鍑� OWNERNAME/鎬昏溅杈嗘暟/瀹綅鏁帮紝鏃犱紒涓氫唬鐮佸垪锛� */
public ImportResult importPassengerAuth(MultipartFile file, String period) throws Exception {
List<PassengerAuthVehicle> authList = new ArrayList<>();
try (Workbook wb = WorkbookFactory.create(file.getInputStream())) {
Sheet sheet = wb.getSheetAt(0);
- Map<String, Integer> colMap = buildHeaderMap(sheet.getRow(0));
- requireHeaderCols(sheet, "鏃呭杩愭斂杞﹁締鏁�", "浼佷笟鍚嶇О", "杞﹁締鏁�", "杞藉浣嶆暟");
+ Map<String, Integer> colMap = buildHeaderMapCompat(sheet.getRow(0));
+ Integer nameCol = firstColIdx(colMap, "浼佷笟鍚嶇О", "OWNERNAME");
+ Integer vehicleCol = firstColIdx(colMap, "杞﹁締鏁�", "鎬昏溅杈嗘暟");
+ Integer seatCol = firstColIdx(colMap, "杞藉浣嶆暟", "瀹綅鏁�");
+ Integer codeCol = firstColIdx(colMap, "浼佷笟浠g爜");
+ if (nameCol == null || vehicleCol == null || seatCol == null) {
+ throw new RuntimeException("鎵�閫夋暟鎹被鍨嬨�愭梾瀹㈣繍鏀胯溅杈嗘暟銆戜笌鏂囦欢鍐呭涓嶇锛氳〃澶撮渶鍚�愪紒涓氬悕绉�/杞﹁締鏁�/杞藉浣嶆暟銆戞垨銆怬WNERNAME/鎬昏溅杈嗘暟/瀹綅鏁般�戯紝璇风‘璁ゆ槸鍚﹂�夐敊浜嗘暟鎹被鍨嬫垨浣跨敤浜嗘棫妯℃澘");
+ }
for (int r = 1; r <= sheet.getLastRowNum(); r++) {
Row row = sheet.getRow(r);
if (row == null) continue;
- String name = gs(row, colMap, "浼佷笟鍚嶇О");
+ String name = getString(row, nameCol);
if (name == null || name.trim().isEmpty()) continue;
PassengerAuthVehicle auth = new PassengerAuthVehicle();
auth.setReportPeriod(period);
- auth.setEnterpriseCode(gs(row, colMap, "浼佷笟浠g爜"));
+ auth.setEnterpriseCode(codeCol == null ? null : getString(row, codeCol));
auth.setEnterpriseName(name.trim());
- auth.setVehicleCount(gi(row, colMap, "杞﹁締鏁�"));
- auth.setSeatCount(gi(row, colMap, "杞藉浣嶆暟"));
+ auth.setVehicleCount(getInt(row, vehicleCol));
+ auth.setSeatCount(getInt(row, seatCol));
authList.add(auth);
}
} catch (Exception e) {
@@ -1396,6 +1402,33 @@
return colMap;
}
+ /** 鍏煎琛ㄥご鏄犲皠锛氬幓寮曞彿/鍘荤┖鐧斤紱绾嫳鏂囪〃澶寸粺涓�澶у啓锛堝 'OWNERNAME' 鈫� OWNERNAME锛夛紝渚夸簬鏂版棫妯℃澘娣风敤 */
+ private Map<String, Integer> buildHeaderMapCompat(Row header) {
+ Map<String, Integer> colMap = new HashMap<>();
+ if (header == null) return colMap;
+ for (Cell cell : header) {
+ if (cell == null) continue;
+ String h = FORMATTER.formatCellValue(cell).replace("'", "").replace("\"", "").trim();
+ if (h.isEmpty()) continue;
+ boolean ascii = true;
+ for (int i = 0; i < h.length(); i++) {
+ if (h.charAt(i) > 127) { ascii = false; break; }
+ }
+ if (ascii) h = h.toUpperCase();
+ if (!colMap.containsKey(h)) colMap.put(h, cell.getColumnIndex());
+ }
+ return colMap;
+ }
+
+ /** 鎸夊埆鍚嶉『搴忓彇绗竴涓瓨鍦ㄧ殑鍒楀彿锛屽叏閮ㄧ己澶辫繑鍥� null */
+ private Integer firstColIdx(Map<String, Integer> colMap, String... aliases) {
+ for (String a : aliases) {
+ Integer idx = colMap.get(a);
+ if (idx != null) return idx;
+ }
+ return null;
+ }
+
private int colIdx(Map<String, Integer> colMap, String header) {
Integer idx = colMap.get(header);
return idx == null ? -1 : idx;
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
index dce943c..2f2ebe2 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/reportexport/service/ReportExportService.java
@@ -3232,7 +3232,9 @@
log.info("姹囨�诲伐浣滅翱瑁佸壀鑷� {} 鏈堝畬鎴愶紝娓呯┖/鏀瑰啓鍗曞厓鏍兼暟={}", toMonth, trimmed);
}
dynamicSummaryYear(wb, year);
- applyTwoDecimalFormat(wb); // 姹囨�诲ぇ琛ㄤ繚鐣欎汉宸ユ瘝鐗堝垪瀹�/鐗堝紡锛氫笉鍋� autoFit锛堥暱鍏紡浼氭妸鍒楀椤剁垎锛�
+ cleanSummarySheetPresentation(wb); // 鍙栨秷鍚勯〉绛涢�夈�佽繕鍘熼殣钘忚锛堝惁鍒欌�滅彮绾垮寘杞︹�濈瓑椤电湅璧锋潵鍍忕己鏁版嵁锛�
+ applyTwoDecimalFormat(wb); // 鏁板�兼樉绀轰袱浣嶅皬鏁帮紙淇濈暀鍏ㄧ簿搴︼級锛�% / 鏃ユ湡绛夋棦鏈夋牱寮忎笉鏀瑰彉
+ autoFitContentColumns(wb); // 鎸夋暟鎹嚜鍔ㄥ姞瀹藉垪瀹斤紙鍙姞瀹戒笉缂╃獎锛岃烦杩囧悎骞舵爣棰樻牸锛岄槻闀挎枃鏈妸鍗曞垪鎾戠垎锛�
if (!wb.getCTWorkbook().isSetCalcPr()) wb.getCTWorkbook().addNewCalcPr();
wb.getCTWorkbook().getCalcPr().setFullCalcOnLoad(true); // 杩樺師/鏀瑰啓鍏紡鍚庢墦寮�鍗抽噸绠�
return toBytes(wb);
@@ -4800,6 +4802,26 @@
}
/** 姹囨�昏〃瀵煎嚭鍚庢寜鍐呭鑷姩鍔犲鍒楀锛堝彧鍔犲涓嶇缉绐勶紱璺宠繃鍚堝苟鍗曞厓鏍兼爣棰橈紝闃查暱鏍囬鎶婂崟鍒楁拺鐖嗭級 */
+ /** 姹囨�诲ぇ琛ㄨ緭鍑哄墠娓呯悊姣嶇増娈嬬暀涓嬫潵鐨勭瓫閫変笌琛岄殣钘忥細绛涢�夌澶�/闅愯棌琛屼細璁╂暣椤电湅璧锋潵鈥滅己鏁版嵁鈥� */
+ private void cleanSummarySheetPresentation(org.apache.poi.ss.usermodel.Workbook wb) {
+ if (wb == null) return;
+ for (int s = 0; s < wb.getNumberOfSheets(); s++) {
+ org.apache.poi.ss.usermodel.Sheet sh = wb.getSheetAt(s);
+ if (sh == null) continue;
+ if (sh instanceof org.apache.poi.xssf.usermodel.XSSFSheet) {
+ org.apache.poi.xssf.usermodel.XSSFSheet xs = (org.apache.poi.xssf.usermodel.XSSFSheet) sh;
+ if (xs.getCTWorksheet().isSetAutoFilter()) xs.getCTWorksheet().unsetAutoFilter();
+ for (org.apache.poi.ss.usermodel.Row row : xs) {
+ if (row == null) continue;
+ org.apache.poi.xssf.usermodel.XSSFRow xr = (org.apache.poi.xssf.usermodel.XSSFRow) row;
+ if (xr.getCTRow().isSetHidden()) xr.getCTRow().unsetHidden();
+ }
+ } else {
+ sh.setAutoFilter(null);
+ }
+ }
+ }
+
private void autoFitContentColumns(org.apache.poi.ss.usermodel.Workbook wb) {
if (wb == null) return;
org.apache.poi.ss.usermodel.DataFormatter dfmt = new org.apache.poi.ss.usermodel.DataFormatter();
diff --git a/traffic-audit-server/src/main/java/com/trafficaudit/rulemanage/controller/RuleManageController.java b/traffic-audit-server/src/main/java/com/trafficaudit/rulemanage/controller/RuleManageController.java
index b55fea1..e4087de 100644
--- a/traffic-audit-server/src/main/java/com/trafficaudit/rulemanage/controller/RuleManageController.java
+++ b/traffic-audit-server/src/main/java/com/trafficaudit/rulemanage/controller/RuleManageController.java
@@ -55,29 +55,94 @@
if (body.getThreshold() != null) rule.setThreshold(body.getThreshold());
if (body.getAlertLevel() != null) rule.setAlertLevel(body.getAlertLevel());
if (body.getDescription() != null) rule.setDescription(body.getDescription());
- // 闃堝�煎彉鍖栨椂鍚屾瑙勫垯鍚嶇О涓庤鏄庯紙鍚嶇О/璇存槑閲岀殑 卤N% 鎸夋柊闃堝�兼敼鍐欙級锛屽苟闅忎繚瀛樻寔涔呭寲
+ // 闃堝�煎彉鍖栨椂鍚屾瑙勫垯鍚嶇О涓庤鏄庯紙鍚嶇О/璇存槑閲屼笌鏃ч槇鍊煎搴旂殑 N% 鐗囨鎸夋柊闃堝�兼敼鍐欙級锛屽苟闅忎繚瀛樻寔涔呭寲
if (body.getThreshold() != null && !body.getThreshold().equals(oldThreshold)) {
- syncThresholdText(rule);
+ syncThresholdText(rule, oldThreshold);
}
rule.setUpdatedAt(LocalDateTime.now());
ruleMapper.updateById(rule);
return Result.ok("宸蹭繚瀛�");
}
- /** 卤N% 瀛楁牱鍖归厤锛堝悕绉�/璇存槑涓殢闃堝�煎姩鎬佸彉鍖栫殑鐗囨锛� */
- private static final Pattern PCT_TOKEN = Pattern.compile("卤\\s*\\d+(?:\\.\\d+)?\\s*%");
+ /** % 鍓嶇殑鏁板�硷紙鍚嶇О/璇存槑涓殢闃堝�煎姩鎬佸彉鍖栫殑鐗囨锛�% 鍓嶅彲鑳芥槸 卤銆�>銆佽秴杩囥�侀珮鍑� 绛夋弿杩拌瘝锛屼粎鏇挎崲鏁板瓧鏈韩锛� */
+ private static final Pattern PCT_NUM = Pattern.compile("\\d+(?:\\.\\d+)?(?=%)");
- /** 鎶婃枃鏈腑鐨� 卤N% 鏇挎崲涓� 卤threshold%锛堝惈宸插甫 卤 鐨勫墠缂�锛岄伩鍏嶅弻 卤锛� */
- private String decorateThresholdText(String text, String threshold) {
- if (text == null || text.trim().isEmpty() || threshold == null || threshold.trim().isEmpty()) return text;
- String token = "卤" + threshold.trim() + "%";
- return PCT_TOKEN.matcher(text).replaceAll(Matcher.quoteReplacement(token));
+ /** 瑙f瀽闃堝�煎瓧绗︿覆涓涓�涓暟鍊硷紱鏃犳硶瑙f瀽杩斿洖 null */
+ private Double parseThresholdNum(String threshold) {
+ if (threshold == null || threshold.trim().isEmpty()) return null;
+ java.util.regex.Matcher m = Pattern.compile("\\d+(?:\\.\\d+)?").matcher(threshold.trim());
+ if (!m.find()) return null;
+ try {
+ return Double.parseDouble(m.group());
+ } catch (Exception e) {
+ return null;
+ }
}
- /** 鍚嶇О/璇存槑闅忛槇鍊煎悓姝ワ紙璇诲垪琛ㄦ椂涔熷姩鎬佹牎姝o紝DB 涓棫鏂囨湰涓嶉樆濉炴樉绀猴級 */
- private void syncThresholdText(AuditRule rule) {
+ /** 鏁板�煎睍绀猴細鏁存暟鍘绘帀灏忔暟浣嶏紝鍏朵綑淇濈暀鍘熺簿搴� */
+ private String fmtNum(double v) {
+ long l = Math.round(v);
+ if (Math.abs(v - l) < 1e-9) return Long.toString(l);
+ return new java.math.BigDecimal(String.valueOf(v)).stripTrailingZeros().toPlainString();
+ }
+
+ /** 鐢遍槇鍊兼暟鍊兼帹瀵尖�滆鏄庢枃瀛楅噷鍐欑殑鏄櫨鍒嗕箣鍑犫�濈殑鍊欓�夊彛寰勶細
+ * 鈶� 闃堝�兼湰韬氨鏄櫨鍒嗘暟锛堝 20 鈫� 卤20%锛夛紱
+ * 鈶� 闃堝�兼槸灏忔暟姣斾緥锛堝 0.02 鈫� 2%銆�0.5 鈫� 50%锛夛紱姝ゆ椂 <1 鎵嶅惎鐢紱
+ * 鈶� 闃堝�兼槸姣斿�硷紙濡� 1.3 鈫� 楂樺嚭30%锛夛紱姝ゆ椂 >1 鎵嶅惎鐢ㄣ�� */
+ private double[] thresholdPercentCandidates(double v) {
+ double[] cands;
+ if (v > 0 && v < 1) {
+ cands = new double[]{v, v * 100};
+ } else if (v > 1) {
+ cands = new double[]{v, (v - 1) * 100};
+ } else {
+ cands = new double[]{v};
+ }
+ return cands;
+ }
+
+ /** 鎸夋棫闃堝�煎尮閰嶆枃鏈腑宸叉湁鐨勭櫨鍒嗘瘮鐗囨锛屼粎鏇挎崲鈥滀笌鏃ч槇鍊煎寰椾笂鈥濈殑鏁板瓧涓烘柊闃堝�煎搴旀暟瀛楋紱瀵逛笉涓婄殑鏁板瓧锛堝璇存槑閲屼笌闃堝�兼棤鍏崇殑鏁板�硷級淇濇寔涓嶅姩 */
+ private String decorateThresholdText(String text, String oldThreshold, String newThreshold) {
+ if (text == null || text.trim().isEmpty()) return text;
+ Double oldNum = parseThresholdNum(oldThreshold);
+ Double newNum = parseThresholdNum(newThreshold);
+ if (oldNum == null || newNum == null) return text;
+ double[] oldCands = thresholdPercentCandidates(oldNum);
+ double[] newCands = thresholdPercentCandidates(newNum);
+ if (oldCands.length != newCands.length) return text;
+ java.util.regex.Matcher m = PCT_NUM.matcher(text);
+ StringBuffer sb = new StringBuffer();
+ while (m.find()) {
+ double token;
+ try {
+ token = Double.parseDouble(m.group());
+ } catch (Exception e) {
+ continue;
+ }
+ String repl = null;
+ for (int i = 0; i < oldCands.length; i++) {
+ if (Math.abs(oldCands[i] - token) < 1e-9) {
+ repl = fmtNum(newCands[i]);
+ break;
+ }
+ }
+ if (repl == null) continue;
+ m.appendReplacement(sb, Matcher.quoteReplacement(repl));
+ }
+ m.appendTail(sb);
+ return sb.toString();
+ }
+
+ /** 鍚嶇О/璇存槑闅忛槇鍊煎悓姝ワ紙update 鏃舵寜 鏃р啋鏂� 鏀瑰啓骞舵寔涔呭寲锛� */
+ private void syncThresholdText(AuditRule rule, String oldThreshold) {
if (rule == null || rule.getThreshold() == null) return;
- rule.setRuleName(decorateThresholdText(rule.getRuleName(), rule.getThreshold()));
- rule.setDescription(decorateThresholdText(rule.getDescription(), rule.getThreshold()));
+ rule.setRuleName(decorateThresholdText(rule.getRuleName(), oldThreshold, rule.getThreshold()));
+ rule.setDescription(decorateThresholdText(rule.getDescription(), oldThreshold, rule.getThreshold()));
+ }
+
+ /** 璇诲垪琛ㄦ椂鑷剤锛氫粎褰撴枃鏈墖娈典笌褰撳墠闃堝�煎搴旀椂鎵嶆敼鍐欙紙骞傜瓑锛屼笉璇激涓庨槇鍊兼棤鍏崇殑鏁板瓧锛� */
+ private void syncThresholdText(AuditRule rule) {
+ syncThresholdText(rule, rule == null ? null : rule.getThreshold());
}
}
\ No newline at end of file
diff --git a/traffic-audit-web/src/views/AuditResult.vue b/traffic-audit-web/src/views/AuditResult.vue
index fb821eb..7c510d5 100644
--- a/traffic-audit-web/src/views/AuditResult.vue
+++ b/traffic-audit-web/src/views/AuditResult.vue
@@ -17,6 +17,9 @@
<el-main :class="{ 'main-focus': focusMode }" style="display:flex;flex-direction:column;min-height:0">
<h3 v-show="!focusMode" style="flex:none;margin:0 0 10px">瀹℃牳缁撴灉</h3>
<el-form :inline="true" style="flex:none">
+ <el-form-item label="鎶ヨ〃鏈�">
+ <el-date-picker v-model="period" type="month" placeholder="閫夋嫨鏈堜唤" value-format="yyyy-MM" @change="onPeriodChange"></el-date-picker>
+ </el-form-item>
<el-form-item label="鎶ヨ〃绫诲瀷">
<el-radio-group v-model="reportType" @change="onTypeChange">
<el-radio label="H2032">璐ц繍鏈堟姤</el-radio>
@@ -30,9 +33,7 @@
</el-radio-group>
</el-form-item>
- <el-form-item label="鎶ヨ〃鏈�">
- <el-date-picker v-model="period" type="month" placeholder="閫夋嫨鏈堜唤" value-format="yyyy-MM" @change="onPeriodChange"></el-date-picker>
- </el-form-item>
+
<el-form-item>
<el-button type="primary" @click="executeAudit" :loading="loading">鎵ц瀹℃牳</el-button>
<el-button type="success" plain @click="markAudited" :loading="marking">鏍囪宸插鏍�</el-button>
@@ -116,12 +117,7 @@
<i :class="statusIcon(row.status)"></i> {{ statusText(row.status) }}
</el-tag>
<span class="spacer"></span>
- <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="goData(row)">鏁版嵁</el-link>
- <el-tag v-if="explainType(reportType)" size="mini" :type="row.verifyExplanation ? 'success' : 'warning'"
- style="cursor:pointer" :title="expandedExplain === row.reportId ? '鏀惰捣瑙i噴' : '灞曞紑濉啓/鏌ョ湅瑙i噴'"
- @click="toggleExplain(row.reportId)">
- {{ row.verifyExplanation ? '瑙i噴锛氬凡濉啓' : '瑙i噴锛氭湭濉啓' }}
- </el-tag>
+ <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(row)">鏁版嵁</el-link>
<el-button v-if="row.status === 'PENDING'" size="mini" type="success" icon="el-icon-check" round @click="review(row, 'CONFIRMED')">纭</el-button>
<el-button v-if="row.status === 'PENDING'" size="mini" type="info" icon="el-icon-close" round plain @click="review(row, 'IGNORED')">蹇界暐</el-button>
<span v-else class="done-text">宸插鐞�</span>
@@ -135,21 +131,6 @@
<div class="detail-line"><span class="dt-label">瀹為檯</span><span class="dt-val">{{ row.actualValue }}</span></div>
<div class="detail-line"><span class="dt-label">鍩哄噯</span><span class="dt-val">{{ row.thresholdValue }}</span></div>
<div class="detail-line"><span class="dt-label">宸紓</span><span class="dt-val dt-warn">{{ row.deviation }}</span></div>
- </div>
- </div>
- <div v-if="explainType(reportType) && expandedExplain === row.reportId" class="explain-side" style="margin:0 12px 10px">
- <div class="explain-head">
- <span class="explain-title">浼佷笟瑙i噴</span>
- <el-tag size="mini" :type="row.verifyExplanation ? 'success' : 'warning'">{{ row.verifyExplanation ? '宸插~鍐�' : '鏈~鍐�' }}</el-tag>
- <span style="flex:1"></span>
- <el-button size="mini" text @click="expandedExplain = null">鏀惰捣</el-button>
- </div>
- <span v-if="row.verifyExplanation" class="explain-cur">{{ row.verifyExplanation }}</span>
- <el-input v-model="explainDrafts[row.reportId]" type="textarea" :rows="2" resize="none"
- placeholder="濉啓/淇敼璇ヤ紒涓氱殑瑙i噴璇存槑鈥�"></el-input>
- <div class="explain-actions">
- <el-button size="mini" type="primary" plain :loading="savingExplainId === row.reportId" @click="saveExplain(row)">淇濆瓨瑙i噴</el-button>
- <el-button v-if="(explainDrafts[row.reportId] || '') !== (row.verifyExplanation || '')" size="mini" text @click="resetDraft(row.reportId)">閲嶇疆</el-button>
</div>
</div>
</div>
@@ -175,7 +156,7 @@
<b>{{ item.ruleName }}</b>
<el-tag :type="item.alertLevel === 'RED' ? 'danger' : 'warning'" size="mini">{{ item.alertLevel }}</el-tag>
<el-tag :type="statusType(item.status)" size="mini">{{ statusText(item.status) }}</el-tag>
- <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="goData(item)">鏁版嵁</el-link>
+ <el-link v-if="dataType(reportType)" type="primary" :underline="false" size="mini" @click="openMonthReport(item)">鏁版嵁</el-link>
<span style="flex:1"></span>
<el-button v-if="item.status === 'PENDING'" size="mini" type="success" @click="review(item, 'CONFIRMED')">纭</el-button>
<el-button v-if="item.status === 'PENDING'" size="mini" type="info" @click="review(item, 'IGNORED')">蹇界暐</el-button>
@@ -188,32 +169,6 @@
</div>
</template>
</el-table-column>
- <el-table-column label="浼佷笟瑙i噴" width="340">
- <template slot-scope="scope">
- <div v-if="explainType(reportType) && scope.row.items[0]" class="explain-cell">
- <div v-if="expandedExplain !== scope.row.items[0].reportId" class="explain-compact">
- <el-tag size="mini" :type="scope.row.items[0].verifyExplanation ? 'success' : 'warning'">{{ scope.row.items[0].verifyExplanation ? '宸插~鍐�' : '鏈~鍐�' }}</el-tag>
- <div v-if="scope.row.items[0].verifyExplanation" class="explain-preview">{{ scope.row.items[0].verifyExplanation }}</div>
- <el-button size="mini" text type="primary" @click="expandedExplain = scope.row.items[0].reportId">濉啓/淇敼</el-button>
- </div>
- <div v-else class="explain-side">
- <div class="explain-head">
- <span class="explain-title">浼佷笟瑙i噴</span>
- <span style="flex:1"></span>
- <el-button size="mini" text @click="expandedExplain = null">鏀惰捣</el-button>
- </div>
- <span v-if="scope.row.items[0].verifyExplanation" class="explain-cur">{{ scope.row.items[0].verifyExplanation }}</span>
- <el-input v-model="explainDrafts[scope.row.items[0].reportId]" type="textarea" :rows="2" resize="none"
- placeholder="濉啓/淇敼璇ヤ紒涓氱殑瑙i噴璇存槑鈥�"></el-input>
- <div class="explain-actions">
- <el-button size="mini" type="primary" plain :loading="savingExplainId === scope.row.items[0].reportId" @click="saveExplain(scope.row.items[0])">淇濆瓨瑙i噴</el-button>
- <el-button v-if="(explainDrafts[scope.row.items[0].reportId] || '') !== (scope.row.items[0].verifyExplanation || '')" size="mini" text @click="resetDraft(scope.row.items[0].reportId)">閲嶇疆</el-button>
- </div>
- </div>
- </div>
- <span v-else style="color:#C0C4CC;font-size:12px">鈥�</span>
- </template>
- </el-table-column>
<el-table-column label="鎿嶄綔" width="130">
<template slot-scope="scope">
<el-button v-if="hasPending(scope.row)" size="mini" type="success" plain @click="reviewAll(scope.row, 'CONFIRMED')">鍏ㄩ儴纭</el-button>
@@ -224,6 +179,50 @@
</div>
</el-main>
</el-container>
+
+ <el-dialog title="鏁版嵁鏌ョ湅锛堟湀鎶ユ牱寮忥級" :visible.sync="monthVisible" width="880px" top="4vh" custom-class="mr-dialog">
+ <div v-if="monthLoading" style="padding:40px 0;text-align:center;color:#909399">鍔犺浇涓��</div>
+ <div v-else-if="!monthRecords.length" style="padding:30px 0;text-align:center;color:#909399">
+ 鏈煡璇㈠埌璇ヤ紒涓氥�佽鎶ヨ〃鏈熺殑濉姤鏁版嵁锛堝彲鑳借繕鏈鍏ワ級
+ </div>
+ <div v-else class="mr-body">
+ <div v-for="(rec, ri) in monthRecords" :key="ri" class="mr-card">
+ <div class="mr-title">{{ monthTitle(rec) }}</div>
+ <table class="mr-meta">
+ <tbody>
+ <tr v-for="(m, mi) in monthMeta(rec)" :key="mi">
+ <td class="mr-meta-k">{{ m.label }}</td>
+ <td class="mr-meta-v">{{ fmtVal(m.value) }}</td>
+ </tr>
+ </tbody>
+ </table>
+ <div v-for="sec in monthSections(rec)" :key="sec.title" class="mr-sec">
+ <div class="mr-sec-title">{{ sec.title }}</div>
+ <table class="mr-sec-tab" border="1">
+ <thead>
+ <tr>
+ <th style="width:34%">鎸囨爣鍚嶇О</th>
+ <th v-for="(h, hi) in sec.head" :key="hi" style="width:16.5%">{{ h }}</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr v-for="(rw, rwi) in sec.rows" :key="rwi">
+ <td>{{ rw.label }}</td>
+ <td v-for="(c, ci) in rw.cells" :key="ci">{{ fmtVal(c.v) }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div v-if="rec.verifyExplanation || rec.reportNotes" class="mr-note">
+ <div v-if="rec.verifyExplanation" class="mr-note-line"><b>鏍稿疄瑙i噴锛�</b>{{ rec.verifyExplanation }}</div>
+ <div v-if="rec.reportNotes" class="mr-note-line"><b>澶囨敞锛�</b>{{ rec.reportNotes }}</div>
+ </div>
+ </div>
+ </div>
+ <span slot="footer">
+ <el-button size="small" @click="monthVisible = false">鍏抽棴</el-button>
+ </span>
+ </el-dialog>
</el-container>
</template>
<script>
@@ -231,6 +230,104 @@
import api from '@/api'
const DATA_TYPE_MAP = { H2032: 'h2032', H2031: 'h2031', CITY_BUS: 'cityBus', CITY_TAXI: 'cityTaxi' }
const EXPLAIN_TYPES = ['H2032', 'H2031', 'CITY_BUS', 'CITY_TAXI']
+
+const MONTH_CFG = {
+ h2032: {
+ meta: [['鎶ヨ〃鏈�', 'reportPeriod'], ['浼佷笟鍚嶇О', 'enterpriseName'], ['缁熶竴绀句細淇$敤浠g爜', 'unifiedCreditCode'], ['濉姤鍗曚綅', 'reportUnit']],
+ sections: [
+ { title: '涓�銆佽繍鍔涙儏鍐�', head: ['杞﹁締鏁帮紙杈嗭級', '鏍囪鍚ㄤ綅鏁帮紙鍚級'], rows: [
+ ['鎬昏', ['vehicleTotal', 'tonsTotal']],
+ ['鍏朵腑锛氱壍寮曡溅', ['vehicleTractor', null]],
+ ['鎸傝溅', ['vehicleTrailer', 'tonsTrailer']],
+ ['鍏朵腑锛氶泦瑁呯杞�', ['vehicleContainer', 'tonsContainer']],
+ ['鏁磋溅', ['vehicleWhole', 'tonsWhole']]
+ ]},
+ { title: '浜屻�佽繍杈撶敓浜ф儏鍐�', head: ['璐ц繍閲忥紙鍚級', '璐х墿鍛ㄨ浆閲忥紙鍚ㄥ叕閲岋級'], rows: [
+ ['杩愯緭閲�', ['freightTotal', 'turnoverTotal']],
+ ['鍏朵腑锛氶泦瑁呯', ['freightContainer', null]],
+ ['鍏朵腑锛氱叅鐐強鍒跺搧', ['freightCoal', null]],
+ ['鐭虫补銆佸ぉ鐒舵皵鍙婂埗鍝�', ['freightOilGas', null]],
+ ['鍏朵腑锛氬師娌�', ['freightCrudeOil', null]],
+ ['閲戝睘鐭跨煶', ['freightMetalOre', null]],
+ ['鍏朵腑锛氶搧鐭跨煶', ['freightIronOre', null]],
+ ['鐭垮缓鎬у缓绛戞潗鏂�', ['freightBuilding', null]],
+ ['绮', ['freightGrain', null]]
+ ]},
+ { title: '骞冲潎鎸囨爣', head: [], rows: [
+ ['璐ц溅骞冲潎鍚ㄤ綅', ['avgTonnage', null]],
+ ['璐ц溅骞冲潎杩愯窛', ['avgDistance', null]]
+ ]},
+ { title: '濉姤浜轰俊鎭�', head: [], rows: [
+ ['鍗曚綅璐熻矗浜�', ['unitLeader', null]], ['缁熻璐熻矗浜�', ['statsLeader', null]],
+ ['濉〃浜�', ['contactPerson', null]], ['鑱旂郴鐢佃瘽', ['contactPhone', null]], ['鎶ュ嚭鏃ユ湡', ['reportDate', null]]
+ ]}
+ ]
+ },
+ h2031: {
+ meta: [['鎶ヨ〃鏈�', 'reportPeriod'], ['浼佷笟鍚嶇О', 'enterpriseName']],
+ sections: [
+ { title: '涓�銆佽繍鍔涙儏鍐�', head: ['杞﹁締鏁帮紙杈嗭級', '鏍稿畾杞藉浣嶏紙瀹綅锛�'], rows: [
+ ['鎬昏', ['vehicleTotal', 'seatTotal']],
+ ['瀹㈣繍鐝溅锛堝惈瀹氱嚎鏃呮父瀹㈣繍瀹㈣溅锛�', ['vehicleSchedule', 'seatSchedule']],
+ ['瀹㈣繍鍖呰溅锛堝惈闈炲畾绾挎梾娓稿杩愬杞︼級', ['vehicleCharter', 'seatCharter']]
+ ]},
+ { title: '浜屻�佽繍杈撶敓浜ф儏鍐�', head: ['瀹㈣繍閲忥紙浜烘锛�', '鏃呭鍛ㄨ浆閲忥紙浜哄叕閲岋級'], rows: [
+ ['鎬昏', ['passengerTotal', 'turnoverTotal']],
+ ['涓�绫诲杩愮彮绾匡紙鍚畾绾挎梾娓革級', ['passengerClass1', 'turnoverClass1']],
+ ['浜岀被瀹㈣繍鐝嚎锛堝惈瀹氱嚎鏃呮父锛�', ['passengerClass2', 'turnoverClass2']],
+ ['涓夌被瀹㈣繍鐝嚎锛堝惈瀹氱嚎鏃呮父锛�', ['passengerClass3', 'turnoverClass3']],
+ ['鍥涚被瀹㈣繍鐝嚎锛堝惈瀹氱嚎鏃呮父锛�', ['passengerClass4', 'turnoverClass4']],
+ ['瀹㈣繍鍖呰溅锛堝惈闈炲畾绾挎梾娓革級', ['passengerCharter', 'turnoverCharter']]
+ ]},
+ { title: '瀹㈣繍骞冲潎杩愯窛', head: [], rows: [
+ ['瀹㈣繍骞冲潎杩愯窛', ['avgDistanceTotal', null]],
+ ['涓�绫诲杩愮彮绾垮钩鍧囪繍璺�', ['avgDistanceClass1', null]],
+ ['浜岀被瀹㈣繍鐝嚎骞冲潎杩愯窛', ['avgDistanceClass2', null]],
+ ['涓夌被瀹㈣繍鐝嚎骞冲潎杩愯窛', ['avgDistanceClass3', null]],
+ ['鍥涚被瀹㈣繍鐝嚎骞冲潎杩愯窛', ['avgDistanceClass4', null]],
+ ['瀹㈣繍鍖呰溅骞冲潎杩愯窛', ['avgDistanceCharter', null]]
+ ]}
+ ]
+ },
+ cityBus: {
+ meta: [['鎶ヨ〃鏈�', 'reportPeriod'], ['甯傚窞', 'city'], ['浼佷笟鍚嶇О', 'enterpriseName']],
+ sections: [
+ { title: '涓�銆佸叕鍏辨苯鐢佃溅杩愯惀', head: [], rows: [
+ ['杩愯惀杞︽暟锛堣締锛�', ['opVehicles', null]], ['杩愯惀绔欑偣鎬讳釜鏁帮紙涓級', ['stopTotal', null]],
+ ['鍏朵腑锛氬煄甯傝繍钀ョ珯鐐�', ['stopCity', null]], ['瀹㈣繍閲忥紙涓囦汉娆★級', ['passengerVolume', null]],
+ ['鍏朵腑锛氬煄甯傚杩愰噺', ['passengerCity', null]], ['鏃呭鍛ㄨ浆閲忥紙涓囦汉鍏噷锛�', ['turnover', null]],
+ ['鍏朵腑锛氬煄甯傛梾瀹㈠懆杞噺', ['turnoverCity', null]]
+ ]},
+ { title: '浜屻�佹淳鐢熸寚鏍囦笌澧為��', head: [], rows: [
+ ['骞冲潎杩愯窛锛堝叕閲岋級', ['avgDistance', null]], ['鍩庡競鍐呭钩鍧囪繍璺�', ['avgDistanceCity', null]],
+ ['鍩庨檯鍩庝埂瀹㈣繍閲�', ['passengerChengxiang', null]], ['鍩庨檯鍩庝埂鍛ㄨ浆閲�', ['turnoverChengxiang', null]],
+ ['鍩庨檯鍩庝埂骞冲潎杩愯窛', ['avgDistanceChengxiang', null]], ['瀹㈣繍閲忕幆姣�', ['ratePassengerMom', null]],
+ ['鍩庡競鍐呭杩愰噺鐜瘮', ['ratePassengerCityMom', null]], ['鍩庨檯鍩庝埂瀹㈣繍閲忕幆姣�', ['rateChengxiangMom', null]],
+ ['瀹㈣繍閲忓悓姣�', ['ratePassengerYoy', null]], ['鍩庡競鍐呭杩愰噺鍗犳瘮', ['passengerCityRatio', null]],
+ ['鍩庨檯鍩庝埂瀹㈣繍閲忓崰姣�', ['chengxiangRatio', null]], ['濉〃浜�', ['contactPerson', null]],
+ ['鎶ュ嚭鏃ユ湡', ['reportDate', null]]
+ ]}
+ ]
+ },
+ cityTaxi: {
+ meta: [['鎶ヨ〃鏈�', 'reportPeriod'], ['甯傚窞', 'city'], ['浼佷笟鍚嶇О', 'enterpriseName']],
+ sections: [
+ { title: '涓�銆佸贰娓稿嚭绉熻繍钀ユ湇鍔�', head: [], rows: [
+ ['杞藉杞︽鎬绘暟锛堜竾杞︽锛�', ['tripTotal', null]], ['鍏朵腑锛氬煄甯傝浇瀹㈣溅娆�', ['tripCity', null]],
+ ['瀹㈣繍閲忥紙涓囦汉娆★級', ['passengerVolume', null]], ['鍏朵腑锛氬煄甯傚杩愰噺', ['passengerCity', null]],
+ ['鏃呭鍛ㄨ浆閲忥紙涓囦汉鍏噷锛�', ['turnover', null]], ['鍏朵腑锛氬煄甯傛梾瀹㈠懆杞噺', ['turnoverCity', null]],
+ ['杩愯惀杞﹁締鏁帮紙杈嗭級', ['opVehicles', null]]
+ ]},
+ { title: '浜屻�佹淳鐢熸寚鏍囦笌澧為��', head: [], rows: [
+ ['骞冲潎杩愯窛锛堝叕閲岋級', ['avgDistance', null]], ['鍩庡競鍐呭钩鍧囪繍璺�', ['avgDistanceCity', null]],
+ ['鍗曡溅娆¤浇瀹汉鏁�', ['passengersPerTrip', null]], ['杞藉杞︽鐜瘮', ['rateTripMom', null]],
+ ['杞藉杞︽鍚屾瘮', ['rateTripYoy', null]], ['瀹㈣繍閲忕幆姣�', ['ratePassengerMom', null]],
+ ['瀹㈣繍閲忓悓姣�', ['ratePassengerYoy', null]], ['鍩庡競鍐呭杩愰噺鍗犳瘮', ['passengerCityRatio', null]],
+ ['鍩庨檯鍩庝埂骞冲潎杩愯窛', ['avgDistanceChengxiang', null]]
+ ]}
+ ]
+ }
+}
export default {
components: { AppHeader },
name: 'AuditResult',
@@ -238,7 +335,8 @@
return {
period: '', reportType: 'H2032', loading: false, marking: false, results: [], ruleStats: [], statsCollapsed: false,
enterpriseFilter: '', ruleFilter: '', viewMode: 'merged', batchSelection: [], focusMode: false,
- explainDrafts: {}, savingExplainId: null, expandedExplain: null
+ explainDrafts: {}, savingExplainId: null, expandedExplain: null,
+ monthVisible: false, monthLoading: false, monthType: '', monthPeriod: '', monthKeyword: '', monthRecords: [], monthColumns: []
}
},
computed: {
@@ -301,10 +399,56 @@
methods: {
dataType(t) { return DATA_TYPE_MAP[t] || '' },
explainType(t) { return EXPLAIN_TYPES.indexOf(t) >= 0 },
- goData(row) {
+ openMonthReport(row) {
const type = DATA_TYPE_MAP[this.reportType]
if (!type) return
- this.$router.push({ path: '/data', query: { type, period: row.reportPeriod, keyword: row.enterpriseName || row.city || '' } })
+ this.monthType = type
+ this.monthPeriod = row.reportPeriod
+ this.monthKeyword = row.enterpriseName || row.city || ''
+ this.monthRecords = []
+ this.monthColumns = []
+ this.monthVisible = true
+ this.monthLoading = true
+ api.get('/data/list', {
+ params: {
+ type, period: row.reportPeriod,
+ keyword: row.enterpriseName || row.city || '',
+ page: 1, size: 50
+ }, timeout: 60000
+ }).then(res => {
+ const d = res.data || {}
+ this.monthRecords = d.records || []
+ this.monthColumns = d.columns || []
+ if (!this.monthRecords.length) this.$message.warning('鏈煡璇㈠埌璇ヤ紒涓氳鎶ヨ〃鏈熺殑濉姤鏁版嵁锛堝彲鑳藉皻鏈鍏ワ級')
+ }).catch(e => {
+ if (e && e._toast) return
+ this.$message.error('鏈堟姤鏁版嵁鏌ヨ澶辫触')
+ }).finally(() => { this.monthLoading = false })
+ },
+ monthTitle(rec) {
+ const cfg = MONTH_CFG[this.monthType] || null
+ if (!cfg) return (this.monthKeyword || '') + '锛�' + this.monthPeriod + '锛�'
+ const name = rec.enterpriseName || rec.city || this.monthKeyword || ''
+ return name + ' ' + (rec.reportPeriod || this.monthPeriod || '') + ' 鏈堟姤鏁版嵁'
+ },
+ monthMeta(rec) {
+ const cfg = MONTH_CFG[this.monthType] || null
+ if (!cfg) return []
+ return cfg.meta.map(m => ({ label: m[0], value: rec[m[1]] })).filter(m => m.value !== undefined)
+ },
+ monthSections(rec) {
+ const cfg = MONTH_CFG[this.monthType]
+ if (!cfg) return []
+ return cfg.sections.map(sec => ({
+ title: sec.title, head: sec.head || [],
+ rows: sec.rows.map(r => ({ label: r[0], cells: (r[1] || []).map(prop => ({ prop, v: prop ? rec[prop] : null })) }))
+ .filter(rw => rw.cells.some(c => c.v !== null && c.v !== undefined && c.v !== ''))
+ })).filter(sec => sec.rows.length)
+ },
+ fmtVal(v) {
+ if (v === null || v === undefined || v === '') return '鈥�'
+ if (typeof v === 'number') return String(v)
+ return String(v)
},
goExplain(row) {
this.$router.push({ path: '/explain', query: { reportType: this.reportType, keyword: row.enterpriseName || row.city || '', period: row.reportPeriod } })
@@ -581,4 +725,20 @@
.stat-num { color: #909399; }
.stat-num b { font-weight: 700; }
.hit-num { color: #E6A23C; }
+
+.mr-dialog .el-dialog__body { padding: 12px 18px; }
+.mr-body { max-height: 66vh; overflow-y: auto; }
+.mr-card { border: 1px solid #DCDFE6; border-radius: 6px; margin-bottom: 14px; overflow: hidden; }
+.mr-title { background: #409EFF; color: #fff; font-weight: 600; padding: 8px 12px; font-size: 15px; }
+.mr-meta { width: 100%; border-collapse: collapse; background: #F7F9FC; }
+.mr-meta td { border: 1px solid #EBEEF5; padding: 6px 10px; font-size: 13px; }
+.mr-meta-k { width: 120px; color: #909399; background: #F0F4FA; }
+.mr-meta-v { color: #303133; font-weight: 600; }
+.mr-sec { padding: 10px 12px 4px; }
+.mr-sec-title { font-weight: 600; color: #303133; margin: 4px 0 8px; }
+.mr-sec-tab { width: 100%; border-collapse: collapse; font-size: 13px; }
+.mr-sec-tab th, .mr-sec-tab td { border: 1px solid #DCDFE6; padding: 5px 8px; text-align: left; color: #303133; }
+.mr-sec-tab th { background: #F5F7FA; font-weight: 600; }
+.mr-note { margin: 6px 12px 12px; background: #FDF6EC; border: 1px solid #FAECD8; border-radius: 4px; padding: 8px 10px; font-size: 12px; color: #8a6d3b; white-space: pre-wrap; word-break: break-all; }
+.mr-note-line { margin: 2px 0; }
</style>
diff --git a/traffic-audit-web/src/views/DataImport.vue b/traffic-audit-web/src/views/DataImport.vue
index a36ee76..3215245 100644
--- a/traffic-audit-web/src/views/DataImport.vue
+++ b/traffic-audit-web/src/views/DataImport.vue
@@ -251,7 +251,7 @@
scaleSplit: '妯℃澘_瑙勪笂瑙勪笅鎷嗗垎杩愯緭閲�.xlsx',
freightTurnover: '妯℃澘_璐ц繍閲忓懆杞噺.xlsx',
passengerMonthly: '鍏矾鏃呭杩愯緭鏈堝害鐢熶骇鎯呭喌.xlsx锛堝惈杩愭斂杞﹁締鏁皊heet锛�',
- passengerAuth: '妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xlsx锛堝垪锛氫紒涓氫唬鐮�/浼佷笟鍚嶇О/杞﹁締鏁�/杞藉浣嶆暟锛�',
+ passengerAuth: '妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xls锛堟敮鎸� 浼佷笟浠g爜/浼佷笟鍚嶇О/杞﹁締鏁�/杞藉浣嶆暟 涓� 杩愭斂搴撳鍑� OWNERNAME/鎬昏溅杈嗘暟/瀹綅鏁帮級',
passengerIndividual: '涓綋瀹㈣繍閲忔眹鎬�.xlsx锛堝垪锛氭墍灞炲湴鍖�/浼佷笟浠g爜/浼佷笟鍚嶇О/涓綋瀹㈣繍閲�/涓綋鏃呭鍛ㄨ浆閲忥級',
energyMonthly: '閬撹矾璐ц繍杞﹁締鑳芥簮娑堣�楁儏鍐碉紙2026骞达級.xlsx锛堣兘鑰楁槑缁�+杩愭斂杞﹁締淇℃伅涓heet锛�',
energyAuth: '妯℃澘_鑳借�楄溅杈嗚繍鏀夸俊鎭�.xlsx锛堝垪锛氳溅鐗屽彿/杞﹁締绫诲瀷/鐕冩枡绫诲瀷/鏍囪鍚ㄤ綅/鍑嗙壍寮曡川閲忥級',
@@ -276,7 +276,7 @@
scaleSplit: '璐ц繍/妯℃澘_瑙勪笂瑙勪笅鎷嗗垎杩愯緭閲�.xlsx',
freightTurnover: '璐ц繍/妯℃澘_璐ц繍閲忓懆杞噺.xlsx',
passengerMonthly: '鍏矾鏃呭/妯℃澘_浜や紒缁烪203-1琛╛鍏矾鏃呭杩愯緭鏈堝害鐢熶骇鎯呭喌.xlsx',
- passengerAuth: '鍏矾鏃呭/妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xlsx',
+ passengerAuth: '鍏矾鏃呭/妯℃澘_鍏矾鏃呭杩愭斂杞﹁締鏁�.xls',
passengerIndividual: '鍏矾鏃呭/涓綋瀹㈣繍閲忔眹鎬�.xlsx',
energyMonthly: '鑳借��/妯℃澘_閬撹矾璐ц繍杞﹁締鑳芥簮娑堣�楁儏鍐碉紙2026锛�.xlsx',
energyAuth: '鑳借��/妯℃澘_鑳借�楄溅杈嗚繍鏀夸俊鎭�.xlsx',
diff --git a/traffic-audit-web/src/views/DataView.vue b/traffic-audit-web/src/views/DataView.vue
index 1ec3c5e..3dce26a 100644
--- a/traffic-audit-web/src/views/DataView.vue
+++ b/traffic-audit-web/src/views/DataView.vue
@@ -111,7 +111,19 @@
this.$message.error('鏁版嵁鏌ヨ澶辫触')
}).finally(() => {
this.loading = false
+ this.$nextTick(() => this.attachBodyScroll())
})
+ },
+ // el-table 鍥哄畾楂樺害鍚庯紝鐪熸鐨勭珫鍚戞粴鍔ㄥ鍣ㄦ槸鍐呴儴鐨� body-wrapper锛堥〉闈㈡湰韬笉婊氬姩锛�
+ attachBodyScroll() {
+ const wrap = this.$refs.tableWrap
+ if (!wrap) return
+ const bw = wrap.querySelector('.el-table__body-wrapper')
+ if (bw && bw._vwScrollHandler !== this.onScroll) {
+ if (bw._vwScrollHandler) bw.removeEventListener('scroll', bw._vwScrollHandler)
+ bw.addEventListener('scroll', this.onScroll, { passive: true })
+ bw._vwScrollHandler = this.onScroll
+ }
},
// 婊氬姩鍒板簳閮ㄨ嚜鍔ㄨ拷鍔犱笅涓�椤碉紙淇濈暀鎵嬪姩鍒嗛〉璺抽〉鑳藉姏锛�
loadMore() {
@@ -143,6 +155,7 @@
this.$message.error('鍔犺浇鏇村澶辫触')
}).finally(() => {
this.loadingMore = false
+ this.$nextTick(() => this.attachBodyScroll())
})
},
onScroll(e) {
@@ -189,17 +202,39 @@
// capture=true锛歟l-table 鍐呴儴 body-wrapper 鐨勬粴鍔ㄥ湪鎹曡幏闃舵涔熻兘鏀跺埌
this.$refs.tableWrap.addEventListener('scroll', this.onScroll, { passive: true, capture: true })
}
+ this.$nextTick(() => this.attachBodyScroll())
},
beforeDestroy() {
window.removeEventListener('scroll', this.onScroll)
if (this.$refs.tableWrap) {
this.$refs.tableWrap.removeEventListener('scroll', this.onScroll, { capture: true })
+ const bw = this.$refs.tableWrap.querySelector('.el-table__body-wrapper')
+ if (bw && bw._vwScrollHandler) bw.removeEventListener('scroll', bw._vwScrollHandler)
}
}
}
</script>
<style scoped>
.el-header { background: #409EFF; color: white; line-height: 60px; font-size: 18px; }
+#app .table-wrap {
+ display: flex;
+ flex-direction: column;
+ height: calc(100vh - 330px);
+ min-height: 300px;
+}
+#app .table-area {
+ flex: 1 1 auto;
+ min-height: 0;
+ overflow: hidden;
+}
+#app .table-area .el-table {
+ width: 100%;
+ height: 100%;
+}
+#app .table-wrap .el-pagination {
+ flex: none;
+ margin-top: 8px;
+}
#app .table-area:fullscreen {
padding: 20px;
background: #fff;
@@ -211,6 +246,7 @@
overflow: auto;
display: flex;
flex-direction: column;
+ height: 100vh;
}
#app .table-wrap:fullscreen .table-area {
flex: 1 1 auto;
diff --git a/traffic-audit-web/src/views/ReportExport.vue b/traffic-audit-web/src/views/ReportExport.vue
index a3ad3c3..3bac892 100644
--- a/traffic-audit-web/src/views/ReportExport.vue
+++ b/traffic-audit-web/src/views/ReportExport.vue
@@ -171,6 +171,11 @@
noteDraft: '',
modules: [
{
+ key: 'summary', title: '姹囨�诲ぇ琛�', items: [
+ { key: 'summaryWorkbook', label: '閬撹矾杩愯緭閲忔眹鎬昏〃锛堟暣鏈級', fileName: '鐢熸垚_閬撹矾杩愯緭閲忔眹鎬昏〃.xlsx', status: null, statusNote: '' }
+ ], checked: []
+ },
+ {
key: 'freight', title: '璐ц繍鎶ヨ〃', items: [
{ key: 'cityDetail', label: '璐ц繍閲忓垎甯傚窞鏄庣粏', fileName: '鐢熸垚_璐ц繍閲忓垎甯傚窞鏄庣粏.xlsx', status: null, statusNote: '' },
{ key: 'freightRank', label: '璐ц繍閲忔帓鍚�', fileName: '鐢熸垚_璐ц繍閲忔帓鍚�.xlsx', status: null, statusNote: '' },
@@ -185,15 +190,14 @@
{ key: 'passengerMidAnalysis', label: '涓彛寰勫垎鏋�', fileName: '鐢熸垚_鍏矾鏃呭涓彛寰勫垎鏋�.xlsx', status: null, statusNote: '' }
], checked: []
}, {
- key: 'cityPassenger', title: '鍩庡競瀹㈣繍鎶ヨ〃', tag: '鍏氦/鍑虹/杞ㄩ亾杞浮/姹囨��', tagType: 'success', items: [
+ key: 'cityPassenger', title: '鍩庡競瀹㈣繍鎶ヨ〃', items: [
{ key: 'cityBusDetail', label: '鍩庡競鍏氦瀹㈣繍閲忓垎甯傚窞鏄庣粏', fileName: '鐢熸垚_鍩庡競鍏氦瀹㈣繍閲忓垎甯傚窞鏄庣粏.xlsx', status: null, statusNote: '' },
{ key: 'cityTaxiDetail', label: '宸℃父鍑虹瀹㈣繍閲忓垎甯傚窞鏄庣粏', fileName: '鐢熸垚_宸℃父鍑虹瀹㈣繍閲忓垎甯傚窞鏄庣粏.xlsx', status: null, statusNote: '' },
{ key: 'cityRailFerryDetail', label: '杞ㄩ亾杞浮瀹㈣繍閲忓垎甯傚窞鏄庣粏', fileName: '鐢熸垚_杞ㄩ亾杞浮瀹㈣繍閲忓垎甯傚窞鏄庣粏.xlsx', status: null, statusNote: '' },
{ key: 'cityPassengerCitySum', label: '鍩庡競瀹㈣繍瀹㈣繍閲忓垎甯傚窞绱', fileName: '鐢熸垚_鍩庡競瀹㈣繍瀹㈣繍閲忓垎甯傚窞绱.xlsx', status: null, statusNote: '' },
{ key: 'cityPassengerDetailSum', label: '鍩庡競瀹㈣繍鍚勫競宸炴槑缁嗚〃', fileName: '鐢熸垚_鍩庡競瀹㈣繍鍚勫競宸炴槑缁嗚〃.xlsx', status: null, statusNote: '' },
{ key: 'cityPassengerSummary', label: '鍩庡競瀹㈣繍姹囨��', fileName: '鐢熸垚_鍩庡競瀹㈣繍姹囨��.xlsx', status: null, statusNote: '' },
- { key: 'wycSplit', label: '缃戠害杞﹀杩愰噺鎷嗗垎琛�', fileName: '鐢熸垚_缃戠害杞﹀杩愰噺鎷嗗垎琛�.xlsx', status: null, statusNote: '' },
- { key: 'summaryWorkbook', label: '閬撹矾杩愯緭閲忔眹鎬昏〃锛堟暣鏈級', fileName: '鐢熸垚_閬撹矾杩愯緭閲忔眹鎬昏〃.xlsx', status: null, statusNote: '' }
+ { key: 'wycSplit', label: '缃戠害杞﹀杩愰噺鎷嗗垎琛�', fileName: '鐢熸垚_缃戠害杞﹀杩愰噺鎷嗗垎琛�.xlsx', status: null, statusNote: '' }
], checked: []
},
{
@@ -238,7 +242,7 @@
// 鎶ヨ〃鏈熶笅鎷夊垎缁勶細骞存姤鎸夊勾浠斤紱鏈堟姤/瀛f姤鎸夊勾鍒嗙粍鍒� 1-12 鏈堬紙鑳借�楀彧鍒楀搴︽湯鏈堬級
periodGroups() {
const year = new Date().getFullYear()
- const years = [year - 1, year, year + 1]
+ const years = [year, year - 1, year + 1]
if (this.cycle === 'year') {
return [{ label: '閫夋嫨骞翠唤', options: years.map(y => ({ label: y + '骞�', value: String(y) })) }]
}
--
Gitblit v1.9.1