一、超管端设计优化 - 文档管理SOP体系建立,docs目录重组 - 统一用户管理:跨租户全局视角,合并用户管理+公众用户 - 活动监管全模块重构:全部活动(统计卡片+阶段筛选+SuperDetail详情页)、报名数据/作品数据/评审进度(两层合一扁平列表)、成果发布(去Tab+统计+隐藏写操作) - 菜单精简:移除评委管理/评审规则/通知管理 - Bug修复:租户编辑丢失隐藏菜单、pageSize限制、主色统一 二、UGC绘本创作社区P0 - 数据库:10张新表(user_works/user_work_pages/work_tags等) - 子女账号独立化:Child升级为独立User,家长切换+独立登录 - 用户作品库:CRUD+发布审核,8个API - AI创作流程:提交→生成→保存到作品库,4个API - 作品广场:首页改造为推荐流,标签+搜索+排序 - 内容审核(超管端):作品审核+作品管理+标签管理 - 活动联动:WorkSelector作品选择器 - 布局改造:底部5Tab(发现/创作/活动/作品库/我的) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
300 lines
13 KiB
Markdown
300 lines
13 KiB
Markdown
# 数据库设计
|
||
|
||
## 1. 变更概览
|
||
|
||
| 操作 | 表名 | 说明 |
|
||
|------|------|------|
|
||
| 修改 | `users` | 新增 phone、wx_openid、user_source、city 等字段 |
|
||
| 修改 | `tenants` | 新增 tenant_type 字段 |
|
||
| 修改 | `registrations` | 新增 participant_type、child_id 字段 |
|
||
| 修改 | `contests` | 新增 visibility 字段 |
|
||
| 新增 | `children` | 子女信息表 |
|
||
| 新增(二期) | `user_identities` | 用户身份表(一号多身份) |
|
||
| 新增(二期) | `contest_co_organizers` | 活动协办机构表 |
|
||
|
||
---
|
||
|
||
## 2. 表结构详细设计
|
||
|
||
### 2.1 users 表(改造)
|
||
|
||
新增字段:
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `phone` | VARCHAR(20) | 否 | NULL | 手机号,全局唯一,用于手机号登录 |
|
||
| `wx_openid` | VARCHAR(64) | 否 | NULL | 微信 OpenID,全局唯一 |
|
||
| `wx_unionid` | VARCHAR(64) | 否 | NULL | 微信 UnionID,跨应用统一标识 |
|
||
| `user_source` | ENUM | 否 | 'admin_created' | 用户来源:admin_created / self_registered |
|
||
| `city` | VARCHAR(50) | 否 | NULL | 所在城市 |
|
||
| `birthday` | DATE | 否 | NULL | 出生日期(自注册用户可填写) |
|
||
|
||
```sql
|
||
-- 新增字段
|
||
ALTER TABLE users ADD COLUMN phone VARCHAR(20) UNIQUE DEFAULT NULL COMMENT '手机号';
|
||
ALTER TABLE users ADD COLUMN wx_openid VARCHAR(64) UNIQUE DEFAULT NULL COMMENT '微信OpenID';
|
||
ALTER TABLE users ADD COLUMN wx_unionid VARCHAR(64) DEFAULT NULL COMMENT '微信UnionID';
|
||
ALTER TABLE users ADD COLUMN user_source VARCHAR(20) NOT NULL DEFAULT 'admin_created' COMMENT '用户来源:admin_created/self_registered';
|
||
ALTER TABLE users ADD COLUMN city VARCHAR(50) DEFAULT NULL COMMENT '所在城市';
|
||
ALTER TABLE users ADD COLUMN birthday DATE DEFAULT NULL COMMENT '出生日期';
|
||
|
||
-- 索引
|
||
CREATE INDEX idx_users_phone ON users(phone);
|
||
CREATE INDEX idx_users_wx_openid ON users(wx_openid);
|
||
CREATE INDEX idx_users_user_source ON users(user_source);
|
||
```
|
||
|
||
**设计说明**:
|
||
- `phone` 设为 UNIQUE 但允许 NULL,因为管理员创建的机构用户可能没有手机号
|
||
- `wx_openid` 和 `wx_unionid` 为二期微信登录预留
|
||
- `user_source` 区分用户是管理员创建的还是自主注册的,方便后台统计和管理
|
||
- 自注册用户归属公众租户(code='public', tenantId=8),而非 tenant_id 为 NULL,以兼容现有 JWT 认证链路
|
||
|
||
---
|
||
|
||
### 2.2 children 表(新增)
|
||
|
||
子女信息表,关联家长账号。
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `id` | INT | 是 | AUTO_INCREMENT | 主键 |
|
||
| `parent_id` | INT | 是 | - | 家长用户 ID,关联 users.id |
|
||
| `name` | VARCHAR(50) | 是 | - | 子女姓名 |
|
||
| `gender` | VARCHAR(10) | 否 | NULL | 性别:male / female |
|
||
| `birthday` | DATE | 否 | NULL | 出生日期 |
|
||
| `grade` | VARCHAR(20) | 否 | NULL | 年级(如:大班、一年级) |
|
||
| `city` | VARCHAR(50) | 否 | NULL | 所在城市 |
|
||
| `school_name` | VARCHAR(100) | 否 | NULL | 学校/幼儿园名称(手动填写) |
|
||
| `avatar` | VARCHAR(500) | 否 | NULL | 头像 URL |
|
||
| `is_deleted` | TINYINT(1) | 否 | 0 | 软删除标记 |
|
||
| `create_time` | DATETIME | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||
| `modify_time` | DATETIME | 否 | CURRENT_TIMESTAMP | 修改时间 |
|
||
|
||
```sql
|
||
CREATE TABLE children (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
parent_id INT NOT NULL COMMENT '家长用户ID',
|
||
name VARCHAR(50) NOT NULL COMMENT '子女姓名',
|
||
gender VARCHAR(10) DEFAULT NULL COMMENT '性别:male/female',
|
||
birthday DATE DEFAULT NULL COMMENT '出生日期',
|
||
grade VARCHAR(20) DEFAULT NULL COMMENT '年级',
|
||
city VARCHAR(50) DEFAULT NULL COMMENT '所在城市',
|
||
school_name VARCHAR(100) DEFAULT NULL COMMENT '学校/幼儿园名称',
|
||
avatar VARCHAR(500) DEFAULT NULL COMMENT '头像URL',
|
||
is_deleted TINYINT(1) NOT NULL DEFAULT 0 COMMENT '软删除标记',
|
||
create_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
modify_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
|
||
INDEX idx_children_parent_id (parent_id),
|
||
CONSTRAINT fk_children_parent FOREIGN KEY (parent_id) REFERENCES users(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='子女信息表';
|
||
```
|
||
|
||
**设计说明**:
|
||
- `parent_id` 关联 users 表,一个家长可以有多个子女
|
||
- `school_name` 是手动填写的文本字段,不关联租户表,因为公众用户的学校不一定是平台上的租户
|
||
- `grade` 存储文本如"大班""一年级",不做枚举约束,因为不同教育体系的年级名称不同
|
||
- 使用软删除(`is_deleted`),避免误删导致历史报名数据关联丢失
|
||
|
||
---
|
||
|
||
### 2.3 tenants 表(改造)
|
||
|
||
新增字段:
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `tenant_type` | VARCHAR(20) | 否 | 'other' | 租户类型 |
|
||
|
||
```sql
|
||
ALTER TABLE tenants ADD COLUMN tenant_type VARCHAR(20) NOT NULL DEFAULT 'other'
|
||
COMMENT '租户类型:platform/library/kindergarten/school/institution/other';
|
||
|
||
CREATE INDEX idx_tenants_type ON tenants(tenant_type);
|
||
```
|
||
|
||
**租户类型枚举值**:
|
||
|
||
| 值 | 说明 |
|
||
|----|------|
|
||
| `platform` | 平台租户(乐绘世界,全局唯一) |
|
||
| `library` | 图书馆 |
|
||
| `kindergarten` | 幼儿园 |
|
||
| `school` | 学校 |
|
||
| `institution` | 社会机构 |
|
||
| `other` | 其他 |
|
||
|
||
---
|
||
|
||
### 2.4 registrations 表(改造)
|
||
|
||
新增字段:
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `participant_type` | VARCHAR(10) | 否 | 'self' | 参与者类型:self(自己)/ child(子女) |
|
||
| `child_id` | INT | 否 | NULL | 子女 ID,participant_type 为 child 时必填 |
|
||
|
||
```sql
|
||
ALTER TABLE registrations ADD COLUMN participant_type VARCHAR(10) NOT NULL DEFAULT 'self'
|
||
COMMENT '参与者类型:self-自己/child-代子女报名';
|
||
ALTER TABLE registrations ADD COLUMN child_id INT DEFAULT NULL
|
||
COMMENT '子女ID,代子女报名时填写';
|
||
|
||
CREATE INDEX idx_registrations_participant ON registrations(participant_type);
|
||
CREATE INDEX idx_registrations_child ON registrations(child_id);
|
||
```
|
||
|
||
**设计说明**:
|
||
- `user_id`(现有字段)始终记录操作人(谁提交的报名)
|
||
- `participant_type = 'self'`:用户以自己身份报名,`child_id` 为 NULL
|
||
- `participant_type = 'child'`:家长代子女报名,`child_id` 指向 children 表
|
||
- 管理端查看报名记录时,能清晰区分"张妈妈帮小明报名"和"李同学自己报名"
|
||
|
||
---
|
||
|
||
### 2.5 contests 表(改造)
|
||
|
||
新增字段:
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `visibility` | VARCHAR(20) | 否 | 'designated' | 活动可见范围 |
|
||
|
||
```sql
|
||
ALTER TABLE contests ADD COLUMN visibility VARCHAR(20) NOT NULL DEFAULT 'designated'
|
||
COMMENT '可见范围:public-公开/designated-指定机构/internal-仅内部';
|
||
```
|
||
|
||
**可见范围说明**:
|
||
|
||
| 值 | 说明 | 数据过滤逻辑 |
|
||
|----|------|-------------|
|
||
| `public` | 全体公开 | 所有注册用户可见,公众端活动大厅展示 |
|
||
| `designated` | 指定机构 | 仅 contest_tenants 中列出的租户可见(现有逻辑) |
|
||
| `internal` | 仅内部 | 仅创建该活动的机构内部可见 |
|
||
|
||
---
|
||
|
||
### 2.6 user_identities 表(二期新增)
|
||
|
||
一号多身份的身份关联表。
|
||
|
||
| 字段名 | 类型 | 必填 | 默认值 | 说明 |
|
||
|--------|------|------|--------|------|
|
||
| `id` | INT | 是 | AUTO_INCREMENT | 主键 |
|
||
| `user_id` | INT | 是 | - | 用户 ID |
|
||
| `identity_type` | VARCHAR(20) | 是 | - | 身份类型 |
|
||
| `tenant_id` | INT | 否 | NULL | 关联租户(公众身份为 NULL) |
|
||
| `role_id` | INT | 否 | NULL | 关联角色 |
|
||
| `status` | VARCHAR(10) | 否 | 'active' | 状态:active / inactive |
|
||
| `create_time` | DATETIME | 否 | CURRENT_TIMESTAMP | 创建时间 |
|
||
|
||
```sql
|
||
-- 二期实现
|
||
CREATE TABLE user_identities (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
user_id INT NOT NULL COMMENT '用户ID',
|
||
identity_type VARCHAR(20) NOT NULL COMMENT '身份类型:public/tenant_admin/judge/staff',
|
||
tenant_id INT DEFAULT NULL COMMENT '关联租户ID',
|
||
role_id INT DEFAULT NULL COMMENT '关联角色ID',
|
||
status VARCHAR(10) NOT NULL DEFAULT 'active' COMMENT '状态:active/inactive',
|
||
create_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
INDEX idx_identity_user (user_id),
|
||
INDEX idx_identity_tenant (tenant_id),
|
||
UNIQUE KEY uk_user_tenant_type (user_id, tenant_id, identity_type),
|
||
CONSTRAINT fk_identity_user FOREIGN KEY (user_id) REFERENCES users(id),
|
||
CONSTRAINT fk_identity_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户身份表';
|
||
```
|
||
|
||
---
|
||
|
||
### 2.7 contest_co_organizers 表(二期新增)
|
||
|
||
活动协办机构关联表。
|
||
|
||
```sql
|
||
-- 二期实现
|
||
CREATE TABLE contest_co_organizers (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
contest_id INT NOT NULL COMMENT '活动ID',
|
||
tenant_id INT NOT NULL COMMENT '协办机构租户ID',
|
||
permission_level VARCHAR(20) NOT NULL DEFAULT 'readonly' COMMENT '权限级别:readonly/limited/full',
|
||
create_time DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
|
||
UNIQUE KEY uk_contest_tenant (contest_id, tenant_id),
|
||
CONSTRAINT fk_co_org_contest FOREIGN KEY (contest_id) REFERENCES contests(id),
|
||
CONSTRAINT fk_co_org_tenant FOREIGN KEY (tenant_id) REFERENCES tenants(id)
|
||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='活动协办机构表';
|
||
```
|
||
|
||
---
|
||
|
||
## 3. ER 关系图
|
||
|
||
```
|
||
┌──────────┐
|
||
│ tenants │
|
||
│──────────│
|
||
│ id │
|
||
│ name │
|
||
│ tenant_ │
|
||
┌──────────│ type │──────────┐
|
||
│ └──────────┘ │
|
||
│ tenant_id │ organizer_
|
||
│ │ tenant_id
|
||
┌────▼─────┐ ┌──────▼──────┐
|
||
│ users │ │ contests │
|
||
│──────────│ │─────────────│
|
||
│ id │ │ id │
|
||
│ username │ │ contestName │
|
||
│ phone │ │ visibility │
|
||
│ user_ │ │ contestType │
|
||
│ source │ └──────┬──────┘
|
||
└──┬───┬───┘ │
|
||
│ │ │ contest_id
|
||
│ │ parent_id ┌─────▼────────┐
|
||
│ │ │registrations │
|
||
│ ├──────────┐ │──────────────│
|
||
│ │ │ │ id │
|
||
│ │ ┌──────▼──────┐ │ user_id ◄────┼──── users.id
|
||
│ │ │ children │ │ participant_ │
|
||
│ │ │─────────────│ │ type │
|
||
│ │ │ id │ │ child_id ◄───┼──── children.id
|
||
│ │ │ parent_id │ │ contest_id │
|
||
│ │ │ name │ │ status │
|
||
│ │ │ birthday │ └──────────────┘
|
||
│ │ └─────────────┘
|
||
│ │
|
||
│ └─── user_id ─────────── registrations.user_id
|
||
│
|
||
└─── tenant_id ──────────── tenants.id (公众用户归属 public 租户)
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 数据迁移注意事项
|
||
|
||
### 4.1 现有数据兼容
|
||
|
||
- `users.user_source`:现有用户默认值为 `admin_created`,无需迁移
|
||
- `users.phone`:允许 NULL,现有用户无需填写
|
||
- `registrations.participant_type`:现有报名记录默认值为 `self`,无需迁移
|
||
- `tenants.tenant_type`:现有租户默认值为 `other`,需要手动为已有租户设置正确类型
|
||
- `contests.visibility`:现有活动默认值为 `designated`,保持现有行为不变
|
||
|
||
### 4.2 Prisma Schema 同步
|
||
|
||
所有数据库变更需要同步到 Prisma Schema 文件,通过 `prisma migrate` 管理迁移。
|
||
|
||
### 4.3 广东省图初始化数据
|
||
|
||
```sql
|
||
-- 创建广东省图租户
|
||
INSERT INTO tenants (name, code, tenant_type, description, valid_state)
|
||
VALUES ('广东省立中山图书馆', 'gdlib', 'library', '广东省图少儿绘本创作活动主办方', 1);
|
||
|
||
-- 创建广东省图管理员账号
|
||
-- (通过初始化脚本创建,关联对应的角色和权限)
|
||
```
|