真人素材库V3

This commit is contained in:
2026-07-07 13:20:50 +08:00
parent d80f5c3577
commit 6ae5e0d663
31 changed files with 1421 additions and 606 deletions
+33 -101
View File
@@ -10,127 +10,59 @@ 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.asset_service import (
asset_to_out,
get_user_private_portrait_config,
list_assets,
set_user_private_portrait_limit,
)
from app.services.private_portrait.project_service import list_projects, project_to_out
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=["admin-private-portrait"])
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)
async def admin_get_private_portrait_config(
user_id: str,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
@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")}),
)
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)
async def admin_update_private_portrait_config(
user_id: str,
payload: PrivatePortraitAdminConfigUpdate,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
@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_image_limit)
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.image_limit} -> {after.image_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 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("/projects", response_model=PrivatePortraitProjectListOut)
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),
keyword: str | None = Query(None),
status: str | None = Query(None),
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
items, total = await list_projects(db, user_id=user_id, 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, "keyword": keyword, "status": status, "page": page, "page_size": page_size},
"total": total,
"returned_count": len(items),
}
),
)
return PrivatePortraitProjectListOut(items=[project_to_out(item, include_user=True) for item in items], total=total, page=page, page_size=page_size)
@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("/assets", response_model=PrivatePortraitAssetListOut)
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),
keyword: str | None = Query(None),
status: str | None = Query(None),
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
assets, total, project_name_map = await list_assets(db, user_id=user_id, project_id=project_id, 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, "keyword": keyword, "status": status, "page": page, "page_size": page_size},
"total": total,
"returned_count": len(assets),
}
),
)
return PrivatePortraitAssetListOut(items=[asset_to_out(asset, project_name=project_name_map.get(asset.project_id), include_user=True) for asset in assets], total=total, page=page, page_size=page_size)
@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)