5b38246801
后端: - 新增 ai_summaries 表 (week_start/week_end/generated_by/summary) - get_cached_summary(): 按周+用户查缓存 - delete_cached_summary(): 生成前清理旧缓存 - generate_summary(): 自动保存到 DB - API: GET /ai/summary(加载) POST(生成) DELETE(清除) 前端: - onMounted 自动 GET 缓存摘要, 有则直接展示 - 按钮: 无缓存→'AI 生成摘要', 有缓存→'重新生成' - 标题栏显示生成时间戳
75 lines
2.6 KiB
Python
75 lines
2.6 KiB
Python
"""AI summary endpoints — LLM-powered weekly report narrative with caching."""
|
|
|
|
import uuid
|
|
from datetime import date
|
|
from typing import Optional
|
|
from fastapi import APIRouter, Depends, Query, HTTPException
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
from app.database import get_db
|
|
from app.middleware.auth import get_current_user
|
|
from app.services.ai_summary import generate_summary, get_cached_summary, delete_cached_summary
|
|
|
|
router = APIRouter(prefix="/ai", tags=["AI Summary"])
|
|
|
|
|
|
def _check_role(role: str):
|
|
if role not in ("director", "leader"):
|
|
raise HTTPException(status_code=403, detail="仅限支局长和分管领导使用")
|
|
|
|
|
|
def _parse_ref(reference_date: Optional[str]) -> date | None:
|
|
return date.fromisoformat(reference_date) if reference_date else None
|
|
|
|
|
|
@router.get("/summary")
|
|
async def get_summary(
|
|
reference_date: Optional[str] = Query(None),
|
|
period: str = Query("week", regex="^(week|month)$"),
|
|
current_user: dict = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""Get cached AI summary for this week. Returns null if none exists."""
|
|
_check_role(current_user["role"])
|
|
cached = await get_cached_summary(
|
|
db, uuid.UUID(current_user["user_id"]), _parse_ref(reference_date), period,
|
|
)
|
|
return cached or {"summary": None}
|
|
|
|
|
|
@router.post("/summary")
|
|
async def create_summary(
|
|
reference_date: Optional[str] = Query(None),
|
|
period: str = Query("week", regex="^(week|month)$"),
|
|
current_user: dict = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""Generate (or regenerate) AI summary. Saves to DB automatically."""
|
|
_check_role(current_user["role"])
|
|
try:
|
|
return await generate_summary(
|
|
db=db,
|
|
user_id=uuid.UUID(current_user["user_id"]),
|
|
role=current_user["role"],
|
|
reference_date=_parse_ref(reference_date),
|
|
period=period,
|
|
)
|
|
except ValueError as e:
|
|
raise HTTPException(status_code=400, detail=str(e))
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=f"AI 摘要生成失败:{str(e)}")
|
|
|
|
|
|
@router.delete("/summary")
|
|
async def delete_summary(
|
|
reference_date: Optional[str] = Query(None),
|
|
period: str = Query("week", regex="^(week|month)$"),
|
|
current_user: dict = Depends(get_current_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
):
|
|
"""Delete cached summary so it can be regenerated fresh."""
|
|
_check_role(current_user["role"])
|
|
deleted = await delete_cached_summary(
|
|
db, uuid.UUID(current_user["user_id"]), _parse_ref(reference_date), period,
|
|
)
|
|
return {"deleted": deleted}
|