|
@@ -55,6 +55,9 @@ class User(Base):
|
|
|
user_level = Column(Integer, default=0, nullable=False, comment="用户等级(0-5)")
|
|
user_level = Column(Integer, default=0, nullable=False, comment="用户等级(0-5)")
|
|
|
last_active_at = Column(TIMESTAMP, nullable=True, comment="最后活跃时间")
|
|
last_active_at = Column(TIMESTAMP, nullable=True, comment="最后活跃时间")
|
|
|
|
|
|
|
|
|
|
+ # 背景图片
|
|
|
|
|
+ current_background_image_id = Column(String(64), nullable=True, comment="当前使用的背景图片ID")
|
|
|
|
|
+
|
|
|
created_at = Column(TIMESTAMP, server_default=func.current_timestamp(), comment="创建时间")
|
|
created_at = Column(TIMESTAMP, server_default=func.current_timestamp(), comment="创建时间")
|
|
|
updated_at = Column(TIMESTAMP, server_default=func.current_timestamp(), onupdate=func.current_timestamp(), comment="更新时间")
|
|
updated_at = Column(TIMESTAMP, server_default=func.current_timestamp(), onupdate=func.current_timestamp(), comment="更新时间")
|
|
|
|
|
|
|
@@ -78,6 +81,7 @@ class User(Base):
|
|
|
"total_speech_duration_ms": self.total_speech_duration_ms,
|
|
"total_speech_duration_ms": self.total_speech_duration_ms,
|
|
|
"user_level": self.user_level,
|
|
"user_level": self.user_level,
|
|
|
"last_active_at": self.last_active_at.isoformat() if self.last_active_at else None,
|
|
"last_active_at": self.last_active_at.isoformat() if self.last_active_at else None,
|
|
|
|
|
+ "current_background_image_id": self.current_background_image_id,
|
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
"created_at": self.created_at.isoformat() if self.created_at else None,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -319,6 +323,98 @@ def _attach_metadata_alias(model_cls):
|
|
|
model_cls.metadata = property(getter, setter)
|
|
model_cls.metadata = property(getter, setter)
|
|
|
|
|
|
|
|
|
|
|
|
|
-for _model in (MissionType, MissionEnergyStone, ConversationEnergyStone):
|
|
|
|
|
|
|
+class BackgroundImage(Base):
|
|
|
|
|
+ """背景图片配置表"""
|
|
|
|
|
+ __tablename__ = "background_images"
|
|
|
|
|
+
|
|
|
|
|
+ id = Column(PKBigInt, primary_key=True, autoincrement=True)
|
|
|
|
|
+ image_id = Column(String(64), unique=True, nullable=False, index=True, comment="背景图片唯一标识")
|
|
|
|
|
+
|
|
|
|
|
+ # 基本信息
|
|
|
|
|
+ image_name = Column(String(100), nullable=False, comment="背景图片名称")
|
|
|
|
|
+ image_url = Column(String(500), nullable=False, comment="背景图片URL")
|
|
|
|
|
+ thumbnail_url = Column(String(500), nullable=True, comment="缩略图URL")
|
|
|
|
|
+
|
|
|
|
|
+ # 解锁条件
|
|
|
|
|
+ unlock_type = Column(Enum("default", "level", "purchase", "mission", name="unlock_type"),
|
|
|
|
|
+ default="default", comment="解锁类型")
|
|
|
|
|
+ unlock_level = Column(Integer, nullable=True, comment="解锁所需等级(unlock_type=level时)")
|
|
|
|
|
+ unlock_mission_type = Column(String(64), nullable=True, comment="解锁所需任务类型(unlock_type=mission时)")
|
|
|
|
|
+
|
|
|
|
|
+ # 显示信息
|
|
|
|
|
+ display_order = Column(Integer, default=0, comment="显示顺序")
|
|
|
|
|
+ is_active = Column(Boolean, default=True, comment="是否启用")
|
|
|
|
|
+ description = Column(String(255), nullable=True, comment="背景图片描述")
|
|
|
|
|
+
|
|
|
|
|
+ # 扩展信息
|
|
|
|
|
+ metadata_json = Column("metadata", JSON, nullable=True, comment="扩展配置")
|
|
|
|
|
+
|
|
|
|
|
+ created_at = Column(TIMESTAMP, server_default=func.current_timestamp(), comment="创建时间")
|
|
|
|
|
+ updated_at = Column(TIMESTAMP, server_default=func.current_timestamp(),
|
|
|
|
|
+ onupdate=func.current_timestamp(), comment="更新时间")
|
|
|
|
|
+
|
|
|
|
|
+ __table_args__ = (
|
|
|
|
|
+ Index("idx_unlock_type", "unlock_type"),
|
|
|
|
|
+ Index("idx_display_order", "display_order"),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def to_dict(self) -> dict:
|
|
|
|
|
+ """转换为字典"""
|
|
|
|
|
+ return {
|
|
|
|
|
+ "image_id": self.image_id,
|
|
|
|
|
+ "image_name": self.image_name,
|
|
|
|
|
+ "image_url": self.image_url,
|
|
|
|
|
+ "thumbnail_url": self.thumbnail_url,
|
|
|
|
|
+ "unlock_type": self.unlock_type,
|
|
|
|
|
+ "unlock_level": self.unlock_level,
|
|
|
|
|
+ "unlock_mission_type": self.unlock_mission_type,
|
|
|
|
|
+ "display_order": self.display_order,
|
|
|
|
|
+ "is_active": self.is_active,
|
|
|
|
|
+ "description": self.description,
|
|
|
|
|
+ "metadata": self.metadata_json,
|
|
|
|
|
+ "created_at": self.created_at.isoformat() if self.created_at else None,
|
|
|
|
|
+ "updated_at": self.updated_at.isoformat() if self.updated_at else None,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+class UserBackgroundImage(Base):
|
|
|
|
|
+ """用户背景图片关联表(记录用户已获得的背景图片)"""
|
|
|
|
|
+ __tablename__ = "user_background_images"
|
|
|
|
|
+
|
|
|
|
|
+ id = Column(PKBigInt, primary_key=True, autoincrement=True)
|
|
|
|
|
+ user_id = Column(String(64), nullable=False, index=True, comment="用户ID")
|
|
|
|
|
+ image_id = Column(String(64), nullable=False, index=True, comment="背景图片ID")
|
|
|
|
|
+
|
|
|
|
|
+ # 获得信息
|
|
|
|
|
+ obtained_at = Column(TIMESTAMP, server_default=func.current_timestamp(), comment="获得时间")
|
|
|
|
|
+ obtained_type = Column(Enum("default", "level_up", "purchase", "mission", "gift", name="obtained_type"),
|
|
|
|
|
+ default="default", comment="获得方式")
|
|
|
|
|
+ obtained_source = Column(String(64), nullable=True, comment="获得来源(任务类型、等级等)")
|
|
|
|
|
+
|
|
|
|
|
+ # 扩展信息
|
|
|
|
|
+ metadata_json = Column("metadata", JSON, nullable=True, comment="扩展信息")
|
|
|
|
|
+
|
|
|
|
|
+ created_at = Column(TIMESTAMP, server_default=func.current_timestamp(), comment="创建时间")
|
|
|
|
|
+
|
|
|
|
|
+ __table_args__ = (
|
|
|
|
|
+ UniqueConstraint("user_id", "image_id", name="uk_user_background_image"),
|
|
|
|
|
+ Index("idx_user_obtained", "user_id", "obtained_at"),
|
|
|
|
|
+ )
|
|
|
|
|
+
|
|
|
|
|
+ def to_dict(self) -> dict:
|
|
|
|
|
+ """转换为字典"""
|
|
|
|
|
+ return {
|
|
|
|
|
+ "id": self.id,
|
|
|
|
|
+ "user_id": self.user_id,
|
|
|
|
|
+ "image_id": self.image_id,
|
|
|
|
|
+ "obtained_at": self.obtained_at.isoformat() if self.obtained_at else None,
|
|
|
|
|
+ "obtained_type": self.obtained_type,
|
|
|
|
|
+ "obtained_source": self.obtained_source,
|
|
|
|
|
+ "metadata": self.metadata_json,
|
|
|
|
|
+ "created_at": self.created_at.isoformat() if self.created_at else None,
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+for _model in (MissionType, MissionEnergyStone, ConversationEnergyStone, BackgroundImage, UserBackgroundImage):
|
|
|
_attach_metadata_alias(_model)
|
|
_attach_metadata_alias(_model)
|
|
|
|
|
|