add ranks filter.
This commit is contained in:
@@ -1,6 +1,11 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useUserStore } from "~/shared/store/user"
|
import { useUserStore } from "~/shared/store/user"
|
||||||
|
import { getRank } from "oj/api"
|
||||||
import { getBaseInfo } from "../api"
|
import { getBaseInfo } from "../api"
|
||||||
|
import Pagination from "~/shared/components/Pagination.vue"
|
||||||
|
import { Rank } from "~/utils/types"
|
||||||
|
import { NButton } from "naive-ui"
|
||||||
|
import { getACRate } from "~/utils/functions"
|
||||||
|
|
||||||
const userCount = ref(0)
|
const userCount = ref(0)
|
||||||
const submissionCount = ref(0)
|
const submissionCount = ref(0)
|
||||||
@@ -8,21 +13,79 @@ const contestCount = ref(0)
|
|||||||
const userStore = useUserStore()
|
const userStore = useUserStore()
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
|
|
||||||
|
const data = ref<Rank[]>([])
|
||||||
|
const total = ref(0)
|
||||||
|
const query = reactive({
|
||||||
|
limit: 10,
|
||||||
|
page: 1,
|
||||||
|
username: "",
|
||||||
|
})
|
||||||
|
|
||||||
|
const columns: DataTableColumn<Rank>[] = [
|
||||||
|
{
|
||||||
|
title: "排名",
|
||||||
|
key: "index",
|
||||||
|
width: 80,
|
||||||
|
align: "center",
|
||||||
|
render: (_, index) => index + (query.page - 1) * query.limit + 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "用户",
|
||||||
|
key: "username",
|
||||||
|
width: 200,
|
||||||
|
render: (row) =>
|
||||||
|
h(
|
||||||
|
NButton,
|
||||||
|
{
|
||||||
|
text: true,
|
||||||
|
type: "info",
|
||||||
|
onClick: () => router.push("/user?name=" + row.user.username),
|
||||||
|
},
|
||||||
|
() => row.user.username,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
{ title: "已解决", key: "accepted_number", width: 100 },
|
||||||
|
{ title: "提交数", key: "submission_number", width: 100 },
|
||||||
|
{
|
||||||
|
title: "正确率",
|
||||||
|
key: "rate",
|
||||||
|
width: 100,
|
||||||
|
render: (row) => getACRate(row.accepted_number, row.submission_number),
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const res = await getBaseInfo()
|
const res = await getBaseInfo()
|
||||||
userCount.value = res.data.user_count
|
userCount.value = res.data.user_count
|
||||||
submissionCount.value = res.data.today_submission_count
|
submissionCount.value = res.data.today_submission_count
|
||||||
contestCount.value = res.data.recent_contest_count
|
contestCount.value = res.data.recent_contest_count
|
||||||
})
|
})
|
||||||
|
|
||||||
|
async function listRanks() {
|
||||||
|
const offset = (query.page - 1) * query.limit
|
||||||
|
const res = await getRank(offset, query.limit, query.username)
|
||||||
|
data.value = res.data.results
|
||||||
|
total.value = res.data.total
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(() => query.page, listRanks)
|
||||||
|
watch(
|
||||||
|
() => query.limit,
|
||||||
|
() => {
|
||||||
|
query.page = 1
|
||||||
|
listRanks()
|
||||||
|
},
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<n-space align="center">
|
<n-space align="center">
|
||||||
<n-avatar round :size="60" :src="userStore.profile?.avatar"></n-avatar>
|
<n-avatar round :size="60" :src="userStore.profile?.avatar" />
|
||||||
<h1 class="name">{{ userStore.user?.username }}</h1>
|
<h1 class="name">亲爱的管理员:{{ userStore.user?.username }}</h1>
|
||||||
</n-space>
|
</n-space>
|
||||||
|
<n-space>
|
||||||
<h2>
|
<h2>
|
||||||
<n-gradient-text type="info">总用户数:{{ userCount }}</n-gradient-text>
|
<n-gradient-text type="info"> 总用户数:{{ userCount }} </n-gradient-text>
|
||||||
</h2>
|
</h2>
|
||||||
<h2>
|
<h2>
|
||||||
<n-gradient-text type="error">
|
<n-gradient-text type="error">
|
||||||
@@ -34,16 +97,34 @@ onMounted(async () => {
|
|||||||
近期比赛:{{ contestCount }}
|
近期比赛:{{ contestCount }}
|
||||||
</n-gradient-text>
|
</n-gradient-text>
|
||||||
</h2>
|
</h2>
|
||||||
<n-space align="center">
|
</n-space>
|
||||||
|
<n-space align="center" class="actions">
|
||||||
<span>我猜你要:</span>
|
<span>我猜你要:</span>
|
||||||
<n-button @click="router.push('/admin/problem/create')">新题目</n-button>
|
<n-button @click="router.push('/admin/problem/create')">新题目</n-button>
|
||||||
<n-button @click="router.push('/admin/contest/create')">新比赛</n-button>
|
<n-button @click="router.push('/admin/contest/create')">新比赛</n-button>
|
||||||
|
<n-input clearable v-model:value="query.username" placeholder="班级前缀" />
|
||||||
|
<n-button @click="listRanks">用户排名</n-button>
|
||||||
|
<Pagination
|
||||||
|
class="pagination"
|
||||||
|
:total="total"
|
||||||
|
v-model:page="query.page"
|
||||||
|
v-model:limit="query.limit"
|
||||||
|
/>
|
||||||
</n-space>
|
</n-space>
|
||||||
|
<n-data-table v-if="data.length" striped :data="data" :columns="columns" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.name {
|
.name {
|
||||||
font-size: 48px;
|
font-size: 32px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pagination {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -90,9 +90,9 @@ export function adminRejudge(id: string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getRank(offset: number, limit: number) {
|
export function getRank(offset: number, limit: number, username?: string) {
|
||||||
return http.get("user_rank", {
|
return http.get("user_rank", {
|
||||||
params: { offset, limit, rule: "acm" },
|
params: { offset, limit, rule: "acm", username },
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user