- Permission 模型新增 sort 字段
- 后端 API 按 sort 升序排列树形菜单
- 前端菜单管理页面增加排序列
- 初始数据添加排序号
- 修复 GET /permissions/{id} 详情接口 bug
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
337 lines
12 KiB
Python
337 lines
12 KiB
Python
from pydantic import BaseModel, Field
|
||
from typing import Optional
|
||
from datetime import datetime
|
||
|
||
|
||
class UserBase(BaseModel):
|
||
"""用户基础模型"""
|
||
|
||
username: str = Field(
|
||
...,
|
||
min_length=3,
|
||
max_length=50,
|
||
description="登录名",
|
||
json_schema_extra={
|
||
"error_messages": {
|
||
"min_length": "用户名长度至少为3个字符",
|
||
"max_length": "用户名长度不能超过50个字符"
|
||
}
|
||
}
|
||
)
|
||
nickname: str = Field(..., max_length=50, description="昵称")
|
||
email: Optional[str] = Field(None, max_length=50, description="电子邮箱")
|
||
phone: Optional[str] = Field(None, max_length=11, description="手机号码")
|
||
wx_openid: Optional[str] = Field(None, max_length=100, description="微信OpenID")
|
||
avatar: Optional[str] = Field(None, max_length=255, description="头像路径")
|
||
role_id: Optional[int] = Field(2, description="角色ID")
|
||
|
||
model_config = {"extra": "ignore"}
|
||
|
||
|
||
class UserCreateRequest(UserBase):
|
||
"""用户创建请求模型"""
|
||
|
||
password: str = Field(
|
||
...,
|
||
min_length=6,
|
||
max_length=50,
|
||
description="密码",
|
||
json_schema_extra={
|
||
"error_messages": {
|
||
"min_length": "密码长度至少为6个字符",
|
||
"max_length": "密码长度不能超过50个字符"
|
||
}
|
||
}
|
||
)
|
||
|
||
|
||
class UserCreate(UserBase):
|
||
"""用户创建模型"""
|
||
|
||
password_hash: str = Field(
|
||
..., min_length=6, max_length=128, description="密码哈希值"
|
||
)
|
||
|
||
|
||
class UserUpdate(BaseModel):
|
||
"""用户更新模型"""
|
||
|
||
username: str = Field(..., min_length=3, max_length=50, description="登录名")
|
||
nickname: str = Field(..., max_length=50, description="昵称")
|
||
email: Optional[str] = Field(None, max_length=50, description="电子邮箱")
|
||
phone: Optional[str] = Field(None, max_length=11, description="手机号码")
|
||
wx_openid: Optional[str] = Field(None, max_length=100, description="微信OpenID")
|
||
avatar: Optional[str] = Field(None, max_length=255, description="头像路径")
|
||
role_id: Optional[int] = Field(2, description="角色ID")
|
||
password: Optional[str] = Field(None, max_length=128, description="密码")
|
||
|
||
|
||
class UserLogin(BaseModel):
|
||
"""用户登录模型"""
|
||
|
||
username: str = Field(..., description="用户名/邮箱/手机号")
|
||
password: str = Field(..., description="密码")
|
||
captcha_id: str = Field(..., description="验证码ID")
|
||
captcha_code: str = Field(..., description="验证码")
|
||
|
||
|
||
class UserResponse(BaseModel):
|
||
"""用户响应模型"""
|
||
|
||
id: int = Field(..., description="用户ID")
|
||
username: str = Field(..., description="登录名")
|
||
nickname: str = Field(..., description="昵称")
|
||
email: Optional[str] = Field(None, description="电子邮箱")
|
||
phone: Optional[str] = Field(None, description="手机号码")
|
||
wx_openid: Optional[str] = Field(None, description="微信OpenID")
|
||
avatar: Optional[str] = Field(None, description="头像路径")
|
||
role_id: int = Field(..., description="角色ID")
|
||
createtime: datetime = Field(..., description="创建时间")
|
||
updatetime: datetime = Field(..., description="更新时间")
|
||
lastlogintime: Optional[datetime] = Field(None, description="最后登录时间")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class Token(BaseModel):
|
||
"""令牌模型"""
|
||
|
||
access_token: str = Field(..., description="访问令牌")
|
||
token_type: str = Field(..., description="令牌类型")
|
||
|
||
|
||
class TokenData(BaseModel):
|
||
"""令牌数据模型"""
|
||
|
||
user_id: Optional[int] = None
|
||
email: Optional[str] = None
|
||
|
||
|
||
class RoleBase(BaseModel):
|
||
"""角色基础模型"""
|
||
|
||
name: str = Field(..., max_length=50, description="角色名称")
|
||
|
||
|
||
class RoleCreate(RoleBase):
|
||
"""角色创建模型"""
|
||
|
||
creator: Optional[str] = Field(None, max_length=50, description="创建人")
|
||
|
||
|
||
class RoleResponse(RoleBase):
|
||
"""角色响应模型"""
|
||
|
||
id: int = Field(..., description="角色ID")
|
||
createtime: datetime = Field(..., description="创建时间")
|
||
updatetime: datetime = Field(..., description="更新时间")
|
||
creator: Optional[str] = Field(None, description="创建人")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
# 权限相关模型
|
||
class PermissionBase(BaseModel):
|
||
"""权限基础模型"""
|
||
|
||
name: str = Field(..., max_length=100, description="权限名称")
|
||
code: str = Field(..., max_length=100, description="权限编码")
|
||
parentid: int = Field(0, description="父权限ID(0表示顶级模块)")
|
||
route: Optional[str] = Field(None, max_length=255, description="前端路由路径")
|
||
description: Optional[str] = Field(None, max_length=255, description="权限描述")
|
||
sort: int = Field(0, description="排序号(升序排列)")
|
||
|
||
|
||
class PermissionCreate(PermissionBase):
|
||
"""权限创建模型"""
|
||
pass
|
||
|
||
|
||
class PermissionResponse(PermissionBase):
|
||
"""权限响应模型"""
|
||
|
||
id: int = Field(..., description="权限ID")
|
||
createtime: datetime = Field(..., description="创建时间")
|
||
updatetime: datetime = Field(..., description="更新时间")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class PermissionTreeResponse(BaseModel):
|
||
"""权限树响应模型"""
|
||
|
||
id: int = Field(..., description="权限ID")
|
||
name: str = Field(..., description="权限名称")
|
||
code: str = Field(..., description="权限编码")
|
||
parentid: int = Field(..., description="父权限ID")
|
||
route: Optional[str] = Field(None, description="前端路由路径")
|
||
createtime: Optional[datetime] = Field(None, description="创建时间")
|
||
updatetime: Optional[datetime] = Field(None, description="更新时间")
|
||
description: Optional[str] = Field(None, description="权限描述")
|
||
sort: int = Field(0, description="排序号")
|
||
children: list = Field([], description="子权限列表")
|
||
|
||
|
||
# 角色权限关联相关模型
|
||
class RolePermissionAssign(BaseModel):
|
||
"""角色权限分配模型"""
|
||
|
||
role_id: int = Field(..., description="角色ID")
|
||
permission_ids: list[int] = Field(..., description="权限ID列表")
|
||
|
||
|
||
class RolePermissionResponse(BaseModel):
|
||
"""角色权限响应模型"""
|
||
|
||
role_id: int = Field(..., description="角色ID")
|
||
role_name: str = Field(..., description="角色名称")
|
||
permissions: list[PermissionResponse] = Field(..., description="权限列表")
|
||
menu: list = Field([], description="菜单树形结构")
|
||
|
||
|
||
# 系统设置相关模型
|
||
class SystemSettingBase(BaseModel):
|
||
"""系统设置基础模型"""
|
||
|
||
key: str = Field(..., max_length=100, description="设置键名")
|
||
value: str = Field(..., max_length=2000, description="设置值")
|
||
type: Optional[str] = Field("string", max_length=20, description="类型:string/image/select/boolean")
|
||
options: Optional[str] = Field(None, max_length=500, description="下拉选项(用|分隔)")
|
||
description: Optional[str] = Field(None, max_length=255, description="设置描述")
|
||
|
||
model_config = {"extra": "ignore"}
|
||
|
||
|
||
class SystemSettingCreate(SystemSettingBase):
|
||
"""系统设置创建模型"""
|
||
pass
|
||
|
||
|
||
class SystemSettingUpdate(SystemSettingBase):
|
||
"""系统设置更新模型"""
|
||
key: Optional[str] = Field(None, max_length=100, description="设置键名")
|
||
|
||
|
||
class SystemSettingResponse(BaseModel):
|
||
"""系统设置响应模型"""
|
||
|
||
id: int = Field(..., description="设置ID")
|
||
key: str = Field(..., description="设置键名")
|
||
value: str = Field(..., description="设置值")
|
||
type: str = Field(..., description="类型")
|
||
options: Optional[str] = Field(None, description="下拉选项")
|
||
description: Optional[str] = Field(None, description="设置描述")
|
||
createtime: datetime = Field(..., description="创建时间")
|
||
updatetime: datetime = Field(..., description="更新时间")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class LoginLogResponse(BaseModel):
|
||
"""登录日志响应模型"""
|
||
|
||
id: int = Field(..., description="日志ID")
|
||
username: str = Field(..., description="用户名")
|
||
login_time: datetime = Field(..., description="登录时间")
|
||
ip_address: Optional[str] = Field(None, description="IP地址")
|
||
user_agent: Optional[str] = Field(None, description="User-Agent")
|
||
status: str = Field(..., description="状态: success/failure")
|
||
failure_reason: Optional[str] = Field(None, description="失败原因")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class LoginLogSearch(BaseModel):
|
||
"""登录日志搜索模型"""
|
||
|
||
username: Optional[str] = Field(None, description="用户名(模糊搜索)")
|
||
status: Optional[str] = Field(None, description="状态")
|
||
start_time: Optional[datetime] = Field(None, description="开始时间")
|
||
end_time: Optional[datetime] = Field(None, description="结束时间")
|
||
|
||
|
||
class LoginLogCleanRequest(BaseModel):
|
||
"""登录日志清理请求模型"""
|
||
|
||
before_date: datetime = Field(..., description="清理此日期之前的日志")
|
||
|
||
|
||
class OperationLogResponse(BaseModel):
|
||
"""操作日志响应模型"""
|
||
|
||
id: int = Field(..., description="日志ID")
|
||
user_id: int = Field(..., description="用户ID")
|
||
username: str = Field(..., description="用户名")
|
||
action_type: str = Field(..., description="操作类型: create/update/delete")
|
||
target_type: str = Field(..., description="目标类型: user/role/permission/setting")
|
||
target_id: Optional[int] = Field(None, description="目标ID")
|
||
target_name: Optional[str] = Field(None, description="目标名称")
|
||
detail: Optional[str] = Field(None, description="变更详情(JSON)")
|
||
ip_address: Optional[str] = Field(None, description="IP地址")
|
||
user_agent: Optional[str] = Field(None, description="User-Agent")
|
||
createtime: datetime = Field(..., description="创建时间")
|
||
|
||
class Config:
|
||
from_attributes = True
|
||
|
||
|
||
class OperationLogSearch(BaseModel):
|
||
"""操作日志搜索模型"""
|
||
|
||
username: Optional[str] = Field(None, description="用户名(模糊搜索)")
|
||
action_type: Optional[str] = Field(None, description="操作类型")
|
||
target_type: Optional[str] = Field(None, description="目标类型")
|
||
start_time: Optional[datetime] = Field(None, description="开始时间")
|
||
end_time: Optional[datetime] = Field(None, description="结束时间")
|
||
|
||
|
||
# ========================================
|
||
# 用户注册相关模型
|
||
# ========================================
|
||
|
||
|
||
class PhoneSendCodeRequest(BaseModel):
|
||
"""发送短信验证码请求"""
|
||
phone: str = Field(..., pattern=r"^\d{11}$", description="手机号(11位数字)")
|
||
|
||
|
||
class PhoneSendCodeResponse(BaseModel):
|
||
"""发送短信验证码响应"""
|
||
message: str = "验证码已发送"
|
||
expire_seconds: int = 300
|
||
|
||
|
||
class PhoneRegisterRequest(BaseModel):
|
||
"""手机号注册请求"""
|
||
username: str = Field(..., min_length=3, max_length=50, description="用户名")
|
||
phone: str = Field(..., pattern=r"^\d{11}$", description="手机号")
|
||
code: str = Field(..., min_length=6, max_length=6, description="短信验证码")
|
||
password: str = Field(..., min_length=6, max_length=50, description="密码")
|
||
nickname: str = Field(..., max_length=50, description="昵称")
|
||
|
||
|
||
class EmailRegisterInitRequest(BaseModel):
|
||
"""邮箱注册初始化请求"""
|
||
username: str = Field(..., min_length=3, max_length=50, description="用户名")
|
||
email: str = Field(..., max_length=50, description="电子邮箱")
|
||
password: str = Field(..., min_length=6, max_length=50, description="密码")
|
||
nickname: str = Field(..., max_length=50, description="昵称")
|
||
|
||
|
||
class EmailRegisterInitResponse(BaseModel):
|
||
"""邮箱注册初始化响应"""
|
||
message: str = "验证邮件已发送,请查收并点击链接完成注册"
|
||
expire_minutes: int = 30
|
||
|
||
|
||
class RegisterSuccessResponse(BaseModel):
|
||
"""注册成功响应"""
|
||
id: int
|
||
username: str
|
||
nickname: str
|
||
message: str = "注册成功" |