bindbox-game/.trae/documents/实现回收站与软删除机制.md
邹方成 2a89a1ab9d
Some checks failed
Build docker and publish / linux (1.24.5) (push) Failing after 39s
feat(admin): 更新前端资源文件及修复相关功能
refactor(service): 修改banner和guild删除逻辑为软删除
fix(service): 修复删除操作使用软删除而非物理删除

build: 添加SQLite测试仓库实现
docs: 新增奖励管理字段拆分和批量抽奖UI改造文档

ci: 更新CI忽略文件
style: 清理无用资源文件
2025-11-19 01:35:55 +08:00

68 lines
6.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 总体方案
- 引入统一软删除机制:所有支持回收站的业务表增加 `deleted_at DATETIME NULL``deleted_by BIGINT NULL` 字段,并在 ORM 层启用 GORM Soft Delete 以默认过滤已删除记录。
- 提供中心化回收站接口与界面:集中列出各类型的软删除数据,支持恢复与彻底删除(二次确认)。
- 权限与菜单对齐:仅管理员可访问回收站;侧边栏在“系统管理”下新增“回收站”菜单,配置角色可见与按钮权限。
## 数据库改造
- 目标表(根据现有模型与端点清单):`activities``activity_issues``activity_reward_settings``products``product_categories``banner``guild``system_titles``system_title_effects``system_item_cards``system_coupons``menus``menu_actions``roles``role_users`
- 变更内容:
- 添加列:`deleted_at DATETIME NULL`(建立索引以提升查询效率)、`deleted_by BIGINT NULL`
- 后续通过 `cmd/gormgen` 重新生成 `internal/repository/mysql/{model,dao}/*.gen.go`,使模型包含 `gorm.DeletedAt``DeletedBy` 字段。
- 迁移策略:当前仓库未集成迁移工具,计划新增 `migrations/` 与 SQL 脚本(或集成 `goose`),在测试/生产库执行列新增与索引建立,完成后重新生成 ORM 代码。
## 后端改造
- 技术栈:`gin` + `gorm`(已存在),读写库封装见 `internal/repository/mysql/mysql.go`,路由集中在 `internal/router/router.go`
- 删除逻辑切换为软删除:
- 将所有 `DELETE /api/...` 对应的处理器由物理删除改为 `gorm` 软删除:`db.Delete(&model)`,自动写入 `deleted_at`;同时通过上下文注入当前用户 ID 写入 `deleted_by`(更新列)。
- 涉及端点示例(集中定义于 `internal/router/router.go` 对应 handler活动、期数、奖励、工会、商品、分类、轮播图、称号/特效、道具卡、优惠券、系统菜单/动作、角色、角色成员等。
- 查询默认过滤:
- 使用含 `gorm.DeletedAt` 的模型,`gorm` 默认生成 `WHERE deleted_at IS NULL`;确保服务与 DAO 层不使用 `Unscoped()`,避免误返回已删除数据。
- 回收站接口:新增 `internal/api/admin/system_recycle.go` 与服务层 `internal/service/recycle/recycle_service.go`
- `GET /api/admin/recycle`:参数 `type`枚举activity、issue、reward、product...)、分页;实现为 `Unscoped().Where("deleted_at IS NOT NULL")` 列表,返回原始字段与 `deleted_at``deleted_by`
- `POST /api/admin/recycle/restore`:参数 `type,id``Unscoped()` 更新目标记录 `deleted_at=NULL, deleted_by=NULL`,恢复数据。
- `DELETE /api/admin/recycle`:参数 `type,id``Unscoped().Delete(&model)` 执行物理删除。
- 关联完整性:
- 软删除不级联子表;外键仍保持,恢复后关联自然可用。
- 若业务场景需要父子一致软删除(可选扩展),在服务层增加按类型的联动策略,但默认不做级联以降低风险。
- 权限拦截:
- 以上回收站接口全部走管理员认证中间件 `internal/router/interceptor/admin_auth.go::AdminTokenAuthVerify`
- 彻底删除在服务层进行额外二次确认校验(配合前端确认对话框),后端也校验 `role``action` 权限。
## 前端改造web/admin
- 框架:`vue3` + `vue-router` + `pinia` + `element-plus`,侧边栏位于 `web/admin/src/components/core/layouts/art-menus/art-sidebar-menu`,菜单数据由路由模块/后端菜单驱动。
- 路由与页面:
- 新增路由模块 `web/admin/src/router/modules/system/recycle.ts``path:'/system/recycle'``meta.roles:['admin']``meta.authList:['recycle:list','recycle:restore','recycle:forceDelete']`
- 新增页面 `web/admin/src/views/system/recycle/index.vue`
- 顶部类型筛选(下拉:活动、商品、工会…)。
- 表格列出删除数据(含关键原字段、`deleted_at``deleted_by`),分页。
- 行操作:`恢复`(调用 `POST /api/admin/recycle/restore`)、`彻底删除``ElMessageBox.confirm` 二次确认后调用 `DELETE /api/admin/recycle`)。
- API 封装:`web/admin/src/api/system/recycle.ts`(使用现有 Axios 封装 `web/admin/src/utils/http/index.ts``listDeleted(type,page,size)``restore(type,id)``forceDelete(type,id)`
- 菜单项:
- 后端在 `menus` 表增加“系统管理/回收站”,`path:'/system/recycle'`,并在角色分配接口 `POST /api/role/:role_id/menus` 仅赋予管理员;前端 `ListSimpleMenus` 拉取后自动渲染。
- 权限指令与守卫:
- 按按钮权限 `meta.authList` 与角色 `meta.roles` 控制显示;普通用户不显示菜单,无法访问路由或调用接口。
## 权限控制细则
- 仅管理员角色拥有“回收站”菜单与相关按钮权限;普通用户删除操作也走软删除,但无法访问回收站接口。
- 彻底删除在前端强制二次确认,并在后端再次校验权限与保护条件(如必须管理员)。
## 测试方案
- 后端Go `testing`
- `internal/api/admin/system_recycle_test.go`
- 删除后记录存在于回收站接口,原查询不可见(验证 `deleted_at` 与默认过滤)。
- 恢复后记录重新可见,`deleted_at`/`deleted_by` 为空。
- 权限:非管理员访问回收站接口返回 `401/403`;管理员正常。
- 关联完整性:恢复后关联查询正常(父子外键未破坏)。
- 前端Vitest
- `web/admin/src/tests/system/recycle/recycle.test.ts`
- 菜单与路由权限:管理员可见“回收站”,普通用户不可见。
- 列表加载与分页、恢复按钮触发成功提示与刷新、彻底删除二次确认弹窗与成功流程。
- 401/403 拦截按现有拦截器工作(参考 `src/tests/auth/401-error-handling.test.ts`)。
## 交付与验证
- 执行数据库迁移并生成 ORM 代码 → 修改删除逻辑到软删除 → 新增回收站接口与前端页面 → 配置菜单与角色 → 编写并运行测试。
- 验收标准:
- 所有默认查询不返回已删除记录。
- 回收站能列出各类删除记录,恢复/彻底删除工作正常。
- 权限严格生效;普通用户删除进入回收站但不可访问回收站界面。
- 恢复后关联数据完整、功能正常。