fix(标签): /problem-tags 计数漏过滤隐藏题和赛题
Some checks failed
Deploy / deploy (push) Has been cancelled

标签列表按题目数 > 0 过滤,但计数没有像 /problems 那样限制
visible=true 且非赛题,导致标签在首页出现、点进去却一道题都没有。

同时把旧仓库冻结政策收紧写进 CLAUDE.md:从今天起旧仓库零改动,
不再有内部小修的例外,所有后续工作只落在 OJ2。

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-26 00:22:05 -06:00
parent d3365ecb32
commit 7b6bfeb6fb
2 changed files with 15 additions and 11 deletions

View File

@@ -2,19 +2,16 @@
OJ2 是判题狗Online Judge的后端重写Django 6 → Bun + TypeScript前后端同仓。
上一代在 `../OnlineJudge/`Django`../ojnext/`Vue SPA**两者都是回滚路径,
默认冻结。**
完全冻结、一行都不改。**
冻结的目的是「回滚那天旧站能原样起来、和新站看到同一份数据」,不是「一个字节都不许动」。
所以红线是**外部可观测的东西**
> **2026-08-26 起**:旧仓库零改动,没有例外——包括修 bug、包括不影响外部接口的
> 内部小修(日志、缓存实现之类,以前允许,现已收紧)。所有后续工作,包括在旧仓库
> 里发现的 bug都只落在 OJ2先确认 OJ2 是否有对应逻辑、是否重现了同样的问题,
> 只在 OJ2 里修;旧仓库那边如实告知用户"未处理,按当前政策不动旧仓库",不要顺手改掉。
- **不许动**:接口路径与响应结构、数据库 schema、磁盘上的数据布局、密码哈希格式、
依赖版本。这些一动回滚就不再是「把上游切回去」那么简单。
- **可以动**:纯内部实现的小修(缓存放哪、日志、注释),前提是签名、异常、
返回结构逐一对齐不变,且 `uv run ruff check` 通过。改完在 commit message 里
写清楚为什么值得破例。
已发生的破例:`utils/cache.py``JsonDataLoader` 把一言数据集塞 Redis每次请求
都要把 323KB 的 pickle 拉过网络再反序列化,改成了进程内缓存。响应结构没动。
冻结的目的是「回滚那天旧站能原样起来、和新站看到同一份数据」——改 OJ2 时,接口路径
与响应结构、数据库 schema 这些外部可观测的东西都要小心,一动回滚就不再是「把上游
切回去」那么简单。
设计文档:`docs/specs/2026-08-06-bun-backend-rewrite-design.md`
切换手册:`docs/specs/phase5-cutover-runbook.md` ← 上线当天照这份走

View File

@@ -148,9 +148,16 @@ problemRoutes.get("/problems", optionalAuth, async (c) => {
problemRoutes.get("/problem-tags", async (c) => {
const keyword = c.req.query("keyword")?.trim()
// 只数公开题库里可见的题:隐藏的题和比赛题都不算,否则标签会出现在
// 首页列表里,点进去却一道题都筛不出来(对齐 /problems 的过滤条件)
const rows = await db.select({ id: schema.problemTag.id, name: schema.problemTag.name, problemCount: countDistinct(schema.problemTags.problemId) })
.from(schema.problemTag)
.innerJoin(schema.problemTags, eq(schema.problemTags.problemtagId, schema.problemTag.id))
.innerJoin(schema.problem, and(
eq(schema.problem.id, schema.problemTags.problemId),
eq(schema.problem.visible, true),
isNull(schema.problem.contestId),
))
.where(keyword ? ilike(schema.problemTag.name, `%${keyword}%`) : undefined)
.groupBy(schema.problemTag.id, schema.problemTag.name).having(sql`count(${schema.problemTags.problemId}) > 0`)
.orderBy(asc(schema.problemTag.name))