Appearance
课程详情接口
接口总览
| 名称 | 方法 | 路径 |
|---|---|---|
| 获取课程详情 | GET | /api/app/course/{courseId}/detail |
| 获取课程介绍页 | GET | /api/app/course/{courseId}/about |
| 获取课程目录 | GET | /api/app/course/{courseId}/detail/outline |
| 获取课程资料列表 | GET | /api/app/course/{courseId}/materials |
| 获取课程公告列表 | GET | /api/app/course/{courseId}/announcements |
| 加入课程 | POST | /api/app/course/{courseId}/join |
| 收藏课程 | POST | /api/app/course/{courseId}/favorite |
| 取消收藏课程 | POST | /api/app/course/{courseId}/unfavorite |
获取课程资料列表(GET /api/app/course/{courseId}/materials)
课程学习页/课程详情页「课程资料」Tab 所用接口,仅对已加入该课程的学员开放;仅展示关联到已发布下载任务的资料。
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
查询参数(分页):
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| page | number | 否 | 页码,从 0 开始,默认 0 |
| size | number | 否 | 每页条数,默认 20 |
返回
标准分页结构:data 为资料列表,paginator 为分页信息(total、size、page 等)。
json
{
"data": [
{
"id": 20001,
"title": "课程资料.pdf",
"description": "第一章学习资料",
"fileSize": 1024000,
"taskId": 10001,
"type": "pdf",
"ext": "pdf",
"convertStatus": "success",
"globalId": "abc123def456"
}
],
"paginator": {
"total": 1,
"size": 20,
"page": 0
}
}字段说明(data 列表项)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 资料ID |
| title | string | 资料名称 |
| description | string/null | 资料描述 |
| fileSize | number/null | 资料大小(字节) |
| taskId | number | 关联的下载任务ID,用于拼下载/播放链接 |
| type | string/null | 文件类型 |
| ext | string/null | 文件扩展名 |
| convertStatus | string/null | 文件转换状态 |
| globalId | string/null | 文件全局ID |
下载链接:GET /api/app/course/{courseId}/task/{taskId}/material/{materialId}/download
播放链接:GET /api/app/course/{courseId}/task/{taskId}/material/{materialId}/play
说明
- 权限:必须先有课程成员身份(已加入课程),否则 403。
- 过滤:仅展示
course_material_v8中本课程、关联到具体课时(lessonId≠0)、来源为课程资料、类型为普通课程,且其对应下载任务已发布的资料。 - 排序与分页:按资料创建时间倒序;默认每页 20 条。
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前用户不是该课程成员 |
获取课程公告列表(GET /api/app/course/{courseId}/announcements)
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
返回
json
{
"data": [
{
"id": 1001,
"content": "<p>各位学员好...</p>",
"userId": 10001,
"createdTime": 1735660800
}
]
}异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
加入课程(POST /api/app/course/{courseId}/join)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程 ID |
返回
json
{
"isJoined": true
}| 字段 | 类型 | 说明 |
|---|---|---|
| isJoined | boolean | 当前是否已加入课程(操作后恒为 true) |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_NOT_VISIBLE | 403 | 课程不可见 | 用户不在课程可见范围内 |
COURSE_ACCESS_DENIED | 403 | 课程加入范围不允许访问 | 课程已关闭或不在加入范围内 |
收藏课程(POST /api/app/course/{courseId}/favorite)
课程详情页头部「收藏」按钮。若已收藏直接返回已收藏;否则将当前课程(courseId)写入收藏。
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程 ID |
返回
json
{
"favorite": true
}| 字段 | 类型 | 说明 |
|---|---|---|
| favorite | boolean | 当前是否已收藏(操作后恒为 true) |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
取消收藏课程(POST /api/app/course/{courseId}/unfavorite)
课程详情页「取消收藏」按钮。
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程 ID |
返回
json
{
"favorite": false
}| 字段 | 类型 | 说明 |
|---|---|---|
| favorite | boolean | 当前是否已收藏(取消后为 false) |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
获取课程详情(GET /api/app/course/{courseId}/detail)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
返回
json
{
"id": 101,
"status": "published",
"cover": "https://example.com/cover.jpg",
"title": "Java基础课程",
"subtitle": "从零开始学习Java编程",
"isJoined": true,
"learningProgress": 75.5,
"finishedTaskNum": 15,
"totalTaskNum": 20,
"earnedCredit": 5,
"earnedRewardPoint": 100,
"earnedCertificateName": "Java基础课程结业证书",
"isFavorite": true,
"recentTaskId": 10001,
"recentTaskTitle": "第一章:Java基础",
"firstTaskId": 10001,
"firstTaskTitle": "第一章:Java基础",
"canJoin": true,
"hasAnnouncements": true
}字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 课程ID |
| status | string | 课程状态:draft(草稿)、published(已发布)、close(已关闭) |
| cover | string | 课程封面URL |
| title | string | 课程标题 |
| subtitle | string | 课程副标题 |
| isJoined | boolean | 是否已加入课程 |
| learningProgress | number/null | 学习进度(百分比),未加入课程时为null |
| finishedTaskNum | number/null | 已完成任务数(分子),未加入课程时为null |
| totalTaskNum | number/null | 总任务数(分母),未加入课程时为null |
| earnedCredit | number/null | 已获得的学分,未加入课程或未获得学分为null |
| earnedRewardPoint | number/null | 已获得的积分,未启用积分为null |
| earnedCertificateName | string/null | 已获得证书名称,未获得证书或未启用证书为null |
| isFavorite | boolean | 是否收藏 |
| recentTaskId | number/null | 最近学习任务ID,无学习记录时为 null(仅已加入时返回) |
| recentTaskTitle | string/null | 最近学习任务标题,无学习记录时为 null |
| firstTaskId | number/null | 第一个任务ID(按序号),无已发布任务时为 null(仅已加入时返回) |
| firstTaskTitle | string/null | 第一个任务标题,无已发布任务时为 null |
| canJoin | boolean | 是否可以加入。已加入时为 true;未加入时为「未关闭且满足加入范围」的结果,课程已关闭或不在加入范围内为 false |
| hasAnnouncements | boolean | 当前是否有未过期公告 |
说明
- 课程基本信息:返回课程的基本信息,包括状态、封面、标题、副标题等。
- 课程状态:
status为课程状态,close 表示课程已关闭,不允许新用户加入,已加入用户也无法继续学习。 - 加入与可加入:
isJoined表示当前用户是否已加入;canJoin表示当前是否允许加入(未关闭且若开启条件加入则需在加入范围内)。 - 学习进度:
- 仅当用户已加入课程时,才会返回学习进度相关信息
learningProgress为已完成任务数除以总任务数的百分比finishedTaskNum和totalTaskNum用于显示进度条(如:15/20)
- 学分、积分、证书:
- 仅返回已获得的数量或名称
- 如果未启用相应功能或未获得,则返回
null
- 收藏状态:
isFavorite表示当前用户是否收藏了该课程。 - 任务(仅已加入课程时返回):
recentTaskId/recentTaskTitle:最近学习的任务,无学习记录时为 nullfirstTaskId/firstTaskTitle:课程第一个任务(按序号排序),无已发布任务时为 null
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_NOT_VISIBLE | 403 | 课程不可见 | 用户不在课程可见范围内 |
获取课程介绍页(GET /api/app/course/{courseId}/about)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
返回
json
{
"summary": "本课程从零开始讲解 Java 基础语法与面向对象思想,适合编程入门学员。",
"goals": ["掌握 Java 基础语法", "理解面向对象编程", "能独立完成简单项目"],
"audiences": ["零基础学员", "转行程序员"],
"certificates": [
{
"id": 1,
"name": "Java基础课程结业证书",
"autoIssue": true,
"summary": "完成全部学习并通过考核后自动发放。",
"obtained": false
}
],
"credit": 5,
"taskRewardPoint": 5,
"courseRewardPoint": 100,
"rewardPointName": "积分",
"teachers": [
{
"id": 1001,
"nickname": "张老师",
"avatar": "https://example.com/avatar.jpg",
"levelName": "高级讲师",
"fieldNames": ["Java", "后端开发"]
}
],
"relatedCourses": [
{
"id": 102,
"title": "Java进阶课程",
"cover": { "small": "", "middle": "https://example.com/cover2.jpg", "large": "" },
"hasCertificate": true,
"studentNum": 1280
}
]
}字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| summary | string/null | 课程简介 |
| goals | string[]/null | 课程目标列表 |
| audiences | string[]/null | 适用人群列表 |
| certificates | object[] | 证书列表(含 name、autoIssue、summary),未配置或证书插件未启用时为空数组 [],见下表 |
| credit | number/null | 学分配置值,未配置或学分插件未启用时为 null |
| taskRewardPoint | number/null | 任务积分(完成单个任务可获得),未配置或积分插件未启用时为 null |
| courseRewardPoint | number/null | 课程积分(完成整个课程可获得),未配置或积分插件未启用时为 null |
| rewardPointName | string/null | 积分名称 |
| teachers | object[] | 授课讲师列表,见下表 |
| relatedCourses | object[] | 相关推荐课程列表(按标签等推荐),见下表 |
证书对象(certificates[])
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 证书ID |
| name | string | 证书名称 |
| autoIssue | boolean | 是否自动发证 |
| summary | string/null | 证书描述 |
| obtained | boolean | 当前用户是否已获得该证书 |
讲师对象(teachers[])
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 用户ID(讲师) |
| nickname | string | 昵称 |
| avatar | string | 头像URL |
| levelName | string/null | 讲师等级名称 |
| fieldNames | string[] | 专业领域名称列表 |
相关课程对象(relatedCourses[])
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 课程ID |
| title | string | 课程标题 |
| cover | object | 封面(含 small/middle/large) |
| hasCertificate | boolean | 是否配置证书 |
| studentNum | number/null | 在学学员数 |
说明
- 课程介绍:用于课程详情页的「介绍」Tab,包含简介、目标、适用人群及激励配置(证书列表含名称/是否自动发证/描述、学分、任务积分、课程积分)。
- 讲师:仅返回本课程可见的授课讲师(角色为教师且设为可见),含讲师资料中的等级与专业领域名称。
- 相关推荐:基于标签等逻辑推荐的同类型课程,受当前用户可见范围过滤,数量有上限。
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
获取课程目录(GET /api/app/course/{courseId}/detail/outline)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
返回
返回结构与学习页目录接口(GET /api/app/course/{courseId}/outline)一致,顶层为 outline、setting;任务节点不包含学习状态字段(无 learningStatus/status),用于未加入学员的目录展示。
json
{
"outline": [
{
"outlineType": "chapter",
"seq": 1,
"title": "第一章",
"children": [
{
"outlineType": "task",
"seq": 1,
"id": 10001,
"title": "任务1",
"type": "text",
"isOptional": false
}
]
}
],
"setting": {
"customChapterEnabled": true
}
}字段说明
顶层字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| outline | array | 课程目录节点列表(章节/单元/任务树) |
| setting | object | 课程目录设置 |
setting 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| customChapterEnabled | boolean | 是否允许自定义章节 |
outline 节点(章节 outlineType=chapter / 单元 outlineType=unit):与学习页目录一致,含 outlineType、seq、title、children 等。
outline 节点(任务类型 outlineType=task):含 outlineType、seq、id、title、type、isOptional 等;不包含学习状态(无 learningStatus),仅供目录展示。
说明
- 用途:用于课程详情页的「目录」展示,已加入与未加入学员均可调用;返回与学习页目录相同的树形结构,但任务节点不包含学员学习状态。
- 与学习页目录的区别:学习页目录(GET
/api/app/course/{courseId}/outline)为已加入学员提供带学习状态(如未开始/进行中/已完成)的目录;本接口仅返回章节目录结构,供详情页预览用。
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_UNPUBLISHED | 403 | 课程未发布 | 课程未发布,不可查看目录 |
COURSE_NOT_VISIBLE | 403 | 课程不可见 | 用户未加入且不在课程可见范围内 |