# 功能模块设计

## 1. 模块总览

### 一期功能（三周内完成）

| 模块 | 优先级 | 说明 |
|------|--------|------|
| 公众端注册/登录 | P0 | 用户名+密码方式自主注册和登录 |
| 公众端活动大厅 | P0 | 浏览公开活动列表，查看活动详情 |
| 子女管理 | P0 | 添加/编辑/删除子女信息 |
| 活动报名 | P0 | 选择参与者（自己/子女）并报名 |
| 作品提交 | P0 | 上传绘本作品（图片/PDF） |
| 个人中心 | P0 | 个人信息、报名记录、作品列表 |
| 租户类型字段 | P0 | 租户新增类型分类 |
| 活动可见范围 | P0 | 新增"公开"选项 |
| 管理端适配 | P0 | 报名记录展示参与者类型和子女信息 |

### 二期功能

| 模块 | 说明 |
|------|------|
| 手机号验证码登录 | 短信服务集成 |
| 微信扫码登录 | 微信开放平台 OAuth |
| 一号多身份切换 | 同一账号在公众端和管理端切换 |
| 多机构联合举办 | 主办+协办模式 |

---

## 2. 公众端注册与登录

> **实现说明**：登录与注册合并为同一页面 `/p/login`，通过 `isRegister` 标志切换表单。公众用户归属公众租户（code='public', tenantId=8），而非 tenant_id 为 NULL。

### 2.1 登录/注册页面（合一）

**路由**：`/p/login`

**注册表单字段**：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 用户名 | 文本输入 | 是 | 4-20位字母数字下划线 |
| 密码 | 密码输入 | 是 | 6-20位，至少包含字母和数字 |
| 确认密码 | 密码输入 | 是 | 与密码一致 |
| 昵称 | 文本输入 | 是 | 2-20位，显示在界面上的名字 |
| 手机号 | 文本输入 | 否 | 预留字段，二期用于验证码登录 |
| 所在城市 | 文本输入 | 否 | 便于活动统计 |

**登录表单字段**：
- 用户名 / 手机号
- 密码

**交互逻辑**：
1. 页面底部有"切换到注册/切换到登录"链接，通过 `isRegister` 标志切换
2. 注册：前端校验 → 提交注册 → 后端创建用户（user_source = 'self_registered', 归属 public 租户）→ 自动登录 → 跳转活动大厅
3. 登录：公众用户登录不需要填写租户编码 → 后端在公众租户中查找匹配用户 → 登录成功 → 跳转活动大厅

### 2.3 与现有登录的关系

```
登录入口：
├── /p/login              → 公众端登录（无需租户编码）
└── /:tenantCode/login    → 管理端登录（现有，需要租户编码）

两套登录页面独立，共用同一个 Auth API（后端区分来源）
```

---

## 3. 公众端活动大厅

### 3.1 活动列表页

**路由**：`/p/activities`

**页面元素**：
- 顶部：搜索框（按活动名称搜索）
- 筛选：活动状态（报名中/进行中/已结束）
- 列表：活动卡片网格展示

**活动卡片信息**：
```
┌─────────────────────────┐
│  [活动封面图]             │
│  ┌─报名中─┐  ┌个人参与┐  │
├─────────────────────────┤
│  活动名称                │
│  主办：广东省立中山图书馆  │
│  报名时间：xx - xx       │
│  [查看详情]              │
└─────────────────────────┘
```

**数据来源**：
- 调用 `/api/public/activities` 接口
- 仅返回 `visibility = 'public'` 且 `contest_state = 'published'` 的活动
- 未登录用户也能浏览列表，但报名需要登录

### 3.2 活动详情页

**路由**：`/p/activities/:id`

**页面结构**：
```
┌─────────────────────────────────┐
│         活动封面/海报            │
├─────────────────────────────────┤
│  活动名称                       │
│  主办单位  |  活动类型  |  状态   │
├─────────────────────────────────┤
│  Tab: [活动详情] [活动公告] [成果] │
├─────────────────────────────────┤
│  活动详情内容（富文本）           │
│  附件下载                       │
├─────────────────────────────────┤
│  [立即报名] / [提交作品] 按钮    │
│  （根据活动阶段动态显示）         │
└─────────────────────────────────┘
```

**按钮状态逻辑**：

| 活动阶段 | 未登录 | 已登录未报名 | 已登录已报名 |
|---------|--------|------------|------------|
| 报名阶段 | 登录后报名 | 立即报名 | 已报名 |
| 提交阶段 | 登录查看 | - | 提交作品 |
| 评审阶段 | - | - | 评审中 |
| 已结束 | 查看成果 | 查看成果 | 查看成果 |

---

## 4. 子女管理

### 4.1 子女列表页

**路由**：`/p/mine/children`

**页面元素**：
- 子女卡片列表
- "添加子女"按钮

**子女卡片**：
```
┌─────────────────────────┐
│  [头像]  小明             │
│  8岁 | 三年级 | 广州      │
│  XX小学                  │
│  [编辑]  [删除]          │
└─────────────────────────┘
```

### 4.2 添加/编辑子女

**弹窗表单字段**：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 姓名 | 文本 | 是 | 子女真实姓名 |
| 性别 | 选择 | 否 | 男/女 |
| 出生日期 | 日期选择 | 否 | 用于自动计算年龄 |
| 年级 | 文本/选择 | 否 | 如：大班、一年级 |
| 所在城市 | 文本 | 否 | |
| 学校/幼儿园 | 文本 | 否 | 手动填写 |

### 4.3 删除保护

- 如果子女有关联的报名记录，提示"该子女有 N 个活动报名记录，删除后历史数据中将显示为'已删除子女'"
- 使用软删除（is_deleted = 1），不物理删除

---

## 5. 活动报名

### 5.1 报名流程

```
步骤1：选择参与者
├── 系统检测用户是否有子女
├── 无子女 → 跳过此步，以自己身份报名
└── 有子女 → 显示参与者选择页面
             ○ 我自己
             ○ 子女A（姓名，年龄）
             ○ 子女B（姓名，年龄）
             ＋ 添加新的子女

步骤2：填写报名信息
├── 参与者基本信息（自动带入，可编辑）
│   ├── 自己报名：显示用户昵称、城市
│   └── 子女报名：显示子女姓名、年龄、学校
├── 活动要求的附加信息（由活动定义，如：创作主题选择）
└── 指导老师信息（可选）

步骤3：确认提交
├── 确认报名信息
└── 提交 → 等待审核（如果活动开启了审核）/ 直接通过
```

### 5.2 报名数据存储

```
registrations 表记录：
├── user_id = 操作人（家长或独立参与者）
├── contest_id = 活动 ID
├── participant_type = 'self' 或 'child'
├── child_id = 子女 ID（仅 child 类型）
├── status = 审核状态
└── 其他现有字段不变
```

### 5.3 重复报名检测

- 同一用户不能以"自己"身份重复报名同一活动
- 同一子女不能被重复报名同一活动（通过 child_id 去重）
- 不同子女可以分别报名同一活动

---

## 6. 作品提交

### 6.1 提交页面

**路由**：`/p/activities/:id/submit`

**前置条件**：
- 用户已登录
- 用户/子女已报名该活动且报名状态为"通过"
- 活动处于"提交阶段"

**表单字段**：

| 字段 | 类型 | 必填 | 说明 |
|------|------|------|------|
| 作品名称 | 文本 | 是 | 绘本作品标题 |
| 作品描述 | 多行文本 | 否 | 创作说明 |
| 作品文件 | 文件上传 | 是 | 支持图片（JPG/PNG）和 PDF |
| 封面图 | 图片上传 | 否 | 作品封面，用于列表展示 |

### 6.2 与现有作品模块的关系

复用现有 works 表和上传逻辑，新增关联：
- 如果是子女报名，作品记录关联 child_id（通过 registration 关联）
- 管理端查看作品时，能看到实际创作者（子女）的信息

---

## 7. 个人中心

### 7.1 个人中心首页

**路由**：`/p/mine`

**页面结构**：
```
┌─────────────────────────┐
│  [头像]  昵称             │
│  手机号  |  城市           │
│  [编辑个人信息]           │
├─────────────────────────┤
│  📋 我的报名（N）         │
│  🎨 我的作品（N）         │
│  👶 子女管理（N）         │
└─────────────────────────┘
```

### 7.2 我的报名

**路由**：`/p/mine/registrations`

**列表项信息**：
```
┌─────────────────────────────────┐
│  [活动封面]                      │
│  活动名称                        │
│  参与者：我自己 / 子女：小明       │
│  报名时间：2026-04-01            │
│  状态：待审核 / 已通过 / 已拒绝   │
│  [查看详情] [提交作品]            │
└─────────────────────────────────┘
```

### 7.3 我的作品

**路由**：`/p/mine/works`

展示该用户提交的所有作品（包括代子女提交的）。

---

## 8. 管理端适配

### 8.1 活动创建改造

**活动创建表单新增字段**：

```
活动可见范围：
○ 公开（所有注册用户可见）
○ 指定机构（选择机构列表）
○ 仅内部
```

当选择"公开"时，`contest_tenants` 字段不需要填写。

### 8.2 报名管理改造

**报名记录表格新增列**：

| 列名 | 说明 |
|------|------|
| 报名人 | user.nickname（操作人） |
| 参与者 | 自己报名显示用户名；子女报名显示"子女：小明" |
| 参与方式 | 自己 / 代子女报名 |

**筛选条件新增**：
- 参与方式：全部 / 自己报名 / 代子女报名

### 8.3 租户管理改造

**租户列表新增列**：
- 租户类型：图书馆 / 幼儿园 / 学校 / 社会机构 / 其他

**租户创建表单新增字段**：
- 租户类型（下拉选择）
