feat(排名): 排名页重做成领奖台加全班赛道,一眼看出自己第几、该追谁、谁在追自己
Deploy / deploy (push) Canceled after 0s

- 一张榜两个开关:本班 / 本年级 / 全服 × 这周 / 这学期 / 全部,默认本班 · 这学期。
  原来最大那张全服 Top100 里,这学期在用的 25 级学生一个都进不去
- 做对一样多的不再按「提交少的在前」排,改成先做到的在前;名次旁边写比周一升降了几名
- 「你」那张卡:第几名、再做对几道上领奖台,要追的人早你几秒、追你的人晚你几秒
- 本年级 / 全服只列前面一段和你附近一段,中间折起来,点开再看
- 班级对抗按人均做对比,另有我和对手的名次走势、这周本班、每周冠军
- 老师不上榜,选班看;每行「⋯」能把怀疑抄代码的学生设成不计入排名(新增 user.rank_hidden_at,
  首页周榜同样不算他),随时能恢复
- 去掉全服 Top10、日活两张图、在线人数和班级详情弹框里的统计词,以及它们背后的旧接口

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-10 07:26:15 +08:00
1 parent 0cee4ef779
commit 1c6e2b9d82
31 files changed
+6633 -1392

No files matched your search

+1 -10
View File
@@ -1,9 +1,8 @@
import type { OnlineCount, Quote, WebsiteConfig } from "@oj2/contract"
import type { Quote, WebsiteConfig } from "@oj2/contract"
import { asc, desc, eq } from "drizzle-orm"
import { Hono } from "hono"
import { resolve } from "node:path"
import { onlineCount } from "../auth/presence"
import { config } from "../config"
import { db, schema } from "../db"
import { failure, success } from "../http"
@@ -26,14 +25,6 @@ siteRoutes.get("/site", async (c) => {
} satisfies WebsiteConfig)
})
/**
* 当前在线人数。匿名可读 —— 一个聚合数字不暴露任何人的身份,
* 而榜单页本身就允许匿名看。谁在线是另一回事,只在 /rankings/users 里对老师下发。
*/
siteRoutes.get("/site/online", async (c) => {
return success(c, { count: await onlineCount() } satisfies OnlineCount)
})
// 数据集读不到时的兜底(本机旁边没有 sentences-bundle 就会走这里)
const fallbackQuotes = [
{