fix: 考试次数与历史始终展示全部提交(不再被 dedupe 吞成 1 条)
- aggregateByStudent 修复:attempts(真实次数) 与 attempts_list(每次提交明细) 无论 dedupe 取值都使用全部提交;dedupe 仅决定主明细表代表成绩取最新 还是最高分。此前 dedupe=true(默认)把 attempts 写成 1、attempts_list 只留 最新一份,导致考试次数列和点击历史都只显示 1 条,多次刷题数据丢失。 - best_score 改为跨全部尝试的真实最高分,修复历史弹窗标题最高分错误。 - 新增 tests/test-aggregate.php 覆盖:11次/2次/1次提交、dedupe 两种取值、 重考低分、导出展开全部记录,共 17 项断言全部通过。 数据印证:第二周测试(1).xlsx 共 146 份提交 / 35 人,31 人多次提交 (最多 11 次),修复后考试次数与历史均完整呈现。
This commit is contained in:
+17
-10
@@ -416,8 +416,13 @@ class DataService
|
||||
|
||||
/**
|
||||
* 按学号聚合一次提交的答卷记录,解决"同人多次刷卷"在看板中被当成多个人的问题。
|
||||
* - dedupe=true:每学号仅保留提交时间最新的一份(原行为)
|
||||
* - dedupe=false:每学号一行,代表成绩取最高分,附 attempts(次数) / attempts_list(每次提交明细)
|
||||
*
|
||||
* 关键语义(修复"考试次数=1 / 历史只有一条"的 bug):
|
||||
* - attempts(真实考试次数) 与 attempts_list(每次提交明细) **始终等于全部提交**,与 dedupe 无关;
|
||||
* 这样"考试次数列"与"点击查看历史"永远展示完整数据。
|
||||
* - dedupe 仅决定主明细表"代表成绩"那一行取哪次考试的成绩:
|
||||
* dedupe=true → 取提交时间最新的一份(默认,看板更干净)
|
||||
* dedupe=false → 取最高分(同分时取最早达到该分数的那次)
|
||||
*
|
||||
* @param array $rows 已匹配学号的原始 row(每条 = 一次提交)
|
||||
* @return array{rows:array, attempts_total:int}
|
||||
@@ -468,14 +473,12 @@ class DataService
|
||||
];
|
||||
}, $sorted);
|
||||
|
||||
// 代表成绩选择(仅影响主明细表那一行的成绩,不影响考试次数 / 历史明细)
|
||||
if ($dedupe) {
|
||||
// 仅保留提交时间最新的一份(明细列表也只留这一份,与"只保留最新"语义一致)
|
||||
// 代表成绩 = 提交时间最新的一份(默认,看板更干净)
|
||||
$row = $sorted[count($sorted) - 1];
|
||||
$row['attempts'] = 1;
|
||||
$row['best_score'] = $row['score'];
|
||||
$row['attempts_list'] = [$attemptsList[count($attemptsList) - 1]];
|
||||
} else {
|
||||
// 代表成绩取最高分(null 成绩不参与比较,全部为 null 时回退为最近一份)
|
||||
// 代表成绩 = 最高分(null 成绩不参与比较,全部为 null 时回退为最近一份)
|
||||
$best = null;
|
||||
$bestScore = null;
|
||||
foreach ($sorted as $a) {
|
||||
@@ -488,10 +491,14 @@ class DataService
|
||||
$best = $sorted[count($sorted) - 1];
|
||||
}
|
||||
$row = $best;
|
||||
$row['attempts'] = count($list);
|
||||
$row['best_score'] = $bestScore;
|
||||
$row['attempts_list'] = $attemptsList;
|
||||
}
|
||||
|
||||
// 关键修复:考试次数与历史明细始终使用真实全部提交,与去重无关
|
||||
// (之前 dedupe=true 时把 attempts 写成 1、attempts_list 只留最新一份,导致"考试次数"和
|
||||
// 历史弹窗都只显示 1 条,多次刷题的数据被吞掉)
|
||||
$row['attempts'] = count($list);
|
||||
$row['best_score'] = $maxScore; // 真实最高分(跨全部尝试),用于历史弹窗标题展示
|
||||
$row['attempts_list'] = $attemptsList;
|
||||
// 最近一次提交时间(与"代表成绩"可能是不同的一次考试):
|
||||
// 用于"按提交时间排序"和"新提交高亮",保证重考(哪怕分数更低)也能被发现
|
||||
$row['last_submit_ts'] = $lastSubmitTs;
|
||||
|
||||
Reference in New Issue
Block a user