This commit is contained in:
2023-02-10 12:32:46 +08:00
parent c106f4bb5f
commit a1d657fe8d
9 changed files with 1417 additions and 2081 deletions

3391
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -12,32 +12,32 @@
"dependencies": { "dependencies": {
"@element-plus/icons-vue": "^2.0.10", "@element-plus/icons-vue": "^2.0.10",
"@monaco-editor/loader": "^1.3.2", "@monaco-editor/loader": "^1.3.2",
"@vueuse/core": "^9.11.1", "@vueuse/core": "^9.12.0",
"axios": "1.2.5", "axios": "1.3.2",
"chart.js": "^4.2.0", "chart.js": "^4.2.0",
"copy-text-to-clipboard": "^3.0.1", "copy-text-to-clipboard": "^3.0.1",
"date-fns": "^2.29.3", "date-fns": "^2.29.3",
"highlight.js": "^11.7.0", "highlight.js": "^11.7.0",
"naive-ui": "^2.34.3", "naive-ui": "^2.34.3",
"party-js": "^2.2.0", "party-js": "^2.2.0",
"pinia": "^2.0.29", "pinia": "^2.0.30",
"vue": "^3.2.45", "vue": "^3.2.47",
"vue-chartjs": "^5.2.0", "vue-chartjs": "^5.2.0",
"vue-router": "^4.1.6" "vue-router": "^4.1.6"
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/ep": "^1.1.8", "@iconify-json/ep": "^1.1.8",
"@types/node": "^18.11.18", "@types/node": "^18.13.0",
"@vitejs/plugin-vue": "^4.0.0", "@vitejs/plugin-vue": "^4.0.0",
"markdown-it-shiki": "^0.7.2", "markdown-it-shiki": "^0.7.2",
"monaco-editor": "^0.34.1", "monaco-editor": "^0.35.0",
"prettier": "^2.8.3", "prettier": "^2.8.4",
"typescript": "^4.9.4", "typescript": "^4.9.5",
"unplugin-auto-import": "^0.12.2", "unplugin-auto-import": "^0.14.2",
"unplugin-icons": "^0.15.2", "unplugin-icons": "^0.15.2",
"unplugin-vue-components": "^0.22.12", "unplugin-vue-components": "^0.23.0",
"vite": "^4.0.4", "vite": "^4.1.1",
"vite-plugin-vue-markdown": "^0.22.2", "vite-plugin-vue-markdown": "^0.22.4",
"vue-tsc": "^1.0.24" "vue-tsc": "^1.0.24"
} }
} }

View File

@@ -83,7 +83,6 @@ declare global {
const refThrottled: typeof import('@vueuse/core')['refThrottled'] const refThrottled: typeof import('@vueuse/core')['refThrottled']
const refWithControl: typeof import('@vueuse/core')['refWithControl'] const refWithControl: typeof import('@vueuse/core')['refWithControl']
const resolveComponent: typeof import('vue')['resolveComponent'] const resolveComponent: typeof import('vue')['resolveComponent']
const resolveDirective: typeof import('vue')['resolveDirective']
const resolveRef: typeof import('@vueuse/core')['resolveRef'] const resolveRef: typeof import('@vueuse/core')['resolveRef']
const resolveUnref: typeof import('@vueuse/core')['resolveUnref'] const resolveUnref: typeof import('@vueuse/core')['resolveUnref']
const setActivePinia: typeof import('pinia')['setActivePinia'] const setActivePinia: typeof import('pinia')['setActivePinia']
@@ -214,6 +213,7 @@ declare global {
const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark'] const usePreferredDark: typeof import('@vueuse/core')['usePreferredDark']
const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages'] const usePreferredLanguages: typeof import('@vueuse/core')['usePreferredLanguages']
const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion'] const usePreferredReducedMotion: typeof import('@vueuse/core')['usePreferredReducedMotion']
const usePrevious: typeof import('@vueuse/core')['usePrevious']
const useRafFn: typeof import('@vueuse/core')['useRafFn'] const useRafFn: typeof import('@vueuse/core')['useRafFn']
const useRefHistory: typeof import('@vueuse/core')['useRefHistory'] const useRefHistory: typeof import('@vueuse/core')['useRefHistory']
const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver'] const useResizeObserver: typeof import('@vueuse/core')['useResizeObserver']
@@ -282,3 +282,8 @@ declare global {
const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter'] const watchWithFilter: typeof import('@vueuse/core')['watchWithFilter']
const whenever: typeof import('@vueuse/core')['whenever'] const whenever: typeof import('@vueuse/core')['whenever']
} }
// for type re-export
declare global {
// @ts-ignore
export type { Component,ComponentPublicInstance,ComputedRef,InjectionKey,PropType,Ref,VNode } from 'vue'
}

View File

@@ -20,15 +20,12 @@ type Sample = Problem["samples"][number] & {
const props = defineProps<Props>() const props = defineProps<Props>()
const route = useRoute() const route = useRoute()
const contestID = <string>route.params.contestID
const theme = useThemeVars() const theme = useThemeVars()
const style = computed(() => "color: " + theme.value.primaryColor) const style = computed(() => "color: " + theme.value.primaryColor)
const solved = ref(false) const solved = ref(false)
onMounted(() => { onMounted(() => {
if (contestID) { if (route.params.contestID) checkSubmission()
checkSubmisson()
}
}) })
const samples = ref<Sample[]>( const samples = ref<Sample[]>(
@@ -50,7 +47,7 @@ const disabled = computed(
) )
) )
async function checkSubmisson() { async function checkSubmission() {
const res = await submissionExists(props.problem.id) const res = await submissionExists(props.problem.id)
solved.value = res.data solved.value = res.data
} }
@@ -97,7 +94,7 @@ const type = (status: ProblemStatus) =>
<template> <template>
<n-alert <n-alert
v-if="problem.my_status === 0 || (contestID && solved)" v-if="problem.my_status === 0 || (route.params.contestID && solved)"
type="success" type="success"
title="🎉 本 题 已 经 被 你 解 决 啦" title="🎉 本 题 已 经 被 你 解 决 啦"
/> />

View File

@@ -166,7 +166,6 @@ function rowProps(row: ProblemFiltered) {
class="select" class="select"
v-model:value="query.tag" v-model:value="query.tag"
:options="tagOptions" :options="tagOptions"
clearable
/> />
</n-form-item> </n-form-item>
<n-form-item label="搜索"> <n-form-item label="搜索">

View File

@@ -67,7 +67,7 @@ onMounted(init)
</n-alert> </n-alert>
<n-card embedded> <n-card embedded>
<n-space justify="end"> <n-space justify="end">
<n-button @click="handleCopy(submission!.code)"> <n-button type="primary" @click="handleCopy(submission!.code)">
{{ copied ? "已复制" : "复制代码" }} {{ copied ? "已复制" : "复制代码" }}
</n-button> </n-button>
</n-space> </n-space>
@@ -78,7 +78,11 @@ onMounted(init)
show-line-numbers show-line-numbers
/> />
</n-card> </n-card>
<n-data-table :columns="columns" :data="submission.info.data" /> <n-data-table
v-if="submission.info"
:columns="columns"
:data="submission.info.data"
/>
</n-space> </n-space>
</template> </template>

View File

@@ -118,28 +118,33 @@ const columns = computed(() => {
{ {
title: "提交时间", title: "提交时间",
key: "create_time", key: "create_time",
width: 180, width: 200,
render: (row) => render: (row) =>
parseTime( parseTime(
row.create_time, row.create_time,
isDesktop ? "YYYY-M-D hh:mm:ss" : "M-D hh:mm" isDesktop ? "YYYY-MM-DD hh:mm:ss" : "M-D hh:mm"
), ),
}, },
{ {
title: "编号", title: "编号",
key: "id", key: "id",
render: (row) => render: (row) => {
h( if (row.show_link) {
NButton, return h(
{ NButton,
text: true, {
type: "info", text: true,
onClick: () => { type: "info",
if (row.show_link) router.push("/submission/" + row.id) onClick: () => {
router.push("/submission/" + row.id)
},
}, },
}, () => row.id.slice(0, 12)
() => row.id.slice(0, 12) )
), } else {
return row.id.slice(0, 12)
}
},
}, },
{ {
title: "状态", title: "状态",
@@ -157,7 +162,18 @@ const columns = computed(() => {
{ {
text: true, text: true,
type: "info", type: "info",
onClick: () => router.push("/problem/" + row.problem), onClick: () => {
if (route.name === "contest submissions") {
router.push({
name: "contest problem",
params: {
problemID: row.problem,
},
})
} else {
router.push("/problem/" + row.problem)
}
},
}, },
() => row.problem () => row.problem
), ),
@@ -215,7 +231,7 @@ const columns = computed(() => {
v-model:value="query.username" v-model:value="query.username"
@change="search" @change="search"
clearable clearable
placeholder="输入后回车或点击搜索" placeholder="输入用户后回车或点击搜索"
/> />
</n-form-item> </n-form-item>
<n-form-item> <n-form-item>

View File

@@ -63,7 +63,7 @@ function goSignup() {
v-model:value="form.username" v-model:value="form.username"
autofocus autofocus
clearable clearable
name="username" name="login username"
/> />
</n-form-item> </n-form-item>
<n-form-item label="密码" path="password"> <n-form-item label="密码" path="password">
@@ -71,7 +71,7 @@ function goSignup() {
v-model:value="form.password" v-model:value="form.password"
clearable clearable
type="password" type="password"
name="password" name="login password"
@change="submit" @change="submit"
/> />
</n-form-item> </n-form-item>

View File

@@ -36,14 +36,14 @@ function submit() {}
v-model:value="form.username" v-model:value="form.username"
autofocus autofocus
clearable clearable
name="username" name="signup username"
/> />
</n-form-item> </n-form-item>
<n-form-item label="邮箱" path="email"> <n-form-item label="邮箱" path="email">
<n-input <n-input
v-model:value="form.email" v-model:value="form.email"
clearable clearable
name="email" name="signup email"
@change="submit" @change="submit"
/> />
</n-form-item> </n-form-item>
@@ -52,7 +52,7 @@ function submit() {}
v-model:value="form.password" v-model:value="form.password"
clearable clearable
type="password" type="password"
name="password" name="signup password"
/> />
</n-form-item> </n-form-item>
<n-form-item label="确认密码" path="password"> <n-form-item label="确认密码" path="password">
@@ -60,7 +60,7 @@ function submit() {}
v-model:value="form.passwordAgain" v-model:value="form.passwordAgain"
clearable clearable
type="password" type="password"
name="passwordAgain" name="signup password again"
/> />
</n-form-item> </n-form-item>
<n-alert v-if="msg" type="error" :show-icon="false"> {{ msg }}</n-alert> <n-alert v-if="msg" type="error" :show-icon="false"> {{ msg }}</n-alert>