基于SpringBoot+vue的在线考试系统-以计算机网络为例,可自行录入题库
- 一、项目简介
- 二、开发环境
- 三、项目技术
- 四、功能结构
- 五、运行截图
- 六、功能实现
- 七、数据库设计
- 八、源码下载地址
 
一、项目简介
随着信息技术的迅猛发展,教育行业正面临着巨大的变革和挑战。为了适应当下时代的需求,我们开发了一款现代化的在线考试系统,旨在提供高效、便捷、安全的考试环境,为学生和教师带来更好的考试体验和教学管理。
我们的在线考试系统采用了先进的技术架构,其中后端采用了Spring Boot,前端则采用Vue2和ElementUI。同时,作为数据库,我们选择了MySQL,以保障数据的可靠性和稳定性。
该系统提供了全面的功能模块,涵盖学生管理、教师管理、题库管理、考试管理、留言、在线考试和成绩统计等方面。学生管理模块包含学生信息的录入、查询和修改功能,教师管理模块提供了教师信息信息添加、删除功能,题库管理模块允许教师对题目进行增加于查看,考试管理模块支持考试计划创建、考试计划修改以及删除等操作,留言功能方便学生和教师之间的交流,而在线考试模块则为学生提供了在线答题和交卷的便捷方式并且提供自动判分。成绩统计模块则帮助教师对学生的考试成绩进行全面统计和分析,为教学提供有效参考。
二、开发环境
| 开发环境 | 版本/工具 | 
|---|---|
| 基础环境 | Jdk1.8、node.js14 | 
| 开发工具 | IntelliJ IDEA、WebStorm | 
| 操作系统 | Windows 10 | 
| 内存要求 | 8GB 以上 | 
| 浏览器 | Firefox (推荐)、Google Chrome (推荐)、Edge | 
| 数据库 | MySQL 8.0 (推荐) | 
| 数据库工具 | Navicat Premium 15 (推荐) | 
| 项目框架 | 后端SpringBoot、前端ElementUi | 
三、项目技术
后端:SpringBoot、MybatisPlus、MySQL
前端:Vue2、ElementUi、vue-router、vuex、JavaScript
四、功能结构
学生管理功能 : 学生管理模块允许学生进行个人信息的修改和添加,保证学生信息的及时更新。学生登录功能为学生提供了便捷的访问入口,让他们可以方便地查看考试计划、参加在线考试,并随时查询个人的考试成绩。
教师管理功能 : 教师管理模块为教师提供了个人信息的管理功能,教师可以随时修改和添加自己的信息。通过教师登录功能,教师可以查看自己负责的考试和班级,进行考试的修改和删除等操作,实现对教学事务的全面管理。
题库管理功能 : 题库管理模块为教师提供了方便快捷的试卷题库添加功能,支持多种题型的题目录入。教师可以查看已有的题库,便于组卷时参考。同时,试卷在线组卷功能可以根据需要自动生成试卷,减轻了教师的工作负担。
考试管理功能 : 考试管理模块支持考试计划的添加、修改和删除,教师可以根据学习进度和课程需要进行灵活安排。考试的修改功能也让教师在出现变动时能够及时调整考试安排,保证教学进度的顺利进行。
成绩查询功能 : 成绩查询功能允许学生方便地查询自己的考试成绩,而且考试分段成绩统计功能可以为教师提供更全面的学生成绩分析,辅助教学改进和个性化辅导。
在线考试客户端 : 在线考试客户端为学生提供了便捷的在线考试体验。学生可以在客户端查看考试计划,准时参加在线答题考试,并通过自动判分功能快速获取考试成 绩。客户端还支持留言功能,学生可以向教师提问或反馈问题,促进师生间的有效沟通。
 
五、运行截图
考试计划查看:
 
 在线考试:
 
提交考试:
 
考试成绩查看:
 
 留言板:
 
登录页面:
 
考试管理:
 
 
题库管理:
 

 
 
教师管理:
 
 
学生管理:
 
 
留言:
 
考试成绩统计:
 
 
六、功能实现
前端获取当前考试信息
    getExamData() { //获取当前试卷所有信息
      let date = new Date()
      this.startTime = this.getTime(date)
      let examCode = this.$route.query.examCode //获取路由传递过来的试卷编号
      this.$axios(`/api/exam/${examCode}`).then(res => {  //通过examCode请求试卷详细信息
        this.examData = { ...res.data.data} //获取考试详情
        this.index = 0
        this.time = this.examData.totalScore //获取分钟数
        let paperId = this.examData.paperId
        this.$axios(`/api/paper/${paperId}`).then(res => {  //通过paperId获取试题题目信息
          this.topic = {...res.data}
          let reduceAnswer = this.topic[1][this.index]
          this.reduceAnswer = reduceAnswer
          let keys = Object.keys(this.topic) //对象转数组
          keys.forEach(e => {
            let data = this.topic[e]
            this.topicCount.push(data.length)
            let currentScore = 0
            for(let i = 0; i< data.length; i++) { //循环每种题型,计算出总分
              currentScore += data[i].score
            }
            this.score.push(currentScore) //把每种题型总分存入score
          })
          let len = this.topicCount[1]
          let father = []
          for(let i = 0; i < len; i++) { //根据填空题数量创建二维空数组存放每道题答案
            let children = [null,null,null,null]
            father.push(children)
          }
          this.fillAnswer = father
          let dataInit = this.topic[1]
          this.number = 1
          this.showQuestion = dataInit[0].question
          this.showAnswer = dataInit[0]
        })
      })
    }
自动判分方法核心代码
   commit() { //答案提交计算分数
      /* 计算选择题总分 */
      let topic1Answer = this.topic1Answer
      let finalScore = 0
      topic1Answer.forEach((element,index) => { //循环每道选择题根据选项计算分数
        let right = null
        if(element != null) {
          switch(element) { //选项1,2,3,4 转换为 "A","B","C","D"
            case 1:
              right = "A"
              break
            case 2:
              right = "B"
              break
            case 3:
              right = "C"
              break
            case 4:
              right = "D"
          }
          if(right == this.topic[1][index].rightAnswer) { // 当前选项与正确答案对比
            finalScore += this.topic[1][index].score // 计算总分数
          }
          console.log(right,this.topic[1][index].rightAnswer)
        }
        // console.log(topic1Answer)
      })
      /**计算判断题总分 */
      // console.log(`this.fillAnswer${this.fillAnswer}`)
      // console.log(this.topic[2][this.index])
      let fillAnswer = this.fillAnswer
      fillAnswer.forEach((element,index) => { //此处index和 this.index数据不一致,注意
        element.forEach((inner) => {
          if(this.topic[2][index].answer.includes(inner)) { //判断填空答案是否与数据库一致
            console.log("正确")
            finalScore += this.topic[2][this.index].score
          }
        })
      });
      /** 计算判断题总分 */
      let topic3Answer = this.judgeAnswer
      topic3Answer.forEach((element,index) => {
        let right = null
        switch(element) {
          case 1:
            right = "T"
            break
          case 2:
            right = "F"
        }
        if(right == this.topic[3][index].answer) { // 当前选项与正确答案对比
            finalScore += this.topic[3][index].score // 计算总分数
          }
      })
      if(this.time != 0) {
        this.$confirm("考试结束时间未到,是否提前交卷","友情提示",{
          confirmButtonText: '立即交卷',
          cancelButtonText: '再检查一下',
          type: 'warning'
        }).then(() => {
          console.log("交卷")
          let date = new Date()
          this.endTime = this.getTime(date)
          let answerDate = this.endTime.substr(0,10)
          //提交成绩信息
          this.$axios({
            url: '/api/score',
            method: 'post',
            data: {
              examCode: this.examData.examCode, //考试编号
              studentId: this.userInfo.id, //学号
              subject: this.examData.source, //课程名称
              etScore: finalScore, //答题成绩
              answerDate: answerDate, //答题日期
            }
          }).then(res => {
            if(res.data.code == 200) {
              this.$router.push({path:'/studentScore',query: {
                score: finalScore,
                startTime: this.startTime,
                endTime: this.endTime
              }})
            }
          })
        }).catch(() => {
          console.log("继续答题")
        })
      }
    },
后端获取考试信息接口
    @GetMapping("/exam/{examCode}")
    public ApiResult findById(@PathVariable("examCode") Integer examCode){
        System.out.println("根据ID查找");
        ExamManage res = examManageService.findById(examCode);
        if(res == null) {
            return ApiResultHandler.buildApiResult(10000,"考试编号不存在",null);
        }
        return ApiResultHandler.buildApiResult(200,"请求成功!",res);
    }
后端获取试题接口
    @GetMapping("/paper/{paperId}")
    public Map<Integer, List<?>> findById(@PathVariable("paperId") Integer paperId) {
        List<MultiQuestion> multiQuestionRes = multiQuestionService.findByIdAndType(paperId);   //选择题题库 1
        List<FillQuestion> fillQuestionsRes = fillQuestionService.findByIdAndType(paperId);     //填空题题库 2
        List<JudgeQuestion> judgeQuestionRes = judgeQuestionService.findByIdAndType(paperId);   //判断题题库 3
        Map<Integer, List<?>> map = new HashMap<>();
        map.put(1,multiQuestionRes);
        map.put(2,fillQuestionsRes);
        map.put(3,judgeQuestionRes);
        return  map;
    }
七、数据库设计
表名:admin
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| adminId | int(11) | 是 | ID号 | 
| adminName | varchar(20) | 否 | 姓名 | 
| sex | varchar(2) | 否 | 性别 | 
| tel | varchar(11) | 否 | 电话号码 | 
| varchar(20) | 否 | 电子邮箱 | |
| pwd | varchar(16) | 否 | 密码 | 
| cardId | varchar(18) | 否 | 身份证号 | 
| role | varchar(1) | 否 | 角色(0管理员,1教师,2学生) | 
表名:exam_manage
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| examCode | int(11) | 是 | 考试编号 | 
| description | varchar(50) | 否 | 该次考试介绍 | 
| source | varchar(20) | 否 | 课程名称 | 
| paperId | int(11) | 否 | 试卷编号 | 
| examDate | varchar(10) | 否 | 考试日期 | 
| totalTime | int(11) | 否 | 持续时长 | 
| grade | varchar(10) | 否 | 年级 | 
| term | varchar(10) | 否 | 学期 | 
| major | varchar(20) | 否 | 专业 | 
| institute | varchar(20) | 否 | 学院 | 
| totalScore | int(11) | 否 | 总分 | 
| type | varchar(255) | 否 | 考试类型 | 
| tips | varchar(255) | 否 | 考生须知 | 
表名:fill_question
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| questionId | int(11) | 是 | 试题编号 | 
| subject | varchar(20) | 否 | 考试科目 | 
| question | varchar(255) | 否 | 试题内容 | 
| answer | varchar(255) | 否 | 正确答案 | 
| analysis | varchar(255) | 否 | 题目解析 | 
| score | int(11) | 否 | 分数 | 
| level | varchar(5) | 否 | 难度等级 | 
| section | varchar(20) | 否 | 所属章节 | 
表名:judge_question
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| questionId | int(11) | 是 | 试题编号 | 
| subject | varchar(20) | 否 | 考试科目 | 
| question | varchar(255) | 否 | 试题内容 | 
| answer | varchar(255) | 否 | 正确答案 | 
| analysis | varchar(255) | 否 | 题目解析 | 
| score | int(11) | 否 | 分数 | 
| level | varchar(1) | 否 | 难度等级 | 
| section | varchar(20) | 否 | 所属章节 | 
表名:message
| 字段名称 | 数据类型 | 是否必填 | 注释 | 
|---|---|---|---|
| id | int(11) | 是 | 留言编号 | 
| title | varchar(20) | 否 | 标题 | 
| content | varchar(255) | 否 | 留言内容 | 
| time | date | 否 | 留言时间 | 
八、源码下载地址
原创项目,开发不易,保证项目经过多人调试与测试,可以准确无误运行(经过最新调试,系统依旧可以持续运行)
项目获取地址:
#浏览器打开一下官方网站进行项目源码下载
www.shiyuncode.com/productlist/2?search=%E8%80%83%E8%AF%95

















