|
@@ -0,0 +1,165 @@
|
|
|
|
|
+# 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
|