""" 用户模型 定义用户数据表结构。 """ from datetime import datetime, timezone from typing import TYPE_CHECKING from uuid import uuid4 from sqlalchemy import Boolean, DateTime, String, Text, func from sqlalchemy.orm import Mapped, mapped_column, relationship from app.database import Base if TYPE_CHECKING: from app.models.balance import UserBalance def generate_uuid() -> str: """生成 UUID 字符串""" return str(uuid4()) def utc_now() -> datetime: """获取当前 UTC 时间""" return datetime.now(timezone.utc) class User(Base): """用户模型""" __tablename__ = "users" # 主键:使用 UUID 字符串 id: Mapped[str] = mapped_column( String(36), primary_key=True, default=generate_uuid, comment="用户唯一标识", ) # 账户信息 username: Mapped[str] = mapped_column( String(32), unique=True, index=True, nullable=False, comment="用户名", ) email: Mapped[str | None] = mapped_column( String(255), unique=True, index=True, nullable=True, comment="邮箱地址", ) hashed_password: Mapped[str | None] = mapped_column( String(255), nullable=True, # OAuth2 用户可能没有密码 comment="密码哈希", ) # OAuth2 关联信息 oauth_provider: Mapped[str | None] = mapped_column( String(32), nullable=True, index=True, comment="OAuth2 提供商(如 linuxdo)", ) oauth_user_id: Mapped[str | None] = mapped_column( String(128), nullable=True, index=True, comment="OAuth2 用户 ID", ) # 用户状态 is_active: Mapped[bool] = mapped_column( Boolean, default=True, nullable=False, comment="是否激活", ) is_superuser: Mapped[bool] = mapped_column( Boolean, default=False, nullable=False, comment="是否为超级管理员", ) # 个人信息 nickname: Mapped[str | None] = mapped_column( String(64), nullable=True, comment="昵称", ) avatar_url: Mapped[str | None] = mapped_column( String(512), nullable=True, comment="头像 URL", ) bio: Mapped[str | None] = mapped_column( Text, nullable=True, comment="个人简介", ) # 时间戳 created_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=utc_now, server_default=func.now(), nullable=False, comment="创建时间", ) updated_at: Mapped[datetime] = mapped_column( DateTime(timezone=True), default=utc_now, onupdate=utc_now, server_default=func.now(), nullable=False, comment="更新时间", ) last_login_at: Mapped[datetime | None] = mapped_column( DateTime(timezone=True), nullable=True, comment="最后登录时间", ) # 关系 balance_account: Mapped["UserBalance | None"] = relationship( "UserBalance", back_populates="user", uselist=False, lazy="selectin", ) def __repr__(self) -> str: return f""