# 全平台测试方案

## 测试范围

| 层级 | 覆盖内容 |
|------|---------|
| 数据库 | 表结构完整性、字段约束、外键关联、索引、数据一致性 |
| 后端 API | 全部 18 个公众端接口 + 核心管理端接口的功能和异常测试 |
| 前端 | 4 个端的页面渲染、交互逻辑、路由守卫、响应式适配 |
| 全链路 | 4 条核心业务流程端到端走通 |

---

## 一、数据库测试

### 1.1 新增/变更表结构验证

| 编号 | 测试项 | 验证方式 | 预期结果 |
|------|--------|---------|---------|
| DB-01 | children 表存在且字段完整 | `DESCRIBE children` | 12 个字段：id, parent_id, name, gender, birthday, grade, city, school_name, avatar, is_deleted, create_time, modify_time |
| DB-02 | children.parent_id 外键关联 users.id | 插入不存在的 parent_id | 外键约束报错 |
| DB-03 | users.phone 唯一约束 | 插入两条相同 phone 的记录 | 唯一约束报错 |
| DB-04 | users.wx_openid 唯一约束 | 插入两条相同 wx_openid | 唯一约束报错 |
| DB-05 | users.user_source 默认值 | 插入不指定 user_source 的记录 | 默认 'admin_created' |
| DB-06 | tenants.tenant_type 默认值 | 插入不指定 tenant_type 的记录 | 默认 'other' |
| DB-07 | t_contest.visibility 默认值 | 插入不指定 visibility 的记录 | 默认 'designated' |
| DB-08 | t_contest.target_cities JSON 格式 | 存储 `["广州","深圳"]` | 正常读写 JSON 数组 |
| DB-09 | t_contest.age_min / age_max 可为 NULL | 插入 NULL 值 | 正常存储 |
| DB-10 | t_contest_registration.participant_type 默认值 | 插入不指定的记录 | 默认 'self' |
| DB-11 | t_contest_registration.child_id 可为 NULL | 自己报名时不传 child_id | 正常存储为 NULL |
| DB-12 | t_contest_registration.child_id 外键 | 关联 children.id | 删除 child 时 SetNull |

### 1.2 租户与角色数据完整性

| 编号 | 测试项 | SQL | 预期结果 |
|------|--------|-----|---------|
| DB-13 | 超级租户存在 | `SELECT * FROM tenants WHERE code='super'` | tenant_type='platform', is_super=1 |
| DB-14 | 公众租户存在 | `SELECT * FROM tenants WHERE code='public'` | tenant_type='platform', is_super=0 |
| DB-15 | 广东省图租户存在 | `SELECT * FROM tenants WHERE code='gdlib'` | tenant_type='library' |
| DB-16 | 评委租户存在 | `SELECT * FROM tenants WHERE code='judge'` | tenant_type='other' |
| DB-17 | 各角色权限数量 | 查询 role_permissions 聚合 | super_admin≥10, tenant_admin≥26, judge≥10, public_user=4 |
| DB-18 | 公众用户角色有正确权限 | 查询 public_user 角色权限 | 包含 activity:read, registration:create, work:create, child:manage |

### 1.3 菜单分配验证

| 编号 | 测试项 | 预期结果 |
|------|--------|---------|
| DB-19 | 超管端菜单 | 4 个一级菜单：活动监管(8子)、机构管理(1子)、用户中心(3子)、系统设置(5子) |
| DB-20 | 广东省图菜单 | 2 个一级菜单：活动管理(8子)、系统设置(3子：用户/角色/日志) |
| DB-21 | 评委端菜单 | 1 个一级菜单：我的评审(2子：评审任务/预设评语) |
| DB-22 | 公众租户无管理菜单 | 公众租户 tenant_menus 为空 |
| DB-23 | 广东省图不含平台级菜单 | 不含菜单管理、权限管理、数据字典、系统配置、租户管理 |

---

## 二、后端 API 测试

### 2.1 公众端认证 API

| 编号 | 接口 | 测试场景 | 方法 | 预期 |
|------|------|---------|------|------|
| API-01 | POST /public/auth/register | 正常注册 | `{"username":"test001","password":"test123456","nickname":"测试用户"}` | 200，返回 token + user 信息，user_source='self_registered' |
| API-02 | POST /public/auth/register | 用户名已存在 | 重复提交 test001 | 409，"用户名已被注册" |
| API-03 | POST /public/auth/register | 用户名太短 | `{"username":"ab","password":"123456","nickname":"test"}` | 400，校验错误 |
| API-04 | POST /public/auth/register | 密码太短 | `{"username":"test002","password":"123","nickname":"test"}` | 400 |
| API-05 | POST /public/auth/register | 缺少必填字段 | `{"username":"test003"}` | 400 |
| API-06 | POST /public/auth/register | 带手机号注册 | `{"username":"test004","password":"123456","nickname":"test","phone":"13800138001"}` | 200，phone 正确存储 |
| API-07 | POST /public/auth/register | 手机号重复 | 再次提交 13800138001 | 409，"该手机号已被注册" |
| API-08 | POST /public/auth/login | 正常登录 | `{"username":"test001","password":"test123456"}` | 200，返回 token |
| API-09 | POST /public/auth/login | 密码错误 | `{"username":"test001","password":"wrong"}` | 401，"用户名或密码错误" |
| API-10 | POST /public/auth/login | 用户不存在 | `{"username":"nonexist","password":"123456"}` | 401 |

### 2.2 子女管理 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-11 | POST /public/mine/children | 正常添加子女 | 200，返回子女信息含 id |
| API-12 | POST /public/mine/children | 缺少姓名 | 400，"子女姓名不能为空" |
| API-13 | POST /public/mine/children | 完整信息 | `{"name":"小明","gender":"male","birthday":"2018-05-15","grade":"二年级","city":"广州","schoolName":"实验小学"}` → 200 |
| API-14 | GET /public/mine/children | 获取列表 | 200，返回数组，按创建时间倒序 |
| API-15 | GET /public/mine/children/:id | 获取详情 | 200，返回单个子女 |
| API-16 | GET /public/mine/children/:id | 非自己的子女 | 404，"子女信息不存在" |
| API-17 | PUT /public/mine/children/:id | 更新信息 | 200，字段更新成功 |
| API-18 | DELETE /public/mine/children/:id | 删除 | 200，is_deleted 置为 1（软删除） |
| API-19 | GET /public/mine/children | 删除后列表 | 200，已删除的子女不出现 |
| API-20 | DELETE /public/mine/children/:id | 非自己的子女 | 404 |

### 2.3 活动浏览 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-21 | GET /public/activities | 无需登录获取列表 | 200，仅返回 visibility=public 或 targeted 的已发布活动 |
| API-22 | GET /public/activities | 关键词搜索 | `?keyword=绘本` → 过滤结果 |
| API-23 | GET /public/activities | 分页 | `?page=1&pageSize=5` → 正确分页 |
| API-24 | GET /public/activities | 类型筛选 | `?contestType=individual` → 仅返回个人参与类型 |
| API-25 | GET /public/activities | 未发布活动不可见 | contestState='unpublished' 的活动不出现 |
| API-26 | GET /public/activities | visibility=internal 不可见 | 仅内部活动不出现在公众列表 |
| API-27 | GET /public/activities | visibility=designated 不可见 | 指定机构活动不出现 |
| API-28 | GET /public/activities/:id | 正常获取详情 | 200，含 attachments 和 notices |
| API-29 | GET /public/activities/:id | 不存在的活动 | 404，"活动不存在或未公开" |
| API-30 | GET /public/activities/:id | 未发布的活动 | 404 |

### 2.4 定向推送 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-31 | GET /public/activities | targeted+城市匹配 | 用户 city='广州'，活动 target_cities=['广州','深圳'] → 可见 |
| API-32 | GET /public/activities | targeted+城市不匹配 | 用户 city='北京'，活动 target_cities=['广州'] → 不可见 |
| API-33 | GET /public/activities | targeted+子女城市匹配 | 用户无城市但子女 city='广州' → 可见 |
| API-34 | GET /public/activities | targeted+未登录 | targeted 活动对未登录用户不可见 |
| API-35 | GET /public/activities | targeted+无城市限制 | target_cities 为空但有年龄限制 → 所有登录用户可见 |

### 2.5 活动报名 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-36 | POST /public/activities/:id/register | 自己报名 | `{"participantType":"self"}` → 200 |
| API-37 | POST /public/activities/:id/register | 代子女报名 | `{"participantType":"child","childId":1}` → 200 |
| API-38 | POST /public/activities/:id/register | 重复报名（自己） | 409，"您已报名此活动" |
| API-39 | POST /public/activities/:id/register | 重复报名（同一子女） | 409，"该子女已报名此活动" |
| API-40 | POST /public/activities/:id/register | 不同子女同一活动 | 200，允许不同子女分别报名 |
| API-41 | POST /public/activities/:id/register | 代子女但不传 childId | 400，"代子女报名时必须选择子女" |
| API-42 | POST /public/activities/:id/register | 非自己的子女 | 404，"子女信息不存在" |
| API-43 | POST /public/activities/:id/register | 不在报名时间范围内 | 400，"当前不在报名时间范围内" |
| API-44 | POST /public/activities/:id/register | 活动不存在或未公开 | 404 |
| API-45 | POST /public/activities/:id/register | 年龄不符合（太小） | 400，"参与者年龄不符合要求（最低 X 岁）" |
| API-46 | POST /public/activities/:id/register | 年龄不符合（太大） | 400，"参与者年龄不符合要求（最高 X 岁）" |
| API-47 | POST /public/activities/:id/register | 年龄符合 | 200，正常报名 |
| API-48 | POST /public/activities/:id/register | 未登录 | 401 |

### 2.6 作品提交 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-49 | GET /public/activities/:id/my-registration | 已报名已通过 | 200，返回报名记录含 contest 信息 |
| API-50 | GET /public/activities/:id/my-registration | 未报名 | 200，返回 null |
| API-51 | POST /public/activities/:id/submit-work | 正常提交 | `{"registrationId":1,"title":"我的绘本"}` → 200，生成 workNo |
| API-52 | POST /public/activities/:id/submit-work | 报名未通过 | 400，"报名未通过审核" |
| API-53 | POST /public/activities/:id/submit-work | 不在提交时间 | 400，"当前不在作品提交时间范围内" |
| API-54 | POST /public/activities/:id/submit-work | submitRule=once 重复提交 | 409，"该活动只允许提交一次作品" |
| API-55 | POST /public/activities/:id/submit-work | 非自己的报名记录 | 404，"报名记录不存在" |
| API-56 | POST /public/activities/:id/submit-work | 带附件提交 | attachments 数组正确创建 |

### 2.7 我的数据 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-57 | GET /public/mine/registrations | 正常获取 | 200，含 contest 和 child 关联信息 |
| API-58 | GET /public/mine/registrations | 分页 | `?page=1&pageSize=5` → 正确分页 |
| API-59 | GET /public/mine/works | 正常获取 | 200，含 contest、registration.child、attachments |
| API-60 | GET /public/mine/profile | 含子女信息 | 200，包含 children 数组和 childrenCount |

### 2.8 公众用户管理 API（超管端）

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-61 | GET /public/users | 仅返回自注册用户 | user_source='self_registered' 的用户 |
| API-62 | GET /public/users | 关键词搜索 | 搜索用户名/昵称/手机号/城市 |
| API-63 | GET /public/users/:id | 详情含子女和报名 | 返回 children 数组 + contestRegistrations |
| API-64 | GET /public/users/:id | 非自注册用户 | 404，"公众用户不存在" |

### 2.9 管理端认证 API

| 编号 | 接口 | 测试场景 | 预期 |
|------|------|---------|------|
| API-65 | POST /auth/login | 超管登录 | `{"username":"admin","password":"admin@super","tenantCode":"super"}` → 200 |
| API-66 | POST /auth/login | 广东省图登录 | `{"username":"admin","password":"admin@gdlib","tenantCode":"gdlib"}` → 200 |
| API-67 | POST /auth/login | 评委登录 | `{"username":"admin","password":"admin@judge","tenantCode":"judge"}` → 200 |
| API-68 | POST /auth/login | 错误租户编码 | `{"tenantCode":"nonexist"}` → 401，"租户不存在" |
| API-69 | GET /auth/user-info | 获取用户信息 | 200，含 roles 和 permissions |

---

## 三、前端测试

### 3.1 公众端（/p/）

#### 3.1.1 登录/注册页

| 编号 | 测试场景 | 操作步骤 | 预期结果 |
|------|---------|---------|---------|
| FE-01 | 默认填充 | 打开 /p/login | 用户名 demo，密码 demo123456 已填充 |
| FE-02 | 登录成功 | 点击登录 | 跳转到 /p/activities |
| FE-03 | 登录失败 | 输入错误密码 → 登录 | 提示"用户名或密码错误" |
| FE-04 | 切换注册 | 点击"立即注册" | 表单切换为注册模式，显示昵称和确认密码 |
| FE-05 | 注册成功 | 填写完整注册信息 → 提交 | 提示"注册成功"，自动登录跳转 |
| FE-06 | 注册校验 | 用户名 2 位/密码 3 位 | 表单校验错误提示 |
| FE-07 | 管理端入口 | 点击底部"平台超管" | 跳转到 /super/login |
| FE-08 | 管理端入口 | 点击"广东省图" | 跳转到 /gdlib/login |
| FE-09 | 管理端入口 | 点击"评委端" | 跳转到 /judge/login |

#### 3.1.2 活动大厅

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-10 | 无需登录访问 | /p/activities 正常打开，显示活动卡片 |
| FE-11 | 搜索功能 | 输入关键词 → 过滤活动 |
| FE-12 | 空状态 | 无公开活动时显示"暂无公开活动" |
| FE-13 | 卡片信息 | 显示封面/名称/时间/类型标签/阶段标签 |
| FE-14 | 年龄标签 | 有年龄限制的活动显示"3-12岁"标签 |
| FE-15 | 点击卡片 | 跳转到活动详情页 |

#### 3.1.3 活动详情页

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-16 | 封面/Placeholder | 有封面显示图片，无封面显示渐变色+首字 |
| FE-17 | 阶段徽章 | 正确显示即将开始/报名中/提交中/评审中/已结束 |
| FE-18 | 报名中+未登录 | 显示"登录后报名"按钮 |
| FE-19 | 报名中+已登录+未报名 | 显示"立即报名"按钮 |
| FE-20 | 报名中+已报名 | 显示"已报名，等待提交阶段" |
| FE-21 | 提交中+已报名 | 显示"提交作品"按钮 |
| FE-22 | 提交中+已提交 | 显示"作品已提交" |
| FE-23 | 评审中 | 显示"评审中，请耐心等待" |
| FE-24 | 已结束 | 显示"查看成果"按钮 |
| FE-25 | 报名弹窗 | 点击报名 → 显示参与者选择（自己+子女列表） |
| FE-26 | 报名弹窗-无子女 | 只显示"我自己" |
| FE-27 | 报名弹窗-有子女 | 显示"我自己"+ 所有子女（姓名+年级） |
| FE-28 | 报名弹窗-添加子女链接 | 点击"添加新的子女"跳转到子女管理 |
| FE-29 | 作品提交弹窗 | 点击提交作品 → 显示标题+描述+文件上传表单 |
| FE-30 | 活动详情 Tab | 显示富文本内容 |
| FE-31 | 活动公告 Tab | 显示公告列表或"暂无公告" |
| FE-32 | 成果 Tab | 活动成果发布后显示此 Tab |
| FE-33 | 年龄要求展示 | 有年龄限制时显示"年龄要求：X-Y 岁" |
| FE-34 | 目标城市展示 | targeted 活动显示"面向城市：广州、深圳" |
| FE-35 | 返回按钮 | 点击"返回"回到上一页 |

#### 3.1.4 个人中心

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-36 | 用户卡片 | 显示头像（首字母）+昵称+城市 |
| FE-37 | 编辑按钮 | 点击"编辑"打开弹窗 |
| FE-38 | 编辑保存 | 修改昵称+城市 → 保存成功 → 卡片刷新 |
| FE-39 | 报名数量 | 显示"N 个活动"或"查看已报名的活动" |
| FE-40 | 作品数量 | 显示"N 个作品"或"管理提交的作品" |
| FE-41 | 子女数量 | 显示"已添加 N 个子女"或"添加子女信息" |
| FE-42 | 退出登录 | 点击退出 → 清除 token → 跳转登录页 |

#### 3.1.5 子女管理

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-43 | 空状态 | 无子女时显示空状态+添加按钮 |
| FE-44 | 添加子女 | 点击添加 → 弹窗 → 填写信息 → 保存成功 |
| FE-45 | 子女卡片 | 显示姓名+年龄+年级+城市+学校（标签形式） |
| FE-46 | 编辑子女 | 点击编辑 → 弹窗回显数据 → 修改保存 |
| FE-47 | 删除子女 | 点击删除 → 确认弹窗 → 删除成功 |
| FE-48 | 年龄计算 | 根据生日自动计算并显示"X 岁" |

#### 3.1.6 我的报名

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-49 | 报名列表 | 显示活动封面+名称+状态标签+参与者类型 |
| FE-50 | 参与者标识 | 自己报名显示"本人参与"，子女显示"子女：小明" |
| FE-51 | 提交作品按钮 | 报名通过+提交阶段 → 显示"提交作品"按钮 |
| FE-52 | 点击跳转 | 点击卡片跳转到活动详情 |

#### 3.1.7 响应式适配

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-53 | 手机宽度(375px) | 底部 Tab 显示，顶部导航精简 |
| FE-54 | 平板宽度(768px) | 底部 Tab 隐藏，顶部导航显示 |
| FE-55 | 活动卡片网格 | 手机 1 列，平板 2 列，PC 3-4 列 |
| FE-56 | 作品网格 | 手机 2 列，PC 自适应 |

### 3.2 管理端登录页

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-57 | 快捷切换标签 | 显示 3 个：平台超管、广东省图、评委端 |
| FE-58 | 点击标签自动填充 | 点击"广东省图"自动填充 admin/admin@gdlib |
| FE-59 | URL 自动识别 | 访问 /gdlib/login → 自动绑定广东省图 |
| FE-60 | 副标题显示 | 显示"广东省立中山图书馆 — 管理端登录" |
| FE-61 | 公众端入口 | 底部显示"参与活动？前往公众端"链接 |

### 3.3 超管端（/super/）

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-62 | 菜单结构 | 4 个一级菜单：活动监管、机构管理、用户中心、系统设置 |
| FE-63 | 活动监管-全部活动 | 显示主办方、可见范围、报名数、作品数、评委数列 |
| FE-64 | 活动监管-可见范围筛选 | 筛选公开/定向推送/指定机构/仅内部 |
| FE-65 | 活动监管-定向推送标签 | 橙色标签，hover 显示城市和年龄条件 |
| FE-66 | 活动监管-无创建按钮 | 超管端不显示"创建活动"按钮 |
| FE-67 | 报名数据 | 显示主办单位列 |
| FE-68 | 作品数据 | 显示主办机构列 |
| FE-69 | 评审进度 | 显示主办机构列 |
| FE-70 | 成果发布 | 显示主办机构列+发布状态列 |
| FE-71 | 通知管理 | 只读（无创建/编辑/删除按钮） |
| FE-72 | 机构管理 | 机构列表：名称+编码+类型(彩色标签)+用户角色数+状态+操作 |
| FE-73 | 机构管理-搜索 | 按名称/编码搜索，按类型筛选 |
| FE-74 | 机构管理-添加 | 弹窗：机构名称+编码+类型+描述，编码自动提示登录地址 |
| FE-75 | 机构管理-菜单分配 | 第二个 Tab "功能菜单"，勾选分配 |
| FE-76 | 机构管理-隐藏 public | 列表中不显示"公众用户"租户 |
| FE-77 | 用户中心-公众用户 | 列表：头像+昵称+手机号+城市+子女数+报名数+状态 |
| FE-78 | 用户中心-公众用户详情 | 抽屉：基本信息+子女列表+报名记录 |
| FE-79 | 用户中心-平台用户 | 管理超管团队内部用户 |
| FE-80 | 用户中心-角色管理 | 管理超管端角色 |

### 3.4 广东省图管理端（/gdlib/）

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-81 | 菜单结构 | 2 个一级菜单：活动管理(8 子)、系统设置(3 子) |
| FE-82 | 创建活动 | 表单含可见范围（公开/定向推送/指定机构/仅内部） |
| FE-83 | 定向推送配置 | 选择"定向推送"→ 展开城市输入+年龄范围 |
| FE-84 | 年龄限制 | 公开和定向推送都可设置年龄范围 |
| FE-85 | 报名管理-参与方式列 | 显示"本人参与"或"代子女报名"+子女姓名 |
| FE-86 | 系统设置 | 仅含用户管理、角色管理、日志记录（无菜单/权限/字典/配置/租户） |

### 3.5 评委端（/judge/）

| 编号 | 测试场景 | 预期结果 |
|------|---------|---------|
| FE-87 | 登录不卡死 | 登录后正确跳转到评审任务页（非死循环） |
| FE-88 | 菜单结构 | 1 个一级菜单：我的评审(评审任务+预设评语) |
| FE-89 | 评审任务 | 显示参与评审的活动列表+进度条+完成状态 |
| FE-90 | 进入评审 | 点击"进入评审"跳转到评审工作台 |
| FE-91 | 评审工作台 | 显示分配的作品列表+搜索+筛选(已评/未评) |
| FE-92 | 预设评语 | 管理评语模板列表 |

---

## 四、全链路端到端测试

### 4.1 流程一：公众用户完整参与流程

```
步骤 1: 公众端注册 → /p/login 注册新用户
步骤 2: 添加子女 → /p/mine/children 添加一个子女
步骤 3: 浏览活动 → /p/activities 看到广东省图的活动
步骤 4: 报名活动 → 选择"子女"作为参与者 → 确认报名
步骤 5: 等待审核 → 我的报名显示"待审核"
步骤 6: [切换到广东省图管理端] → 报名管理 → 看到该报名记录 → 显示"代子女报名"
步骤 7: [广东省图管理端] → 审核通过
步骤 8: [切回公众端] → 我的报名显示"已通过" → 出现"提交作品"按钮
步骤 9: 提交作品 → 填写标题+描述 → 提交成功
步骤 10: [广东省图管理端] → 作品管理 → 看到提交的作品
```

**验证点：** 跨端数据一致性、参与者类型传递、审核状态流转

### 4.2 流程二：定向推送活动

```
步骤 1: [广东省图管理端] 创建活动 → 可见范围=定向推送 → 城市=广州 → 年龄=6-12岁
步骤 2: [公众端-广州用户] 活动大厅能看到该活动
步骤 3: [公众端-北京用户] 活动大厅看不到该活动
步骤 4: [公众端-广州用户] 报名 → 选择 5 岁子女 → 报错"年龄不符合"
步骤 5: [公众端-广州用户] 报名 → 选择 8 岁子女 → 成功
```

**验证点：** 城市过滤、年龄校验、子女城市匹配

### 4.3 流程三：评审完整流程

```
步骤 1: [广东省图管理端] 创建活动+发布
步骤 2: [广东省图管理端] 评委管理 → 添加评委
步骤 3: [公众端] 报名+提交作品
步骤 4: [广东省图管理端] 审核报名通过
步骤 5: [广东省图管理端] 评审进度 → 分配作品给评委
步骤 6: [评委端] 评审任务 → 看到该活动 → 进入评审
步骤 7: [评委端] 给作品打分+写评语
步骤 8: [广东省图管理端] 评审进度 → 查看评审完成率
步骤 9: [广东省图管理端] 成果发布 → 发布成果
步骤 10: [公众端] 活动详情 → 看到"成果"Tab
```

**验证点：** 评委分配、评分数据流转、成果发布到公众端可见

### 4.4 流程四：超管监管视角

```
步骤 1: [超管端] 活动监管 → 全部活动 → 看到所有机构的活动
步骤 2: [超管端] 可见范围筛选 → 筛选"定向推送"类型
步骤 3: [超管端] 报名数据 → 看到各活动报名人数
步骤 4: [超管端] 用户中心 → 公众用户 → 看到自注册用户列表
步骤 5: [超管端] 公众用户详情 → 看到子女信息+报名记录
步骤 6: [超管端] 机构管理 → 看到广东省图（类型=图书馆）
```

**验证点：** 跨机构数据可见性、公众用户管理、机构类型展示

---

## 五、测试数据准备

### 5.1 必需的测试活动

在广东省图管理端创建以下活动：

| 活动名称 | 可见范围 | 城市 | 年龄 | 报名时间 | 提交时间 |
|---------|---------|------|------|---------|---------|
| 全国少儿绘本创作大赛 | 公开 | - | 3-16 | 当前时间内 | 报名后 |
| 广州绘本工作坊 | 定向推送 | 广州,深圳 | 6-12 | 当前时间内 | 报名后 |
| 内部测试活动 | 仅内部 | - | - | 当前时间内 | 报名后 |

### 5.2 必需的测试用户

| 用户 | 城市 | 子女 | 用途 |
|------|------|------|------|
| 广州家长 | 广州 | 8 岁+5 岁 | 测试定向推送+年龄校验 |
| 北京家长 | 北京 | 10 岁 | 测试城市不匹配 |
| 独立少年 | 广州 | 无 | 测试自己报名 |

---

## 六、执行优先级

| 优先级 | 类别 | 编号范围 | 说明 |
|--------|------|---------|------|
| P0 | 全链路 | 4.1-4.4 | 业务流程必须走通 |
| P0 | 认证 | API-01~10, FE-01~09 | 登录注册基础功能 |
| P0 | 报名 | API-36~48, FE-18~28 | 核心业务流程 |
| P1 | 定向推送 | API-31~35, FE-83~84 | 新功能验证 |
| P1 | 作品提交 | API-49~56, FE-29 | 核心流程完整性 |
| P1 | 数据库 | DB-01~23 | 数据完整性保障 |
| P2 | 管理端 | FE-62~86 | 管理端适配验证 |
| P2 | 响应式 | FE-53~56 | H5 适配 |
