diff --git a/app/main/routes.py b/app/main/routes.py index 9735053..62bbb29 100644 --- a/app/main/routes.py +++ b/app/main/routes.py @@ -30,7 +30,108 @@ def rollcall(): @main_bp.route("/stats") @login_required def stats(): - return render_template("stats.html") + # 排行榜:按总积分、出勤次数、学号排序 + students = ( + Student.query.filter_by(user_id=current_user.id) + .order_by( + Student.total_score.desc(), + Student.attendance_count.desc(), + Student.student_no.asc(), + ) + .all() + ) + + # 最近点名记录 + records = ( + db.session.query(RollCall, Student) + .join(Student, RollCall.student_id == Student.id) + .filter(RollCall.user_id == current_user.id) + .order_by(RollCall.call_time.desc()) + .limit(50) + .all() + ) + + return render_template("stats.html", students=students, records=records) + + +@main_bp.route("/stats/export/students") +@login_required +def export_students(): + # 导出当前账号学生积分详单 + students = ( + Student.query.filter_by(user_id=current_user.id) + .order_by(Student.student_no.asc()) + .all() + ) + + import csv + from io import StringIO + from flask import Response + + output = StringIO() + writer = csv.writer(output) + writer.writerow(["学号", "姓名", "专业", "出勤次数", "随机点名次数", "总积分"]) + for s in students: + writer.writerow( + [ + s.student_no, + s.name, + s.major or "", + s.attendance_count or 0, + s.random_called_count or 0, + f"{(s.total_score or 0):.1f}", + ] + ) + + output.seek(0) + return Response( + output.getvalue().encode("utf-8-sig"), + mimetype="text/csv; charset=utf-8", + headers={ + "Content-Disposition": "attachment; filename=students_scores.csv", + }, + ) + + +@main_bp.route("/stats/export/rollcalls") +@login_required +def export_rollcalls(): + # 导出当前账号点名记录 + records = ( + db.session.query(RollCall, Student) + .join(Student, RollCall.student_id == Student.id) + .filter(RollCall.user_id == current_user.id) + .order_by(RollCall.call_time.asc()) + .all() + ) + + import csv + from io import StringIO + from flask import Response + + output = StringIO() + writer = csv.writer(output) + writer.writerow(["时间", "学号", "姓名", "模式", "状态", "积分变化"]) + for rc, s in records: + writer.writerow( + [ + rc.call_time.strftime("%Y-%m-%d %H:%M:%S"), + s.student_no, + s.name, + rc.mode, + rc.status, + f"{rc.score_change:.1f}", + ] + ) + + output.seek(0) + return Response( + output.getvalue().encode("utf-8-sig"), + mimetype="text/csv; charset=utf-8", + headers={ + "Content-Disposition": "attachment; filename=rollcalls.csv", + }, + ) @main_bp.route("/manage") diff --git a/app/templates/stats.html b/app/templates/stats.html index 321c35d..11eec07 100644 --- a/app/templates/stats.html +++ b/app/templates/stats.html @@ -1,6 +1,91 @@ {% extends 'base.html' %} {% block title %}统计 - 课堂点名系统{% endblock %} {% block content %} -
上半部分:积分随时间走势图;下半部分:排行榜;右侧:点名记录。
+| 名次 | +学号 | +姓名 | +专业 | +总积分 | +出勤次数 | +随机点名次数 | +
|---|---|---|---|---|---|---|
| {{ loop.index }} | +{{ s.student_no }} | +{{ s.name }} | +{{ s.major }} | +{{ '%.1f'|format(s.total_score or 0) }} | +{{ s.attendance_count or 0 }} | +{{ s.random_called_count or 0 }} | +
| 暂无学生数据。 | +||||||
| 时间 | +姓名 | +学号 | +模式 | +状态 | +积分 | +
|---|---|---|---|---|---|
| {{ rc.call_time.strftime('%m-%d %H:%M') }} | +{{ s.name }} | +{{ s.student_no }} | +{{ '随机' if rc.mode == 'random' else '顺序' }} | ++ {% if rc.status == 'absent' %}缺勤{% elif rc.status == 'distracted' %}走神{% else %}到课{% endif %} + | +{{ '%.1f'|format(rc.score_change or 0) }} | +
| 暂无点名记录。 | +|||||