| docs/功能测试报告/功能测试报告_汇总大表进度弹窗优化_2026-09-22.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| docs/工作日结/工作日结_2026-09-22.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
| traffic-audit-web/src/views/ReportExport.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_»ã×Ü´ó±í½ø¶Èµ¯´°ÓÅ»¯_2026-09-22.md
New file @@ -0,0 +1,54 @@ # åè½æµè¯æ¥å_æ±æ»å¤§è¡¨è¿åº¦å¼¹çªä¼å_2026-09-22 ## ä¸ãåè½è¯´æ ç¨æ·é®é¢ï¼ãæ±æ»è¡¨çè¿åº¦æ¡å¼¹çªçãä¿åãä¼ä½¿ä¸è½½çæ±æ»è¡¨å次ä¸è½½ï¼è¿ä¸ªå¼¹çªå¯ä»¥æä¹ä¼åä¸ä¸å¢ï¼ã **åå **ï¼ä»»å¡å®ææ¶ `downloadTaskFile(true)` ä¼èªå¨ä¸è½½ä¸æ¬¡ï¼èå¼¹çªåºé¨ä¸ç´æçãä¿åæä»¶ãï¼ç¼åå½ä¸æ¶æ¯ãä¸è½½ãï¼ï¼ç¹ä¸ä¸ä¼**忬¡è¯·æ±å端æ¿åä¸ä¸ªæä»¶å¹¶ç¬¬äºæ¬¡ä¸è½½**ï¼çèµ·æ¥åãä¿ååä¸äºä¸éããåæ¶å¼¹çªæ é¢å§ç»æ¯ãæ£å¨çææ±æ»å¤§è¡¨ãï¼å®æ/失败åä¸ååã **æ¹å¨**ï¼`traffic-audit-web/src/views/ReportExport.vue`ï¼ï¼ | # | æ¹å¨ | 说æ | | --- | --- | --- | | 1 | å®æåæ¾ç¤ºãå·²èªå¨ä¸è½½ã | `å·²èªå¨ä¸è½½ï¼<æä»¶å>ï¼<大å°>ï¼` + æç¤ºãæµè§å¨æ²¡å¼¹åºä¸è½½æ¶å¯ç¹ã忬¡ä¸è½½ãââç¨æ¬å°ç¼åä¿åï¼ä¸ä¼éæ°è¯·æ±æå¡å¨ã | | 2 | æé®ææ¡éç¶æåå | å·²ä¸è½½ â **忬¡ä¸è½½**ï¼æªä¸è½½ï¼ç¼åå½ä¸åºæ¯ï¼â ä¸è½½ï¼çæä¸ â ä¿åæä»¶ï¼ç¦ç¨ï¼ | | 3 | 忬¡ä¸è½½èµ°**å åç¼å** | 馿¬¡ä¸è½½åæ Blob åè¿ `taskBlob`ï¼å次ç¹å»ç´æ¥æ¬å°å¦åï¼æç¤ºã已仿¬å°ç¼åä¿åãï¼ï¼**ä¸å请æ±å端** | | 4 | å¼¹çªæ é¢éç¶æåå | æ£å¨çææ±æ»å¤§è¡¨ / **æ±æ»å¤§è¡¨å·²çæ** / æ±æ»å¤§è¡¨çæå¤±è´¥ | | 5 | 宿æä¸»æé®æ¹ä¸ºãå ³éã | çæä¸ä»æ¯ãåå°è¿è¡ãï¼å®æå主æé®æ¯ãå ³éãï¼ä¸è½½æé®é为次è¦ï¼ | | 6 | æ¯æ¬¡æ°ä»»å¡éç½®ç¶æ | `taskDownloaded/taskFileName/taskFileSize/taskBlob` å¨ `startSummaryTask` 鿏 é¶ | ## äºãæµè¯ç¯å¢ - å端ï¼`npm run serve`ï¼8080ï¼ï¼æ¹åçç¼è¯ `Compiled successfully in 592ms`ï¼10:00:24ï¼ - å端ï¼Spring Boot 8090ï¼ä»æ¥è¿è¡ä¸ï¼ï¼æ°æ®åº MySQL 3308 / `traffic_audit` - æµè§å¨ï¼Codex å ç½®æµè§å¨ï¼è§å£ 1280Ã720ï¼ï¼ç»å½ `admin/123456` - æ¥è¡¨æï¼2026-08ï¼ææ¥ï¼æ±æ»å¤§è¡¨ãéè·¯è¿è¾éæ±æ»è¡¨ï¼æ´æ¬ï¼ãæ°æ®ç¶æ=æ°æ®å°±ç»ªï¼ - çæèæ¶ï¼**13.5 ç§**ï¼æªå½ä¸ç¼åï¼ï¼äº§ç© `çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsx`ï¼**1.15 MB** ## ä¸ãç¨ä¾è¡¨ | # | ç¨ä¾ | è¾å ¥/æä½ | 颿 | å®é | ç»è®º | | --- | --- | --- | --- | --- | --- | | T01 | çæä¸å¼¹çªç¶æï¼æ£åï¼ | é 2026-08 â ç¹ã导åºã | æ é¢ãæ£å¨çææ±æ»å¤§è¡¨ãï¼è¿åº¦éå¢ï¼æé®ãä¿åæä»¶(ç¦ç¨)/éæ°çæ(ç¦ç¨)/åå°è¿è¡ã | æ 颿£ç¡®ï¼è¿åº¦ 6%â45%ï¼æ¥éª¤æåãè¯»åæ¯çå·¥ä½ç°¿ãâãå·æ°æå页ä¸è·¨é¡µåæé¡µãï¼æé®ç¶æä¸é¢æä¸è´ | éè¿ | | T02 | 宿åèªå¨ä¸è½½ + æç¤ºï¼æ£åï¼ | çå¾ ä»»å¡ç»æ | æ é¢åãæ±æ»å¤§è¡¨å·²çæãï¼æ¾ç¤ºãå·²èªå¨ä¸è½½ï¼æä»¶åï¼å¤§å°ï¼ãï¼æé®åã忬¡ä¸è½½/éæ°çæ/å ³éã | è¿åº¦ 100%ãã宿ããå·²ç¨ 13.5 ç§ï¼æç¤ºãå·²èªå¨ä¸è½½ï¼çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsx ï¼1.15 MBï¼ãï¼æé®å·²åæ´ | éè¿ | | T03 | 忬¡ä¸è½½èµ°æ¬å°ç¼åï¼æ£åï¼æ ¸å¿ï¼ | ç¹ã忬¡ä¸è½½ã | æç¤ºèµ°ç¼åãä¸**ä¸å请æ±å端** | æç¤ºã已仿¬å°ç¼åä¿åï¼çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsxãï¼æªåºç°ãæ¥è¡¨å¯¼åºæåãï¼è¯¥ææ¡åªå¨èµ°å端æ¥å£æ¶åºç°ï¼â èµ°çæ¯ç¼å忝 | éè¿ | | T04 | å ³éæé®ï¼æ£åï¼ | ç¹ãå ³éã | å¼¹çªæ¶å¤±ãå表页å¯ç»§ç»æä½ | å¼¹çªå®¹å¨ä»å¯è®¿é®æ§æ ä¸ç§»é¤ï¼å表æ£å¸¸ | éè¿ | | T05 | æ§å¶å°æ æ¥éï¼åå½ï¼ | 读å dev logsï¼error/warnï¼ | æ æ°å¢é误 | 0 æ¡ | éè¿ | | T06 | å ¶å®æ¥è¡¨å¯¼åºè·¯å¾æªåå½±åï¼åå½ï¼éæï¼ | ââ | åå¼ /æ¹é导åºä»èµ°å `downloadBlob` | æ¬æ¬¡åªæ¹æ±æ»å¤§è¡¨å¼æ¥ä»»å¡åæ¯ï¼`exportChecked` ä¸å ¶å®åæ¯æªå¨ | éè¿ï¼éæï¼ | ## åãåç°çé®é¢ä¸å¤ç½® | # | é®é¢ | å¤ç½® | | --- | --- | --- | | P1 | å¼¹çªæ é¢ä¸æé®ææ¡åçå®ç¶æä¸ç¬¦ï¼å·²å®æä»åãæ£å¨çæãï¼å·²èªå¨ä¸è½½ä»åãä¿åæä»¶ãï¼ | å·²ä¿®ï¼æ é¢éç¶æãæé®ææ¡éä¸è½½ç¶æï¼ | | P2 | åä¸ä»½æä»¶è¢«éå¤è¯·æ±å端ï¼1.15 MB à 次æ°ï¼ | 已修ï¼å å Blob ç¼åï¼éå¤ä¿å 0 请æ±ï¼ | | P3 | éªè¯æ¹æ³è®°å½ï¼Element UI æä»½éæ©æ¡æ¯ **readonly** è¾å ¥æ¡ï¼èªå¨åä¸è½ç¨ fill/typeï¼å¿ é¡»å ç¹å¼å¼¹å±åéæä»½ï¼`setValue` 对该æ§ä»¶æ æ | ä» è®°å½ä¸ºæµè¯æ¹æ³å¤æ³¨ï¼éç³»ç»ç¼ºé· | ## äºãç»è®º - å¼¹çªç°å¨è½æç¡®åè¯ç¨æ·ãå·²èªå¨ä¸è½½äºä»ä¹æä»¶ãå¤å¤§ãï¼æé®è¯ä¹ä¸è¡ä¸ºä¸è´ï¼ã忬¡ä¸è½½ã= ååä¸ä»½ï¼èµ°æ¬å°ç¼åï¼ï¼ - éå¤ä¸è½½ä¸åéå¤è¯·æ±å端ï¼ä½éªä¸å¸¦å®½é½æ¹åï¼ - çæä¸/已宿/失败ä¸ç§ç¶æå¨æ é¢ãè¿åº¦ãæé®ä¸é½æåºåï¼ - æµè§å¨ç«¯å®æµ 6 æ¡ç¨ä¾éè¿ï¼æ æ§å¶å°æ¥éã æµè¯äººï¼Codexï¼AIï¼ãæµè¯æ¥æï¼2026-09-22 docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-22.md
@@ -24,9 +24,21 @@ ç¨æ·å¨å«å¤çå°"æ±æ»"æé®ï¼å®é æ ¸æ¥ï¼å端 `DataView.vue` å ¨ææ "æ±æ»/导åº"ï¼`ReportExport.vue` ææï¼ï¼åç«¯åªæ `/api/data/list`ï¼å ¨ä» + `traffic-audit-web/dist` + é¨ç½² jar + gitea è¿ç«¯ `main` åæ ç¸å ³ä»£ç ãå·²åç¨æ·è¯´æï¼æ"å°æªå®ç°ãç±æ¬ä»å®ç°"æ¨è¿ã ### 4. æ±æ»å¤§è¡¨è¿åº¦å¼¹çªä¼åï¼ç¨æ·ï¼"ä¿å"ä¼å¯¼è´åä¸è½½ä¸æ¬¡ï¼ - **æ ¹å **ï¼ä»»å¡å®ææ¶ä¼èªå¨ä¸è½½ä¸æ¬¡ï¼ä½å¼¹çªåºé¨ä»æçãä¿åæä»¶ãæé®ï¼ç¹å®ä¼å次请æ±å端æ¿åä¸ä»½æä»¶å¹¶ç¬¬äºæ¬¡ä¸è½½ï¼åæ¶æ é¢/æé®ææ¡ä¸éç¶æååã - **æ¹å¨**ï¼`traffic-audit-web/src/views/ReportExport.vue`ï¼ï¼ 1. å®æåæ¾ç¤ºãå·²èªå¨ä¸è½½ï¼<æä»¶å>ï¼<大å°>ï¼ã+ æç¤ºå¯ç¹ã忬¡ä¸è½½ãï¼æ¬å°ç¼åï¼ä¸åè¯·æ±æå¡å¨ï¼ï¼ 2. æé®ææ¡éç¶æï¼å次ä¸è½½ / ä¸è½½ / ä¿åæä»¶ï¼çæä¸ç¦ç¨ï¼ï¼ 3. 馿¬¡ä¸è½½åæ Blob åå åï¼éå¤ä¿å **0 请æ±**ï¼ 4. å¼¹çªæ é¢éç¶æï¼æ£å¨çæ / **å·²çæ** / çæå¤±è´¥ï¼å®ææä¸»æé®æ¹ä¸ºãå ³éãï¼ 5. æ¯æ¬¡æ°ä»»å¡éç½® `taskDownloaded/taskFileName/taskFileSize/taskBlob`ã - **æµè§å¨å®æµ**ï¼admin/123456ï¼2026-08ï¼ï¼çæ 13.5 ç§ãäº§ç© 1.15 MBï¼å®æåæ é¢ãæ±æ»å¤§è¡¨å·²çæããæç¤ºãå·²èªå¨ä¸è½½ï¼çæ_éè·¯è¿è¾éæ±æ»è¡¨_2026-08.xlsx ï¼1.15 MBï¼ããç¹ã忬¡ä¸è½½ãæç¤ºã已仿¬å°ç¼åä¿åãï¼æ§å¶å° 0 æ¥éã ## äºãæµè¯ç»ææè¦ - æ¥åï¼`docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æ°æ®æ¥çè¡¥é½ç½çº¦è½¦ä¸ä¸ªä½å®¢è¿ç±»å_2026-09-22.md` - æ¥åï¼`docs/åè½æµè¯æ¥å/åè½æµè¯æ¥å_æ±æ»å¤§è¡¨è¿åº¦å¼¹çªä¼å_2026-09-22.md`ï¼6 æ¡ç¨ä¾éè¿ï¼çæä¸ç¶æ / 宿æç¤º / 忬¡ä¸è½½èµ°ç¼å / å ³é / æ æ§å¶å°æ¥é / å ¶å®å¯¼åºæªåå½±åï¼ - ç¯å¢ï¼å端 `mvn spring-boot:run`ï¼8090ï¼`Started TrafficAuditApplication`ï¼ï¼å端 `npm run serve`ï¼8080ï¼`Compiled successfully in 4769ms`ï¼ï¼MySQL `localhost:3308/traffic_audit`ï¼ç»å½ admin/123456 å JWTã - ç»æï¼3 个æ°ç±»åæ£åï¼å«æé´/å ³é®åçéï¼ãè´åï¼æªç¥ç±»åãæ æ°æ®æãæ tokenï¼å ¨é¨éè¿ï¼å ¥åºæ½æ¥æ¡æ°ä¸åºå ä¸è´ï¼20 / 20 / 139ï¼ï¼åæ 15 ç±»å彿£å¸¸ã traffic-audit-web/src/views/ReportExport.vue
@@ -162,7 +162,7 @@ </el-dialog> <!-- æ±æ»å¤§è¡¨å¼æ¥çæè¿åº¦ï¼çæä¸æ¬¡çº¦ 10~20 ç§ï¼é¿å ç¹å»åé¿æ¶é´æ ååºï¼ --> <el-dialog title="æ£å¨çææ±æ»å¤§è¡¨" :visible.sync="taskVisible" width="460px" <el-dialog :title="taskDialogTitle" :visible.sync="taskVisible" width="460px" :close-on-click-modal="false" :show-close="taskFinished"> <div class="task-body"> <el-progress :percentage="taskInfo.percent || 0" :status="taskInfo.status === 'FAILED' ? 'exception' : (taskDone ? 'success' : null)" @@ -170,13 +170,17 @@ <p class="task-step">{{ taskInfo.step || 'æéä¸' }}</p> <p class="task-meta" v-if="taskInfo.period">æ¥è¡¨æ {{ taskInfo.period }}ã{{ taskInfo.fromCache ? '䏿¬¡çæç¨æ¶' : 'å·²ç¨' }} {{ (taskInfo.elapsedMs / 1000).toFixed(1) }} ç§</p> <p class="task-meta" v-if="taskInfo.fromCache">æ¬æ¬¡ç´æ¥ä½¿ç¨ {{ taskCacheTime }} çæçç»æï¼10 åéå 䏿鴿²¡ææ°å¯¼å ¥æ°æ®ï¼ãå¦éæææ°æ°æ®éç®ï¼è¯·ç¹ãéæ°çæãã</p> <p class="task-done" v-if="taskDownloaded"> å·²èªå¨ä¸è½½ï¼<b>{{ taskFileName }}</b><span v-if="taskFileSize">ï¼{{ taskFileSizeText }}ï¼</span><br> æµè§å¨æ²¡å¼¹åºä¸è½½æ¶å¯ç¹ã忬¡ä¸è½½ãââç¨æ¬å°ç¼åä¿åï¼ä¸ä¼éæ°è¯·æ±æå¡å¨ã </p> <p class="task-error" v-if="taskInfo.status === 'FAILED'">{{ taskInfo.error }}</p> </div> <span slot="footer"> <el-button size="small" type="primary" :disabled="!taskDone" @click="downloadTaskFile">{{ taskInfo.fromCache ? 'ä¸è½½' : 'ä¿åæä»¶' }}</el-button> <el-button size="small" :disabled="!taskDone" @click="downloadTaskFile()">{{ taskDownloaded ? '忬¡ä¸è½½' : (taskInfo.fromCache ? 'ä¸è½½' : 'ä¿åæä»¶') }}</el-button> <el-button size="small" :disabled="taskRunning" @click="restartTask">éæ°çæ</el-button> <el-button size="small" v-if="taskRunning" @click="minimizeTask">åå°è¿è¡</el-button> <el-button size="small" v-else @click="closeTask">å ³é</el-button> <el-button size="small" v-else type="primary" @click="closeTask">å ³é</el-button> </span> </el-dialog> </el-main> @@ -212,6 +216,11 @@ taskVisible: false, taskInfo: {}, taskTimer: null, // è¿åº¦å¼¹çªï¼å®æåä¼èªå¨ä¸è½½ä¸æ¬¡ï¼è¿éè®°å½ãå·²ä¸è½½ãä¸æä»¶ä¿¡æ¯ï¼éå¤ç¹å»èµ°æ¬å°ç¼åï¼ä¸å请æ±åç«¯ï¼ taskDownloaded: false, taskFileName: '', taskFileSize: 0, taskBlob: null, taskKey: 'summaryWorkbook', modules: [ { @@ -320,6 +329,18 @@ const d = new Date(t) const p = (n) => String(n).padStart(2, '0') return d.getFullYear() + '-' + p(d.getMonth() + 1) + '-' + p(d.getDate()) + ' ' + p(d.getHours()) + ':' + p(d.getMinutes()) + ':' + p(d.getSeconds()) }, // å¼¹çªæ é¢éä»»å¡ç¶æååï¼é¿å ã已宿ãè¿åçãæ£å¨çæã taskDialogTitle() { const s = this.taskInfo && this.taskInfo.status if (s === 'FAILED') return 'æ±æ»å¤§è¡¨çæå¤±è´¥' if (s === 'DONE') return 'æ±æ»å¤§è¡¨å·²çæ' return 'æ£å¨çææ±æ»å¤§è¡¨' }, taskFileSizeText() { const n = this.taskFileSize || 0 if (!n) return '' return n >= 1048576 ? (n / 1048576).toFixed(2) + ' MB' : Math.round(n / 1024) + ' KB' } }, watch: { @@ -524,6 +545,10 @@ this.stopTaskPolling() this.taskInfo = { status: 'PENDING', percent: 0, step: 'æäº¤ä»»å¡', period: this.period, elapsedMs: 0 } this.taskVisible = true this.taskDownloaded = false this.taskFileName = '' this.taskFileSize = 0 this.taskBlob = null this.loading = 'gen-' + this.curModule.key const params = Object.assign({}, this.buildParams(), { refresh: refresh ? 'true' : 'false' }) api.get('/report/exportTask/summaryWorkbook', { params, timeout: 60000 }) @@ -536,7 +561,7 @@ return } this.taskInfo = res.data if (this.taskInfo.status === 'DONE') { this.loading = ''; this.downloadTaskFile(); return } if (this.taskInfo.status === 'DONE') { this.loading = ''; this.downloadTaskFile(true); return } if (this.taskInfo.status === 'FAILED') { this.loading = ''; return } this.pollTask() }) @@ -568,7 +593,7 @@ if (this.taskInfo.status === 'DONE') { this.stopTaskPolling() this.loading = '' this.downloadTaskFile() this.downloadTaskFile(true) } else if (this.taskInfo.status === 'FAILED') { this.stopTaskPolling() this.loading = '' @@ -581,12 +606,26 @@ stopTaskPolling() { if (this.taskTimer) { clearInterval(this.taskTimer); this.taskTimer = null } }, downloadTaskFile() { // auto=true 表示ãä»»å¡å®æåçèªå¨ä¸è½½ãï¼ç¨æ·ç¹æé®æ¶ä¸º false downloadTaskFile(auto) { const id = this.taskInfo && this.taskInfo.taskId if (!id) return const name = this.taskInfo.fileName || ('çæ_éè·¯è¿è¾éæ±æ»è¡¨_' + this.period + '.xlsx') this.taskFileName = name // å·²ç»ä¸è½½è¿ï¼ç´æ¥ç¨å åéç Blob åå䏿¬¡ï¼ä¸å请æ±å端ï¼é¿å åä¸ä»½æä»¶é夿å 1MB+ï¼ if (this.taskBlob) { this.downloadBlob(this.taskBlob, name) this.$message.success('已仿¬å°ç¼åä¿åï¼' + name) return } api.get('/report/exportTask/' + id + '/file', { responseType: 'blob', timeout: 120000 }) .then(res => { this.downloadBlob(res, name); this.$message.success('æ¥è¡¨å¯¼åºæå') }) .then(res => { this.taskBlob = res this.taskFileSize = (res && res.size) || 0 this.taskDownloaded = true this.downloadBlob(res, name) this.$message.success(auto ? 'çæå®æï¼å·²èªå¨ä¸è½½' : 'æ¥è¡¨å¯¼åºæå') }) .catch(err => this.failWith(err)) }, restartTask() { this.startSummaryTask(true) }, @@ -756,6 +795,7 @@ .task-step { margin: 12px 0 4px; font-size: 14px; color:#303133; } .task-meta { margin: 2px 0; font-size: 12px; color:#909399; line-height: 1.6; } .task-error { margin: 8px 0 0; font-size: 13px; color:#F56C6C; word-break: break-all; } .task-done { margin: 8px 0 0; font-size: 13px; color:#67C23A; line-height: 1.6; } </style> <style>