| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276 |
- """
- 后台管理系统数据传输对象定义
- 定义管理员认证、用户管理、模型管理相关API请求和响应的数据结构
- """
- from datetime import datetime, date
- from decimal import Decimal
- from typing import Optional, List
- from pydantic import BaseModel, ConfigDict, Field
- # ==================== 认证相关 Schema ====================
- class AdminLoginRequest(BaseModel):
- """管理员登录请求"""
- username: str = Field(..., min_length=1, max_length=50, description="用户名")
- password: str = Field(..., min_length=1, max_length=100, description="密码")
- class AdminLoginResponse(BaseModel):
- """管理员登录响应"""
- token: str = Field(..., description="JWT Token")
- admin_id: int = Field(..., description="管理员ID")
- username: str = Field(..., description="用户名")
- nickname: str = Field(..., description="昵称")
- expires_at: datetime = Field(..., description="Token过期时间")
- class AdminInfo(BaseModel):
- """管理员信息"""
- id: int
- username: str
- nickname: str
- status: str
- created_at: datetime
- model_config = ConfigDict(from_attributes=True)
- # ==================== 用户管理相关 Schema ====================
- class UserListParams(BaseModel):
- """用户列表查询参数"""
- keyword: Optional[str] = Field(None, description="搜索关键词(用户ID/用户名/手机号/邮箱)")
- status: Optional[str] = Field(None, description="账户状态:active/disabled")
- register_start: Optional[date] = Field(None, description="注册开始日期")
- register_end: Optional[date] = Field(None, description="注册结束日期")
- sort_by: Optional[str] = Field("created_at", description="排序字段:created_at")
- sort_order: Optional[str] = Field("desc", description="排序方向:asc/desc")
- page: int = Field(1, ge=1, description="页码")
- size: int = Field(20, ge=1, le=100, description="每页数量")
- class UserListItem(BaseModel):
- """用户列表项"""
- id: str
- username: Optional[str] = None
- nickname: str
- phone: Optional[str] = None
- registration_date: Optional[date] = None
- status: str = "active"
- is_verified: Optional[str] = None
- real_name: Optional[str] = None
- model_config = ConfigDict(from_attributes=True)
- class UserDetailResponse(BaseModel):
- """用户详情响应"""
- id: str
- username: Optional[str] = None
- nickname: str
- phone: Optional[str] = None
- email: Optional[str] = None
- avatar: Optional[str] = None
- registration_date: Optional[date] = None
- status: str = "active"
- model_config = ConfigDict(from_attributes=True)
- class UserUsageStats(BaseModel):
- """用户使用统计"""
- conversation_count: int = 0
- token_consumed: int = 0
- image_count: int = 0
- audio_count: int = 0
- audio_duration: int = 0
- video_count: int = 0
- api_call_count: int = 0
- api_input_tokens: int = 0
- api_output_tokens: int = 0
- class UserStatusRequest(BaseModel):
- """用户状态变更请求"""
- status: str = Field(..., pattern="^(active|disabled)$", description="目标状态:active/disabled")
- class ResetPasswordResponse(BaseModel):
- """密码重置响应"""
- user_id: str
- new_password: str
- # ==================== 模型管理相关 Schema ====================
- class ModelListParams(BaseModel):
- """模型列表查询参数"""
- keyword: Optional[str] = Field(None, description="搜索关键词(模型标识/显示名称/供应商)")
- category: Optional[int] = Field(None, description="模型分类")
- supplier: Optional[str] = Field(None, description="供应商")
- is_show_enabled: Optional[bool] = Field(None, description="是否展示")
- is_api_enabled: Optional[bool] = Field(None, description="是否启用API")
- page: int = Field(1, ge=1, description="页码")
- size: int = Field(20, ge=1, le=100, description="每页数量")
- class ModelListItem(BaseModel):
- """模型列表项"""
- id: int
- model_code: str
- display_name: Optional[str] = None
- img: str = ""
- category: int
- categories: List[int] = []
- supplier: str
- description: Optional[str] = None # 描述摘要(前80字)
- # 价格摘要:取第一条 is_active 价格记录
- price_label: Optional[str] = None # 如 "input<=32k"
- input_price_original: Optional[Decimal] = None
- output_price_original: Optional[Decimal] = None
- input_price_discounted: Optional[Decimal] = None
- output_price_discounted: Optional[Decimal] = None
- discount_rate: Optional[Decimal] = None
- discount_label: Optional[str] = None
- price_unit: Optional[str] = None
- is_show_enabled: bool = True
- is_api_enabled: bool = False
- is_featured: bool = False
- is_search: bool = False
- is_thinking: bool = False
- model_config = ConfigDict(from_attributes=True)
- class PriceTierItem(BaseModel):
- """价格阶梯项"""
- tier_min: int
- tier_max: Optional[int] = None
- input_price: Decimal
- output_price: Decimal
- class ModelPriceDetail(BaseModel):
- """模型价格详情"""
- id: Optional[int] = None
- pricing_mode: str = "simple"
- input_price: Optional[Decimal] = None
- output_price: Optional[Decimal] = None
- unit: str = "tokens"
- currency: str = "CNY"
- tiers: Optional[List[PriceTierItem]] = None
- class ModelDetailResponse(BaseModel):
- """模型详情响应"""
- id: int
- model_code: str
- display_name: Optional[str] = None
- img: Optional[str] = None
- category: int
- supplier: str
- description: Optional[str] = None
- custom_description: Optional[str] = None
- tag1: Optional[str] = None
- tag2: Optional[str] = None
- keywords: Optional[str] = None
- is_featured: bool = False
- is_search: bool = False
- is_thinking: bool = False
- is_show_enabled: bool = True
- is_api_enabled: bool = False
- source_keys: Optional[List[str]] = None
- normalized_keys: Optional[List[str]] = None
- created_at: datetime
- updated_at: datetime
- model_config = ConfigDict(from_attributes=True)
- class ModelCreateRequest(BaseModel):
- """模型创建请求"""
- model_code: str = Field(..., min_length=1, max_length=200, description="模型唯一标识")
- display_name: Optional[str] = Field(None, max_length=255, description="显示名称")
- img: Optional[str] = Field(None, description="图标URL")
- category: int = Field(0, ge=0, le=8, description="模型分类")
- supplier: str = Field("Qwen", min_length=1, max_length=100, description="供应商")
- description: Optional[str] = Field(None, description="模型描述")
- custom_description: Optional[str] = Field(None, description="管理员自定义描述")
- tag1: Optional[str] = Field(None, max_length=100, description="主标签")
- tag2: Optional[str] = Field(None, max_length=100, description="次要标签")
- keywords: Optional[str] = Field(None, description="关键词")
- is_featured: bool = Field(False, description="是否精选")
- is_search: bool = Field(False, description="是否支持搜索")
- is_thinking: bool = Field(False, description="是否支持思考")
- is_show_enabled: bool = Field(True, description="是否展示")
- is_api_enabled: bool = Field(False, description="是否启用API")
- class ModelUpdateRequest(BaseModel):
- """模型更新请求"""
- display_name: Optional[str] = Field(None, max_length=255, description="显示名称")
- img: Optional[str] = Field(None, description="图标URL")
- category: Optional[int] = Field(None, ge=0, le=8, description="模型分类")
- supplier: Optional[str] = Field(None, min_length=1, max_length=100, description="供应商")
- description: Optional[str] = Field(None, description="模型描述")
- custom_description: Optional[str] = Field(None, description="管理员自定义描述")
- tag1: Optional[str] = Field(None, max_length=100, description="主标签")
- tag2: Optional[str] = Field(None, max_length=100, description="次要标签")
- keywords: Optional[str] = Field(None, description="关键词")
- is_featured: Optional[bool] = Field(None, description="是否精选")
- is_search: Optional[bool] = Field(None, description="是否支持搜索")
- is_thinking: Optional[bool] = Field(None, description="是否支持思考")
- class ModelPriceRequest(BaseModel):
- """模型价格设置请求"""
- label: str = Field("default", description="价格标签,如 input<=128k / 视频生成(720P)")
- tier_min: Optional[Decimal] = Field(None, description="阶梯下限")
- tier_max: Optional[Decimal] = Field(None, description="阶梯上限")
- tier_unit: Optional[str] = Field(None, description="阶梯单位:tokens/seconds/images")
- input_price: Optional[Decimal] = Field(None, description="输入原价")
- output_price: Optional[Decimal] = Field(None, description="输出原价")
- discount_rate: Optional[Decimal] = Field(Decimal("100"), description="折扣率 0-100,100=无折扣")
- unit: str = Field("元/每百万tokens", description="显示单位")
- display_multiplier: int = Field(1000000, description="展示倍数")
- currency: str = Field("CNY", description="货币单位")
- class ModelStatusRequest(BaseModel):
- """模型状态变更请求"""
- field: str = Field(..., pattern="^(is_show_enabled|is_api_enabled|is_featured)$", description="状态字段")
- value: bool = Field(..., description="目标值")
- # ==================== 本地模型管理相关 Schema ====================
- class LocalModelListParams(BaseModel):
- """本地模型列表查询参数"""
- keyword: Optional[str] = Field(None, description="搜索关键词")
- user_id: Optional[str] = Field(None, description="用户ID筛选")
- visibility: Optional[str] = Field(None, description="可见性筛选: user/global")
- page: int = Field(1, ge=1, description="页码")
- size: int = Field(20, ge=1, le=100, description="每页数量")
- class LocalModelListItem(BaseModel):
- """本地模型列表项"""
- id: int
- title: str
- name: str
- supplier: Optional[str] = "Custom"
- user_id: str
- username: Optional[str] = None
- base_url: str
- visibility: str = "user"
- category: int = 0
- created_at: datetime
- updated_at: datetime
- model_config = ConfigDict(from_attributes=True)
- class LocalModelVisibilityRequest(BaseModel):
- """本地模型可见性变更请求"""
- visibility: str = Field(..., pattern="^(user|global)$", description="可见性: user/global")
|