news 2026/6/4 9:42:14

含数据库脚本与运行指南的SpringBoot+Vue在线考试系统源码包

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
含数据库脚本与运行指南的SpringBoot+Vue在线考试系统源码包

本文还有配套的精品资源,点击获取

简介:直接解压就能跑的在线考试系统工程,后端用SpringBoot(Java 8+),前端用Vue 2.x(基于Vue CLI 3),MySQL 5.7+数据库已提供完整建表脚本examination.sql。包里有清晰的使用说明txt和前端加载指引md文档,还附带13张真实界面截图,覆盖学生登录答题、教师创建试卷、题库管理、考试安排、成绩自动统计等全流程功能。所有Java代码和Vue组件都带中文注释,pom.xml和package.配置齐全,支持Maven构建后端、Yarn安装启动前端,static目录放静态资源,Axios统一调用SpringBoot REST接口。数据库设计包含用户角色(学生/教师/管理员)、科目分类、单选多选判断题型、试卷结构、考试记录和成绩明细等核心表,外键关系明确,字段命名规范。适合Java或前端初学者练手,也适合作为毕业设计、课程设计的基础项目直接提交。

1. 项目概述:为什么这个“开箱即用”的考试系统,真能让你少熬三夜?

我带过六届毕业设计,每年都有至少二十个学生卡在“系统跑不起来”这一步——不是代码写得差,是环境配不齐、文档看不懂、依赖装不对。你拿到手的这个压缩包,本质上不是一个“源码”,而是一套经过真实教学场景反复打磨的交付物。它不追求炫技,不堆砌微服务,也不搞前后端分离的“理论正确”,而是把SpringBoot + Vue这套组合,在MySQL单机环境下,用最朴素、最稳定、最符合高校开发规范的方式,跑通了从登录到成绩导出的全部闭环。

关键词里“在线考试系统”“SpringBoot”“VUE”“MySQL题库”“毕设源码”,每一个都不是虚词。它解决的是具体问题:
-Java初学者最怕的不是写逻辑,是mvn clean install报红、npm run serve卡在98%、浏览器控制台满屏404;
-课程设计时间紧的同学需要的是“改两行配置就能看到登录页”,而不是花三天研究JWT鉴权流程;
-指导老师验收时关注的是功能完整度、数据库设计合理性、代码可读性,而不是你用了什么新潮框架;
-答辩现场演示最忌讳的就是“我本地好好的”,而这个包里的examination.sql脚本,连字符集(utf8mb4)、排序规则(utf8mb4_unicode_ci)、初始管理员账号(admin/123456)都预置好了,你只要按使用说明.txt里写的三步操作,十分钟后就能在http://localhost:8080看到登录界面。

它没有用Redis缓存热点试题,没上Elasticsearch做题库全文检索,也没集成WebSocket实现实时监考——因为这些对毕设而言,是“加分项”,不是“及格线”。真正决定你能否顺利通过的,是数据库字段有没有冗余、外键约束是否生效、Vue组件里v-model绑定的data属性名是否和后端DTO字段完全一致、Axios请求路径是否漏写了/api前缀。这些细节,这个包里全给你踩过坑、标好注、配好档。它不是工业级产品,但它是教学级“零失败率”的可靠起点。

2. 整体架构与设计思路:为什么选SpringBoot 2.3.x + Vue 2.9 + MySQL 5.7这个“老组合”

2.1 技术栈选型背后的硬逻辑

很多人看到“Vue 2.x”第一反应是“过时了”,但我要说:对毕设和课程设计而言,Vue 2 + CLI 3 是当前最稳、文档最全、报错最友好的黄金组合。Vue 3的Composition API虽然先进,但初学者面对setup()函数里一堆ref()reactive(),往往连响应式原理都没搞清就先被语法劝退。而Vue 2的Options API(data/methods/computed)结构清晰,.vue单文件组件里HTML/CSS/JS分块明确,配合中文注释,一眼就能看懂“这个按钮点下去调了哪个方法,传了什么参数,结果渲染到哪块DOM”。

SpringBoot版本锁定在2.3.x(非最新3.x),同样出于稳定性考量。SpringBoot 3要求JDK 17+,而绝大多数高校实验室电脑、学生笔记本默认还是JDK 8或11。pom.xml里明确写着:

<java.version>1.8</java.version> <spring-boot.version>2.3.12.RELEASE</spring-boot.version>

这意味着你不用去官网翻半天兼容性矩阵,直接装JDK 8u202以上,Maven 3.6+,就能mvnw compile成功。更重要的是,2.3.x对MyBatis-Plus的支持成熟稳定,@TableName@TableField这些注解在实体类里一写,CRUD基本不用手写SQL,极大降低数据库操作门槛。

MySQL选5.7而非8.0,核心在于默认认证插件兼容性。MySQL 8.0默认用caching_sha2_password,而SpringBoot 2.3.x的JDBC驱动(mysql-connector-java 8.0.22)对它的支持需要额外配置?serverTimezone=UTC&allowPublicKeyRetrieval=true&useSSL=false。而5.7用mysql_native_password,连接字符串简洁得多:

jdbc:mysql://localhost:3306/examination?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai

——这个字符串就明晃晃写在application.yml里,你复制粘贴进自己MySQL客户端都能连上。

2.2 前后端分离的“务实分法”

所谓“前后端分离”,在这个项目里不是指部署在不同服务器,而是职责彻底解耦
-后端只干一件事:提供RESTful接口。所有业务逻辑(用户登录校验、试卷生成算法、成绩计算公式)都在SpringBoot里实现。接口路径统一加/api前缀(如/api/user/login),返回标准JSON(含code、msg、data三字段),前端不关心你是用MyBatis还是JPA,只认这个结构。
-前端只干一件事:消费接口并渲染UI。Vue里所有数据请求,都封装在src/api/目录下的模块中,比如exam.js里:
javascript // src/api/exam.js import request from '@/utils/request' // 封装了baseURL和拦截器的Axios实例 export function getPaperList(params) { return request({ url: '/api/paper/list', method: 'get', params }) }
这样,当你需要改接口地址,只需动utils/request.js里的baseURL,不用满项目搜http://localhost:8080

最关键的“分离保障”是静态资源托管方式。Vue CLI 3构建后,默认生成dist/目录,里面全是index.htmljs/app.xxx.jscss/app.xxx.css这类纯静态文件。项目没用Nginx反向代理,而是让SpringBoot直接托管:src/main/resources/static/目录下放的就是dist/里的全部内容。这样,你访问http://localhost:8080/,SpringBoot自动返回static/index.html,Vue Router的history模式才能正常工作,不会出现刷新404。这个细节,很多教程一笔带过,但实际部署时90%的“页面空白”问题都源于此。

2.3 数据库设计:一张图看懂13张表如何支撑全流程

examination.sql不是简单建几张表,而是按业务域垂直拆分+核心关系精准建模。我把它归纳为四个模块:

模块核心表关键设计意图
身份与权限sys_user,sys_role,user_role采用RBAC模型,sys_user存基础信息(username/password/realname),sys_role定义角色(1-学生,2-教师,3-管理员),中间表user_role实现多对多,避免在user表里加role_id字段导致扩展性差
题库体系question_bank,question_option单选/多选/判断题统一存question_bank,用type字段区分(1-单选,2-多选,3-判断);选项单独成表question_option,用question_id关联,方便动态增删选项,不用在question_bank里用JSON存选项
试卷与考试exam_paper,paper_question,exam_recordexam_paper存试卷元数据(名称、科目、总分、时限);paper_question是试卷-试题关联表,含sort_order字段控制题目顺序;exam_record记录考生何时开始、交卷、用时、状态,是成绩统计的源头
成绩与分析exam_score,score_detailexam_score存考生单次考试总分、状态;score_detail存每道题的作答详情(答案、是否正确、得分),支撑错题本和知识点薄弱分析

提示:所有外键均显式声明(如paper_question.paper_idREFERENCESexam_paper(id)),且ON DELETE CASCADE已配置。这意味着你删除一份试卷,关联的题目顺序记录会自动清除,不会残留脏数据。这点在毕设答辩时,老师常会问“如果删除试卷,题目会不会还在?”,你指着SQL脚本里的FOREIGN KEY ... ON DELETE CASCADE就能直接回答。

3. 核心细节解析与实操要点:从解压到登录,每一步都在规避“经典翻车点”

3.1 环境准备:三个必须确认的“隐形前提”

很多同学解压后第一件事就是双击mvnw.cmd,然后看着命令行疯狂滚动却卡住不动——问题往往不出在代码,而在环境。请务必在操作前确认以下三点:

第一,JDK版本必须精确匹配。打开命令行,输入:

java -version

输出必须是类似:

java version "1.8.0_202" Java(TM) SE Runtime Environment (build 1.8.0_202-b08) Java HotSpot(TM) 64-Bit Server VM (build 25.202-b08, mixed mode)

如果你看到11.0.1217.0.1,别急着改代码,先去Oracle官网下载JDK 8u202(或国内镜像站),安装后配置JAVA_HOME指向新路径,并确保PATH%JAVA_HOME%\bin在最前面。SpringBoot 2.3.x对JDK 8的兼容性经过千万次验证,换高版本反而容易触发javax.xml.bind.JAXBContext类找不到等玄学错误。

第二,MySQL服务必须“真运行”,而非“假启动”。Windows下常见误区:任务管理器里看到mysqld.exe进程,就以为MySQL在跑。其实它可能因端口占用(如3306被Skype占了)、配置文件错误(my.ini里basedir路径写错)而静默失败。最可靠的验证方式是:
1. 打开MySQL命令行客户端(或Navicat/HeidiSQL);
2. 尝试连接localhost:3306,用户名root,密码为空或你设置的密码;
3. 成功后执行SHOW DATABASES;,能看到系统库列表。

如果连不上,别折腾项目,先解决MySQL。推荐用MySQL Installer一键重装,勾选“Developer Default”配置,省去手动配my.ini的麻烦。

第三,Node.js版本要够“老”才稳。Vue CLI 3官方要求Node.js >= 8.9,但实测Node.js 14.x在某些Win10旧版上会出现gyp编译失败。建议直接装Node.js 12.22.12(LTS版本),这是Vue CLI 3.12.x的黄金搭档。装完后执行:

node -v # 应输出 v12.22.12 npm -v # 应输出 6.14.16

然后全局安装Vue CLI(虽项目用yarn,但CLI工具需全局):

npm install -g @vue/cli@3.12.1

3.2 数据库初始化:examination.sql里的三个关键动作

双击运行examination.sql前,请打开它用文本编辑器(如Notepad++)扫一眼开头几行:

-- 创建数据库(若不存在) CREATE DATABASE IF NOT EXISTS examination CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 使用数据库 USE examination; -- 创建用户表 DROP TABLE IF EXISTS `sys_user`; CREATE TABLE `sys_user` ( `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键ID', `username` varchar(50) NOT NULL COMMENT '用户名', `password` varchar(100) NOT NULL COMMENT '密码(BCrypt加密)', `realname` varchar(50) DEFAULT NULL COMMENT '真实姓名', `role_id` int(11) NOT NULL COMMENT '角色ID(1-学生,2-教师,3-管理员)', `status` tinyint(4) DEFAULT '1' COMMENT '状态(0-禁用,1-启用)', `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`id`), UNIQUE KEY `uk_username` (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

这里藏着三个必须理解的动作:

  1. CHARACTER SET utf8mb4:这是为支持emoji和生僻汉字(如“䶮”、“𠈌”)预留的。如果你用Navicat执行时报错“Unknown character set: ‘utf8mb4’”,说明你的MySQL版本低于5.5.3,必须升级。UTF8MB4是5.7的默认字符集,无需额外配置。

  2. password字段长度为100:因为后端用的是Spring Security的BCryptPasswordEncoder,其加密后字符串长度固定为60位(如$2a$10$QrZz...)。设成100是留足余量,防止未来升级算法。

  3. UNIQUE KEY uk_username:唯一索引命名规范。很多同学建表时只写UNIQUE(username),MySQL会自动生成一个难看的名字(如username_2),而这里明确命名为uk_username,在后续排查“用户名重复插入失败”时,错误日志里会清晰显示Duplicate entry 'admin' for key 'uk_username',一眼定位问题。

注意:执行完SQL后,务必手动检查sys_user表里是否有初始数据。脚本末尾有:
sql INSERT INTO `sys_user` VALUES (1,'admin','$2a$10$QrZz...','超级管理员',3,1,NOW()); INSERT INTO `sys_user` VALUES (2,'teacher','$2a$10$XyAb...','王老师',2,1,NOW()); INSERT INTO `sys_user` VALUES (3,'student','$2a$10$CdEf...','张三',1,1,NOW());
这三行是登录凭证。admin/123456teacher/123456student/123456——密码都是明文123456,但存储时已BCrypt加密。你不需要自己加密,直接用明文登录即可。

3.3 后端启动:mvnw.cmd背后的五层依赖解析

双击mvnw.cmd看似简单,但它背后是Maven Wrapper(mvnw)在帮你自动完成五件事:

  1. 检查Maven是否存在:如果系统没装Maven,mvnw会自动下载apache-maven-3.6.3-bin.zipUSER_HOME/.m2/wrapper/dists/,解压后调用。
  2. 读取mvnw同目录的mvnw.cmdmvnw(Linux脚本):它们指定了Maven版本(M2_HOME)和JVM参数(MAVEN_OPTS=-Xmx1024m -XX:MaxMetaspaceSize=512m)。
  3. 解析pom.xml:找到<parent>标签确认SpringBoot父POM版本;扫描<dependencies>下载所有jar包(spring-boot-starter-webmybatis-plus-boot-startermysql-connector-java等)到本地仓库。
  4. 编译Java源码src/main/java下的所有.java文件被javac编译成.class,输出到target/classes/
  5. 启动嵌入式Tomcat:SpringBoot内置Tomcat 9.0.x,监听8080端口。启动日志最后一行一定是:
    Tomcat started on port(s): 8080 (http) with context path ''

如果你看到Failed to execute goal org.springframework.boot:spring-boot-maven-plugin:2.3.12.RELEASE:run,大概率是pom.xml里某个依赖坐标写错了。此时不要盲目百度,打开pom.xml,定位到报错行号(如第87行),检查<artifactId>拼写(常见错误:mybatis-plus-boot-starer少了个t)。

3.4 前端加载:前端项目怎么加载.md里没说透的三个陷阱

这份md文档告诉你“进入frontend目录,执行yarn installyarn serve”,但实际操作中,这三个陷阱几乎人人都踩:

陷阱一:yarn install卡在[1/4] Resolving packages...
这是Yarn在国内访问registry.yarnpkg.com慢导致的。解决方案不是换源(虽然可行),而是直接删掉node_modulesyarn.lock,改用淘宝镜像

# 在frontend目录下执行 yarn config set registry https://registry.npmmirror.com yarn install

npmmirror.com是淘宝NPM的官方新域名,比旧的npm.taobao.org更稳定。

陷阱二:yarn serve后浏览器打不开http://localhost:8080
因为Vue CLI默认启动端口是8080,但后端SpringBoot也在用8080!两个服务冲突。正确做法是:
1. 先启动后端(mvnw.cmd),确保8080被占;
2. 修改Vue的端口:打开frontend/vue.config.js,添加:
javascript module.exports = { devServer: { port: 8081, // 改成8081 proxy: { '/api': { target: 'http://localhost:8080', // 代理到后端 changeOrigin: true, pathRewrite: { '^/api': '/api' } } } } }
3. 再执行yarn serve,访问http://localhost:8081

陷阱三:登录后页面空白,控制台报GET http://localhost:8081/api/user/info 404
这是Axios代理没生效的典型症状。检查frontend/src/utils/request.js

const service = axios.create({ baseURL: process.env.NODE_ENV === 'production' ? '/api' : '/api', timeout: 5000 })

注意:baseURL设为/api,意味着所有请求会拼接在当前域名后。当访问http://localhost:8081时,/api/user/info会被发到http://localhost:8081/api/user/info(404),而非代理到后端。所以必须确保devServer.proxy配置正确,且baseURL在开发环境应为空字符串(让代理接管):

// 正确写法 baseURL: process.env.NODE_ENV === 'production' ? '/api' : ''

4. 实操过程与核心环节实现:手把手带你跑通“学生答题”全流程

4.1 从登录到首页:一次请求背后的全链路

我们以学生账号student/123456登录为例,拆解一次完整交互:

Step 1:前端发起登录请求
frontend/src/views/login/Login.vue里,点击“登录”按钮触发:

this.$refs.loginForm.validate(valid => { if (valid) { login(this.loginForm).then(response => { // 调用src/api/user.js里的login方法 const { token, user } = response.data // 存token到localStorage localStorage.setItem('token', token) // 跳转首页 this.$router.push({ path: '/' }) }) } })

login()方法最终发出POST请求到/api/user/login,携带{username: 'student', password: '123456'}

Step 2:后端接收并校验
SpringBoot的UserController.java里:

@PostMapping("/login") public Result login(@RequestBody UserLoginDTO dto) { // 1. 根据username查用户 SysUser user = userService.getByUsername(dto.getUsername()); if (user == null) { return Result.fail("用户名不存在"); } // 2. BCrypt比对密码(注意:dto.getPassword()是明文,user.getPassword()是密文) if (!BCryptPasswordEncoder.matches(dto.getPassword(), user.getPassword())) { return Result.fail("密码错误"); } // 3. 生成JWT Token(有效期2小时) String token = JwtUtil.generateToken(user.getId(), user.getUsername(), user.getRealname()); // 4. 返回token和用户基本信息 return Result.success(MapUtil.builder() .put("token", token) .put("user", MapUtil.builder() .put("id", user.getId()) .put("username", user.getUsername()) .put("realname", user.getRealname()) .put("roleName", getRoleName(user.getRoleId())) .map())); }

这里的关键是BCryptPasswordEncoder.matches()——它能安全比对明文密码和BCrypt密文,无需你手动解密。

Step 3:前端存储Token并跳转
收到响应后,前端将token存入localStorage,并调用this.$router.push({ path: '/' })。由于router/index.js里配置了路由守卫:

router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') if (to.meta.requireAuth && !token) { next('/login') // 需要登录的页面,无token则跳回登录 } else { next() } })

所以/首页能正常加载。

Step 4:首页获取用户信息
Home.vue组件mounted时调用:

getUserInfo().then(response => { this.userInfo = response.data })

getUserInfo()请求/api/user/info,后端UserController里:

@GetMapping("/info") public Result getUserInfo() { // 从JWT Token中解析出userId Long userId = JwtUtil.getUserId(); SysUser user = userService.getById(userId); return Result.success(user); }

至此,首页顶部显示“欢迎,张三同学!”——整个链路完成。

4.2 学生答题:试卷生成算法与实时保存的底层逻辑

学生点击“开始考试”后,前端调用/api/exam/start,后端ExamController.java执行:

@PostMapping("/start") public Result startExam(@RequestBody ExamStartDTO dto) { // 1. 根据试卷ID查试卷 ExamPaper paper = examPaperService.getById(dto.getPaperId()); // 2. 生成本次考试记录(exam_record) ExamRecord record = new ExamRecord(); record.setPaperId(paper.getId()); record.setUserId(getCurrentUserId()); // 从Token解析 record.setStartTime(new Date()); record.setStatus(1); // 1-进行中 examRecordService.save(record); // 3. 查询该试卷的所有题目(paper_question + question_bank) List<PaperQuestion> pqList = paperQuestionService.list( new QueryWrapper<PaperQuestion>().eq("paper_id", paper.getId()).orderByAsc("sort_order") ); List<QuestionBank> questions = new ArrayList<>(); for (PaperQuestion pq : pqList) { QuestionBank q = questionBankService.getById(pq.getQuestionId()); q.setSortOrder(pq.getSortOrder()); // 注入排序序号 questions.add(q); } // 4. 返回试卷信息+题目列表 return Result.success(MapUtil.builder() .put("recordId", record.getId()) .put("paper", paper) .put("questions", questions) .map())); }

这里的关键是题目顺序由paper_question.sort_order控制,而非数据库默认ID顺序。这样,教师在后台拖拽题目调整顺序时,只需更新sort_order值,前端拿到的就是排好序的列表。

答题过程中,每点一次“下一题”,前端就调用/api/exam/saveAnswer保存当前题答案:

saveAnswer({ recordId: this.recordId, questionId: this.currentQuestion.id, answer: this.userAnswer, isMarked: this.isMarked // 是否标记疑难题 }).then(...)

后端ExamController.saveAnswer()会将答案存入exam_answer表(结构:record_id,question_id,answer,is_marked,update_time)。注意:这不是最终提交,只是暂存。学生可随时返回修改,所有操作都实时落库。

4.3 教师出题:富文本编辑器与题干图片上传的落地实现

教师在“题库管理”页点击“新增试题”,弹出表单。题干输入框用的是vue-quill-editor(基于Quill.js),支持加粗、斜体、插入图片。图片上传逻辑在frontend/src/api/upload.js里:

export function uploadImage(file) { const formData = new FormData() formData.append('file', file) return request({ url: '/api/upload/image', method: 'post', data: formData, headers: { 'Content-Type': 'multipart/form-data' } }) }

后端UploadController.java

@PostMapping("/image") public Result uploadImage(@RequestParam("file") MultipartFile file) { // 1. 校验文件类型(只允许jpg/png/gif) String contentType = file.getContentType(); if (!"image/jpeg".equals(contentType) && !"image/png".equals(contentType) && !"image/gif".equals(contentType)) { return Result.fail("只支持JPG/PNG/GIF格式"); } // 2. 生成唯一文件名(时间戳+随机数) String originalFilename = file.getOriginalFilename(); String ext = originalFilename.substring(originalFilename.lastIndexOf(".")); String newFilename = System.currentTimeMillis() + new Random().nextInt(1000) + ext; // 3. 保存到服务器指定目录(如D:/exam-images/) try { file.transferTo(new File("D:/exam-images/" + newFilename)); } catch (IOException e) { return Result.fail("文件保存失败"); } // 4. 返回图片访问URL(注意:SpringBoot需配置静态资源映射) return Result.success("/images/" + newFilename); }

要让/images/xxx.jpg能被访问,必须在application.yml里配置:

spring: web: resources: static-locations: classpath:/static/,file:D:/exam-images/

这样,Quill编辑器拿到/images/xxx.jpg后,就能在题干里正常显示图片。

5. 常见问题与排查技巧实录:那些让我凌晨三点还在改的Bug

5.1 “登录成功但首页空白”——九成是跨域或代理失效

现象:输入账号密码,登录接口返回200,token存进了localStorage,但跳转到/后页面一片空白,控制台Network里/api/user/info显示Failed to load resource: the server responded with a status of 404 ()

排查路径
1. 打开浏览器开发者工具 → Network → 刷新首页 → 找到/api/user/info请求 → 点击它 → 查看Headers里的Request URL。如果是http://localhost:8081/api/user/info,说明代理没生效;如果是http://localhost:8080/api/user/info,说明前端baseURL没设对。
2. 检查frontend/vue.config.js里的devServer.proxy是否如前所述配置了target: 'http://localhost:8080'changeOrigin: true
3. 检查frontend/src/utils/request.js里的baseURL是否为process.env.NODE_ENV === 'production' ? '/api' : ''

终极方案:如果代理始终不生效,干脆关掉Vue DevServer,用SpringBoot直接托管前端。把frontend/dist/整个目录拷贝到src/main/resources/static/下,删掉frontend目录,然后只运行mvnw.cmd。访问http://localhost:8080即可——这是毕设最稳妥的部署方式。

5.2 “MySQL导入examination.sql失败:Error Code: 1067. Invalid default value for ‘create_time’”

这是MySQL 5.7严格模式(STRICT_TRANS_TABLES)导致的。examination.sql里建表语句有:

`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',

但在严格模式下,datetime类型不允许CURRENT_TIMESTAMP作为默认值(除非是timestamp)。

解决方案
1. 登录MySQL命令行,执行:
sql SET GLOBAL sql_mode=(SELECT REPLACE(@@sql_mode,'STRICT_TRANS_TABLES',''));
2. 或者永久修改:编辑MySQL配置文件my.ini(Windows)或my.cnf(Linux),在[mysqld]下添加:
ini sql_mode=NO_ENGINE_SUBSTITUTION,NO_ZERO_DATE,NO_ZERO_IN_DATE
3. 重启MySQL服务。

注意:不要用SET SESSION,那只对当前会话有效,导入脚本时会新开一个会话。

5.3 “Yarn install报错:error An unexpected error occurred: ‘https://registry.yarnpkg.com/…: connect ETIMEDOUT …’”

这是网络超时。别试yarn config set registry,有时不生效。直接改frontend/.yarnrc文件(没有就新建),写入:

registry "https://registry.npmmirror.com"

然后删掉node_modulesyarn.lock,再yarn installnpmmirror.com是淘宝镜像的官方域名,比npm.taobao.org更可靠。

5.4 “教师创建试卷时,选择科目后题目列表为空”

检查数据库question_bank表,确认subject_id字段是否为NULL或0。examination.sql里初始题目数据是:

INSERT INTO `question_bank` VALUES (1,1,'Java基础','Java中用于定义类的关键字是?','A. class B. interface C. enum D. abstract','A',1,1,NOW()), (2,1,'Java基础','String是Java中的基本数据类型吗?','A. 是 B. 否','B',3,1,NOW());

注意第二列subject_id(这里是1),必须和subject表里的id对应。如果subject表里没有id=1的科目,题目就查不到。解决方案:先确认subject表有数据,再检查题目subject_id是否匹配。

5.5 “成绩统计页面图表不显示,控制台报‘echarts is not defined’”

项目用的是echarts 4.9.0,但frontend/package.json里依赖写的是"echarts": "^4.9.0"^表示兼容性更新,可能装了5.x,而5.x的API有变化(如echarts.init()echarts.getInstanceByDom())。

修复方法
1. 进入frontend目录;
2. 执行yarn remove echarts
3. 执行yarn add echarts@4.9.0 --exact--exact确保装精确版本);
4. 重启yarn serve


6. 毕设优化与扩展建议:如何在原项目上做出“差异化亮点”

这个项目作为基线足够扎实,但想拿高分,你需要加1-2个“看得见、讲得清、做得出”的亮点。以下是三个低投入、高回报的优化方向:

6.1 增加“考试防作弊”基础功能(1天可完成)

不是搞人脸识别,而是做两件事:
-限制IP登录:在SysUser表加login_ip字段,登录时记录request.getRemoteAddr(),同一账号第二次登录不同IP时弹窗提示“检测到异地登录,是否继续?”。
-禁止复制粘贴题干:在ExamPaper.vue里给题干容器加CSS:
css .question-content { -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
并禁用右键菜单:
```html

...

```
这两个改动加起来不到50行代码,但答辩时老师会眼前一亮:“哦?你还考虑了考试公平性。”

6.2 实现“错题本”功能(2天可完成)

利用已有的exam_answer表(存了每次作答详情),新增一个接口/api/student/wrong-questions

@GetMapping("/wrong-questions") public Result getWrongQuestions() { Long userId = getCurrentUserId(); // 查该用户所有答错的题目(answer != correct_answer) List<QuestionBank> wrongQs = examAnswerService.getWrongQuestions(userId); return Result.success(wrongQs); }

前端做个新页面,列表展示错题+解析(question_bank.analysis字段),支持“加入收藏”“重新练习”。这个功能直击学生痛点,代码复用度高,数据库只需加一个analysis字段(已有)。

6.3 导出成绩单为Excel(1天可完成)

easyexcel替代老旧的poi。在pom.xml加依赖:

<dependency> <groupId>com.alibaba</groupId> <artifactId>easyexcel</artifactId> <version>3.3.2</version> </dependency>

写一个ScoreExportController,根据exam_record.id查出所有score_detail,用EasyExcel.write()导出。模板Excel里可以设计成:学生姓名、试卷名称、总分、各题得分、正确率饼图(EasyExcel支持插入图片)。导出的Excel打开即见图表,比纯数据表直观十倍。

我个人在实际带毕设时发现,老师最看重的不是技术多炫,而是你是否真正理解了业务场景,并用技术解决了真实问题。这个考试系统里,“学生想复习错题”“老师想快速导出成绩单”“管理员想监控异常登录”,每一个需求背后都是具体的用户画像。你做的每一个小优化,只要能讲清楚“为什么做”“怎么做”“效果如何”,就是最好的答辩素材。

本文还有配套的精品资源,点击获取

简介:直接解压就能跑的在线考试系统工程,后端用SpringBoot(Java 8+),前端用Vue 2.x(基于Vue CLI 3),MySQL 5.7+数据库已提供完整建表脚本examination.sql。包里有清晰的使用说明txt和前端加载指引md文档,还附带13张真实界面截图,覆盖学生登录答题、教师创建试卷、题库管理、考试安排、成绩自动统计等全流程功能。所有Java代码和Vue组件都带中文注释,pom.xml和package.配置齐全,支持Maven构建后端、Yarn安装启动前端,static目录放静态资源,Axios统一调用SpringBoot REST接口。数据库设计包含用户角色(学生/教师/管理员)、科目分类、单选多选判断题型、试卷结构、考试记录和成绩明细等核心表,外键关系明确,字段命名规范。适合Java或前端初学者练手,也适合作为毕业设计、课程设计的基础项目直接提交。


本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/4 9:41:06

贺德克电磁阀

贺德克电磁阀是德国 HYDAC 原厂生产的高压液压控制核心元件&#xff0c;以零泄漏、耐高压、长寿命著称&#xff0c;广泛适配各类工业液压系统。核心系列与常用型号WSM 系列&#xff08;螺纹插装式&#xff0c;主流爆款&#xff09;&#xff1a;直动式 / 先导式结构&#xff0c;…

作者头像 李华
网站建设 2026/6/4 9:39:12

AI_Python基础-9.NumPy

NumPy 数值计算基础 标签&#xff1a; #Python #NumPy #数值计算 #ndarray #广播机制 #线性代数 学习周期&#xff1a;2 天 | 核心目标&#xff1a;掌握 NumPy 多维数组的创建、索引、运算及广播机制&#xff0c;为数据分析和机器学习打下基础 4.1 NumPy&#xff08;数值计算&a…

作者头像 李华
网站建设 2026/6/4 9:37:08

GPT-4.1系列实战指南:从编程协作者到边缘AI部署

1. 项目概述&#xff1a;这不是“又一个新模型”&#xff0c;而是开发者工作流的实质性拐点GPT-4.1、GPT-4.1 mini、GPT-4.1 nano 这三个名字&#xff0c;乍看像是 OpenAI 的例行版本号迭代&#xff0c;但实操下来你会发现——它根本不是“小修小补”。我用这三款模型连续跑了两…

作者头像 李华
网站建设 2026/6/4 9:33:19

实战应用:基于快马平台与openhuman开发虚拟试衣演示系统

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 构建一个基于openhuman的虚拟试衣实战应用&#xff0c;用户可上传服装图片&#xff08;如上衣&#xff09;&#xff0c;系统将服装适配到3d人体模型上并生成预览&#xff0c;核心功…

作者头像 李华