import csv import io import uuid from urllib.parse import quote from fastapi import APIRouter, Depends from fastapi.responses import Response from sqlalchemy.orm import Session, joinedload from app.core.database import get_db from app.core.deps import get_current_user from app.models.user import ExamRecord, SubjectScore, User from app.services.student_access import get_student_for_user router = APIRouter(tags=["export"]) @router.get("/students/{student_id}/scores/export") def export_scores_csv( student_id: uuid.UUID, db: Session = Depends(get_db), current_user: User = Depends(get_current_user), ): student = get_student_for_user(db, student_id, current_user.id) exams = ( db.query(ExamRecord) .options(joinedload(ExamRecord.scores).joinedload(SubjectScore.subject)) .filter(ExamRecord.student_id == student_id) .order_by(ExamRecord.exam_date.asc()) .all() ) output = io.StringIO() writer = csv.writer(output) writer.writerow(["考试日期", "考试类型", "标题", "科目", "总分", "得分", "占比"]) type_map = {"weekly": "周考", "monthly": "月考", "final": "期末"} for exam in exams: exam_type = exam.exam_type.value if hasattr(exam.exam_type, "value") else str(exam.exam_type) for score in exam.scores: writer.writerow([ exam.exam_date.isoformat(), type_map.get(exam_type, exam_type), exam.title or "", score.subject.name if score.subject else "", float(score.total_score), float(score.obtained_score), f"{float(score.ratio) * 100:.2f}%", ]) content = output.getvalue().encode("utf-8-sig") filename = f"{student.name}_scores.csv" encoded = quote(filename) return Response( content=content, media_type="text/csv; charset=utf-8", headers={ "Content-Disposition": f'attachment; filename="scores.csv"; filename*=UTF-8\'\'{encoded}' }, )