Files
012-kaopeilian/backend/app/schemas/user.py
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

155 lines
3.7 KiB
Python

"""
用户相关 Schema
"""
from datetime import datetime
from typing import List, Optional
from pydantic import EmailStr, Field, field_validator
from .base import BaseSchema
class UserBase(BaseSchema):
"""用户基础信息"""
username: str = Field(..., min_length=3, max_length=50)
email: Optional[EmailStr] = None
phone: Optional[str] = Field(None, pattern=r"^1[3-9]\d{9}$")
full_name: Optional[str] = Field(None, max_length=100)
avatar_url: Optional[str] = None
bio: Optional[str] = None
role: str = Field(default="trainee", pattern="^(admin|manager|trainee)$")
gender: Optional[str] = Field(None, pattern="^(male|female)$")
school: Optional[str] = Field(None, max_length=100)
major: Optional[str] = Field(None, max_length=100)
class UserCreate(UserBase):
"""创建用户"""
password: str = Field(..., min_length=6, max_length=100)
@field_validator("password")
def validate_password(cls, v):
if len(v) < 6:
raise ValueError("密码长度至少为6位")
return v
class UserUpdate(BaseSchema):
"""更新用户"""
email: Optional[EmailStr] = None
phone: Optional[str] = Field(None, pattern=r"^1[3-9]\d{9}$")
full_name: Optional[str] = Field(None, max_length=100)
avatar_url: Optional[str] = None
bio: Optional[str] = None
role: Optional[str] = Field(None, pattern="^(admin|manager|trainee)$")
is_active: Optional[bool] = None
gender: Optional[str] = Field(None, pattern="^(male|female)$")
school: Optional[str] = Field(None, max_length=100)
major: Optional[str] = Field(None, max_length=100)
class UserPasswordUpdate(BaseSchema):
"""更新密码"""
old_password: str
new_password: str = Field(..., min_length=6, max_length=100)
class UserInDBBase(UserBase):
"""数据库中的用户基础信息"""
id: int
is_active: bool
is_verified: bool
created_at: datetime
updated_at: datetime
last_login_at: Optional[datetime] = None
class User(UserInDBBase):
"""用户信息(不含敏感数据)"""
teams: List["TeamBasic"] = []
class UserWithPassword(UserInDBBase):
"""用户信息(含密码)"""
hashed_password: str
# Team Schemas
class TeamBase(BaseSchema):
"""团队基础信息"""
name: str = Field(..., min_length=2, max_length=100)
code: str = Field(..., min_length=2, max_length=50)
description: Optional[str] = None
team_type: str = Field(
default="department", pattern="^(department|project|study_group)$"
)
class TeamCreate(TeamBase):
"""创建团队"""
leader_id: Optional[int] = None
parent_id: Optional[int] = None
class TeamUpdate(BaseSchema):
"""更新团队"""
name: Optional[str] = Field(None, min_length=2, max_length=100)
description: Optional[str] = None
leader_id: Optional[int] = None
is_active: Optional[bool] = None
class TeamBasic(BaseSchema):
"""团队基本信息"""
id: int
name: str
code: str
team_type: str
class Team(TeamBase):
"""团队完整信息"""
id: int
is_active: bool
leader_id: Optional[int] = None
parent_id: Optional[int] = None
created_at: datetime
updated_at: datetime
member_count: Optional[int] = 0
class TeamWithMembers(Team):
"""团队信息(含成员)"""
members: List[User] = []
leader: Optional[User] = None
# 避免循环引用
UserBase.model_rebuild()
User.model_rebuild()
Team.model_rebuild()
# Filter schemas
class UserFilter(BaseSchema):
"""用户筛选条件"""
role: Optional[str] = Field(None, pattern="^(admin|manager|trainee)$")
is_active: Optional[bool] = None
team_id: Optional[int] = None
keyword: Optional[str] = None # 搜索用户名、邮箱、姓名