feat(题目): 左栏顶上标出「这节课做完几道」、题单进度或比赛倒计时,统计 / 点评 / 我的提交收进抽屉
- 上下文条(按入口三选一):课堂 = 「这节课 做完 3/5」+ 每道题号 + 上一题 / 下一题; 题单 = 题单名 + 进度 +「第 N 题」+ 上一题 / 下一题;比赛 = 比赛名 + 每道题号 +「还剩 38:12」+ 排名。 题号只放号码,状态用 ✓ / ! 字符区分,不只靠颜色;多于 5 道横向滚动,当前题保持可见。 通过之后当场 +1,不用刷新 - 左栏只剩「题目 / 结果」两个页签;统计 / 点评 / 我的提交变成页签行右侧的按钮,点开是抽屉, 只盖题面、编辑器不动,交完判出结果时自动收起。手机上收进页签行的「⋯」 - 流程图并进「题目」页签:参考流程图默认折叠;自己画到 A/S 的那张缩略显示、可放大, 一进题就能看到(原来要先切到「流程图」这门「语言」),也不再强行切页签 - 「本题已经被你解决啦」两条整宽提示改成标题下的「✓ 已解决 / ! 尝试过」标签; 时间内存限制只写「限时 1 秒」 - 入口差异收成一张表(problemPageContext):题单里不给抽屉、状态标签、相似题; 比赛里没有点评和求助。工具栏的「本题提交」挪到「我的提交」抽屉底部 - 顺手修:没有例子的题点「去自测猫」会抛错;「我的提交」没交过时一片空白 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
45505e8384
commit
116b0a2c95
16 files changed
+1057
-251
No files matched your search
@@ -19,6 +19,7 @@ import type { LANGUAGE } from "utils/types"
|
||||
import { Icon } from "@iconify/vue"
|
||||
import { NFlex } from "naive-ui"
|
||||
import SubmitCode from "./SubmitCode.vue"
|
||||
import { useProblemPageContext } from "../composables/problemPageContext"
|
||||
|
||||
const SubmitFlowchart = defineAsyncComponent(() => import("./SubmitFlowchart.vue"))
|
||||
// 只有老师看得见(下面的弹框挂了 isTeacherOrAbove),静态 import 的话每个学生
|
||||
@@ -38,8 +39,8 @@ const emit = defineEmits<{
|
||||
}>()
|
||||
|
||||
const message = useMessage()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const ctx = useProblemPageContext()
|
||||
const userStore = useUserStore()
|
||||
const codeStore = useCodeStore()
|
||||
const problemStore = useProblemStore()
|
||||
@@ -63,8 +64,6 @@ const canRunSamples = computed(
|
||||
codeStore.code.language !== "SQL",
|
||||
)
|
||||
|
||||
// 计算属性
|
||||
const isContestMode = computed(() => route.name === "contest problem")
|
||||
const buttonSize = computed(() => (isDesktop.value ? "medium" : "small"))
|
||||
// 可见条件沿用原来的 showSyncFeature,再加上「不是教师」——
|
||||
// 教师端的入口在顶栏,不在题目页
|
||||
@@ -76,7 +75,7 @@ const showHelpButton = computed(
|
||||
// 演示模式下协作通道是断开的(见 App.vue),按钮点了也没人收
|
||||
!userStore.demoMode &&
|
||||
codeStore.code.language !== "Flowchart" &&
|
||||
!isContestMode.value,
|
||||
ctx.value.help,
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -124,29 +123,14 @@ const toggleHelp = () => {
|
||||
collabStore.requestHelp(problem.value!._id, codeStore.code.language)
|
||||
}
|
||||
|
||||
const showGoSubmissionButton = computed(() => {
|
||||
if (isContestMode.value) return true
|
||||
else if (userStore.isAdminRole) return true
|
||||
else if (userStore.showSubmissions) return true
|
||||
else return false
|
||||
})
|
||||
|
||||
const menuOptions = computed<DropdownOption[]>(() => {
|
||||
const options: DropdownOption[] = []
|
||||
// 移动端额外收纳桌面端常驻的两项
|
||||
if (!isDesktop.value) {
|
||||
if (showGoSubmissionButton.value) {
|
||||
options.push({
|
||||
label: "本题提交",
|
||||
key: "submissions",
|
||||
})
|
||||
}
|
||||
if (userStore.isTeacherOrAbove) {
|
||||
options.push({
|
||||
label: "课堂统计",
|
||||
key: "statistics",
|
||||
})
|
||||
}
|
||||
// 移动端额外收纳桌面端常驻的「课堂统计」。「本题提交」挪到了「我的提交」抽屉的底部
|
||||
if (!isDesktop.value && userStore.isTeacherOrAbove) {
|
||||
options.push({
|
||||
label: "课堂统计",
|
||||
key: "statistics",
|
||||
})
|
||||
}
|
||||
if (codeStore.code.language !== "Flowchart") {
|
||||
if (codeStore.code.language !== "SQL") {
|
||||
@@ -179,9 +163,6 @@ const menuOptions = computed<DropdownOption[]>(() => {
|
||||
|
||||
const handleMenuSelect = (key: string) => {
|
||||
switch (key) {
|
||||
case "submissions":
|
||||
goSubmissions()
|
||||
break
|
||||
case "statistics":
|
||||
statisticPanel.value = true
|
||||
break
|
||||
@@ -238,26 +219,14 @@ const goTestCat = () => {
|
||||
const data = {
|
||||
lang,
|
||||
code: codeStore.code.value,
|
||||
input: problemStore.problem?.samples[0].input,
|
||||
// 没有例子的题原来在这里抛 TypeError,点了没反应
|
||||
input: problemStore.problem?.samples[0]?.input ?? "",
|
||||
}
|
||||
const base64 = compressToBase64(JSON.stringify(data))
|
||||
const url = `${import.meta.env.PUBLIC_CODE_URL}?share=${encodeURIComponent(base64)}`
|
||||
window.open(url, "_blank")
|
||||
}
|
||||
|
||||
const goSubmissions = () => {
|
||||
const name = route.params.contestID ? "contest submissions" : "submissions"
|
||||
const target = { name, query: { problem: problem.value!._id } }
|
||||
// 协作中走新标签:教师端「页面即协作现场」,跳走这一页协作就结束了
|
||||
// (求助会退回排队,但老师还得再接一次)。而「看看这学生都交了什么」恰好是
|
||||
// 协作时最常点的一个按钮 —— 这是整条工具栏上唯一会跳路由的按钮
|
||||
if (showCollabBar.value) {
|
||||
window.open(router.resolve(target).href, "_blank")
|
||||
return
|
||||
}
|
||||
router.push(target)
|
||||
}
|
||||
|
||||
const goEdit = () => {
|
||||
const url = problem.value!.contestId
|
||||
? `/admin/contest/${problem.value!.contestId}/problem/edit/${problem.value!.id}`
|
||||
@@ -294,10 +263,6 @@ const goEdit = () => {
|
||||
|
||||
<SubmitCode v-else />
|
||||
|
||||
<n-button v-if="isDesktop && showGoSubmissionButton" :size="buttonSize" @click="goSubmissions">
|
||||
本题提交
|
||||
</n-button>
|
||||
|
||||
<n-button
|
||||
v-if="isDesktop && userStore.isTeacherOrAbove"
|
||||
:size="buttonSize"
|
||||
@@ -306,7 +271,7 @@ const goEdit = () => {
|
||||
课堂统计
|
||||
</n-button>
|
||||
|
||||
<!-- 自测猫 / 复制代码 / 重置代码 / 编辑题目 收进下拉菜单;移动端再加上本题提交 / 课堂统计 -->
|
||||
<!-- 自测猫 / 复制代码 / 重置代码 / 编辑题目 收进下拉菜单;移动端再加上课堂统计 -->
|
||||
<n-dropdown
|
||||
v-if="menuOptions.length"
|
||||
trigger="click"
|
||||
|
||||
Reference in new issue
Block a user