feat(课堂): 老师的课堂看板——布置这节课的题、看全班谁还没开始谁卡住了,布置的题直接出现在学生首页

2025 秋平均每节课有 14 个平时在用的学生一道都没交(三分之一),交了 3 次以上还没过的
平均不到 1 个;而老师原来只能一道题一道题打开统计弹窗看。

- 新表 class_lesson(迁移 0023,仅建表):一个班一天一行,存老师布置的 problem.id 与顺序;
  day 存东八区日历日文本,created_by CASCADE
- GET /classroom/board:这个班今天的题 × 全班学生(通过与否不限今天、今天交了几次、
  最后提交时间);不给班级时猜最近两小时提交人数最多的班,不记老师上次选的
- PUT /classroom/lesson:按展示题号布置,对不上的题号点名拒绝,空数组 = 清掉
- /me/class-activity 优先返回老师布置的题(source = teacher),否则照旧推断
- 前端 /classroom:没交过的名单置顶,按 没交过 → 卡住 → 在做 → 做完 排序,15 秒刷新;
  投影模式只显示每题完成人数、不出名字;用户菜单给老师加入口
- 学生首页:老师布置的标题写「今天老师布置的题」,没人交时不显示 0/0

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-27 22:37:59 +08:00
1 parent 7e964fdbdd
commit 80106eaa04
12 files changed
+4992 -69

No files matched your search

+11
View File
@@ -9,6 +9,7 @@ import {
type Metrics,
type TutorialSummary,
type ClassActivity,
type ClassBoard,
type ClassComparisonResponse,
type ClassRankItem,
type ClassUserRank,
@@ -217,6 +218,16 @@ export function getWeeklyRank(scope: "global" | "class") {
return api.get<WeeklyRank>("rankings/weekly", { params: { scope } })
}
/** 课堂看板(老师)。不给班级时后端猜最近两小时在交题的那个班 */
export function getClassBoard(className?: string) {
return api.get<ClassBoard>("classroom/board", { params: { className } })
}
/** 给这个班布置今天的题,空数组 = 清掉 */
export function setClassLesson(className: string, problemDisplayIds: string[]) {
return api.put<null>("classroom/lesson", { className, problemDisplayIds })
}
export function getClassActivity() {
return api.get<ClassActivity>("me/class-activity")
}