重构排名
Some checks failed
Deploy / deploy (push) Has been cancelled

This commit is contained in:
2026-01-04 15:53:35 +08:00
parent 2becfedafd
commit e073ef240c
6 changed files with 339 additions and 338 deletions

View File

@@ -1,95 +0,0 @@
<script setup lang="ts">
import { getUserClassRank } from "oj/api"
import { useUserStore } from "shared/store/user"
import { NButton } from "naive-ui"
const userStore = useUserStore()
const router = useRouter()
const message = useMessage()
interface UserRank {
rank: number
username: string
accepted_number: number
submission_number: number
}
const myRank = ref(-1)
const className = ref("")
const data = ref<UserRank[]>([])
const loading = ref(false)
const columns: DataTableColumn<UserRank>[] = [
{
title: "排名",
key: "rank",
width: 100,
align: "center",
},
{
title: "用户名",
key: "username",
width: 200,
render: (row) =>
h(
NButton,
{
text: true,
type: "info",
onClick: () => router.push("/user?name=" + row.username),
},
() => row.username,
),
},
{
title: "AC数",
key: "accepted_number",
width: 120,
align: "center",
},
{
title: "提交数",
key: "submission_number",
width: 120,
align: "center",
},
]
async function init() {
loading.value = true
try {
if (!userStore.user) {
await userStore.getMyProfile()
}
const user = userStore.user
if (!user || !user.class_name) {
message.warning("您没有班级信息")
return
}
const res = await getUserClassRank()
myRank.value = res.data.my_rank
className.value = res.data.class_name
data.value = res.data.ranks
} finally {
loading.value = false
}
}
onMounted(init)
</script>
<template>
<n-flex vertical size="large" v-if="!loading">
<n-h2>我的班级排名</n-h2>
<n-alert v-if="className" type="info">
班级{{ className }} | 我的排名{{
myRank > 0 ? `${myRank}` : "暂无排名"
}}
| 班级总人数{{ data.length }}
</n-alert>
<n-alert v-else type="warning"> 您还没有加入班级 </n-alert>
<n-data-table :data="data" :columns="columns" />
</n-flex>
</template>

View File

@@ -1,144 +0,0 @@
<script setup lang="ts">
import { getClassRank } from "oj/api"
import Pagination from "shared/components/Pagination.vue"
interface ClassRank {
rank: number
class_name: string
user_count: number
total_ac: number
total_submission: number
avg_ac: number
ac_rate: number
}
const data = ref<ClassRank[]>([])
const total = ref(0)
const query = reactive({
limit: 10,
page: 1,
grade: null as number | null,
})
const gradeOptions = [
{ label: "24年级", value: 24 },
{ label: "23年级", value: 23 },
{ label: "22年级", value: 22 },
{ label: "21年级", value: 21 },
{ label: "20年级", value: 20 },
]
const columns: DataTableColumn<ClassRank>[] = [
{
title: "排名",
key: "rank",
width: 100,
titleAlign: "center",
align: "center",
render: (row) => {
if (row.rank === 1) return "🥇"
if (row.rank === 2) return "🥈"
if (row.rank === 3) return "🥉"
return row.rank
},
},
{
title: "班级",
key: "class_name",
width: 200,
titleAlign: "center",
align: "center",
},
{
title: "人数",
key: "user_count",
width: 100,
titleAlign: "center",
align: "center",
},
{
title: "总AC数",
key: "total_ac",
width: 120,
titleAlign: "center",
align: "center",
},
{
title: "总提交数",
key: "total_submission",
width: 120,
titleAlign: "center",
align: "center",
},
{
title: "平均AC数",
key: "avg_ac",
width: 120,
titleAlign: "center",
align: "center",
},
{
title: "正确率",
key: "ac_rate",
width: 100,
titleAlign: "center",
align: "center",
render: (row) => `${row.ac_rate}%`,
},
]
async function init() {
if (query.grade === null) {
data.value = []
total.value = 0
return
}
const offset = (query.page - 1) * query.limit
const res = await getClassRank(offset, query.limit, query.grade)
data.value = res.data.results
total.value = res.data.total
}
watch(() => query.page, init)
watch(
() => query.limit,
() => {
query.page = 1
init()
},
)
watch(
() => query.grade,
() => {
query.page = 1
init()
},
)
onMounted(() => {
if (query.grade !== null) {
init()
}
})
</script>
<template>
<n-flex justify="center">
<n-h2>班级排名</n-h2>
</n-flex>
<n-flex justify="center" style="margin-bottom: 16px">
<n-select
v-model:value="query.grade"
placeholder="选择年级"
clearable
style="width: 200px"
:options="gradeOptions"
/>
</n-flex>
<n-data-table :data="data" :columns="columns" />
<Pagination
:total="total"
v-model:page="query.page"
v-model:limit="query.limit"
/>
</template>