From 0bcc981e6fb91846ce5de6946a23117ac1838997 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Tue, 29 Sep 2026 18:52:58 +0800 Subject: [PATCH] =?UTF-8?q?fix(=E6=8F=90=E4=BA=A4=E5=88=97=E8=A1=A8/?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1):=20=E6=8C=89=E6=96=B9=E5=90=91=E9=94=AE?= =?UTF-8?q?=E4=BC=9A=E9=A1=BA=E6=89=8B=E5=88=87=E6=8E=89=E3=80=8C=E4=BB=A3?= =?UTF-8?q?=E7=A0=81/=E6=B5=81=E7=A8=8B=E5=9B=BE=E3=80=8D=E3=80=81?= =?UTF-8?q?=E9=87=8D=E5=88=A4=E5=90=8E=E5=8F=B3=E6=A0=8F=E8=BF=98=E6=98=AF?= =?UTF-8?q?=E6=97=A7=E5=86=85=E5=AE=B9=E3=80=81=E6=B2=A1=E4=BA=BA=E4=BA=A4?= =?UTF-8?q?=E6=97=B6=E7=BB=9F=E8=AE=A1=E8=AF=B4=E3=80=8C=E5=85=A8=E9=83=BD?= =?UTF-8?q?=E5=81=9A=E5=AE=8C=E4=BA=86=E3=80=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 提交列表: - 焦点在单选框、下拉框上时方向键不再一边切控件一边换条;跨页没回来前不再连跳一整页 - 重判、重新评分之后右栏重新拉,不再命中旧缓存;同一条新旧请求不再互相覆盖 - 从「我的提交」点顶栏「提交」、浏览器后退时,地址里没有的筛选回到默认 - 找回点用户名开个人主页;「只看他 / 只看这题」学生也能用;重判不用等代码拉下来 - 手机上老师也能重判、能按语言筛,流程图行有手机排版;学生界面带着的班级筛选显示成能点掉的标签 - mermaid 画不出来时先说中文、原始报错折起来 统计页: - 没人交时说「这段时间没有人交」,不再说「全都做完了」;没填题号时各处统一叫「做对过题」 - 班级按 class_name 单独传;查询失败清掉旧数据并说清原因;标签跟着查出来的那一份走 - 「语法未过」的格子单独标「语」;正确率不算还在判的;截断提示说清哪些数字受影响 - 看板的请假隐藏只藏还没交过、没在举手的人,「恢复」只恢复这个班的 - 手机上筛选折行、上下排,不再挤出屏幕 Co-Authored-By: Claude Opus 5.5 --- apps/web/CLAUDE.md | 2 +- apps/web/src/admin/contest/helper.vue | 1 - apps/web/src/oj/api.ts | 27 +-- apps/web/src/oj/classroom/board.vue | 21 +- .../statistics/components/AttemptSquares.vue | 5 +- .../src/oj/statistics/components/ByClass.vue | 39 +++- .../oj/statistics/components/CodeStats.vue | 183 +++++++++++++++--- .../oj/statistics/components/FlowStats.vue | 52 ++++- apps/web/src/oj/statistics/index.vue | 136 +++++++++---- apps/web/src/oj/statistics/period.ts | 8 +- .../submission/components/FlowchartPane.vue | 82 ++++++-- .../submission/components/SubmissionPane.vue | 57 ++++-- apps/web/src/oj/submission/detail.vue | 1 - apps/web/src/oj/submission/list.vue | 161 ++++++++++++--- .../src/shared/composables/hiddenStudents.ts | 35 ++-- 15 files changed, 613 insertions(+), 197 deletions(-) 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()