feat: align agent preview with learner topics

This commit is contained in:
2026-07-31 18:21:36 +08:00
parent ab2c945f0b
commit b6aff78aac
18 changed files with 656 additions and 44 deletions

View File

@@ -9,7 +9,7 @@ from fastapi.responses import StreamingResponse
from openpyxl import Workbook, load_workbook
from pydantic import BaseModel
from pydantic import ValidationError
from sqlalchemy import extract, func, select
from sqlalchemy import extract, func, or_, select
from sqlalchemy.orm import Session
from app.core.database import get_db
@@ -267,11 +267,49 @@ def user_operation_detail(
"recentTopics": _recent_topics(db, user.id),
"recentHelpCards": [help_card_dict(item) for item in _recent_help_cards(db, user.id)],
"recentShareDrafts": [share_draft_dict(item) for item in _recent_share_drafts(db, user.id)],
"recentReports": [periodic_report_dict(item) for item in PeriodicReportService.list_user_reports(db, user_id=user.id, limit=10)],
"recentReports": [
periodic_report_dict(item)
for item in PeriodicReportService.list_user_reports(db, user_id=user.id, limit=10)
],
}
)
@router.get("/user/{user_id}/topics")
def user_topic_options(
user_id: int,
keyword: str = Query(default="", max_length=100),
page: int = Query(default=1, ge=1),
pageSize: int = Query(default=50, ge=10, le=100),
db: Session = Depends(get_db),
current_admin: Admin = Depends(get_current_admin),
) -> dict:
"""Lightweight topic selector data for Agent preview; no message bodies are returned."""
user = _get_user(db, user_id)
conditions = [TopicSession.user_id == user.id]
normalized_keyword = keyword.strip()
if normalized_keyword:
like = f"%{normalized_keyword}%"
conditions.append(or_(TopicSession.title.like(like), TopicSession.core_question.like(like)))
total = db.scalar(select(func.count(TopicSession.id)).where(*conditions)) or 0
rows = db.execute(
select(TopicSession, TopicSummary.id)
.join(TopicSummary, TopicSummary.topic_session_id == TopicSession.id, isouter=True)
.where(*conditions)
.order_by(TopicSession.updated_at.desc(), TopicSession.id.desc())
.offset((page - 1) * pageSize)
.limit(pageSize)
).all()
items = [
{
**topic_dict(topic),
"summaryAvailable": summary_id is not None,
}
for topic, summary_id in rows
]
return api_success(page_result(items, total=total, page=page, page_size=pageSize))
@router.get("/user/{user_id}/reports")
def user_reports(
user_id: int,