- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
155 lines
3.7 KiB
Python
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 # 搜索用户名、邮箱、姓名
|