研究背景
在教育信息化 2.0 行动计划的推动下,数字化学习工具逐渐融入中小学的日常教学与课后辅导中。中小学生的注意力持续时间较短,传统的刷题模式形式单一、趣味性不足,难以调动学生的学习积极性,而游戏化学习模式将学习与互动、竞赛相结合,能够有效提升学生的参与度和学习效率。 微信作为国内用户量最大的社交平台,其小程序生态日趋完善,具有无需下载安装、即用即走、开发成本低、传播便捷等特点,非常适合开发轻量化的教育类应用。同时,腾讯微信云开发技术为小程序提供了一站式的云端开发解决方案,无需开发者搭建独立的服务器和域名,降低了小程序的开发和部署门槛,为教育类小程序的快速开发提供了技术支撑。在此背景下,设计并实现一款基于微信云开发的中小学学科答题小程序,能够满足校方、教师的教学辅助需求和家长的课后辅导需求,助力中小学教育的数字化转型。
主要研究内容
(1)通过调研中小学教学和课后辅导的实际需求,结合游戏化学习理论,完成小程序的功能性和非功能性需求分析,并进行技术、经济、操作可行性分析; (2)确定小程序的设计原则,设计基于微信云开发的系统架构,将小程序划分为前端用户模块和后台管理模块,并对各模块的功能进行详细设计; (3)根据需求分析和总体设计,完成小程序的数据库设计,设计用户表、题库表、答题记录表、竞赛表等核心数据表的结构; (4)选择微信小程序平台和腾讯云开发技术作为核心技术栈,完成小程序前端页面的开发、云函数的编写和后台管理功能的实现; (5)制定详细的系统部署步骤,完成小程序的本地部署和云端发布,并设计功能测试用例,对小程序的各项功能进行测试,验证系统的稳定性和实用性; (6)总结本次研究的成果和不足,对小程序的后续优化和功能拓展进行展望。
系统需求分析
需求分析是系统开发的基础,通过调研校方、教师、家长和学生的实际需求,明确系统的功能和性能要求,为后续的系统设计和实现提供依据。本次调研采用问卷调查和访谈相结合的方式,调研对象包括中小学教师、家长和学生,共发放问卷 300 份,回收有效问卷 286 份,访谈中小学教师 20 名、家长 30 名。
功能性需求
根据调研结果,将中小学学科答题小程序的用户分为普通用户(学生)、** 管理用户(教师 / 家长 / 校方管理员)** 两类,不同用户的功能性需求不同,同时小程序需满足基础的系统管理需求,具体功能性需求如下: 2.1.1 普通用户(学生)需求 普通用户为中小学学生,核心需求是通过小程序进行学科知识点的练习和答题竞赛,具体需求包括: (1)用户登录:支持通过微信授权快速登录,无需单独注册账号,登录后可查看个人信息和答题记录; (2)题库选择:支持按照学科(数学、语文、英语等)和知识点对题库进行分类筛选,方便学生选择针对性的知识点进行练习; (3)随机抽题:支持选择特定学科或知识点,由系统随机生成题目进行练习,抽题数量可灵活选择; (4)答题练习:答题过程中显示题目序号、题干和答题选项,支持选择题、判断题等常见题型,答题完成后即时显示答题结果; (5)解析详解:每道题目答题完成后,提供详细的解答和解题思路解析,帮助学生理解错题原因,巩固知识点; (6)答题竞赛:支持参与模拟竞赛,竞赛前可查看竞赛规则(答题时间、题目数量),竞赛过程中倒计时显示,答题完成后即时显示竞赛成绩; (7)排行榜查看:支持查看答题竞赛的积分排行榜,按积分从高到低排序,显示用户昵称、积分和排名,提升学习的竞争性; (8)个人中心:支持查看个人答题记录(答题次数、正确率、错题集)、竞赛记录(竞赛次数、最高成绩、平均成绩),可修改个人昵称等基础信息。
系统基础需求
(1)权限管理:实现超级管理员和普通管理员的权限分离,超级管理员拥有所有操作权限,普通管理员仅拥有题库管理、答题参数设置等部分权限; (2)数据备份与恢复:支持对题库、用户信息等核心数据进行备份,防止数据丢失;支持在数据异常时进行数据恢复; (3)缓存清理:支持清理小程序的本地缓存,提升小程序的运行速度。
性能需求
(1)响应速度:小程序前端页面的加载时间不超过 3 秒,随机抽题、答题结果展示、排行榜查看等操作的响应时间不超过 1 秒; (2)并发处理:支持至少 100 名用户同时参与答题竞赛,系统无卡顿、无延迟; (3)数据处理:支持 Excel 文件批量导入题库,5000 条数据的导入时间不超过 30 秒。
技术可行性
本小程序基于微信小程序平台和腾讯微信云开发技术进行开发,相关技术均为腾讯官方推出,技术文档完善、社区支持活跃,开发门槛较低。 (1)微信小程序的开发框架提供了丰富的组件和 API,支持前端页面的快速开发,且兼容 iOS 和 Android 两大移动操作系统; (2)微信云开发技术提供了云函数、云数据库、云存储、定时器等一站式云端服务,无需开发者搭建独立的服务器和域名,降低了后端开发的复杂度; (3)开发所需的辅助技术如 Node.js、NPM 均为开源技术,学习资源丰富,开发者可快速掌握; (4)微信开发者工具为小程序的开发、调试、预览、部署提供了一体化的支持,支持本地调试和真机测试,方便开发过程中的问题排查。
经济可行性
本项目的开发和部署成本较低,后期维护成本几乎为零,具有良好的经济可行性: (1)开发成本:项目基于开源技术和腾讯免费的云开发基础配额进行开发,开发过程中无需支付软件授权费、服务器租赁费、域名注册费等费用; (2)部署成本:微信云开发的资源配额价格低廉,基础版配额可满足中小学校方的日常使用需求,即使后续需要提升资源配额,费用也远低于传统的服务器部署; (3)维护成本:微信云开发由腾讯官方进行维护,无需开发者进行服务器的运维、升级、安全防护等工作,节省了大量的维护人力和物力成本; (4)使用成本:小程序对用户完全免费,用户无需支付任何费用即可使用所有功能,易于推广和使用。
系统总体设计
模块化设计原则:将系统划分为多个独立的功能模块,每个模块实现特定的功能,模块之间通过统一的接口进行交互,降低模块之间的耦合度,方便后续的功能扩展和 bug 修复; 用户体验优先原则:结合中小学生和管理员的使用习惯,进行前端界面和操作流程的设计,保证界面友好、操作简单,提升用户的使用体验; 轻量化设计原则:基于微信小程序 “即用即走” 的特性,简化前端页面的代码和资源,降低小程序的代码包大小,提升页面的加载速度; 云原生设计原则:充分利用微信云开发的技术优势,将业务逻辑、数据存储、文件存储均部署在云端,实现前后端的解耦,降低本地开发的复杂度; 权限最小化原则:针对不同的管理员角色分配最小的操作权限,超级管理员拥有所有权限,普通管理员仅拥有必要的操作权限,保证系统的数据安全; 可扩展设计原则:在系统架构和数据库设计中,预留扩展接口和字段,方便后续新增功能和扩展数据类型,适应不同用户的个性化需求。
数据库设计
本小程序采用微信云开发的云数据库进行数据存储,云数据库是一种非关系型数据库(NoSQL),以集合(Collection)为单位存储数据,每个集合包含多个文档(Document),文档采用 JSON 格式存储数据,具有灵活的结构,适合小程序的轻量化开发需求。根据系统的功能需求,设计用户集合、题库集合、答题记录集合、竞赛记录集合、管理员集合、答题参数集合、系统日志集合七个核心集合
前端功能实现
小程序前端是用户与系统的交互界面,采用 WXML、WXSS、JavaScript 进行开发,遵循微信小程序的页面 - 逻辑 - 配置开发模式,每个页面由.wxml(页面结构)、.wxss(页面样式)、.js(页面逻辑)、.json(页面配置)四个文件组成。前端功能实现的核心是通过微信云开发的 API 与云端进行交互,将用户的操作请求发送至云函数,接收云函数返回的处理结果,并完成页面的动态渲染。
云函数实现
云函数是本小程序的业务逻辑处理核心,基于 Node.js 开发,核心云函数为mcloud,包含用户管理、题库管理、答题处理、竞赛管理、参数设置、数据统计六大业务模块的处理逻辑。云函数的开发遵循模块化原则,将不同的业务逻辑拆分为不同的函数,通过action参数区分前端的请求类型,实现对不同请求的处理。
// 得分统计
async statAnswer(userId) {
let where = {
ANSWER_USER_ID: userId,
ANSWER_TYPE: 1
}
let cnt = await AnswerModel.count(where);
let score = await AnswerModel.sum(where, 'ANSWER_SCORE');
let data = {
USER_ANSWER_CNT: cnt,
USER_ANSWER_SCORE: score
}
await UserModel.edit({ USER_MINI_OPENID: userId }, data);
}
// 每日可答题次数校验
async isAnswerTimes(userId, cateId) {
let dayCnt = 100;
let setup = await setupUtil.get('answer');
if (setup) {
setup = dataUtil.dbForms2Obj(setup);
dayCnt = Number(setup.daycnt);
if (setup.open != true) {
return '竞赛尚未开始!';
}
}
let where = {
ANSWER_CATE_ID: String(cateId),
ANSWER_USER_ID: userId,
ANSWER_TYPE: 1,
ANSWER_DAY: timeUtil.time('Y-M-D')
}
let cnt = await AnswerModel.count(where);
if (cnt >= dayCnt) {
return '每日竞赛答题最多' + dayCnt + '次,请明日再来!';
}
return '';
}
async saveMyAnswer(userId,
) {
}
// 随机N条记录,生成本次题库
async genQuestion(userId, type, cateId) {
return { questionList: [], maxTime:10 };
}
async getMyAnswerList(userId, {
search, // 搜索条件
sortType, // 搜索菜单
sortVal, // 搜索菜单
orderBy, // 排序
page,
size,
isTotal = true,
oldTotal
}) {
orderBy = orderBy || {
'ANSWER_ADD_TIME': 'desc'
};
let fields = 'ANSWER_SCORE,ANSWER_CATE_NAME,ANSWER_TYPE,ANSWER_ADD_TIME,ANSWER_CNT,ANSWER_PER,ANSWER_SUCC_CNT,ANSWER_DURATION,ANSWER_START,ANSWER_END';
let where = {};
where.and = {
ANSWER_USER_ID: userId,
_pid: this.getProjectId() //复杂的查询在此处标注PID
};
if (util.isDefined(search) && search) {
where.or = [
];
} else if (sortType && util.isDefined(sortVal)) {
// 搜索菜单
switch (sortType) {
case 'type': {
where.and.ANSWER_TYPE = Number(sortVal);
break;
}
case 'cateId': {
where.and.ANSWER_CATE_ID = String(sortVal);
break;
}
case 'sort': {
orderBy = this.fmtOrderBySort(sortVal, 'ANSWER_ADD_TIME');
break;
}
}
}
return await AnswerModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
}