mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-24 05:26:58 +00:00
1. 重构后端API路由、CRUD与模块结构,整合日志管理,移除废弃demo代码 2. 优化前端组件类型定义、样式与路由配置,修复权限判断逻辑 3. 调整默认排序规则、滚动条样式与工具类函数,更新依赖与配置文件 4. 修复多处类型不匹配与默认值问题,完善表单与菜单验证逻辑
146 lines
5.2 KiB
Python
146 lines
5.2 KiB
Python
from datetime import datetime
|
||
from typing import Any, Generic, TypeVar
|
||
|
||
from pydantic import BaseModel, ConfigDict, Field, model_validator
|
||
|
||
from app.core.validator import DateTimeStr
|
||
|
||
T = TypeVar("T")
|
||
|
||
|
||
class CommonSchema(BaseModel):
|
||
"""通用信息模型"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
id: int = Field(description="编号ID")
|
||
name: str = Field(description="名称")
|
||
|
||
|
||
class BaseSchema(BaseModel):
|
||
"""通用输出模型,包含基础字段和审计字段"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
id: int | None = Field(default=None, description="主键ID")
|
||
uuid: str | None = Field(default=None, description="UUID")
|
||
status: int = Field(default=0, description="状态")
|
||
description: str | None = Field(default=None, description="描述")
|
||
created_time: DateTimeStr | None = Field(default=None, description="创建时间")
|
||
updated_time: DateTimeStr | None = Field(default=None, description="更新时间")
|
||
is_deleted: bool = Field(default=False, description="是否已删除")
|
||
deleted_time: DateTimeStr | None = Field(default=None, description="删除时间")
|
||
|
||
|
||
class UserBySchema(BaseModel):
|
||
"""通用创建模型,包含基础字段和审计字段"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
created_id: int | None = Field(default=None, description="创建人ID")
|
||
created_by: CommonSchema | None = Field(default=None, description="创建人信息")
|
||
updated_id: int | None = Field(default=None, description="更新人ID")
|
||
updated_by: CommonSchema | None = Field(default=None, description="更新人信息")
|
||
deleted_id: int | None = Field(default=None, description="删除人ID")
|
||
deleted_by: CommonSchema | None = Field(default=None, description="删除人信息")
|
||
|
||
|
||
class TenantBySchema(BaseModel):
|
||
"""租户嵌套出参(不再使用扁平 tenant_id / tenant_name / tenant_code)"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
tenant_id: int | None = Field(default=None, description="租户ID")
|
||
tenant_by: CommonSchema | None = Field(default=None, description="租户信息")
|
||
|
||
|
||
class BatchSetAvailable(BaseModel):
|
||
"""批量设置可用状态的请求模型"""
|
||
|
||
ids: list[int] = Field(default_factory=list, description="ID列表")
|
||
status: int = Field(default=0, ge=0, le=1, description="是否可用")
|
||
|
||
|
||
class UploadResponseSchema(BaseModel):
|
||
"""上传响应模型"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
file_path: str | None = Field(default=None, description="新文件映射路径")
|
||
file_name: str | None = Field(default=None, description="新文件名称")
|
||
origin_name: str | None = Field(default=None, description="原文件名称")
|
||
file_url: str | None = Field(default=None, description="新文件访问地址")
|
||
|
||
|
||
class DownloadFileSchema(BaseModel):
|
||
"""下载文件模型"""
|
||
|
||
file_path: str = Field(..., description="新文件映射路径")
|
||
file_name: str = Field(..., description="新文件名称")
|
||
|
||
|
||
class BatchDelete(BaseModel):
|
||
"""批量删除请求模型"""
|
||
|
||
ids: list[int] = Field(..., min_length=1, description="ID列表")
|
||
|
||
|
||
class AuthSchema(BaseModel):
|
||
"""权限认证模型"""
|
||
|
||
model_config = ConfigDict(arbitrary_types_allowed=True)
|
||
|
||
user: Any = Field(default=None, description="用户信息", exclude=True)
|
||
check_data_scope: bool = Field(default=True, description="是否检查数据权限")
|
||
db: Any = Field(default=None, description="数据库会话", exclude=True)
|
||
tenant_id: int | None = Field(default=None, description="租户ID,用于用户认证前查询")
|
||
|
||
|
||
class JWTPayloadSchema(BaseModel):
|
||
"""JWT载荷模型"""
|
||
|
||
sub: str = Field(..., description="用户登录信息")
|
||
is_refresh: bool = Field(default=False, description="是否刷新token")
|
||
exp: datetime | int = Field(..., description="过期时间")
|
||
|
||
@model_validator(mode="after")
|
||
def validate_fields(self):
|
||
if not self.sub or len(self.sub.strip()) == 0:
|
||
raise ValueError("会话编号不能为空")
|
||
return self
|
||
|
||
|
||
class JWTOutSchema(BaseModel):
|
||
"""JWT响应模型"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
access_token: str = Field(..., min_length=1, description="访问token")
|
||
refresh_token: str = Field(..., min_length=1, description="刷新token")
|
||
token_type: str = Field(default="Bearer", description="token类型")
|
||
expires_in: int = Field(..., gt=0, description="过期时间(秒)")
|
||
|
||
|
||
class RefreshTokenPayloadSchema(BaseModel):
|
||
"""刷新Token载荷模型"""
|
||
|
||
refresh_token: str = Field(..., min_length=1, description="刷新token")
|
||
|
||
|
||
class LogoutPayloadSchema(BaseModel):
|
||
"""退出登录载荷模型"""
|
||
|
||
token: str = Field(..., min_length=1, description="token")
|
||
|
||
|
||
class PageResultSchema(BaseModel, Generic[T]):
|
||
"""分页查询结果模型"""
|
||
|
||
model_config = ConfigDict(from_attributes=True)
|
||
|
||
page_no: int | None = Field(default=None, ge=1, description="页码,默认为1")
|
||
page_size: int | None = Field(default=None, ge=1, description="页面大小,默认为10")
|
||
total: int = Field(default=0, ge=0, description="总记录数")
|
||
has_next: bool | None = Field(default=False, description="是否有下一页")
|
||
items: list[T] = Field(default_factory=list, description="分页后的数据列表")
|