This commit is contained in:
2025-10-05 10:04:36 +08:00
parent ece84e15c7
commit 94d2066a99
9 changed files with 341 additions and 331 deletions

View File

@@ -1,57 +1,54 @@
<script lang="ts" setup>
import { code } from "oj/composables/code"
import { problem } from "oj/composables/problem"
import { SOURCES } from "utils/constants"
import CodeEditor from "~/shared/components/CodeEditor.vue"
import { isDesktop } from "~/shared/composables/breakpoints"
import storage from "~/utils/storage"
import { LANGUAGE } from "~/utils/types"
import Form from "./Form.vue"
const route = useRoute()
const contestID = route.params.contestID || null
const storageKey = computed(
() =>
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`,
)
const editorHeight = computed(() =>
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)",
)
onMounted(() => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode ||
problem.value!.template[code.language] ||
SOURCES[code.language]
})
const changeCode = (v: string) => {
storage.set(storageKey.value, v)
}
const changeLanguage = (v: LANGUAGE) => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode && storageKey.value.split("_").pop() === v
? savedCode
: problem.value!.template[code.language] || SOURCES[code.language]
}
</script>
<template>
<n-flex vertical>
<Form
:storage-key="storageKey"
@change-language="changeLanguage"
/>
<CodeEditor
v-model:value="code.value"
:language="code.language"
:height="editorHeight"
@update:model-value="changeCode"
/>
</n-flex>
</template>
<script lang="ts" setup>
import { code } from "oj/composables/code"
import { problem } from "oj/composables/problem"
import { SOURCES } from "utils/constants"
import CodeEditor from "~/shared/components/CodeEditor.vue"
import { isDesktop } from "~/shared/composables/breakpoints"
import storage from "~/utils/storage"
import { LANGUAGE } from "~/utils/types"
import Form from "./Form.vue"
const route = useRoute()
const contestID = route.params.contestID || null
const storageKey = computed(
() =>
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`,
)
const editorHeight = computed(() =>
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)",
)
onMounted(() => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode ||
problem.value!.template[code.language] ||
SOURCES[code.language]
})
const changeCode = (v: string) => {
storage.set(storageKey.value, v)
}
const changeLanguage = (v: LANGUAGE) => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode && storageKey.value.split("_").pop() === v
? savedCode
: problem.value!.template[code.language] || SOURCES[code.language]
}
</script>
<template>
<n-flex vertical>
<Form :storage-key="storageKey" @change-language="changeLanguage" />
<CodeEditor
v-model:value="code.value"
:language="code.language"
:height="editorHeight"
@update:model-value="changeCode"
/>
</n-flex>
</template>

View File

@@ -1,94 +1,94 @@
<script lang="ts" setup>
import { code } from "oj/composables/code"
import { problem } from "oj/composables/problem"
import { SOURCES } from "utils/constants"
import SyncCodeEditor from "~/shared/components/SyncCodeEditor.vue"
import { isDesktop } from "~/shared/composables/breakpoints"
import storage from "~/utils/storage"
import { LANGUAGE } from "~/utils/types"
import Form from "./Form.vue"
const route = useRoute()
const formRef = useTemplateRef<InstanceType<typeof Form>>("formRef")
const sync = ref(false)
const otherUserInfo = ref<{ name: string; isSuperAdmin: boolean }>()
const hadConnection = ref(false)
const contestID = route.params.contestID || null
const storageKey = computed(
() =>
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`,
)
const editorHeight = computed(() =>
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)",
)
onMounted(() => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode ||
problem.value!.template[code.language] ||
SOURCES[code.language]
})
const changeCode = (v: string) => {
storage.set(storageKey.value, v)
}
const changeLanguage = (v: LANGUAGE) => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode && storageKey.value.split("_").pop() === v
? savedCode
: problem.value!.template[code.language] || SOURCES[code.language]
}
const toggleSync = (value: boolean) => {
sync.value = value
if (!value) {
hadConnection.value = false
}
}
const handleSyncClosed = () => {
sync.value = false
otherUserInfo.value = undefined
hadConnection.value = false
formRef.value?.resetSyncStatus()
}
const handleSyncStatusChange = (status: {
otherUser?: { name: string; isSuperAdmin: boolean }
}) => {
otherUserInfo.value = status.otherUser
if (status.otherUser) {
hadConnection.value = true
}
}
</script>
<template>
<n-flex vertical>
<Form
ref="formRef"
:storage-key="storageKey"
:other-user-info="otherUserInfo"
:is-connected="sync"
:had-connection="hadConnection"
@change-language="changeLanguage"
@toggle-sync="toggleSync"
/>
<SyncCodeEditor
v-model:value="code.value"
:sync="sync"
:problem="problem!._id"
:language="code.language"
:height="editorHeight"
@update:model-value="changeCode"
@sync-closed="handleSyncClosed"
@sync-status-change="handleSyncStatusChange"
/>
</n-flex>
</template>
<script lang="ts" setup>
import { code } from "oj/composables/code"
import { problem } from "oj/composables/problem"
import { SOURCES } from "utils/constants"
import SyncCodeEditor from "~/shared/components/SyncCodeEditor.vue"
import { isDesktop } from "~/shared/composables/breakpoints"
import storage from "~/utils/storage"
import { LANGUAGE } from "~/utils/types"
import Form from "./Form.vue"
const route = useRoute()
const formRef = useTemplateRef<InstanceType<typeof Form>>("formRef")
const sync = ref(false)
const otherUserInfo = ref<{ name: string; isSuperAdmin: boolean }>()
const hadConnection = ref(false)
const contestID = route.params.contestID || null
const storageKey = computed(
() =>
`problem_${problem.value!._id}_contest_${contestID}_lang_${code.language}`,
)
const editorHeight = computed(() =>
isDesktop.value ? "calc(100vh - 133px)" : "calc(100vh - 172px)",
)
onMounted(() => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode ||
problem.value!.template[code.language] ||
SOURCES[code.language]
})
const changeCode = (v: string) => {
storage.set(storageKey.value, v)
}
const changeLanguage = (v: LANGUAGE) => {
const savedCode = storage.get(storageKey.value)
code.value =
savedCode && storageKey.value.split("_").pop() === v
? savedCode
: problem.value!.template[code.language] || SOURCES[code.language]
}
const toggleSync = (value: boolean) => {
sync.value = value
if (!value) {
hadConnection.value = false
}
}
const handleSyncClosed = () => {
sync.value = false
otherUserInfo.value = undefined
hadConnection.value = false
formRef.value?.resetSyncStatus()
}
const handleSyncStatusChange = (status: {
otherUser?: { name: string; isSuperAdmin: boolean }
}) => {
otherUserInfo.value = status.otherUser
if (status.otherUser) {
hadConnection.value = true
}
}
</script>
<template>
<n-flex vertical>
<Form
ref="formRef"
:storage-key="storageKey"
:other-user-info="otherUserInfo"
:is-connected="sync"
:had-connection="hadConnection"
@change-language="changeLanguage"
@toggle-sync="toggleSync"
/>
<SyncCodeEditor
v-model:value="code.value"
:sync="sync"
:problem="problem!._id"
:language="code.language"
:height="editorHeight"
@update:model-value="changeCode"
@sync-closed="handleSyncClosed"
@sync-status-change="handleSyncStatusChange"
/>
</n-flex>
</template>

View File

@@ -158,7 +158,8 @@ watch(query, listSubmissions)
<template #header>
<n-flex align="center">
<span>
本道题你还没有解决你们班共有 <b>{{ class_ac_count }}</b> 人答案正确
本道题你还没有解决你们班共有
<b>{{ class_ac_count }}</b> 人答案正确
</span>
<n-button
v-if="userStore.showSubmissions"
@@ -245,7 +246,12 @@ watch(query, listSubmissions)
</template>
<template v-if="userStore.showSubmissions && userStore.isAuthed">
<n-data-table v-if="submissions.length > 0" striped :columns="columns" :data="submissions" />
<n-data-table
v-if="submissions.length > 0"
striped
:columns="columns"
:data="submissions"
/>
<Pagination
:total="total"
v-model:limit="query.limit"

View File

@@ -9,8 +9,12 @@ import {
} from "~/shared/composables/switchScreen"
import { problem } from "../composables/problem"
const ProblemEditor = defineAsyncComponent(() => import("./components/ProblemEditor.vue"))
const ContestEditor = defineAsyncComponent(() => import("./components/ContestEditor.vue"))
const ProblemEditor = defineAsyncComponent(
() => import("./components/ProblemEditor.vue"),
)
const ContestEditor = defineAsyncComponent(
() => import("./components/ContestEditor.vue"),
)
const EditorWithTest = defineAsyncComponent(
() => import("./components/EditorWithTest.vue"),
)