编辑 | blame | 历史 | 原始文档

功能测试报告_汇总大表导出结果落盘缓存复用_2026-09-22

一、功能说明

用户诉求:「我已经下载过了为什么还要重新生成呢?可以弄一个记忆功能吗——我下载过某个数据,第二次下载期间没有新导入数据,就直接沿用上次算好的结果。不然每次下载都要等很久。」

改造前:已有「10 分钟内 + 期间无新导入」的内存缓存,但①窗口只有 10 分钟;②存在内存里,进程一重启就没了 → 正常场景下第二次下载仍要重算 13~17 秒。

改造后:
1. 结果**落盘**保存到 docs/生成汇总大表/_cache/(已加入 .gitignore),文件名 <key>_v<数据版本>.xlsx;
2. 提交导出时(未点「重新生成」):**内存缓存 → 落盘缓存 → 真算**;落盘命中要求「同一报表期 + 同一数据版本」;
3. 数据版本 = MAX(import_batch.id):只要期间有任何一次数据导入,版本就变,旧缓存自动失效;
4. 复用上限 7 天(防陈年结果被当新表发出),超期文件在下次提交时自动清理;同一 key 只保留最新版本文件;
5. 前端命中缓存时显示「本次直接沿用 <生成时间> 生成的结果(期间没有新的数据导入)。如需按最新数据重算,请点「重新生成」。」,并把一行元信息改成「报表期 2026-08 上次生成于 …」(不再显示「上次生成用时 0.0 秒」);
6. 修掉落盘命中时 elapsedMs 为负数的问题(以生成时间作为任务起点)。

改动文件:ReportExportTaskService.java(核心)、ReportExportController.java(注释)、ReportExport.vue(文案)、.gitignore。

二、测试环境

  • 后端 Spring Boot 8090(重启加载新代码);前端 npm run serve 8080(Compiled successfully)
  • 数据库 MySQL 3308 / traffic_audit;报表期 2026-08(月报)
  • 缓存目录:docs/生成汇总大表/_cache/;命中判据 MAX(import_batch.id)(测试时为 541)

三、用例表

# 用例 操作 预期 实际 结论
T01 首次提交(无缓存,正向) GET /api/report/exportTask/summaryWorkbook?period=2026-08 真算,完成后写落盘缓存 RUNNING → DONE(12.4 s);生成 summaryWorkbook_2026-08_month__v541.xlsx(1,204,461 B) 通过
T02 再次提交(内存命中) 同上报 立即 DONE、fromCache=true 提交耗时 164 ms,fromCache=true;下载 1,204,461 B 与缓存文件一致 通过
T03 重启后端后再提交(落盘命中,核心) 停/起前后端后提交 仍立即 DONE(不再重算) 提交 1,194 ms,fromCache=true,日志「命中落盘缓存…」,下载字节一致 通过
T04 有新导入(负向) 临时插入一条 import_batch(id 变 542)后提交 缓存失效、重新生成 fromCache=false、status=RUNNING 通过
T05 同 key 只留最新版本 重算完成后看缓存目录 旧版本文件被删除 目录只剩 …_v542.xlsx(v541 已删) 通过
T06 版本回落后 删掉临时导入行(版本回到 541)后再提交 不命中 v542,重算并写回 v541 fromCache=false → 重算完成;目录只剩 …_v541.xlsx 通过
T07 时长显示(回归修复) 落盘命中时看 elapsedMs / 前端元信息 不为负数 修复前 elapsedMs=-72937;修复后 elapsedMs=0,前端显示「报表期 2026-08 上次生成于 2026-09-22 11:27:32」 通过
T08 浏览器端到端(正向) admin/123456 → 报表生成 → 汇总大表 → 2026-08 → 导出 秒出并自动下载,文案正确 点击后**立即**「汇总大表已生成」100%;显示「本次直接沿用 2026-09-22 11:27:32 生成的结果(期间没有新的数据导入)」、「已自动下载:生成_道路运输量汇总表_2026-08.xlsx (1.15 MB)…」;按钮仅「重新生成 / 关闭」;控制台 0 报错 通过
T09 缓存不串期(静态) —— 不同报表期/模式互不命中 key(type|period|mode|toMonth)同时进入内存键与落盘文件名前缀 通过(静态)
T10 自动清理 —— 超期文件被删除 每次提交调用 cleanupExpired():内存条目与磁盘文件超过 7 天即清 通过(静态)

四、发现的问题与处置

# 问题 处置
P1 落盘命中时前端「用时」为负数(elapsedMs=-72937,因为任务起点是现在、结束时间是历史生成时间) 已修:落盘命中时把任务起点设为生成时间;前端缓存命中不再显示用时,改显示「上次生成于 …」
P2 测试用的临时 import_batch 行 已删除(MAX(id) 回到 541、批次 419 条),仅用于验证「导入即失效」
P3 数据版本是**全局**的:任何一次导入(含与汇总大表无关的投资/能耗导入)都会让汇总缓存失效 属保守设计(宁可重算不可出错)。若希望「只有相关数据导入才失效」,需要按 import_type 细分依赖,待用户确认后排期
P4 落盘目录 新增 docs/生成汇总大表/_cache/ 并加入 .gitignore(结果文件不入库)

五、结论

  • 「下载过一次、期间没有新导入 → 第二次直接沿用」已实现,且**跨后端重启有效**(这是本次的关键增量);
  • 复用正确性由「数据版本(MAX(import_batch.id))+ 7 天上限」双重把关:有新导入必定重算,测试已覆盖;
  • 用户体验:命中缓存时点导出**秒回**(毫秒级),不再每次等 13~17 秒;「重新生成」保留为强制重算入口;
  • 浏览器端到端实测通过,无控制台报错。

测试人:Codex(AI) 测试日期:2026-09-22