diff --git a/components.d.ts b/components.d.ts index f1b6e92..80e9452 100644 --- a/components.d.ts +++ b/components.d.ts @@ -37,6 +37,7 @@ declare module 'vue' { NPagination: typeof import('naive-ui')['NPagination'] NPopover: typeof import('naive-ui')['NPopover'] NRate: typeof import('naive-ui')['NRate'] + NSelect: typeof import('naive-ui')['NSelect'] NSpin: typeof import('naive-ui')['NSpin'] NSplit: typeof import('naive-ui')['NSplit'] NTab: typeof import('naive-ui')['NTab'] diff --git a/src/api.ts b/src/api.ts index 2e4e8ce..ab9255f 100644 --- a/src/api.ts +++ b/src/api.ts @@ -67,6 +67,11 @@ export const Account = { const res = await http.post("/account/batch", payload) return res.data }, + + async leaderboard() { + const res = await http.get("/account/leaderboard") + return res.data as { rank: number; username: string; total_score: number }[] + }, } export const Tutorial = { @@ -172,6 +177,18 @@ export const Submission = { const res = await http.put(`/submission/${id}/flag`, { flag }) return res.data }, + + async myScores() { + const res = await http.get("/submission/my-scores") + return res.data as { + task_id: number + task_display: number + task_title: string + score: number + created: string + }[] + }, + } export const Prompt = { diff --git a/src/components/Challenge.vue b/src/components/Challenge.vue index bd3bc85..908065b 100644 --- a/src/components/Challenge.vue +++ b/src/components/Challenge.vue @@ -19,6 +19,14 @@ @@ -31,7 +39,7 @@ import { ref, onMounted } from "vue" import { Icon } from "@iconify/vue" import { marked } from "marked" import { useRouter } from "vue-router" -import { Challenge } from "../api" +import { Challenge, Submission } from "../api" import { taskTab, taskId, challengeDisplay } from "../store/task" import { TASK_TYPE } from "../utils/const" import type { ChallengeSlim } from "../utils/type" @@ -40,6 +48,16 @@ const router = useRouter() const challenges = ref([]) const currentChallenge = ref(null) const content = ref("") +const myScoreMap = ref>(new Map()) + +async function loadMyScores() { + try { + const scores = await Submission.myScores() + myScoreMap.value = new Map(scores.map((s) => [s.task_display, s.score])) + } catch { + // 未登录时忽略 + } +} async function loadList() { challenges.value = await Challenge.listDisplay() @@ -72,7 +90,10 @@ function back() { router.push({ name: "home-challenge-list" }) } -onMounted(loadList) +onMounted(async () => { + await loadList() + await loadMyScores() +}) diff --git a/src/pages/MyScores.vue b/src/pages/MyScores.vue new file mode 100644 index 0000000..4a97175 --- /dev/null +++ b/src/pages/MyScores.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/pages/Submissions.vue b/src/pages/Submissions.vue index 130bd77..29483cc 100644 --- a/src/pages/Submissions.vue +++ b/src/pages/Submissions.vue @@ -393,6 +393,8 @@ watch( init() }, ) + + onMounted(init) onUnmounted(() => { submission.value = { diff --git a/src/router.ts b/src/router.ts index e33d617..3e3c241 100644 --- a/src/router.ts +++ b/src/router.ts @@ -25,6 +25,17 @@ const routes = [ component: () => import("./pages/Submission.vue"), props: true, }, + { + path: "/leaderboard", + name: "leaderboard", + component: () => import("./pages/Leaderboard.vue"), + }, + { + path: "/my-scores", + name: "my-scores", + component: () => import("./pages/MyScores.vue"), + meta: { auth: true }, + }, { path: "/dashboard", name: "dashboard",