feat: add student/class statistics page with Chart.js visualizations

This commit is contained in:
hmo
2026-04-27 19:28:04 +08:00
parent 7c35f4cac3
commit dcc0457848
3 changed files with 329 additions and 0 deletions
+75
View File
@@ -16,6 +16,7 @@ from app.models import (
db,
Student,
Class,
StudentProblem,
PracticePlan,
PROBLEM_LIST,
SEVERITY_LEVELS,
@@ -67,6 +68,14 @@ def students_page():
)
@main_bp.route("/statistics")
def statistics_page():
"""数据统计页"""
if not check_login():
return redirect("/login")
return render_template("statistics.html", active_nav="statistics")
@main_bp.route("/api/students", methods=["GET"])
@login_required_json
def get_students():
@@ -366,3 +375,69 @@ def import_students():
except Exception as e:
return jsonify({"error": f"导入失败: {str(e)}"}), 500
@main_bp.route("/api/statistics/students")
def get_student_statistics():
"""获取学员统计数据"""
# 全体学员数量
total_students = Student.query.count()
# 全体问题记录
problems = StudentProblem.query.all()
# 问题级别分布(来自 StudentProblem.level
levels = ["启蒙", "入门", "进阶", "熟练", "精通"]
level_dist = {lv: 0 for lv in levels}
for p in problems:
if p.level in level_dist:
level_dist[p.level] += 1
# 问题严重程度分布
severity_dist = {"轻微": 0, "中等": 0, "严重": 0}
for p in problems:
if p.severity in severity_dist:
severity_dist[p.severity] += 1
# 各班级学员数量
classes = Class.query.filter_by(active=True).all()
class_student_count = []
for c in classes:
class_student_count.append({
"class_id": c.id,
"class_name": c.name,
"level": c.level,
"student_count": len(c.students)
})
# 问题×级别矩阵(严重程度 × 学员级别)
severities = ["轻微", "中等", "严重"]
matrix = {}
for sev in severities:
matrix[sev] = {}
for lv in levels:
matrix[sev][lv] = 0
for p in problems:
if p.level in levels and p.severity in severities:
matrix[p.severity][p.level] += 1
# 各班级问题数量
class_problem_count = []
for c in classes:
class_problems = [p for p in problems if p.student.class_id == c.id]
class_problem_count.append({
"class_id": c.id,
"class_name": c.name,
"problem_count": len(class_problems)
})
return jsonify({
"total_students": total_students,
"total_problems": len(problems),
"level_distribution": level_dist,
"severity_distribution": severity_dist,
"class_student_count": class_student_count,
"class_problem_count": class_problem_count,
"problem_level_matrix": matrix,
})