"""采集管理 API:类别与信息源的 CRUD""" from fastapi import APIRouter, Depends, HTTPException, Request from sqlalchemy.orm import Session from typing import List from pydantic import BaseModel from typing import Optional from ..database import get_db from ..models import CollectorCategory, CollectorSource from .auth import get_current_admin, require_role router = APIRouter(prefix="/api/admin/collector", tags=["collector_mgmt"], dependencies=[Depends(get_current_admin)]) # ---------- Schemas ---------- class CategoryCreate(BaseModel): name: str description: Optional[str] = None search_query: Optional[str] = None sort_order: int = 0 is_active: bool = True class CategoryUpdate(BaseModel): name: Optional[str] = None description: Optional[str] = None search_query: Optional[str] = None sort_order: Optional[int] = None is_active: Optional[bool] = None class SourceCreate(BaseModel): category_id: Optional[int] = None name: str source_type: str url: Optional[str] = None query: Optional[str] = None credibility: str = "medium" focus: Optional[str] = None is_active: bool = True sort_order: int = 0 class SourceUpdate(BaseModel): category_id: Optional[int] = None name: Optional[str] = None source_type: Optional[str] = None url: Optional[str] = None query: Optional[str] = None credibility: Optional[str] = None focus: Optional[str] = None is_active: Optional[bool] = None sort_order: Optional[int] = None # ---------- Categories ---------- @router.get("/categories") def list_categories(db: Session = Depends(get_db)): cats = db.query(CollectorCategory).order_by(CollectorCategory.sort_order).all() result = [] for c in cats: d = c.to_dict() d["source_count"] = db.query(CollectorSource).filter(CollectorSource.category_id == c.id).count() result.append(d) return result @router.post("/categories", status_code=201) def create_category(data: CategoryCreate, db: Session = Depends(get_db)): existing = db.query(CollectorCategory).filter(CollectorCategory.name == data.name).first() if existing: raise HTTPException(400, "类别名已存在") cat = CollectorCategory(**data.model_dump()) db.add(cat) db.commit() db.refresh(cat) return cat.to_dict() @router.put("/categories/{cat_id}") def update_category(cat_id: int, data: CategoryUpdate, db: Session = Depends(get_db)): cat = db.query(CollectorCategory).filter(CollectorCategory.id == cat_id).first() if not cat: raise HTTPException(404, "类别不存在") for k, v in data.model_dump(exclude_unset=True).items(): setattr(cat, k, v) db.commit() db.refresh(cat) return cat.to_dict() @router.delete("/categories/{cat_id}") def delete_category(cat_id: int, db: Session = Depends(get_db)): cat = db.query(CollectorCategory).filter(CollectorCategory.id == cat_id).first() if not cat: raise HTTPException(404, "类别不存在") db.delete(cat) db.commit() return {"ok": True} # ---------- Sources ---------- @router.get("/sources") def list_sources(category_id: Optional[int] = None, db: Session = Depends(get_db)): q = db.query(CollectorSource).order_by(CollectorSource.sort_order) if category_id is not None: q = q.filter(CollectorSource.category_id == category_id) return [s.to_dict() for s in q.all()] @router.post("/sources", status_code=201) def create_source(data: SourceCreate, db: Session = Depends(get_db)): src = CollectorSource(**data.model_dump()) db.add(src) db.commit() db.refresh(src) return src.to_dict() @router.put("/sources/{src_id}") def update_source(src_id: int, data: SourceUpdate, db: Session = Depends(get_db)): src = db.query(CollectorSource).filter(CollectorSource.id == src_id).first() if not src: raise HTTPException(404, "信息源不存在") for k, v in data.model_dump(exclude_unset=True).items(): setattr(src, k, v) db.commit() db.refresh(src) return src.to_dict() @router.delete("/sources/{src_id}") def delete_source(src_id: int, db: Session = Depends(get_db)): src = db.query(CollectorSource).filter(CollectorSource.id == src_id).first() if not src: raise HTTPException(404, "信息源不存在") db.delete(src) db.commit() return {"ok": True}