4.4 KiB
4.4 KiB
上传垃圾资源清理 - 收尾计划
概述
本计划承接前一会话的工作。前一会话已实现上传垃圾清理的完整三层防御机制(前端即时清理 + 后端保存时清理 + 后端 GC 兜底),并完成了 8 个页面的接入。经探查验证,发现一个遗漏场景:后台顶栏的个人资料弹窗(AdminLayout.vue)使用了 IconUpload 上传头像,但未接入上传会话清理机制。本计划补齐该场景并完成整体验证。
当前状态分析
已完成(无需改动)
- 前端基础设施:
api/index.ts的deleteUpload方法、useUploadSession.tscomposable - 上传组件:
IconUpload.vue、VideoUpload.vue已支持uploadSessionprop +currentKey跟踪 - 8 个页面接入:Categories / Platforms / Banners / Partners / Employees / Customers / Settings / ProjectEdit
- 后端基础设施:SystemController Upload/DELETE 端点、UploadTrackingService、UploadCleanupJob、各业务 Service 的 ConsumeAsync 调用
遗漏场景(本次修复)
- AdminLayout.vue 个人资料弹窗:使用 IconUpload 上传头像,但未接入上传会话。当用户上传新头像后点击"取消"或关闭弹窗,文件成为垃圾资源(仅靠 24h GC 兜底,不符合即时清理目标)。
范围外说明(不在本次修复)
- ProjectPackage 软删除孤儿:
DeletePackageAsync仅设IsDeleted = true,不删除存储文件。这是实体级清理问题,不属于"上传垃圾清理"范畴(上传时立即消费,无 pending 状态),单独跟踪。 - WebGL 解压失败孤儿:ZIP 上传成功但解压失败时,文件已落库存储。属于异常流程清理,单独跟踪。
计划改动
改动 1:AdminLayout.vue 接入上传会话清理
文件:d:\TraeProject\MilliSim4\frontend\src\layouts\AdminLayout.vue
改动内容(参照 Employees.vue 模式):
-
导入 composable(script 顶部):
import { useUploadSession } from '@/composables/useUploadSession' -
创建实例(setup 区域):
const uploadSession = useUploadSession() -
个人资料 el-dialog 增加 @closed 事件(约 L142):
<el-dialog v-model="profileVisible" ... @closed="uploadSession.cleanupPending()"> -
IconUpload 传入 uploadSession prop(约 L157):
<IconUpload v-model="profileForm.avatar" folder="avatars" alt="头像" :upload-session="uploadSession" /> -
saveProfile 成功后重置会话(约 L259-276 内的成功分支):
// 保存成功后清空 pending 列表:头像已被后端 ConsumeAsync 消费 uploadSession.reset()
注意:
- AdminLayout 是常驻布局组件,不会频繁卸载,
onBeforeUnmount自动清理在此场景下主要起兜底作用;真正的清理依赖@closed事件。 - 不需要改"取消"按钮逻辑,因为
@closed事件在点击取消(关闭弹窗)时也会触发。
改动 2:验证步骤
前端验证:
- 后端 dev server 已运行(前一会话已启动,确认端口 5041 监听)
- 前端 Vite dev server 已运行(确认无 HMR 编译错误)
- 如有编译错误则修复
功能场景测试(建议用户在浏览器手动验证至少 2 个场景):
- 场景 A:新增分类 → 上传图标 → 点击取消 → 确认图标被清理(检查后端日志 DELETE 请求)
- 场景 B:编辑员工 → 上传新头像 → 点击取消 → 确认头像被清理
- 场景 C:后台顶栏 → 点击头像 → 上传新头像 → 点击取消 → 确认头像被清理(本次新增场景)
假设与决策
- 不动后端代码:前一会话后端已完整实现,本次仅前端补漏。
- 不动 ProjectPackage 软删除逻辑:属于实体生命周期管理,不在上传垃圾清理范畴。
- 保留 onBeforeUnmount 兜底:AdminLayout 虽不常卸载,但 composable 的 onBeforeUnmount 仍是安全网,不删除。
- 使用
@closed而非@close:@closed在弹窗动画结束后触发,避免与销毁逻辑冲突(与已接入页面保持一致)。
验证步骤
- 修改 AdminLayout.vue 后,查看 Vite HMR 日志确认无编译错误
- 检查后端进程仍在运行(端口 5041)
- 向用户报告:本次补漏 + 整体验证结果
- 建议用户手动测试场景 C(个人资料头像取消清理)