Files
life-echo/api/database/models.py
penghanyuan 44bd478c1e agent init
2026-01-21 22:31:09 +01:00

139 lines
5.5 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.
"""
数据库模型定义
"""
from datetime import datetime
from typing import Optional, List
from sqlalchemy import Column, String, Integer, DateTime, Boolean, Text, ForeignKey, JSON
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
Base = declarative_base()
class User(Base):
"""用户表"""
__tablename__ = "users"
id = Column(String, primary_key=True)
phone = Column(String, unique=True, nullable=False, index=True) # 手机号(唯一,必填)
password_hash = Column(String, nullable=False) # 密码哈希
email = Column(String, unique=True, nullable=True) # 邮箱(可选)
openid = Column(String, unique=True, nullable=True) # 微信 OpenID可选
nickname = Column(String, nullable=False)
avatar_url = Column(String, nullable=True)
subscription_type = Column(String, default="free") # free, premium
created_at = Column(DateTime, default=datetime.utcnow)
# Relationships
conversations = relationship("Conversation", back_populates="user")
chapters = relationship("Chapter", back_populates="user")
books = relationship("Book", back_populates="user")
memoir_state = relationship("MemoirState", back_populates="user", uselist=False, cascade="all, delete-orphan")
refresh_tokens = relationship("RefreshToken", back_populates="user", cascade="all, delete-orphan")
class Conversation(Base):
"""对话会话表"""
__tablename__ = "conversations"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False)
started_at = Column(DateTime, default=datetime.utcnow)
ended_at = Column(DateTime, nullable=True)
duration_seconds = Column(Integer, default=0)
summary = Column(Text, nullable=True)
status = Column(String, default="active") # active, ended, processing
current_topic = Column(String, nullable=True)
conversation_stage = Column(String, nullable=True) # childhood, education, career, family, beliefs, summary
# Relationships
user = relationship("User", back_populates="conversations")
segments = relationship("Segment", back_populates="conversation", cascade="all, delete-orphan")
class Segment(Base):
"""对话段落表"""
__tablename__ = "segments"
id = Column(String, primary_key=True)
conversation_id = Column(String, ForeignKey("conversations.id"), nullable=False)
audio_url = Column(String, nullable=True)
transcript_text = Column(Text, nullable=False)
created_at = Column(DateTime, default=datetime.utcnow)
processed = Column(Boolean, default=False)
topic_category = Column(String, nullable=True)
agent_response = Column(Text, nullable=True)
# Relationships
conversation = relationship("Conversation", back_populates="segments")
class Chapter(Base):
"""章节表"""
__tablename__ = "chapters"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False)
title = Column(String, nullable=False)
content = Column(Text, nullable=False)
order_index = Column(Integer, nullable=False)
status = Column(String, default="draft") # draft, completed
images = Column(JSON, nullable=True) # 图片 URL 列表
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
category = Column(String, nullable=True) # 章节分类
is_new = Column(Boolean, default=True) # 是否为新内容(未读)
source_segments = Column(JSON, nullable=True) # 来源 segment IDs 列表
# Relationships
user = relationship("User", back_populates="chapters")
class Book(Base):
"""回忆录表"""
__tablename__ = "books"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False)
title = Column(String, nullable=False)
total_pages = Column(Integer, default=0)
total_words = Column(Integer, default=0)
cover_image_url = Column(String, nullable=True)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
has_update = Column(Boolean, default=False) # 是否有新内容
last_update_chapter_id = Column(String, nullable=True) # 最近更新的章节 ID
# Relationships
user = relationship("User", back_populates="books")
class MemoirState(Base):
"""回忆录状态表 - 对话 Agent 与后台 Agent 共享"""
__tablename__ = "memoir_states"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), unique=True, nullable=False)
stage_order = Column(JSON, default=list) # 阶段顺序
current_stage = Column(String, default="childhood") # 当前阶段
covered_stages = Column(JSON, default=list) # 已完成阶段列表
slots = Column(JSON, nullable=False) # 各阶段 slot 信息
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# Relationships
user = relationship("User", back_populates="memoir_state")
class RefreshToken(Base):
"""刷新令牌表"""
__tablename__ = "refresh_tokens"
id = Column(String, primary_key=True)
user_id = Column(String, ForeignKey("users.id"), nullable=False, index=True)
token = Column(String, unique=True, nullable=False, index=True) # 刷新令牌(唯一)
expires_at = Column(DateTime, nullable=False) # 过期时间30天后
created_at = Column(DateTime, default=datetime.utcnow)
is_revoked = Column(Boolean, default=False) # 是否已撤销
# Relationships
user = relationship("User", back_populates="refresh_tokens")