默认是这个班上一次布置选的语言。学生那边首页、题号下拉、题目页课堂条都写上「C语言」; 打开这节课的题时编辑器自动切过去,每道题只切一次,学生自己再换就按他的。提交列表的 「这节课」连语言一起筛。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
a18e129f4c
commit
773d15b033
7 files changed
+93
-14
No files matched your search
@@ -41,6 +41,7 @@ import {
|
||||
type FlowchartStatistics,
|
||||
type SubmissionStatistics,
|
||||
type SubmissionLessons,
|
||||
type RunnableLanguage,
|
||||
type SubmissionStatisticsGrid,
|
||||
type TodaySubmissionStatistics,
|
||||
} from "@oj2/contract"
|
||||
@@ -242,8 +243,12 @@ export function getClassLesson(className?: string) {
|
||||
}
|
||||
|
||||
/** 给这个班布置今天的题,空数组 = 清掉 */
|
||||
export function setClassLesson(className: string, problemDisplayIds: string[]) {
|
||||
return api.put<null>("classroom/lesson", { className, problemDisplayIds })
|
||||
export function setClassLesson(
|
||||
className: string,
|
||||
problemDisplayIds: string[],
|
||||
language: RunnableLanguage | null,
|
||||
) {
|
||||
return api.put<null>("classroom/lesson", { className, problemDisplayIds, language })
|
||||
}
|
||||
|
||||
/** 我的知识点地图(只有自己的,不能查别人) */
|
||||
|
||||
@@ -3,7 +3,9 @@ import { getClassBoard, setClassLesson } from "oj/api"
|
||||
import { useHiddenStudents } from "shared/composables/hiddenStudents"
|
||||
import { useCollabStore } from "shared/store/collab"
|
||||
import { useConfigStore } from "shared/store/config"
|
||||
import type { RunnableLanguage } from "@oj2/contract"
|
||||
import { errorMessage } from "utils/api"
|
||||
import { LANGUAGE_SHOW_VALUE } from "utils/constants"
|
||||
import { parseTime } from "utils/functions"
|
||||
import type { ClassBoard, ClassBoardCell, ClassBoardStudent } from "utils/types"
|
||||
|
||||
@@ -34,6 +36,16 @@ const updatedAt = ref<Date | null>(null)
|
||||
const projector = ref(false)
|
||||
|
||||
const lessonInput = ref("")
|
||||
/**
|
||||
* 这份作业用什么语言做,跟着这一次布置走(用户定的:不是给班级定死的设置)。默认是这个班
|
||||
* 上一次布置时选的;选了之后看板和学生那边的「做完」都只认这个语言交对的
|
||||
*/
|
||||
const lessonLanguage = ref<RunnableLanguage>("Python")
|
||||
const LESSON_LANGUAGES: RunnableLanguage[] = ["Python", "C", "C++"]
|
||||
const languageOptions = LESSON_LANGUAGES.map((value) => ({
|
||||
label: LANGUAGE_SHOW_VALUE[value],
|
||||
value,
|
||||
}))
|
||||
const saving = ref(false)
|
||||
|
||||
function classLabel(name: string) {
|
||||
@@ -65,7 +77,7 @@ async function load() {
|
||||
}
|
||||
}
|
||||
|
||||
// 换了班要把输入框换成那个班今天布置的题
|
||||
// 换了班要把输入框换成那个班今天布置的题、布置时选的语言(15 秒一次的刷新不动它们)
|
||||
watch(
|
||||
() => [board.value?.className, board.value?.source] as const,
|
||||
() => {
|
||||
@@ -73,6 +85,7 @@ watch(
|
||||
board.value?.source === "teacher"
|
||||
? board.value.problems.map((problem) => problem.problemDisplayId).join(" ")
|
||||
: ""
|
||||
lessonLanguage.value = board.value?.language ?? board.value?.lastLanguage ?? "Python"
|
||||
},
|
||||
)
|
||||
|
||||
@@ -86,8 +99,12 @@ async function saveLesson() {
|
||||
const ids = lessonInput.value.split(/[\s,,、;;]+/).filter(Boolean)
|
||||
saving.value = true
|
||||
try {
|
||||
await setClassLesson(className.value, ids)
|
||||
message.success(ids.length ? "已布置,学生首页会显示这几道题" : "已清掉,学生那边改回自动推断")
|
||||
await setClassLesson(className.value, ids, ids.length ? lessonLanguage.value : null)
|
||||
message.success(
|
||||
ids.length
|
||||
? `已布置(${LANGUAGE_SHOW_VALUE[lessonLanguage.value]}),学生首页会显示这几道题`
|
||||
: "已清掉,学生那边改回自动推断",
|
||||
)
|
||||
await load()
|
||||
} catch (error) {
|
||||
message.error(errorMessage(error))
|
||||
@@ -241,7 +258,12 @@ function submissionsHref(
|
||||
username: student.username,
|
||||
exactUsername: "1",
|
||||
today: "1",
|
||||
...(flowchart ? { language: "Flowchart" } : {}),
|
||||
// 布置时选了语言的,代码那边只看这个语言交的(和格子里数的一致)
|
||||
...(flowchart
|
||||
? { language: "Flowchart" }
|
||||
: board.value?.language
|
||||
? { language: board.value.language }
|
||||
: {}),
|
||||
...(problemDisplayId ? { problem: problemDisplayId } : {}),
|
||||
},
|
||||
}).href
|
||||
@@ -293,6 +315,12 @@ function submissionsHref(
|
||||
<n-card v-if="!projector" size="small" class="section">
|
||||
<n-flex align="center" :wrap="false">
|
||||
<n-text strong style="flex-shrink: 0">这节课的题</n-text>
|
||||
<n-select
|
||||
v-model:value="lessonLanguage"
|
||||
:options="languageOptions"
|
||||
aria-label="用什么语言做"
|
||||
style="width: 110px; flex-shrink: 0"
|
||||
/>
|
||||
<n-input
|
||||
v-model:value="lessonInput"
|
||||
placeholder="输入题号,用空格隔开,比如 8019 8020 8021"
|
||||
@@ -303,13 +331,15 @@ function submissionsHref(
|
||||
</n-flex>
|
||||
<n-text depth="3" class="meta">
|
||||
<template v-if="board.source === 'teacher'">
|
||||
学生首页的「班里在做」显示的就是这几道。清空再点布置就改回自动推断。
|
||||
学生首页的「班里在做」显示的就是这几道<template v-if="board.language"
|
||||
>,用 {{ LANGUAGE_SHOW_VALUE[board.language] }} 交对才算做完</template
|
||||
>。清空再点布置就改回自动推断。
|
||||
</template>
|
||||
<template v-else-if="board.source === 'inferred'">
|
||||
还没布置。下面这几道是按今天的提交记录推断的(同班 5 人以上做过的题)。
|
||||
</template>
|
||||
<template v-else>
|
||||
布置之后,学生打开首页就能看到这几道题,没听清题号的也能找到。
|
||||
布置之后,学生打开首页就能看到这几道题,没听清题号的也能找到;打开题目时编辑器默认就是左边选的语言。
|
||||
</template>
|
||||
</n-text>
|
||||
</n-card>
|
||||
|
||||
@@ -17,7 +17,7 @@ import { useBreakpoints } from "shared/composables/breakpoints"
|
||||
import { useProblemJump } from "shared/composables/problemJump"
|
||||
import { pickHeadline, type Headline } from "oj/user/knowledge"
|
||||
import { useUserStore } from "shared/store/user"
|
||||
import { ContestStatus, CONTEST_STATUS, JUDGE_STATUS } from "utils/constants"
|
||||
import { ContestStatus, CONTEST_STATUS, JUDGE_STATUS, LANGUAGE_SHOW_VALUE } from "utils/constants"
|
||||
import { duration, parseTime, zonedParts, zonedYear } from "utils/functions"
|
||||
import type {
|
||||
AnnouncementListItem,
|
||||
@@ -227,7 +227,10 @@ const classActivityTitle = computed(() => {
|
||||
const day = classActivity.value?.day
|
||||
if (!day) return ""
|
||||
// 老师在课堂看板布置的,说成「老师布置的」,比「班里在做」更让人知道该做这几道
|
||||
if (classActivity.value?.source === "teacher") return "今天老师布置的题"
|
||||
if (classActivity.value?.source === "teacher") {
|
||||
const language = classActivity.value.language
|
||||
return `今天老师布置的题${language ? ` · 用${LANGUAGE_SHOW_VALUE[language]}做` : ""}`
|
||||
}
|
||||
if (classToday.value) return "今天班里在做"
|
||||
const [, month, date] = day.split("-").map(Number)
|
||||
return `${month}月${date}日班里做了`
|
||||
|
||||
@@ -232,7 +232,10 @@ onSolvedHere(() => {
|
||||
<template>
|
||||
<!-- 课堂 -->
|
||||
<div v-if="lesson" class="context-bar lesson">
|
||||
<span class="lead lesson-lead">这节课 做完 {{ lesson.done }}/{{ lesson.total }}</span>
|
||||
<span class="lead lesson-lead"
|
||||
>这节课<template v-if="lessonStore.languageText"> · {{ lessonStore.languageText }}</template>
|
||||
做完 {{ lesson.done }}/{{ lesson.total }}</span
|
||||
>
|
||||
<!-- 手机上放不下一排题号:只说是第几道,箭头做大(设计稿「手机:题目 / 代码 / 结果」) -->
|
||||
<span v-if="isMobile" class="meta">这是第 {{ lesson.position }} 道</span>
|
||||
<ProblemChips v-else :items="lesson.chips" :current="currentId" variant="lesson" />
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useCollabHere, useTeacherCollab } from "../composables/teacherCollab"
|
||||
import { useProblemPageContext } from "../composables/problemPageContext"
|
||||
import CollabBar from "./CollabBar.vue"
|
||||
import { useFlowchartStore } from "oj/store/flowchart"
|
||||
import { useLessonStore } from "oj/store/lesson"
|
||||
|
||||
const FlowchartEditor = defineAsyncComponent(
|
||||
() => import("shared/components/FlowchartEditor/index.vue"),
|
||||
@@ -151,6 +152,30 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
/**
|
||||
* 老师在课堂看板布置这节课时选了语言:打开这节课的题,编辑器默认就用它。学 C 的班,
|
||||
* 编辑器停在默认的 Python(或者上一个用这台电脑的人留下的偏好)的话,学生交上去才发现
|
||||
* 不算数。课堂条只在题库入口出现,这里同一个范围。
|
||||
*
|
||||
* 每道题只自动换一次:学生自己再切回别的语言,就按他的来。课堂状态可能比题面晚到
|
||||
* (课堂条进页面才去拉),所以两边都等到了再判断;画着流程图时不动他。
|
||||
*/
|
||||
const lessonStore = useLessonStore()
|
||||
let lessonLanguageFor: string | null = null
|
||||
watch(
|
||||
() => [problem.value?._id, lessonStore.activity] as const,
|
||||
([id, activity]) => {
|
||||
if (!id || !activity || lessonLanguageFor === id) return
|
||||
lessonLanguageFor = id
|
||||
const language = activity.language
|
||||
if (!language || ctx.value.entry !== "problem" || teacherCollab.value) return
|
||||
if (!lessonStore.includes(id) || !problemStore.codeLanguages.includes(language)) return
|
||||
if (codeStore.code.language === language || codeStore.code.language === "Flowchart") return
|
||||
problemStore.switchLanguage(language)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
|
||||
/**
|
||||
* 画着流程图时忽然不让画了:工具栏的「写代码 / 画流程图」和语言下拉都跟着 canDraw 藏起来,
|
||||
* 编辑器要是还停在画布上,学生就回不去写代码了。拖窄到手机宽度时页面会换一套布局、编辑器
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { defineStore } from "pinia"
|
||||
import { getClassActivity } from "oj/api"
|
||||
import { LANGUAGE_SHOW_VALUE } from "utils/constants"
|
||||
import type { ClassActivity, ClassActivityProblem } from "utils/types"
|
||||
|
||||
/** 同一节课里来回换题不用每次都重拉;过了这么久再进题目页就重拉一次 */
|
||||
@@ -74,10 +75,18 @@ export const useLessonStore = defineStore("lesson", () => {
|
||||
return { total: list.length, next: rest[0] ?? null, remaining: rest.length }
|
||||
}
|
||||
|
||||
/** 老师布置的叫「老师布置的题」,推断出来的叫「这节课的题」 */
|
||||
/** 老师布置时选的语言,给界面写「C语言」;没选(推断出来的课、以前布置的)为空 */
|
||||
const languageText = computed(() => {
|
||||
const language = activity.value?.language
|
||||
return language ? LANGUAGE_SHOW_VALUE[language] : ""
|
||||
})
|
||||
|
||||
/** 老师布置的叫「老师布置的题」(选了语言带上语言),推断出来的叫「这节课的题」 */
|
||||
const label = computed(() =>
|
||||
activity.value?.source === "teacher" ? "老师布置的题" : "这节课的题",
|
||||
activity.value?.source === "teacher"
|
||||
? `老师布置的题${languageText.value ? ` · ${languageText.value}` : ""}`
|
||||
: "这节课的题",
|
||||
)
|
||||
|
||||
return { activity, label, load, markAccepted, includes, nextAfter }
|
||||
return { activity, label, languageText, load, markAccepted, includes, nextAfter }
|
||||
})
|
||||
@@ -508,6 +508,8 @@ async function toggleLesson() {
|
||||
if (lessonActive.value) {
|
||||
query.problem = ""
|
||||
query.today = "0"
|
||||
// 「这节课」顺带筛上的语言一起放掉;老师自己另选的别动
|
||||
if (lesson.value?.language && query.language === lesson.value.language) query.language = ""
|
||||
return
|
||||
}
|
||||
lessonLoading.value = true
|
||||
@@ -525,6 +527,8 @@ async function toggleLesson() {
|
||||
lesson.value = res
|
||||
query.problem = lessonIds.value
|
||||
query.today = "1"
|
||||
// 老师布置时选了语言:看板上只数这个语言交的,列表也只列它(流程图那边不动)
|
||||
if (res.language && !flowMode.value) query.language = res.language
|
||||
} finally {
|
||||
lessonLoading.value = false
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user