"""任务路由:列表 / 状态 / 下载字幕。""" from __future__ import annotations from pathlib import Path from fastapi import APIRouter, Depends, HTTPException, Query from fastapi.responses import FileResponse from sqlalchemy.orm import Session from ..config import get_settings from ..database import get_db from ..models.task import Task from ..schemas.task import TaskListResponse, TaskResponse router = APIRouter(prefix="/api/tasks", tags=["task"]) def _to_resp(task: Task) -> TaskResponse: return TaskResponse( id=task.id, filename=task.filename, status=task.status, progress=task.progress, error=task.error, created_at=task.created_at, updated_at=task.updated_at, ) @router.get("", response_model=TaskListResponse, summary="任务列表") def list_tasks( limit: int = Query(100, ge=1, le=500), offset: int = Query(0, ge=0), q: str = Query("", description="按文件名模糊搜索(大小写不敏感,匹配子串)"), db: Session = Depends(get_db), ) -> TaskListResponse: q_base = db.query(Task).order_by(Task.id.desc()) if q.strip(): # SQLite 的 LIKE 默认大小写不敏感(ASCII),ilike 等价于 LIKE like = f"%{q.strip()}%" q_base = q_base.filter(Task.filename.ilike(like)) total = q_base.count() tasks = q_base.offset(offset).limit(limit).all() return TaskListResponse(tasks=[_to_resp(t) for t in tasks], total=total) @router.get("/{task_id}", response_model=TaskResponse, summary="任务状态") def get_task(task_id: int, db: Session = Depends(get_db)) -> TaskResponse: task = db.get(Task, task_id) if task is None: raise HTTPException(404, f"任务不存在:{task_id}") return _to_resp(task) @router.get("/{task_id}/subtitle", summary="下载字幕") def download_subtitle( task_id: int, type: str = Query("bilingual", pattern="^(bilingual|en|zh)$"), db: Session = Depends(get_db), ) -> FileResponse: task = db.get(Task, task_id) if task is None: raise HTTPException(404, f"任务不存在:{task_id}") if task.status != "done": raise HTTPException(409, f"任务尚未完成(当前状态:{task.status})") rel = { "bilingual": task.bilingual_srt_path, "en": task.en_srt_path, "zh": task.zh_srt_path, }[type] if not rel: raise HTTPException(404, f"该类型字幕不存在:{type}") s = get_settings() path = s.output_dir() / rel if not path.is_file(): raise HTTPException(404, f"字幕文件丢失:{path}") base = Path(task.filename).stem suffix = "" if type == "bilingual" else f".{type}" download_name = f"{base}{suffix}.srt" return FileResponse( path=path, media_type="application/x-subrip", filename=download_name, )