feat(标签): 题目列表的标签分成「知识点」「主题」两组,新建的标签在后台标出待归类
Deploy / deploy (push) Canceled after 0s

- 迁移 0022:problem_tag 加 category(knowledge / theme)和 category_confirmed;
  存量 25 个题材、题集类标签归主题,其余归知识点,全部记为已确认
- 前台题目列表按两组显示标签,组内按题目数从多到少
- 后台标签管理:每行切换分类;出题时新建的标签默认知识点、标「待归类」并排在最前,
  页头提示待归类数量,可点「确认」保留默认;加分类筛选
- 新接口 PUT /admin/problem-tags/:id/category,设置分类即视为确认

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-27 20:38:43 +08:00
1 parent e1b6a9e9fa
commit d07459928d
12 files changed
+4226 -30

No files matched your search

+16
View File
@@ -0,0 +1,16 @@
-- 标签分「知识点 / 主题」两类,前台题目列表按两组显示,含义见契约 tagCategorySchema。
-- 带常量默认值的加列只改目录不重写表;新标签默认算知识点、且分类「未确认」,
-- 后台标签管理把未确认的排在最前面,等老师点一下归类。
ALTER TABLE "problem_tag" ADD COLUMN "category" text DEFAULT 'knowledge' NOT NULL;--> statement-breakpoint
ALTER TABLE "problem_tag" ADD COLUMN "category_confirmed" boolean DEFAULT false NOT NULL;--> statement-breakpoint
-- 存量标签的归类:按名字挑出主题类标签,其余留在知识点。按 lower(name) 匹配
-- (和唯一索引 problem_tag_name_ci_unique 同一口径),库里没有的名字空转即可。
-- 必会题、技能队、力扣是题集 / 来源而不是知识点,也归主题。
UPDATE "problem_tag" SET "category" = 'theme' WHERE lower("name") IN (
'弱智吧', '二次元', '狐妖小红娘', '第五人格', '农药', '哈利波特', '九大学科', '原',
'职一第一深情', '异兽', '反诈', '三角洲', '火影', '神秘复苏', 'blue archive',
'空洞骑士', '周杰伦', 'lol', '奥特曼', '无畏契约', '图书馆', '物联网',
'必会题', '技能队', '力扣'
);--> statement-breakpoint
-- 上面这版归类已经人工过目,存量标签一律算确认过;之后新建的才进「待归类」
UPDATE "problem_tag" SET "category_confirmed" = true;
File diff suppressed because it is too large. Load diff
+7
View File
@@ -155,6 +155,13 @@
"when": 1789990062378,
"tag": "0021_ai_hint_level",
"breakpoints": true
},
{
"idx": 22,
"version": "7",
"when": 1790512513639,
"tag": "0022_add_tag_category",
"breakpoints": true
}
]
}
+5
View File
@@ -52,6 +52,7 @@ import type {
ReactionKey,
SqlConfig,
SqlDisplay,
TagCategory,
TutorialType,
} from "@oj2/contract"
import {
@@ -738,6 +739,10 @@ export const problemTag = pgTable(
{
id: serial().primaryKey().notNull(),
name: text().notNull(),
category: text().notNull().default("knowledge").$type<TagCategory>(),
// 分类有没有人确认过。出题时顺手新建的标签一律先落在「知识点」,这一列为 false,
// 后台标签管理把它们排在最前面等老师归类;存量标签由 0022 统一标成 true
categoryConfirmed: boolean("category_confirmed").notNull().default(false),
},
() => [uniqueIndex("problem_tag_name_ci_unique").using("btree", sql`lower(name)`)],
)