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

独立开发实战:学生管理+考试防作弊机制设计 独立开发实战学生管理 考试防作弊机制设计一、问题起源在上一篇我分享了在线考试系统的整体搭建过程。但在实际使用中老师和学生都反馈了一些问题老师反馈「学生关了浏览器后台还显示在作答这个记录怎么消失」「有的学生考完了还能再进去这不是挂我们的人数吗」「能不能管理学生名单现在我们谁考了谁没考都靠人工记」学生反馈「考完了想回去看成绩怎么看」「别人是不是也能看我的成绩」这些问题其实很有代表性——任何用户系统都会遇到会话管理和权限控制的问题。这篇就详细讲讲我是怎么解决的。二、心跳机制解决「挂机不交卷」为什么需要心跳学生开始考试后系统在t_exam_session表里创建一条会话记录。正常情况下交卷后会自动删除这条记录。但如果学生直接关了浏览器❌beforeunload事件可以发请求但不是100%可靠❌ 等考试时长到了再清理要等45分钟✅ 心跳机制定期检查断开后快速释放实现方案前端每 30 秒发一个请求到后端// 前端每30秒发一次心跳heartbeatRef.currentsetInterval((){api.sendHeartbeat(examId,studentNo).catch((){})},30000)后端收到心跳更新last_heartbeat_at// 后端更新心跳时间session.setLastHeartbeatAt(LocalDateTime.now());sessionMapper.updateById(session);然后定时清理超过 1 分钟没心跳的会话// 每次查询前先清理LocalDateTimecutoffLocalDateTime.now().minusMinutes(1);sessionMapper.delete(newLambdaQueryWrapperExamSession().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表有没有记录。// 开始考试前检查是否已交卷longexistingCountresultMapper.selectCount(newLambdaQueryWrapperExamResult().eq(ExamResult::getPaperId,examId).eq(ExamResult::getStudentId,studentId));if(existingCount0){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)COMMENTBCrypt加密密码,statusTINYINTDEFAULT0COMMENT0正常 1禁用,created_byVARCHAR(50),updated_byVARCHAR(50),create_timeDATETIMEDEFAULTCURRENT_TIMESTAMP,update_timeDATETIMEDEFAULTNULLONUPDATECURRENT_TIMESTAMP,UNIQUEKEYuk_student_no(student_no));导入策略老师通过 Excel 模板导入学生模板格式学号、姓名、性别、班级、年级。第一次导入时自动设密码为student123。如果学号已存在则跳过不覆盖已有数据也不改密码。登录流程学生首页输入学号 密码后端的逻辑链输入学号密码 → 查学生表 → 学号不存在→ 提示「请联系老师」 → 被禁用 → 提示「已被禁用」 → 密码错 → 提示「密码错误」 → 全部通过 → 显示姓名班级允许选试卷考试权限控制学生只能看「我的成绩」接口按 studentId 过滤老师可以在后台查看所有学生的成绩和统计老师可以禁用某个学生该学号无法再登录考试但历史成绩保留五、前端通用组件沉淀这次开发中我写了一些通用组件以后新项目可以直接复用Toast 组件右上角滑入3秒自动消失支持 success/error/warning 三种类型。不用原生 alert体验好很多。ConfirmDialog 组件自定义确认弹窗毛玻璃背景 缩放动画支持 danger/warning/info 三种样式。API 封装统一requestT()函数自动注入 Bearer token解析后端{code, data, message}响应格式。这些组件已经提取成模板新项目直接用。六、小结做这个考试系统最大的体会是用户系统再小权限和会话管理都不能马虎。心跳机制解决挂机问题开始考试前检查已交卷防止重复进入学号密码登录防止无关人员乱入学生只能看自己的成绩老师看全部如果你也在做类似的小项目欢迎关注我后续分享更多实战经验。 如果你对某个功能的具体实现感兴趣欢迎留言交流。完整代码在 Gitee 私库设计文档可以分享参考。关于作者无羡独立开发者专注AI应用开发。 分类全栈开发 关注我获取更多技术分享 个人博客云深不知处 独立开发省钱攻略查看详情 体验我的AI产品一纸云深如果这篇文章对你有帮助欢迎点赞、收藏、关注你的支持是我持续创作的动力点击「阅读原文」查看我的独立开发笔记 点击查看我的个人介绍 点击查看我的小红书主页