答题卡一跳两题:一场 24 题多选考试的逐题核对法
一场 24 题的在线考试,我有 13 道题的答案没被记住,而页面从头到尾没有报过一次错。等我发现的时候,剩余时间还剩 40 分钟,账面「已答题 11/24」。这篇记录怎么查出这 13 道空题,以及一套能复用到最后一道题的核对顺序。
现象:下一题会跳两题
点第一次「下一题」,题号从 1 变成 3。第 2 题的题干我压根没见过,就这样被跳过去了。继续点,5、7、9 一路单数往上走。回头看答题卡,1、3、5、7 是已答状态,2、4、6、8 全是空白。
成因不难猜:按钮的点击回调里既做了「保存当前答案」,又做了「前进一题」,而外层还有一层同样的前进逻辑;或者保存后弹出的「已提交,请勿重复提交」确认框,在关闭时又触发了一次前进。两种都会让一次点击吃掉两题。
答题卡才是唯一可信的状态源
页面顶部写着「已答题 X/24」,这个数字有延迟,不能拿它做判断。真正准确的是答题卡的每一格,它的 class 会区分三种状态:
已答:class="item on" 当前:class="item on active" 未答:class="item"
把 24 格的状态一次性读出来,对着看哪些格子少了 on,就是漏掉的题:
const cards = [...document.querySelectorAll(".item")]
.filter(e => e.offsetParent && /^\d+$/.test(e.innerText.trim()))
.map(e => e.innerText.trim() + (/on/.test(e.className) ? "*" : ""));
输出形如 1* 2 3* 4 5*,带星号的就是已经落库的。这个办法不依赖任何接口,也不受顶部计数延迟影响。
多选题的选中态要读 checked
单选题点的是 label,选中与否看 aria-checked 就够了。多选题不行:它的 aria-checked 恒为 false,哪怕框已经勾上。真正的状态在最里面的原生输入框上:
document.querySelectorAll("label.tiny-checkbox input[type=checkbox]")
读 input.checked,返回 true 才算选中。用 aria-checked 判断会把已经答对的题当成没答,然后手忙脚乱地重新点一遍,反而把正确答案取消掉。
可用的逐题推进方式
别用「下一题」按钮,直接点答题卡上的数字格。它是切题入口,不触发前进逻辑,一次只走一格:
const cards = [...document.querySelectorAll(".item")]
.filter(e => e.offsetParent && /^\d+$/.test(e.innerText.trim()));
cards[目标题号 - 1].click();
每答完一题就回读一次答题卡状态,确认刚答的这格多了 on,再跳下一题。这个回读只花一次 DOM 查询,比事后翻回来补答便宜得多。
回到那场考试
用上面的顺序重跑一遍,把漏掉的 13 道题逐格补上,最后答题卡读到 24 个带星号,顶部计数同步显示 24/24。交卷,70 分通过。
如果当初答完就直接交卷,13 道空题按零分计,总分连及格线一半都够不到。真正救回来的不是运气,而是「以 UI 的最终状态为准,不以操作成功的假设为准」这一条。凡是点击类操作,只要它有中间态和延迟,就应该回读一次真实状态再往下走。
- 点赞
- 收藏
- 关注作者
评论(0)