Vue+SpringBoot在线教育考试及管理平台开发(纯原创)后续还在开发,会持续更新

登录页面设计

        登录页面设计思路-分为三个角色进行登录,分别为学生,教师,管理员。

        前端将登录设计为表单形式,通过选项组件绑定角色参数,向后端传递角色信息,通过表单绑定向后端传递登录者所有信息

              <div style="display: flex;  gap: 20px;">
                <vs-radio color="rgb(59,222,200)" v-model="form.type" val="学生">
                  学生
                </vs-radio>
                <vs-radio v-model="form.type" val="教师">
                  教师
                </vs-radio>
                <vs-radio danger v-model="form.type" val="管理员">
                  管理员
                </vs-radio>
              </div>
    @PostMapping("/user/login")
    public Map<String,Object> Login(@RequestBody User user){
        Map<String,Object> map = new HashMap<>();
        User u = userService.LoginByUserName(user.getUserNumber());
        Map<String,String>payload = new HashMap<>();
        if(u!=null){
            if(user.getPassword().equals(u.getPassword()) && user.getType().equals(u.getType())){
                if (u.getType().equals("学生")){
                    String className = userService.FindClassNameByClassId(u.getClassid());
                    map.put("className",className);
                }
                payload.put("id",u.getId().toString());
                payload.put("username",u.getUserNumber());
                String token = JWTUtil.createToken(payload);
                System.out.println("token为"+token);
                map.put("UserInfo",u);
                map.put("userId",u.getId());
                map.put("code",200);
                map.put("status",token);
                map.put("msg","登陆成功");
            }
            else {
                map.put("msg","密码错误");
                map.put("status",0);
            }
        }
        else{
            map.put("msg","不存在该用户");
            map.put("status",0);
        }
        return map;
    }

        通过在数据库中存入type字段,实现与后台对接并实现特定角色登录

考试系统设计

附:一张设计手稿,随笔字丑请忽略

设计思路(可结合下面数据表进行理解):

        1.试卷表:每一张试卷都对应一个特有的PaperId,并且在表中存有PaperName(试卷名),PaperTime(考试时间),PaperImageSrc(考试封面图),后续可以自信添加字段,丰富考卷所具有的信息。
        2.题目表:每一道题目都有一个PaperId,可以以此将隶属与对应试卷的题目信息读取,每一道题目含有独有的QuestionId(题目ID),QuestionContent(题目内容),QuestionScore(题目的得分,可以通过组卷时设置对应分数,实现灵活组卷),QuestionType(题目类型),通过这个字段可以定义题目对应的不同类型。
        3.题目细节表:每一条数据都有一个独有的QuestionId,可以让它属于对应的题目,QuesitonOption(题目选项表,设置ABCD等类型的选项内容),可以通过读取对应细节有几条数据来设置它为单选题还是填空题,QuestionCorrect(选项是否正确),通过此字段判断选项正确与否。
        4.题目商店表:用于老师的组卷功能,QuestionId,QuestionContent,QuestionType,QuestionTheme(问题主题,方便用于搜索,但是VueSax搜索不需要后端数据即可实现)。

思路串联:

        一、用户对应考卷的设计:通过UserNumber字段从f_exam_userneedexam表中查询该用户对应的所有PaperId,然后通过此PaperId查询f_exam_paper表中考卷具体信息,即可展示用户对应所需的考试信息。
        二、考卷的设计:一张试卷对应独特的PaperId,一道题目衔接对应的PaperId(衔接试卷表),题目选项衔接对应的QuestionId(衔接题目表)。
    //把试卷组好
    @GetMapping("/exam/SelectAllQustionByPaperIdUpdate")
    public List<QuestionWithOptions> SelectAllQustionByPaperIdUpdate(@RequestParam Integer PaperId){
        List<QuestionWithOptions> questionsWithOptions = new ArrayList<>();
        List<Questions> allQuestions = userExamService.SelectAllQustionByPaperIdUpdate(PaperId);

        for (Questions question : allQuestions) {
            List<Options> options = userExamService.SelectAllQustionByQuestionId(question.getQuestionId());
            QuestionWithOptions questionWithOptions = new QuestionWithOptions(question, options);
            questionsWithOptions.add(questionWithOptions);
        }

//        System.out.println("第一组数据测试获取问题列表"+questionsWithOptions.get(0).getQuestion());
//        System.out.println("第一组数据测试获取选项列表"+questionsWithOptions.get(0).getOptions());
//        System.out.println("第一组数据测试获取选项列表的第一个选项内容"+questionsWithOptions.get(0).getOptions().get(0));
//        System.out.println("第一组数据测试获取选项列表的第二个选项内容"+questionsWithOptions.get(0).getOptions().get(1));
//        System.out.println("第一组数据"+questionsWithOptions.get(0));
//        System.out.println("返回的最终数据"+questionsWithOptions);

        return questionsWithOptions;
    }
@Data
public class QuestionWithOptions {
    private Questions question;
    private List<Options> options;
}

        <vs-dialog scroll overflow-hidden  auto-width  blur not-close  :prevent-close="true"  full-screen v-model="ExamActive">
          <div>
            <h1>考卷</h1>
            <div v-for="(questionWithOptions, index) in examQuestions" :key="index">
              <h2>{{ questionWithOptions.question.questionContent }}</h2>
              <div v-for="(option, i) in questionWithOptions.options" :key="i">
                <label>
<!--                  <vs-checkbox :value="option" v-model="selectedOptions[index]">-->
<!--                    {{ option.questionOption }}-->
<!--                  </vs-checkbox>-->
                  <input type="radio" :value="option" v-model="selectedOptions[index]">
                  {{ option.questionOption }}
                </label>
              </div>
            </div>

            <vs-button gradient @click="submitExam">提交</vs-button>
          </div>
        </vs-dialog>
export default {
  data(){
    return{
      UserNumber:"",
      UserName:"",
      examInfo:[],
      active: false,
      input1: '',
      input2: '',
      checkbox1: false,
      ExamActive: false,
      examQuestions: [], // 包含问题和选项的数组
      selectedOptions: [], // 用户选择的答案
    //   JSON格式理解
    //
    //   数组和对象
    //   LJL:[      ExamRecord:{
    //   PaperId: "",
    //       ExamUserNumber: "",
    //       ExamUserName: "",
    // },,      ExamRecord1:{
    //   PaperId: "",
    //       ExamUserNumber: "",
    //       ExamUserName: "",
    // },]
      ExamRecord:{
        paperId: "",
        examUserNumber: "",
        examUserName: "",
      },
      UserAnswer:{
        Answers:"",
        UserNumber:"",
        UserName:"",
        PaperId:"",
      },
      PaperId:""
    }
  },
  methods:{
    StartExam(){
      this.active = !this.active;
      this.ExamActive = !this.ExamActive;
      this.ExamRecord = {
        paperId: this.PaperId,
        examUserNumber: this.UserNumber,
        examUserName: this.UserName
      };
      //插入开考记录
      this.$ExamApi.insertRecordFromStartExam(this.ExamRecord).then(res=>{
        console.log(this.ExamRecord)
      }).catch(err=>console.log(err))
    },
    SelectExamByPaperId(paperId) {
      this.active = !this.active
      this.PaperId = paperId
      this.$ExamApi.SelectAllQustionByPaperIdUpdate(paperId).then(res=>{
        this.examQuestions = res.data
        console.log(res.data)
        // 初始化选项
        this.selectedOptions = new Array(this.examQuestions.length).fill("");
        console.log(this.selectedOptions)
      }).catch(err=>console.log(err))
      // 这里可以根据 paperId 执行你需要的逻辑,比如打开对应考试的详情页面等
    },
    submitExam() {
      this.UserAnswer={
        Answers: this.selectedOptions,
        UserName: this.UserName,
        UserNumber: this.UserNumber,
        PaperId: this.PaperId
      }
      this.$ExamApi.insertUserAnswerAndSubmitExamToAddScore(this.UserAnswer).then(res=>{
        console.log(this.UserAnswer)
        this.openNotification('top-center', '#7d33ff', `<i class='bx bx-bell' ></i>`)
        this.ExamActive = !this.ExamActive
      })
      // 这里可以将用户的答案发送给后端进行处理
    },

    //获取当前用户所需要的考试信息
    UserNeedExamByUserNumber(){
      // this.$loginApi.UserLogin(this.loginData).then(res=>{
      this.$ExamApi.UserNeedExamByUserNumber(this.UserNumber).then(res=>{
        this.examInfo = res.data.dataobject
        console.log("查询到的考试信息为")
        console.log(this.examInfo)
      }).catch(err=>console.log(err))
    },
    getCoverUrl(coverUrl) {
      return this.$config.getBaseUrl()+coverUrl;
    },
    //消息通知框
    openNotification(position = null, color, icon) {
      const noti = this.$vs.notification({
        icon,
        color,
        position,
        title: '恭喜您!,顺利完成了测试!',
        text: `您将可以在考试查询界面,查询到自己的成绩以及答题情况!!!`
      })
    }
  },
  mounted() {
    this.UserNumber = sessionStorage.getItem("userNumber");
    this.UserName = sessionStorage.getItem("userName");
    this.UserNeedExamByUserNumber();
  }
}
        三、点击开考的设计:向f_exam_record(考试记录表)中插入,考试人员信息(ExamUserNumber,ExamUserName),开考时间(ExamStartTime),对应试卷PaperId。此时每条数据对应的ExamScore和ExamEndTime为空,通过交卷执行Update操作进行记录。
        四、点击交卷的设计:
        将用户所选的选项进行遍历,分别插入f_exam_user_answer(用户答题内容表,用于查看用户答题具体情况,即生成一份用户答题内容卷),记录用户所答题的具体信息。
        通过以下代码获取此用户所作的卷子记录(通过用户学号,开考时间的降序排序,限制为一条数据,获取用户当前所考的最新试卷,用于插入交卷时间和总分)
<!--    获得记录Id-->
    <select id="SelectRecordId" parameterType="String" resultType="Integer">
        SELECT * from f_exam_record where ExamUserNumber = #{ExamUserNumber}  ORDER BY ExamStartTime DESC LIMIT 1
    </select>
        通过遍历questionCorrect字段,以获取哪条记录为正确选项,如果questionCorrect为true,通过此记录的QuestionId和PaperId在f_exam_question表中查找此题对应的QuestionScore值,然后在此时定义Score对象进行计算总分(避免了异步冲突),然后将总分以及交卷时间插入记录表格。
    @PostMapping("/exam/insertUserAnswerAndSubmitExamToAddScore")
    public void insertUserAnswer(@RequestBody Map<String, Object> requestData) {
        List<Map<String, Object>> answersMapList = (List<Map<String, Object>>) requestData.get("Answers");
        String userName = (String) requestData.get("UserName");
        String userNumber = (String) requestData.get("UserNumber");
        Integer recordId = userExamService.SelectRecordId(userNumber);

        Integer PaperId = (Integer) requestData.get("PaperId");
        int score = 0;

        for (Map<String, Object> answerMap : answersMapList) {
            UserAnswer userAnswer = new UserAnswer();
            userAnswer.setId((int) answerMap.get("id"));
            userAnswer.setQuestionId((int) answerMap.get("questionId"));
            userAnswer.setQuestionOption((String) answerMap.get("questionOption"));
            userAnswer.setQuestionCorrect((boolean) answerMap.get("questionCorrect"));
            userAnswer.setExamUserNumber(userNumber);
            userAnswer.setExamUserName(userName);
            userAnswer.setRecordId(recordId);
            userExamService.insertUserAnswer(userAnswer);
            if((Boolean) answerMap.get("questionCorrect")==true){
                ExamRequestScore examRequestScore = new ExamRequestScore();
                examRequestScore.setPaperId(PaperId);
                examRequestScore.setQuestionId(userAnswer.getQuestionId());
                Integer s = userExamService.selectScoreFromStoreByQuestionIdAndPaperId(examRequestScore);
                score = s+score;
                System.out.println("编号为"+userAnswer.getQuestionId()+"的问题回答正确"+"并且正确答案的分数为:"+s);
                System.out.println("总分为"+score);
            }
        }
        ExamRecord examRecord = new ExamRecord();
        examRecord.setPaperId(PaperId);
        examRecord.setExamUserNumber(userNumber);
        examRecord.setExamScore(score);
        System.out.println("examRecord"+examRecord);
        userExamService.updateRecordFromEndExam(examRecord);
    }

 数据库分为:

        题目所对应的数据表:

        试卷表

        题目表

        题目细节表(选项表)

        题目商店表(题库表)

用户考试对应的表:

        用户所需考试表

        用户考试记录表

        用户答题记录表

附:一些界面设计截图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/477011.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

js中filter处理后端返回表格数据

<template><div><el-table:data"tableData"style"width: 100%"><el-table-column:formatter"tranForm"prop"gender"label"性别"width"180"></el-table-column><el-table-column…

K8S Storage

概述 一般情况下&#xff0c;K8S中的Pod都不应该将数据持久化到Pod中&#xff0c;因为Pod可能被随时创建和删除&#xff08;扩容或缩容&#xff09;&#xff0c;即便是StatefulSet或Operator的Pod&#xff0c;也都不建议在Pod里存放数据&#xff0c;可以将数据持久化到Host上。…

构建以太网交换网络——(以太网基础与VLAN配置实验)

实验介绍 关于本实验 以太网是一种基于CSMA/CD&#xff08;Carrier Sense Multiple Access/Collision Detection&#xff09;的共享通讯介质的数据网络通讯技术。当主机数目较多时会导致冲突严重、广播泛滥、性能显著下降甚至造成网络不可用等问题。通过交换机实现LAN互连虽然…

小程序云开发实战:通用企业产品信息展示小程序

之前做小程序都是自己搭建数据管理后台&#xff0c;比如我之前做的小程序&#xff1a;一搜就学&#xff0c;就是使用java来做管理后台&#xff0c;小程序做前端展示。但是对于简单的小程序来说&#xff0c;做一套管理后台有点拿大炮打蚊子&#xff0c;所以使用云开发就是不错的…

怎样修改grafana的Loading picture和加载的文本

登录装了grafana的linux机器 command “sudo vi /usr/share/grafana/public/views/index.html”&#xff0c;编辑配置文件。 找到.preloader__logo更改background-image. 这里可以是个url也可以是个路径。 如果想要更改加载的文字.可以更改 的内容 改完:wq保存以后退出&…

Leetcode热题100:图论

Leetcode 200. 岛屿数量 深度优先搜索法&#xff1a; 对于这道题来说&#xff0c;是一个非常经典的图的问题&#xff0c;我们可以先从宏观上面来看问题&#xff0c;也就是说在不想具体算法的前提下&#xff0c;简单的说出如何找到所有的岛屿呢&#xff1f; 如图中所示&#x…

在 MacOS 中安装

查看&#xff1a;OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;在基于 Android 相机预览的 CV 应用程序中使用 OpenCL 下一篇&#xff1a;基于ARM 的Linux系统的交叉编译 以下步骤已针对 MacOSX &#xff08;Mavericks&#xff09; 进行了…

NEC 78K系列MCU概述

一.初识 NEC MCU NEC&#xff0c;即日本电气株式会社&#xff0c; 经营半导体业务。 NEC 倡导“ ALL Flash”&#xff0c;即 MCU 内的程序存储器使用 Flash ROM。 为什么用 Flash ROM&#xff1f; 与掩膜 ROM 微控制器相比&#xff0c; Flash 微控制器加速了系…

开源表单设计器颗粒度级别控制表单的显示条件原理分析

表单渲染中, 有些表单的显示有不同条件, 比如需要上一个表单的开关打开,或者文本内容为 xxxx, 或者需要大于或等于或小于指定值, 或者需要选中某个选项, 或者需满足以上多个条件或在满足多个条件中的一个, 有 n 种场景选择, 这样就需要条件显示配置功能, 来满足多样化需求 预览…

【Django实战一】创建新项目

一、新建Project django-admin startproject 项目名称二、创建应用 1、创建应用 python manage.py startapp 应用名称应用创建后&#xff0c;项目的根目录下会生成对应应用名称的文件夹 2、注册应用 新创建的应用需要在settings.py中的INSTALLED_APPS中注册该应用 INSTALL…

Prompt-RAG:在特定领域中应用的革新性无需向量嵌入的RAG技术

论文地址&#xff1a;https://arxiv.org/ftp/arxiv/papers/2401/2401.11246.pdf 原文地址&#xff1a;https://cobusgreyling.medium.com/prompt-rag-98288fb38190 2024 年 3 月 21 日 虽然 Prompt-RAG 确实有其局限性&#xff0c;但在特定情况下它可以有效地替代传统向量嵌入 …

KW音乐搜索参数

声明&#xff1a; 本文章中所有内容仅供学习交流&#xff0c;抓包内容、敏感网址、数据接口均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 逆向目标: …

基于SpringBoot+Layui的社区物业管理系统

项目介绍 社区物业管理系统是基于java程序开发,本系统分为业主和管理员两个角色 业主可以登陆系统,查看车位费用信息,查看物业费用信息,在线投诉,查看投诉,在线报修; 管理员可以车位收费信息,物业收费信息,投诉信息,楼宇信息,房屋信息,业主信息,车位信息,抄表信…

ArkTS编写的HarmonyOS原生聊天UI框架

简介 ChatUI&#xff0c;是一个ArkTS编写的HarmonyOS原生聊天UI框架&#xff0c;提供了开箱即用的聊天对话组件。 下载安装 ohpm install changwei/chatuiOpenHarmony ohpm 环境配置等更多内容&#xff0c;请参考如何安装 OpenHarmony ohpm 包 接口和属性列表 接口列表 接…

Git、Github、Gitee、GitLab学习,团队协助/版本控制

Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种 项目。B站尚硅谷Git学习笔记 一、Git的常用命令 1.git工作机制 工作区和暂存区的文件都可删除&#xff0c;但是提交到本地库则不可删除&#xff0c;有历史记录 2.历史版本 2.1查…

如何打破SAST代码审计工具的局限性?

关键词&#xff1a;白盒测试&#xff1b;代码分析工具&#xff1b;代码扫描工具&#xff1b;静态代码检测工具&#xff1b; 在代码的世界里&#xff0c;安全问题如同潜伏的暗礁&#xff0c;随时可能让航行中的软件项目触礁沉没。SAST代码审计工具如同雷达一样&#xff0c;以其独…

Doris记录

Doris是一个开源的分布式分析型数据库&#xff0c;最初由阿里巴巴开发并开源&#xff0c;目前隶属于Apache基金会。 Doris基于大规模并行处理&#xff08;MPP&#xff09;架构&#xff0c;提供高性能和实时的数据分析能力。它以极速易用的特点被广泛使用&#xff0c;能够应对高…

探索 PostgreSQL 的外部数据包装器和统计函数

PostgreSQL 因其稳定性和可扩展性而广受青睐&#xff0c;为开发人员和数据管理员提供了许多有用的函数。在这些函数中&#xff0c;file_fdw_handler、file_fdw_validator、pg_stat_statements、pg_stat_statements_info 以及 pg_stat_statements_reset 是其中的重要函数&#x…

鸿蒙Harmony应用开发—ArkTS-全局UI方法(时间滑动选择器弹窗)

以24小时的时间区间创建时间滑动选择器&#xff0c;展示在弹窗上。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 本模块功能依赖UI的执行上下文&#xff0c;不可在UI上下文不明确的地方使用&…

java设计模式--模板方法

在开始模板方法的学习之前&#xff0c;先看下面一段话&#xff1a; 模板&#xff0c;是指作图或设计方案的固定格式。模板是将一个事物的结构规律予以固定化、标准化的成果&#xff0c;它体现的是结构形式的标准化。 ----百度百科 通俗来说&#xff0c;模板其实就是把一个事物的…