This commit is contained in:
2026-07-23 12:07:34 +08:00
18 changed files with 777 additions and 1022 deletions
+52
View File
@@ -36,6 +36,7 @@ from app.schemas.admin import (
DailyCreditOut,
TeamCreditOut,
ModelUsageOut,
VideoParamOut,
CreateUserRequest,
UpdateMenusRequest,
ResetPasswordRequest,
@@ -1711,6 +1712,15 @@ async def list_operation_logs(
}
def _build_param_out(model_map: dict[str, dict[str, int]]) -> list[VideoParamOut]:
"""{模型: {标签: 数量}} 转为扁平列表,按模型+数量排序。"""
result: list[VideoParamOut] = []
for model, labels in model_map.items():
for label, count in sorted(labels.items(), key=lambda x: -x[1]):
result.append(VideoParamOut(model=model, label=label, count=count))
return result
# ── Stats ────────────────────────────────────────────────
@router.get("/stats", response_model=AdminStatsOut)
@@ -1950,6 +1960,45 @@ async def get_stats(
for row in model_usage_rows
]
# ── 视频分辨率/比例/时长使用分布(按模型分组)
_video_gen_q = (
select(
func.coalesce(CreditRecord.engine_name, '未知').label('model'),
ChatGenerationTask.resolution,
ChatGenerationTask.aspect_ratio,
ChatGenerationTask.duration,
)
.join(CreditRecord, CreditRecord.related_id == ChatGenerationTask.id)
.where(
ChatGenerationTask.gen_type == "video",
CreditRecord.type == "consume",
ChatGenerationTask.created_at >= date_start,
ChatGenerationTask.created_at <= date_end,
ChatGenerationTask.deleted_at.is_(None),
)
)
_video_rows = (await db.execute(_video_gen_q)).all()
_res_map: dict[str, dict[str, int]] = {}
_ratio_map: dict[str, dict[str, int]] = {}
_dur_map: dict[str, dict[str, int]] = {}
for row in _video_rows:
model = row.model or '未知'
if row.resolution:
_res_map.setdefault(model, {})
_res_map[model][row.resolution] = _res_map[model].get(row.resolution, 0) + 1
if row.aspect_ratio:
_ratio_map.setdefault(model, {})
_ratio_map[model][row.aspect_ratio] = _ratio_map[model].get(row.aspect_ratio, 0) + 1
if row.duration:
_k = f"{row.duration}"
_dur_map.setdefault(model, {})
_dur_map[model][_k] = _dur_map[model].get(_k, 0) + 1
video_resolution_usage = _build_param_out(_res_map)
video_ratio_usage = _build_param_out(_ratio_map)
video_duration_usage = _build_param_out(_dur_map)
return AdminStatsOut(
total_users=total_users,
total_projects=total_projects,
@@ -1969,6 +2018,9 @@ async def get_stats(
period_credits_by_module=period_credits_by_module,
credits_by_team=credits_by_team,
model_usage=model_usage,
video_resolution_usage=video_resolution_usage,
video_ratio_usage=video_ratio_usage,
video_duration_usage=video_duration_usage,
)
+9
View File
@@ -127,6 +127,12 @@ class ModelUsageOut(BaseModel):
count: int
class VideoParamOut(BaseModel):
model: str
label: str
count: int
class AdminStatsOut(BaseModel):
total_users: int
total_projects: int
@@ -147,6 +153,9 @@ class AdminStatsOut(BaseModel):
period_credits_by_module: list[DailyCreditOut] = []
credits_by_team: list[TeamCreditOut] = []
model_usage: list[ModelUsageOut] = []
video_resolution_usage: list[VideoParamOut] = []
video_ratio_usage: list[VideoParamOut] = []
video_duration_usage: list[VideoParamOut] = []
class AdminCreditRecordSummaryOut(BaseModel):