本项目采用微信小程序原生框架,后端使用云开发,无需单独购买服务器。开发前请确保已完成以下准备。
访问微信公众平台(https://mp.weixin.qq.com/),注册小程序账号,获取AppID。下载并安装微信开发者工具(https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html)。
在微信开发者工具中,新建项目,填入AppID,后端服务选择“微信云开发”。项目创建后,点击云开发控制台,开通环境,环境名称建议为“prod-档案教育”。记录环境ID,后续配置需要。
在项目根目录下,创建以下标准目录结构。
project/
├── pages/
│ ├── index/ 首页
│ ├── course/ 课程列表页
│ ├── study/ 学习页
│ └── profile/ 个人中心页
├── cloudfunctions/ 云函数目录
├── components/ 自定义组件
├── images/ 图片资源
└── utils/ 工具类
在app.js的onLaunch生命周期中初始化云开发环境。
App({
onLaunch: function () {
wx.cloud.init({
env: 'prod-档案教育-环境ID', // 替换为你的环境ID
traceUser: true,
})
}
})
在云开发控制台的“数据库”标签页中,创建以下四个集合(表)。
用于存储所有课程信息。点击“添加集合”,输入名称“courses”。创建后,添加初始记录,字段结构如下:
{
"_id": "自动生成",
"title": "《档案数字化管理规范》解读",
"cover": "cloud://xxx.png", // 云存储文件ID
"description": "本课程详细讲解...",
"duration": 90, // 课程时长(分钟)
"chapterList": [ // 章节列表
{
"title": "第一章",
"videoId": "cloud://xxx.mp4"
}
],
"isFree": false,
"credit": 5, // 学时
"createTime": "数据库自动生成时间戳"
}
集合名:study_records。记录用户学习进度。
{
"_id": "自动生成",
"userId": "用户openid",
"courseId": "课程_id",
"chapterIndex": 0, // 当前学习到的章节索引
"progress": 30, // 当前章节观看进度(百分比)
"status": "studying", // studying, finished
"lastStudyTime": "最后学习时间戳"
}
集合名:certificates。用户完成课程后生成证明。
{
"_id": "自动生成",
"userId": "用户openid",
"courseId": "课程_id",
"credit": 5,
"createTime": "完成时间戳",
"certificateNo": "ZS202311270001" // 证书编号
}
集合名:banners。用于首页运营位。
{
"_id": "自动生成",
"imageUrl": "cloud://xxx.jpg",
"link": "/pages/course/detail?id=xxx",
"order": 1
}
首页主要包括轮播图、课程分类和推荐课程列表。在index.js的onLoad函数中加载数据。
// index.js
Page({
data: {
bannerList: [],
courseList: []
},
onLoad: function() {
this.loadBannerData();
this.loadCourseData();
},
loadBannerData: async function() {
const db = wx.cloud.database();
const res = await db.collection('banners')
.orderBy('order', 'asc')
.get();
this.setData({ bannerList: res.data });
},
loadCourseData: async function() {
const db = wx.cloud.database();
const res = await db.collection('courses')
.limit(10)
.get();
this.setData({ courseList: res.data });
}
})
在index.wxml中,使用swiper组件展示轮播图,使用wx:for循环渲染课程列表。
这是最核心的页面,包含视频播放器与进度同步。页面接收课程ID参数。

// study.js
Page({
data: {
videoContext: null,
course: {},
currentChapterIndex: 0,
studyRecord: null
},
onLoad: function(options) {
this.courseId = options.id;
this.loadCourseDetail();
this.loadOrCreateStudyRecord();
},
// 加载课程详情
loadCourseDetail: async function() {
const db = wx.cloud.database();
const res = await db.collection('courses').doc(this.courseId).get();
this.setData({ course: res.data });
// 创建视频上下文
this.videoContext = wx.createVideoContext('studyVideo');
},
// 加载或创建学习记录
loadOrCreateStudyRecord: async function() {
const db = wx.cloud.database();
const _ = db.command;
const openid = wx.getStorageSync('openid');
// 查询是否已有记录
const recordRes = await db.collection('study_records')
.where({
userId: openid,
courseId: this.courseId
})
.get();
if (recordRes.data.length > 0) {
this.setData({ studyRecord: recordRes.data[0] });
} else {
// 创建新记录
const newRecord = {
userId: openid,
courseId: this.courseId,
chapterIndex: 0,
progress: 0,
status: 'studying',
lastStudyTime: db.serverDate()
};
const addRes = await db.collection('study_records').add({ data: newRecord });
this.setData({ studyRecord: { _id: addRes._id, ...newRecord } });
}
}
})
在study.wxml中,放置video组件,并绑定播放事件。
实现onTimeUpdate函数,每隔10秒将播放进度同步到数据库。
// study.js 中继续添加
onTimeUpdate: function(e) {
const currentTime = e.detail.currentTime;
const duration = e.detail.duration;
const progress = Math.round((currentTime / duration) 100);
// 节流:每10秒或进度变化超过5%时更新一次
if (Date.now() - this.lastUpdateTime > 10000 || Math.abs(progress - this.lastProgress) > 5) {
this.updateStudyProgress(progress);
this.lastUpdateTime = Date.now();
this.lastProgress = progress;
}
},
updateStudyProgress: async function(progress) {
const db = wx.cloud.database();
await db.collection('study_records').doc(this.data.studyRecord._id).update({
data: {
progress: progress,
lastStudyTime: db.serverDate()
}
});
}
当用户学习进度达到100%时,触发完成逻辑。在study.js中监听视频结束事件。
// 在 video 组件上绑定 bindended 事件
//
onVideoEnded: async function() {
const { studyRecord, course } = this.data;
const db = wx.cloud.database();
const _ = db.command;
// 更新学习记录状态为完成
await db.collection('study_records').doc(studyRecord._id).update({
data: {
status: 'finished'
}
});
// 生成学时证明记录
const certificateNo = 'ZS' + new Date().getTime() + Math.floor(Math.random()1000);
await db.collection('certificates').add({
data: {
userId: studyRecord.userId,
courseId: course._id,
credit: course.credit,
createTime: db.serverDate(),
certificateNo: certificateNo
}
});
wx.showToast({ title: '课程完成,学时证明已生成' });
}
小程序端无法直接获取用户OpenID,需通过云函数获取。
1. 在cloudfunctions目录右键,新建Node.js云函数,命名为“getOpenId”。
2. 修改index.js文件。
// cloudfunctions/getOpenId/index.js
const cloud = require('wx-server-sdk')
cloud.init({ env: process.env.Env })
exports.main = async (event, context) => {
const wxContext = cloud.getWXContext()
return {
openid: wxContext.OPENID,
appid: wxContext.APPID,
unionid: wxContext.UNIONID,
}
}
3. 右键云函数目录,选择“上传并部署:云端安装依赖”。
4. 在小程序页面中调用。
// 在app.js或需要的页面中调用
wx.cloud.callFunction({
name: 'getOpenId',
success: res => {
const openid = res.result.openid;
wx.setStorageSync('openid', openid);
}
})
进入云开发控制台“存储”标签页,创建文件夹“course_media”。将课程封面图、视频文件上传至此。上传后,点击文件详情,复制“File ID”(格式为cloud://xxx),将其填入courses集合对应记录的字段中。
在微信开发者工具点击“上传”,填写版本号与备注。登录微信公众平台,在“版本管理”中,将上传的版本设为“体验版”,可生成体验二维码进行测试。确认无误后,提交审核。
确保小程序类目选择为“教育 > 在线教育”。在“设置”->“基本设置”->“服务类目”中添加。隐私协议需在“设置”->“服务内容声明”中配置,明确说明收集的用户学习数据用途。
云开发支持通过云函数实现后台管理API。创建一个名为“admin”的云函数,用于课程和轮播图的增删改查。使用cloud.database()的API进行操作。为简化,可暂时使用云开发控制台的数据库管理界面直接添加和修改数据。
如需更复杂的后台,可参考微信云开发官方文档,使用CMS内容管理系统快速搭建。