""" 扫描管理API路由 """ from fastapi import APIRouter, Depends, HTTPException, status, BackgroundTasks from sqlalchemy.orm import Session from typing import List from app.database import get_db from app.models.scan import Scan, ScanStatus, ScanType from app.models.project import Project from app.schemas.scan import ScanCreate, ScanResponse, ScanStatusResponse from app.services.scan_service import ScanService router = APIRouter() @router.get("/", response_model=List[ScanResponse]) async def get_scans( project_id: int = None, skip: int = 0, limit: int = 100, db: Session = Depends(get_db) ): """获取扫描历史""" query = db.query(Scan) if project_id: query = query.filter(Scan.project_id == project_id) scans = query.order_by(Scan.created_at.desc()).offset(skip).limit(limit).all() return scans @router.post("/", response_model=ScanResponse, status_code=status.HTTP_201_CREATED) async def create_scan( scan_data: ScanCreate, background_tasks: BackgroundTasks, db: Session = Depends(get_db) ): """创建并启动扫描任务""" # 验证项目存在 project = db.query(Project).filter(Project.id == scan_data.project_id).first() if not project: raise HTTPException(status_code=404, detail="项目不存在") # 创建扫描记录 scan = Scan( project_id=scan_data.project_id, scan_type=scan_data.scan_type, scan_config=scan_data.scan_config, status=ScanStatus.PENDING ) db.add(scan) db.commit() db.refresh(scan) # 启动后台扫描任务 background_tasks.add_task(ScanService.run_scan, scan.id) return scan @router.get("/{scan_id}", response_model=ScanResponse) async def get_scan( scan_id: int, db: Session = Depends(get_db) ): """获取扫描详情""" scan = db.query(Scan).filter(Scan.id == scan_id).first() if not scan: raise HTTPException(status_code=404, detail="扫描任务不存在") return scan @router.get("/{scan_id}/status", response_model=ScanStatusResponse) async def get_scan_status( scan_id: int, db: Session = Depends(get_db) ): """获取扫描状态""" scan = db.query(Scan).filter(Scan.id == scan_id).first() if not scan: raise HTTPException(status_code=404, detail="扫描任务不存在") return { "scan_id": scan.id, "status": scan.status.value, "progress": { "total_files": scan.total_files, "scanned_files": scan.scanned_files, "percentage": (scan.scanned_files / scan.total_files * 100) if scan.total_files > 0 else 0 }, "started_at": scan.started_at, "completed_at": scan.completed_at, "error_message": scan.error_message } @router.post("/{scan_id}/cancel") async def cancel_scan( scan_id: int, db: Session = Depends(get_db) ): """取消扫描任务""" scan = db.query(Scan).filter(Scan.id == scan_id).first() if not scan: raise HTTPException(status_code=404, detail="扫描任务不存在") if scan.status in [ScanStatus.COMPLETED, ScanStatus.FAILED, ScanStatus.CANCELLED]: raise HTTPException(status_code=400, detail="扫描任务已完成或已取消") scan.status = ScanStatus.CANCELLED db.commit() return {"message": "扫描任务已取消"}