diff --git a/apps/web/src/admin/api.ts b/apps/web/src/admin/api.ts index db949aa..99cd557 100644 --- a/apps/web/src/admin/api.ts +++ b/apps/web/src/admin/api.ts @@ -1,7 +1,6 @@ import api from "utils/api" import { toAdminProblemRow } from "admin/transforms" import type { - AcTrend, BatchProblemTagResponse, GenerateSqlTestCaseResponse, RenameTagResponse, @@ -9,6 +8,8 @@ import type { AdminAiReport, AdminAiReportList, StuckProblem, + StuckProblemDetail, + YearlyOverview, LearnBoard, LearnExerciseProgressList, LearnExerciseAttempt, @@ -598,9 +599,13 @@ export function deleteProblemSetBadge(problemSetId: number, badgeId: number) { return api.delete(`admin/problem-sets/${problemSetId}/badges/${badgeId}`) } -// 学生卡点分析 -export function getStuckProblems() { - return api.get("admin/problem-analytics/stuck") +// 卡点分析:start 是时间段的起点(ISO),不给就是全部时间 +export function getStuckProblems(params: { className?: string; start?: string }) { + return api.get("admin/problem-analytics/stuck", { params }) +} + +export function getStuckProblemDetail(id: number, params: { className?: string; start?: string }) { + return api.get(`admin/problem-analytics/stuck/${id}`, { params }) } export function getLearnBoard(params: { type: "python" | "c"; className?: string }) { @@ -619,12 +624,8 @@ export function getLearnExerciseAttempts(exerciseId: number, params: { className }) } -export function getTopACTrend(params: { - sinceYear: number - untilYear: number - minPerYear: number -}) { - return api.get("admin/problem-analytics/ac-trend", { params }) +export function getYearlyOverview() { + return api.get("admin/problem-analytics/yearly") } // AI 学习分析报告 diff --git a/apps/web/src/admin/problem/Stuck.vue b/apps/web/src/admin/problem/Stuck.vue index f69da70..3818367 100644 --- a/apps/web/src/admin/problem/Stuck.vue +++ b/apps/web/src/admin/problem/Stuck.vue @@ -1,49 +1,863 @@ + + diff --git a/apps/web/src/admin/problem/Yearly.vue b/apps/web/src/admin/problem/Yearly.vue new file mode 100644 index 0000000..9245af0 --- /dev/null +++ b/apps/web/src/admin/problem/Yearly.vue @@ -0,0 +1,255 @@ + + + + + diff --git a/apps/web/src/routes.ts b/apps/web/src/routes.ts index c7d4911..be294f9 100644 --- a/apps/web/src/routes.ts +++ b/apps/web/src/routes.ts @@ -310,11 +310,13 @@ export const admins: RouteRecordRaw = { meta: { requiresTeacherAdmin: true }, }, { - path: "problem/top_ac_trend", - name: "admin top ac trend", - component: () => import("admin/problem/TopACTrend.vue"), + path: "problem/yearly", + name: "admin yearly overview", + component: () => import("admin/problem/Yearly.vue"), meta: { requiresTeacherAdmin: true }, }, + // 「年度趋势」改名「历年概况」之前的地址,收藏夹里可能还有 + { path: "problem/top_ac_trend", redirect: "/admin/problem/yearly" }, // 题单管理路由 { path: "problemset/list", diff --git a/apps/web/src/shared/layout/admin.vue b/apps/web/src/shared/layout/admin.vue index 2323762..84b1ca0 100644 --- a/apps/web/src/shared/layout/admin.vue +++ b/apps/web/src/shared/layout/admin.vue @@ -85,9 +85,9 @@ const NAV: NavGroup[] = [ role: "teacher", }, { - label: "年度趋势", + label: "历年概况", icon: "ph:chart-line-up", - path: "/admin/problem/top_ac_trend", + path: "/admin/problem/yearly", role: "teacher", }, { label: "自学情况", icon: "ph:student", path: "/admin/learn", role: "teacher" }, diff --git a/apps/web/src/utils/types.ts b/apps/web/src/utils/types.ts index 49a40f2..0ac569c 100644 --- a/apps/web/src/utils/types.ts +++ b/apps/web/src/utils/types.ts @@ -328,7 +328,10 @@ export type { AdminAiReportListItem, AdminAiReportList, StuckProblem, - AcTrend, + StuckProblemDetail, + StuckStudent, + YearlyOverview, + YearlySummary, LearnBoard, LearnBoardStudent, LearnExerciseProgress,