feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View 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()