feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
352
backend/app/api/v1/admin_portal/schemas.py
Normal file
352
backend/app/api/v1/admin_portal/schemas.py
Normal file
@@ -0,0 +1,352 @@
|
||||
"""
|
||||
管理后台数据模型
|
||||
"""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Optional, List, Any, Dict
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
# ============================================
|
||||
# 通用模型
|
||||
# ============================================
|
||||
|
||||
class ResponseModel(BaseModel):
|
||||
"""通用响应模型"""
|
||||
code: int = 0
|
||||
message: str = "success"
|
||||
data: Optional[Any] = None
|
||||
|
||||
|
||||
class PaginationParams(BaseModel):
|
||||
"""分页参数"""
|
||||
page: int = Field(default=1, ge=1)
|
||||
page_size: int = Field(default=20, ge=1, le=100)
|
||||
|
||||
|
||||
class PaginatedResponse(BaseModel):
|
||||
"""分页响应"""
|
||||
items: List[Any]
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
total_pages: int
|
||||
|
||||
|
||||
# ============================================
|
||||
# 认证相关
|
||||
# ============================================
|
||||
|
||||
class AdminLoginRequest(BaseModel):
|
||||
"""管理员登录请求"""
|
||||
username: str = Field(..., min_length=1, max_length=50)
|
||||
password: str = Field(..., min_length=6)
|
||||
|
||||
|
||||
class AdminLoginResponse(BaseModel):
|
||||
"""管理员登录响应"""
|
||||
access_token: str
|
||||
token_type: str = "bearer"
|
||||
expires_in: int
|
||||
admin_user: "AdminUserInfo"
|
||||
|
||||
|
||||
class AdminUserInfo(BaseModel):
|
||||
"""管理员信息"""
|
||||
id: int
|
||||
username: str
|
||||
email: Optional[str]
|
||||
full_name: Optional[str]
|
||||
role: str
|
||||
last_login_at: Optional[datetime]
|
||||
|
||||
|
||||
class AdminChangePasswordRequest(BaseModel):
|
||||
"""修改密码请求"""
|
||||
old_password: str = Field(..., min_length=6)
|
||||
new_password: str = Field(..., min_length=6)
|
||||
|
||||
|
||||
# ============================================
|
||||
# 租户相关
|
||||
# ============================================
|
||||
|
||||
class TenantBase(BaseModel):
|
||||
"""租户基础信息"""
|
||||
code: str = Field(..., min_length=2, max_length=20, pattern=r'^[a-z0-9_]+$')
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
display_name: Optional[str] = Field(None, max_length=200)
|
||||
domain: str = Field(..., min_length=1, max_length=200)
|
||||
logo_url: Optional[str] = None
|
||||
favicon_url: Optional[str] = None
|
||||
contact_name: Optional[str] = None
|
||||
contact_phone: Optional[str] = None
|
||||
contact_email: Optional[str] = None
|
||||
industry: str = Field(default="medical_beauty")
|
||||
remarks: Optional[str] = None
|
||||
|
||||
|
||||
class TenantCreate(TenantBase):
|
||||
"""创建租户请求"""
|
||||
pass
|
||||
|
||||
|
||||
class TenantUpdate(BaseModel):
|
||||
"""更新租户请求"""
|
||||
name: Optional[str] = Field(None, min_length=1, max_length=100)
|
||||
display_name: Optional[str] = Field(None, max_length=200)
|
||||
domain: Optional[str] = Field(None, min_length=1, max_length=200)
|
||||
logo_url: Optional[str] = None
|
||||
favicon_url: Optional[str] = None
|
||||
contact_name: Optional[str] = None
|
||||
contact_phone: Optional[str] = None
|
||||
contact_email: Optional[str] = None
|
||||
industry: Optional[str] = None
|
||||
status: Optional[str] = None
|
||||
expire_at: Optional[datetime] = None
|
||||
remarks: Optional[str] = None
|
||||
|
||||
|
||||
class TenantResponse(TenantBase):
|
||||
"""租户响应"""
|
||||
id: int
|
||||
status: str
|
||||
expire_at: Optional[datetime]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
config_count: int = 0 # 配置项数量
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TenantListResponse(BaseModel):
|
||||
"""租户列表响应"""
|
||||
items: List[TenantResponse]
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
|
||||
|
||||
# ============================================
|
||||
# 配置相关
|
||||
# ============================================
|
||||
|
||||
class ConfigTemplateResponse(BaseModel):
|
||||
"""配置模板响应"""
|
||||
id: int
|
||||
config_group: str
|
||||
config_key: str
|
||||
display_name: str
|
||||
description: Optional[str]
|
||||
value_type: str
|
||||
default_value: Optional[str]
|
||||
is_required: bool
|
||||
is_secret: bool
|
||||
options: Optional[List[str]]
|
||||
sort_order: int
|
||||
|
||||
|
||||
class TenantConfigBase(BaseModel):
|
||||
"""租户配置基础"""
|
||||
config_group: str
|
||||
config_key: str
|
||||
config_value: Optional[str] = None
|
||||
|
||||
|
||||
class TenantConfigCreate(TenantConfigBase):
|
||||
"""创建租户配置请求"""
|
||||
pass
|
||||
|
||||
|
||||
class TenantConfigUpdate(BaseModel):
|
||||
"""更新租户配置请求"""
|
||||
config_value: Optional[str] = None
|
||||
|
||||
|
||||
class TenantConfigResponse(TenantConfigBase):
|
||||
"""租户配置响应"""
|
||||
id: int
|
||||
value_type: str
|
||||
is_encrypted: bool
|
||||
description: Optional[str]
|
||||
created_at: Optional[datetime] = None
|
||||
updated_at: Optional[datetime] = None
|
||||
# 从模板获取的额外信息
|
||||
display_name: Optional[str] = None
|
||||
is_required: bool = False
|
||||
is_secret: bool = False
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TenantConfigGroupResponse(BaseModel):
|
||||
"""租户配置分组响应"""
|
||||
group_name: str
|
||||
group_display_name: str
|
||||
configs: List[TenantConfigResponse]
|
||||
|
||||
|
||||
class ConfigBatchUpdate(BaseModel):
|
||||
"""批量更新配置请求"""
|
||||
configs: List[TenantConfigCreate]
|
||||
|
||||
|
||||
# ============================================
|
||||
# 提示词相关
|
||||
# ============================================
|
||||
|
||||
class AIPromptBase(BaseModel):
|
||||
"""AI提示词基础"""
|
||||
code: str = Field(..., min_length=1, max_length=50)
|
||||
name: str = Field(..., min_length=1, max_length=100)
|
||||
description: Optional[str] = None
|
||||
module: str
|
||||
system_prompt: str
|
||||
user_prompt_template: Optional[str] = None
|
||||
variables: Optional[List[str]] = None
|
||||
output_schema: Optional[Dict] = None
|
||||
model_recommendation: Optional[str] = None
|
||||
max_tokens: int = 4096
|
||||
temperature: float = 0.7
|
||||
|
||||
|
||||
class AIPromptCreate(AIPromptBase):
|
||||
"""创建提示词请求"""
|
||||
pass
|
||||
|
||||
|
||||
class AIPromptUpdate(BaseModel):
|
||||
"""更新提示词请求"""
|
||||
name: Optional[str] = Field(None, min_length=1, max_length=100)
|
||||
description: Optional[str] = None
|
||||
system_prompt: Optional[str] = None
|
||||
user_prompt_template: Optional[str] = None
|
||||
variables: Optional[List[str]] = None
|
||||
output_schema: Optional[Dict] = None
|
||||
model_recommendation: Optional[str] = None
|
||||
max_tokens: Optional[int] = None
|
||||
temperature: Optional[float] = None
|
||||
is_active: Optional[bool] = None
|
||||
|
||||
|
||||
class AIPromptResponse(AIPromptBase):
|
||||
"""提示词响应"""
|
||||
id: int
|
||||
is_system: bool
|
||||
is_active: bool
|
||||
version: int
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class AIPromptVersionResponse(BaseModel):
|
||||
"""提示词版本响应"""
|
||||
id: int
|
||||
prompt_id: int
|
||||
version: int
|
||||
system_prompt: str
|
||||
user_prompt_template: Optional[str]
|
||||
variables: Optional[List[str]]
|
||||
change_summary: Optional[str]
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TenantPromptResponse(BaseModel):
|
||||
"""租户自定义提示词响应"""
|
||||
id: int
|
||||
tenant_id: int
|
||||
prompt_id: int
|
||||
prompt_code: str
|
||||
prompt_name: str
|
||||
system_prompt: Optional[str]
|
||||
user_prompt_template: Optional[str]
|
||||
is_active: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class TenantPromptUpdate(BaseModel):
|
||||
"""更新租户自定义提示词"""
|
||||
system_prompt: Optional[str] = None
|
||||
user_prompt_template: Optional[str] = None
|
||||
is_active: Optional[bool] = None
|
||||
|
||||
|
||||
# ============================================
|
||||
# 功能开关相关
|
||||
# ============================================
|
||||
|
||||
class FeatureSwitchBase(BaseModel):
|
||||
"""功能开关基础"""
|
||||
feature_code: str
|
||||
feature_name: str
|
||||
feature_group: Optional[str] = None
|
||||
is_enabled: bool = True
|
||||
config: Optional[Dict] = None
|
||||
description: Optional[str] = None
|
||||
|
||||
|
||||
class FeatureSwitchCreate(FeatureSwitchBase):
|
||||
"""创建功能开关请求"""
|
||||
pass
|
||||
|
||||
|
||||
class FeatureSwitchUpdate(BaseModel):
|
||||
"""更新功能开关请求"""
|
||||
is_enabled: Optional[bool] = None
|
||||
config: Optional[Dict] = None
|
||||
|
||||
|
||||
class FeatureSwitchResponse(FeatureSwitchBase):
|
||||
"""功能开关响应"""
|
||||
id: int
|
||||
tenant_id: Optional[int]
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class FeatureSwitchGroupResponse(BaseModel):
|
||||
"""功能开关分组响应"""
|
||||
group_name: str
|
||||
group_display_name: str
|
||||
features: List[FeatureSwitchResponse]
|
||||
|
||||
|
||||
# ============================================
|
||||
# 操作日志相关
|
||||
# ============================================
|
||||
|
||||
class OperationLogResponse(BaseModel):
|
||||
"""操作日志响应"""
|
||||
id: int
|
||||
admin_username: Optional[str]
|
||||
tenant_code: Optional[str]
|
||||
operation_type: str
|
||||
resource_type: str
|
||||
resource_name: Optional[str]
|
||||
old_value: Optional[Dict]
|
||||
new_value: Optional[Dict]
|
||||
ip_address: Optional[str]
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
|
||||
# 更新前向引用
|
||||
AdminLoginResponse.model_rebuild()
|
||||
|
||||
Reference in New Issue
Block a user