教师端的协作编辑器只有高亮和括号匹配,没装 autocompletion —— 老师替学生 写代码时没有下拉补全,只能盲敲。而且语言写死 cpp(),学生写 Python 时老师 看到的是 C 的高亮。 - 求助协议带上语言:help_request 记到 HelpRequest,accept 时写进 Room, room_open 发给两端;认不出的语言一律当 C(老客户端不带这个字段,而它 以前就是写死 C 的) - 新增 help_language / room_language:学生在排队或协作期间切语言,只更新 语言,不动队列位置和房间;已开房就把新语言推给老师,弹框的高亮和补全 实时跟着换 - CollabModal 装上 autocompletion,和学生端用同一套 enhanceCompletion + completeAnyWord;语言→高亮扩展的映射抽到 shared/extensions/language.ts 两端共用,免得再分叉 - 学生端求助按钮合并状态提示:原来按钮旁边还挂一个 n-tag,一行工具栏在 1280 的机房屏上放不下,改成状态全进 label(已求助 · 待接入 / 已求助 · 前面 N 人 / xxx 老师帮你中) 扩展数组变了 vue-codemirror 会整体 reconfigure,但 CM6 对已存在的 compartment 取 `compartments.get() || ext.inner`,collabDoc 那个装 yCollab 的 compartment 内容会被沿用,切语言、切主题都不会把协作弄断 —— 实跑验证过 双向同步、补全下拉、协作中切语言三条路径。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015APGLsyaCUa7XFMYAaCho4
This commit is contained in:
@@ -1,12 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { cpp } from "@codemirror/lang-cpp"
|
||||
import { bracketMatching } from "@codemirror/language"
|
||||
import { closeBrackets } from "@codemirror/autocomplete"
|
||||
import {
|
||||
autocompletion,
|
||||
closeBrackets,
|
||||
completeAnyWord,
|
||||
} from "@codemirror/autocomplete"
|
||||
import type { EditorView } from "@codemirror/view"
|
||||
import { Codemirror } from "vue-codemirror"
|
||||
import type { LANGUAGE } from "utils/types"
|
||||
import { oneDark } from "../themes/oneDark"
|
||||
import { smoothy } from "../themes/smoothy"
|
||||
import { styleTheme } from "shared/extensions/baseTheme"
|
||||
import { enhanceCompletion } from "shared/extensions/autocompletion"
|
||||
import { languageExtension } from "shared/extensions/language"
|
||||
import { useCollabDoc } from "../composables/collabDoc"
|
||||
import { useCollabStore } from "shared/store/collab"
|
||||
|
||||
@@ -26,12 +32,25 @@ const show = computed({
|
||||
},
|
||||
})
|
||||
|
||||
/**
|
||||
* 语言跟着学生走:room_open 带过来,学生协作期间切语言会再来一条 room_language。
|
||||
* 取不到时按 C —— 和这里原来写死 cpp() 的表现一致。
|
||||
*/
|
||||
const language = computed<LANGUAGE>(() => collabStore.room?.language ?? "C")
|
||||
|
||||
const extensions = computed(() => [
|
||||
styleTheme,
|
||||
cpp(),
|
||||
languageExtension(language.value),
|
||||
bracketMatching(),
|
||||
closeBrackets(),
|
||||
isDark.value ? oneDark : smoothy,
|
||||
// 学生端有的补全这里必须也有:老师是在替学生写代码,缺了下拉菜单只能盲敲。
|
||||
// 数组一变 vue-codemirror 会整体 reconfigure,但 collabDoc 那个 compartment
|
||||
// 的内容会被 CM6 沿用(@codemirror/state 的 flatten 里 `compartments.get() ||
|
||||
// ext.inner`),所以切语言、切主题都不会把 yCollab 弄掉
|
||||
autocompletion({
|
||||
override: [enhanceCompletion(language.value), completeAnyWord],
|
||||
}),
|
||||
getInitialExtension(),
|
||||
])
|
||||
|
||||
@@ -80,7 +99,7 @@ onUnmounted(() => {
|
||||
v-model:show="show"
|
||||
preset="card"
|
||||
:style="{ width: '80vw', maxWidth: '1100px' }"
|
||||
:title="`正在帮 ${collabStore.room?.peerName ?? ''} · ${collabStore.room?.problemId ?? ''}`"
|
||||
:title="`正在帮 ${collabStore.room?.peerName ?? ''} · ${collabStore.room?.problemId ?? ''} · ${language}`"
|
||||
>
|
||||
<template #header-extra>
|
||||
<n-button
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<script lang="ts" setup>
|
||||
import { cpp } from "@codemirror/lang-cpp"
|
||||
import { python } from "@codemirror/lang-python"
|
||||
import { sql, SQLite } from "@codemirror/lang-sql"
|
||||
import { bracketMatching } from "@codemirror/language"
|
||||
import { Codemirror } from "vue-codemirror"
|
||||
import {
|
||||
@@ -9,13 +6,13 @@ import {
|
||||
closeBrackets,
|
||||
completeAnyWord,
|
||||
} from "@codemirror/autocomplete"
|
||||
import type { Extension } from "@codemirror/state"
|
||||
import type { EditorView } from "@codemirror/view"
|
||||
import type { LANGUAGE } from "utils/types"
|
||||
import { oneDark } from "../themes/oneDark"
|
||||
import { smoothy } from "../themes/smoothy"
|
||||
import { styleTheme } from "shared/extensions/baseTheme"
|
||||
import { enhanceCompletion } from "shared/extensions/autocompletion"
|
||||
import { languageExtension } from "shared/extensions/language"
|
||||
import { useCollabDoc } from "../composables/collabDoc"
|
||||
import { useCollabStore } from "shared/store/collab"
|
||||
|
||||
@@ -40,11 +37,7 @@ const {
|
||||
} = defineProps<Props>()
|
||||
const code = defineModel<string>("value")
|
||||
|
||||
const langExtension = computed((): Extension => {
|
||||
if (language === "SQL")
|
||||
return sql({ dialect: SQLite, upperCaseKeywords: true })
|
||||
return ["Python2", "Python3"].includes(language) ? python() : cpp()
|
||||
})
|
||||
const langExtension = computed(() => languageExtension(language))
|
||||
|
||||
const extensions = computed(() => [
|
||||
styleTheme,
|
||||
@@ -96,6 +89,15 @@ watch(
|
||||
},
|
||||
)
|
||||
|
||||
// 求助期间切了语言:同步给老师,他那边的高亮和补全跟着换。
|
||||
// 教师端不发 —— 这个组件在教师自己的题目页上也挂着,他的语言和房间无关
|
||||
watch(
|
||||
() => language,
|
||||
(lang) => {
|
||||
if (!collabStore.isTeacher) collabStore.updateLanguage(lang)
|
||||
},
|
||||
)
|
||||
|
||||
onUnmounted(() => {
|
||||
stop()
|
||||
// 这个组件卸载意味着编辑器没了(切走页面、或者把语言切成流程图),
|
||||
|
||||
Reference in New Issue
Block a user