From 04c6c49eaa246a3ba6dab5d47500d5a32d362bd9 Mon Sep 17 00:00:00 2001 From: yuetsh <517252939@qq.com> Date: Sun, 5 Oct 2025 09:54:42 +0800 Subject: [PATCH] fix --- src/oj/problem/components/ContestEditor.vue | 57 ++++++ src/oj/problem/components/Form.vue | 162 ++++++++------- .../{Editor.vue => ProblemEditor.vue} | 188 +++++++++--------- src/oj/problem/detail.vue | 11 +- src/shared/components/CodeEditor.vue | 81 +------- src/shared/components/SyncCodeEditor.vue | 138 +++++++++++++ src/shared/composables/sync.ts | 29 +-- 7 files changed, 394 insertions(+), 272 deletions(-) create mode 100644 src/oj/problem/components/ContestEditor.vue rename src/oj/problem/components/{Editor.vue => ProblemEditor.vue} (91%) create mode 100644 src/shared/components/SyncCodeEditor.vue diff --git a/src/oj/problem/components/ContestEditor.vue b/src/oj/problem/components/ContestEditor.vue new file mode 100644 index 0000000..f48360f --- /dev/null +++ b/src/oj/problem/components/ContestEditor.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/oj/problem/components/Form.vue b/src/oj/problem/components/Form.vue index b850beb..f16aed8 100644 --- a/src/oj/problem/components/Form.vue +++ b/src/oj/problem/components/Form.vue @@ -16,13 +16,13 @@ interface Props { storageKey: string withTest?: boolean otherUserInfo?: { name: string; isSuperAdmin: boolean } - isSynced?: boolean + isConnected?: boolean // WebSocket 实际的连接状态(已建立/未建立) hadConnection?: boolean } const props = withDefaults(defineProps(), { withTest: false, - isSynced: false, + isConnected: false, hadConnection: false, }) @@ -36,34 +36,40 @@ const route = useRoute() const router = useRouter() const userStore = useUserStore() -const isSynced = ref(false) +const syncEnabled = ref(false) // 用户点击按钮后的意图状态(想要开启/关闭) const statisticPanel = ref(false) +// 计算属性 +const isContestMode = computed(() => route.name === "contest problem") +const buttonSize = computed(() => (isDesktop.value ? "medium" : "small")) +const showSyncFeature = computed( + () => isDesktop.value && userStore.isAuthed && !isContestMode.value, +) + const menu = computed(() => [ - { label: "去自测猫", key: "test", show: isMobile.value }, + { label: "去自测猫", key: "goTestCat", show: isMobile.value }, { label: "复制代码", key: "copy" }, { label: "重置代码", key: "reset" }, ]) -const languageOptions: DropdownOption[] = problem.value!.languages.map((it) => ({ - label: () => - h("div", { style: "display: flex; align-items: center;" }, [ - h("img", { - src: `/${it}.svg`, - style: { width: "16px", height: "16px", marginRight: "8px" }, - }), - LANGUAGE_SHOW_VALUE[it], - ]), - value: it, -})) +const languageOptions: DropdownOption[] = problem.value!.languages.map( + (it) => ({ + label: () => + h("div", { style: "display: flex; align-items: center;" }, [ + h("img", { + src: `/${it}.svg`, + style: { width: "16px", height: "16px", marginRight: "8px" }, + }), + LANGUAGE_SHOW_VALUE[it], + ]), + value: it, + }), +) +// 代码操作相关 const copy = async () => { const success = await copyToClipboard(code.value) - if (success) { - message.success("代码复制成功") - } else { - message.error("代码复制失败") - } + message[success ? "success" : "error"](`代码复制${success ? "成功" : "失败"}`) } const reset = () => { @@ -72,123 +78,129 @@ const reset = () => { message.success("代码重置成功") } +const changeLanguage = (v: LANGUAGE) => { + storage.set(STORAGE_KEY.LANGUAGE, v) + emit("changeLanguage", v) +} + +const runCode = async () => { + const res = await createTestSubmission(code, input.value) + output.value = res.output +} + +// 导航相关 +const goTestCat = () => { + window.open(import.meta.env.PUBLIC_CODE_URL, "_blank") +} + const goSubmissions = () => { const name = route.params.contestID ? "contest submissions" : "submissions" router.push({ name, query: { problem: problem.value!._id } }) } const goEdit = () => { - const baseUrl = "/admin/problem/edit/" + problem.value!.id const url = problem.value!.contest ? `/admin/contest/${problem.value!.contest}/problem/edit/${problem.value!.id}` - : baseUrl + : `/admin/problem/edit/${problem.value!.id}` window.open(router.resolve(url).href, "_blank") } -const test = async () => { - const res = await createTestSubmission(code, input.value) - output.value = res.output -} - +// 菜单处理 const handleMenuSelect = (key: string) => { const actions: Record void> = { reset, copy, - test: () => window.open(import.meta.env.PUBLIC_CODE_URL, "_blank"), + goTestCat, } actions[key]?.() } -const changeLanguage = (v: LANGUAGE) => { - storage.set(STORAGE_KEY.LANGUAGE, v) - emit("changeLanguage", v) -} - +// 协同编辑相关 const toggleSync = () => { - isSynced.value = !isSynced.value - emit("toggleSync", isSynced.value) -} - -const gotoTestCat = () => { - window.open(import.meta.env.PUBLIC_CODE_URL, "_blank") + syncEnabled.value = !syncEnabled.value + emit("toggleSync", syncEnabled.value) } defineExpose({ resetSyncStatus: () => { - isSynced.value = false + syncEnabled.value = false }, })