diff --git a/apps/web/CLAUDE.md b/apps/web/CLAUDE.md index cfb8178..31e5860 100644 --- a/apps/web/CLAUDE.md +++ b/apps/web/CLAUDE.md @@ -59,7 +59,7 @@ API 调用不按模块分:学生端全在 `oj/api.ts`、后台全在 `admin/ap Shared logic lives in `shared/`: - `store/` — Pinia stores: `user` (auth/roles), `config` (site-wide settings), `authModal` (login/signup form state), `loginSummary` (AI activity summary), `collab` (help-request queue + collab room), `achievement` (解锁弹窗队列), `myFlowchart` (题面「你画的流程图」那张 A/S 图的 mermaid 源码) -- `composables/` — `aiStream`, `pagination` (URL-synced), `websocket` (reconnect + heartbeat), `collabDoc` (Yjs binding for the collab channel), `configUpdate` (WS-pushed config sync), `useMermaid` (lazy Mermaid render), `darkTransition` (View Transitions,111 以下走降级分支), `hiddenStudents` (统计面板的「请假隐藏」), `chartTheme`, `breakpoints`, `maxkb`, `learnProgress`, `rarity` +- `composables/` — `aiStream`, `pagination` (URL-synced), `websocket` (reconnect + heartbeat), `collabDoc` (Yjs binding for the collab channel), `configUpdate` (WS-pushed config sync), `useMermaid` (lazy Mermaid render), `darkTransition` (View Transitions,111 以下走降级分支), `hiddenStudents` (课堂看板的「请假隐藏」), `chartTheme`, `breakpoints`, `maxkb`, `learnProgress`, `rarity` - `layout/` — `default.vue` and `admin.vue` layout wrappers - `api.ts` — shared API calls (auth, profile, tags, captcha) diff --git a/apps/web/src/admin/contest/helper.vue b/apps/web/src/admin/contest/helper.vue index 7fa9fd8..cfce653 100644 --- a/apps/web/src/admin/contest/helper.vue +++ b/apps/web/src/admin/contest/helper.vue @@ -282,7 +282,6 @@ onMounted(loadData) (`submissions/${encodeURIComponent(id)}/rejudge`) } -/** - * 统计面板展开一行时拉这个人的明细。username 这里要**精确**到人, - * 和上面那个按班级模糊匹配的不是一回事。 - */ -export function getSubmissionStatisticsItems( - duration: { start?: string; end: string }, - username: string, - problemDisplayId?: string, -) { - return api.get("submissions/statistics/items", { - params: { ...duration, problemDisplayId, username }, - }) -} - export function getSubmissionStatistics( duration: { start?: string; end: string }, problemDisplayId?: string, username?: string, + /** 班级(user.class_name)精确匹配。别再拼 `ks231` 塞进 username —— 会连带 2311、2312 班 */ + className?: string, ) { return api.get("submissions/statistics", { - params: { ...duration, problemDisplayId, username }, + params: { ...duration, problemDisplayId, username, className }, }) } @@ -203,9 +190,10 @@ export function getSubmissionStatisticsGrid( duration: { start?: string; end: string }, problemDisplayId?: string, username?: string, + className?: string, ) { return api.get("submissions/statistics/grid", { - params: { ...duration, problemDisplayId, username }, + params: { ...duration, problemDisplayId, username, className }, }) } @@ -430,6 +418,8 @@ export function getFlowchartSubmission(id: string) { export function getFlowchartSubmissions(params: { username?: string + /** "1" = username 整名匹配,同代码提交列表 */ + exactUsername?: "1" className?: string problemDisplayId?: string myself?: string @@ -445,9 +435,10 @@ export function getFlowchartStatistics( duration: { start?: string; end: string }, problemDisplayId?: string, username?: string, + className?: string, ) { return api.get("flowcharts/statistics", { - params: { ...duration, problemDisplayId, username }, + params: { ...duration, problemDisplayId, username, className }, }) } diff --git a/apps/web/src/oj/classroom/board.vue b/apps/web/src/oj/classroom/board.vue index de2b1e5..7767c7a 100644 --- a/apps/web/src/oj/classroom/board.vue +++ b/apps/web/src/oj/classroom/board.vue @@ -142,12 +142,19 @@ function nameOf(student: ClassBoardStudent) { * 请假隐藏(原来在「数据统计」弹框里,统计改成回头看之后挪到这儿 —— 盯这节课的是看板)。 * 请假、转班、学号错了的那几个一直挂在「还没交过」里,会盖住真正要去看的人。 * 藏两个小时(够一节课),下节课自动回来;只记在这台电脑上,换人换机器都不继承。 - * 键沿用统计弹框那份,老师上午藏的人这里接着藏着 + * 键沿用统计弹框那份,老师上午藏的人这里接着藏着。 + * + * **只藏「还没交过」的人**:一个学生只要今天交过、或者正在举手,就不算请假,照常显示、 + * 照常算进人数。迟到的学生后来交了题、卡住了、举手了,老师得看得见 */ -const { hideMode, hideStudent, showAll, isHidden } = useHiddenStudents("oj_hidden_students") -const hiddenStudents = computed(() => - (board.value?.students ?? []).filter((student) => isHidden(student.username)), -) +const { hideMode, hideStudent, unhide, isHidden } = useHiddenStudents("oj_hidden_students") +function hiddenNow(student: ClassBoardStudent) { + return !student.lastSubmitAt && !helpOf(student) && isHidden(student.username) +} +const hiddenStudents = computed(() => (board.value?.students ?? []).filter(hiddenNow)) +function restoreHidden() { + unhide(hiddenStudents.value.map((student) => student.username)) +} const students = computed(() => [...(board.value?.students ?? [])] @@ -328,7 +335,7 @@ function submissionsHref(student: ClassBoardStudent, problemDisplayId?: string) @@ -341,7 +348,7 @@ function submissionsHref(student: ClassBoardStudent, problemDisplayId?: string) size="tiny" text type="primary" - @click="showAll" + @click="restoreHidden" > 隐藏了 {{ hiddenStudents.length }} 位:{{ hiddenStudents.map(nameOf).join("、") }} · 恢复 diff --git a/apps/web/src/oj/statistics/components/AttemptSquares.vue b/apps/web/src/oj/statistics/components/AttemptSquares.vue index c79fabb..8533c25 100644 --- a/apps/web/src/oj/statistics/components/AttemptSquares.vue +++ b/apps/web/src/oj/statistics/components/AttemptSquares.vue @@ -9,6 +9,7 @@ const codeCache = new Map()