开发背景调研

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

功能规划

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

概要设计

image.png

数据库设计

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设计

image.png
image.png
image.png
image.png
image.png
image.png
image.png
image.png

后台管理系统设计

image.png
image.png
image.png
image.png
image.png
image.png
image.png

git代码

git代码网址


CC同学呀
27 声望13 粉丝

鹅厂程序猿一枚,交流v: cclinux0730