zhizhijie
9 天以前 654556a05394481b138b1070d83a22dbf311e94b
fix(报表生成): 已自动下载后不再显示下载按钮(按用户反馈调整)

- 用户反馈「已经下载过了就不需要再次下载」:删除「再次下载」按钮与内存 Blob 缓存

- 完成后弹窗底部只保留「重新生成 / 关闭」;仅当自动下载失败(taskDownloaded=false)时才显示「保存文件」兜底,并提示「自动下载没成功,可点保存文件再存一次」

- 提示语改为「已自动下载:<文件名>(<大小>),文件在浏览器默认下载目录。」

- 浏览器复验(admin/123456, 2026-08, 13.6s):生成中/完成后按钮均符合预期,控制台 0 报错;测试报告补「六、变更记录(v1→v2)」
3个文件已修改
41 ■■■■■ 已修改文件
docs/功能测试报告/功能测试报告_汇总大表进度弹窗优化_2026-09-22.md 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/工作日结/工作日结_2026-09-22.md 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
traffic-audit-web/src/views/ReportExport.vue 17 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
docs/¹¦ÄܲâÊÔ±¨¸æ/¹¦ÄܲâÊÔ±¨¸æ_»ã×Ü´ó±í½ø¶Èµ¯´°ÓÅ»¯_2026-09-22.md
@@ -10,9 +10,9 @@
| # | æ”¹åЍ | è¯´æ˜Ž |
| --- | --- | --- |
| 1 | å®ŒæˆåŽæ˜¾ç¤ºã€Œå·²è‡ªåŠ¨ä¸‹è½½ã€ | `已自动下载:<文件名>(<大小>)` + æç¤ºã€Œæµè§ˆå™¨æ²¡å¼¹å‡ºä¸‹è½½æ—¶å¯ç‚¹ã€Žå†æ¬¡ä¸‹è½½ã€â€”—用本地缓存保存,不会重新请求服务器」 |
| 2 | æŒ‰é’®æ–‡æ¡ˆéšçŠ¶æ€å˜åŒ– | å·²ä¸‹è½½ â†’ **再次下载**;未下载(缓存命中场景)→ ä¸‹è½½ï¼›ç”Ÿæˆä¸­ â†’ ä¿å­˜æ–‡ä»¶ï¼ˆç¦ç”¨ï¼‰ |
| 3 | å†æ¬¡ä¸‹è½½èµ°**内存缓存** | é¦–次下载后把 Blob å­˜è¿› `taskBlob`,再次点击直接本地另存(提示「已从本地缓存保存」),**不再请求后端** |
| 1 | å®ŒæˆåŽæ˜¾ç¤ºã€Œå·²è‡ªåŠ¨ä¸‹è½½ã€ | `已自动下载:<文件名>(<大小>),文件在浏览器默认下载目录。` |
| 2 | **已自动下载后不再显示下载按钮** | å®ŒæˆåŽåº•部只剩「重新生成 / å…³é—­ã€ï¼›åªæœ‰**自动下载失败**时才出现「保存文件」兜底按钮(见 Â§å…­ å˜æ›´è®°å½•) |
| 3 | è‡ªåŠ¨ä¸‹è½½å¤±è´¥å…œåº• | `taskDownloaded=false` æ—¶æç¤ºã€Œè‡ªåŠ¨ä¸‹è½½æ²¡æˆåŠŸï¼Œå¯ç‚¹ã€Žä¿å­˜æ–‡ä»¶ã€å†å­˜ä¸€æ¬¡ã€ï¼Œå¹¶æ˜¾ç¤ºã€Œä¿å­˜æ–‡ä»¶ã€æŒ‰é’® |
| 4 | å¼¹çª—标题随状态变化 | æ­£åœ¨ç”Ÿæˆæ±‡æ€»å¤§è¡¨ / **汇总大表已生成** / æ±‡æ€»å¤§è¡¨ç”Ÿæˆå¤±è´¥ |
| 5 | å®Œæˆæ€ä¸»æŒ‰é’®æ”¹ä¸ºã€Œå…³é—­ã€ | ç”Ÿæˆä¸­ä»æ˜¯ã€ŒåŽå°è¿è¡Œã€ï¼Œå®ŒæˆåŽä¸»æŒ‰é’®æ˜¯ã€Œå…³é—­ã€ï¼ˆä¸‹è½½æŒ‰é’®é™ä¸ºæ¬¡è¦ï¼‰ |
| 6 | æ¯æ¬¡æ–°ä»»åŠ¡é‡ç½®çŠ¶æ€ | `taskDownloaded/taskFileName/taskFileSize/taskBlob` åœ¨ `startSummaryTask` é‡Œæ¸…é›¶ |
@@ -31,8 +31,8 @@
| --- | --- | --- | --- | --- | --- |
| T01 | ç”Ÿæˆä¸­å¼¹çª—状态(正向) | é€‰ 2026-08 â†’ ç‚¹ã€Œå¯¼å‡ºã€ | æ ‡é¢˜ã€Œæ­£åœ¨ç”Ÿæˆæ±‡æ€»å¤§è¡¨ã€ï¼›è¿›åº¦é€’增;按钮「保存文件(禁用)/重新生成(禁用)/后台运行」 | æ ‡é¢˜æ­£ç¡®ï¼›è¿›åº¦ 6%→45%;步骤文字「读取母版工作簿」→「刷新排名页与跨页合成页」;按钮状态与预期一致 | é€šè¿‡ |
| T02 | å®ŒæˆåŽè‡ªåŠ¨ä¸‹è½½ + æç¤ºï¼ˆæ­£å‘) | ç­‰å¾…任务结束 | æ ‡é¢˜å˜ã€Œæ±‡æ€»å¤§è¡¨å·²ç”Ÿæˆã€ï¼›æ˜¾ç¤ºã€Œå·²è‡ªåŠ¨ä¸‹è½½ï¼šæ–‡ä»¶åï¼ˆå¤§å°ï¼‰ã€ï¼›æŒ‰é’®å˜ã€Œå†æ¬¡ä¸‹è½½/重新生成/关闭」 | è¿›åº¦ 100%、「完成」、已用 13.5 ç§’;提示「已自动下载:生成_道路运输量汇总表_2026-08.xlsx ï¼ˆ1.15 MB)」;按钮已变更 | é€šè¿‡ |
| T03 | å†æ¬¡ä¸‹è½½èµ°æœ¬åœ°ç¼“存(正向,核心) | ç‚¹ã€Œå†æ¬¡ä¸‹è½½ã€ | æç¤ºèµ°ç¼“存、且**不再请求后端** | æç¤ºã€Œå·²ä»Žæœ¬åœ°ç¼“存保存:生成_道路运输量汇总表_2026-08.xlsx」,未出现「报表导出成功」(该文案只在走后端接口时出现)→ èµ°çš„æ˜¯ç¼“存分支 | é€šè¿‡ |
| T04 | å…³é—­æŒ‰é’®ï¼ˆæ­£å‘) | ç‚¹ã€Œå…³é—­ã€ | å¼¹çª—消失、列表页可继续操作 | å¼¹çª—容器从可访问性树中移除,列表正常 | é€šè¿‡ |
| T03 | å®ŒæˆåŽ**不再提供下载按钮**(正向,核心) | ä»»åŠ¡å®Œæˆ | åº•部只有「重新生成 / å…³é—­ã€ | åº•部按钮为「重新生成 / å…³é—­ã€ï¼Œæ— ä¸‹è½½æŒ‰é’® | é€šè¿‡ |
| T04 | å…³é—­æŒ‰é’®ï¼ˆæ­£å‘) | ç‚¹ã€Œå…³é—­ã€ | å¼¹çª—消失、列表页可继续操作 | `.el-dialog__wrapper` display=none,列表正常 | é€šè¿‡ |
| T05 | æŽ§åˆ¶å°æ— æŠ¥é”™ï¼ˆå›žå½’) | è¯»å– dev logs(error/warn) | æ— æ–°å¢žé”™è¯¯ | 0 æ¡ | é€šè¿‡ |
| T06 | å…¶å®ƒæŠ¥è¡¨å¯¼å‡ºè·¯å¾„未受影响(回归,静态) | â€”— | å•å¼ /批量导出仍走原 `downloadBlob` | æœ¬æ¬¡åªæ”¹æ±‡æ€»å¤§è¡¨å¼‚步任务分支,`exportChecked` ä¸­å…¶å®ƒåˆ†æ”¯æœªåЍ | é€šè¿‡ï¼ˆé™æ€ï¼‰ |
@@ -41,7 +41,7 @@
| # | é—®é¢˜ | å¤„ç½® |
| --- | --- | --- |
| P1 | å¼¹çª—标题与按钮文案和真实状态不符(已完成仍写「正在生成」;已自动下载仍写「保存文件」) | å·²ä¿®ï¼ˆæ ‡é¢˜éšçŠ¶æ€ã€æŒ‰é’®æ–‡æ¡ˆéšä¸‹è½½çŠ¶æ€ï¼‰ |
| P2 | åŒä¸€ä»½æ–‡ä»¶è¢«é‡å¤è¯·æ±‚后端(1.15 MB Ã— æ¬¡æ•°ï¼‰ | å·²ä¿®ï¼ˆå†…å­˜ Blob ç¼“存,重复保存 0 è¯·æ±‚) |
| P2 | åŒä¸€ä»½æ–‡ä»¶è¢«é‡å¤ä¸‹è½½/重复请求后端(1.15 MB) | å·²ä¿®ï¼šè‡ªåŠ¨ä¸‹è½½åŽä¸å†æ˜¾ç¤ºä¸‹è½½æŒ‰é’®ï¼Œä»Žæ ¹ä¸Šæ¶ˆé™¤é‡å¤ä¸‹è½½ï¼›è‡ªåŠ¨ä¸‹è½½å¤±è´¥æ—¶æ‰å‡ºçŽ°ã€Œä¿å­˜æ–‡ä»¶ã€å…œåº• |
| P3 | éªŒè¯æ–¹æ³•记录:Element UI æœˆä»½é€‰æ‹©æ¡†æ˜¯ **readonly** è¾“入框,自动化不能用 fill/type,必须先点开弹层再选月份;`setValue` å¯¹è¯¥æŽ§ä»¶æ— æ•ˆ | ä»…记录为测试方法备注,非系统缺陷 |
## äº”、结论
@@ -52,3 +52,12 @@
- æµè§ˆå™¨ç«¯å®žæµ‹ 6 æ¡ç”¨ä¾‹é€šè¿‡ï¼Œæ— æŽ§åˆ¶å°æŠ¥é”™ã€‚
测试人:Codex(AI) 测试日期:2026-09-22
## å…­ã€å˜æ›´è®°å½•(用户反馈后调整)
| ç‰ˆæœ¬ | è¡Œä¸º | è¯´æ˜Ž |
| --- | --- | --- |
| v1(09-22 ä¸Šåˆï¼‰ | å®ŒæˆåŽè‡ªåŠ¨ä¸‹è½½ä¸€æ¬¡ï¼ŒæŒ‰é’®å˜ã€Œå†æ¬¡ä¸‹è½½ã€ï¼ˆèµ°å†…å­˜ç¼“å­˜ï¼Œ0 è¯·æ±‚) | è§£å†³äº†ã€Œé‡å¤è¯·æ±‚后端」,但用户反馈:**「已经下载过了就不需要了,为什么还要有一个再次下载」** |
| **v2(09-22 ä¸‹åˆï¼Œæœ€ç»ˆï¼‰** | å®ŒæˆåŽè‡ªåŠ¨ä¸‹è½½ä¸€æ¬¡ï¼Œ**底部只保留「重新生成 / å…³é—­ã€**;仅当自动下载失败(`taskDownloaded=false`)时才显示「保存文件」兜底按钮 | å·²åˆ é™¤ã€Œå†æ¬¡ä¸‹è½½ã€æŒ‰é’®ä¸Žå†…å­˜ Blob ç¼“存;提示语改为「已自动下载:<文件名>(<大小>),文件在浏览器默认下载目录。」 |
**v2 æµè§ˆå™¨å¤éªŒ**(admin/123456,2026-08,未命中缓存 13.6 ç§’):生成中底部为「重新生成(禁用)/后台运行」;完成后标题「汇总大表已生成」、提示「已自动下载:生成_道路运输量汇总表_2026-08.xlsx ï¼ˆ1.15 MB),文件在浏览器默认下载目录。」、底部为「重新生成/**关闭**」;控制台 0 æŠ¥é”™ï¼›ç‚¹ã€Œå…³é—­ã€åŽå¼¹çª— `display:none`。
docs/¹¤×÷ÈÕ½á/¹¤×÷ÈÕ½á_2026-09-22.md
@@ -33,7 +33,8 @@
  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 æŠ¥é”™ã€‚
- **浏览器实测**(admin/123456,2026-08):生成 13.5 ç§’、产物 1.15 MB;完成后标题「汇总大表已生成」、提示「已自动下载:生成_道路运输量汇总表_2026-08.xlsx ï¼ˆ1.15 MB)」;控制台 0 æŠ¥é”™ã€‚
- **用户反馈后改 v2**:「已经下载过了就不需要再次下载」→ åˆ æŽ‰ã€Œå†æ¬¡ä¸‹è½½ã€æŒ‰é’®ä¸Žå†…存缓存,**完成后底部只留「重新生成 / å…³é—­ã€**;仅当自动下载失败时才出现「保存文件」兜底。复验:生成中「重新生成(禁用)/后台运行」→ å®ŒæˆåŽã€Œé‡æ–°ç”Ÿæˆ/关闭」,提示语为「已自动下载:…,文件在浏览器默认下载目录。」,13.6 ç§’、控制台 0 æŠ¥é”™ã€‚
### 5. æ•°æ®æŸ¥çœ‹ä½“验优化(第二轮,用户当日反馈)
traffic-audit-web/src/views/ReportExport.vue
@@ -171,13 +171,13 @@
            <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>
              æµè§ˆå™¨æ²¡å¼¹å‡ºä¸‹è½½æ—¶å¯ç‚¹ã€Œå†æ¬¡ä¸‹è½½ã€â€”—用本地缓存保存,不会重新请求服务器。
              å·²è‡ªåŠ¨ä¸‹è½½ï¼š<b>{{ taskFileName }}</b><span v-if="taskFileSize">({{ taskFileSizeText }})</span>,文件在浏览器默认下载目录。
            </p>
            <p class="task-error" v-else-if="taskDone">自动下载没成功,可点「保存文件」再存一次。</p>
            <p class="task-error" v-if="taskInfo.status === 'FAILED'">{{ taskInfo.error }}</p>
          </div>
          <span slot="footer">
            <el-button size="small" :disabled="!taskDone" @click="downloadTaskFile()">{{ taskDownloaded ? '再次下载' : (taskInfo.fromCache ? '下载' : '保存文件') }}</el-button>
            <el-button size="small" v-if="taskDone && !taskDownloaded" @click="downloadTaskFile()">保存文件</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 type="primary" @click="closeTask">关闭</el-button>
@@ -216,11 +216,10 @@
      taskVisible: false,
      taskInfo: {},
      taskTimer: null,
      // è¿›åº¦å¼¹çª—:完成后会自动下载一次,这里记录「已下载」与文件信息(重复点击走本地缓存,不再请求后端)
      // è¿›åº¦å¼¹çª—:完成后会自动下载一次,这里记录「是否已下载」与文件信息(已下载就不再显示下载按钮)
      taskDownloaded: false,
      taskFileName: '',
      taskFileSize: 0,
      taskBlob: null,
      taskKey: 'summaryWorkbook',
      modules: [
        {
@@ -548,7 +547,6 @@
      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 })
@@ -612,15 +610,8 @@
      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.taskBlob = res
          this.taskFileSize = (res && res.size) || 0
          this.taskDownloaded = true
          this.downloadBlob(res, name)