This commit is contained in:
2023-01-18 21:47:39 +08:00
parent 5763f6dea2
commit a192c6d77a
14 changed files with 56 additions and 125 deletions

1
src/components.d.ts vendored
View File

@@ -38,6 +38,7 @@ declare module '@vue/runtime-core' {
NTabPane: typeof import('naive-ui')['NTabPane'] NTabPane: typeof import('naive-ui')['NTabPane']
NTabs: typeof import('naive-ui')['NTabs'] NTabs: typeof import('naive-ui')['NTabs']
NTag: typeof import('naive-ui')['NTag'] NTag: typeof import('naive-ui')['NTag']
NTooltip: typeof import('naive-ui')['NTooltip']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
} }

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import Loading from "./components/Loading.vue" import Loading from "./components/Loading.vue"
import Monaco from "../shared/monaco/index.vue" import Monaco from "../shared/Monaco.vue"
const route = useRoute() const route = useRoute()
const step = route.hash.replace("#step-", "") || "1" const step = route.hash.replace("#step-", "") || "1"

View File

@@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import { SOURCES } from "utils/constants" import { SOURCES } from "utils/constants"
import { Problem } from "utils/types" import { Problem } from "utils/types"
import Monaco from "~/shared/Monaco/index.vue" import Monaco from "~/shared/Monaco.vue"
import { code } from "oj/composables/code" import { code } from "oj/composables/code"
interface Props { interface Props {

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import { Flag, CloseBold, Select, CopyDocument } from "@element-plus/icons-vue" import { Flag, CloseBold, Select } from "@element-plus/icons-vue"
import copy from "copy-text-to-clipboard" import Copy from "~/shared/Copy.vue"
import { code } from "oj/composables/code" import { code } from "oj/composables/code"
import { SOURCES } from "utils/constants" import { SOURCES } from "utils/constants"
import { Problem, ProblemStatus } from "utils/types" import { Problem, ProblemStatus } from "utils/types"
@@ -131,7 +131,7 @@ const type = (status: ProblemStatus) =>
<template #label> <template #label>
<n-space> <n-space>
<span>输入</span> <span>输入</span>
<n-icon @click="copy(sample.input)"><CopyDocument /></n-icon> <Copy :value="sample.input" />
</n-space> </n-space>
</template> </template>
<div class="testcase">{{ sample.input }}</div> <div class="testcase">{{ sample.input }}</div>
@@ -140,7 +140,7 @@ const type = (status: ProblemStatus) =>
<template #label> <template #label>
<n-space> <n-space>
<span>输出</span> <span>输出</span>
<n-icon @click="copy(sample.output)"><CopyDocument /></n-icon> <Copy :value="sample.output" />
</n-space> </n-space>
</template> </template>
<div class="testcase">{{ sample.output }}</div> <div class="testcase">{{ sample.output }}</div>

View File

@@ -4,7 +4,7 @@ import { filterEmptyValue, getTagColor } from "utils/functions"
import { isDesktop } from "~/shared/composables/breakpoints" import { isDesktop } from "~/shared/composables/breakpoints"
import { getProblemList, getProblemTagList, getRandomProblemID } from "oj/api" import { getProblemList, getProblemTagList, getRandomProblemID } from "oj/api"
import Pagination from "~/shared/Pagination/index.vue" import Pagination from "~/shared/Pagination.vue"
import { DataTableColumn, NIcon, NSpace, NTag, useThemeVars } from "naive-ui" import { DataTableColumn, NIcon, NSpace, NTag, useThemeVars } from "naive-ui"
import { Select, SemiSelect } from "@element-plus/icons-vue" import { Select, SemiSelect } from "@element-plus/icons-vue"

View File

@@ -1,8 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { c, DataTableColumn, SelectOption } from "naive-ui" import { DataTableColumn, SelectOption } from "naive-ui"
import { NButton } from "naive-ui" import { NButton } from "naive-ui"
import Pagination from "~/shared/Pagination/index.vue"
import SubmissionResultTag from "oj/components/SubmissionResultTag.vue" import SubmissionResultTag from "oj/components/SubmissionResultTag.vue"
import Pagination from "~/shared/Pagination.vue"
import { import {
submissionMemoryFormat, submissionMemoryFormat,
submissionTimeFormat, submissionTimeFormat,
@@ -38,14 +38,10 @@ const query = reactive<Query>({
const options: SelectOption[] = [ const options: SelectOption[] = [
{ label: "全部", value: "" }, { label: "全部", value: "" },
{ label: "编译失败", value: "-2" },
{ label: "答案错误", value: "-1" },
{ label: "答案正确", value: "0" }, { label: "答案正确", value: "0" },
{ label: "运行超时", value: "1" }, { label: "答案错误", value: "-1" },
{ label: "内存超限", value: "3" }, { label: "编译失败", value: "-2" },
{ label: "运行时错误", value: "4" }, { label: "运行时错误", value: "4" },
{ label: "系统错误", value: "5" },
{ label: "部分正确", value: "8" },
] ]
async function listSubmissions() { async function listSubmissions() {
@@ -133,7 +129,15 @@ const columns: DataTableColumn<Submission>[] = [
key: "problem", key: "problem",
width: 100, width: 100,
render: (row) => render: (row) =>
h(NButton, { text: true, type: "info" }, () => row.problem), h(
NButton,
{
text: true,
type: "info",
onClick: () => router.push("/problem/" + row.problem),
},
() => row.problem
),
}, },
{ {
title: "执行耗时", title: "执行耗时",

24
src/shared/Copy.vue Normal file
View File

@@ -0,0 +1,24 @@
<script setup lang="ts">
import { DocumentCopy, Select } from "@element-plus/icons-vue"
import copy from "copy-text-to-clipboard"
defineProps<{ value: string }>()
const [copied, toggle] = useToggle()
const { start } = useTimeoutFn(() => toggle(false), 1000, { immediate: false })
function handleClick(value: string) {
copy(value)
toggle(true)
start()
}
</script>
<template>
<n-tooltip trigger="hover">
<template #trigger>
<n-icon @click="handleClick(value)">
<component :is="copied ? Select : DocumentCopy"></component>
</n-icon>
</template>
{{ copied ? "已复制" : "复制" }}
</n-tooltip>
</template>

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { Sunny, Moon } from "@element-plus/icons-vue" import { Sunny, Moon } from "@element-plus/icons-vue"
import { logout } from "../api" import { logout } from "./api"
import { useUserStore } from "../store/user" import { useUserStore } from "./store/user"
import { isDark, toggleDark } from "~/shared/composables/dark" import { isDark, toggleDark } from "~/shared/composables/dark"
import { toggleLogin, toggleSignup } from "~/shared/composables/modal" import { toggleLogin, toggleSignup } from "~/shared/composables/modal"
import type { import type {

View File

@@ -1,7 +1,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { login } from "../api" import { login } from "./api"
import { loginModal, toggleLogin, toggleSignup } from "../composables/modal" import { loginModal, toggleLogin, toggleSignup } from "./composables/modal"
import { useUserStore } from "../store/user" import { useUserStore } from "./store/user"
import type { FormRules } from "naive-ui" import type { FormRules } from "naive-ui"
const userStore = useUserStore() const userStore = useUserStore()

View File

@@ -3,7 +3,7 @@ import type * as Monaco from "monaco-editor"
import { LANGUAGE_VALUE } from "utils/constants" import { LANGUAGE_VALUE } from "utils/constants"
import { LANGUAGE } from "utils/types" import { LANGUAGE } from "utils/types"
import { isMobile } from "~/shared/composables/breakpoints" import { isMobile } from "~/shared/composables/breakpoints"
import { isDark } from "../composables/dark" import { isDark } from "./composables/dark"
interface Props { interface Props {
value: string value: string

View File

@@ -1,98 +0,0 @@
<script setup lang="ts">
import type * as Monaco from "monaco-editor"
import { LANGUAGE_VALUE } from "utils/constants"
import { LANGUAGE } from "utils/types"
import { isMobile } from "~/shared/composables/breakpoints"
import { isDark } from "../composables/dark"
interface Props {
value: string
language?: LANGUAGE
height?: string
fontSize?: number
class?: string
}
const props = withDefaults(defineProps<Props>(), {
language: "C",
height: "100%",
fontSize: 20,
class: "",
})
const emit = defineEmits<{
(e: "change", value: string): void
}>()
const monacoEditorRef = ref()
let editor: Monaco.editor.IStandaloneCodeEditor
onMounted(function () {
const model = window.monaco.editor.createModel(
props.value,
LANGUAGE_VALUE[props.language]
)
editor = window.monaco.editor.create(monacoEditorRef.value, {
model,
theme: isDark.value ? "dark" : "light", // 官方自带三种主题vs, hc-black, or vs-dark
minimap: {
enabled: false,
},
lineNumbersMinChars: 3,
automaticLayout: true, // 自适应布局
tabSize: 4,
fontSize: isMobile.value ? 20 : 24, // 字体大小
scrollBeyondLastLine: false,
lineDecorationsWidth: 0,
scrollBeyondLastColumn: 0,
glyphMargin: false,
scrollbar: {
useShadows: false,
vertical: "hidden",
horizontal: "hidden",
},
overviewRulerLanes: 0,
})
model.onDidChangeContent(() => {
const value = model.getValue().toString()
emit("change", value)
})
editor.onKeyDown((e) => {
if ((e.ctrlKey || e.metaKey) && e.code === "KeyS") {
e.preventDefault()
}
if ((e.ctrlKey || e.metaKey) && e.code === "KeyR") {
e.preventDefault()
}
})
watchEffect(() => {
window.monaco.editor.setModelLanguage(model, LANGUAGE_VALUE[props.language])
})
watchEffect(() => {
if (props.value !== model.getValue()) {
model.setValue(props.value)
}
})
watchEffect(() => {
window.monaco.editor.setTheme(isDark.value ? "dark" : "light")
})
})
onUnmounted(() => {
editor && editor.dispose()
})
</script>
<template>
<div
ref="monacoEditorRef"
:class="props.class"
:style="{ height: props.height }"
></div>
</template>
<style scoped></style>

View File

@@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { FormRules } from "naive-ui" import type { FormRules } from "naive-ui"
import { signupModal, toggleLogin, toggleSignup } from "../composables/modal" import { signupModal, toggleLogin, toggleSignup } from "./composables/modal"
const form = reactive({ const form = reactive({
username: "", username: "",

View File

@@ -1,11 +1,11 @@
<script setup lang="ts"> <script setup lang="ts">
import Login from "../Login/index.vue" import Login from "../Login.vue"
import Signup from "../Signup/index.vue" import Signup from "../Signup.vue"
import Header from "../Header/index.vue" import Header from "../Header.vue"
</script> </script>
<template> <template>
<n-layout> <n-layout position="absolute" :native-scrollbar="false">
<n-layout-header bordered class="header"> <n-layout-header bordered class="header">
<Header /> <Header />
</n-layout-header> </n-layout-header>