263 lines
6.2 KiB
Vue
263 lines
6.2 KiB
Vue
<script setup lang="ts">
|
|
import { DataTableColumn, SelectOption } from "naive-ui"
|
|
import { NButton } from "naive-ui"
|
|
import SubmissionResultTag from "~/shared/SubmissionResultTag.vue"
|
|
import Pagination from "~/shared/Pagination.vue"
|
|
import {
|
|
submissionMemoryFormat,
|
|
submissionTimeFormat,
|
|
parseTime,
|
|
filterEmptyValue,
|
|
} from "utils/functions"
|
|
import { Submission } from "utils/types"
|
|
import { adminRejudge, getSubmissions } from "oj/api"
|
|
import { isDesktop } from "~/shared/composables/breakpoints"
|
|
import { useUserStore } from "~/shared/store/user"
|
|
|
|
interface Query {
|
|
username: string
|
|
result: string
|
|
limit: number
|
|
page: number
|
|
myself: boolean
|
|
}
|
|
|
|
const route = useRoute()
|
|
const router = useRouter()
|
|
const userStore = useUserStore()
|
|
const message = useMessage()
|
|
|
|
const submissions = ref([])
|
|
const total = ref(0)
|
|
const query = reactive<Query>({
|
|
result: <string>route.query.result ?? "",
|
|
page: parseInt(<string>route.query.page) || 1,
|
|
limit: parseInt(<string>route.query.limit) || 10,
|
|
username: <string>route.query.username ?? "",
|
|
myself: route.query.myself === "1",
|
|
})
|
|
|
|
const options: SelectOption[] = [
|
|
{ label: "全部", value: "" },
|
|
{ label: "答案正确", value: "0" },
|
|
{ label: "答案错误", value: "-1" },
|
|
{ label: "编译失败", value: "-2" },
|
|
{ label: "运行时错误", value: "4" },
|
|
]
|
|
|
|
async function listSubmissions() {
|
|
query.result = <string>route.query.result ?? ""
|
|
query.page = parseInt(<string>route.query.page) || 1
|
|
query.limit = parseInt(<string>route.query.limit) || 10
|
|
query.username = <string>route.query.username ?? ""
|
|
query.myself = route.query.myself === "1"
|
|
|
|
if (query.page < 1) query.page = 1
|
|
const offset = query.limit * (query.page - 1)
|
|
const res = await getSubmissions({
|
|
...query,
|
|
myself: query.myself ? "1" : "0",
|
|
offset,
|
|
problem_id: <string>route.query.problem ?? "",
|
|
contest_id: <string>route.params.contestID ?? "",
|
|
})
|
|
submissions.value = res.data.results
|
|
total.value = res.data.total
|
|
}
|
|
|
|
onMounted(listSubmissions)
|
|
|
|
function routerPush() {
|
|
const newQuery = {
|
|
...query,
|
|
myself: query.myself ? "1" : "0",
|
|
}
|
|
router.push({
|
|
path: route.path,
|
|
query: filterEmptyValue(newQuery),
|
|
})
|
|
}
|
|
|
|
function search(value: string) {
|
|
query.username = value
|
|
}
|
|
|
|
function clear() {
|
|
query.username = ""
|
|
query.myself = false
|
|
query.result = ""
|
|
}
|
|
|
|
async function rejudge(submissionID: string) {
|
|
await adminRejudge(submissionID)
|
|
message.success("重新判分成功")
|
|
listSubmissions()
|
|
}
|
|
|
|
watch(() => query.page, routerPush)
|
|
|
|
watch(
|
|
() => [query.limit, query.myself, query.username, query.result],
|
|
() => {
|
|
query.page = 1
|
|
routerPush()
|
|
}
|
|
)
|
|
|
|
watch(
|
|
() =>
|
|
(route.name === "submissions" || route.name === "contest submissions") &&
|
|
route.query,
|
|
(newVal) => {
|
|
if (newVal) listSubmissions()
|
|
}
|
|
)
|
|
|
|
const columns = computed(() => {
|
|
const res: 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",
|
|
render: (row) => {
|
|
if (row.show_link) {
|
|
return h(
|
|
NButton,
|
|
{
|
|
text: true,
|
|
type: "info",
|
|
onClick: () => {
|
|
router.push("/submission/" + row.id)
|
|
},
|
|
},
|
|
() => row.id.slice(0, 12)
|
|
)
|
|
} else {
|
|
return row.id.slice(0, 12)
|
|
}
|
|
},
|
|
},
|
|
{
|
|
title: "状态",
|
|
key: "status",
|
|
width: 120,
|
|
render: (row) => h(SubmissionResultTag, { result: row.result }),
|
|
},
|
|
{
|
|
title: "题目",
|
|
key: "problem",
|
|
width: 120,
|
|
render: (row) =>
|
|
h(
|
|
NButton,
|
|
{
|
|
text: true,
|
|
type: "info",
|
|
onClick: () => {
|
|
if (route.name === "contest submissions") {
|
|
router.push({
|
|
name: "contest problem",
|
|
params: {
|
|
problemID: row.problem,
|
|
},
|
|
})
|
|
} else {
|
|
router.push("/problem/" + row.problem)
|
|
}
|
|
},
|
|
},
|
|
() => row.problem
|
|
),
|
|
},
|
|
{
|
|
title: "执行耗时",
|
|
key: "time",
|
|
width: 120,
|
|
render: (row) => submissionTimeFormat(row.statistic_info.time_cost),
|
|
},
|
|
{
|
|
title: "占用内存",
|
|
key: "memory",
|
|
width: 120,
|
|
render: (row) => submissionMemoryFormat(row.statistic_info.memory_cost),
|
|
},
|
|
{ title: "语言", key: "language", width: 120 },
|
|
{
|
|
title: "用户",
|
|
key: "username",
|
|
minWidth: 120,
|
|
render: (row) =>
|
|
h(
|
|
NButton,
|
|
{
|
|
text: true,
|
|
type: "info",
|
|
onClick: () => router.push("/user?name=" + row.username),
|
|
},
|
|
() => row.username
|
|
),
|
|
},
|
|
]
|
|
if (!route.params.contestID && userStore.isSuperAdmin) {
|
|
res.push({
|
|
title: "选项",
|
|
key: "rejudge",
|
|
render: (row) =>
|
|
h(
|
|
NButton,
|
|
{
|
|
size: "small",
|
|
tertiary: true,
|
|
onClick: () => rejudge(row.id),
|
|
},
|
|
() => "重新判题"
|
|
),
|
|
})
|
|
}
|
|
return res
|
|
})
|
|
</script>
|
|
<template>
|
|
<n-form :inline="isDesktop" label-placement="left">
|
|
<n-form-item label="提交状态">
|
|
<n-select
|
|
class="select"
|
|
v-model:value="query.result"
|
|
:options="options"
|
|
/>
|
|
</n-form-item>
|
|
<n-form-item label="只看自己">
|
|
<n-switch v-model:value="query.myself" />
|
|
</n-form-item>
|
|
<n-form-item label="搜索用户">
|
|
<n-input @change="search" clearable placeholder="输入后回车或点击搜索" />
|
|
</n-form-item>
|
|
<n-form-item>
|
|
<n-space>
|
|
<n-button @click="search(query.username)">搜索</n-button>
|
|
<n-button @click="clear">重置</n-button>
|
|
</n-space>
|
|
</n-form-item>
|
|
</n-form>
|
|
<n-data-table striped size="small" :columns="columns" :data="submissions" />
|
|
<Pagination
|
|
:total="total"
|
|
v-model:limit="query.limit"
|
|
v-model:page="query.page"
|
|
/>
|
|
</template>
|
|
<style scoped>
|
|
.select {
|
|
width: 120px;
|
|
}
|
|
</style>
|