成绩明细历史记录:按提交年月日分类,每个分类标记最高分
新增 DataService::dayKeyOf(),日期键一律用服务端本地时区计算(避免 UTC 导致东八区零点前后错一天);aggregateByStudent 为 attempts_list 每项附加 day/day_best/day_count,expandAttempts 透传。 弹窗按天分组渲染分组行(日期 + 共N次 + 最高X分),组内新到旧;当日最高标签仅在当天有多次提交时显示,避免单次日每行都挂标签。 修复:submit_ts=0(时间未知)的记录原本被误标为第1次(升序排序 idx=1 但展示在末尾),现显示 -;未知时间统一归入「未知时间」组。 aggregate 单测 17 -> 33(跨天归属/日内次数/每日最高/未知时间组/时区边界 00:30 与 23:30);全量 148 项全绿。
This commit is contained in:
@@ -89,6 +89,75 @@ $r4 = $agg4['rows'][0];
|
||||
check('单次提交 attempts = 1', ($r4['attempts'] ?? 0) === 1);
|
||||
check('单次提交 attempts_list = 1', count($r4['attempts_list'] ?? []) === 1);
|
||||
|
||||
echo "\n== 按提交时间年月日分组:每个分类内标记当日最高 ==\n";
|
||||
/** 按 [时间戳, 分数] 造行;ts=0 表示时间未知 */
|
||||
function makeRowsAt(string $sid, array $items): array
|
||||
{
|
||||
$rows = [];
|
||||
foreach ($items as $it) {
|
||||
[$ts, $sc] = $it;
|
||||
$rows[] = [
|
||||
'sid' => $sid,
|
||||
'name' => '测试生',
|
||||
'cls' => '1班',
|
||||
'grp' => 'A',
|
||||
'score' => $sc,
|
||||
'submit_ts' => $ts,
|
||||
'submit_at' => $ts > 0 ? date('Y-m-d H:i:s', $ts) : '-',
|
||||
'duration' => 120,
|
||||
'duration_txt' => '2分0秒',
|
||||
'answer_id' => 'ans-' . $ts,
|
||||
'matched' => true,
|
||||
'temp_save' => false,
|
||||
];
|
||||
}
|
||||
return $rows;
|
||||
}
|
||||
// 09-08 三次(70/95/88),09-09 两次(60/90)
|
||||
$rows5 = makeRowsAt('S005', [
|
||||
[strtotime('2026-09-08 09:00:00'), 70.0],
|
||||
[strtotime('2026-09-08 11:00:00'), 95.0],
|
||||
[strtotime('2026-09-08 15:00:00'), 88.0],
|
||||
[strtotime('2026-09-09 10:00:00'), 60.0],
|
||||
[strtotime('2026-09-09 14:00:00'), 90.0],
|
||||
]);
|
||||
$agg5 = DataService::aggregateByStudent($rows5, true);
|
||||
$r5 = $agg5['rows'][0];
|
||||
$al5 = $r5['attempts_list'];
|
||||
check('5 次提交 attempts_list = 5', count($al5) === 5);
|
||||
check('前 3 条归属 2026-09-08', ($al5[0]['day'] ?? '') === '2026-09-08' && ($al5[2]['day'] ?? '') === '2026-09-08',
|
||||
'got ' . ($al5[0]['day'] ?? '?'));
|
||||
check('后 2 条归属 2026-09-09', ($al5[3]['day'] ?? '') === '2026-09-09' && ($al5[4]['day'] ?? '') === '2026-09-09',
|
||||
'got ' . ($al5[3]['day'] ?? '?'));
|
||||
check('09-08 当天次数 = 3', ($al5[0]['day_count'] ?? 0) === 3, 'got ' . ($al5[0]['day_count'] ?? '?'));
|
||||
check('09-09 当天次数 = 2', ($al5[3]['day_count'] ?? 0) === 2, 'got ' . ($al5[3]['day_count'] ?? '?'));
|
||||
$dayBestIdx = array_values(array_filter($al5, fn($a) => !empty($a['day_best'])));
|
||||
check('每个分类各标记 1 个当日最高(共 2 个)', count($dayBestIdx) === 2, 'got ' . count($dayBestIdx));
|
||||
check('09-08 当日最高 = 95(第 2 次)', (int)($dayBestIdx[0]['idx'] ?? 0) === 2 && (float)($dayBestIdx[0]['score'] ?? -1) === 95.0,
|
||||
'got idx=' . ($dayBestIdx[0]['idx'] ?? '?') . ' score=' . ($dayBestIdx[0]['score'] ?? '?'));
|
||||
check('09-09 当日最高 = 90(第 5 次)', (int)($dayBestIdx[1]['idx'] ?? 0) === 5 && (float)($dayBestIdx[1]['score'] ?? -1) === 90.0,
|
||||
'got idx=' . ($dayBestIdx[1]['idx'] ?? '?') . ' score=' . ($dayBestIdx[1]['score'] ?? '?'));
|
||||
check('全局最佳仍是 95(第 2 次)', (int)($al5[1]['is_best'] ?? 0) === 1 || !empty($al5[1]['is_best']));
|
||||
|
||||
echo "\n== 时间未知(submit_ts=0)归入「未知时间」分组 ==\n";
|
||||
$rows6 = makeRowsAt('S006', [[0, 50.0], [0, 80.0]]);
|
||||
$agg6 = DataService::aggregateByStudent($rows6, true);
|
||||
$al6 = $agg6['rows'][0]['attempts_list'];
|
||||
check('时间未知时 day = 空串', ($al6[0]['day'] ?? 'x') === '' && ($al6[1]['day'] ?? 'x') === '',
|
||||
'got ' . var_export($al6[0]['day'] ?? null, true));
|
||||
check('未知时间组次数 = 2', ($al6[0]['day_count'] ?? 0) === 2, 'got ' . ($al6[0]['day_count'] ?? '?'));
|
||||
check('未知时间组内仍标记最高(80)', !empty($al6[1]['day_best']) && (float)($al6[1]['score'] ?? -1) === 80.0);
|
||||
|
||||
echo "\n== 日期键时区边界(不能用 UTC,否则零点前后错一天)==\n";
|
||||
check('00:30 仍算当天(东八区不会退到前一天)',
|
||||
DataService::dayKeyOf((int)strtotime('2026-09-08 00:30:00')) === '2026-09-08',
|
||||
'got ' . DataService::dayKeyOf((int)strtotime('2026-09-08 00:30:00')));
|
||||
check('23:30 仍算当天',
|
||||
DataService::dayKeyOf((int)strtotime('2026-09-08 23:30:00')) === '2026-09-08',
|
||||
'got ' . DataService::dayKeyOf((int)strtotime('2026-09-08 23:30:00')));
|
||||
check('无时间戳时从展示串取日期', DataService::dayKeyOf(0, '2026-09-08 09:41:20') === '2026-09-08');
|
||||
check('无时间戳且展示串为 - 时返回空串', DataService::dayKeyOf(0, '-') === '');
|
||||
|
||||
echo "\n========================================\n";
|
||||
echo "通过 {$pass} · 失败 {$fail}\n";
|
||||
exit($fail === 0 ? 0 : 1);
|
||||
|
||||
Reference in New Issue
Block a user