diff --git a/apps/web/src/oj/classroom/board.vue b/apps/web/src/oj/classroom/board.vue index d259495..999174c 100644 --- a/apps/web/src/oj/classroom/board.vue +++ b/apps/web/src/oj/classroom/board.vue @@ -16,12 +16,14 @@ import type { ClassBoard, ClassBoardCell, ClassBoardProblem, ClassBoardStudent } import ExplainModal, { type ExplainPerson } from "./components/ExplainModal.vue" import LeaveModal from "./components/LeaveModal.vue" import LessonForm from "./components/LessonForm.vue" +import TrailPanel from "./components/TrailPanel.vue" import { errorKind, type ErrorKind } from "utils/errorKind" import { cellStyle as cellStyleOf, cellText, cellTitle as cellTitleOf, STUCK_ATTEMPTS, + trailSummary, } from "./boardCells" /** @@ -378,6 +380,22 @@ const cellStyle = (cell: ClassBoardCell) => cellStyleOf(cell, board.value?.day, const cellTitle = (cell: ClassBoardCell, student: ClassBoardStudent) => cellTitleOf(cell, student, board.value?.day) +/** + * 点开着轨迹的那个格子(学生 id:第几道题)。做对了、今天交过代码的格子点了不再直接去提交列表, + * 先在格子下面看他是怎么一次次做对的,列表在弹出来的那块里 + */ +const trailKey = ref(null) + +function toggleTrail(key: string) { + trailKey.value = trailKey.value === key ? null : key +} + +/** 点到别的格子时,那边自己会换过去;这里只管点到空白处收起 */ +function trailOutside(event: MouseEvent) { + if ((event.target as Element | null)?.closest(".cell")) return + trailKey.value = null +} + /** * 点格子 / 名字到提交列表看他今天交的。新标签打开:看板一般开着不关,别把它顶掉。 * 用户名按整名匹配(学号互相包含是常态,ks24a1 会混进 ks24a10)。 @@ -520,10 +538,19 @@ function lastText(student: ClassBoardStudent) {
- + {{ board.problems[selectedIndex]!.problemDisplayId }} {{ board.problems[selectedIndex]!.title }} - + 错着的 {{ problemStats[selectedIndex]!.wrong }} 人 @@ -688,6 +715,35 @@ function lastText(student: ClassBoardStudent) { > {{ cellText(cell) }} + + + + 1 ? `✓ ${cell.acceptedTry}` : "✓" if (cell.status === "tried") return cell.attempts ? `✗ ${cell.attempts}` : "✗" return "" } @@ -62,3 +63,13 @@ export function cellTitle( } return "" } + +/** 点开做对的格子,方块串旁边那句 */ +export function trailSummary(cell: ClassBoardCell, day: string | undefined) { + const total = cell.trail.length + if (cell.acceptedTry === 1) return total === 1 ? "一次就做对" : `交了 ${total} 次,第 1 次就做对` + if (cell.acceptedTry) return `交了 ${total} 次,第 ${cell.acceptedTry} 次做对` + return acceptedToday(cell, day) + ? `今天交了 ${total} 次代码` + : `以前就做对了,今天又交了 ${total} 次` +} diff --git a/apps/web/src/oj/classroom/components/TrailPanel.vue b/apps/web/src/oj/classroom/components/TrailPanel.vue new file mode 100644 index 0000000..47df5d8 --- /dev/null +++ b/apps/web/src/oj/classroom/components/TrailPanel.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/apps/web/src/oj/statistics/attempts.ts b/apps/web/src/oj/statistics/attempts.ts new file mode 100644 index 0000000..709f0e2 --- /dev/null +++ b/apps/web/src/oj/statistics/attempts.ts @@ -0,0 +1,40 @@ +import { getSubmission } from "oj/api" +import { SubmissionStatus } from "utils/constants" +import type { Submission } from "utils/types" +import type { Tone } from "shared/composables/tone" + +/** + * 一次提交一格的那串方块(统计页的 AttemptSquares、课堂看板做对格子的轨迹)共用的两样: + * 方块的颜色,和停上去看代码时拉的提交。 + */ + +/** 对了绿;编译失败、运行时错误、语法规则没过、部分通过橙;判题中蓝;其余红 */ +export function attemptTone(result: number): Tone { + if (result === SubmissionStatus.accepted) return "success" + if ( + result === SubmissionStatus.compile_error || + result === SubmissionStatus.runtime_error || + result === SubmissionStatus.ast_check_failed || + result === SubmissionStatus.partial_accepted + ) { + return "warning" + } + if (result === SubmissionStatus.pending || result === SubmissionStatus.judging) return "info" + return "error" +} + +/** + * 代码按提交 id 缓存,整页共用:交了就不会再变,老师在一排方块之间来回对比时 + * 不用每次都等网络。失败的不进缓存,下次停上去再试。 + */ +const codeCache = new Map>() + +export function cachedSubmission(id: string) { + let hit = codeCache.get(id) + if (!hit) { + hit = getSubmission(id) + hit.catch(() => codeCache.delete(id)) + codeCache.set(id, hit) + } + return hit +} diff --git a/apps/web/src/oj/statistics/components/AttemptSquares.vue b/apps/web/src/oj/statistics/components/AttemptSquares.vue index b8c20e8..2fcb14d 100644 --- a/apps/web/src/oj/statistics/components/AttemptSquares.vue +++ b/apps/web/src/oj/statistics/components/AttemptSquares.vue @@ -1,20 +1,10 @@ - -