""" 用户相关 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 # 搜索用户名、邮箱、姓名