From 078e643987f20d919ba0323c4299fa515c5418c5 Mon Sep 17 00:00:00 2001
From: yuetsh <517252939@qq.com>
Date: Sat, 3 Jan 2026 21:52:09 +0800
Subject: [PATCH] add class pk
---
src/oj/api.ts | 25 ++
src/oj/class/my-rank.vue | 121 ++++++++++
src/oj/class/pk.vue | 403 +++++++++++++++++++++++++++++++
src/oj/class/rank.vue | 137 +++++++++++
src/routes.ts | 18 ++
src/shared/components/Header.vue | 24 ++
src/utils/types.ts | 1 +
7 files changed, 729 insertions(+)
create mode 100644 src/oj/class/my-rank.vue
create mode 100644 src/oj/class/pk.vue
create mode 100644 src/oj/class/rank.vue
diff --git a/src/oj/api.ts b/src/oj/api.ts
index 88f3331..282bcb3 100644
--- a/src/oj/api.ts
+++ b/src/oj/api.ts
@@ -143,6 +143,31 @@ export function getActivityRank(start: string) {
})
}
+export function getClassRank(offset: number, limit: number, grade?: number | null) {
+ return http.get("class_rank", {
+ params: { offset, limit, grade },
+ })
+}
+
+export function getUserClassRank(offset: number, limit: number) {
+ return http.get("user_class_rank", {
+ params: { offset, limit },
+ })
+}
+
+export function getClassPK(classNames: string[], startTime?: string, endTime?: string) {
+ const payload: any = {
+ class_name: classNames,
+ }
+ if (startTime) {
+ payload.start_time = startTime
+ }
+ if (endTime) {
+ payload.end_time = endTime
+ }
+ return http.post("class_pk", payload)
+}
+
export function getContestList(query: {
offset: number
limit: number
diff --git a/src/oj/class/my-rank.vue b/src/oj/class/my-rank.vue
new file mode 100644
index 0000000..2463c5f
--- /dev/null
+++ b/src/oj/class/my-rank.vue
@@ -0,0 +1,121 @@
+
+
+
+
+ 我的班级排名
+
+ 班级:{{ className }} | 我的排名:{{
+ myRank > 0 ? `第${myRank}名` : "暂无排名"
+ }}
+ | 班级总人数:{{ totalUsers }}
+
+ 您还没有加入班级
+
+
+
+
+
+
diff --git a/src/oj/class/pk.vue b/src/oj/class/pk.vue
new file mode 100644
index 0000000..8519fb7
--- /dev/null
+++ b/src/oj/class/pk.vue
@@ -0,0 +1,403 @@
+
+
+
+
+
+ 班级PK
+
+
+
+
+
+
+
+
+
+
+
+ 开始PK
+
+
+
+
+
+
+
+
+
+ {{ getRankColor(index).text }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ showDetails[classData.class_name] ? "收起" : "展开" }}详细统计
+
+
+
+
+
+
+
+
+
+
+ {{ classData.q1_ac.toFixed(2) }}
+
+
+ {{ classData.q3_ac.toFixed(2) }}
+
+
+ {{ classData.iqr.toFixed(2) }}
+
+
+ {{ classData.std_dev.toFixed(2) }}
+
+
+
+
+
+
+ 分层统计
+
+
+ {{ classData.top_10_avg.toFixed(2) }}
+
+
+ {{ classData.bottom_10_avg.toFixed(2) }}
+
+
+ {{ classData.top_25_avg.toFixed(2) }}
+
+
+ {{ classData.bottom_25_avg.toFixed(2) }}
+
+
+
+
+
+
+ 比率统计
+
+
+
+ 优秀率: {{ classData.excellent_rate.toFixed(1) }}%
+
+
+
+
+ 及格率: {{ classData.pass_rate.toFixed(1) }}%
+
+
+
+
+ 参与度: {{ classData.active_rate.toFixed(1) }}%
+
+
+
+
+
+
+
+ 时间段内表现
+
+
+ {{ classData.recent_total_ac }}
+
+
+ {{ classData.recent_avg_ac?.toFixed(2) }}
+
+
+ {{ classData.recent_median_ac?.toFixed(2) }}
+
+
+ {{ classData.recent_top_10_avg?.toFixed(2) }}
+
+
+ {{ classData.recent_active_count }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/oj/class/rank.vue b/src/oj/class/rank.vue
new file mode 100644
index 0000000..1512db0
--- /dev/null
+++ b/src/oj/class/rank.vue
@@ -0,0 +1,137 @@
+
+
+
+
+ 班级排名
+
+
+
+
+
+
+
diff --git a/src/routes.ts b/src/routes.ts
index 458ee3e..2a40ffa 100644
--- a/src/routes.ts
+++ b/src/routes.ts
@@ -66,6 +66,24 @@ export const ojs: RouteRecordRaw = {
path: "rank",
component: () => import("oj/rank/list.vue"),
},
+ {
+ path: "class",
+ children: [
+ {
+ path: "rank",
+ component: () => import("oj/class/rank.vue"),
+ },
+ {
+ path: "pk",
+ component: () => import("oj/class/pk.vue"),
+ },
+ {
+ path: "my-rank",
+ component: () => import("oj/class/my-rank.vue"),
+ meta: { requiresAuth: true },
+ },
+ ],
+ },
{
path: "announcement",
component: () => import("oj/announcement/list.vue"),
diff --git a/src/shared/components/Header.vue b/src/shared/components/Header.vue
index a0a5600..4551943 100644
--- a/src/shared/components/Header.vue
+++ b/src/shared/components/Header.vue
@@ -118,6 +118,30 @@ const menus = computed(() => [
key: "rank",
icon: renderIcon("streamline-emojis:hibiscus"),
},
+ {
+ label: () => "班级",
+ key: "class",
+ show: false,
+ icon: renderIcon("twemoji:crossed-swords"),
+ children: [
+ {
+ label: () =>
+ h(RouterLink, { to: "/class/rank" }, { default: () => "班级排名" }),
+ key: "class-rank",
+ },
+ {
+ label: () =>
+ h(RouterLink, { to: "/class/pk" }, { default: () => "班级PK" }),
+ key: "class-pk",
+ },
+ {
+ label: () =>
+ h(RouterLink, { to: "/class/my-rank" }, { default: () => "我的排名" }),
+ key: "my-rank",
+ show: userStore.isAuthed,
+ },
+ ],
+ },
{
label: () =>
h(RouterLink, { to: "/announcement" }, { default: () => "公告" }),
diff --git a/src/utils/types.ts b/src/utils/types.ts
index b39410d..55ab34a 100644
--- a/src/utils/types.ts
+++ b/src/utils/types.ts
@@ -49,6 +49,7 @@ export interface User {
is_disabled: boolean
password?: string
raw_password?: string
+ class_name?: string | null
}
export type LANGUAGE =