feat: 支持单套试卷同一提交人多次刷卷并展示

- DataService::build 新增 aggregateByStudent 按学号聚合:
  dedupe=true 仅保留最新一份;false 则每学号一行(代表成绩取最高分)
  附 attempts(次数) 与 attempts_list(每次提交明细),修正提交人数被多次提交inflate的问题
- api.php dashboard 透传 attempts/attempts_list;statOf 增加 attempts 求和;export 增加刷题次数列
- dashboard.php 成员榜加"刷N次"徽标,点击下钻弹窗看每次提交(时间/成绩/时长/暂存);hero 显示总提交次数
- 主统计页成绩明细同样加"刷N次"徽标与下钻弹窗
- stats 新增 attempts_total
This commit is contained in:
2026-09-09 15:55:06 +08:00
parent 3952c77afe
commit d2f0908385
6 changed files with 188 additions and 27 deletions
+10 -4
View File
@@ -217,6 +217,7 @@ try {
$statOf = static function (array $stu, array $rs, int $fs): array {
$total = count($stu);
$submitted = count($rs);
$attempts = array_sum(array_map(static fn($r) => (int)($r['attempts'] ?? 1), $rs));
$scores = array_values(array_filter(array_map(static fn($r) => $r['score'] ?? null, $rs), static fn($v) => $v !== null));
$avg = $scores !== [] ? round(array_sum($scores) / count($scores), 2) : null;
$pass = count(array_filter($rs, static fn($r) => ($r['score'] ?? null) !== null && ($r['score'] >= 0.6 * $fs)));
@@ -226,6 +227,7 @@ try {
return [
'total' => $total,
'submitted' => $submitted,
'attempts' => $attempts,
'absent' => max(0, $total - $submitted),
'rate' => $total > 0 ? round($submitted / $total * 100, 1) : 0,
'avg' => $avg,
@@ -237,13 +239,16 @@ try {
};
// 已提交成员榜:按成绩从高到低,缺成绩者排最后,并给出排名
// 透传 attempts / attempts_list,供前端展示"同人多刷卷"
$membersOf = static function (array $rs): array {
$ms = [];
foreach ($rs as $r) {
$ms[] = [
'sid' => (string)($r['sid'] ?? ''),
'name' => (string)($r['name'] ?? ''),
'score' => ($r['score'] ?? null),
'sid' => (string)($r['sid'] ?? ''),
'name' => (string)($r['name'] ?? ''),
'score' => ($r['score'] ?? null),
'attempts' => (int)($r['attempts'] ?? 1),
'attempts_list' => $r['attempts_list'] ?? [],
];
}
usort($ms, static function (array $a, array $b): int {
@@ -440,7 +445,7 @@ try {
fputcsv($out, [$r['sid'] ?? '', $r['name'] ?? '', $r['cls'] ?? '', $r['grp'] ?? '']);
}
} else {
fputcsv($out, ['学号', '姓名', '班级', '组别', '成绩', '提交时间', '考试时长', '考试时长(秒)']);
fputcsv($out, ['学号', '姓名', '班级', '组别', '成绩', '提交时间', '考试时长', '考试时长(秒)', '刷题次数']);
foreach ($rows as $r) {
fputcsv($out, [
$r['sid'] ?? '',
@@ -451,6 +456,7 @@ try {
$r['submit_at'] ?? '',
$r['duration_txt'] ?? '',
$r['duration'] === null ? '' : $r['duration'],
(int)($r['attempts'] ?? 1),
]);
}
}