Files
qiji/backend/app/api/ai_summary.py
T
v6ole 5b38246801 feat: AI 摘要持久化 — DB 缓存 + 自动加载
后端:
- 新增 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 生成摘要', 有缓存→'重新生成'
- 标题栏显示生成时间戳
2026-06-25 11:45:04 +08:00

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}