feat(自学情况): 看得到配套题做没做——每人一列、每课一个页签、学生明细里逐题列出
Deploy / deploy (push) Canceled after 0s

- 方块格多一列「配套题」:他打开过的那些课挂的题,做对几道 / 一共几道;格子提示里也带上
- 右栏分「练一练 / 配套题」两个页签:每道题读过这课的人里几人做对,点开看谁没交、谁交了没对,
  一键跳到这个人这道题的提交
- 学生明细每课多一段配套题:做对没有、交了几次、最后哪天交的
- 做对不论早晚,读教程之前在课上做对的也算;口径同学生端课文里那个勾(代码 AC 或流程图 A / S)
- 1366 宽下 C 语言 20 课也不用横着滑了:「最后学习」只留日期,几列收窄

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-10-16 12:21:34 +08:00
1 parent 7839a65f59
commit 1ebb23cdac
5 files changed
+474 -33

No files matched your search

+29
View File
@@ -639,6 +639,18 @@ export const gradeTrendProblemSchema = z.object({
// ---------------------------------------------------------------- 自学情况
/**
* 一个学生在一道配套题上的状态。「做对」不论早晚 —— 读这课之前在课上就做对的也算,
* 口径同学生端课文里的勾:代码 AC(含 AST_CHECK_FAILED)或流程图评到 A / S
*/
const learnProblemStateSchema = z.object({
problemId: z.number().int(),
solved: z.boolean(),
/** 代码和流程图一共交了几次,比赛提交不算 */
submissions: z.number().int(),
lastSubmitAt: z.string(),
})
/**
* 「自学情况」的方块格:一个班的学生 × 这门课的每一课。
*
@@ -666,6 +678,8 @@ export const learnBoardStudentSchema = z.object({
wrongAttempts: z.number().int(),
}),
),
/** 交过的配套题(一次没交的不在里面),哪一课的题由 `tutorials[].problems` 对 */
problems: z.array(learnProblemStateSchema),
totalSeconds: z.number().int(),
lastViewedAt: z.string().nullable(),
})
@@ -679,6 +693,10 @@ export const learnBoardSchema = z.object({
title: z.string(),
project: z.string(),
exerciseTotal: z.number().int(),
/** 这课的配套题,按老师排的顺序;藏起来的题不算 */
problems: z.array(
z.object({ id: z.number().int(), displayId: z.string(), title: z.string() }),
),
}),
),
students: z.array(learnBoardStudentSchema),
@@ -757,6 +775,17 @@ export const learnStudentDetailSchema = z.object({
lastAttemptAt: z.string().nullable(),
}),
),
/** 配套题,没交过的 `submissions` 为 0、`lastSubmitAt` 为空 */
problems: z.array(
z.object({
id: z.number().int(),
displayId: z.string(),
title: z.string(),
solved: z.boolean(),
submissions: z.number().int(),
lastSubmitAt: z.string().nullable(),
}),
),
}),
),
})