从0到1到100:中小学学科答题小程序的设计与实现

0 阅读10分钟

研究背景

在教育信息化 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);
	}

git代码

点击下载