feat(提交): 列表标出来自题单的提交
Deploy / deploy (push) Has been cancelled

submission 新增 problemset_id,学生从 /problemset/:id/problem/:pid 入口提交时
前端带上、后端落库,提交列表在题目后面挂一个「题单 xxx」的标签,点了进题单。

只是来源标记:题单进度和奖章仍由判完之后的 recordSolvedProblem 按「已加入且含
这道题的所有题单」记账,和从哪个入口进来无关,所以这个字段带错顶多标签不准,
不影响成绩。校验只确认这道题在那个题单里 —— 不查 visible / status、也不查有没有
加入,藏起来的题单里还困着已加入的学生;对不上就当没带,提交照收。

外键 ON DELETE SET NULL:删题单不该带走提交,清掉标记就行。索引建成部分索引
(WHERE problemset_id IS NOT NULL),绝大多数提交不来自题单,全列索引是给 12 万行
白建一遍;谓词能被 problemset_id = $1 蕴含,删题单时的外键检查也用得上它。

列表按页单独查一次题单标题,没有把 problemset join 进那条调过的深翻页查询。
比赛提交恒为 null:题单只收非比赛题。

历史回填从 problemset_submission 取「当年首次 AC 那条」,其余老提交无从判断入口,
一律留空。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Y7AsqceaUfC81k7UCDcSk2
This commit is contained in:
xuyueandClaude Opus 5 committed 2026-09-02 22:06:29 -06:00
1 parent cf1eea0810
commit e624c62502
8 files changed
+4100 -11

No files matched your search

@@ -0,0 +1,14 @@
ALTER TABLE "submission" ADD COLUMN "problemset_id" bigint;--> statement-breakpoint
ALTER TABLE "submission" ADD CONSTRAINT "submission_problemset_id_fk_problemset_id" FOREIGN KEY ("problemset_id") REFERENCES "public"."problemset"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
CREATE INDEX "submission_problemset_id_idx" ON "submission" USING btree ("problemset_id") WHERE "submission"."problemset_id" is not null;--> statement-breakpoint
-- 历史回填。老提交没有入口信息,唯一可考的是 problemset_submission:它记的是
-- 「这条提交让这道题在这个题单里算完成了」,本来就是刷题单刷出来的那一条,标出来不算冤枉。
-- 覆盖不到的是同一道题在此之前的 WA 和之后的重复 AC —— 那些只能留空,往后新提交才准。
-- 一条提交在多个题单里都记过账时(recordSolvedProblem 会记进所有已加入的题单),
-- 任取其一:来源入口只有一个,但事后已经分不出是哪个了。
UPDATE "submission" SET "problemset_id" = "ps"."problemset_id"
FROM (
SELECT DISTINCT ON ("submission_id") "submission_id", "problemset_id"
FROM "problemset_submission" ORDER BY "submission_id", "problemset_id"
) AS "ps"
WHERE "ps"."submission_id" = "submission"."id" AND "submission"."problemset_id" IS NULL;