团队管理设置

This commit is contained in:
2026-06-30 11:31:54 +08:00
parent 152392e3d9
commit 9fb81dcfc1
24 changed files with 1231 additions and 127 deletions
+51 -6
View File
@@ -23,6 +23,7 @@ from app.models.image_engine import ImageEngine
from app.models.credit_ratio import CreditRatio
from app.models.operation_log import OperationLog
from app.enums.user import FrontendUserKind, UserType
from app.enums.team import TEAM_UNASSIGNED_VALUE
from app.schemas.admin import (
CreditAdjustRequest,
ModelConfigCreate,
@@ -37,6 +38,7 @@ from app.schemas.admin import (
UpdateFrontendUserKindRequest,
OperationLogOut,
)
from app.schemas.team import UpdateUserTeamRequest
from app.schemas.industry import IndustryConfigCreate, IndustryConfigOut
from app.schemas.video_engine import VideoEngineCreate, VideoEngineOut
from app.schemas.image_engine import ImageEngineCreate, ImageEngineOut
@@ -50,6 +52,7 @@ from app.services.operation_log import log_operation
from app.services.resource_signed_url_service import build_resource_signed_url
from app.services.payment import sync_pending_orders, process_refund
from app.services.resource_capacity_service import batch_get_user_resource_capacity_usage, get_user_resource_capacity_usage
from app.services.team_service import batch_get_team_name_map, set_frontend_user_team
from app.services.generation_billing_service import (
OWNER_GENERATION_RECORD,
@@ -89,6 +92,7 @@ async def list_users(
search: str = Query(""),
user_type: str | None = Query(None, pattern="^(frontend|admin)$"),
frontend_user_kind: str | None = Query(None, pattern="^(internal|external)$"),
team_id: str | None = Query(None),
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
@@ -105,16 +109,28 @@ async def list_users(
if frontend_user_kind:
query = query.where(User.user_type == UserType.FRONTEND.value, User.frontend_user_kind == frontend_user_kind)
count_query = count_query.where(User.user_type == UserType.FRONTEND.value, User.frontend_user_kind == frontend_user_kind)
if team_id:
team_filter = User.team_id.is_(None) if team_id == TEAM_UNASSIGNED_VALUE else (User.team_id == team_id)
query = query.where(team_filter)
count_query = count_query.where(team_filter)
total = (await db.execute(count_query)).scalar() or 0
result = await db.execute(query.offset((page - 1) * page_size).limit(page_size))
items = result.scalars().all()
capacity_map = await batch_get_user_resource_capacity_usage(db, [u.id for u in items])
users = list(result.scalars().all())
user_ids = [u.id for u in users]
team_ids = [getattr(u, "team_id", None) for u in users if getattr(u, "team_id", None)]
capacity_map = await batch_get_user_resource_capacity_usage(db, user_ids)
team_name_map = await batch_get_team_name_map(db, team_ids)
return {
"items": [
AdminUserOut.model_validate(u)
.model_copy(update={"resource_capacity": capacity_map.get(u.id)})
AdminUserOut.model_validate(user)
.model_copy(
update={
"resource_capacity": capacity_map.get(user.id),
"team_name": team_name_map.get(getattr(user, "team_id", None)),
}
)
.model_dump(mode="json")
for u in items
for user in users
],
"total": total,
}
@@ -194,8 +210,12 @@ async def get_user(
raise HTTPException(status_code=404, detail="用户不存在")
user.credits = round(user.credits, 2)
resource_capacity = await get_user_resource_capacity_usage(db, user.id)
team_name_map = await batch_get_team_name_map(db, [getattr(user, "team_id", None)])
return AdminUserOut.model_validate(user).model_copy(
update={"resource_capacity": resource_capacity}
update={
"resource_capacity": resource_capacity,
"team_name": team_name_map.get(getattr(user, "team_id", None)),
}
)
@@ -254,6 +274,29 @@ async def update_user_frontend_kind(
return user
@router.put("/users/{user_id}/team", response_model=AdminUserOut)
async def update_user_team(
user_id: str,
req: UpdateUserTeamRequest,
admin: User = Depends(get_admin_user),
db: AsyncSession = Depends(get_db),
):
user, before, after = await set_frontend_user_team(db, user_id=user_id, team_id=req.team_id)
await log_operation(
db,
admin.id,
admin.username,
f"设置用户团队 {user.username}",
"PUT",
f"/admin/users/{user_id}/team",
detail=json.dumps({"before": before, "after": after}, ensure_ascii=False),
)
resource_capacity = await get_user_resource_capacity_usage(db, user.id)
return AdminUserOut.model_validate(user).model_copy(
update={"resource_capacity": resource_capacity, "team_name": after.get("team_name")}
)
@router.put("/users/{user_id}/reset-password")
async def reset_user_password(
user_id: str,
@@ -299,6 +342,7 @@ async def list_credit_records(
user_name: str | None = Query(None),
user_type: str | None = Query(None),
frontend_user_kind: str | None = Query(None),
team_id: str | None = Query(None),
record_type: str | None = Query(None),
type: str | None = Query(None),
credit_subject: str | None = Query(None),
@@ -321,6 +365,7 @@ async def list_credit_records(
user_name=user_name,
user_type=user_type,
frontend_user_kind=frontend_user_kind,
team_id=team_id,
record_type=record_type or type,
credit_subject=credit_subject,
media_type=media_type,