This commit is contained in:
2023-01-20 12:29:32 +08:00
parent 40fae1c7c0
commit 0b2d9e3efd
23 changed files with 271 additions and 150 deletions

View File

@@ -1,8 +1,22 @@
<script setup lang="ts">
import { zhCN, dateZhCN, darkTheme } from "naive-ui"
import { isDark } from "./shared/composables/dark"
import hljs from "highlight.js/lib/core"
import c from "highlight.js/lib/languages/c"
import cpp from "highlight.js/lib/languages/c"
import java from "highlight.js/lib/languages/java"
import python from "highlight.js/lib/languages/python"
import javascript from "highlight.js/lib/languages/javascript"
import go from "highlight.js/lib/languages/go"
const theme = computed(() => (isDark.value ? darkTheme : null))
hljs.registerLanguage("c", c)
hljs.registerLanguage("cpp", cpp)
hljs.registerLanguage("java", java)
hljs.registerLanguage("python", python)
hljs.registerLanguage("javascript", javascript)
hljs.registerLanguage("go", go)
</script>
<template>
@@ -11,6 +25,7 @@ const theme = computed(() => (isDark.value ? darkTheme : null))
:theme="theme"
:locale="zhCN"
:date-locale="dateZhCN"
:hljs="hljs"
>
<router-view></router-view>
</n-config-provider>

View File

@@ -207,6 +207,7 @@ declare global {
const useParallax: typeof import('@vueuse/core')['useParallax']
const usePermission: typeof import('@vueuse/core')['usePermission']
const usePointer: typeof import('@vueuse/core')['usePointer']
const usePointerLock: typeof import('@vueuse/core')['usePointerLock']
const usePointerSwipe: typeof import('@vueuse/core')['usePointerSwipe']
const usePreferredColorScheme: typeof import('@vueuse/core')['usePreferredColorScheme']
const usePreferredContrast: typeof import('@vueuse/core')['usePreferredContrast']

4
src/components.d.ts vendored
View File

@@ -12,15 +12,15 @@ declare module '@vue/runtime-core' {
IEpLoading: typeof import('~icons/ep/loading')['default']
NAlert: typeof import('naive-ui')['NAlert']
NButton: typeof import('naive-ui')['NButton']
NCard: typeof import('naive-ui')['NCard']
NCode: typeof import('naive-ui')['NCode']
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
NDataTable: typeof import('naive-ui')['NDataTable']
NDescriptions: typeof import('naive-ui')['NDescriptions']
NDescriptionsItem: typeof import('naive-ui')['NDescriptionsItem']
NDropdown: typeof import('naive-ui')['NDropdown']
NForm: typeof import('naive-ui')['NForm']
NFormGrid: typeof import('naive-ui')['NFormGrid']
NFormItem: typeof import('naive-ui')['NFormItem']
NFormItemGi: typeof import('naive-ui')['NFormItemGi']
NGi: typeof import('naive-ui')['NGi']
NGrid: typeof import('naive-ui')['NGrid']
NIcon: typeof import('naive-ui')['NIcon']

View File

@@ -1 +0,0 @@
<template>loading...</template>

View File

@@ -1,16 +1,13 @@
<script setup lang="ts">
import Loading from "./components/Loading.vue"
import Monaco from "../shared/Monaco.vue"
import raw from "./step-1/1.c?raw"
const route = useRoute()
const step = route.hash.replace("#step-", "") || "1"
const id = route.hash.replace("#step-", "") || "1"
const Md = defineAsyncComponent({
loader: () => import(`./step-${step}/index.md`),
loadingComponent: Loading,
})
const Md = defineAsyncComponent(() => import(`./step-${id}/index.md`))
const code = ref("")
const code = ref(raw)
function change(value: string) {
code.value = value
@@ -21,6 +18,10 @@ function change(value: string) {
<n-grid :cols="2">
<n-gi>
<Md />
<n-space justify="space-between">
<n-button text type="primary">上一步</n-button>
<n-button text type="primary">下一步</n-button>
</n-space>
</n-gi>
<n-gi>
<Monaco :value="code" @change="change" />

6
src/learn/step-1/1.c Normal file
View File

@@ -0,0 +1,6 @@
#include <stdio.h>
int main()
{
return 0;
}

View File

@@ -1,13 +1 @@
# 我的是第一步骤
```c
#include<stdio.h>
int main() {
return 0;
}
```
## nihao
我的
# 11

View File

@@ -1,6 +1,5 @@
import { createRouter, createWebHistory } from "vue-router"
import { createPinia } from "pinia"
import loader from "@monaco-editor/loader"
import storage from "utils/storage"
import { STORAGE_KEY } from "utils/constants"
@@ -9,6 +8,7 @@ import { routes } from "./routes"
import App from "./App.vue"
import { toggleLogin } from "./shared/composables/modal"
import { init } from "./shared/composables/monaco"
const router = createRouter({
history: createWebHistory(),
@@ -27,24 +27,8 @@ router.beforeEach((to, from, next) => {
next()
}
})
init()
const pinia = createPinia()
loader.init().then((monaco) => {
window.monaco = monaco
fetch("/dark.json").then((data) =>
data.json().then((theme) => monaco.editor.defineTheme("dark", theme))
)
fetch("/light.json").then((data) =>
data.json().then((theme) => monaco.editor.defineTheme("light", theme))
)
})
loader.config({
paths: { vs: "https://cdn.staticfile.org/monaco-editor/0.34.1/min/vs" },
"vs/nls": { availableLanguages: { "*": "zh-cn" } },
})
const app = createApp(App)
app.use(router)
app.use(pinia)

View File

@@ -36,7 +36,7 @@ function change(value: string) {
<n-form-item>
<n-space>
<n-button @click="reset">重置</n-button>
<n-button @click="$router.push(`/status?problem=${problem._id}`)">
<n-button @click="$router.push(`/submission?problem=${problem._id}`)">
提交信息
</n-button>
</n-space>

View File

@@ -7,7 +7,7 @@ import { SOURCES, JUDGE_STATUS, SubmissionStatus } from "utils/constants"
import { submissionMemoryFormat, submissionTimeFormat } from "utils/functions"
import { Problem, Submission, SubmitCodePayload } from "utils/types"
import { getSubmission, submitCode } from "oj/api"
import SubmissionResultTag from "../../components/SubmissionResultTag.vue"
import SubmissionResultTag from "../../../shared/SubmissionResultTag.vue"
import { DataTableColumn } from "naive-ui"
const problem = inject<Ref<Problem>>("problem")

View File

@@ -1,5 +0,0 @@
<script setup lang="ts"></script>
<template>status detail</template>
<style scoped></style>

View File

@@ -0,0 +1,80 @@
<script setup lang="ts">
import { getSubmission } from "oj/api"
import { Submission } from "utils/types"
import { JUDGE_STATUS, LANGUAGE_VALUE } from "utils/constants"
import {
parseTime,
submissionMemoryFormat,
submissionTimeFormat,
} from "utils/functions"
import { DataTableColumn, NAlert, NDataTable } from "naive-ui"
import copy from "copy-text-to-clipboard"
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
const props = defineProps<{
submissionID: string
}>()
const submission = ref<Submission>()
async function init() {
const res = await getSubmission(props.submissionID)
submission.value = res.data
}
const columns: DataTableColumn<Submission["info"]["data"][number]>[] = [
{ title: "测试用例", key: "test_case" },
{
title: "测试状态",
key: "result",
render: (row) => h(SubmissionResultTag, { result: row.result }),
},
{
title: "占用内存",
key: "memory",
render: (row) => submissionMemoryFormat(row.memory),
},
{
title: "执行耗时",
key: "real_time",
render: (row) => submissionTimeFormat(row.real_time),
},
{ title: "信号", key: "signal" },
]
onMounted(init)
</script>
<template>
<n-space vertical v-if="submission" :size="24">
<n-alert
:type="JUDGE_STATUS[submission.result]['type']"
:title="JUDGE_STATUS[submission.result]['name']"
>
<n-space>
<span>提交时间{{ parseTime(submission.create_time) }}</span>
<span>语言{{ submission.language }}</span>
<span>提交人 {{ submission.username }}</span>
</n-space>
</n-alert>
<n-card embedded>
<n-space justify="end">
<n-button @click="copy(submission!.code)">复制代码</n-button>
</n-space>
<n-code
class="code"
word-wrap
:language="LANGUAGE_VALUE[submission.language]"
:code="submission.code"
show-line-numbers
/>
</n-card>
<n-data-table :columns="columns" :data="submission.info.data" />
</n-space>
</template>
<style scoped>
.code {
font-size: 20px;
}
</style>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts">
import { DataTableColumn, SelectOption } from "naive-ui"
import { NButton } from "naive-ui"
import SubmissionResultTag from "oj/components/SubmissionResultTag.vue"
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
import Pagination from "~/shared/Pagination.vue"
import {
submissionMemoryFormat,
@@ -23,8 +23,6 @@ interface Query {
const route = useRoute()
const router = useRouter()
const problemID = <string>route.query.problem ?? ""
const contestID = <string>route.query.contest ?? ""
const submissions = ref([])
const total = ref(0)
@@ -57,8 +55,8 @@ async function listSubmissions() {
...query,
myself: query.myself ? "1" : "0",
offset,
problem_id: problemID,
contest_id: contestID,
problem_id: <string>route.query.problem ?? "",
contest_id: <string>route.params.contestID ?? "",
})
submissions.value = res.data.results
total.value = res.data.total
@@ -98,7 +96,7 @@ watch(
)
watch(
() => route.path === "/status" && route.query,
() => route.path === "/submission" && route.query,
(newVal) => {
if (newVal) listSubmissions()
}
@@ -116,7 +114,15 @@ const columns: DataTableColumn<Submission>[] = [
title: "编号",
key: "id",
render: (row) =>
h(NButton, { text: true, type: "info" }, () => row.id.slice(0, 12)),
h(
NButton,
{
text: true,
type: "info",
onClick: () => router.push("/submission/" + row.id),
},
() => row.id.slice(0, 12)
),
},
{
title: "状态",

View File

@@ -11,13 +11,13 @@ export const routes = [
name: "ProblemDetail",
},
{
path: "status",
component: () => import("oj/status/list.vue"),
path: "submission",
component: () => import("oj/submission/list.vue"),
meta: { requiresAuth: true },
},
{
path: "status/:statusID",
component: () => import("oj/status/detail.vue"),
path: "submission/:submissionID",
component: () => import("oj/submission/detail.vue"),
props: true,
},
{

View File

@@ -45,7 +45,8 @@ const menus: MenuOption[] = [
key: "contest",
},
{
label: () => h(RouterLink, { to: "/status" }, { default: () => "提交" }),
label: () =>
h(RouterLink, { to: "/submission" }, { default: () => "提交" }),
key: "status",
},
{

View File

@@ -4,6 +4,7 @@ import { LANGUAGE_VALUE } from "utils/constants"
import { LANGUAGE } from "utils/types"
import { isMobile } from "~/shared/composables/breakpoints"
import { isDark } from "./composables/dark"
import { monaco } from "./composables/monaco"
interface Props {
value: string
@@ -15,7 +16,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
language: "C",
height: "100%",
height: "calc(100vh - 92px)",
fontSize: 20,
class: "",
})
@@ -26,14 +27,16 @@ const emit = defineEmits<{
const monacoEditorRef = ref()
let editor: Monaco.editor.IStandaloneCodeEditor
let model: Monaco.editor.ITextModel
onMounted(function () {
const model = window.monaco.editor.createModel(
onMounted(() => {
if (!monaco.value) return
model = monaco.value!.editor.createModel(
props.value,
LANGUAGE_VALUE[props.language]
)
editor = window.monaco.editor.create(monacoEditorRef.value, {
editor = monaco.value!.editor.create(monacoEditorRef.value, {
model,
theme: isDark.value ? "dark" : "light", // 官方自带三种主题vs, hc-black, or vs-dark
minimap: {
@@ -70,7 +73,8 @@ onMounted(function () {
})
watchEffect(() => {
window.monaco.editor.setModelLanguage(model, LANGUAGE_VALUE[props.language])
if (!monaco.value) return
monaco.value.editor.setModelLanguage(model, LANGUAGE_VALUE[props.language])
})
watchEffect(() => {
@@ -80,16 +84,17 @@ onMounted(function () {
})
watchEffect(() => {
window.monaco.editor.setTheme(isDark.value ? "dark" : "light")
if (!monaco.value) return
monaco.value.editor.setTheme(isDark.value ? "dark" : "light")
})
})
onUnmounted(() => {
editor && editor.dispose()
})
</script>
<template>
<div
v-if="monaco"
ref="monacoEditorRef"
:class="props.class"
:style="{ height: props.height }"

View File

@@ -1,6 +1,6 @@
<script setup lang="ts">
import { JUDGE_STATUS } from "../../utils/constants"
import { SUBMISSION_RESULT } from "../../utils/types"
import { JUDGE_STATUS } from "utils/constants"
import { SUBMISSION_RESULT } from "utils/types"
interface Props {
result: SUBMISSION_RESULT

View File

@@ -0,0 +1,19 @@
import loader, { Monaco } from "@monaco-editor/loader"
export const monaco = ref<Monaco>()
export async function init() {
loader.config({
paths: { vs: "https://cdn.staticfile.org/monaco-editor/0.34.1/min/vs" },
"vs/nls": { availableLanguages: { "*": "zh-cn" } },
})
const [m, light, dark] = await Promise.all([
loader.init(),
fetch("/light.json").then((t) => t.json()),
fetch("/dark.json").then((t) => t.json()),
])
monaco.value = m
monaco.value.editor.defineTheme("light", light)
monaco.value.editor.defineTheme("dark", dark)
}

11
src/shims.d.ts vendored
View File

@@ -3,14 +3,3 @@ declare module "*.md" {
const Component: ComponentOptions
export default Component
}
declare global {
let monaco: Monaco
interface Window {
monaco: Monaco
}
}
interface Window {
monaco: Monaco
}

View File

@@ -90,7 +90,7 @@ export interface Submission {
code: string
result: SUBMISSION_RESULT
info: Info
language: string
language: LANGUAGE
shared: boolean
statistic_info: {
score?: number