Files
ojnext/src/oj/problem/components/ProblemSubmission.vue
yuetsh b14316b919
Some checks failed
Deploy / deploy (push) Has been cancelled
batch update
2025-10-08 00:46:49 +08:00

293 lines
7.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<script lang="ts" setup>
import { NButton } from "naive-ui"
import { getSubmissions, getRankOfProblem } from "oj/api"
import Pagination from "shared/components/Pagination.vue"
import SubmissionResultTag from "shared/components/SubmissionResultTag.vue"
import { useUserStore } from "shared/store/user"
import { LANGUAGE_SHOW_VALUE } from "utils/constants"
import { parseTime } from "utils/functions"
import { renderTableTitle } from "utils/renders"
import { Submission } from "utils/types"
import SubmissionDetail from "oj/submission/detail.vue"
import { useBreakpoints } from "shared/composables/breakpoints"
const userStore = useUserStore()
const route = useRoute()
const router = useRouter()
const { isDesktop } = useBreakpoints()
// 弹框状态管理
const [codePanelVisible, toggleCodePanel] = useToggle(false)
const submissionID = ref("")
const problemID = ref("")
// 显示代码弹框
function showCodePanel(id: string, problem: string) {
submissionID.value = id
problemID.value = problem
toggleCodePanel(true)
}
const columns: DataTableColumn<Submission>[] = [
{
title: renderTableTitle("提交时间", "noto:seven-oclock"),
key: "create_time",
width: 200,
render: (row) => parseTime(row.create_time, "YYYY-MM-DD HH:mm:ss"),
},
{
title: renderTableTitle("编号", "fluent-emoji-flat:input-numbers"),
key: "id",
minWidth: 160,
render: (row) => {
return h(
NButton,
{
text: true,
type: "info",
onClick: () => {
showCodePanel(row.id, <string>route.params.problemID ?? "")
},
},
() => row.id.slice(0, 12),
)
},
},
{
title: renderTableTitle("状态", "streamline-emojis:panda-face"),
key: "status",
width: 140,
render: (row) => h(SubmissionResultTag, { result: row.result }),
},
{
title: renderTableTitle(
"语言",
"streamline-emojis:globe-showing-europe-africa",
),
key: "language",
width: 100,
render: (row) => LANGUAGE_SHOW_VALUE[row.language],
},
]
const class_name = ref("")
const rank = ref(-1)
const class_ac_count = ref(0)
const all_ac_count = ref(0)
const loading = ref(false)
const submissions = ref<Submission[]>([])
const total = ref(0)
const query = reactive({
limit: 10,
page: 1,
})
const errorMsg = computed(() => {
if (!userStore.isAuthed) return "请先登录"
else if (!userStore.showSubmissions) return "提交列表已被管理员关闭"
else return ""
})
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
}
async function getRankOfThisProblem() {
loading.value = true
const res = await getRankOfProblem(<string>route.params.problemID ?? "")
loading.value = false
class_name.value = res.data.class_name
rank.value = res.data.rank
class_ac_count.value = res.data.class_ac_count
all_ac_count.value = res.data.all_ac_count
}
onMounted(() => {
listSubmissions()
if (route.name === "problem") {
getRankOfThisProblem()
}
})
watch(query, listSubmissions)
</script>
<template>
<n-alert
class="tip"
type="error"
v-if="!userStore.showSubmissions || !userStore.isAuthed"
:title="errorMsg"
/>
<template v-if="!loading && route.name === 'problem' && userStore.isAuthed">
<template v-if="class_name">
<n-alert class="tip" type="success" :show-icon="false" v-if="rank !== -1">
<template #header>
<n-flex align="center">
<span>
本道题你在班上排名第 <b>{{ rank }}</b
>你们班共有 <b>{{ class_ac_count }}</b> 人答案正确
</span>
<n-button
secondary
v-if="userStore.showSubmissions"
@click="
router.push({
name: 'submissions',
query: {
problem: route.params.problemID,
result: '0',
page: 1,
limit: 10,
username: 'ks' + class_name,
},
})
"
>
查看
</n-button>
</n-flex>
</template>
</n-alert>
<n-alert
class="tip"
type="error"
:show-icon="false"
v-if="rank === -1 && class_ac_count > 0"
>
<template #header>
<n-flex align="center">
<span>
本道题你还没有解决你们班共有
<b>{{ class_ac_count }}</b> 人答案正确
</span>
<n-button
v-if="userStore.showSubmissions"
secondary
@click="
router.push({
name: 'submissions',
query: {
problem: route.params.problemID,
result: '0',
page: 1,
limit: 10,
username: 'ks' + class_name,
},
})
"
>
查看
</n-button>
</n-flex>
</template>
</n-alert>
</template>
<template v-else>
<n-alert class="tip" type="success" :show-icon="false" v-if="rank !== -1">
<template #header>
<n-flex align="center">
<span>
本道题你在全服排名第 <b>{{ rank }}</b
>全服共有 <b>{{ all_ac_count }}</b> 人答案正确
</span>
<n-button
secondary
v-if="userStore.showSubmissions"
@click="
router.push({
name: 'submissions',
query: {
problem: route.params.problemID,
result: '0',
page: 1,
limit: 10,
},
})
"
>
查看
</n-button>
</n-flex>
</template>
</n-alert>
<n-alert
class="tip"
type="error"
:show-icon="false"
v-if="rank === -1 && all_ac_count > 0"
>
<template #header>
<n-flex align="center">
<span>
本道题你还没有解决全服共有 <b>{{ all_ac_count }}</b> 人答案正确
</span>
<n-button
v-if="userStore.showSubmissions"
secondary
@click="
router.push({
name: 'submissions',
query: {
problem: route.params.problemID,
result: '0',
page: 1,
limit: 10,
},
})
"
>
查看
</n-button>
</n-flex>
</template>
</n-alert>
</template>
</template>
<template v-if="userStore.showSubmissions && userStore.isAuthed">
<n-data-table
v-if="submissions.length > 0"
striped
:columns="columns"
:data="submissions"
/>
<Pagination
:total="total"
v-model:limit="query.limit"
v-model:page="query.page"
/>
</template>
<!-- 代码详情弹框 -->
<n-modal
v-model:show="codePanelVisible"
preset="card"
:style="{ maxWidth: isDesktop && '70vw', maxHeight: '80vh' }"
:content-style="{ overflow: 'auto' }"
title="代码详情"
>
<SubmissionDetail
:problemID="problemID"
:submissionID="submissionID"
hideList
/>
</n-modal>
</template>
<style scoped>
.tip {
margin-bottom: 16px;
}
</style>