# 后端 **Repository Path**: videoclub/backend ## Basic Information - **Project Name**: 后端 - **Description**: 本项目是“教师视频俱乐部”在线学习社区的后端服务系统。该平台以视频为核心,支持教师加入俱乐部、完成研修任务(看视频/研视频)以及进行跨时空的互动讨论。 - **Primary Language**: NodeJS - **License**: Not specified - **Default Branch**: dev - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-12-11 - **Last Updated**: 2026-04-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 视频俱乐部后端 开发说明 版本: 1.5.5 最后更新: 2026-01-28 开发者:[Jieyang W.](https://gitee.com/mick_wj)、[Cheng R. Zhu](https://syouei.github.io/about/)、[J.J. Gao](https://gitee.com/gjj1122) ------ ## 1. 项目简介 本项目是"教师视频俱乐部"在线学习社区的后端服务系统。该平台以视频为核心,支持教师加入俱乐部、完成研修任务(看视频/研视频)以及进行跨时空的互动讨论。 ### 核心能力 - **俱乐部管理**:创建、加入、退出、管理成员。 - **资源沉淀**:视频资源的上传与管理。 - **研修任务**:发布"观看"或"研究"任务,并追踪用户的完成状态。 - **深度互动**:支持基于视频时间轴的弹幕式评论与楼中楼回复。 - **消息通知**:支持系统通知管理,包括俱乐部加入请求、审批等消息推送。 - **行为埋点**:前端用户行为数据采集与分析,支持点击、输入、页面浏览等事件追踪。 ### 项目文档 **API文档:** [docs/api-doc.md](docs/api-doc.md) **数据库文档:** [docs/database-doc.md](docs/database-doc.md) **代码风格规范:** [docs/code-style.md](docs/code-style.md) **编码规范:** [docs/engineering.md](docs/engineering.md) ------ ## 2. 技术栈与环境 - **运行环境**: Node.js (v16+), MySQL (8.0+) - **核心框架**: NestJS (TypeScript) - **ORM 框架**: TypeORM - **鉴权机制**: JWT (JSON Web Token) + Passport - **数据校验**: class-validator + class-transformer - **工程规范**: 遵循 Vibe 工程化规范 ------ ## 3. 项目结构 项目采用 NestJS 标准的模块化架构,职责分层清晰。 Plaintext ``` src/ ├── common/ # 公共基础设施 │ ├── decorators/ # 自定义装饰器 (@CurrentUser, @Public) │ ├── exceptions/ # 异常定义 (BizException) │ ├── filters/ # 全局异常过滤器 (HttpExceptionFilter) │ ├── guards/ # 守卫 (JwtAuthGuard) │ ├── interceptors/ # 拦截器 (TransformInterceptor) │ └── result.ts # 统一返回结构封装 ├── modules/ # 业务模块 │ ├── auth/ # 认证模块 (登录/注册) │ ├── user/ # 用户模块 (个人信息/我的俱乐部) │ ├── club/ # 俱乐部模块 (CRUD/成员管理) │ ├── video/ # 视频资源模块 │ ├── task/ # 任务模块 (发布/完成状态) │ ├── comment/ # 评论模块 (时间轴互动) │ ├── notification/ # 通知模块 (消息推送/消息管理) │ └── analytics/ # 埋点模块 (行为数据采集) ├── app.module.ts # 根模块 (数据库连接/模块聚合) └── main.ts # 入口文件 (全局配置) ``` ------ ## 4. 核心程序逻辑 ### 4.1 统一响应与异常处理 系统实施了全局拦截机制,确保 API 始终返回一致的 JSON 格式: - **成功响应**:由 `TransformInterceptor` 自动封装为 `{ code: 0, msg: "ok", data: ... }`。 - **异常响应**:由 `HttpExceptionFilter` 捕获,将 HTTP 错误或业务异常转换为 `{ code: non-zero, msg: "error", data: null }`。 ### 4.2 鉴权与用户上下文 - **全局守卫**:`JwtAuthGuard` 默认拦截所有请求。 - **公开接口**:使用 `@Public()` 装饰器标记的接口(如登录、注册)可跳过鉴权。 - **用户获取**:通过 `@CurrentUser()` 参数装饰器,在 Controller 中直接获取解析后的用户信息(`userId`, `role` 等)。 ### 4.3 俱乐部成员关联逻辑 - **创建即加入**:用户创建俱乐部时,事务性地在 `ClubMembers` 表中插入一条记录,角色设为 `manager`。 - **加入查重**:用户申请加入前,会校验是否已在 `ClubMembers` 表中,防止重复加入。 - **我的俱乐部**:通过查询 `ClubMembers` 表并关联 (`relations`) `Clubs` 表来获取用户参与列表。 ### 4.4 任务状态计算 在获取任务列表时,系统采用内存匹配策略: 1. 查询该俱乐部下所有 `Task`。 2. 查询当前用户在该俱乐部下的所有 `TaskCompletion` 记录。 3. 在内存中生成 Set,遍历任务列表动态计算 status: 'complete' | 'incomplete'。 ### 4.5 时间轴评论 - 评论挂载于 `Video` 而非 `Task`,实现资源复用。 - 支持 `videoTime` 字段记录秒数,前端据此在进度条渲染红点。 - 列表查询时优先按 `videoTime` 升序排列,还原视频播放的时间线性。 ### 4.6 通知管理 - **通知类型**:支持 `club_join_request`(加入请求)、`club_join_approved`(审批通过)、`club_join_rejected`(审批拒绝)。 - **处理状态**:包含 `isRead`(已读状态)、`isProcessed`(处理状态)两个维度,便于区分用户感知和系统处理。 - **批量通知**:提供 `notifyMany` 方法,支持向多个用户同时发送通知。 - **业务集成**:在俱乐部加入申请、审批等关键业务节点自动触发通知。 ### 4.7 行为埋点 - **公开接口**:`POST /analytics/events` 使用 `@Public()` 装饰器,无需鉴权即可调用。 - **事件类型**:支持 `click`、`input`、`page_view`、`route_change`、`scroll_depth` 等多种事件类型。 - **数据完整性**:记录用户ID、俱乐部ID、页面路径、模块、事件时间等上下文信息。 - **异步处理**:直接写入数据库,提供事件ID作为响应,适合高并发场景。 ------ ## 5. 数据库设计 系统包含 9 张核心表,关系如下: - **Users**: 用户基础表。 - **Clubs**: 俱乐部元数据。 - **ClubMembers**: 多对多关联表 (User <-> Club),存储角色。 - **Videos**: 独立的视频资源库,归属于 Club。 - **Tasks**: 指向 Video 的研修任务。 - **TaskCompletions**: 记录用户完成任务的状态及笔记。 - **Comments**: 挂载于 Video 的互动数据,支持层级回复。 - **Notifications**: 系统通知表,存储各类业务通知(如加入请求、审批结果等)。 - **AnalyticsEvents**: 埋点数据表,记录前端用户行为事件。 详细定义见 `docs/database-doc.md`。 ------ ## 6. 部署与启动 ### 6.1 依赖环境 - **Node.js**: v16.13.0 或更高 - **MySQL**: 8.0 ### 6.2 依赖版本 (package.json) 核心依赖包括: - `@nestjs/core`, `@nestjs/common`, `@nestjs/platform-express`: 框架核心 - `typeorm`, `mysql2`: 数据库 ORM - `@nestjs/jwt`, `passport`, `bcrypt`: 安全认证 - `class-validator`: 参数校验 ### 6.3 启动步骤 1. 配置数据库 修改 src/app.module.ts 中的数据库连接配置(Host, Username, Password, Database)。 2. **安装依赖** Bash ``` npm install //或者 npm install @nestjs/platform-express @nestjs/common @nestjs/core @nestjs/typeorm typeorm mysql2 @nestjs/jwt @nestjs/passport passport passport-jwt bcrypt class-validator class-transformer reflect-metadata rxjs --save ``` 3. **启动开发环境** Bash ``` npm run start:dev ``` *启动后 TypeORM 会自动同步表结构 (`synchronize: true`)。* 4. **生产环境部署** Bash ``` npm run build npm run start:prod ``` ### 6.4 全程接口测试 请按顺序执行以下请求,以验证各个模块是否正常工作。 详细接口说明请见: #### 1. 注册用户 (Auth) - **URL**: `POST http://localhost:3000/api/v1/auth/register` - **Body (JSON)**: JSON ``` { "username": "teacher_wang", "password": "123456", "role": "teacher" } ``` - **预期**: 返回 `code: 0`,`msg: "注册成功"`。 #### 2. 登录获取 Token (Auth) - **URL**: `POST http://localhost:3000/api/v1/auth/login` - **Body (JSON)**: JSON ``` { "username": "teacher_wang", "password": "123456" } ``` - **预期**: 返回 `data.accessToken`。 > **注意**:请复制这个 Token,后续所有请求都要用到。 #### 3. 创建俱乐部 (Club) - **URL**: `POST http://localhost:3000/api/v1/clubs` - **Headers**: `Authorization: Bearer <你的Token>` - **Body (JSON)**: JSON ``` { "name": "初中数学研修社", "tag": "数学" } ``` - **预期**: 返回 `data.clubId` (假设为 `1`)。 #### 4. 上传视频 (Video) - **URL**: `POST http://localhost:3000/api/v1/videos` - **Headers**: `Authorization: Bearer <你的Token>` - **Body (JSON)**: JSON ``` { "clubId": 1, "title": "勾股定理讲解", "url": "http://oss.example.com/video1.mp4", "duration": 600 } ``` - **预期**: 返回 `data.videoId` (假设为 `1`)。 #### 5. 发布任务 (Task) - **URL**: `POST http://localhost:3000/api/v1/tasks` - **Headers**: `Authorization: Bearer <你的Token>` - **Body (JSON)**: JSON ``` { "clubId": 1, "videoId": 1, "type": "watch", "title": "观看示范课" } ``` - **预期**: 返回 `data.taskId`。 #### 6. 发表时间轴评论 (Comment) - **URL**: `POST http://localhost:3000/api/v1/comments` - **Headers**: `Authorization: Bearer <你的Token>` - **Body (JSON)**: JSON ``` { "videoId": 1, "content": "这里是重点!", "videoTime": 125 } ``` - **预期**: 返回评论数据。 #### 7. 验证"我的俱乐部"关联 (User) - **URL**: `GET http://localhost:3000/api/v1/users/me/clubs` - **Headers**: `Authorization: Bearer <你的Token>` - **预期**: 返回数组,包含 `"clubName": "初中数学研修社"`,且 `"memberRole": "manager"`(证明创建时自动加入逻辑生效)。 #### 8. 发送埋点事件 (Analytics) - **URL**: `POST http://localhost:3000/api/v1/analytics/events` - **Headers**: 无需鉴权 - **Body (JSON)**: JSON ``` { "event": "click", "sub_event": "play_button", "module": "video", "target_object": "video_1", "user_id": 1, "user_name": "teacher_wang", "user_true_name": "王老师", "club_id": 1, "page": "/clubs/1/videos/1", "event_time": 1706457600000 } ``` - **预期**: 返回 `data.eventId`。 #### 9. 查询通知列表 (Notification) - **URL**: `GET http://localhost:3000/api/v1/notifications?page=1&pageSize=10` - **Headers**: `Authorization: Bearer <你的Token>` - **预期**: 返回通知列表,包含 `list`、`total`、`page`、`pageSize`。 #### 10. 标记通知已读 (Notification) - **URL**: `PUT http://localhost:3000/api/v1/notifications/:notificationId/read` - **Headers**: `Authorization: Bearer <你的Token>` - **预期**: 返回成功响应,通知状态更新为已读。 ------ *Assisted by Gemini 3 Pro / Codex / CodeBuddy ...* ©2025-2026