feat(题单): 「截止时间」改成「布置期」,布置期内没加入的人也藏旧代码;老师能看全班情况,后台一次加好几道题

- 布置期(列名仍是 end_time,机房共库不改名)+ 新列 assigned_at:布置期内题单里这几道题,
  学生在布置开始之前交的代码先藏起来,不管加没加入,堵住「先抄再加入」;做对或到期放出来,不拦做题
- 「总分达到 N」奖章换成「做对 N 道」,草稿并进「不公开」(0026)
- /problem-sets 带布置期、必做题数、奖章获得时间;题目带做对时刻、错几次、旧代码藏着没有
- 新增 /problem-sets/:id/class-view(老师看一个班:真名 × 每题,加入前就做对过)、/problem-sets/locks
- 后台:批量加题、拖动排序、切必做;去掉状态、难度、分数、提示和单独的进度页

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-09 22:01:39 +08:00
1 parent 2224478294
commit 8c53e28dcb
11 files changed
+4958 -617

No files matched your search

@@ -0,0 +1,10 @@
-- 题单的「截止时间」改成「布置到」:它从来不截止任何东西,只管布置期内藏学生以前的代码(防抄),
-- 见 services/problemset.ts 的 problemSetLockCutoffs。列名 end_time 不改(机房和服务器共库,
-- 改名会让没升级的那边直接报错);旧值是按旧语义填的(3 个题单,都已过期),清掉。
ALTER TABLE "problemset" ADD COLUMN "assigned_at" timestamp with time zone;--> statement-breakpoint
UPDATE "problemset" SET "end_time" = NULL;--> statement-breakpoint
-- 「状态」和「可见」两道闸合成一个「公开」:草稿等于不公开,归档等于公开(一直都还能进)
UPDATE "problemset" SET "visible" = false WHERE "status" = 'draft';--> statement-breakpoint
UPDATE "problemset" SET "status" = 'active' WHERE "status" <> 'active';--> statement-breakpoint
-- 分数拿掉了,「总分达到 N」的奖章换成「做对 N 道」(线上那几套题每题 10 分,门槛不变)
UPDATE "problemset_badge" SET "condition_type" = 'problem_count', "condition_value" = GREATEST(1, CEIL("condition_value" / 10.0)) WHERE "condition_type" = 'score';
File diff suppressed because it is too large. Load diff
+7
View File
@@ -183,6 +183,13 @@
"when": 1791521256834,
"tag": "0025_submission_problem_user_idx",
"breakpoints": true
},
{
"idx": 26,
"version": "7",
"when": 1791553481647,
"tag": "0026_problemset_assignment",
"breakpoints": true
}
]
}
+11 -1
View File
@@ -417,7 +417,17 @@ export const problemset = pgTable(
difficulty: text().notNull().$type<ProblemSetDifficulty>(),
status: text().notNull().$type<ProblemSetStatus>(),
createdById: integer("created_by_id").notNull(),
endTime: timestamp("end_time", { withTimezone: true, mode: "string" }),
/**
* 布置期:assignedAt 是这一轮布置开始的时刻,assignedUntil 是布置到哪天(东八区当天结束)。
* 布置期内,题单里这几道题学生在 assignedAt 之前交的代码先藏起来(防抄),见
* services/problemset.ts 的 problemSetLockCutoffs。不拦做题,过期照样做、照样记进度。
* 两个都为空 = 没布置。
*
* 列名还是 end_time(以前叫「截止时间」,名不副实):机房那套和服务器共用这个库、
* 不一定同时升级,改列名会让没升级的那边一查题单就报错,所以只改代码里的名字
*/
assignedUntil: timestamp("end_time", { withTimezone: true, mode: "string" }),
assignedAt: timestamp("assigned_at", { withTimezone: true, mode: "string" }),
},
(table) => [
index("problemset_created_by_id_01b5197f").using(