feat(提交列表): 重做成左边列表、右边代码,方向键一条条翻,不再开弹框

- 右栏常驻选中那条的代码:编译失败 / 运行时错误用中文说清第几行错了并标红,
  老师看得到逐个测试点,学生看别人的只显示结果
- 老师一键「这节课」:筛到正在上课的班、这节课的题、今天
- 「正在评分」的行自己变成结果;新交的不插队,顶上提示「有 N 条新提交」
- 按天分组、默认每页 30 条;状态筛选补全,语言补上 SQL;流程图的评分详情也放进右栏
- 课堂看板的格子和名字能直接点进这个学生今天的提交

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-29 11:08:49 +08:00
1 parent ea480d5e0c
commit 660f689a5c
14 files changed
+2845 -673

No files matched your search

+5 -48
View File
@@ -8,13 +8,11 @@ import {
submissionMemoryFormat,
submissionResultTitle,
submissionTimeFormat,
compressToBase64,
} from "utils/functions"
import type { Submission } from "utils/types"
import SubmissionResultTag from "shared/components/SubmissionResultTag.vue"
import { useBreakpoints } from "shared/composables/breakpoints"
import { useCodeStore } from "oj/store/code"
import storage from "utils/storage"
import { useCopySubmission } from "./composables/copySubmission"
const props = defineProps<{
submissionID: string
@@ -26,10 +24,6 @@ const props = defineProps<{
// 在弹框中使用时,父组件监听此事件关闭弹框,否则弹框会挡住已更新的编辑器
const emit = defineEmits<{ copied: [] }>()
const route = useRoute()
const router = useRouter()
const codeStore = useCodeStore()
const { isMobile, isDesktop } = useBreakpoints()
const submission = ref<Submission>()
@@ -69,51 +63,14 @@ const columns: DataTableColumn<JudgeCaseResult>[] = [
},
]
const { copyToCat: catCopy, copyToProblem: problemCopy } = useCopySubmission()
function copyToCat() {
const lang = LANGUAGE_FORMAT_VALUE[submission.value!.language]
const data = {
lang,
code: submission.value!.code,
input: "",
}
const base64 = compressToBase64(JSON.stringify(data))
const url = `${import.meta.env.PUBLIC_CODE_URL}?share=${encodeURIComponent(base64)}`
window.open(url, "_blank")
catCopy(submission.value!)
}
function copyToProblem() {
const { code, language, contestId } = submission.value!
// 编辑器的 storageKey 用 display id(problem._id),不是 submission.problemId
// (内部数字 id)。**不能只靠 props.problemID** —— 独立的 /submission/:id 路由
// 只喂 submissionID,那个 prop 是 undefined,原来会一路带进 router.push 抛
// `Missing required param "problemID"`。响应里的 problemDisplayId 就是干这个的。
const problemID = props.problemID ?? submission.value!.problemDisplayId
const contestIDForKey = contestId || null
const storageKey = `problem_${problemID}_contest_${contestIDForKey}_lang_${language}`
storage.set(storageKey, code)
// 设置语言 + 代码:localStorage 覆盖全新挂载的编辑器,
// setCode 覆盖已挂载(同页 modal)的编辑器
codeStore.setLanguage(language)
codeStore.setCode(code)
const problemSetId = (route.params.problemSetId as string) ?? ""
if (contestId) {
router.push({
name: "contest problem",
params: { contestID: String(contestId), problemID },
})
} else if (problemSetId) {
router.push({
name: "problemset problem",
params: { problemSetId, problemID },
})
} else {
router.push({
name: "problem",
params: { problemID },
})
}
problemCopy(submission.value!)
emit("copied")
}