# 课程更新接口文档 ## 接口概述 课程更新接口支持完整的课程信息更新,包括基本信息、章节结构和视频内容的增删改查。 ## 接口信息 - **请求方法**: `PUT` - **请求路径**: `/user/course/{id}` - **接口描述**: 更新课程信息,包括章节和视频的完整更新 ## 请求参数 ### 路径参数 | 参数名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 是 | 课程ID | ### 请求体 (CourseUpdateDto) ```json { "title": "课程标题", "description": "课程描述", "coverUrl": "封面图URL", "price": 29.99, "level": 1, "category": "课程分类", "isFree": true, "submitForAudit": false, "deleteMissing": true, "chapters": [ { "id": 123, "title": "章节标题", "description": "章节描述", "orderNum": 1, "videos": [ { "id": 456, "title": "视频标题", "orderNum": 1, "durationSec": 120, "videoId": 789, "vodVideoId": "vod-abc123" } ] } ] } ``` ### 字段说明 #### 课程基本信息 | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|------| | title | String | 否 | 课程标题,最大128字符 | | description | String | 否 | 课程描述 | | coverUrl | String | 否 | 封面图URL | | price | BigDecimal | 否 | 价格,不能为负数 | | level | Integer | 否 | 访问课程所需的最低用户级别,不能为负数 | | category | String | 否 | 课程分类,最大64字符 | | isFree | Boolean | 否 | 是否免费 | | submitForAudit | Boolean | 否 | 是否提交审核,默认false | | deleteMissing | Boolean | 否 | 是否删除未提交的章节和视频,默认true | #### 章节信息 (ChapterUpdateDto) | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 否 | 章节ID,更新时必填,新建时不填 | | title | String | 是 | 章节标题,最大128字符 | | description | String | 否 | 章节描述 | | orderNum | Integer | 否 | 排序号,未提供则按数组顺序 | | videos | List | 否 | 视频列表 | #### 视频信息 (VideoUpdateDto) | 字段名 | 类型 | 必填 | 说明 | |--------|------|------|------| | id | Long | 否 | 视频ID,更新时必填,新建时不填 | | title | String | 是 | 视频标题,最大128字符 | | orderNum | Integer | 否 | 排序号,未提供则按数组顺序 | | durationSec | Integer | 是 | 视频时长(秒),必须大于0 | | videoId | Long | 否 | 视频ID(与vodVideoId二选一) | | vodVideoId | String | 否 | 阿里云VOD视频ID(与videoId二选一) | ## 响应结果 ### 成功响应 (200) ```json { "code": 200, "message": "success", "data": { "id": 1, "title": "更新后的课程标题", "description": "更新后的课程描述", "coverUrl": "https://example.com/cover.jpg", "price": 39.99, "level": 2, "category": "机器学习", "isFree": true, "createTime": "2024-01-15T10:30:00", "updateTime": "2024-01-15T15:45:00", "creator": { "id": "100", "username": "creator_user", "avatarUrl": "https://example.com/avatar.jpg" }, "chapters": [ { "id": 10, "title": "新章节", "description": "新章节描述", "orderNum": 1, "videos": [ { "id": 20, "chapterId": 10, "title": "新视频", "videoId": "vod-abc123", "durationSec": 120, "orderNum": 1 } ] } ] } } ``` ### 错误响应 #### 400 - 参数错误 ```json { "code": 400, "message": "视频必须提供videoId或vodVideoId" } ``` #### 401 - 未登录 ```json { "code": 401, "message": "用户未登录" } ``` #### 403 - 无权限 ```json { "code": 403, "message": "无权限修改此课程" } ``` #### 404 - 课程不存在 ```json { "code": 404, "message": "课程不存在" } ``` #### 500 - 服务器错误 ```json { "code": 500, "message": "更新课程失败" } ``` ## 业务规则 ### 1. 权限控制 - 只有课程创建者可以更新课程 - 用户必须已登录 ### 2. 数据验证 - 标题长度不能超过128字符 - 价格不能为负数 - 用户级别不能为负数 - 分类长度不能超过64字符 - 视频必须提供videoId或vodVideoId之一,不能同时提供 ### 3. 章节和视频处理 - **新建**: 不提供id的章节/视频将被创建 - **更新**: 提供id的章节/视频将被更新 - **删除**: 当deleteMissing=true时,未在本次提交中出现的章节/视频将被软删除 ### 4. 视频资源绑定 - 提供videoId: 直接绑定到现有的Video记录 - 提供vodVideoId: - 先查找是否已存在对应的Video记录 - 若存在且属于当前用户,则绑定 - 若不存在,则创建新的Video记录并绑定 ### 5. 审核状态 - 当发生结构性变更(新增/删除章节或视频、视频资源替换)时,课程审核状态自动重置为"待审核" - 仅元信息微调(如coverUrl)不会重置审核状态 ### 6. 排序处理 - 章节和视频的orderNum若未提供,将按数组顺序自动设置 - 支持自定义排序号 ## 使用示例 ### 示例1: 更新课程基本信息 ```json { "title": "AI图像处理进阶课程", "description": "深入学习AI图像处理的高级技术", "price": 49.99, "level": 2, "isFree": false } ``` ### 示例2: 添加新章节和视频 ```json { "chapters": [ { "title": "第三章:高级算法", "description": "学习高级图像处理算法", "orderNum": 3, "videos": [ { "title": "3.1 卷积神经网络", "durationSec": 300, "vodVideoId": "vod-new123" } ] } ] } ``` ### 示例3: 替换视频资源 ```json { "chapters": [ { "id": 1, "videos": [ { "id": 5, "title": "更新的视频标题", "durationSec": 180, "vodVideoId": "vod-replace456" } ] } ] } ``` ### 示例4: 删除章节(通过不包含在chapters中) ```json { "deleteMissing": true, "chapters": [ { "id": 1, "title": "保留的章节" } // 其他章节不包含,将被删除 ] } ``` ## 注意事项 1. **事务性**: 整个更新操作在单一事务内执行,确保数据一致性 2. **幂等性**: 支持重复调用,不会产生副作用 3. **软删除**: 删除操作采用软删除,数据不会物理删除 4. **审核联动**: 结构性变更会自动触发审核流程 5. **资源管理**: 视频资源必须属于当前用户,确保权限安全 ## 相关接口 - `GET /user/course/{id}` - 获取课程详情 - `POST /user/course` - 创建课程 - `DELETE /user/course/{id}` - 删除课程