diff --git a/api.php b/api.php index 92c922e..1f7b13f 100644 --- a/api.php +++ b/api.php @@ -171,11 +171,42 @@ try { ]; }; + // 已提交成员榜:按成绩从高到低,缺成绩者排最后,并给出排名 + $membersOf = static function (array $rs): array { + $ms = []; + foreach ($rs as $r) { + $ms[] = [ + 'sid' => (string)($r['sid'] ?? ''), + 'name' => (string)($r['name'] ?? ''), + 'score' => ($r['score'] ?? null), + ]; + } + usort($ms, static function (array $a, array $b): int { + $as = $a['score']; + $bs = $b['score']; + if ($as === null && $bs === null) { + return 0; + } + if ($as === null) { + return 1; // 无成绩排最后 + } + if ($bs === null) { + return -1; + } + return $bs <=> $as; // 成绩降序 + }); + foreach ($ms as $i => $m) { + $ms[$i]['rank'] = $i + 1; + } + return $ms; + }; + $classes = []; foreach ($byCls as $k => $stu) { $rs = $rowsByCls[$k] ?? []; $row = $statOf($stu, $rs, $fs); - $row['class'] = $k; + $row['class'] = $k; + $row['members'] = $membersOf($rs); // 班级内按组别(A/B 等)再聚合,用于看板下钻对比 $stuByGrp = []; @@ -191,7 +222,8 @@ try { $groups = []; foreach ($stuByGrp as $g => $gstu) { $gs = $statOf($gstu, $rowsByGrp[$g] ?? [], $fs); - $gs['group'] = $g; + $gs['group'] = $g; + $gs['members'] = $membersOf($rowsByGrp[$g] ?? []); $groups[] = $gs; } usort($groups, static fn(array $a, array $b): int => strcmp((string)$a['group'], (string)$b['group'])); diff --git a/assets/style.css b/assets/style.css index 31c151c..65d8cf9 100644 --- a/assets/style.css +++ b/assets/style.css @@ -499,8 +499,36 @@ body.fs-on .topbar { padding-top: 8px; padding-bottom: 8px; } .gpanel .ghead strong { font-size: 16px; } .gpanel .ghead .rate-num { font-size: 15px; font-weight: 800; } +/* 成员榜:排名 / 姓名 / 成绩 */ +.mem-title { + margin-top: 16px; margin-bottom: 8px; + font-size: 12px; font-weight: 700; color: var(--text-2); +} +.member-list { + max-height: 300px; overflow: auto; + border: 1px solid var(--border-2); border-radius: 10px; background: #fff; +} +.member-list table.grid { font-size: 12.5px; } +.member-list table.grid th { padding: 8px 10px; } +.member-list table.grid td { padding: 6px 10px; } +.rk { + display: inline-flex; align-items: center; justify-content: center; + min-width: 22px; height: 22px; padding: 0 6px; border-radius: 999px; + background: var(--border-2); color: var(--text-2); + font-size: 12px; font-weight: 700; font-variant-numeric: tabular-nums; +} +.rk-1 { background: #fff2d6; color: #b7791f; } +.rk-2 { background: #eef1f6; color: #64748b; } +.rk-3 { background: #fbe9dd; color: #b45309; } + +/* 防溢出:网格子项允许收缩,长内容不撑破页面 */ +.class-grid, .group-compare, .cards, .gpanel, .class-card { min-width: 0; } +.gpanel, .class-card { overflow: hidden; } +.member-list td.name { max-width: 140px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + /* 看板全屏适配 */ body.fs-on .wrap { max-width: none; padding-top: 14px; } +body.fs-on .member-list { max-height: 46vh; } body.fs-on .class-grid { grid-template-columns: repeat(auto-fill, minmax(340px, 1fr)); } body.fs-on .group-compare { grid-template-columns: 1fr 1fr; } body.fs-on .dash-hero { border-radius: var(--radius); } diff --git a/dashboard.php b/dashboard.php index 33e2c60..c56f0c4 100644 --- a/dashboard.php +++ b/dashboard.php @@ -152,6 +152,27 @@ function renderClasses(d){ }).join(''); } +/* ---------- 成员榜:排名 / 姓名 / 成绩(默认成绩降序) ---------- */ +function membersTable(members){ + if (!members || !members.length) { + return '
| 排名 | 姓名 | 成绩 |
|---|---|---|
| ' + rk + ' | ' + + '' + esc(m.name) + ' | ' + + '' + (sc == null ? '-' : sc) + ' | ' + + '