## 检查项
- 路由与前端：确认管理端生成/摘要接口使用活动级路径
  - 生成：`POST /api/admin/activities/:activity_id/commitment/generate`
  - 摘要：`GET /api/admin/activities/:activity_id/commitment/summary`
  - 前端 API 指向上述路径（不是旧的 `/ichiban/...`）
- 数据迁移：核实 `activities` 已存在承诺字段（algo/seed_master/seed_hash/state_version/items_root）且成功执行
- 服务实现：检查 ActivityCommitmentService
  - 生成：写入 `seed_master`、`seed_hash`、`state_version`；当前 items_root 为 NULL，需要按最新设计计算
  - 摘要：从 `activities` 读取版本与算法，`has_seed` 通过 `LENGTH(seed_master)` 判断
- 策略消费：一番赏映射读取活动承诺种子（非期级表），若缺承诺返回明确错误

## 修正与实现（不兼容旧期级）
- 计算并写入 `commitment_items_root`
  - 规则：对活动下各期的奖励配置，按每个奖励的 `original_qty` 构造 slots 数组（长度为 N），计算 `items_root = SHA256(JSON(slots))`
  - 写入 `activities.commitment_items_root`，用于事后验证映射根
  - 版本递增：每次生成承诺 `state_version+1`
- 一番赏映射页承诺校验
  - 进入列表或详情时检查活动承诺存在（`has_seed=true`）；无承诺返回“请在活动管理生成承诺”提示
- 活动管理显示
  - 活动列表新增“承诺版本”列（已加），确保加载摘要后填充版本
  - 活动编辑弹窗顶部承诺信息卡片（已加），显示 `seed_version/algo/状态`

## 验证流程
- 生成承诺后，确认 `activities` 中：
  - `LENGTH(commitment_seed_master)=32`、`LENGTH(commitment_seed_hash)=32`
  - `commitment_state_version` 递增
  - `LENGTH(commitment_items_root)>0`
- 前端列表显示版本值；映射页顶部显示活动承诺版本
- 并发占位与映射不变：种子存在即可按位置开奖；缺承诺时前端/后端均提示

## 接口与 curl
- 生成：`curl -X POST 'http://127.0.0.1:9991/api/admin/activities/<id>/commitment/generate' -H 'Authorization: Bearer TOKEN'`
- 摘要：`curl 'http://127.0.0.1:9991/api/admin/activities/<id>/commitment/summary' -H 'Authorization: Bearer TOKEN'`
- DB 校验：`SELECT LENGTH(commitment_seed_master), LENGTH(commitment_seed_hash), LENGTH(commitment_items_root), commitment_state_version FROM activities WHERE id=<id>;`

## 交付修改点
- 后端：完善 ActivityCommitmentService 的 items_root 计算与写入（活动维度）
- 前端：确保活动列表与编辑对话框显示承诺；映射页在无承诺时给出指导提示

## 说明
- 全量切换到活动级承诺；不读取旧 `issue_random_commitments`
- 保持统一接口与策略，后续抽奖逻辑统一使用活动承诺