from typing import Annotated from fastapi import APIRouter, HTTPException, Depends from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy import select from app.database import get_db from app.models.story import Story from app.models.person import Person from app.schemas.schemas import MatchCreate, MatchOut router = APIRouter(prefix="/matches", tags=["匹配管理"]) # 特殊讲述者 ID:暂无 UNKNOWN_PERSON_ID = "unknown" UNKNOWN_PERSON_NAME = "暂无" @router.post("") async def create_match(data: MatchCreate, db: Annotated[AsyncSession, Depends(get_db)]): """创建匹配关系(支持 person_id='unknown' 表示暂无讲述者)""" story = await db.get(Story, data.story_id) if not story or story.match_status == "deleted": raise HTTPException(404, "故事不存在") if data.person_id == UNKNOWN_PERSON_ID: person_name = UNKNOWN_PERSON_NAME else: person = await db.get(Person, data.person_id) if not person: raise HTTPException(404, "讲述者不存在") person_name = person.name story.person_id = data.person_id story.match_status = "matched" await db.commit() await db.refresh(story) return {"message": "匹配成功", "story_id": story.id, "person_id": data.person_id, "person_name": person_name} @router.delete("/{story_id}") async def remove_match(story_id: str, db: Annotated[AsyncSession, Depends(get_db)]): """取消匹配""" story = await db.get(Story, story_id) if not story: raise HTTPException(404, "故事不存在") story.person_id = None story.match_status = "pending" await db.commit() return {"message": "已取消匹配"} @router.get("", response_model=list[MatchOut]) async def list_matches(db: Annotated[AsyncSession, Depends(get_db)]): """获取所有匹配关系""" result = await db.execute( select(Story, Person) .join(Person, Story.person_id == Person.id, isouter=True) .where(Story.match_status == "matched") ) matches = [] for story, person in result.all(): if story.person_id == UNKNOWN_PERSON_ID: person_name = UNKNOWN_PERSON_NAME elif person: person_name = person.name else: person_name = UNKNOWN_PERSON_NAME matches.append({ "story_id": story.id, "person_id": story.person_id, "person_name": person_name, "story_title": story.title, }) return matches