geo/backend/app/api/trends.py

125 lines
3.6 KiB
Python

import uuid
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
from app.api.deps import get_current_user
from app.database import get_db
from app.models.user import User
from app.models.brand import Brand
from app.models.trend_insight import TrendInsight
from app.schemas.trend_insight import (
TrendInsightRequest,
TrendInsightResponse,
TrendInsightList,
TrendSummary,
)
from app.services.trend.trend_analyzer_service import TrendAnalyzerService
router = APIRouter()
async def _get_brand_with_access(
brand_id: uuid.UUID,
db: AsyncSession,
current_user: User,
) -> Brand:
stmt = select(Brand).where(
Brand.id == brand_id,
Brand.user_id == current_user.id,
)
result = await db.execute(stmt)
brand = result.scalar_one_or_none()
if not brand:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="品牌不存在",
)
return brand
@router.post("/insight", response_model=TrendInsightResponse)
async def create_trend_insight(
request: TrendInsightRequest,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
await _get_brand_with_access(request.brand_id, db, current_user)
service = TrendAnalyzerService(db)
result = await service.analyze_trends(
brand_id=request.brand_id,
days=request.period_days,
platforms=request.platforms,
keywords=request.keywords,
)
if result.get("status") == "insufficient_data":
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=result.get("message", "数据不足"),
)
insight_id = uuid.UUID(result["insight_id"])
insight = await service.get_insight_by_id(insight_id)
if insight is None:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail="洞察创建失败",
)
return insight
@router.get("/brand/{brand_id}", response_model=TrendInsightList)
async def list_trend_insights(
brand_id: uuid.UUID,
skip: int = Query(0, ge=0),
limit: int = Query(20, ge=1, le=100),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
await _get_brand_with_access(brand_id, db, current_user)
service = TrendAnalyzerService(db)
items, total = await service.get_insights(
brand_id=brand_id,
skip=skip,
limit=limit,
)
return TrendInsightList(items=items, total=total)
@router.get("/brand/{brand_id}/summary", response_model=TrendSummary)
async def get_trend_summary(
brand_id: uuid.UUID,
period_days: int = Query(30, ge=7, le=365),
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
await _get_brand_with_access(brand_id, db, current_user)
service = TrendAnalyzerService(db)
summary = await service.get_summary(
brand_id=brand_id,
days=period_days,
)
return TrendSummary(**summary)
@router.get("/{insight_id}", response_model=TrendInsightResponse)
async def get_trend_insight_detail(
insight_id: uuid.UUID,
current_user: User = Depends(get_current_user),
db: AsyncSession = Depends(get_db),
):
service = TrendAnalyzerService(db)
insight = await service.get_insight_by_id(insight_id)
if insight is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="洞察不存在",
)
return insight