Files
dekun 1cb3c7fad5 新增作文区与 AI 解读开关,修复 CSV 导出。
系统设置可关闭成绩复盘 AI;学生详情增加作文区(OCR/手动题目、方案与范文、历史与 MD 下载);导出改用 UTF-8 文件名响应。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-28 17:42:17 +08:00

60 lines
2.1 KiB
Python

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}'
},
)