## 背景
- 当前不启用数据库外键约束（FK），删除由业务逻辑驱动。
- 现有删除实现多为单表删除，未做级联：如删除活动 `internal/service/activity/activity_delete.go:9`、删除期 `internal/service/activity/issue_delete.go:9`、删除用户 `internal/service/user/batch_user.go:32`。
- GORM 初始化未声明外键或级联：`internal/repository/mysql/mysql.go:97`。

## 目标
- 在业务层实现“逻辑级联删除”，保证删除主实体时，同步清理其关联业务数据，且性能与可控性优于 FK 级联。

## 级联清单
### 删除活动（Activities.ID）
- 删除活动期：`activity_issues` 按 `activity_id`（`internal/repository/mysql/model/activity_issues.gen.go:18`）
- 期下配置与承诺：
  - 奖励配置 `activity_reward_settings` 按 `issue_id`（`internal/repository/mysql/model/activity_reward_settings.gen.go:18`）
  - 活动承诺字段：`activities.commitment_*`（活动维度，已统一使用活动级承诺，不存在期级承诺表）
- 期下抽奖相关：
  - 抽奖日志 `activity_draw_logs` 按 `issue_id`（`internal/repository/mysql/model/activity_draw_logs.gen.go:18`）
  - 抽奖效果 `activity_draw_effects` 按 `draw_log_id`/`issue_id`（`internal/repository/mysql/model/activity_draw_effects.gen.go:17,29`）
  - 抽奖凭据 `activity_draw_receipts` 按 `draw_log_id`（`internal/repository/mysql/model/activity_draw_receipts.gen.go:17`）
- 活动范围效果与道具：
  - 用户道具使用记录 `user_item_cards` 按 `used_activity_id` / `used_issue_id` / `used_draw_log_id`（`internal/repository/mysql/model/user_item_cards.gen.go:24,25,23`）
  - 抽奖效果快照 `activity_draw_effects` 按 `activity_id`/`issue_id`（`internal/repository/mysql/model/activity_draw_effects.gen.go:28,29`）
- 资产与日志：
  - 用户资产 `user_inventory` 按 `activity_id`（`internal/repository/mysql/model/user_inventory.gen.go:21`）
  - 公会贡献日志 `guild_contribute_logs` 按 `activity_id` / `issues_id`（`internal/repository/mysql/model/guild_contribute_logs.gen.go:19,20`）
- 系统模板：
  - 系统道具卡 `system_item_cards` 按 `activity_id` / `issue_id`（`internal/repository/mysql/model/system_item_cards.gen.go:23,24`）
  - 系统优惠券 `system_coupons` 按 `activity_id`（`internal/repository/mysql/model/system_coupons.gen.go:20`）
- 最后删除活动主表：`activities`（`internal/repository/mysql/model/activities.gen.go:15`）

### 删除用户（Users.ID）
- 用户身份与权益：
  - 头衔 `user_titles` 按 `user_id`（`internal/repository/mysql/model/user_titles.gen.go:16`）
  - 领取型权益限流 `user_title_effect_claims` 按 `user_id`（`internal/repository/mysql/model/user_title_effect_claims.gen.go:16`）
- 用户账户与地址：
  - 地址 `user_addresses` 按 `user_id`（`internal/repository/mysql/model/user_addresses.gen.go:18`）
  - 积分余额 `user_points` 按 `user_id`（`internal/repository/mysql/model/user_points.gen.go:18`）
  - 积分流水 `user_points_ledger` 按 `user_id`（`internal/repository/mysql/model/user_points_ledger.gen.go:17`）
- 用户订单与优惠：
  - 订单 `orders` 按 `user_id`（`internal/repository/mysql/model/orders.gen.go:18`）
  - 用户优惠券 `user_coupons` 按 `user_id`（`internal/repository/mysql/model/user_coupons.gen.go:18`）
- 用户资产与道具：
  - 用户资产 `user_inventory` 按 `user_id`（`internal/repository/mysql/model/user_inventory.gen.go:18`）
  - 用户道具卡 `user_item_cards` 按 `user_id`（`internal/repository/mysql/model/user_item_cards.gen.go:18`）
- 与抽奖相关：
  - 抽奖效果 `activity_draw_effects` 按 `user_id` 或关联 `draw_log_id`（`internal/repository/mysql/model/activity_draw_effects.gen.go:18,17`）
  - 抽奖凭据 `activity_draw_receipts` 关联 `draw_log_id`（`internal/repository/mysql/model/activity_draw_receipts.gen.go:17`）
  - 抽奖日志 `activity_draw_logs` 按 `user_id`（`internal/repository/mysql/model/activity_draw_logs.gen.go:17`）
- 公会关联：
  - 公会成员 `guild_members` 按 `user_id`（`internal/repository/mysql/model/guild_members.gen.go:18`）
  - 公会贡献日志 `guild_contribute_logs` 按 `user_id`（`internal/repository/mysql/model/guild_contribute_logs.gen.go:18`）
- 履约/发货：
  - 发货记录 `shipping_records` 按 `user_id`（`internal/repository/mysql/model/shipping_records.gen.go:18`）
  - 运营发货统计 `ops_shipping_stats` 按 `user_id`（`internal/repository/mysql/model/ops_shipping_stats.gen.go:21`）
- 最后软删用户：`users.deleted_at`（`internal/repository/mysql/model/users.gen.go:20`）

## 删除顺序（事务内）
- 统一采用“从叶到根”的顺序：
  1) 以日志/效果/凭据等子表为先（`activity_draw_effects`、`activity_draw_receipts`、`activity_draw_logs`）
  2) 再清理资产/权益/模板（`user_inventory`、`user_item_cards`、`user_titles`、`system_*`）
  3) 清理期与期下配置（`activity_issues`、`activity_reward_settings`）
  4) 删除根实体（`activities` 或软删 `users`）
- 全过程包裹在单事务中，任何一步失败则回滚。

## 实现策略
- 新增业务服务方法：
  - `DeleteActivityCascade(ctx, activityID)`：按“删除活动”清单顺序删除
  - `DeleteUserCascade(ctx, userID)`：按“删除用户”清单顺序删除
- 技术要点：
  - 批量删除使用分批（如 5k/批）避免长事务与大锁；必要时按时间/ID 片段迭代
  - 统一 `WHERE` 条件与索引列（`user_id`/`activity_id`/`issue_id`/`draw_log_id`）确保扫描性能
  - 软删与硬删：保留用户软删（合规与审计），其余按当前表定义硬删；如需统一软删，可后续逐表补充 `gorm.DeletedAt`
  - 幂等性：每个子删除操作按条件删除，无记录时直接通过；重复调用不报错
  - 审计：记录操作日志（操作者、对象ID、影响行数），便于回溯

## 验收标准
- 删除活动时，任一期及其抽奖日志/效果/凭据、奖励配置、承诺、资产、贡献日志与相关模板均被清理；根活动删除成功。
- 删除用户时，地址/订单/优惠券/积分（余额+流水）/资产/道具/抽奖相关/公会关系/发货记录及统计均被清理；根用户软删成功。
- 全流程事务保障、失败回滚；批量删除性能稳定，无显著锁表或超时。

## 需要改造的现有入口（参考）
- 活动删除入口：`internal/service/activity/activity_delete.go:9` → 升级为调用 `DeleteActivityCascade`
- 期删除入口：`internal/service/activity/issue_delete.go:9` → 被 `DeleteActivityCascade` 内部调用（或保留独立级联）
- 用户删除入口：`internal/service/user/batch_user.go:32` → 升级为调用 `DeleteUserCascade`

## 后续动作
- 我将基于以上清单与顺序，补充两套事务级联删除实现，并为关键入口替换调用；同时补充单元测试覆盖正常/边界/异常三类用例，验证幂等与性能。
