feat: add teaching enhancement features

1. AI personalized hints after 3 failures (streaming SSE)
2. Submission error distribution panel in "my submissions" tab
3. Similar problem recommendations on AC or 3+ failures
4. Admin stuck problems analysis page

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-08 21:12:47 +08:00
parent c1977d7152
commit 9029e29148
11 changed files with 336 additions and 5 deletions

View File

@@ -434,3 +434,8 @@ export function getProblemSetProgress(problemSetId: number) {
export function removeUserFromProblemSet(problemSetId: number, userId: number) {
return http.delete(`admin/problemset/${problemSetId}/progress/${userId}`)
}
// 学生卡点分析
export function getStuckProblems() {
return http.get("admin/problem/stuck")
}

View File

@@ -0,0 +1,56 @@
<script setup lang="ts">
import { getStuckProblems } from "admin/api"
interface StuckProblem {
problem_id: string
problem_title: string
total: number
failed: number
failed_users: number
ac_rate: number
}
const loading = ref(true)
const data = ref<StuckProblem[]>([])
const columns: DataTableColumn<StuckProblem>[] = [
{ title: "题目 ID", key: "problem_id", width: 100 },
{ title: "题目名称", key: "problem_title", minWidth: 200 },
{ title: "总提交", key: "total", width: 100, sorter: "default" },
{ title: "失败次数", key: "failed", width: 100, sorter: "default" },
{
title: "卡住学生数",
key: "failed_users",
width: 120,
sorter: "default",
defaultSortOrder: "descend",
},
{
title: "AC 率",
key: "ac_rate",
width: 100,
sorter: "default",
render: (row) => `${row.ac_rate}%`,
},
]
onMounted(async () => {
try {
const res = await getStuckProblems()
data.value = res.data
} finally {
loading.value = false
}
})
</script>
<template>
<h2 style="margin-top: 0">学生卡点分析</h2>
<n-data-table
:loading="loading"
:columns="columns"
:data="data"
striped
:pagination="{ pageSize: 20 }"
/>
</template>