Files
1818web-hoduan/docs/course-video-api.md
2025-11-14 17:41:15 +08:00

251 lines
7.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 课程视频接口文档
## 概述
本文档描述了新增的两个课程视频相关接口:
1. 课程视频详情接口 - 所有用户都可以访问,获取课程和视频的基本信息
2. 课程视频播放凭证接口 - 需要权限验证,根据用户会员级别控制播放权限
## 权限等级说明
系统中的用户权限等级:
- **0 - 游客**: 未登录用户或普通游客
- **1 - 普通用户**: 已注册的普通用户
- **2 - VIP用户**: VIP会员用户
- **3 - SVIP用户**: SVIP会员用户
课程的访问权限规则:
- 免费课程level=0所有用户都可以观看
- 普通课程level=1普通用户及以上可以观看
- VIP课程level=2VIP用户及以上可以观看
- SVIP课程level=3仅SVIP用户可以观看
## 接口详情
### 1. 获取课程视频详情
**接口路径**: `GET /user/course/{courseId}/video-detail`
**接口描述**: 获取课程的视频详情信息,包含章节和视频列表。所有用户都可以访问此接口,但会根据用户权限显示不同的播放权限信息。
**路径参数**:
- `courseId`: 课程ID必需
**请求头**:
- `Authorization`: Bearer token可选未登录用户也可以访问
**响应示例**:
```json
{
"code": 200,
"msg": "success",
"data": {
"course": {
"id": 1,
"title": "AI图像处理入门课程",
"description": "学习AI图像处理的基础知识和实践技巧",
"coverUrl": "https://example.com/cover.jpg",
"price": 29.99,
"level": 2,
"category": "人工智能",
"isFree": false,
"levelName": "VIP用户",
"createTime": "2024-01-15T10:30:00",
"updateTime": "2024-01-15T10:30:00",
"creator": {
"id": "1",
"username": "teacher01",
"avatarUrl": "https://example.com/avatar.jpg"
}
},
"chapters": [
{
"id": 1,
"title": "第一章:基础概念",
"description": "介绍AI图像处理的基础概念",
"orderNum": 1,
"videos": [
{
"id": 1,
"chapterId": 1,
"title": "1.1 什么是AI图像处理",
"vodVideoId": "abc123def456",
"durationSec": 1800,
"durationFormatted": "30:00",
"orderNum": 1,
"canPlay": false,
"lockReason": "需要VIP用户及以上权限"
}
]
}
],
"userPermission": {
"userRole": 1,
"userRoleName": "普通用户",
"requiredLevel": 2,
"requiredLevelName": "VIP用户",
"hasAccess": false,
"accessDeniedReason": "您当前是普通用户用户该课程需要VIP用户及以上权限",
"membershipExpiresAt": null
}
}
}
```
**未登录用户响应示例**:
```json
{
"code": 200,
"msg": "success",
"data": {
"course": { /* 课程信息 */ },
"chapters": [ /* 章节列表所有视频的canPlay都为false */ ],
"userPermission": {
"userRole": 0,
"userRoleName": "游客",
"requiredLevel": 2,
"requiredLevelName": "VIP用户",
"hasAccess": false,
"accessDeniedReason": "请先登录该课程需要VIP用户及以上权限",
"membershipExpiresAt": null
}
}
}
```
### 2. 获取课程视频播放凭证
**接口路径**: `POST /user/course/{courseId}/video/{videoId}/play-auth`
**接口描述**: 根据用户权限获取课程视频的播放凭证。需要用户登录和权限验证,只有满足课程要求权限级别的用户才能获取播放凭证。
**路径参数**:
- `courseId`: 课程ID必需
- `videoId`: 视频ID必需
**请求头**:
- `Authorization`: Bearer token必需
**请求体**:
```json
{
"chapterId": 1,
"authInfoTimeout": 3600
}
```
**请求参数说明**:
- `chapterId`: 章节ID必需
- `authInfoTimeout`: 播放凭证过期时间默认3600秒
**成功响应示例**:
```json
{
"code": 200,
"msg": "success",
"data": {
"playAuth": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"requestId": "req-123456789",
"videoMeta": {
"vodVideoId": "abc123def456",
"title": "1.1 什么是AI图像处理",
"duration": 1800.0,
"coverURL": "https://example.com/video-cover.jpg",
"status": "Normal",
"size": 104857600
},
"userPermission": {
"userRole": 2,
"userRoleName": "VIP用户",
"requiredLevel": 2,
"hasPermission": true,
"checkTime": "2024-01-15T10:30:00"
}
}
}
```
**权限不足响应示例**:
```json
{
"code": 403,
"msg": "权限不足您当前是普通用户用户该课程需要VIP用户及以上权限",
"data": null
}
```
**未登录响应示例**:
```json
{
"code": 401,
"msg": "请先登录",
"data": null
}
```
## 业务逻辑说明
### 课程视频详情接口逻辑
1. **无权限验证**: 所有用户(包括未登录用户)都可以访问此接口
2. **基础信息展示**: 显示课程的基本信息、章节结构和视频列表
3. **权限状态指示**: 根据用户当前权限级别,标识每个视频是否可播放
4. **友好提示**: 对于无权限播放的视频,提供明确的权限要求说明
### 播放凭证接口逻辑
1. **登录验证**: 必须是已登录用户才能访问
2. **权限验证**: 验证用户的会员级别是否满足课程要求
3. **章节视频验证**: 验证视频与章节的关联关系
4. **播放凭证生成**: 调用阿里云VOD服务生成播放凭证
5. **权限记录**: 记录用户的权限验证信息
### 权限验证规则
- 游客level=0只能观看免费课程
- 普通用户level=1可以观看免费课程和普通课程
- VIP用户level=2可以观看免费、普通和VIP课程
- SVIP用户level=3可以观看所有课程
## 错误码说明
| 错误码 | 说明 |
|--------|------|
| 200 | 成功 |
| 400 | 请求参数错误或课程不存在 |
| 401 | 未登录 |
| 403 | 权限不足 |
| 500 | 服务器内部错误 |
## 使用建议
1. **前端实现**: 建议先调用视频详情接口获取课程信息和用户权限状态,再根据权限决定是否显示播放按钮
2. **用户体验**: 对于权限不足的用户,可以显示升级提示或购买链接
3. **缓存策略**: 课程详情信息可以适当缓存,但播放凭证应该实时获取
4. **错误处理**: 播放凭证获取失败时,应该给用户友好的错误提示
## 数据库变更
为了支持这些接口,在 `CourseVideoMapper` 中新增了 `selectById` 方法:
```xml
<select id="selectById" resultMap="CourseVideoResultMap">
SELECT id, chapter_id, title, video_id, duration_sec, order_num, create_time, update_time, is_deleted
FROM course_video
WHERE id = #{id} AND is_deleted = 0
</select>
```
## 新增文件
1. `CourseVideoDetailDto.java` - 课程视频详情响应DTO
2. `CourseVideoPlayDto.java` - 播放凭证相关DTO
3. `docs/course-video-api.md` - 本API文档
## 修改文件
1. `CourseController.java` - 新增两个接口端点
2. `CourseService.java` - 新增两个服务方法接口
3. `CourseServiceImpl.java` - 实现两个服务方法
4. `CourseVideoMapper.java` - 新增selectById方法
5. `CourseVideoMapper.xml` - 新增selectById查询SQL