## 总体方案
- 引入统一软删除机制：所有支持回收站的业务表增加 `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 代码 → 修改删除逻辑到软删除 → 新增回收站接口与前端页面 → 配置菜单与角色 → 编写并运行测试。
- 验收标准：
  - 所有默认查询不返回已删除记录。
  - 回收站能列出各类删除记录，恢复/彻底删除工作正常。
  - 权限严格生效；普通用户删除进入回收站但不可访问回收站界面。
  - 恢复后关联数据完整、功能正常。