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
@@ -0,0 +1,120 @@
|
||||
<script setup lang="ts">
|
||||
import { storeToRefs } from "pinia"
|
||||
import { useProblemStore } from "oj/store/problem"
|
||||
import { useCollabStore } from "shared/store/collab"
|
||||
import { useUserStore } from "shared/store/user"
|
||||
import {
|
||||
DRAWER_TITLE,
|
||||
useProblemPageContext,
|
||||
type ProblemDrawer,
|
||||
} from "../composables/problemPageContext"
|
||||
|
||||
/**
|
||||
* 统计 / 点评 / 我的提交。原来是左栏的三个页签,课上几乎没人点,却和「题目」挤在一排;
|
||||
* 现在收进抽屉,盖住左栏、编辑器不动。
|
||||
*
|
||||
* 抽屉里的内容关上就卸载:再打开时「我的提交」要重新拉,刚交的那次才看得见。
|
||||
*/
|
||||
const ProblemInfo = defineAsyncComponent(() => import("./ProblemInfo.vue"))
|
||||
const ProblemReaction = defineAsyncComponent(() => import("./ProblemReaction.vue"))
|
||||
const ProblemSubmission = defineAsyncComponent(() => import("./ProblemSubmission.vue"))
|
||||
|
||||
const open = defineModel<ProblemDrawer | null>({ required: true })
|
||||
|
||||
const props = defineProps<{
|
||||
/** 桌面:挂进左栏(它得是 position: relative);手机:不传,从底下拉起来盖住整屏 */
|
||||
to?: string
|
||||
}>()
|
||||
|
||||
const ctx = useProblemPageContext()
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const collabStore = useCollabStore()
|
||||
const { problem } = storeToRefs(useProblemStore())
|
||||
|
||||
const show = computed({
|
||||
get: () => open.value !== null,
|
||||
set: (value) => {
|
||||
if (!value) open.value = null
|
||||
},
|
||||
})
|
||||
|
||||
// 内容和标题都按最后一次打开的来:关的时候有一段滑出去的动画,那时 open 已经是 null 了。
|
||||
// 关完 n-drawer 自己把内容卸掉
|
||||
const lastOpened = ref<ProblemDrawer>("info")
|
||||
watch(open, (key) => {
|
||||
if (key) lastOpened.value = key
|
||||
})
|
||||
|
||||
// 换题就关:抽屉里是上一道题的统计和提交
|
||||
watch(
|
||||
() => problem.value?._id,
|
||||
() => {
|
||||
open.value = null
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* 「看这道题所有人的提交」,原来是工具栏上的「本题提交」。可见条件照旧:
|
||||
* 比赛里总给(看的是这场比赛的提交),题库里要管理员或者开着提交列表。
|
||||
*/
|
||||
const showAllSubmissions = computed(
|
||||
() => ctx.value.entry === "contest" || userStore.isAdminRole || userStore.showSubmissions,
|
||||
)
|
||||
|
||||
function goAllSubmissions() {
|
||||
const target = {
|
||||
name: ctx.value.entry === "contest" ? "contest submissions" : "submissions",
|
||||
params: ctx.value.entry === "contest" ? { contestID: route.params.contestID } : {},
|
||||
query: { problem: problem.value!._id },
|
||||
}
|
||||
// 协作中走新标签:教师端「页面即协作现场」,跳走这一页协作就结束了
|
||||
// (求助会退回排队,但老师还得再接一次)。而「看看这学生都交了什么」恰好是
|
||||
// 协作时最常点的一个
|
||||
const collabHere =
|
||||
collabStore.room !== null &&
|
||||
collabStore.room.problemId === problem.value?._id &&
|
||||
userStore.isTeacherOrAbove
|
||||
if (collabHere) {
|
||||
window.open(router.resolve(target).href, "_blank")
|
||||
return
|
||||
}
|
||||
router.push(target)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-drawer
|
||||
v-model:show="show"
|
||||
:to="props.to"
|
||||
:placement="props.to ? 'left' : 'bottom'"
|
||||
:width="props.to ? '100%' : undefined"
|
||||
:height="props.to ? undefined : '85%'"
|
||||
:trap-focus="false"
|
||||
:block-scroll="!props.to"
|
||||
>
|
||||
<n-drawer-content :title="DRAWER_TITLE[lastOpened]" closable :native-scrollbar="false">
|
||||
<ProblemInfo v-if="lastOpened === 'info'" />
|
||||
<ProblemReaction v-else-if="lastOpened === 'reaction'" />
|
||||
<template v-else>
|
||||
<ProblemSubmission />
|
||||
<n-button
|
||||
v-if="showAllSubmissions"
|
||||
class="all-submissions"
|
||||
text
|
||||
type="primary"
|
||||
@click="goAllSubmissions"
|
||||
>
|
||||
看这道题所有人的提交 ›
|
||||
</n-button>
|
||||
</template>
|
||||
</n-drawer-content>
|
||||
</n-drawer>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.all-submissions {
|
||||
margin-top: 12px;
|
||||
}
|
||||
</style>
|
||||
Reference in new issue
Block a user