from __future__ import annotations import json from typing import Any from fastapi import APIRouter, Depends, Query from sqlalchemy.ext.asyncio import AsyncSession from app.dependencies import get_admin_user, get_db from app.models.user import User from app.schemas.private_portrait import ( PrivatePortraitAdminConfigUpdate, PrivatePortraitAdminStatsOut, PrivatePortraitAssetListOut, PrivatePortraitConfigOut, PrivatePortraitProjectListOut, ) from app.services.operation_log import log_operation from app.services.private_portrait.admin.asset_query_service import admin_list_assets from app.services.private_portrait.admin.project_query_service import admin_list_projects from app.services.private_portrait.admin.stats_query_service import admin_get_private_portrait_stats from app.services.private_portrait.quota_service import get_user_private_portrait_config, set_user_private_portrait_limit router = APIRouter(prefix="/admin/private-portrait", tags=["管理后台-私域人像素材库"]) def _json_detail(data: dict[str, Any]) -> str: return json.dumps(data, ensure_ascii=False, default=str) @router.get("/users/{user_id}/config", response_model=PrivatePortraitConfigOut, summary="管理后台:查看用户私域人像素材额度") async def admin_get_private_portrait_config(user_id: str, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db)): config = await get_user_private_portrait_config(db, user_id=user_id) await log_operation(db, admin.id, admin.username, "查看私域人像素材库配置", "GET", f"/admin/private-portrait/users/{user_id}/config", detail=_json_detail({"target_user_id": user_id, "config": config.model_dump(mode="json")})) return config @router.put("/users/{user_id}/config", response_model=PrivatePortraitConfigOut, summary="管理后台:设置用户私域人像素材总量") async def admin_update_private_portrait_config(user_id: str, payload: PrivatePortraitAdminConfigUpdate, admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db)): before = await get_user_private_portrait_config(db, user_id=user_id) await set_user_private_portrait_limit(db, user_id=user_id, limit=payload.private_portrait_asset_limit) after = await get_user_private_portrait_config(db, user_id=user_id) await log_operation(db, admin.id, admin.username, f"设置私域人像素材总量限制:{before.asset_limit} -> {after.asset_limit}", "PUT", f"/admin/private-portrait/users/{user_id}/config", detail=_json_detail({"target_user_id": user_id, "before": before.model_dump(mode="json"), "after": after.model_dump(mode="json")})) await db.commit() return after @router.get("/stats", response_model=PrivatePortraitAdminStatsOut, summary="管理后台:私域人像素材统计") async def admin_get_private_portrait_stats_api(user_id: str | None = Query(None), library_type: str | None = Query(None), admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db)): stats = await admin_get_private_portrait_stats(db, user_id=user_id, library_type=library_type) await log_operation(db, admin.id, admin.username, "查看私域人像素材统计", "GET", "/admin/private-portrait/stats", detail=_json_detail({"filters": {"user_id": user_id, "library_type": library_type}, "stats": stats.model_dump(mode="json")})) return stats @router.get("/projects", response_model=PrivatePortraitProjectListOut, summary="管理后台:查询私域人像项目列表") async def admin_list_private_portrait_projects(page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), user_id: str | None = Query(None), library_type: str | None = Query(None), keyword: str | None = Query(None), status: str | None = Query(None), admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db)): items, total = await admin_list_projects(db, user_id=user_id, library_type=library_type, page=page, page_size=page_size, keyword=keyword, status=status) await log_operation(db, admin.id, admin.username, "查看私域人像素材项目列表", "GET", "/admin/private-portrait/projects", detail=_json_detail({"filters": {"user_id": user_id, "library_type": library_type, "keyword": keyword, "status": status, "page": page, "page_size": page_size}, "total": total, "returned_count": len(items)})) await db.commit() return PrivatePortraitProjectListOut(items=items, total=total, page=page, page_size=page_size) @router.get("/assets", response_model=PrivatePortraitAssetListOut, summary="管理后台:查询私域人像素材列表") async def admin_list_private_portrait_assets(page: int = Query(1, ge=1), page_size: int = Query(20, ge=1, le=100), user_id: str | None = Query(None), project_id: str | None = Query(None), library_type: str | None = Query(None), asset_type: str | None = Query(None), keyword: str | None = Query(None), status: str | None = Query(None), admin: User = Depends(get_admin_user), db: AsyncSession = Depends(get_db)): items, total = await admin_list_assets(db, user_id=user_id, project_id=project_id, library_type=library_type, asset_type=asset_type, status=status, keyword=keyword, page=page, page_size=page_size) await log_operation(db, admin.id, admin.username, "查看私域人像素材列表", "GET", "/admin/private-portrait/assets", detail=_json_detail({"filters": {"user_id": user_id, "project_id": project_id, "library_type": library_type, "asset_type": asset_type, "keyword": keyword, "status": status, "page": page, "page_size": page_size}, "total": total, "returned_count": len(items)})) await db.commit() return PrivatePortraitAssetListOut(items=items, total=total, page=page, page_size=page_size)