# backend/app/api/spiders.py from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form from sqlalchemy.orm import Session from typing import Optional import os from ..database import get_db from ..models import Spider, Category from ..schemas import SpiderCreate, SpiderUpdate, Spider, ListResponse, SuccessResponse from ..services.category_service import CategoryService from ..services.file_service import FileService router = APIRouter(prefix="/api/spiders", tags=["spiders"]) @router.post("/", response_model=Spider) def create_spider( name: str = Form(...), description: Optional[str] = Form(None), cron_expression: str = Form("0 0 * * *"), enabled: bool = Form(True), timeout: int = Form(300), category_id: int = Form(...), code_content: Optional[str] = Form(None), file: Optional[UploadFile] = File(None), db: Session = Depends(get_db) ): # 验证分类是否存在 category = CategoryService.get_category_by_id(db, category_id) # 检查脚本名称是否重复 existing_spider = db.query(Spider).filter(Spider.name == name).first() if existing_spider: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="脚本名称已存在" ) file_service = FileService() filename = None file_path = None final_code_content = code_content if file and file.filename: # 文件上传方式 filename, file_path = file_service.save_uploaded_file(file) final_code_content = file_service.read_file_content(file_path) elif code_content: # 代码粘贴方式 filename, file_path = file_service.save_code_content(code_content, name) else: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="必须提供代码内容或上传文件" ) spider_data = { "name": name, "description": description, "filename": filename, "file_path": file_path, "code_content": final_code_content, "cron_expression": cron_expression, "enabled": enabled, "timeout": timeout, "category_id": category_id } db_spider = Spider(**spider_data) db.add(db_spider) db.commit() db.refresh(db_spider) return db_spider @router.get("/", response_model=ListResponse) def get_spiders(category_id: Optional[int] = None, db: Session = Depends(get_db)): query = db.query(Spider) if category_id: query = query.filter(Spider.category_id == category_id) spiders = query.all() # 加载分类信息 for spider in spiders: spider.category return ListResponse(total=len(spiders), items=spiders) @router.get("/{spider_id}", response_model=Spider) def get_spider(spider_id: int, db: Session = Depends(get_db)): spider = db.query(Spider).filter(Spider.id == spider_id).first() if not spider: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="脚本不存在" ) spider.category return spider @router.put("/{spider_id}", response_model=Spider) def update_spider(spider_id: int, spider_update: SpiderUpdate, db: Session = Depends(get_db)): db_spider = db.query(Spider).filter(Spider.id == spider_id).first() if not db_spider: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="脚本不存在" ) update_data = spider_update.dict(exclude_unset=True) file_service = FileService() # 如果更新了代码内容,需要更新文件 if 'code_content' in update_data and update_data['code_content']: # 删除旧文件 file_service.delete_file(db_spider.file_path) # 保存新文件 filename, file_path = file_service.save_code_content( update_data['code_content'], update_data.get('name', db_spider.name) ) update_data['filename'] = filename update_data['file_path'] = file_path # 更新字段 for field, value in update_data.items(): if field != 'code_content': setattr(db_spider, field, value) db.commit() db.refresh(db_spider) return db_spider @router.delete("/{spider_id}") def delete_spider(spider_id: int, db: Session = Depends(get_db)): db_spider = db.query(Spider).filter(Spider.id == spider_id).first() if not db_spider: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="脚本不存在" ) # 删除服务器上的脚本文件 file_service = FileService() file_service.delete_file(db_spider.file_path) db.delete(db_spider) db.commit() return SuccessResponse(success=True, message="脚本删除成功") @router.put("/{spider_id}/toggle", response_model=Spider) def toggle_spider(spider_id: int, db: Session = Depends(get_db)): db_spider = db.query(Spider).filter(Spider.id == spider_id).first() if not db_spider: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="脚本不存在" ) db_spider.enabled = not db_spider.enabled db.commit() db.refresh(db_spider) return db_spider