287 lines
13 KiB
Markdown
287 lines
13 KiB
Markdown
|
|
# 系统架构设计
|
|||
|
|
|
|||
|
|
## 1. 整体架构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌─────────────────────────────────────────────────────────────┐
|
|||
|
|
│ 用户访问层 │
|
|||
|
|
│ ┌─────────────┐ ┌──────────────┐ ┌────────────────────┐ │
|
|||
|
|
│ │ 公众端(H5) │ │ 管理后台(Web) │ │ 微信内置浏览器(H5) │ │
|
|||
|
|
│ │ /p/... │ │ /:tenant/... │ │ /p/... │ │
|
|||
|
|
│ └──────┬──────┘ └──────┬───────┘ └─────────┬──────────┘ │
|
|||
|
|
└─────────┼────────────────┼────────────────────┼─────────────┘
|
|||
|
|
│ │ │
|
|||
|
|
┌─────────▼────────────────▼────────────────────▼─────────────┐
|
|||
|
|
│ Vue3 前端应用 │
|
|||
|
|
│ ┌─────────────────┐ ┌──────────────────────────────────┐ │
|
|||
|
|
│ │ 公众端模块 │ │ 管理端模块 │ │
|
|||
|
|
│ │ - 活动大厅 │ │ - 机构管理端(图书馆/学校/...) │ │
|
|||
|
|
│ │ - 活动详情 │ │ - 评审端 │ │
|
|||
|
|
│ │ - 报名/提交作品 │ │ - 平台管理端(超管) │ │
|
|||
|
|
│ │ - 个人中心 │ │ - 现有功能保持不变 │ │
|
|||
|
|
│ │ - 子女管理 │ │ │ │
|
|||
|
|
│ └─────────────────┘ └──────────────────────────────────┘ │
|
|||
|
|
└────────────────────────────┬─────────────────────────────────┘
|
|||
|
|
│ HTTP API
|
|||
|
|
┌────────────────────────────▼─────────────────────────────────┐
|
|||
|
|
│ NestJS 后端 │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
|
|||
|
|
│ │ Auth模块 │ │ 用户模块 │ │ 活动模块 │ │ 公众API模块 │ │
|
|||
|
|
│ │(多种登录) │ │(子女管理) │ │(现有改造) │ │ (公众端专用) │ │
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │
|
|||
|
|
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
|
|||
|
|
│ │ 租户模块 │ │ 评审模块 │ │ 作品模块 │ │ 其他现有模块 │ │
|
|||
|
|
│ │(类型扩展) │ │(现有) │ │(现有改造) │ │ (保持不变) │ │
|
|||
|
|
│ └──────────┘ └──────────┘ └──────────┘ └────────────────┘ │
|
|||
|
|
└────────────────────────────┬─────────────────────────────────┘
|
|||
|
|
│ Prisma ORM
|
|||
|
|
┌────────────────────────────▼─────────────────────────────────┐
|
|||
|
|
│ MySQL 数据库 │
|
|||
|
|
│ users / children / tenants / contests / registrations / ... │
|
|||
|
|
└──────────────────────────────────────────────────────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 租户模型设计
|
|||
|
|
|
|||
|
|
### 2.1 租户类型
|
|||
|
|
|
|||
|
|
| 类型标识 | 名称 | 说明 | 举例 |
|
|||
|
|
|---------|------|------|------|
|
|||
|
|
| `platform` | 平台租户 | 系统运营方,全局唯一 | 乐绘世界 |
|
|||
|
|
| `library` | 图书馆 | 公共图书馆机构 | 广东省立中山图书馆 |
|
|||
|
|
| `kindergarten` | 幼儿园 | 幼儿教育机构 | XX幼儿园 |
|
|||
|
|
| `school` | 学校 | 中小学校 | XX小学 |
|
|||
|
|
| `institution` | 社会机构 | 美术培训、文化机构等 | XX美术中心 |
|
|||
|
|
| `other` | 其他 | 未分类的机构 | - |
|
|||
|
|
|
|||
|
|
### 2.2 租户与用户的关系
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
租户(机构)
|
|||
|
|
├── 拥有机构用户:管理员、工作人员、评委
|
|||
|
|
│ └── 通过 tenant_id 关联
|
|||
|
|
│
|
|||
|
|
公众用户
|
|||
|
|
├── 不隶属任何租户
|
|||
|
|
├── 通过自主注册创建
|
|||
|
|
├── 可以查看所有"公开"活动并报名
|
|||
|
|
│
|
|||
|
|
身份重叠场景(二期实现)
|
|||
|
|
├── 一个手机号 = 一个账号
|
|||
|
|
├── 同一账号可以同时拥有:公众用户身份 + 机构用户身份
|
|||
|
|
└── 通过"身份切换"在不同工作台之间切换
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2.3 活动可见范围
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
活动创建时设置 visibility 字段:
|
|||
|
|
├── public — 公开(所有注册用户可见,广东省图本次使用)
|
|||
|
|
├── designated — 指定机构(选择哪些租户可见,现有逻辑)
|
|||
|
|
└── internal — 仅内部(仅本机构内部可见)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 用户体系设计
|
|||
|
|
|
|||
|
|
### 3.1 核心原则:一号多身份
|
|||
|
|
|
|||
|
|
**一个手机号/账号 = 一个用户**,用户可以拥有多个身份角色。
|
|||
|
|
|
|||
|
|
一期先实现账号密码登录,二期补充手机号和微信登录。一期阶段公众用户通过"用户名+密码"自主注册。
|
|||
|
|
|
|||
|
|
### 3.2 用户来源
|
|||
|
|
|
|||
|
|
| 来源 | 标识 | 说明 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| 管理员创建 | `admin_created` | 现有方式,管理员在后台创建用户 |
|
|||
|
|
| 自主注册 | `self_registered` | 新增,用户通过公众端注册页面自行注册 |
|
|||
|
|
|
|||
|
|
### 3.3 用户参与模型
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
注册用户(User)
|
|||
|
|
├── 可以以"自己"的身份报名活动(所有用户默认能力)
|
|||
|
|
├── 可以添加子女,以"子女"的身份代为报名(可选能力)
|
|||
|
|
│
|
|||
|
|
├── 我自己报名的活动(participant_type = 'self')
|
|||
|
|
│ └── 适用场景:有手机号的青少年自己注册参与
|
|||
|
|
│
|
|||
|
|
└── 我为子女报名的活动(participant_type = 'child')
|
|||
|
|
├── child_id 指向具体哪个子女
|
|||
|
|
└── 适用场景:家长为年幼子女代报名
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.4 报名流程
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户点击"报名活动"
|
|||
|
|
│
|
|||
|
|
├── 检查是否已登录 → 未登录则跳转登录/注册页
|
|||
|
|
│
|
|||
|
|
├── 已登录 → 检查是否有关联子女
|
|||
|
|
│
|
|||
|
|
├── 无子女 → 直接以自己身份报名
|
|||
|
|
│ → 填写报名补充信息 → 提交
|
|||
|
|
│
|
|||
|
|
└── 有子女 → 弹出"选择参与者"
|
|||
|
|
┌─────────────────────────┐
|
|||
|
|
│ 请选择参与者: │
|
|||
|
|
│ ○ 我自己 │
|
|||
|
|
│ ○ 子女:小明(8岁) │
|
|||
|
|
│ ○ 子女:小红(5岁) │
|
|||
|
|
│ + 添加新的子女 │
|
|||
|
|
└─────────────────────────┘
|
|||
|
|
→ 选择后填写报名信息 → 提交
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 前端架构
|
|||
|
|
|
|||
|
|
### 4.1 路由设计
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
前端路由结构:
|
|||
|
|
│
|
|||
|
|
├── /p/ # 公众端(H5 + Web 响应式)
|
|||
|
|
│ ├── /p/login # 公众端登录
|
|||
|
|
│ ├── /p/register # 公众端注册
|
|||
|
|
│ ├── /p/activities # 活动大厅(活动列表)
|
|||
|
|
│ ├── /p/activities/:id # 活动详情
|
|||
|
|
│ ├── /p/activities/:id/register # 报名页面
|
|||
|
|
│ ├── /p/activities/:id/submit # 提交作品
|
|||
|
|
│ ├── /p/mine # 个人中心
|
|||
|
|
│ ├── /p/mine/children # 子女管理
|
|||
|
|
│ ├── /p/mine/registrations # 我的报名
|
|||
|
|
│ └── /p/mine/works # 我的作品
|
|||
|
|
│
|
|||
|
|
├── /:tenantCode/ # 管理端(现有,保持不变)
|
|||
|
|
│ ├── /:tenantCode/login # 机构登录
|
|||
|
|
│ ├── /:tenantCode/contests # 活动管理
|
|||
|
|
│ ├── /:tenantCode/system # 系统管理
|
|||
|
|
│ └── ...
|
|||
|
|
│
|
|||
|
|
└── / # 根路径重定向
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.2 公众端布局
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
┌────────────────────────────────────────┐ Web 端
|
|||
|
|
│ 顶部导航栏 │
|
|||
|
|
│ [Logo 乐绘世界] [活动大厅] [个人中心] │
|
|||
|
|
├────────────────────────────────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ 页面内容区 │
|
|||
|
|
│ │
|
|||
|
|
└────────────────────────────────────────┘
|
|||
|
|
|
|||
|
|
┌──────────────┐ H5 移动端
|
|||
|
|
│ 顶部标题栏 │
|
|||
|
|
├──────────────┤
|
|||
|
|
│ │
|
|||
|
|
│ 页面内容区 │
|
|||
|
|
│ │
|
|||
|
|
├──────────────┤
|
|||
|
|
│ 底部Tab导航 │
|
|||
|
|
│ [首页][我的] │
|
|||
|
|
└──────────────┘
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 4.3 响应式适配策略
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
一套 Vue 代码,通过 CSS 媒体查询和 Tailwind 断点适配:
|
|||
|
|
├── sm (< 640px) → H5 移动端布局(底部 Tab 导航)
|
|||
|
|
├── md (640-1024px) → 平板端布局
|
|||
|
|
└── lg (> 1024px) → Web 端布局(顶部导航栏)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 后端 API 设计
|
|||
|
|
|
|||
|
|
### 5.1 新增公众端 API 模块
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
/api/public/ # 公众端 API(无需租户上下文)
|
|||
|
|
├── POST /auth/register # 公众注册
|
|||
|
|
├── POST /auth/login # 公众登录
|
|||
|
|
├── GET /activities # 获取公开活动列表
|
|||
|
|
├── GET /activities/:id # 获取活动详情
|
|||
|
|
├── POST /activities/:id/register # 报名活动
|
|||
|
|
├── POST /activities/:id/submit # 提交作品
|
|||
|
|
├── GET /mine/profile # 获取个人信息
|
|||
|
|
├── PUT /mine/profile # 更新个人信息
|
|||
|
|
├── GET /mine/children # 获取子女列表
|
|||
|
|
├── POST /mine/children # 添加子女
|
|||
|
|
├── PUT /mine/children/:id # 编辑子女
|
|||
|
|
├── DELETE /mine/children/:id # 删除子女
|
|||
|
|
├── GET /mine/registrations # 我的报名列表
|
|||
|
|
└── GET /mine/works # 我的作品列表
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 5.2 现有 API 改造
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
活动相关 API 变更:
|
|||
|
|
├── 创建活动:新增 visibility 字段(public/designated/internal)
|
|||
|
|
├── 获取活动列表:支持按 visibility 过滤
|
|||
|
|
├── 报名接口:新增 participant_type 和 child_id 字段
|
|||
|
|
└── 报名记录查询:支持按 participant_type 筛选
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 多机构联合举办(二期)
|
|||
|
|
|
|||
|
|
### 6.1 主办-协办模型
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
活动表新增:
|
|||
|
|
├── organizer_tenant_id — 主办机构 ID
|
|||
|
|
└── co_organizer_ids — 协办机构 ID 列表(JSON 数组)
|
|||
|
|
|
|||
|
|
权限分配:
|
|||
|
|
├── 主办方:完整管理权限(创建、编辑、审核、发布成果)
|
|||
|
|
└── 协办方:有限权限(查看报名数据、推荐评委、查看成果)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 6.2 活动页面展示
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
活动详情页展示:
|
|||
|
|
├── 主办单位:广东省立中山图书馆
|
|||
|
|
└── 协办单位:北京国家图书馆、上海图书馆
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 一号多身份(二期)
|
|||
|
|
|
|||
|
|
### 7.1 身份切换机制
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户登录后:
|
|||
|
|
├── 默认进入公众端(活动大厅)
|
|||
|
|
├── 如果用户同时是某机构的管理员/工作人员
|
|||
|
|
│ └── 显示"切换到管理端"入口
|
|||
|
|
├── 切换身份 = 切换工作台视角
|
|||
|
|
└── 不需要重新登录,JWT token 中包含所有身份信息
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 7.2 身份绑定
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
用户身份表(user_identities)
|
|||
|
|
├── user_id — 用户 ID
|
|||
|
|
├── identity_type — 身份类型(public / tenant_admin / judge / staff)
|
|||
|
|
├── tenant_id — 关联租户(公众身份为 NULL)
|
|||
|
|
├── role_id — 关联角色
|
|||
|
|
└── status — 状态(active / inactive)
|
|||
|
|
```
|