from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.orm import Session from app.auth import hash_password, require_admin from app.database import get_db from app.grader_scope import get_grader_subjects, set_grader_subjects, validate_subject_names from app.models import User from app.schemas import GraderCreate, GraderOut, GraderUpdate, GradersResponse router = APIRouter(prefix="/api/admin/graders", tags=["admin-graders"]) def _get_grader(db: Session, grader_id: int) -> User: user = db.get(User, grader_id) if not user or user.role != "grader": raise HTTPException(404, detail="考评员不存在") return user def _to_out(db: Session, u: User) -> GraderOut: return GraderOut( id=u.id, username=u.username, display_name=u.display_name or "", is_active=u.is_active, created_at=u.created_at.isoformat() if u.created_at else "", subjects=get_grader_subjects(db, u.id), ) @router.get("", response_model=GradersResponse) def list_graders( db: Session = Depends(get_db), _: User = Depends(require_admin), ): rows = db.scalars(select(User).where(User.role == "grader").order_by(User.id)).all() return GradersResponse(items=[_to_out(db, u) for u in rows]) @router.post("", response_model=GraderOut, status_code=201) def create_grader( body: GraderCreate, db: Session = Depends(get_db), _: User = Depends(require_admin), ): username = body.username.strip() if db.query(User).filter(User.username == username).first(): raise HTTPException(409, detail="用户名已存在") validate_subject_names(db, body.subjects) user = User( username=username, password_hash=hash_password(body.password), display_name=body.display_name.strip(), role="grader", is_active=True, ) db.add(user) db.flush() set_grader_subjects(db, user.id, body.subjects) db.commit() db.refresh(user) return _to_out(db, user) @router.put("/{grader_id}", response_model=GraderOut) def update_grader( grader_id: int, body: GraderUpdate, db: Session = Depends(get_db), _: User = Depends(require_admin), ): user = _get_grader(db, grader_id) if body.username is not None: username = body.username.strip() if not username: raise HTTPException(400, detail="用户名不能为空") other = db.query(User).filter(User.username == username, User.id != grader_id).first() if other: raise HTTPException(409, detail="用户名已存在") user.username = username if body.display_name is not None: user.display_name = body.display_name.strip() if body.password is not None: user.password_hash = hash_password(body.password) if body.is_active is not None: user.is_active = body.is_active if body.subjects is not None: set_grader_subjects(db, user.id, body.subjects) db.commit() db.refresh(user) return _to_out(db, user) @router.delete("/{grader_id}", status_code=204) def delete_grader( grader_id: int, db: Session = Depends(get_db), admin: User = Depends(require_admin), ): if grader_id == admin.id: raise HTTPException(400, detail="不能删除当前登录账号") user = _get_grader(db, grader_id) db.delete(user) db.commit()