基于微信小程序的竞赛答题小程序开发笔记(一)

开发背景调研

中小学学科答题小程序,适合各中小学校方,老师或者家长。通过互动和参与式学习,小程序能够通过游戏化元素提升学习的积极性和参与度,从而提升学习效率,促进学生自主学习

功能规划

  • 分类题库:按照学科(数学、语文、英语等)和知识点进行分类,方便用户选择。
  • 随机抽题:用户可以选择特定学科,系统随机生成题目。
  • 答题竞赛: 模拟真实竞赛或考试环境,可以设置每场的时间。
  • 解析详解:每道题目提供详细的解答和解析,帮助用户理解解题思路。
  • 排行榜:展示用户的积分排名,促进比赛竞争。
  • 后台-题库管理:支持直接录入,或者通过Excel导入题库(每次5000条)
  • 后台-答题参数设置:可以设置竞赛开始状态,每次答题数目,每次答题时长限制,每天可参与答题竞赛次数等参数

概要设计

数据库设计

复制代码
AnswerModel.DB_STRUCTURE = {
	_pid: 'string|true',
	ANSWER_ID: 'string|true',

	ANSWER_USER_ID: 'string|true',
	ANSWER_TYPE: 'int|true|default=0|comment=类型 0=测试,1=正式',

	ANSWER_CATE_ID: 'string|true|default=0|comment=分类',
	ANSWER_CATE_NAME: 'string|false|comment=分类冗余', 

	ANSWER_DAY: 'string|true',

	ANSWER_START: 'int|true|default=0',
	ANSWER_END: 'int|true|default=0',
	ANSWER_DURATION: 'string|false',

	ANSWER_PER: 'int|true|default=0',
	ANSWER_SCORE: 'int|true|default=0',
	ANSWER_CNT: 'int|true|default=0',
	ANSWER_SUCC_CNT: 'int|true|default=0',

	ANSWER_LIST: 'array|true|default=[]',

	ANSWER_ADD_TIME: 'int|true',
	ANSWER_EDIT_TIME: 'int|true',
	ANSWER_ADD_IP: 'string|false',
	ANSWER_EDIT_IP: 'string|false',
};

QuestionModel.DB_STRUCTURE = {
	_pid: 'string|true',
	QUESTION_ID: 'string|true',

	QUESTION_TITLE: 'string|true|comment=题目',
	QUESTION_STATUS: 'int|true|default=1|comment=状态 0=未启用,1=使用中',

	QUESTION_CATE_ID: 'string|true|default=0|comment=分类',
	QUESTION_CATE_NAME: 'string|false|comment=分类冗余', 

	QUESTION_ORDER: 'int|true|default=9999',

	QUESTION_FORMS: 'array|true|default=[]',
	QUESTION_OBJ: 'object|true|default={}', 

	QUESTION_ADD_TIME: 'int|true',
	QUESTION_EDIT_TIME: 'int|true',
	QUESTION_ADD_IP: 'string|false',
	QUESTION_EDIT_IP: 'string|false',
};

难点与实现

复制代码
class QuestionService extends BaseProjectService {

	async getAnswerDetail(id) {
		return await AnswerModel.getOne(id);
	}

	async delAnswer(userId, id) {
		return await AnswerModel.del({ ANSWER_USER_ID: userId, _id: id });
	}

	// 得分统计
	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);
	}


	async getScoreRankList({
		search, // 搜索条件
		sortType, // 搜索菜单
		sortVal, // 搜索菜单
		orderBy, // 排序 
		page,
		size,
		isTotal = true,
		oldTotal
	}) {

		orderBy = {
			'USER_ANSWER_SCORE': 'desc'
		};
		let fields = 'USER_NAME,USER_ANSWER_SCORE';

		let where = {};
		where.and = {
			_pid: this.getProjectId() //复杂的查询在此处标注PID
		};

		if (util.isDefined(search) && search) {
			where.or = [

			];
		} else if (sortType && util.isDefined(sortVal)) {
			// 搜索菜单
			switch (sortType) {
				case 'sort': {
					orderBy = this.fmtOrderBySort(sortVal, 'ANSWER_ADD_TIME');
					break;
				}
			}
		}

		return await UserModel.getList(where, fields, orderBy, page, size, isTotal, oldTotal);
	}

}

UI设计








后台管理系统设计







git代码

git代码网址

相关推荐
qq_284274057 小时前
机械原理笔记:平面机构自由度计算(复合铰链、局部自由度、虚约束)与四杆机构入门(含考点)
笔记·学习·平面·自动化·制造
qq_284274058 小时前
数控铣床与加工中心笔记:铣刀与刀柄系统、G54试切对刀、镜像加工指令、孔加工工艺(钻扩铰镗)与固定循环G73/G83/G81/G76/G87/G84
笔记·学习·自动化·制造
Titan20249 小时前
MySQL访问个人学习笔记
笔记·学习·mysql
深圳老胡11 小时前
STM32CubeMX 生成 CMake 工程,用 VSCode 编译与调试的完整流程
笔记·stm32·单片机·代码规范
坤坤子吖11 小时前
C++智能指针:RAII、shared_ptr与内存泄漏
开发语言·c++·笔记·学习
乐橙开放平台11 小时前
智慧连锁客流检测和离岗检测怎么对接
大数据·人工智能·笔记·物联网·自动化·音视频·智能家居
零基础12311 小时前
FinalShell 使用教程:从安装到高效运维
运维·经验分享·笔记·finalshell
ACP广源盛1392462567311 小时前
Type‑C 扩展坞方案选型笔记|国产 DP1.4 转 HDMI2.0 桥接芯片 GSV2201S @ACP评估
c语言·开发语言·笔记·硬件架构·硬件工程·国产芯片
敲个大西瓜13 小时前
langchain笔记(一)
redis·笔记·langchain
带金箍的至尊宝13 小时前
系统架构设计师笔记 05:第2章硬件与软件基础,冯诺依曼结构怎么考
数据库·笔记·系统架构