From f0597c28b7d722301f2177e3ef46d2ce6e95b102 Mon Sep 17 00:00:00 2001
From: xyc <jc_xiong@hotmail.com>
Date: 星期一, 31 八月 2026 09:15:07 +0800
Subject: [PATCH] docs: 崩溃根因实锤更新——el-tabs 布局无限循环(684da41),sessionStorage 强制登录完成(c62a61c),4 个菜单问题全部闭环

---
 traffic-audit-web/src/views/DataImport.vue |   61 +++++++++++++++++++++---------
 1 files changed, 42 insertions(+), 19 deletions(-)

diff --git a/traffic-audit-web/src/views/DataImport.vue b/traffic-audit-web/src/views/DataImport.vue
index f311c07..f4434b0 100644
--- a/traffic-audit-web/src/views/DataImport.vue
+++ b/traffic-audit-web/src/views/DataImport.vue
@@ -1,6 +1,6 @@
 <template>
-  <el-container>
-    <el-header>浜ら�氱粺璁℃姤琛ㄥ鏍哥郴缁� - 鏁版嵁瀵煎叆</el-header>
+  <el-container direction="vertical">
+    <app-header title="浜ら�氱粺璁℃姤琛ㄥ鏍哥郴缁� - 鏁版嵁瀵煎叆"></app-header>
     <el-container>
       <el-aside width="200px">
         <el-menu router default-active="/import">
@@ -12,7 +12,6 @@
           <el-menu-item index="/report">鎶ヨ〃鐢熸垚</el-menu-item>
           <el-menu-item index="/rules">瑙勫垯绠$悊</el-menu-item>
           <el-menu-item index="/users">鐢ㄦ埛绠$悊</el-menu-item>
-          <el-menu-item index="/login" @click="logout">閫�鍑虹櫥褰�</el-menu-item>
 </el-menu>
       </el-aside>
       <el-main>
@@ -27,7 +26,7 @@
 
           <el-card shadow="hover" class="import-card" style="margin-bottom:15px">
             <div class="card-head">鏈湀瀵煎叆杩涘害锛坽{ period || '鏈�夋嫨鎶ヨ〃鏈�' }}锛�
-              <el-button type="text" icon="el-icon-refresh" style="float:right" @click="loadOverview">鍒锋柊</el-button>
+              <el-button type="text" icon="el-icon-refresh" style="float:right" @click="loadData">鍒锋柊</el-button>
             </div>
             <div v-if="!period" class="tip">璇峰厛鍦ㄤ笂鏂归�夋嫨鎶ヨ〃鏈�</div>
             <div v-else class="overview-grid">
@@ -44,8 +43,12 @@
             <div class="card-head">閫夋嫨绫诲瀷骞舵寕杞芥枃浠�
               <span class="tip" style="float:right;line-height:24px">鍚勬ā鍧椾簰涓嶅奖鍝嶏細鍏堥�夌被鍨嬨�佹寕杞芥枃浠讹紝鍙�岀珛鍗冲鍏ャ�嶆垨銆屽姞鍏ラ槦鍒椼�嶇粺涓�鎵ц锛涗篃鍙湪涓嬫柟绮樿创鐩綍璺緞鐐广�屽鍏ヨ鐩綍銆嶏紝鏂囦欢澶归噷澶氫釜鏈堢殑 Excel 浼氭寜鏂囦欢鍚嶈嚜鍔ㄨ瘑鍒湀浠姐�佸垎鍒鍏ュ搴旀姤琛ㄦ湡</span>
             </div>
-            <el-tabs v-model="activeModule" class="module-tabs">
-              <el-tab-pane v-for="g in groups" :key="g.key" :label="g.name" :name="g.key">
+            <div class="module-tabs-head">
+                <el-radio-group v-model="activeModule" size="small">
+                  <el-radio-button v-for="g in groups" :key="g.key" :label="g.key">{{ g.name }}</el-radio-button>
+                </el-radio-group>
+              </div>
+              <div v-for="g in groups" :key="g.key" v-show="activeModule === g.key" class="module-tab-pane">
                 <div class="module-sel">
                   <el-select v-model="moduleSel[g.key]" placeholder="閫夋嫨瀵煎叆绫诲瀷" style="width:260px"
                              @change="onModuleChange(g.key)" clearable>
@@ -89,8 +92,7 @@
                     </div>
                   </div>
                 </div>
-              </el-tab-pane>
-            </el-tabs>
+              </div>
             <div v-if="importType" class="type-info">
               <div>妯℃澘锛歿{ templateName }}
                 <el-link v-if="templateUrl" type="primary" icon="el-icon-download" :underline="false"
@@ -159,6 +161,8 @@
               <div class="tip">鍗曞嚮鏂囦欢澶硅繘鍏ュ瓙鏂囦欢澶癸紱<b>鍙屽嚮鐩爣鏂囦欢澶圭珛鍗冲鍏�</b>鍏朵腑鍏ㄩ儴 Excel锛涗篃鍙繘鍏ュ悗鐐逛笅鏂规寜閽�傚鍏ユ椂浼氭寜鏂囦欢鍚嶈嚜鍔ㄨ瘑鍒湀浠姐��</div>
               <div v-if="dirExcelCount === 0" class="tip">褰撳墠鏂囦欢澶瑰唴娌℃湁 Excel 鏂囦欢锛�.xlsx/.xls锛�</div>
               <div v-else class="tip">褰撳墠鏂囦欢澶瑰唴 Excel锛歿{ dirExcelCount }} 涓� 鈥斺�� {{ dirFiles.slice(0, 6).join('銆�') }}{{ dirFiles.length > 6 ? ' 绛�' : '' }}锛堜粎瀵煎叆鐩存帴浣嶄簬璇ユ枃浠跺す鐨勬枃浠讹級</div>
+              <div v-if="dirDirsTruncated" class="tip">瀛愭枃浠跺す杩囧锛屼粎鏄剧ず鍓� 300 涓�</div>
+              <div v-if="dirFilesTruncated" class="tip">Excel 鏂囦欢杩囧锛堝叡 {{ dirExcelCount }} 涓級锛屼粎鏄剧ず鍓� 300 涓�</div>
             </div>
             <span slot="footer">
               <el-button size="small" @click="dirDialog = false">鍙栨秷</el-button>
@@ -169,7 +173,7 @@
           <el-card shadow="never" style="margin-top:15px" class="batch-card">
             <div slot="header" class="card-head">
               瀵煎叆璁板綍锛坽{ period || '鍏ㄩ儴鎶ヨ〃鏈�' }}锛�
-              <el-button type="text" icon="el-icon-refresh" style="float:right" @click="loadBatches">鍒锋柊</el-button>
+              <el-button type="text" icon="el-icon-refresh" style="float:right" @click="loadData">鍒锋柊</el-button>
             </div>
             <el-table :data="batches" border size="small" v-loading="batchLoading" style="width:100%">
               <el-table-column prop="importType" label="瀵煎叆绫诲瀷" width="150">
@@ -206,6 +210,7 @@
   </el-container>
 </template>
 <script>
+import AppHeader from '@/components/AppHeader.vue'
 import api from '@/api'
 const TYPE_LABELS = {
   h2032: 'H203-2鏈堟姤', transportAuth: '杩愭斂杞﹁締', trackMileage: '杞ㄨ抗閲岀▼', scaleSplit: '瑙勪笂瑙勪笅鎷嗗垎',
@@ -229,6 +234,7 @@
   INVEST_SYSTEM: 'investmentSystem'
 }
 export default {
+  components: { AppHeader },
   name: 'DataImport',
   data() {
     return {
@@ -242,7 +248,9 @@
       dirCurrent: '',
       dirParent: '',
       dirDirs: [],
+      dirDirsTruncated: false,
       dirExcelCount: 0,
+      dirFilesTruncated: false,
       dirFiles: [],
       dirLoading: false,
       dirImporting: false,
@@ -389,7 +397,7 @@
       this.importType = this.moduleSel[key] || ''
       this.dirPath = (this.importType && localStorage.getItem('dirLast_' + this.importType)) || ''
     },
-    onPeriodChange() { this.loadOverview(); this.loadBatches() },
+    onPeriodChange() { this.loadData() },
     endpoint(t) {
       const map = {
         h2032: '/import/h2032',
@@ -427,10 +435,12 @@
           this.dirCurrent = d.current || ''
           this.dirParent = d.parent || ''
           this.dirDirs = d.dirs || []
+          this.dirDirsTruncated = !!d.dirsTruncated
           this.dirExcelCount = d.excelCount || 0
           this.dirFiles = d.files || []
+          this.dirFilesTruncated = !!d.filesTruncated
         })
-        .catch(e => { this.$message.error((e.response && e.response.data && e.response.data.message) || '鐩綍鍔犺浇澶辫触') })
+        .catch(e => { if (e && e._toast) return; this.$message.error((e.response && e.response.data && e.response.data.message) || '鐩綍鍔犺浇澶辫触') })
         .finally(() => { this.dirLoading = false })
     },
     goDirParent() { if (this.dirParent) this.loadDirs(this.dirParent) },
@@ -457,6 +467,11 @@
           const d = (res && res.data) || {}
           const files = (d.files || []).filter(n => /\.(xlsx|xls)$/i.test(n))
           if (!files.length) { this.$message.warning('璇ョ洰褰曟病鏈� Excel 鏂囦欢锛�.xlsx/.xls锛夛細' + dir); this.dirImporting = false; return }
+          if (files.length > 60) {
+            this.dirImporting = false
+            this.$message.warning('鐩綍鍐� Excel 鏂囦欢杩囧锛�' + files.length + ' 涓級锛屼负閬垮厤娴忚鍣ㄥ崱椤胯鍒嗘壒瀵煎叆锛堟瘡鎵逛笉瓒呰繃 60 涓級')
+            return
+          }
           localStorage.setItem('dirLast_' + type, dir)
           this.dirPath = dir
           this.dirImportFiles = files.map(n => ({ name: n, status: 'pending', period: '', msg: '' }))
@@ -493,6 +508,7 @@
         })
         .catch(e => {
           this.dirImporting = false
+          if (e && e._toast) return
           this.$message.error((e.response && e.response.data && e.response.data.message) || '鐩綍涓嶅瓨鍦ㄦ垨鏃犳硶璁块棶锛�' + dir)
         })
     },
@@ -573,6 +589,7 @@
           this.afterImport()
         })
         .catch(e => {
+          if (e && e._toast) return
           this.$message.error((e.response && e.response.data && e.response.data.message) || '鎵归噺瀵煎叆澶辫触')
         })
         .finally(() => { this.cityDirLoading = false })
@@ -643,13 +660,17 @@
         run(0)
       })
     },
-    afterImport() { this.loadOverview(); this.loadBatches() },
-    loadOverview() {
-      if (!this.period) return
-      api.get('/import/batches', { params: { period: this.period, limit: 200 } })
+    afterImport() { this.loadData() },
+    loadData() {
+      if (this.batchLoading) return
+      this.batchLoading = true
+      const params = { limit: 200 }
+      if (this.period) params.period = this.period
+      api.get('/import/batches', { params })
         .then(res => {
-          const map = {}
           const records = (res.data && res.data.records) || []
+          this.batches = records.slice(0, 50)
+          const map = {}
           records.forEach(r => {
             const key = this.batchKeyToType(r.importType)
             if (!key) return
@@ -660,7 +681,8 @@
           })
           this.overview = map
         })
-        .catch(() => {})
+        .catch(e => { if (!e || !e._toast) this.$message.error('瀵煎叆璁板綍鍔犺浇澶辫触锛岃鍒锋柊閲嶈瘯') })
+        .finally(() => { this.batchLoading = false })
     },
     batchKeyToType(k) {
       if (BATCH_TYPE_MAP[k]) return BATCH_TYPE_MAP[k]
@@ -712,8 +734,7 @@
     }
   },
   mounted() {
-    this.loadBatches()
-    this.loadOverview()
+    this.loadData()
   }
 }
 </script>
@@ -757,4 +778,6 @@
 .dir-empty { padding: 14px; font-size: 12px; color: #909399; text-align: center; }
 .dir-files { margin-top: 8px; }
 
+.module-tabs-head { margin-bottom: 10px; }
+.module-tab-pane { min-height: 120px; }
 </style>

--
Gitblit v1.9.1