当前位置: 首页 > news >正文

独立开发实战:学生管理+考试防作弊机制设计

独立开发实战:学生管理 + 考试防作弊机制设计


一、问题起源

在上一篇我分享了在线考试系统的整体搭建过程。但在实际使用中,老师和学生都反馈了一些问题:

老师反馈:

  • 「学生关了浏览器,后台还显示在作答,这个记录怎么消失?」
  • 「有的学生考完了还能再进去,这不是挂我们的人数吗?」
  • 「能不能管理学生名单?现在我们谁考了谁没考都靠人工记」

学生反馈:

  • 「考完了想回去看成绩怎么看?」
  • 「别人是不是也能看我的成绩?」

这些问题其实很有代表性——任何用户系统都会遇到会话管理权限控制的问题。这篇就详细讲讲我是怎么解决的。


二、心跳机制:解决「挂机不交卷」

为什么需要心跳

学生开始考试后,系统在t_exam_session表里创建一条会话记录。正常情况下交卷后会自动删除这条记录。但如果学生直接关了浏览器:

  • beforeunload事件可以发请求,但不是100%可靠
  • ❌ 等考试时长到了再清理,要等45分钟
  • ✅ 心跳机制:定期检查,断开后快速释放

实现方案

前端每 30 秒发一个请求到后端:

// 前端:每30秒发一次心跳heartbeatRef.current=setInterval(()=>{api.sendHeartbeat(examId,studentNo).catch(()=>{})},30000)

后端收到心跳更新last_heartbeat_at

// 后端:更新心跳时间session.setLastHeartbeatAt(LocalDateTime.now());sessionMapper.updateById(session);

然后定时清理超过 1 分钟没心跳的会话:

// 每次查询前先清理LocalDateTimecutoff=LocalDateTime.now().minusMinutes(1);sessionMapper.delete(newLambdaQueryWrapper<ExamSession>().eq(ExamSession::getPaperId,paperId).and(w->w.isNull(ExamSession::getLastHeartbeatAt).or().lt(ExamSession::getLastHeartbeatAt,cutoff)));

三层防御

为了确保不遗漏,我做了三层防御:

防御层机制效果
beforeunload关标签页弹确认框 + fetch keepalive给用户一次反悔机会
visibilitychange切标签页时发一次心跳切走也能保持会话
后端定时清理1分钟无心跳自动清除兜底方案,无论什么情况都不超过1分钟

这样设计后,学生正常考试不受影响,意外断开后最多 1 分钟就会自动清理。


三、防重复进入:已考过的不能再考

原来的流程是:输入姓名 → 选试卷 → 开始考试 → 创建会话 → 答题 → 交卷

问题在于「开始考试」时没有检查是否已交卷。已考过的学生点开始考试,系统又给他创建了会话,但交卷时会被拦住「你已经提交过试卷了」。会话就挂在那了。

修复很简单:创建会话之前先查t_exam_result表有没有记录。

// 开始考试前检查是否已交卷longexistingCount=resultMapper.selectCount(newLambdaQueryWrapper<ExamResult>().eq(ExamResult::getPaperId,examId).eq(ExamResult::getStudentId,studentId));if(existingCount>0){returnApiResult.error(400,"你已经参加过本场考试");}

这样已考过的学生根本进不到考试页面,也不会产生无效的会话记录。


四、学生管理:学号 + 密码登录

之前任何人都能输入姓名就考试,显然不行。我加了个完整的学生管理模块。

数据库设计

CREATETABLEt_student(idBIGINTAUTO_INCREMENTPRIMARYKEY,student_noVARCHAR(50)NOTNULLUNIQUECOMMENT'学号',nameVARCHAR(50)NOTNULLCOMMENT'姓名',genderVARCHAR(10)COMMENT'男/女',gradeVARCHAR(20)COMMENT'年级(下拉选择)',class_nameVARCHAR(50)COMMENT'班级(自由输入)',passwordVARCHAR(200)COMMENT'BCrypt加密密码',statusTINYINTDEFAULT0COMMENT'0=正常 1=禁用',created_byVARCHAR(50),updated_byVARCHAR(50),create_timeDATETIMEDEFAULTCURRENT_TIMESTAMP,update_timeDATETIMEDEFAULTNULLONUPDATECURRENT_TIMESTAMP,UNIQUEKEYuk_student_no(student_no));

导入策略

老师通过 Excel 模板导入学生,模板格式:学号、姓名、性别、班级、年级。

第一次导入时自动设密码为student@123。如果学号已存在则跳过,不覆盖已有数据,也不改密码。

登录流程

学生首页输入学号 + 密码,后端的逻辑链:

输入学号密码 → 查学生表 → 学号不存在?→ 提示「请联系老师」 → 被禁用? → 提示「已被禁用」 → 密码错? → 提示「密码错误」 → 全部通过 → 显示姓名班级,允许选试卷考试

权限控制

  • 学生只能看「我的成绩」,接口按 studentId 过滤
  • 老师可以在后台查看所有学生的成绩和统计
  • 老师可以禁用某个学生(该学号无法再登录考试,但历史成绩保留)

五、前端通用组件沉淀

这次开发中我写了一些通用组件,以后新项目可以直接复用:

Toast 组件:右上角滑入,3秒自动消失,支持 success/error/warning 三种类型。不用原生 alert,体验好很多。

ConfirmDialog 组件:自定义确认弹窗,毛玻璃背景 + 缩放动画,支持 danger/warning/info 三种样式。

API 封装:统一request<T>()函数,自动注入 Bearer token,解析后端{code, data, message}响应格式。

这些组件已经提取成模板,新项目直接用。


六、小结

做这个考试系统最大的体会是:用户系统再小,权限和会话管理都不能马虎。

  • 心跳机制解决挂机问题
  • 开始考试前检查已交卷,防止重复进入
  • 学号+密码登录,防止无关人员乱入
  • 学生只能看自己的成绩,老师看全部

如果你也在做类似的小项目,欢迎关注我,后续分享更多实战经验。

💡 如果你对某个功能的具体实现感兴趣,欢迎留言交流。完整代码在 Gitee 私库,设计文档可以分享参考。


关于作者:无羡,独立开发者,专注AI应用开发。

📌 分类:全栈开发

👉 关注我获取更多技术分享
👉 个人博客:云深不知处
👉 独立开发省钱攻略:查看详情
👉 体验我的AI产品:一纸云深

如果这篇文章对你有帮助,欢迎点赞、收藏、关注,你的支持是我持续创作的动力!

点击「阅读原文」查看我的独立开发笔记


👉 点击查看我的个人介绍

👉 点击查看我的小红书主页

http://www.jsqmd.com/news/1123791/

相关文章:

  • laserMapping.cpp 中的 sync_packages() 详细讲解
  • 如何永久保存微信聊天记录:简单三步实现数据自主管理终极指南
  • 掌握专业级Windows Defender控制:高效系统安全防护管理实战指南
  • 彻底掌控你的Windows“此电脑“:MyComputerManager让顽固图标消失无踪
  • 深耕低代码5年,终于遇见打破行业桎梏的AI原生平台
  • 不受待见的钻石又火了?新娘不要英伟达为啥抢着要?
  • Obsidian插件汉化终极指南:3种模式快速实现英文插件中文化
  • GTA5终极修改器YimMenu:10分钟快速上手指南
  • 50. 怎么给OrCAD封装库添加新的属性?I Cadence Allegro 电子设计 快问快答
  • Shell的基础知识和常用命令
  • OpenClaw:AI智能体开发的高效跨平台解决方案
  • CUE: Concept-Aware Multi-Label Expansion to Mitigate Concept Confusion in Long-Tailed Learning
  • PIC32与25CSM04 SPI EEPROM高速数据检索实现
  • 5分钟解锁你的音乐宝库:qmcdump音频格式转换工具完全指南
  • 强力解锁喜马拉雅音频自由:跨平台下载神器XMly-Downloader-Qt5深度解析
  • 终极智能控制:用Turbo Boost Switcher重新掌控你的Mac性能体验
  • 蛋糕烘焙小程序|实用线上展示页面设计分享
  • Office批量打印软件推荐,告别低效操作
  • Python 语法基础 IO
  • Java非对称加密实战:RSA、DSA、ECC算法对比与选型指南
  • C++中的STL与标准库算法
  • 杭州创始人IP打造运营如何进行?
  • 通过kickstart 执行mysql、clickhouse数据导入
  • Web应用文件安全:IDOR、路径遍历与SSRF漏洞防御实战
  • 5分钟自动化部署:Brigadier跨平台Boot Camp驱动管理解决方案
  • 做网课直播还在用手比划?这两款键盘鼠标显示工具,让观众看清你的每一步操作
  • AI 电动窗帘电机智能驱动 静音化、高效率 完整选型方案
  • HoRain云--Java文档注释规范与最佳实践指南
  • 当青春记忆面临消失危机时,QZoneExport如何为你守护数字时光
  • SMT贴片机抛料原因深度解析