# app/api/endpoints/events.py from fastapi import APIRouter, Depends, Query from sqlalchemy.orm import Session from datetime import timedelta from typing import List from app.api.dependencies import get_db from app.models.models import UnifiedEvent, TrendingEvent, InfoSource, RankingLog, utcnow # 导入你上传的 Schema from app.schemas.event_schema import UnifiedEventResponse, PlatformTrendResponse router = APIRouter() @router.get("/unified", response_model=List[UnifiedEventResponse]) def list_unified_events( min_hot: int = Query(5, description="热度过滤阈值"), hours: int = Query(24, description="查询过去 X 小时的数据"), db: Session = Depends(get_db) ): """ 获取聚合大事件列表,完全适配前端 template.html 所需的数据结构 """ # 计算时间水位线 time_limit = utcnow() - timedelta(hours=hours) # 1. 查询大事件(按热度降序,且满足时间范围) events = db.query(UnifiedEvent).filter( UnifiedEvent.hot_score >= min_hot, UnifiedEvent.created_at >= time_limit ).order_by(UnifiedEvent.hot_score.desc()).all() results = [] for ev in events: # 2. 联表查询:获取该大事件下关联的所有平台及其具体热搜信息 trends = db.query(TrendingEvent, InfoSource.source_name).join( InfoSource, TrendingEvent.source_id == InfoSource.id ).filter(TrendingEvent.unified_event_id == ev.id).all() platform_list = [] for trend, s_name in trends: # 3. 获取排名历史轨迹 (用于前端渲染) # 这里的排序顺序 asc 保证了数组从旧到新 logs = db.query(RankingLog.ranking_position).filter( RankingLog.event_id == trend.id, RankingLog.observed_at >= time_limit ).order_by(RankingLog.observed_at.asc()).all() # 组装符合 PlatformTrendResponse 结构的字典 platform_list.append(PlatformTrendResponse( source_id=trend.source_id, platform_name=s_name, headline=trend.current_headline, url=trend.event_url, current_ranking=trend.current_ranking, ranking_history=[log[0] for log in logs] )) # 4. 组装符合 UnifiedEventResponse 结构的字典 results.append(UnifiedEventResponse( event_id=ev.id, unified_title=ev.unified_title if ev.unified_title else "暂无标题", summary=ev.ai_comprehensive_summary, hot_score=ev.hot_score, created_at=ev.created_at, platforms=platform_list )) return results