基于springboot+vue的计算机等级考试系统的设计与实现 - 代码讲解文档
·
基于springboot+vue的计算机等级考试系统的设计与实现 - 代码讲解文档

一、项目概述
本项目是一个基于SpringBoot+Vue前后端分离架构的华北大学计算机等级考试系统,为学生、教师和管理员提供完整的计算机等级考试管理平台。系统实现了考试报名、准考证管理、模拟考试、在线答题、成绩评定、学习资源等核心功能,是典型的在线考试管理系统。
1.1 系统主要功能
- 考试信息管理:发布计算机等级考试信息
- 报名管理:学生在线报名参加考试
- 准考证生成:自动生成准考证信息
- 模拟考试:支持多题型在线模拟测试
- 题库管理:试题录入、试卷生成
- 成绩评定:自动评分与人工评卷结合
- 学习资源:提供备考资料下载
- 系统日志:记录用户操作日志
1.2 技术选型
| 技术 | 版本 | 说明 |
|---|---|---|
| SpringBoot | 2.x | 后端框架 |
| Vue.js | 前端 | 前端框架(前后端分离) |
| MyBatis-Plus | 2.3 | ORM框架 |
| MySQL | 默认 | 关系型数据库 |
| WebSocket | 内置 | 实时通信 |
| SysLog注解 | 自定义 | 操作日志记录 |
二、技术架构
2.1 项目结构
springboots0hsf1ep/
├── src/main/java/com/
│ ├── annotation/ # 自定义注解
│ │ ├── APPLoginUser.java # APP登录用户
│ │ ├── IgnoreAuth.java # 无需权限验证
│ │ ├── LoginUser.java # 登录用户
│ │ └ SysLog.java # 系统日志注解
│ ├── aspect/ # AOP切面
│ │ └ SysLogAspect.java # 日志记录切面
│ ├── config/ # 配置类
│ ├── controller/ # 控制器层(14个)
│ ├── dao/ # 数据访问层
│ ├── entity/ # 实体类
│ │ ├── model/ # Model对象
│ │ ├── view/ # View对象
│ │ └ vo/ # VO对象
│ ├── interceptor/ # 拦截器
│ ├── service/ # 业务逻辑层
│ │ └ impl/ # Service实现
│ └── utils/ # 工具类
├── src/main/resources/
│ └ mapper/ # MyBatis映射
│ └ application.yml # 配置文件
└── pom.xml
2.2 Controller层模块
| Controller | 功能说明 |
|---|---|
| BaomingxinxiController | 报名信息管理 |
| KaoshixinxiController | 考试信息管理 |
| ZhunkaozhengController | 准考证管理 |
| ExampaperController | 试卷管理 |
| ExamquestionbankController | 题库管理 |
| ExamquestionController | 试题管理 |
| ExamrecordController | 考试记录 |
| PingdingfenxiController | 成绩评定 |
| JiaoshiController | 教师管理 |
| XueshengController | 学生管理 |
| XuexiziyuanController | 学习资源 |
| SyslogController | 系统日志 |
| NewsController | 公告新闻 |
三、核心功能模块讲解
3.1 考试记录模块(核心模块)
ExamrecordController.java
@RestController
@RequestMapping("/examrecord")
public class ExamrecordController {
@Autowired
private ExamrecordService examrecordService;
@Autowired
private ExampaperService exampaperService;
// 按试卷分组查询考试记录
@RequestMapping("/groupby")
public R page2(@RequestParam Map<String, Object> params, ExamrecordEntity examrecord, HttpServletRequest request) {
String tableName = request.getSession().getAttribute("tableName").toString();
if(tableName.equals("jiaoshi")) {
examrecord.setJiaoshizhanghao((String)request.getSession().getAttribute("username"));
} else {
if(!request.getSession().getAttribute("role").toString().equals("管理员")) {
examrecord.setUserid((Long)request.getSession().getAttribute("userId"));
}
}
EntityWrapper<ExamrecordEntity> ew = new EntityWrapper<>();
PageUtils page = examrecordService.queryPageGroupBy(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, examrecord), params), params));
return R.ok().put("data", page);
}
// 选项统计接口(用于分析答题分布)
@RequestMapping("/options/num")
public R optionsNum(@RequestParam Map<String, Object> params, ExamrecordEntity examrecord, HttpServletRequest request) {
EntityWrapper<ExamrecordEntity> ew = new EntityWrapper<>();
PageUtils page = examrecordService.queryPageOptionsNum(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, examrecord), params), params));
return R.ok().put("data", page);
}
// 保存考试记录(带系统日志)
@RequestMapping("/save")
@SysLog("新增模拟考试记录表")
public R save(@RequestBody ExamrecordEntity examrecord, HttpServletRequest request) {
examrecord.setUserid((Long)request.getSession().getAttribute("userId"));
ExampaperEntity exampaper = exampaperService.selectById(examrecord.getPaperid());
examrecord.setJiaoshizhanghao(exampaper.getJiaoshizhanghao());
examrecordService.insert(examrecord);
return R.ok().put("data", examrecord.getId());
}
// 重新考试时删除历史记录
@RequestMapping("/deleteRecords")
public R deleteRecords(@RequestParam Long userid, @RequestParam Long paperid) {
examrecordService.delete(new EntityWrapper<ExamrecordEntity>()
.eq("paperid", paperid).eq("userid", userid));
return R.ok();
}
}
Entity层 - ExamrecordEntity.java
考试记录实体,存储学生答题详情:
| 字段名 | 类型 | 说明 |
|---|---|---|
| id | Long | 主键ID |
| userid | Long | 用户ID |
| username | String | 用户名 |
| paperid | Long | 试卷ID(外键) |
| papername | String | 试卷名称 |
| questionid | Long | 题目ID(外键) |
| questionname | String | 题目名称 |
| options | String | 选项(JSON字符串) |
| score | Long | 分值 |
| answer | String | 正确答案 |
| analysis | String | 答案解析 |
| ismark | Long | 是否批卷(0/1) |
| type | Long | 题目类型(0单选/1多选/2判断/3填空/4主观) |
| myscore | Long | 学生得分 |
| myanswer | String | 学生答案 |
| jiaoshizhanghao | String | 教师账号 |
3.2 试卷与题库模块
ExampaperEntity - 试卷实体
@TableName("exampaper")
public class ExampaperEntity {
private Long id; // 试卷ID
private String papername; // 试卷名称
private Long paperexamtime; // 考试时长(分钟)
private Long paperscore; // 试卷总分
private String paperstate; // 试卷状态(启用/禁用)
private String jiaoshizhanghao; // 创建教师
}
ExamquestionbankEntity - 题库实体
试题库管理,支持多种题型:
- 单选题(type=0)
- 多选题(type=1)
- 判断题(type=2)
- 填空题(type=3)
- 主观题(type=4)
3.3 报名与准考证模块
BaomingxinxiController - 报名管理
学生报名流程:
- 查看考试信息
- 提交报名申请
- 管理员审核
- 生成准考证
ZhunkaozhengController - 准考证管理
准考证包含信息:
- 学生姓名
- 考试科目
- 考试时间
- 考试地点
- 准考证号
3.4 系统日志模块(特色功能)
@SysLog注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SysLog {
String value() default "";
}
SysLogAspect切面
@Aspect
@Component
public class SysLogAspect {
@Around("@annotation(sysLog)")
public Object around(ProceedingJoinPoint point, SysLog sysLog) throws Throwable {
// 记录操作时间、用户、方法名、参数等信息
long beginTime = System.currentTimeMillis();
Object result = point.proceed();
long time = System.currentTimeMillis() - beginTime;
// 保存日志到数据库
SyslogEntity syslogEntity = new SyslogEntity();
syslogEntity.setOperation(sysLog.value());
syslogEntity.setMethod(point.getSignature().getName());
syslogEntity.setTime(time);
syslogService.insert(syslogEntity);
return result;
}
}
3.5 学习资源模块
XuexiziyuanController
提供备考学习资料:
- 视频教程
- PDF文档
- 示例代码
- 练习题库
四、数据库设计分析
4.1 主要数据表结构
examrecord(考试记录表)
| 字段 | 类型 | 约束 | 说明 |
|---|---|---|---|
| id | bigint | PK, AUTO | 主键 |
| userid | bigint | FK | 用户ID |
| username | varchar(50) | 用户名 | |
| paperid | bigint | FK | 试卷ID |
| papername | varchar(100) | 试卷名称 | |
| questionid | bigint | FK | 题目ID |
| questionname | varchar(200) | 题目内容 | |
| options | text | 选项JSON | |
| score | bigint | 题目分值 | |
| answer | varchar(50) | 正确答案 | |
| analysis | text | 答案解析 | |
| ismark | bigint | DEFAULT 0 | 是否批卷 |
| type | bigint | 题目类型 | |
| myscore | bigint | 学生得分 | |
| myanswer | varchar(200) | 学生答案 | |
| jiaoshizhanghao | varchar(50) | FK | 教师账号 |
| addtime | datetime | 创建时间 |
exampaper(试卷表)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 试卷ID |
| papername | varchar(100) | 试卷名称 |
| paperexamtime | bigint | 考试时长(分钟) |
| paperscore | bigint | 总分 |
| paperstate | varchar(20) | 状态 |
| jiaoshizhanghao | varchar(50) | 创建教师 |
examquestionbank(题库表)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 题目ID |
| questionname | varchar(200) | 题目内容 |
| options | text | 选项JSON |
| answer | varchar(50) | 正确答案 |
| analysis | text | 答案解析 |
| score | bigint | 分值 |
| type | bigint | 题型 |
| jiaoshizhanghao | varchar(50) | 创建教师 |
baomingxinxi(报名信息表)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| xueshengzhanghao | varchar | 学生账号 |
| kaoshixiangmu | varchar | 考试项目 |
| baomingshijian | datetime | 报名时间 |
| sfsh | varchar | 是否审核 |
| shhf | varchar | 审核回复 |
syslog(系统日志表)
| 字段 | 类型 | 说明 |
|---|---|---|
| id | bigint | 主键 |
| operation | varchar | 操作描述 |
| method | varchar | 方法名 |
| params | text | 参数 |
| time | bigint | 执行时长(ms) |
| userid | bigint | 操作用户 |
| ip | varchar | IP地址 |
| createdate | datetime | 操作时间 |
4.2 数据表关系
- 教师(jiaoshi) 1:N 创建试卷(exampaper)
- 教师(jiaoshi) 1:N 创建题库(examquestionbank)
- 试卷(exampaper) 1:N 包含试题(examquestion)
- 学生(xuesheng) 1:N 报名信息(baomingxinxi)
- 学生(xuesheng) 1:N 考试记录(examrecord)
- 报名信息(baomingxinxi) 1:1 准考证(zhunkaozheng)
五、关键代码解析
5.1 题目类型处理
系统支持5种题型,每种类型有不同的评分逻辑:
// 单选题(type=0):答案完全匹配得分
// 多选题(type=1):部分正确按比例得分
// 判断题(type=2):答案匹配得分
// 填空题(type=3):字符串匹配得分
// 主观题(type=4):教师人工评分(ismark=1)
5.2 智能排序功能
@IgnoreAuth
@RequestMapping("/autoSort")
public R autoSort(@RequestParam Map<String, Object> params, ExamrecordEntity examrecord, HttpServletRequest request) {
EntityWrapper<ExamrecordEntity> ew = new EntityWrapper<>();
params.put("sort", "clicktime");
params.put("order", "desc");
PageUtils page = examrecordService.queryPage(params, MPUtil.sort(MPUtil.between(MPUtil.likeOrEq(ew, examrecord), params), params));
return R.ok().put("data", page);
}
5.3 考试记录分组统计
用于查看每次考试的完整答题情况:
// 查询某用户某试卷的所有答题记录
examrecordService.queryPageGroupBy(params, wrapper);
// 统计各选项选择人数分布
examrecordService.queryPageOptionsNum(params, wrapper);
5.4 数据脱敏处理
Map<String, String> deSens = new HashMap<>();
DeSensUtil.desensitize(examrecord, deSens);
对学生姓名、账号等敏感信息进行脱敏。
六、项目亮点总结
- 前后端分离架构:SpringBoot+Vue,前端独立部署
- 多题型支持:单选、多选、判断、填空、主观题
- 自动评分系统:客观题自动评分,主观题人工评卷
- 系统日志记录:基于AOP切面自动记录操作日志
- 准考证生成:报名审核后自动生成准考证
- 学习资源管理:提供完整的备考资料库
- 答题统计分析:统计各选项分布,便于教学分析
七、运行部署说明
7.1 环境要求
- JDK 1.8+
- MySQL 5.7+
- Node.js(前端)
- Maven 3.x
7.2 后端部署
- 导入数据库SQL脚本
- 修改application.yml配置
- 执行:
mvn spring-boot:run
7.3 前端部署
- 进入前端目录:
cd front - 安装依赖:
npm install - 启动项目:
npm run dev
7.4 访问地址
- 前台:http://localhost:8080/front
- 后台:http://localhost:8080/admin
更多推荐

所有评论(0)