|
一个能跑的线系统在线考试系统,代码量往往比你想的考试要少。我见过最精简的源码一个PHP版本,核心文件加起来不到2MB,线系统却撑起了学校期末的考试800人同时在线考试。这套源码的源码骨架,无非是线系统三块:题库管理、考试会话、考试自动判分。源码但真正让它“活”起来的线系统,是考试几个容易被忽略的细节。 先看题库。源码源码里通常有个`question_bank`表,线系统字段不外乎题干、考试选项、源码答案、分值。但好的系统会在`question_type`上做文章——单选、多选、判断,甚至填空题。PHP处理多选判分时有个坑:必须把用户提交的数组和正确答案的数组都排序后再比较,否则顺序不一致直接判错。我见过不少新手在这摔跟头,源码里如果直接用了`array_diff`,那多半有隐患,得用`sort()`先处理。 考试会话这块,源码设计得巧妙与否,直接决定服务器扛不扛得住。常规做法是用户点击“开始考试”后,PHP生成一个加密的`exam_token`,存在SESSION里,同时把试卷题目快照进一张`exam_paper`表。为什么要快照?因为题库管理员可能中途改题,如果考试中直接读题库,用户看到的题目会变,这就不公平了。好的源码会锁定试卷,每道题的状态(已答、未答、标记)都记录在`exam_answer`表里,字段就三个:`user_id`、`question_id`、`user_option`。简洁到极致。 自动判分的逻辑,才是这套源码的灵魂。单选判断简单,比对字符串就行。多选要拆分成数组比对。填空题最麻烦,因为用户可能多打空格,或者答案有多个等价表述。源码里如果用了`trim()`和`str_replace`把全角空格转半角,那算及格;如果还支持正则表达式模糊匹配,比如`/答案1|答案2/`,那这系统起码是认真打磨过的。我见过一个狠的,直接在判分函数里调用了`similar_text()`做模糊匹配,给主观题打相似度分,虽然不完美,但省了老师不少事。 前端交互这块,PHP源码往往配点JavaScript。倒计时是必须的,到点自动交卷。但有个细节很多人忽略:用户切换浏览器标签页时,考试系统应该记录切出次数。源码里如果只是简单用`setInterval`倒计时,那用户开个新窗口查资料完全没法防。好一点的会监听`visibilitychange`事件,把切出时间戳发给后端,后端在交卷时能调出这个记录。虽然不能完全防作弊,但至少能吓唬住一部分人。 这套源码部署起来也就一顿饭的功夫。你把文件丢到Apache或Nginx的web目录,导入`database.sql`,改一下`config.php`里的数据库连接,就完事了。但真正跑起来,你会发现瓶颈在并发。PHP默认是阻塞式的,每个请求占一个进程,800人同时交卷那几秒,CPU会飙到90%以上。解决办法也简单,把判分逻辑拆成队列,用Redis做延迟处理,但大部分开源源码不会帮你做这一步——你得自己加。 最后说个让我印象深刻的案例。有个职教老师用这套源码改造成技能大赛模拟系统,他加了随机抽题和错题重练功能。抽题逻辑其实就一条SQL:`ORDER BY RAND() LIMIT 10`,但数据量过万时这条语句会把数据库拖垮。后来他改成先`SELECT id FROM question_bank`,然后在PHP里用`array_rand`随机取10个id,再去查详情。就这么个改动,响应时间从3秒降到0.2秒。你看,源码是死的,但改源码的人是活的。这套东西的价值,不在于它多完美,而在于你能站在它的肩膀上,快速搞出一个能用的考试环境——剩下的,就看你的需求有多野了。 |