简介
本开发文档围绕 DouPHP 小程序“课程学习”功能,系统梳理在线学习系统的核心能力与实现方式,包括:
- 课程分类管理、课程内容展示、学习进度跟踪、考试测评系统(扩展建议)
- 课程页面 UI 组件:课程列表、视频播放器、进度条、章节导航等
- 学习业务逻辑:课程解锁机制、学习记录保存、知识掌握度评估
- 完整接口调用示例:报名、开始学习、更新进度、提交考试
- 个性化推荐算法:基于兴趣的课程推荐、学习路径规划
- 常见问题解决方案:离线学习支持、学习中断恢复、成绩统计导出
说明:当前仓库已提供课程/视频的前台 API 与小程序页面基础实现。本文在已有代码基础上进行系统化整理,并对缺失的学习进度、考试、推荐等能力给出可落地的扩展方案。
项目结构
与课程学习相关的关键目录与文件:
- 前台 API 控制器与服务:课程与视频的列表、详情、点击统计
- 小程序前端:课程详情页、视频详情页的页面逻辑与模板
- 路由与数据组装:通过服务层统一构建返回数据,控制器负责校验与响应
graph TB
subgraph "小程序端"
A["课程详情页<br/>course.ts / course.wxml"]
B["视频详情页<br/>video.ts"]
end
subgraph "API 层"
C["课程 API 控制器<br/>CourseController.php"]
D["视频 API 控制器<br/>VideoController.php"]
end
subgraph "业务服务层"
E["课程服务<br/>CourseService.php"]
end
A --> C
B --> D
C --> E
核心组件
- 课程 API 控制器:提供课程列表、分类、归档与课程详情接口;负责参数解析、权限校验、访问统计
- 课程服务:封装课程列表构建、详情渲染(Markdown)、分类查询、点击量统计
- 视频 API 控制器:提供视频列表、详情与点击统计
- 小程序课程/视频页面:加载详情数据、设置分享标题、渲染内容
架构总览
小程序前端通过 HTTP 请求调用后端 API,API 控制器将请求委派给服务层处理,服务层组合模型与工具完成数据组装与持久化操作,最终返回结构化 JSON。
sequenceDiagram
participant MP as "小程序页面"
participant API as "API 控制器"
participant SVC as "业务服务"
participant DB as "数据模型/存储"
MP->>API : 获取课程详情(id)
API->>SVC : buildCourseShowData(id)
SVC->>DB : 查询课程(发布状态)
DB-->>SVC : 课程数据
SVC->>SVC : Markdown 渲染内容
SVC-->>API : 课程数据
API->>DB : 记录点击量(+1)
API-->>MP : 返回{course, defined}
详细组件分析
课程详情接口流程
- 入口:小程序课程详情页 onLoad 时调用课程详情接口
- 控制器:解析路由 ID,调用服务构建详情数据,记录点击量并返回
- 服务:查询已发布课程,多语言处理,Markdown 渲染内容,统计点击量
sequenceDiagram
participant Page as "课程页面(course.ts)"
participant Ctrl as "课程API控制器"
participant Svc as "课程服务"
Page->>Ctrl : GET /course/show?id=...
Ctrl->>Svc : buildCourseShowData(id)
Svc-->>Ctrl : {title,content,...}
Ctrl->>Ctrl : recordCourseView(id)
Ctrl-->>Page : {course, defined}
课程列表与分类
- 列表接口支持按分类、归档(年/月)分页查询
- 服务层使用模型关联预取分类信息,格式化摘要与 URL
- 控制器组装分类树与页头信息返回
flowchart TD
Start(["进入课程列表"]) --> Parse["解析分类ID/归档参数"]
Parse --> Query["分页查询课程(含分类)"]
Query --> Format["格式化课程项(摘要/URL/分类)"]
Format --> BuildTree["构建分类树"]
BuildTree --> Return["返回{course_list, category_tree, pager}"]
视频详情接口流程
- 小程序视频详情页调用视频详情接口
- 控制器解析 ID,调用服务构建详情,记录点击量并返回
sequenceDiagram
participant VPage as "视频页面(video.ts)"
participant VCtrl as "视频API控制器"
participant VSvc as "视频服务"
VPage->>VCtrl : GET /video/show?id=...
VCtrl->>VSvc : buildVideoShowData(id)
VSvc-->>VCtrl : {video, cate_info}
VCtrl->>VCtrl : recordVideoView(id)
VCtrl-->>VPage : {video, defined, cate_info}
课程页面 UI 组件
- 顶部导航栏:显示页面标题
- 内容区:标题、创建时间、点击量、自定义字段、富文本内容
- 分享:设置分享标题为课程标题
graph LR
Nav["navbar 组件"] --> Title["课程标题"]
Title --> Meta["创建时间/点击量/自定义字段"]
Meta --> Content["mp-html 富文本"]
Content --> Share["分享标题设置"]
学习进度跟踪(扩展设计)
- 目标:记录用户观看课程的章节/视频进度,支持断点续学
- 数据模型建议:
- 用户-课程进度表:user_id, course_id, chapter_id, progress(百分比), last_watched_at, status(未开始/进行中/已完成)
- 章节元数据:chapter_id, course_id, title, media_url, duration
- 关键接口:
- 开始学习:POST /learning/start {course_id, chapter_id}
- 更新进度:POST /learning/update {course_id, chapter_id, progress, last_watched_at}
- 查询进度:GET /learning/status?course_id={id}
- 业务规则:
- 进度更新节流:服务端合并多次更新,避免频繁写入
- 自动完成:当 progress>=100% 且持续时长达标,标记为已完成
- 防作弊:校验播放时长与进度一致性
flowchart TD
S(["开始学习"]) --> Check["检查是否已报名/购买"]
Check --> |否| Enroll["引导报名/支付"]
Check --> |是| Play["播放章节/视频"]
Play --> Update["定时上报进度(节流)"]
Update --> Complete{"进度>=100%?"}
Complete --> |是| MarkDone["标记章节完成"]
Complete --> |否| Continue["继续学习"]
[此图为概念设计,不直接映射到具体源码]
考试测评系统(扩展设计)
- 目标:课程结束后进行测评,记录成绩与掌握度
- 数据模型建议:
- 试卷:paper_id, title, pass_score, time_limit
- 题目:question_id, paper_id, type, content, options, answer
- 答卷:attempt_id, user_id, paper_id, score, answers(JSON), submitted_at
- 关键接口:
- 获取试卷:GET /exam/paper/{paper_id}
- 提交答卷:POST /exam/submit {attempt_data}
- 查询成绩:GET /exam/result?paper_id={id}
- 评分策略:客观题自动评分,主观题人工复核;支持错题回顾
sequenceDiagram
participant U as "用户"
participant E as "考试服务"
U->>E : 获取试卷
E-->>U : 返回题目列表
U->>E : 提交答卷
E->>E : 计算得分/生成报告
E-->>U : 返回成绩与解析
[此图为概念设计,不直接映射到具体源码]
个性化推荐算法(扩展设计)
- 目标:基于用户兴趣与学习行为推荐课程/视频
- 数据来源:浏览历史、收藏、学习进度、考试成绩、标签偏好
- 算法思路:
- 协同过滤:相似用户喜欢的课程
- 内容匹配:基于标签/关键词相似度
- 学习路径:根据薄弱知识点推荐前置课程
- 接口建议:
- 推荐列表:GET /recommend/course?user_id={id}&limit=10
- 学习路径:GET /path/recommend?user_id={id}&goal={topic}
[此图为概念设计,不直接映射到具体源码]
依赖关系分析
- 控制器依赖服务:课程/视频控制器均依赖对应服务完成数据构建与统计
- 服务依赖模型与工具:课程服务使用 Markdown 渲染、多语言处理、分页与排序
- 小程序页面依赖 HTTP 服务与路由工具:统一发起请求与跳转
graph TB
P1["课程页面(course.ts)"] --> C1["课程API控制器"]
P2["视频页面(video.ts)"] --> C2["视频API控制器"]
C1 --> S1["课程服务(CourseService)"]
C2 --> S2["视频服务(VideoService)"]
S1 --> M1["课程模型/存储"]
S2 --> M2["视频模型/存储"]
性能考虑
- 列表分页:合理设置每页数量,避免一次性加载过多数据
- 图片与富文本:对图片进行压缩与懒加载,富文本按需渲染
- 点击统计:采用异步或批量上报,降低主流程阻塞
- 缓存策略:课程分类树、热门课程列表可短期缓存
- 接口限流:防止恶意刷量导致统计失真
故障排查指南
- 页面空白或数据为空:
- 检查课程是否已发布,路由 ID 是否正确
- 查看 API 返回的错误码与消息
- 分享标题不正确:
- 确认页面 onLoad 中设置的分享标题来源
- 点击量未增加:
- 检查控制器是否调用统计方法,数据库写入是否成功
- 富文本渲染异常:
- 检查 Markdown 渲染配置与内容格式
结论
当前仓库已具备课程与视频的基础学习与展示能力,包含列表、详情、点击统计与小程序页面渲染。为实现完整的在线学习系统,建议在现有基础上扩展学习进度跟踪、考试测评与个性化推荐模块,完善报名与解锁机制,提升用户体验与学习效果。
附录
- 常用接口参考(基于现有代码):
- 课程列表:GET /course/index (支持分类、归档、分页)
- 课程详情:GET /course/show (返回课程与自定义字段)
- 视频列表:GET /video/index (支持分类、归档、分页)
- 视频详情:GET /video/show (返回视频信息与分类)
- 小程序页面参考:
- 课程详情页:course.ts / course.wxml
- 视频详情页:video.ts