只改界面文字和注释:网址 /problemset、接口、表名、字段名都不动,老链接照常能打开。 设计稿页名「题单重设计」和已执行的迁移文件保留原样。 线上 3 个成就(题单收藏家 / 入门 / 通关)已同步改名。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
959c326bc9
commit
1b703d13ae
68 files changed
+306
-306
No files matched your search
@@ -62,7 +62,7 @@ export const pendingAchievementSchema = z.object({
|
||||
|
||||
/**
|
||||
* WebSocket 推来的解锁通知。比 `/achievements/pending` 多一个 `kind` ——
|
||||
* 题单奖章和成就来自两张表、id 会重叠,前端靠它区分(见 events.ts 的 publishAchievementNotification)。
|
||||
* 专题奖章和成就来自两张表、id 会重叠,前端靠它区分(见 events.ts 的 publishAchievementNotification)。
|
||||
*/
|
||||
export const achievementNotificationSchema = pendingAchievementSchema.extend({
|
||||
kind: z.enum(['achievement', 'badge']),
|
||||
|
||||
@@ -462,7 +462,7 @@ export const updateAcmHelperRequestSchema = z.object({
|
||||
checked: z.boolean(),
|
||||
})
|
||||
|
||||
// ---------------------------------------------------------------- 题单管理
|
||||
// ---------------------------------------------------------------- 专题管理
|
||||
|
||||
export const adminProblemSetSchema = z.object({
|
||||
id: z.number().int(),
|
||||
@@ -474,13 +474,13 @@ export const adminProblemSetSchema = z.object({
|
||||
assignedAt: z.string().nullable(),
|
||||
/** 现在在不在布置期内(服务端的钟) */
|
||||
assigning: z.boolean(),
|
||||
/** 公开:学生能在题单列表里看到、能进 */
|
||||
/** 公开:学生能在专题列表里看到、能进 */
|
||||
visible: z.boolean(),
|
||||
createdBy: sampleUserSchema,
|
||||
createTime: z.string(),
|
||||
lastUpdateTime: z.string(),
|
||||
problemsCount: z.number().int(),
|
||||
/** 加入这份题单的人数,后台用来判断改动会影响多少人 */
|
||||
/** 加入这个专题的人数,后台用来判断改动会影响多少人 */
|
||||
participantCount: z.number().int(),
|
||||
/** 做完(必做题全对)的人数 */
|
||||
completedCount: z.number().int(),
|
||||
@@ -519,7 +519,7 @@ export const addProblemsToSetResultSchema = z.object({
|
||||
added: z.array(z.string()),
|
||||
/** 题号不存在、不可见或是比赛题 */
|
||||
missing: z.array(z.string()),
|
||||
/** 本来就在题单里 */
|
||||
/** 本来就在专题里 */
|
||||
duplicate: z.array(z.string()),
|
||||
})
|
||||
|
||||
@@ -527,7 +527,7 @@ export const updateProblemInSetRequestSchema = z.object({
|
||||
isRequired: z.boolean(),
|
||||
})
|
||||
|
||||
/** 拖动排序:题单里题目的链接 id,按新顺序给全 */
|
||||
/** 拖动排序:专题里题目的链接 id,按新顺序给全 */
|
||||
export const reorderProblemSetProblemsRequestSchema = z.object({
|
||||
ids: z.array(z.number().int()).min(1),
|
||||
})
|
||||
|
||||
@@ -66,7 +66,7 @@ export const createFlowchartResponseSchema = z.object({
|
||||
status: z.literal('pending'),
|
||||
})
|
||||
/**
|
||||
* 流程图画到这两档算这道题做完:题单进度、课堂条、课堂任务、「你画的流程图」、结果页签的 ✓
|
||||
* 流程图画到这两档算这道题做完:专题进度、课堂条、课堂任务、「你画的流程图」、结果页签的 ✓
|
||||
* 都按它(设计文档 2026-09-28-problem-page-redesign 第 3 节决定 4、6)。前后端只有这一份
|
||||
*/
|
||||
export const FLOWCHART_PASS_GRADES = ['S', 'A'] as const
|
||||
@@ -75,7 +75,7 @@ export function isFlowchartPass(grade: string | null | undefined) {
|
||||
return (FLOWCHART_PASS_GRADES as readonly string[]).includes(grade ?? '')
|
||||
}
|
||||
|
||||
/** 自己在一道题上评完的历次分数,早的在前;hidden = 被题单闸门藏起来的次数 */
|
||||
/** 自己在一道题上评完的历次分数,早的在前;hidden = 被专题闸门藏起来的次数 */
|
||||
export const flowchartScoresSchema = z.object({
|
||||
scores: z.array(
|
||||
z.object({
|
||||
|
||||
@@ -472,7 +472,7 @@ export const problemListItemSchema = z.object({
|
||||
hasAstRules: z.boolean(),
|
||||
/** SQL 题(可选语言里有 SQL):写 SQL 语句查数据库,和写 C / Python 是两回事,列表里单独标出来 */
|
||||
isSql: z.boolean(),
|
||||
/** 0 = 做对了。画流程图的题,流程图评到 A / S 也给 0(和题单、课堂条一个口径) */
|
||||
/** 0 = 做对了。画流程图的题,流程图评到 A / S 也给 0(和专题、课堂条一个口径) */
|
||||
myStatus: z.number().int().nullable(),
|
||||
/**
|
||||
* 做对的人 / 交过的人,和题目页「统计」页签同一个口径(代码提交、不算还在判的)。
|
||||
|
||||
@@ -4,7 +4,7 @@ import { paginatedSchema, sampleUserSchema } from './common'
|
||||
import { maskedProblemDifficultySchema } from './problem'
|
||||
|
||||
/**
|
||||
* 我在这份题单里的进度。
|
||||
* 我在这个专题里的进度。
|
||||
*
|
||||
* 两个计数口径不同,别混用:
|
||||
* - completedCount / totalCount 只数**必做题**,进度条和「做完了」看它;
|
||||
@@ -60,9 +60,9 @@ export const problemSetSchema = z.object({
|
||||
export const problemSetListSchema = paginatedSchema(problemSetSchema)
|
||||
|
||||
/**
|
||||
* 题单页的题目行只渲染题号、标题,所以只下发这几样(外加题目主键)。
|
||||
* 专题页的题目行只渲染题号、标题,所以只下发这几样(外加题目主键)。
|
||||
* 以前复用 problemListItemSchema,服务端每次要多 join 一次 user / 标签表,
|
||||
* 而那些字段题单页一个都不渲染。
|
||||
* 而那些字段专题页一个都不渲染。
|
||||
*/
|
||||
export const problemSetProblemItemSchema = z.object({
|
||||
id: z.number().int(),
|
||||
@@ -77,11 +77,11 @@ export const problemSetProblemSchema = z.object({
|
||||
problem: problemSetProblemItemSchema,
|
||||
order: z.number().int(),
|
||||
isRequired: z.boolean(),
|
||||
/** 在这份题单里做对了没有(代码通过,或流程图拿到 A / S) */
|
||||
/** 在这个专题里做对了没有(代码通过,或流程图拿到 A / S) */
|
||||
isCompleted: z.boolean(),
|
||||
/** 在这份题单里做对的时刻 */
|
||||
/** 在这个专题里做对的时刻 */
|
||||
solvedTime: z.string().nullable(),
|
||||
/** 在这份题单里交错了几次(还没做对时显示「交过 n 次」) */
|
||||
/** 在这个专题里交错了几次(还没做对时显示「交过 n 次」) */
|
||||
wrongCount: z.number().int(),
|
||||
/**
|
||||
* 布置期内、以前做对过、旧代码正被藏着 —— 行上标「以前做对过 · 旧代码先藏着」。
|
||||
@@ -94,11 +94,11 @@ export const joinProblemSetRequestSchema = z.object({
|
||||
problemSetId: z.number().int().positive(),
|
||||
})
|
||||
|
||||
/** 老师看某个班在这份题单里的情况:真名 × 每道题 */
|
||||
/** 老师看某个班在这个专题里的情况:真名 × 每道题 */
|
||||
export const problemSetClassCellSchema = z.object({
|
||||
/** 在题单里做对的时刻 */
|
||||
/** 在专题里做对的时刻 */
|
||||
solvedTime: z.string().nullable(),
|
||||
/** 在题单里交错的次数 */
|
||||
/** 在专题里交错的次数 */
|
||||
wrongCount: z.number().int(),
|
||||
/** 加入之前就做对过这道题(任何入口) */
|
||||
solvedBefore: z.boolean(),
|
||||
@@ -116,7 +116,7 @@ export const problemSetClassStudentSchema = z.object({
|
||||
})
|
||||
|
||||
export const problemSetClassViewSchema = z.object({
|
||||
/** 加入过这份题单的学生分属哪些班:三分之一以上的人加入了的班在前(按最近一次加入),零星几个人的在后 */
|
||||
/** 加入过这个专题的学生分属哪些班:三分之一以上的人加入了的班在前(按最近一次加入),零星几个人的在后 */
|
||||
classes: z.array(z.object({ className: z.string(), joined: z.number().int(), size: z.number().int() })),
|
||||
/** 这次看的是哪个班;谁都没加入时为 null */
|
||||
className: z.string().nullable(),
|
||||
@@ -126,7 +126,7 @@ export const problemSetClassViewSchema = z.object({
|
||||
_id: z.string(),
|
||||
title: z.string(),
|
||||
isRequired: z.boolean(),
|
||||
/** 这个班在题单里做对的人数 */
|
||||
/** 这个班在专题里做对的人数 */
|
||||
solved: z.number().int(),
|
||||
}),
|
||||
),
|
||||
@@ -136,7 +136,7 @@ export const problemSetClassViewSchema = z.object({
|
||||
students: z.array(problemSetClassStudentSchema),
|
||||
})
|
||||
|
||||
/** 某道题为什么藏着旧代码:落在哪些正在布置的题单里 */
|
||||
/** 某道题为什么藏着旧代码:落在哪些正在布置的专题里 */
|
||||
export const problemSetLockSchema = z.object({
|
||||
problemSetId: z.number().int(),
|
||||
title: z.string(),
|
||||
|
||||
@@ -185,11 +185,11 @@ export const createSubmissionRequestSchema = z.object({
|
||||
.max(1024 * 1024),
|
||||
contestId: z.number().int().positive().optional(),
|
||||
/**
|
||||
* 来源题单。学生从 `/problemset/:id/problem/:pid` 那个入口提交时前端带上,
|
||||
* 后端落进 `submission.problemset_id`,提交列表据此标出「这条是刷题单刷出来的」。
|
||||
* 来源专题。学生从 `/problemset/:id/problem/:pid` 那个入口提交时前端带上,
|
||||
* 后端落进 `submission.problemset_id`,提交列表据此标出「这条是刷专题刷出来的」。
|
||||
*
|
||||
* 只是**来源标记**,不参与判题、也不参与题单进度记账 —— 进度由判完之后的
|
||||
* `recordSolvedProblem` 记进所有已加入且含这道题的题单,和从哪个入口进来无关。
|
||||
* 只是**来源标记**,不参与判题、也不参与专题进度记账 —— 进度由判完之后的
|
||||
* `recordSolvedProblem` 记进所有已加入且含这道题的专题,和从哪个入口进来无关。
|
||||
* 所以这里带错了顶多是标记不准,不会影响成绩。
|
||||
*/
|
||||
problemSetId: z.number().int().positive().optional(),
|
||||
@@ -249,10 +249,10 @@ export const submissionDetailSchema = z.object({
|
||||
problemTitle: z.string(),
|
||||
/** 提交者**现在**的班级(和提交列表同口径);已删号的为 null */
|
||||
className: z.string().nullable(),
|
||||
/** 从哪个题单交的,同列表的 problemSet */
|
||||
/** 从哪个专题交的,同列表的 problemSet */
|
||||
problemSet: z.object({ id: z.number().int(), title: z.string() }).nullable(),
|
||||
/**
|
||||
* false = 自己的这份代码在题单布置期内先藏着(见后端 problemSetLockCutoffs):code 为空串、
|
||||
* false = 自己的这份代码在专题布置期内先藏着(见后端 problemSetLockCutoffs):code 为空串、
|
||||
* statisticInfo / info 为空对象,其余照给,页面照样摆出是谁、哪道题、什么结果。
|
||||
* 别人的代码看不到时不走这里,直接 403
|
||||
*/
|
||||
@@ -262,7 +262,7 @@ export const submissionDetailSchema = z.object({
|
||||
/**
|
||||
* 同一个人在同一道题、同一场比赛(或都不在比赛里)交过的每一次,按时间先后。只有带
|
||||
* `?attempts=1` 时才给(独立的提交详情页用),否则为 null —— 题目页每判完一次都要拉一遍
|
||||
* 详情,用不着这一串。showLink 的口径同上,题单藏着的那几次点不进去
|
||||
* 详情,用不着这一串。showLink 的口径同上,专题藏着的那几次点不进去
|
||||
*/
|
||||
attempts: z
|
||||
.array(
|
||||
@@ -310,7 +310,7 @@ export const submissionListItemSchema = z.object({
|
||||
language: problemLanguageSchema,
|
||||
statisticInfo: statisticInfoSchema,
|
||||
/**
|
||||
* 来源题单,非题单入口提交的为 null。比赛提交恒为 null(比赛题不会进题单)。
|
||||
* 来源专题,非专题入口提交的为 null。比赛提交恒为 null(比赛题不会进专题)。
|
||||
* 历史提交里只有「当年首次 AC 那一条」有值 —— 迁移 0007 从 problemset_submission
|
||||
* 回填的就是这些,其余老提交无从判断入口,一律留空。
|
||||
*/
|
||||
@@ -488,7 +488,7 @@ export const submissionLessonsSchema = z.object({
|
||||
* 只认那个语言,流程图评到 A / S 也算 —— 和任务页同一个口径)。推断的课为 null
|
||||
*/
|
||||
doneCount: z.number().int().nullable(),
|
||||
/** 多半是从题单里交的 —— 「题单 7 道」 */
|
||||
/** 多半是从专题里交的 —— 「专题 7 道」 */
|
||||
fromProblemSet: z.boolean(),
|
||||
/** 这节课的题(上面 problems)交了几次 —— 和点进去看到的对得上 */
|
||||
total: z.number().int(),
|
||||
|
||||
Reference in new issue
Block a user