add access.
This commit is contained in:
94
package-lock.json
generated
94
package-lock.json
generated
@@ -11,7 +11,7 @@
|
||||
"@element-plus/icons-vue": "^2.0.10",
|
||||
"@monaco-editor/loader": "^1.3.2",
|
||||
"@vueuse/core": "^9.11.1",
|
||||
"axios": "1.2.3",
|
||||
"axios": "1.2.5",
|
||||
"chart.js": "^4.2.0",
|
||||
"copy-text-to-clipboard": "^3.0.1",
|
||||
"date-fns": "^2.29.3",
|
||||
@@ -31,8 +31,8 @@
|
||||
"monaco-editor": "^0.34.1",
|
||||
"prettier": "^2.8.3",
|
||||
"typescript": "^4.9.4",
|
||||
"unplugin-auto-import": "^0.12.1",
|
||||
"unplugin-icons": "^0.15.1",
|
||||
"unplugin-auto-import": "^0.12.2",
|
||||
"unplugin-icons": "^0.15.2",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
"vite": "^4.0.4",
|
||||
"vite-plugin-vue-markdown": "^0.22.2",
|
||||
@@ -463,9 +463,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@iconify/utils": {
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.0.12.tgz",
|
||||
"integrity": "sha512-hhUyt1/k5RRhfcW/PRRdBw8e1ACehJT5QEZJRm7HnkCiUx11/0ccLr7K0OMlPSwjnfYcBS2gAUD3EpmL0iJCkQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.1.0.tgz",
|
||||
"integrity": "sha512-ouXv1hQfOKq4k3wxQ2OJBYQ2gXBMeFoUCIiORmuUVUNlSq9oOTzQBF3jpFRb0+/P0bnV+RIoHcbZKufZTlJ16g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@antfu/install-pkg": "^0.1.1",
|
||||
@@ -970,9 +970,9 @@
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"node_modules/axios": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.2.3.tgz",
|
||||
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.2.5.tgz",
|
||||
"integrity": "sha512-9pU/8mmjSSOb4CXVsvGIevN+MlO/t9OWtKadTaLuN85Gge3HGorUckgp8A/2FH4V4hJ7JuQ3LIeI7KAV9ITZrQ==",
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
@@ -1902,9 +1902,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/pathe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.0.0.tgz",
|
||||
"integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.0.tgz",
|
||||
"integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/picocolors": {
|
||||
@@ -2276,9 +2276,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/unimport": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-1.3.0.tgz",
|
||||
"integrity": "sha512-fOkrdxglsHd428yegH0wPH/6IfaSdDeMXtdRGn6en/ccyzc2aaoxiUTMrJyc6Bu+xoa18RJRPMfLUHEzjz8atw==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-2.0.1.tgz",
|
||||
"integrity": "sha512-hMeDspGrEcocahicTr0AQYUGes24FvJtOxk9QEjeEOGv+n1EdpsDiT6z8t209PWhemPg0T5w/ooTVhup2GdrFA==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@rollup/pluginutils": "^5.0.2",
|
||||
@@ -2287,7 +2287,7 @@
|
||||
"local-pkg": "^0.4.3",
|
||||
"magic-string": "^0.27.0",
|
||||
"mlly": "^1.1.0",
|
||||
"pathe": "^1.0.0",
|
||||
"pathe": "^1.1.0",
|
||||
"pkg-types": "^1.0.1",
|
||||
"scule": "^1.0.0",
|
||||
"strip-literal": "^1.0.0",
|
||||
@@ -2307,16 +2307,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/unplugin-auto-import": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.12.1.tgz",
|
||||
"integrity": "sha512-J/3ZORq5YGKG+8D5vLLOgqaHNK77izlVN07mQ752yRLqBNDbJiwPRSnUwwYqH5N6rDay1SqnJCHaUdbJ9QMI2w==",
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.12.2.tgz",
|
||||
"integrity": "sha512-hC4w0GZjPjmLtrxV0u10XO350V9eCtQyEyifXr7B9UGD7SvbbIvKuOcHt58Zd4FAqZJXKWoXkpr9mdhBp85Usw==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@antfu/utils": "^0.7.2",
|
||||
"@rollup/pluginutils": "^5.0.2",
|
||||
"local-pkg": "^0.4.2",
|
||||
"local-pkg": "^0.4.3",
|
||||
"magic-string": "^0.27.0",
|
||||
"unimport": "^1.0.2",
|
||||
"unimport": "^2.0.1",
|
||||
"unplugin": "^1.0.1"
|
||||
},
|
||||
"engines": {
|
||||
@@ -2332,14 +2332,14 @@
|
||||
}
|
||||
},
|
||||
"node_modules/unplugin-icons": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.15.1.tgz",
|
||||
"integrity": "sha512-d4Gc8A4qIJYIXKueltTwoHfR3Cxsdfnmz8lSN5dsITEyai5tdb0uWpbQkn3j9HUlLDSB1ybdQIf5CItxJT3UDw==",
|
||||
"version": "0.15.2",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.15.2.tgz",
|
||||
"integrity": "sha512-oWTTdLMuqfEYfZcko+KZHDEOIsqT4OeyJB1e4U7luCOo9gto/JLyHkqfbqjmjkjdQqA3DNHS18WOKh5esqQM5g==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@antfu/install-pkg": "^0.1.1",
|
||||
"@antfu/utils": "^0.7.2",
|
||||
"@iconify/utils": "^2.0.9",
|
||||
"@iconify/utils": "^2.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"kolorist": "^1.6.0",
|
||||
"local-pkg": "^0.4.2",
|
||||
@@ -2827,9 +2827,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@iconify/utils": {
|
||||
"version": "2.0.12",
|
||||
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.0.12.tgz",
|
||||
"integrity": "sha512-hhUyt1/k5RRhfcW/PRRdBw8e1ACehJT5QEZJRm7HnkCiUx11/0ccLr7K0OMlPSwjnfYcBS2gAUD3EpmL0iJCkQ==",
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-2.1.0.tgz",
|
||||
"integrity": "sha512-ouXv1hQfOKq4k3wxQ2OJBYQ2gXBMeFoUCIiORmuUVUNlSq9oOTzQBF3jpFRb0+/P0bnV+RIoHcbZKufZTlJ16g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@antfu/install-pkg": "^0.1.1",
|
||||
@@ -3268,9 +3268,9 @@
|
||||
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
|
||||
},
|
||||
"axios": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.2.3.tgz",
|
||||
"integrity": "sha512-pdDkMYJeuXLZ6Xj/Q5J3Phpe+jbGdsSzlQaFVkMQzRUL05+6+tetX8TV3p4HrU4kzuO9bt+io/yGQxuyxA/xcw==",
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmmirror.com/axios/-/axios-1.2.5.tgz",
|
||||
"integrity": "sha512-9pU/8mmjSSOb4CXVsvGIevN+MlO/t9OWtKadTaLuN85Gge3HGorUckgp8A/2FH4V4hJ7JuQ3LIeI7KAV9ITZrQ==",
|
||||
"requires": {
|
||||
"follow-redirects": "^1.15.0",
|
||||
"form-data": "^4.0.0",
|
||||
@@ -3990,9 +3990,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"pathe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.0.0.tgz",
|
||||
"integrity": "sha512-nPdMG0Pd09HuSsr7QOKUXO2Jr9eqaDiZvDwdyIhNG5SHYujkQHYKDfGQkulBxvbDHz8oHLsTgKN86LSwYzSHAg==",
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmmirror.com/pathe/-/pathe-1.1.0.tgz",
|
||||
"integrity": "sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w==",
|
||||
"dev": true
|
||||
},
|
||||
"picocolors": {
|
||||
@@ -4270,9 +4270,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"unimport": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-1.3.0.tgz",
|
||||
"integrity": "sha512-fOkrdxglsHd428yegH0wPH/6IfaSdDeMXtdRGn6en/ccyzc2aaoxiUTMrJyc6Bu+xoa18RJRPMfLUHEzjz8atw==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmmirror.com/unimport/-/unimport-2.0.1.tgz",
|
||||
"integrity": "sha512-hMeDspGrEcocahicTr0AQYUGes24FvJtOxk9QEjeEOGv+n1EdpsDiT6z8t209PWhemPg0T5w/ooTVhup2GdrFA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rollup/pluginutils": "^5.0.2",
|
||||
@@ -4281,7 +4281,7 @@
|
||||
"local-pkg": "^0.4.3",
|
||||
"magic-string": "^0.27.0",
|
||||
"mlly": "^1.1.0",
|
||||
"pathe": "^1.0.0",
|
||||
"pathe": "^1.1.0",
|
||||
"pkg-types": "^1.0.1",
|
||||
"scule": "^1.0.0",
|
||||
"strip-literal": "^1.0.0",
|
||||
@@ -4301,28 +4301,28 @@
|
||||
}
|
||||
},
|
||||
"unplugin-auto-import": {
|
||||
"version": "0.12.1",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.12.1.tgz",
|
||||
"integrity": "sha512-J/3ZORq5YGKG+8D5vLLOgqaHNK77izlVN07mQ752yRLqBNDbJiwPRSnUwwYqH5N6rDay1SqnJCHaUdbJ9QMI2w==",
|
||||
"version": "0.12.2",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-auto-import/-/unplugin-auto-import-0.12.2.tgz",
|
||||
"integrity": "sha512-hC4w0GZjPjmLtrxV0u10XO350V9eCtQyEyifXr7B9UGD7SvbbIvKuOcHt58Zd4FAqZJXKWoXkpr9mdhBp85Usw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@antfu/utils": "^0.7.2",
|
||||
"@rollup/pluginutils": "^5.0.2",
|
||||
"local-pkg": "^0.4.2",
|
||||
"local-pkg": "^0.4.3",
|
||||
"magic-string": "^0.27.0",
|
||||
"unimport": "^1.0.2",
|
||||
"unimport": "^2.0.1",
|
||||
"unplugin": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"unplugin-icons": {
|
||||
"version": "0.15.1",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.15.1.tgz",
|
||||
"integrity": "sha512-d4Gc8A4qIJYIXKueltTwoHfR3Cxsdfnmz8lSN5dsITEyai5tdb0uWpbQkn3j9HUlLDSB1ybdQIf5CItxJT3UDw==",
|
||||
"version": "0.15.2",
|
||||
"resolved": "https://registry.npmmirror.com/unplugin-icons/-/unplugin-icons-0.15.2.tgz",
|
||||
"integrity": "sha512-oWTTdLMuqfEYfZcko+KZHDEOIsqT4OeyJB1e4U7luCOo9gto/JLyHkqfbqjmjkjdQqA3DNHS18WOKh5esqQM5g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@antfu/install-pkg": "^0.1.1",
|
||||
"@antfu/utils": "^0.7.2",
|
||||
"@iconify/utils": "^2.0.9",
|
||||
"@iconify/utils": "^2.1.0",
|
||||
"debug": "^4.3.4",
|
||||
"kolorist": "^1.6.0",
|
||||
"local-pkg": "^0.4.2",
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
"@element-plus/icons-vue": "^2.0.10",
|
||||
"@monaco-editor/loader": "^1.3.2",
|
||||
"@vueuse/core": "^9.11.1",
|
||||
"axios": "1.2.3",
|
||||
"axios": "1.2.5",
|
||||
"chart.js": "^4.2.0",
|
||||
"copy-text-to-clipboard": "^3.0.1",
|
||||
"date-fns": "^2.29.3",
|
||||
@@ -33,8 +33,8 @@
|
||||
"monaco-editor": "^0.34.1",
|
||||
"prettier": "^2.8.3",
|
||||
"typescript": "^4.9.4",
|
||||
"unplugin-auto-import": "^0.12.1",
|
||||
"unplugin-icons": "^0.15.1",
|
||||
"unplugin-auto-import": "^0.12.2",
|
||||
"unplugin-icons": "^0.15.2",
|
||||
"unplugin-vue-components": "^0.22.12",
|
||||
"vite": "^4.0.4",
|
||||
"vite-plugin-vue-markdown": "^0.22.2",
|
||||
|
||||
1
src/components.d.ts
vendored
1
src/components.d.ts
vendored
@@ -13,6 +13,7 @@ declare module '@vue/runtime-core' {
|
||||
IEpLock: typeof import('~icons/ep/lock')['default']
|
||||
NAlert: typeof import('naive-ui')['NAlert']
|
||||
NButton: typeof import('naive-ui')['NButton']
|
||||
NButtonGroup: typeof import('naive-ui')['NButtonGroup']
|
||||
NCard: typeof import('naive-ui')['NCard']
|
||||
NCode: typeof import('naive-ui')['NCode']
|
||||
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
|
||||
|
||||
@@ -112,9 +112,11 @@ export function getContestAccess(id: string) {
|
||||
|
||||
export function checkContestPassword(contestID: string, password: string) {
|
||||
return http.post("contest/password", {
|
||||
data: {
|
||||
contest_id: contestID,
|
||||
password,
|
||||
},
|
||||
contest_id: contestID,
|
||||
password,
|
||||
})
|
||||
}
|
||||
|
||||
export function getContestProblem(contestID: string) {
|
||||
return http.get("contest/problem", { params: { contest_id: contestID } })
|
||||
}
|
||||
|
||||
20
src/oj/contest/components/ContestType.vue
Normal file
20
src/oj/contest/components/ContestType.vue
Normal file
@@ -0,0 +1,20 @@
|
||||
<script setup lang="ts">
|
||||
import { Contest } from "~/utils/types"
|
||||
import { ContestType } from "~/utils/constants"
|
||||
|
||||
interface Props {
|
||||
contest: Contest
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const isPrivate = computed(
|
||||
() => props.contest.contest_type === ContestType.private
|
||||
)
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-tag :type="isPrivate ? 'error' : 'default'">
|
||||
{{ isPrivate ? "需要密码" : "公开" }}
|
||||
</n-tag>
|
||||
</template>
|
||||
@@ -1,42 +1,129 @@
|
||||
<script setup lang="ts">
|
||||
import { Contest } from "utils/types"
|
||||
import { Contest, Problem } from "utils/types"
|
||||
import { CONTEST_STATUS, ContestStatus, ContestType } from "utils/constants"
|
||||
import { parseTime } from "utils/functions"
|
||||
import { getContest, getContestAccess } from "../api"
|
||||
import { getACRate, parseTime } from "utils/functions"
|
||||
import {
|
||||
getContest,
|
||||
getContestAccess,
|
||||
getContestProblem,
|
||||
checkContestPassword,
|
||||
} from "../api"
|
||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||
import ContestTypeVue from "./components/ContestType.vue"
|
||||
import { DataTableColumn } from "naive-ui"
|
||||
import { useUserStore } from "~/shared/store/user"
|
||||
|
||||
const props = defineProps<{
|
||||
contestID: string
|
||||
}>()
|
||||
const router = useRouter()
|
||||
const userStore = useUserStore()
|
||||
const contest = ref<Contest>()
|
||||
const problems = ref<Problem[]>([])
|
||||
const password = ref("")
|
||||
const [access, toggleAccsess] = useToggle()
|
||||
|
||||
async function init() {
|
||||
const res = await getContest(props.contestID)
|
||||
contest.value = res.data
|
||||
if (contest.value?.contest_type === ContestType.private) {
|
||||
const res = await getContestAccess(props.contestID)
|
||||
// TODO: 这里 access 的逻辑不清楚
|
||||
console.log(res.data)
|
||||
toggleAccsess(res.data.access)
|
||||
}
|
||||
getProblems()
|
||||
}
|
||||
|
||||
async function getProblems() {
|
||||
try {
|
||||
const res = await getContestProblem(props.contestID)
|
||||
problems.value = res.data
|
||||
} catch (err) {
|
||||
toggleAccsess(false)
|
||||
}
|
||||
}
|
||||
|
||||
async function checkPassword() {
|
||||
try {
|
||||
const res = await checkContestPassword(props.contestID, password.value)
|
||||
toggleAccsess(res.data)
|
||||
if (res.data) {
|
||||
getProblems()
|
||||
}
|
||||
} catch (err) {
|
||||
toggleAccsess(false)
|
||||
}
|
||||
}
|
||||
onMounted(init)
|
||||
const isContestAdmin = computed(
|
||||
() =>
|
||||
userStore.isSuperAdmin ||
|
||||
(userStore.isAuthed && contest.value?.created_by.id === userStore.user.id)
|
||||
)
|
||||
|
||||
const passwordFormVisible = computed(
|
||||
() =>
|
||||
contest.value?.contest_type === ContestType.private &&
|
||||
!access.value &&
|
||||
!isContestAdmin
|
||||
)
|
||||
|
||||
const problemsColumns: DataTableColumn<Problem>[] = [
|
||||
{ title: "编号", key: "_id", width: 100 },
|
||||
{ title: "标题", key: "title" },
|
||||
{ title: "总提交数", key: "submission_number", width: 100 },
|
||||
{
|
||||
title: "通过率",
|
||||
key: "rate",
|
||||
width: 100,
|
||||
render: (row) => getACRate(row.accepted_number, row.submission_number),
|
||||
},
|
||||
]
|
||||
|
||||
function rowProps(row: Problem) {
|
||||
return {
|
||||
style: "cursor: pointer",
|
||||
onClick() {
|
||||
router.push(`/contest/${props.contestID}/problem/${row._id}`)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<n-card v-if="contest">
|
||||
<template #header>
|
||||
<n-space align="center">
|
||||
<n-tag :type="CONTEST_STATUS[contest.status]['type']">
|
||||
{{ CONTEST_STATUS[contest.status]["name"] }}
|
||||
</n-tag>
|
||||
<span>{{ contest.title }}</span>
|
||||
<n-icon
|
||||
v-if="contest.contest_type === ContestType.private"
|
||||
class="lockIcon"
|
||||
>
|
||||
<i-ep-lock />
|
||||
</n-icon>
|
||||
</n-space>
|
||||
</template>
|
||||
<div v-if="contest">
|
||||
<n-space align="center">
|
||||
<n-tag :type="CONTEST_STATUS[contest.status]['type']">
|
||||
{{ CONTEST_STATUS[contest.status]["name"] }}
|
||||
</n-tag>
|
||||
<h2 class="contestTitle">{{ contest.title }}</h2>
|
||||
<n-icon
|
||||
v-if="contest.contest_type === ContestType.private"
|
||||
class="lockIcon"
|
||||
>
|
||||
<i-ep-lock />
|
||||
</n-icon>
|
||||
</n-space>
|
||||
<div v-html="contest.description"></div>
|
||||
<n-form inline label-placement="left">
|
||||
<n-form-item v-if="passwordFormVisible" label="需要输入密码才能看到题目">
|
||||
<n-input
|
||||
name="ContestPassword"
|
||||
type="password"
|
||||
v-model:value="password"
|
||||
/>
|
||||
</n-form-item>
|
||||
<n-form-item v-if="passwordFormVisible">
|
||||
<n-button @click="checkPassword" :disabled="!password">确认</n-button>
|
||||
</n-form-item>
|
||||
<n-form-item>
|
||||
<n-space>
|
||||
<n-button type="primary">比赛题目</n-button>
|
||||
<n-button>提交信息</n-button>
|
||||
<n-button>比赛排名</n-button>
|
||||
<n-button>管理员助手</n-button>
|
||||
</n-space>
|
||||
</n-form-item>
|
||||
</n-form>
|
||||
<n-descriptions bordered :column="isDesktop ? 5 : 2">
|
||||
<n-descriptions-item
|
||||
:span="isDesktop ? 1 : 2"
|
||||
@@ -63,17 +150,34 @@ onMounted(init)
|
||||
{{ parseTime(contest.end_time, "YYYY年M月D日 hh:mm:ss") }}
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="比赛类型">
|
||||
{{ contest.contest_type === ContestType.private ? "需要密码" : "公开" }}
|
||||
<ContestTypeVue :contest="contest" />
|
||||
</n-descriptions-item>
|
||||
<n-descriptions-item label="发起人">
|
||||
{{ contest.created_by.username }}
|
||||
</n-descriptions-item>
|
||||
</n-descriptions>
|
||||
</n-card>
|
||||
</div>
|
||||
<n-data-table
|
||||
striped
|
||||
size="small"
|
||||
class="problems"
|
||||
:data="problems"
|
||||
:columns="problemsColumns"
|
||||
:row-props="rowProps"
|
||||
v-if="problems?.length"
|
||||
></n-data-table>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.contestTitle {
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
}
|
||||
.lockIcon {
|
||||
transform: translateY(2px);
|
||||
}
|
||||
|
||||
.problems {
|
||||
margin-top: 24px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -132,7 +132,9 @@ const columns = computed(() => {
|
||||
{
|
||||
text: true,
|
||||
type: "info",
|
||||
onClick: () => router.push("/submission/" + row.id),
|
||||
onClick: () => {
|
||||
if (row.show_link) router.push("/submission/" + row.id)
|
||||
},
|
||||
},
|
||||
() => row.id.slice(0, 12)
|
||||
),
|
||||
|
||||
@@ -140,6 +140,7 @@ export interface Submission {
|
||||
info: Info
|
||||
language: LANGUAGE
|
||||
shared: boolean
|
||||
show_link: boolean
|
||||
statistic_info: {
|
||||
score?: number
|
||||
err_info?: string
|
||||
|
||||
Reference in New Issue
Block a user