用户上报(问题 3):**「汇总大表点下载后要过一会才反应下载,现在数据库的数据还不是很多,那数据库的数据多了这个程序会卡死吗?」**
背景:汇总大表导出是**同步请求**——点击后浏览器要等 10~20 秒才拿到文件(母版读取+回填 6.5s、整本约 4 万格公式重算 4.1s、写盘传输 3.4s),期间页面无任何反馈;
且生成过程一直占着 HTTP 请求线程,多人同时点会让容器线程池被长任务占满。
本次改造(用户确认「可以」):
ReportExportTaskService(固定 1 线程池 report-export-task,daemon)。fromCache=true),跳过母版读取与公式重算;SELECT IFNULL(MAX(id),0) FROM import_batch,期间只要有新导入就自动失效(取不到版本时禁用缓存)。回答用户疑问:**数据量增大主要是 SQL 聚合变慢,不会「卡死」**;改造后生成走后台线程、同报表期结果可复用、同报表期并发自动去重,
即使多人同时点也只是排队(弹窗显示「排队中」),不会占满 Web 线程。
Started TrafficAuditApplication 15:10:53)、前端 Vue 8080(Compiled successfully)_qa_task.ps1、_qa_task2.ps1、_qa_task3.ps1(保留未删)docs/功能测试报告/汇总大表异步导出进度弹窗_2026-09-20.png| 编号 | 用例 | 输入 | 预期 | 实际 | 结论 |
|---|---|---|---|---|---|
| T-A1 | 提交异步任务 | GET /api/report/exportTask/summaryWorkbook?period=2026-08&mode=month |
立即返回 taskId,不阻塞 | 提交耗时 0.07s,进度 6→22→45→70→95→100,终态 DONE,**14.4s** | 通过 |
| T-A2 | 下载任务文件 | GET /api/report/exportTask/{id}/file |
返回 xlsx | 1,325,109 字节,**1.27s** | 通过 |
| T-A3 | 10 分钟内同报表期复用 | 再次提交同参数 | fromCache=true、同 taskId、近乎瞬时 | fromCache=true,**0.01s**,taskId 相同 | 通过 |
| T-A4 | 强制重算 | 提交 refresh=true |
新任务号、真实重算 | 新 taskId,14.2s 重算完成 | 通过 |
| T-A5 | 运行中并发去重 | 连发两次 refresh=true |
返回同一 taskId | 同一 taskId,11.1s | 通过 |
| T-A6 | 新增导入使缓存失效 | 临时插入一条 import_batch(id 533→534)后提交 |
fromCache=false,重新生成 | fromCache=false,11.4s 重算;**测试后已 DELETE 清回 id=533** | 通过 |
| T-A7 | 负向:不存在的 taskId | GET /exportTask/notexist123 / .../file |
返回明确错误 | 状态接口 code=500「导出任务不存在或已过期(生成结果保留 30 分钟)」;文件接口 HTTP 500 + 同提示 |
通过 |
| T-A8 | 负向:未完成就下载 | 任务 RUNNING 时请求 /file |
拒绝并说明 | 抛「导出任务尚未完成(当前状态:RUNNING)」 | 通过 |
| 编号 | 用例 | 输入 | 预期 | 实际 | 结论 |
|---|---|---|---|---|---|
| UI-1 | 进度弹窗 | 报表生成 → 汇总大表 → 2026-08 → 点「导出」 | 立即弹窗并逐档推进 | 弹窗即时出现,实测采样:0.7s 读取母版工作簿(6%) → 1.5s 回填当月数据(22%) → 2.2s 刷新排名页与跨页合成页(45%) → 7.2s 重算整本公式(约 4 万格)(70%) → 10.1s 写出文件(95%) → 11.6s 完成(100%) | 通过 |
| UI-2 | 完成后自动下载 | 同上 | 自动触发保存 | 下载 生成_道路运输量汇总表_2026-08.xlsx,**1,325,109 字节**,与接口产物同哈希 |
通过 |
| UI-3 | 缓存命中提示 | 关闭后再次点「导出」 | 提示来源时间 + 「下载」按钮 | 「上次生成用时 11.3 秒」「本次直接使用 2026-09-20 15:43:50 生成的结果(10 分钟内且期间没有新导入数据)」,按钮变「下载」,秒级完成 | 通过 |
| UI-4 | 「重新生成」 | 缓存态点「重新生成」 | 真实重算 | 进度从 0 重新推进(「已用 2.1 秒」),按钮区切回「保存文件/重新生成/后台运行」,23.4s 内完成并自动下载 | 通过 |
| UI-5 | 「后台运行」 | 生成中点「后台运行」 | 收起弹窗、任务继续、完成仍自动下载 | 弹窗收起 + 提示「已转入后台生成,完成后会自动下载」,随后自动下载 1,325,109 字节 | 通过 |
| UI-6 | 负向:无数据报表期 | 选 2025-01 → 导出 → 确认「仍要导出」 | 显示失败原因、可关闭、不可保存 | 弹窗显示「生成失败|未找到模板文件: 2025年1月道路运输量汇总表.xlsx」,X 可关闭,「保存文件」禁用,「重新生成」可用 | 通过 |
| UI-7 | 产物一致性 | 冷启动件 vs 刷新重算件 | 数据一致 | 两次产物解包后**逐条目一致**(无差异条目);三份缓存下载件 SHA256 完全相同 | 通过 |
| 编号 | 用例 | 输入 | 预期 | 实际 | 结论 |
|---|---|---|---|---|---|
| P-1 | 预览同比项是否补全 | 汇总大表预览弹窗 | 8 项同比都在 | 12 行(货运/城市客运/中口径 × 当月·累计 × 量·周转),同比列齐全 | 通过 |
| P-2 | 「累计货物周转量·累计同比 0%」是否为 bug | 查库 scale_split_transport |
应为取数源本身的值 | 库内 total_yoy=0.00000346(约 0.0003%)→ 一位小数四舍五入即 0%,非计算错误 |
通过(非缺陷) |
ReportExport.vue 出现重复的 computed 键(本次浏览器实测发现,属严重回归)computed: {,username / realName / myModules / visibleModules 计算属性全部丢失,created() 直接抛 Cannot read properties of undefined (reading 'filter'),**整页白屏不可用**。computed 块(并加注释说明不可另起同名 key),编译通过并浏览器复验正常。Result(错误时 HTTP 仍 200、data 为空),this.taskInfo = res.data || {} 会得到一个空对象 → 进度停在 0% 且不给提示。res.code !== 200 || !res.data:提交失败立即显示失败原因;轮询判为「任务已失效」并停止轮询。:disabled="!taskDone",生成中三个按钮全灰、右上角 X 也隐藏,用户被锁在弹窗里等 10~20 秒。computed 回归(该问题在接口测试中不可见)。