"""在线课程:只有外链的视频/课程资源,与教材分表维护。""" from __future__ import annotations from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from database import get_db from dependencies import get_current_user, require_permission from models import Course, User from schemas import CourseCreate, CourseOut, CourseUpdate router = APIRouter(prefix="/courses", tags=["courses"]) def _load(db: Session, course_id: int) -> Course: course = db.get(Course, course_id) if course is None: raise HTTPException(status_code=404, detail="课程不存在") return course def _clean_url(url: str | None) -> str: url = (url or "").strip() if not url: raise HTTPException(status_code=400, detail="请填写课程链接") return url @router.get("", response_model=list[CourseOut]) def list_courses( db: Session = Depends(get_db), _: User = Depends(get_current_user), ): return ( db.query(Course) .order_by(Course.position.asc(), Course.id.asc()) .all() ) @router.post("", response_model=CourseOut) def create_course( payload: CourseCreate, db: Session = Depends(get_db), _: User = Depends(require_permission("catalog:manage")), ): if db.query(Course).filter(Course.name == payload.name).first(): raise HTTPException(status_code=400, detail="同名课程已存在") course = Course( name=payload.name, provider=payload.provider, url=_clean_url(payload.url), grade=payload.grade, description=payload.description, position=db.query(Course).count(), ) db.add(course) db.commit() return course @router.put("/{course_id}", response_model=CourseOut) def update_course( course_id: int, payload: CourseUpdate, db: Session = Depends(get_db), _: User = Depends(require_permission("catalog:manage")), ): course = _load(db, course_id) fields = payload.model_dump(exclude_unset=True) if "name" in fields and fields["name"] != course.name: exists = ( db.query(Course) .filter(Course.name == fields["name"], Course.id != course.id) .first() ) if exists: raise HTTPException(status_code=400, detail="同名课程已存在") if "url" in fields: fields["url"] = _clean_url(fields["url"]) for field, value in fields.items(): setattr(course, field, value) db.commit() return course @router.delete("/{course_id}") def delete_course( course_id: int, db: Session = Depends(get_db), _: User = Depends(require_permission("catalog:manage")), ): course = _load(db, course_id) db.delete(course) db.commit() return {"deleted": course_id}