Files
012-kaopeilian/backend/app/models/level.py
yuliang_guo 813ba2c295
Some checks failed
continuous-integration/drone/push Build is failing
fix: 所有等级奖章模型使用 Base 而非 BaseModel
2026-01-29 16:29:45 +08:00

141 lines
6.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
等级与奖章系统模型
包含:
- UserLevel: 用户等级信息
- ExpHistory: 经验值变化历史
- BadgeDefinition: 奖章定义
- UserBadge: 用户已获得的奖章
- LevelConfig: 等级配置
"""
from datetime import datetime, date
from typing import Optional, List
from sqlalchemy import Column, Integer, String, DateTime, Date, Boolean, ForeignKey, Text
from sqlalchemy.orm import relationship
from app.models.base import Base, BaseModel
class UserLevel(Base):
"""用户等级表"""
__tablename__ = "user_levels"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, unique=True, index=True)
level = Column(Integer, nullable=False, default=1, comment="当前等级")
exp = Column(Integer, nullable=False, default=0, comment="当前经验值")
total_exp = Column(Integer, nullable=False, default=0, comment="累计获得经验值")
login_streak = Column(Integer, nullable=False, default=0, comment="连续登录天数")
max_login_streak = Column(Integer, nullable=False, default=0, comment="历史最长连续登录天数")
last_login_date = Column(Date, nullable=True, comment="最后登录日期")
last_checkin_at = Column(DateTime, nullable=True, comment="最后签到时间")
created_at = Column(DateTime, nullable=False, default=datetime.now)
updated_at = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
# 关联
user = relationship("User", backref="user_level", uselist=False)
class ExpHistory(Base):
"""经验值历史表"""
__tablename__ = "exp_history"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
exp_change = Column(Integer, nullable=False, comment="经验值变化")
exp_type = Column(String(50), nullable=False, index=True, comment="类型exam/practice/training/task/login/badge/other")
source_id = Column(Integer, nullable=True, comment="来源记录ID")
description = Column(String(255), nullable=False, comment="描述")
level_before = Column(Integer, nullable=True, comment="变化前等级")
level_after = Column(Integer, nullable=True, comment="变化后等级")
created_at = Column(DateTime, nullable=False, default=datetime.now)
# 关联
user = relationship("User", backref="exp_histories")
class BadgeDefinition(Base):
"""奖章定义表"""
__tablename__ = "badge_definitions"
id = Column(Integer, primary_key=True, autoincrement=True)
code = Column(String(50), nullable=False, unique=True, comment="奖章编码")
name = Column(String(100), nullable=False, comment="奖章名称")
description = Column(String(255), nullable=False, comment="奖章描述")
icon = Column(String(100), nullable=False, default="Medal", comment="图标名称")
category = Column(String(50), nullable=False, index=True, comment="分类")
condition_type = Column(String(50), nullable=False, comment="条件类型")
condition_field = Column(String(100), nullable=True, comment="条件字段")
condition_value = Column(Integer, nullable=False, default=1, comment="条件数值")
exp_reward = Column(Integer, nullable=False, default=0, comment="奖励经验值")
sort_order = Column(Integer, nullable=False, default=0, comment="排序")
is_active = Column(Boolean, nullable=False, default=True, comment="是否启用")
created_at = Column(DateTime, nullable=False, default=datetime.now)
updated_at = Column(DateTime, nullable=False, default=datetime.now, onupdate=datetime.now)
# 关联
user_badges = relationship("UserBadge", back_populates="badge")
class UserBadge(Base):
"""用户奖章表"""
__tablename__ = "user_badges"
id = Column(Integer, primary_key=True, autoincrement=True)
user_id = Column(Integer, ForeignKey("users.id", ondelete="CASCADE"), nullable=False, index=True)
badge_id = Column(Integer, ForeignKey("badge_definitions.id", ondelete="CASCADE"), nullable=False, index=True)
unlocked_at = Column(DateTime, nullable=False, default=datetime.now, comment="解锁时间")
is_notified = Column(Boolean, nullable=False, default=False, comment="是否已通知")
notified_at = Column(DateTime, nullable=True, comment="通知时间")
created_at = Column(DateTime, nullable=False, default=datetime.now)
# 关联
user = relationship("User", backref="badges")
badge = relationship("BadgeDefinition", back_populates="user_badges")
class LevelConfig(Base):
"""等级配置表"""
__tablename__ = "level_configs"
id = Column(Integer, primary_key=True, autoincrement=True)
level = Column(Integer, nullable=False, unique=True, comment="等级")
exp_required = Column(Integer, nullable=False, comment="升到此级所需经验值")
total_exp_required = Column(Integer, nullable=False, comment="累计所需经验值")
title = Column(String(50), nullable=False, comment="等级称号")
color = Column(String(20), nullable=True, comment="等级颜色")
created_at = Column(DateTime, nullable=False, default=datetime.now)
# 经验值类型枚举
class ExpType:
"""经验值类型"""
EXAM = "exam" # 考试
PRACTICE = "practice" # 练习
TRAINING = "training" # 陪练
TASK = "task" # 任务
LOGIN = "login" # 登录/签到
BADGE = "badge" # 奖章奖励
OTHER = "other" # 其他
# 奖章分类枚举
class BadgeCategory:
"""奖章分类"""
LEARNING = "learning" # 学习进度
EXAM = "exam" # 考试成绩
PRACTICE = "practice" # 练习时长
STREAK = "streak" # 连续打卡
SPECIAL = "special" # 特殊成就
# 条件类型枚举
class ConditionType:
"""解锁条件类型"""
COUNT = "count" # 次数
SCORE = "score" # 分数
STREAK = "streak" # 连续天数
LEVEL = "level" # 等级
DURATION = "duration" # 时长