import uuid as _uuid from sqlalchemy import Column, Integer, String, Text, Date, DateTime, Boolean, ForeignKey, Table, desc from sqlalchemy.orm import relationship from app.database import Base from app.utils.datetime import utcnow # 目标-任务关联表(多对多) goal_tasks = Table( "goal_tasks", Base.metadata, Column("goal_id", Integer, ForeignKey("goals.id"), primary_key=True), Column("task_id", Integer, ForeignKey("tasks.id"), primary_key=True), ) class Goal(Base): """长期目标模型""" __tablename__ = "goals" id = Column(Integer, primary_key=True, index=True) uuid = Column(String(36), default=lambda: str(_uuid.uuid4()), unique=True, index=True) title = Column(String(200), nullable=False) description = Column(Text, nullable=True) status = Column(String(20), default="active") # active/paused/completed/abandoned progress = Column(Integer, default=0) # 0-100,从里程碑自动计算 target_date = Column(Date, nullable=True) completed_at = Column(DateTime, nullable=True) category_id = Column(Integer, ForeignKey("categories.id"), nullable=True) color = Column(String(20), default="#FFB7C5") icon = Column(String(50), default="flag") sort_order = Column(Integer, default=0) is_deleted = Column(Boolean, default=False) sync_version = Column(Integer, default=1) created_at = Column(DateTime, default=utcnow) updated_at = Column(DateTime, default=utcnow, onupdate=utcnow) # 关联关系 category = relationship("Category") steps = relationship( "GoalStep", back_populates="goal", cascade="all, delete-orphan", order_by="GoalStep.sort_order", ) reviews = relationship( "GoalReview", back_populates="goal", cascade="all, delete-orphan", order_by=lambda: desc(GoalReview.created_at), ) tasks = relationship("Task", secondary=goal_tasks, back_populates="goals") class GoalStep(Base): """目标阶段/里程碑模型(step_type 区分类型)""" __tablename__ = "goal_steps" id = Column(Integer, primary_key=True, index=True) uuid = Column(String(36), default=lambda: str(_uuid.uuid4()), unique=True, index=True) goal_id = Column(Integer, ForeignKey("goals.id"), nullable=False) parent_id = Column(Integer, ForeignKey("goal_steps.id"), nullable=True) title = Column(String(200), nullable=False) step_type = Column(String(20), nullable=False) # "phase" | "milestone" status = Column(String(20), default="pending") # pending/in_progress/completed target_date = Column(Date, nullable=True) reached_at = Column(DateTime, nullable=True) sort_order = Column(Integer, default=0) is_deleted = Column(Boolean, default=False) sync_version = Column(Integer, default=1) created_at = Column(DateTime, default=utcnow) # 关联关系 goal = relationship("Goal", back_populates="steps") parent = relationship("GoalStep", remote_side=[id], backref="children") class GoalReview(Base): """目标复盘记录模型""" __tablename__ = "goal_reviews" id = Column(Integer, primary_key=True, index=True) uuid = Column(String(36), default=lambda: str(_uuid.uuid4()), unique=True, index=True) goal_id = Column(Integer, ForeignKey("goals.id"), nullable=False) content = Column(Text, nullable=False) rating = Column(Integer, nullable=True) # 1-5 自评 is_deleted = Column(Boolean, default=False) sync_version = Column(Integer, default=1) created_at = Column(DateTime, default=utcnow) # 关联关系 goal = relationship("Goal", back_populates="reviews")