problem submission tab,
This commit is contained in:
100
src/oj/problem/components/ProblemSubmission.vue
Normal file
100
src/oj/problem/components/ProblemSubmission.vue
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
<script lang="ts" setup>
|
||||||
|
import { useUserStore } from "~/shared/store/user"
|
||||||
|
import { Submission } from "~/utils/types"
|
||||||
|
import { parseTime } from "~/utils/functions"
|
||||||
|
import { LANGUAGE_SHOW_VALUE } from "~/utils/constants"
|
||||||
|
import { getSubmissions } from "~/oj/api"
|
||||||
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
|
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
|
||||||
|
import Pagination from "~/shared/Pagination.vue"
|
||||||
|
import { NButton } from "naive-ui"
|
||||||
|
|
||||||
|
const userStore = useUserStore()
|
||||||
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
|
const columns: DataTableColumn<Submission>[] = [
|
||||||
|
{
|
||||||
|
title: "提交时间",
|
||||||
|
key: "create_time",
|
||||||
|
width: 200,
|
||||||
|
render: (row) =>
|
||||||
|
parseTime(
|
||||||
|
row.create_time,
|
||||||
|
isDesktop ? "YYYY-MM-DD hh:mm:ss" : "M-D hh:mm"
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "编号",
|
||||||
|
key: "id",
|
||||||
|
minWidth: 160,
|
||||||
|
render: (row) => {
|
||||||
|
if (row.show_link) {
|
||||||
|
return h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
type: "info",
|
||||||
|
onClick: () => {
|
||||||
|
const data = router.resolve("/submission/" + row.id)
|
||||||
|
window.open(data.href, "_blank")
|
||||||
|
},
|
||||||
|
},
|
||||||
|
() => row.id.slice(0, 12)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
return row.id.slice(0, 12)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "状态",
|
||||||
|
key: "status",
|
||||||
|
width: 140,
|
||||||
|
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "语言",
|
||||||
|
key: "language",
|
||||||
|
width: 100,
|
||||||
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
const submissions = ref<Submission[]>([])
|
||||||
|
const total = ref(0)
|
||||||
|
const query = reactive({
|
||||||
|
limit: 10,
|
||||||
|
page: 1,
|
||||||
|
})
|
||||||
|
|
||||||
|
async function listSubmissions() {
|
||||||
|
const offset = query.limit * (query.page - 1)
|
||||||
|
const res = await getSubmissions({
|
||||||
|
...query,
|
||||||
|
myself: "1",
|
||||||
|
offset,
|
||||||
|
problem_id: <string>route.params.problemID ?? "",
|
||||||
|
contest_id: <string>route.params.contestID ?? "",
|
||||||
|
})
|
||||||
|
submissions.value = res.data.results
|
||||||
|
total.value = res.data.total
|
||||||
|
}
|
||||||
|
onMounted(listSubmissions)
|
||||||
|
watch(query, listSubmissions)
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<n-data-table
|
||||||
|
v-if="userStore.isAuthed"
|
||||||
|
striped
|
||||||
|
:columns="columns"
|
||||||
|
:data="submissions"
|
||||||
|
/>
|
||||||
|
<Pagination
|
||||||
|
v-if="userStore.isAuthed"
|
||||||
|
:total="total"
|
||||||
|
v-model:limit="query.limit"
|
||||||
|
v-model:page="query.page"
|
||||||
|
/>
|
||||||
|
<n-alert type="error" v-if="!userStore.isAuthed" title="请先登录" />
|
||||||
|
</template>
|
||||||
@@ -10,6 +10,9 @@ const ProblemContent = defineAsyncComponent(
|
|||||||
const ProblemInfo = defineAsyncComponent(
|
const ProblemInfo = defineAsyncComponent(
|
||||||
() => import("./components/ProblemInfo.vue")
|
() => import("./components/ProblemInfo.vue")
|
||||||
)
|
)
|
||||||
|
const ProblemSubmission = defineAsyncComponent(
|
||||||
|
() => import("./components/ProblemSubmission.vue")
|
||||||
|
)
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
problemID: string
|
problemID: string
|
||||||
@@ -51,6 +54,9 @@ onBeforeUnmount(() => {
|
|||||||
<n-tab-pane name="info" tab="题目统计">
|
<n-tab-pane name="info" tab="题目统计">
|
||||||
<ProblemInfo />
|
<ProblemInfo />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="submission" tab="我的提交">
|
||||||
|
<ProblemSubmission />
|
||||||
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-scrollbar>
|
</n-scrollbar>
|
||||||
<n-tabs v-else default-value="content" type="segment">
|
<n-tabs v-else default-value="content" type="segment">
|
||||||
@@ -63,6 +69,9 @@ onBeforeUnmount(() => {
|
|||||||
<n-tab-pane name="info" tab="题目统计">
|
<n-tab-pane name="info" tab="题目统计">
|
||||||
<ProblemInfo />
|
<ProblemInfo />
|
||||||
</n-tab-pane>
|
</n-tab-pane>
|
||||||
|
<n-tab-pane name="submission" tab="我的提交">
|
||||||
|
<ProblemSubmission />
|
||||||
|
</n-tab-pane>
|
||||||
</n-tabs>
|
</n-tabs>
|
||||||
</n-gi>
|
</n-gi>
|
||||||
<n-gi v-if="isDesktop">
|
<n-gi v-if="isDesktop">
|
||||||
|
|||||||
@@ -65,16 +65,6 @@ onMounted(init)
|
|||||||
</n-space>
|
</n-space>
|
||||||
</n-alert>
|
</n-alert>
|
||||||
<n-card embedded>
|
<n-card embedded>
|
||||||
<n-space justify="end">
|
|
||||||
<n-button
|
|
||||||
quaternary
|
|
||||||
class="copyBtn"
|
|
||||||
type="primary"
|
|
||||||
@click="handleCopy(submission!.code)"
|
|
||||||
>
|
|
||||||
{{ copied ? "已复制" : "复制代码" }}
|
|
||||||
</n-button>
|
|
||||||
</n-space>
|
|
||||||
<n-code
|
<n-code
|
||||||
class="code"
|
class="code"
|
||||||
:language="LANGUAGE_FORMAT_VALUE[submission.language]"
|
:language="LANGUAGE_FORMAT_VALUE[submission.language]"
|
||||||
@@ -82,6 +72,9 @@ onMounted(init)
|
|||||||
show-line-numbers
|
show-line-numbers
|
||||||
/>
|
/>
|
||||||
</n-card>
|
</n-card>
|
||||||
|
<n-button type="primary" @click="handleCopy(submission!.code)">
|
||||||
|
{{ copied ? "成功复制" : "复制代码" }}
|
||||||
|
</n-button>
|
||||||
<n-data-table
|
<n-data-table
|
||||||
v-if="submission.info && submission.info.data"
|
v-if="submission.info && submission.info.data"
|
||||||
:columns="columns"
|
:columns="columns"
|
||||||
@@ -94,8 +87,4 @@ onMounted(init)
|
|||||||
.code {
|
.code {
|
||||||
font-size: 20px;
|
font-size: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.copyBtn {
|
|
||||||
margin-bottom: 16px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import { Submission } from "utils/types"
|
|||||||
import { adminRejudge, getSubmissions } from "oj/api"
|
import { adminRejudge, getSubmissions } from "oj/api"
|
||||||
import { isDesktop } from "~/shared/composables/breakpoints"
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
||||||
import { useUserStore } from "~/shared/store/user"
|
import { useUserStore } from "~/shared/store/user"
|
||||||
|
import { LANGUAGE_SHOW_VALUE } from "~/utils/constants"
|
||||||
|
|
||||||
interface Query {
|
interface Query {
|
||||||
username: string
|
username: string
|
||||||
@@ -136,9 +137,7 @@ const columns = computed(() => {
|
|||||||
{
|
{
|
||||||
text: true,
|
text: true,
|
||||||
type: "info",
|
type: "info",
|
||||||
onClick: () => {
|
onClick: () => router.push("/submission/" + row.id),
|
||||||
router.push("/submission/" + row.id)
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
() => row.id.slice(0, 12)
|
() => row.id.slice(0, 12)
|
||||||
)
|
)
|
||||||
@@ -191,7 +190,12 @@ const columns = computed(() => {
|
|||||||
width: 120,
|
width: 120,
|
||||||
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
|
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
|
||||||
},
|
},
|
||||||
{ title: "语言", key: "language", width: 120 },
|
{
|
||||||
|
title: "语言",
|
||||||
|
key: "language",
|
||||||
|
width: 120,
|
||||||
|
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "用户",
|
title: "用户",
|
||||||
key: "username",
|
key: "username",
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ const active = computed(() => {
|
|||||||
const path = route.path.split("/")[1] || "problem"
|
const path = route.path.split("/")[1] || "problem"
|
||||||
return !["user", "setting"].includes(path) ? path : ""
|
return !["user", "setting"].includes(path) ? path : ""
|
||||||
})
|
})
|
||||||
|
const hiddenTitle = computed(() => isMobile.value && route.name === "learn")
|
||||||
|
|
||||||
async function handleLogout() {
|
async function handleLogout() {
|
||||||
await logout()
|
await logout()
|
||||||
@@ -98,7 +99,7 @@ function goHome() {
|
|||||||
<template>
|
<template>
|
||||||
<n-space justify="space-between" align="center">
|
<n-space justify="space-between" align="center">
|
||||||
<n-space align="center">
|
<n-space align="center">
|
||||||
<div v-if="isDesktop" class="websiteTitle" @click="goHome">
|
<div v-if="!hiddenTitle" class="websiteTitle" @click="goHome">
|
||||||
{{ configStore.config?.website_name }}
|
{{ configStore.config?.website_name }}
|
||||||
</div>
|
</div>
|
||||||
<n-menu
|
<n-menu
|
||||||
|
|||||||
Reference in New Issue
Block a user