"""Signal list/create/project-link endpoints.""" from __future__ import annotations import json from typing import Optional from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.future import select from ...database import get_db from ...models import Project, ProjectSignalLink, Signal from ...schemas import SignalCreate router = APIRouter() @router.get("/") async def list_signals( roles: Optional[str] = Query(None, description="逗号分隔的角色列表,如 'frontend,backend'"), db: AsyncSession = Depends(get_db), ): """获取信号列表,支持按角色过滤""" result = await db.execute(select(Signal).order_by(Signal.impact_score.desc())) signals = result.scalars().all() if roles: role_list = [r.strip() for r in roles.split(",")] filtered_signals = [] for signal in signals: tasks = [] if signal.tasks_generated: try: tasks = json.loads(signal.tasks_generated) except Exception: tasks = [] filtered_tasks = [task for task in tasks if task.get("type") in role_list] if filtered_tasks: signal_dict = { "id": str(signal.id), "source": signal.source, "content": signal.content, "impact_score": signal.impact_score, "priority": signal.priority, "processed": signal.processed, "strategic_analysis": signal.strategic_analysis, "tasks_generated": signal.tasks_generated, "tasks_filtered": filtered_tasks, "created_at": signal.created_at.isoformat() if signal.created_at else None, } filtered_signals.append(signal_dict) return filtered_signals return signals @router.post("/", response_model=dict) async def create_signal(signal: SignalCreate, db: AsyncSession = Depends(get_db)): new_signal = Signal( source=signal.source, content=signal.content, impact_score=signal.impact_score, ) db.add(new_signal) await db.commit() await db.refresh(new_signal) return {"id": str(new_signal.id), "status": "received"} @router.get("/{signal_id}/projects") async def get_signal_projects( signal_id: str, db: AsyncSession = Depends(get_db), ): """获取信号关联的项目""" try: sid = int(signal_id) except (ValueError, TypeError): raise HTTPException(status_code=400, detail="Invalid signal_id") signal_result = await db.execute(select(Signal).where(Signal.id == sid)) if not signal_result.scalar_one_or_none(): raise HTTPException(status_code=404, detail="Signal not found") result = await db.execute( select(Project, ProjectSignalLink) .join(ProjectSignalLink, Project.id == ProjectSignalLink.project_id) .where(ProjectSignalLink.signal_id == sid) ) rows = result.all() return [ { "id": str(project.id), "title": project.title, "status": project.status, "assigned_role": project.assigned_role, "link_type": link.link_type, "relevance_score": link.relevance_score, } for project, link in rows ]