"""admin 反馈工单:列表(读,支持 状态/用户ID/内容/时间 筛选 + 排序)+ 标记已处理(写,带审计)。""" from __future__ import annotations from datetime import datetime from typing import Annotated from fastapi import APIRouter, Depends, HTTPException, Query, Request from app.admin.audit import write_audit from app.admin.deps import AdminDb, get_client_ip, get_current_admin, require_role from app.admin.repositories import mutations, queries from app.admin.schemas.common import CursorPage, OkResponse from app.admin.schemas.feedback import FeedbackOut from app.models.admin import AdminUser from app.models.feedback import Feedback router = APIRouter( prefix="/admin/api/feedbacks", tags=["admin-feedback"], dependencies=[Depends(get_current_admin)], ) @router.get("", response_model=CursorPage[FeedbackOut], summary="反馈工单列表") def list_feedbacks( db: AdminDb, status: Annotated[str | None, Query()] = None, user_id: Annotated[int | None, Query()] = None, content: Annotated[str | None, Query(max_length=100)] = None, created_from: Annotated[datetime | None, Query()] = None, created_to: Annotated[datetime | None, Query()] = None, sort_by: Annotated[str, Query(pattern="^(id|created_at)$")] = "id", sort_order: Annotated[str, Query(pattern="^(asc|desc)$")] = "desc", limit: Annotated[int, Query(ge=1, le=100)] = 20, cursor: Annotated[int | None, Query()] = None, ) -> CursorPage[FeedbackOut]: items, next_cursor, total = queries.list_feedbacks( db, status=status, user_id=user_id, content=content, created_from=created_from, created_to=created_to, sort_by=sort_by, sort_order=sort_order, limit=limit, cursor=cursor, ) return CursorPage( items=[FeedbackOut.model_validate(f) for f in items], next_cursor=next_cursor, total=total, ) @router.post("/{feedback_id}/handle", response_model=OkResponse, summary="标记反馈已处理") def handle_feedback( feedback_id: int, request: Request, admin: Annotated[AdminUser, Depends(require_role("operator"))], db: AdminDb, ) -> OkResponse: fb = db.get(Feedback, feedback_id) if fb is None: raise HTTPException(status_code=404, detail="反馈不存在") before = fb.status mutations.update_feedback_status(db, fb, status="handled", commit=False) write_audit( db, admin, action="feedback.handle", target_type="feedback", target_id=feedback_id, detail={"before": before, "after": "handled"}, ip=get_client_ip(request), commit=False, ) db.commit() return OkResponse()