Appearance
课程学习接口
接口总览
| 名称 | 方法 | 路径 |
|---|---|---|
| 获取课程目录 | GET | /api/app/course/{courseId}/outline |
| 获取课程任务学习信息 | GET | /api/app/course/{courseId}/task/{taskId}/learning |
| 下载任务资料 | GET | /api/app/course/{courseId}/task/{taskId}/material/{materialId}/download |
| 播放任务资料 | GET | /api/app/course/{courseId}/task/{taskId}/material/{materialId}/play |
| 学习事件上报 | POST | /api/app/course/{courseId}/task/{taskId}/trigger/doing |
| 完成事件上报 | POST | /api/app/course/{courseId}/task/{taskId}/trigger/finish |
| 观看事件上报 | POST | /api/app/course/{courseId}/task/{taskId}/trigger/watching |
获取课程目录(GET /api/app/course/{courseId}/outline)
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
返回
json
{
"outline": [
{
"outlineType": "chapter",
"seq": 1,
"title": "第一章",
"children": [
{
"outlineType": "task",
"seq": 1,
"taskId": 10001,
"title": "任务1",
"type": "text",
"isOptional": false,
"status": "finished"
}
]
}
],
"setting": {
"customChapterEnabled": true
}
}字段说明
顶层字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| outline | array | 课程目录节点列表 |
| setting | object | 课程目录设置 |
setting 字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| customChapterEnabled | boolean | 是否允许自定义章节 |
outline 节点字段(章节类型 outlineType=chapter):
| 字段 | 类型 | 说明 |
|---|---|---|
| outlineType | string | 节点类型:chapter |
| seq | number | 序号 |
| title | string | 章节标题 |
| children | array | 子节点列表(任务节点) |
outline 节点字段(任务类型 outlineType=task):
| 字段 | 类型 | 说明 |
|---|---|---|
| outlineType | string | 节点类型:task |
| seq | number | 序号 |
| taskId | number | 任务ID |
| title | string | 任务标题 |
| type | string | 任务类型:text(图文)/download(下载)/ppt(PPT)/video(视频)/audio(音频)/doc(文档)/discuss(讨论) |
| isOptional | boolean | 是否是选修任务 |
| status | string | 任务状态:none/start/finished |
课程详情页目录接口(GET /api/app/course/{courseId}/detail/outline)返回结构与本节一致,但任务节点不包含学习状态(learningStatus),供未加入学员查看目录。
获取课程任务学习信息(GET /api/app/course/{courseId}/task/{taskId}/learning)
请求参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
返回
返回示例
不同任务类型的 activity.media 字段结构不同:
图文任务(mediaType=text):
json
{
"isProhibitDownload": false,
"content": "<p>图文内容</p><img src=\"https://cdn.example.com/image.png\" />",
"playerWatermarkTxt": ["用户名", "2025-01-01"],
"playerWatermarkColor": "#000000",
"playerWatermarkAlpha": 80
}下载任务(mediaType=download):
json
{
"mediaCount": 3,
"materials": [
{
"id": 20001,
"name": "课程资料.pdf",
"description": "第一章学习资料",
"size": 1024000,
"type": "pdf",
"ext": "pdf",
"convertStatus": "success",
"globalId": "abc123def456"
}
]
}PPT任务(mediaType=ppt):
json
{
"url": "https://cdn.example.com/file.ppt",
"resNo": "abc123def456",
"token": "token123456",
"images": ["https://cdn.example.com/image1.jpg"],
"playMode": "auto",
"fileStorage": "cloud",
"fileConvertStatus": "success",
"playerWatermarkTxt": ["用户名", "2025-01-01"],
"playerWatermarkColor": "#000000",
"playerWatermarkAlpha": 80,
"cloudSdkBaseUri": "https://sdk.example.com"
}视频任务(mediaType=video):
json
{
"url": "https://cdn.example.com/video.mp4",
"resNo": "abc123def456",
"token": "token123456",
"mediaSource": "self",
"fileStorage": "cloud",
"fileConvertStatus": "success",
"playerWatermarkTxt": ["用户名", "2025-01-01"],
"playerWatermarkColor": "#000000",
"playerWatermarkAlpha": 80,
"enablePlaybackRates": true,
"cloudSdkBaseUri": "https://sdk.example.com",
"watchTimeReportCycle": 60
}音频任务(mediaType=audio):
json
{
"url": "https://cdn.example.com/audio.mp3",
"resNo": "abc123def456",
"token": "token123456",
"fileConvertStatus": "success",
"playerWatermarkTxt": ["用户名", "2025-01-01"],
"playerWatermarkColor": "#000000",
"playerWatermarkAlpha": 80,
"enablePlaybackRates": true,
"cloudSdkBaseUri": "https://sdk.example.com",
"watchTimeReportCycle": 60
}文档任务(mediaType=doc):
json
{
"url": "https://cdn.example.com/doc.pdf",
"resNo": "abc123def456",
"token": "token123456",
"fileStorage": "cloud",
"fileConvertStatus": "success",
"playerWatermarkTxt": ["用户名", "2025-01-01"],
"playerWatermarkColor": "#000000",
"playerWatermarkAlpha": 80,
"cloudSdkBaseUri": "https://sdk.example.com"
}字段说明
顶层字段
| 字段 | 类型 | 说明 |
|---|---|---|
| setting | object | 课程学习设置 |
| course | object | 课程信息 |
| task | object | 任务信息(含 prevTaskId、nextTaskId) |
| activity | object | 活动信息 |
| taskResult | object | 任务学习结果信息 |
setting 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| rewardPointName | string | 积分名称 |
course 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 课程ID |
| title | string | 课程标题 |
| categoryId | number | 分类ID |
| serializeMode | string | 连载方式 |
| credit | number | 完成课程奖励的学分数量 |
| rewardPoint | number | 课程奖励积分 |
| learnTimeReportCycle | number | 学习时长上报周期/秒 |
| learnTimeAntiBrushEnabled | boolean | 是否开启学习防刷 |
task 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 任务ID |
| courseId | number | 课程ID |
| type | string | 任务类型:text(图文)/download(下载)/ppt(PPT)/video(视频)/audio(音频)/doc(文档)/discuss(讨论) |
| number | number | 任务编号 |
| title | string | 任务标题 |
| status | string | 任务状态:create/publish/unpublish |
| isOptional | boolean | 是否是选修任务 |
| seq | number | 任务序号 |
| length | number/null | 任务时长/分钟(图文/视频/音频/文档任务表示需要学习的时长,PPT任务表示页数,下载/讨论任务为null) |
| rewardPoint | number | 完成任务奖励积分 |
| prevTaskId | number/null | 上一任务ID |
| nextTaskId | number/null | 下一任务ID |
| finishCondition | object | 完成条件 |
finishCondition 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| finishType | string | 完成类型:time(学习时长)/download(下载)/end(学习到最后一页)/join_discuss(参与讨论) |
| finishDetail | number/null | 完成详情:time类型为需要学习的时长(分钟),end/download/join_discuss类型为null |
activity 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 活动ID |
| title | string | 活动标题 |
| remark | string | 备注 |
| mediaId | number | 教学活动详细信息Id |
| mediaType | string | 教学活动详细信息类型:text(图文)/download(下载)/ppt(PPT)/video(视频)/audio(音频)/doc(文档)/discuss(讨论) |
| length | number/null | 活动时长/分钟(PPT任务表示页数,下载/讨论任务为null) |
| taskId | number/null | 任务ID,用于视频类型查询弹题标记 |
| media | object | 教学活动详细信息(结构因 mediaType 而异,详见下方说明) |
activity.media 字段说明
图文任务(mediaType=text):
| 字段 | 类型 | 说明 |
|---|---|---|
| isProhibitDownload | boolean | 是否禁止下载 |
| content | string | 图文内容(HTML格式,已处理图片地址为绝对URL) |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
下载任务(mediaType=download):
| 字段 | 类型 | 说明 |
|---|---|---|
| mediaCount | number | 资料数量 |
| materials | array | 下载资料列表 |
materials 数组项字段:
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 资料ID |
| name | string | 资料名称 |
| description | string/null | 资料描述 |
| size | number | 资料大小(字节) |
| type | string/null | 文件类型 |
| ext | string/null | 文件扩展名 |
| convertStatus | string/null | 文件转换状态 |
| globalId | string/null | 文件全局ID |
PPT任务(mediaType=ppt):
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 本地资源地址 |
| resNo | string | 资源编号 |
| token | string | 访问token |
| images | array | PPT图片列表 |
| playMode | string | 播放模式 |
| fileStorage | string | 文件存储类型 |
| fileConvertStatus | string | 文件转换状态 |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
| cloudSdkBaseUri | string | 云SDK基础地址 |
视频任务(mediaType=video):
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 本地资源地址 |
| resNo | string | 资源编号 |
| token | string | 访问token |
| mediaSource | string | 视频源(self/livereplay/segment/外链) |
| fileStorage | string | 文件存储类型 |
| fileConvertStatus | string | 文件转换状态 |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
| enablePlaybackRates | boolean | 是否开启倍速播放 |
| cloudSdkBaseUri | string | 云SDK基础地址 |
| watchTimeReportCycle | number | 观看时长上报周期/秒 |
| startAt | number/null | 分段起始时间(毫秒),智萃分段视频时返回,详见 api-course-learning-segment-video |
| endAt | number/null | 分段结束时间(毫秒),智萃分段视频时返回 |
| segmentId | number/null | 分段 ID,智萃分段视频时返回 |
| hasMarker | boolean | 是否有弹题驻点(仅视频任务有效) |
音频任务(mediaType=audio):
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 本地资源地址 |
| resNo | string | 资源编号 |
| token | string | 访问token |
| fileConvertStatus | string | 文件转换状态 |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
| enablePlaybackRates | boolean | 是否开启倍速播放 |
| cloudSdkBaseUri | string | 云SDK基础地址 |
| watchTimeReportCycle | number | 观看时长上报周期/秒 |
文档任务(mediaType=doc):
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string | 本地资源地址 |
| resNo | string | 资源编号 |
| token | string | 访问token |
| fileStorage | string | 文件存储类型 |
| fileConvertStatus | string | 文件转换状态 |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
| cloudSdkBaseUri | string | 云SDK基础地址 |
讨论任务(mediaType=discuss):
| 字段 | 类型 | 说明 |
|---|---|---|
| content | string | 讨论内容(HTML格式,已处理图片地址为绝对URL) |
| playerWatermarkTxt | array | 播放器水印文本列表 |
| playerWatermarkColor | string | 播放器水印颜色 |
| playerWatermarkAlpha | number | 播放器水印透明度 |
taskResult 字段
| 字段 | 类型 | 说明 |
|---|---|---|
| id | number | 任务结果ID |
| activityId | number | 活动ID |
| courseId | number | 课程ID |
| courseTaskId | number | 课程任务ID |
| status | string | 状态:none(未开始)/start(学习中)/finished(已完成) |
| maxLearnTime | number | 最大学习时间/秒 |
| lastLearnTime | number | 最后学习时间时间戳 |
| learnUuid | string | 学习的UUID |
| finishedTime | number/null | 完成时间时间戳 |
| time | number | 任务进行时长/秒 |
| watchTime | number | 观看时间/秒 |
| remainTime | number | 剩余时间/秒 |
| currentTime | number | 当前时间时间戳 |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
下载任务资料(GET /api/app/course/{courseId}/task/{taskId}/material/{materialId}/download)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
| materialId | number | 是 | 资料ID |
返回
json
{
"downloadUrl": "https://play.qiqiuyun.net/sdk_api/download?resNo=abc123def456&token=eyJ0eXAiOiJKV1QiLCJhbGc..."
}字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| downloadUrl | string | 下载URL(云存储返回带Token的URL,本地存储返回文件下载路径) |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
COURSE_TASK_UNPUBLISHED | 403 | 课程任务未发布 | 任务状态为 create |
COURSE_TASK_CANCEL_PUBLISHED | 403 | 课程任务已取消发布 | 任务状态为 unpublish |
COURSE_TASK_LOCKED | 403 | 课程任务未解锁 | 前置任务未完成(锁定模式) |
COURSE_MATERIAL_NOT_FOUND | 404 | 课程资料不存在 | materialId 无效或已删除 |
COURSE_MATERIAL_NOT_BELONG_TO_TASK | 403 | 课程资料不属于该任务 | 资料不属于指定的下载任务 |
说明
- 权限校验:接口会校验用户是否为课程学员、课程是否已发布、任务是否已发布等。
- 任务锁定:如果课程为锁定模式,会校验前置任务是否已完成。
- 资料归属:会校验资料是否属于指定的下载任务。
- 下载URL:
- 云存储:返回带JWT Token的下载URL,有效期5分钟
- 本地存储:返回本地文件下载路径
- SSL协议:系统会根据请求自动判断使用
http或https协议。
播放任务资料(GET /api/app/course/{courseId}/task/{taskId}/material/{materialId}/play)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
| materialId | number | 是 | 资料ID |
返回
云存储示例:
json
{
"url": null,
"resNo": "abc123def456",
"token": "token123456",
"fileStorage": "cloud",
"fileConvertStatus": "success",
"cloudSdkBaseUri": "https://sdk.example.com"
}本地存储示例:
json
{
"url": "//example.com/player/20001/file/abc123def456.pdf",
"resNo": null,
"token": "abc123def456",
"fileStorage": "local",
"fileConvertStatus": "success",
"cloudSdkBaseUri": null
}字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| url | string/null | 播放URL(本地存储返回文件播放路径,云存储为null,需要通过SDK生成) |
| resNo | string | 资源编号 |
| token | string | 访问token |
| fileStorage | string | 文件存储类型:cloud(云存储)/local(本地存储) |
| fileConvertStatus | string | 文件转换状态 |
| cloudSdkBaseUri | string | 云SDK基础地址 |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
COURSE_TASK_UNPUBLISHED | 403 | 课程任务未发布 | 任务状态为 create |
COURSE_TASK_CANCEL_PUBLISHED | 403 | 课程任务已取消发布 | 任务状态为 unpublish |
COURSE_TASK_LOCKED | 403 | 课程任务未解锁 | 前置任务未完成(锁定模式) |
COURSE_MATERIAL_NOT_FOUND | 404 | 课程资料不存在 | materialId 无效或已删除 |
COURSE_MATERIAL_NOT_BELONG_TO_TASK | 403 | 课程资料不属于该任务 | 资料不属于指定的任务 |
说明
- 权限校验:接口会校验用户是否为课程学员、课程是否已发布、任务是否已发布等。
- 任务锁定:如果课程为锁定模式,会校验前置任务是否已完成。
- 资料归属:会校验资料是否属于指定的任务。
- 播放URL:
- 云存储:
url字段为null,需要客户端使用resNo、token和cloudSdkBaseUri通过云SDK生成播放URL - 本地存储:
url字段返回本地文件播放路径,格式为//{host}/player/{fileId}/file/{token}.{ext}
- 云存储:
- 与下载接口的区别:
- 下载接口直接返回完整的下载URL(云存储和本地存储都返回完整URL)
- 播放接口的云存储不返回完整URL,需要客户端通过SDK生成
- 适用场景:用于在线播放任务资料,适用于视频、音频、文档等可播放类型的资料。
学习事件上报(POST /api/app/course/{courseId}/task/{taskId}/trigger/doing)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
请求体:
json
{
"lastAt": 1735660800,
"learnUuid": "6b8029e83003401ab0b796be594ad37a",
"lastLearnTime": 120.5,
"trigger": "play",
"watchTime": 120
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lastAt | number | 否 | 上次学习请求时间时间戳 |
| learnUuid | string | 是 | 学习的UUID |
| lastLearnTime | number | 否 | 上次学习进度(单位秒) |
| trigger | string | 否 | 触发点来源:play 等 |
| watchTime | number | 否 | 观看时长/秒 |
返回
json
{
"taskId": 10001,
"nextTaskId": 10002,
"event": "doing",
"type": "text",
"lastLearnAt": 1735660800,
"remainingLearnTime": 480,
"learnUuid": "6b8029e83003401ab0b796be594ad37a",
"maxLearnTime": 600,
"learnTime": 120.5,
"finishedTime": null,
"doingTime": 120,
"watchTime": 120,
"currentTime": 1735660920,
"taskStatus": "start",
"firstTaskFinished": false,
"firstCourseFinished": false
}字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
| taskId | number | 任务ID |
| nextTaskId | number/null | 下一个任务ID |
| event | string | 触发事件:doing |
| type | string | 任务类型:text(图文)/download(下载)/ppt(PPT)/video(视频)/audio(音频)/doc(文档)/discuss(讨论) |
| lastLearnAt | number | 上次学习时间时间戳 |
| remainingLearnTime | number | 剩余学习时间/秒 |
| learnUuid | string | 学习的UUID |
| maxLearnTime | number | 最大学习时间/秒 |
| learnTime | number | 上次学习进度(单位秒) |
| finishedTime | number/null | 完成时间时间戳 |
| doingTime | number | 任务进行时长/秒 |
| watchTime | number | 观看时间/秒 |
| currentTime | number | 当前时间时间戳 |
| taskStatus | string | 任务完成状态:none(未开始)/start(学习中)/finished(已完成) |
| firstTaskFinished | boolean | 是否是第一次任务完成 |
| firstCourseFinished | boolean | 是否是第一次课程完成 |
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
COURSE_TASK_RESULT_NOT_FOUND | 404 | 任务学习结果不存在 | 需要先调用学习信息接口 |
完成事件上报(POST /api/app/course/{courseId}/task/{taskId}/trigger/finish)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
请求体:
json
{
"lastAt": 1735660800,
"learnUuid": "6b8029e83003401ab0b796be594ad37a",
"lastLearnTime": 600.0
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lastAt | number | 是 | 上次学习请求时间时间戳 |
| learnUuid | string | 是 | 学习的UUID |
| lastLearnTime | number | 是 | 上次学习进度(单位秒) |
返回
json
{
"taskId": 10001,
"nextTaskId": 10002,
"event": "finish",
"type": "text",
"lastLearnAt": 1735660800,
"remainingLearnTime": 0,
"learnUuid": "6b8029e83003401ab0b796be594ad37a",
"maxLearnTime": 600,
"learnTime": 600.0,
"finishedTime": 1735660920,
"doingTime": 600,
"watchTime": 600,
"currentTime": 1735660920,
"taskStatus": "finished",
"firstTaskFinished": true,
"firstCourseFinished": false
}字段说明
返回字段与学习事件上报相同,主要区别:
| 字段 | 类型 | 说明 |
|---|---|---|
| event | string | 触发事件:finish |
| taskStatus | string | 任务完成状态:finished(已完成) |
| finishedTime | number | 完成时间时间戳 |
| remainingLearnTime | number | 剩余学习时间/秒(通常为0) |
其他字段说明参见学习事件上报接口。
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
COURSE_TASK_RESULT_NOT_FOUND | 404 | 任务学习结果不存在 | 需要先调用学习信息接口 |
观看事件上报(POST /api/app/course/{courseId}/task/{taskId}/trigger/watching)
请求参数
路径参数:
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| courseId | number | 是 | 课程ID |
| taskId | number | 是 | 任务ID |
请求体:
json
{
"lastAt": 1735660800,
"learnUuid": "6b8029e83003401ab0b796be594ad37a",
"lastLearnTime": 120.5,
"watchTime": 120
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| lastAt | number | 否 | 上次学习请求时间时间戳 |
| learnUuid | string | 是 | 学习的UUID |
| lastLearnTime | number | 否 | 上次学习进度(单位秒) |
| watchTime | number | 否 | 观看时长/秒 |
返回
返回格式与学习事件上报相同,主要区别:
| 字段 | 类型 | 说明 |
|---|---|---|
| event | string | 触发事件:watching |
字段说明
返回字段与学习事件上报相同,参见学习事件上报接口字段说明。
异常
| 错误码 | HTTP状态码 | 错误信息 | 说明 |
|---|---|---|---|
COURSE_NOT_FOUND | 404 | 课程不存在 | courseId 无效或已删除 |
COURSE_TASK_NOT_FOUND | 404 | 课程任务不存在 | taskId 无效或已删除 |
COURSE_MEMBER_NOT_FOUND | 403 | 学员未加入课程 | 当前登录用户不是该课程成员 |
COURSE_TASK_RESULT_NOT_FOUND | 404 | 任务学习结果不存在 | 需要先调用学习信息接口 |
任务学习流程说明
1. 获取课程目录
学员进入课程学习页面时,首先调用获取课程目录接口,获取课程的任务列表和目录结构。
2. 获取任务学习信息
学员点击某个任务时,调用获取课程任务学习信息接口,获取任务的详细信息,包括:
- 任务基本信息(标题、类型、完成条件等)
- 活动信息(内容、媒体资源等)
- 学习进度信息(已学习时长、剩余时长等)
3. 学习事件上报
学员在学习任务过程中,需要定期调用学习事件上报接口(doing),用于记录学习进度。建议上报频率:
- 每隔一定时间(如30秒)上报一次
- 页面可见性变化时上报
- 页面关闭前上报
4. 完成事件上报
当学员完成任务要求后,调用完成事件上报接口(finish),系统会:
- 更新任务完成状态
- 记录完成时间
- 发放任务奖励(积分等)
- 更新课程进度
5. 观看事件上报(可选)
对于视频、音频等媒体类型,可以调用观看事件上报接口(watching),用于精确记录观看时长。
任务完成条件
不同任务类型的完成条件:
| 任务类型 | 完成类型 | 完成条件 |
|---|---|---|
| 图文 | time | 累计学习时长(秒) >= finishDetail * 60 |
| 视频 | time | 累计学习时长(秒) >= finishDetail * 60 |
| 音频 | time | 累计学习时长(秒) >= finishDetail * 60 |
| 文档 | time | 累计学习时长(秒) >= finishDetail * 60 |
| PPT | end | 学习到最后一页 |
| PPT | time | 累计学习时长(秒) >= finishDetail * 60 |
| 下载 | download | 下载任意资料 |
| 讨论 | join_discuss | 参与讨论 |
注意事项
学习UUID:每次开始学习任务时,系统会生成一个唯一的学习UUID(
learnUuid),后续所有事件上报都需要携带此UUID,用于防刷和进度追踪。学习时长计算:任务的学习时长通过
doing和finish事件上报来累计,系统会根据上报的时间间隔和时长计算累计学习时间。防刷机制:如果课程开启了学习防刷(
learnTimeAntiBrushEnabled=true),系统会校验学习UUID的有效性和学习时长的合理性。完成条件:需要学习时长的任务必须满足学习时长要求才能完成,学员需要持续学习达到指定时长后才能调用完成事件上报接口。
任务状态:任务状态包括:
none:未开始start:学习中finished:已完成
选修任务:如果任务为选修任务(
isOptional=true),完成与否不影响课程完成进度。水印字段:所有任务类型的播放器水印字段统一使用
playerWatermarkTxt、playerWatermarkColor、playerWatermarkAlpha命名。下载任务:下载任务的资料列表字段为
materials,每个资料项包含id(资料ID)、name(资料名称)、ext(文件扩展名)等字段。下载资料时需要使用资料ID调用下载接口。