276 lines
8.1 KiB
Python
276 lines
8.1 KiB
Python
from pydantic import BaseModel, Field
|
||
|
||
from app.schemas.common import NaiveDatetime, NaiveDatetimeOptional
|
||
from app.schemas.resource_capacity import ResourceCapacityUsageOut
|
||
|
||
|
||
class CreditAdjustRequest(BaseModel):
|
||
amount: float = Field(..., ge=-9999999.99, le=9999999.99, multiple_of=0.01)
|
||
description: str = Field(..., max_length=256)
|
||
|
||
|
||
class ModelConfigCreate(BaseModel):
|
||
name: str = Field(..., max_length=64)
|
||
provider: str = Field(..., max_length=32)
|
||
api_base: str = Field(..., max_length=512)
|
||
api_key: str = Field(..., max_length=256)
|
||
model_name: str = Field(..., max_length=128)
|
||
weight: int = Field(default=1, ge=0)
|
||
max_tokens: int = Field(default=4096, ge=1)
|
||
temperature: float = Field(default=0.7, ge=0, le=2)
|
||
is_active: bool = True
|
||
priority: int = 0
|
||
|
||
|
||
class ModelConfigOut(ModelConfigCreate):
|
||
id: str
|
||
created_at: NaiveDatetime
|
||
deleted_at: NaiveDatetimeOptional = None
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
class SystemConfigCreate(BaseModel):
|
||
key: str
|
||
value: str
|
||
description: str | None = None
|
||
|
||
|
||
class SystemConfigUpdate(BaseModel):
|
||
value: str | int | float
|
||
|
||
|
||
class SystemConfigOut(BaseModel):
|
||
id: str
|
||
key: str
|
||
value: str
|
||
description: str | None = None
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
class AdminUserOut(BaseModel):
|
||
id: str
|
||
username: str
|
||
email: str | None = None
|
||
phone: str | None = None
|
||
credits: float
|
||
is_active: bool
|
||
is_admin: bool
|
||
user_type: str = "frontend"
|
||
frontend_user_kind: str = "external"
|
||
team_id: str | None = None
|
||
team_name: str | None = None
|
||
created_at: NaiveDatetime
|
||
last_login_at: NaiveDatetimeOptional = None
|
||
allowed_menus: list | None = None
|
||
resource_capacity: ResourceCapacityUsageOut | None = None
|
||
private_portrait_asset_limit: int = 50
|
||
single_device_login_override: bool | None = None
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
class CreateUserRequest(BaseModel):
|
||
username: str | None = Field(None, max_length=64)
|
||
password: str = Field(..., min_length=6, max_length=128)
|
||
email: str | None = None
|
||
phone: str | None = None
|
||
credits: float = 0.0
|
||
user_type: str = Field(default="frontend", pattern="^(frontend|admin)$")
|
||
is_admin: bool = False
|
||
frontend_user_kind: str = Field(default="external", pattern="^(internal|external)$")
|
||
allowed_menus: list | None = None
|
||
private_portrait_asset_limit: int = Field(default=50, ge=0, le=9999, description="私域人像素材总量限制,真人/虚拟、图片/视频共用,0 表示关闭")
|
||
|
||
|
||
class UpdateFrontendUserKindRequest(BaseModel):
|
||
frontend_user_kind: str = Field(..., pattern="^(internal|external)$")
|
||
|
||
|
||
class UpdateMenusRequest(BaseModel):
|
||
allowed_menus: list | None = None
|
||
|
||
|
||
class ResetPasswordRequest(BaseModel):
|
||
new_password: str = Field(..., min_length=6, max_length=128)
|
||
|
||
|
||
class OperationLogOut(BaseModel):
|
||
id: str
|
||
user_id: str
|
||
username: str
|
||
action: str
|
||
method: str
|
||
path: str
|
||
detail: str | None = None
|
||
ip: str | None = None
|
||
created_at: NaiveDatetime
|
||
|
||
model_config = {"from_attributes": True}
|
||
|
||
|
||
class DailyCreditOut(BaseModel):
|
||
date: str
|
||
module: str
|
||
credits: float
|
||
|
||
|
||
class TeamCreditOut(BaseModel):
|
||
team_name: str
|
||
team_id: str | None
|
||
credits: float
|
||
|
||
|
||
class ModelUsageOut(BaseModel):
|
||
model_name: str
|
||
provider: str
|
||
count: int
|
||
|
||
|
||
class VideoParamOut(BaseModel):
|
||
model: str
|
||
label: str
|
||
count: int
|
||
|
||
|
||
class AdminStatsOut(BaseModel):
|
||
total_users: int
|
||
total_projects: int
|
||
total_generations: int
|
||
total_records: int
|
||
total_revenue: float
|
||
credits_consumed_today: float
|
||
today_alipay_revenue: float
|
||
today_wechat_revenue: float
|
||
last_period_users: int = 0
|
||
last_period_projects: int = 0
|
||
last_period_generations: int = 0
|
||
last_period_records: int = 0
|
||
last_period_revenue: float = 0.0
|
||
last_period_credits_consumed: float = 0.0
|
||
# 图表数据
|
||
daily_credits_by_module: list[DailyCreditOut] = []
|
||
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):
|
||
total_recharge: float = 0.0
|
||
total_consume: float = 0.0
|
||
total_refund: float = 0.0
|
||
# 消费类分解(仅 type=consume,不含 team_internal 团队内部转账;真实扣费 + 预扣占用 = total_consume)
|
||
# - total_charge : 真实扣费 charge(含历史 NULL),对应"筛选明细类型=消费 且 action=charge/NULL"求和
|
||
# - total_hold : 预扣占用 hold
|
||
total_charge: float = 0.0
|
||
total_hold: float = 0.0
|
||
# 回退类分解(仅 type=refund;真实退款 + 预扣释放 = total_refund)
|
||
# - total_refund_real : 真实退款 refund(含历史 NULL)
|
||
# - total_hold_release: 预扣释放 hold_release
|
||
total_refund_real: float = 0.0
|
||
total_hold_release: float = 0.0
|
||
# 净消耗 = max(total_consume - total_refund, 0) = 实际"用掉了"的积分
|
||
net_consume: float = 0.0
|
||
transaction_count: int = 0
|
||
generation_count: int = 0
|
||
generation_attempt_count: int = 0
|
||
image_generation_count: int = 0
|
||
video_generation_count: int = 0
|
||
image_consume: float = 0.0
|
||
video_consume: float = 0.0
|
||
text_consume: float = 0.0
|
||
analysis_consume: float = 0.0
|
||
total_tokens: int = 0
|
||
input_tokens: int = 0
|
||
output_tokens: int = 0
|
||
|
||
|
||
|
||
|
||
class AdminCreditRecordAllocationOut(BaseModel):
|
||
id: str
|
||
credit_balance_id: str
|
||
source_allocation_id: str | None = None
|
||
allocation_action: str
|
||
amount: float
|
||
credit_level: str
|
||
source_type: str
|
||
source_id: str | None = None
|
||
valid_from: str | None = None
|
||
expires_at: str | None = None
|
||
unspent_before: float = 0.0
|
||
unspent_after: float = 0.0
|
||
consumed_before: float = 0.0
|
||
consumed_after: float = 0.0
|
||
|
||
class AdminCreditRecordOut(BaseModel):
|
||
id: str
|
||
user_id: str
|
||
username: str | None = None
|
||
phone: str | None = None
|
||
email: str | None = None
|
||
user_type: str | None = None
|
||
user_type_label: str | None = None
|
||
frontend_user_kind: str | None = None
|
||
frontend_user_kind_label: str | None = None
|
||
team_id_snapshot: str | None = None
|
||
team_name_snapshot: str | None = None
|
||
type: str
|
||
record_type: str
|
||
record_type_label: str | None = None
|
||
amount: float
|
||
balance_delta: float = 0.0
|
||
expired_amount: float = 0.0
|
||
balance_after: float
|
||
description: str | None = None
|
||
related_id: str | None = None
|
||
biz_key: str | None = None
|
||
refund_for_biz_key: str | None = None
|
||
owner_type: str | None = None
|
||
owner_id: str | None = None
|
||
owner_deleted: bool = False
|
||
owner_deleted_at: str | None = None
|
||
attempt_no: int | None = None
|
||
charge_kind: str | None = None
|
||
charge_kind_label: str | None = None
|
||
charge_action: str | None = None
|
||
charge_action_label: str | None = None
|
||
credit_subject: str | None = None
|
||
credit_subject_label: str | None = None
|
||
media_type: str | None = None
|
||
media_type_label: str | None = None
|
||
billing_scene: str | None = None
|
||
billing_scene_label: str | None = None
|
||
scene_name_snapshot: str | None = None
|
||
request_time: str | None = None
|
||
source_module: str | None = None
|
||
source_module_label: str | None = None
|
||
source_project_id: str | None = None
|
||
source_step_id: str | None = None
|
||
source_step_code: str | None = None
|
||
source_step_code_label: str | None = None
|
||
token_usage_id: str | None = None
|
||
input_tokens: int = 0
|
||
output_tokens: int = 0
|
||
total_tokens: int = 0
|
||
llm_call_count: int = 0
|
||
llm_success_call_count: int = 0
|
||
llm_failed_call_count: int = 0
|
||
allocations: list[AdminCreditRecordAllocationOut] = Field(default_factory=list)
|
||
engine_type: str | None = None
|
||
engine_id: str | None = None
|
||
engine_name: str | None = None
|
||
engine_provider: str | None = None
|
||
engine_model_name: str | None = None
|
||
created_at: str | None = None
|
||
|
||
|
||
class AdminCreditRecordListOut(BaseModel):
|
||
items: list[AdminCreditRecordOut]
|
||
total: int
|
||
summary: AdminCreditRecordSummaryOut
|