- 新增数据库表: growth_path_nodes, user_growth_path_progress, user_node_completions - 新增 Model: GrowthPathNode, UserGrowthPathProgress, UserNodeCompletion - 新增 Service: GrowthPathService(管理端CRUD、学员端进度追踪) - 新增 API: 学员端获取成长路径、管理端CRUD - 前端学员端从API动态加载成长路径数据 - 更新管理端API接口定义
This commit is contained in:
206
backend/app/models/growth_path.py
Normal file
206
backend/app/models/growth_path.py
Normal file
@@ -0,0 +1,206 @@
|
||||
"""
|
||||
成长路径相关数据库模型
|
||||
"""
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
from datetime import datetime
|
||||
from decimal import Decimal
|
||||
|
||||
from sqlalchemy import (
|
||||
String,
|
||||
Text,
|
||||
Integer,
|
||||
Boolean,
|
||||
ForeignKey,
|
||||
Enum as SQLEnum,
|
||||
JSON,
|
||||
DateTime,
|
||||
DECIMAL,
|
||||
)
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
||||
|
||||
from app.models.base import BaseModel, SoftDeleteMixin
|
||||
|
||||
|
||||
class GrowthPathStatus(str, Enum):
|
||||
"""成长路径学习状态"""
|
||||
NOT_STARTED = "not_started" # 未开始
|
||||
IN_PROGRESS = "in_progress" # 进行中
|
||||
COMPLETED = "completed" # 已完成
|
||||
|
||||
|
||||
class NodeStatus(str, Enum):
|
||||
"""节点状态"""
|
||||
LOCKED = "locked" # 锁定(前置未完成)
|
||||
UNLOCKED = "unlocked" # 已解锁(可以开始)
|
||||
IN_PROGRESS = "in_progress" # 学习中
|
||||
COMPLETED = "completed" # 已完成
|
||||
|
||||
|
||||
class GrowthPathNode(BaseModel, SoftDeleteMixin):
|
||||
"""
|
||||
成长路径节点表
|
||||
每个节点对应一门课程
|
||||
"""
|
||||
__tablename__ = "growth_path_nodes"
|
||||
|
||||
# 关联
|
||||
growth_path_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("growth_paths.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="成长路径ID"
|
||||
)
|
||||
course_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("courses.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="课程ID"
|
||||
)
|
||||
|
||||
# 节点信息
|
||||
stage_name: Mapped[Optional[str]] = mapped_column(
|
||||
String(100), nullable=True, comment="所属阶段名称"
|
||||
)
|
||||
title: Mapped[str] = mapped_column(
|
||||
String(200), nullable=False, comment="节点标题"
|
||||
)
|
||||
description: Mapped[Optional[str]] = mapped_column(
|
||||
Text, nullable=True, comment="节点描述"
|
||||
)
|
||||
|
||||
# 配置
|
||||
order_num: Mapped[int] = mapped_column(
|
||||
Integer, default=0, nullable=False, comment="排序顺序"
|
||||
)
|
||||
is_required: Mapped[bool] = mapped_column(
|
||||
Boolean, default=True, nullable=False, comment="是否必修"
|
||||
)
|
||||
prerequisites: Mapped[Optional[List[int]]] = mapped_column(
|
||||
JSON, nullable=True, comment="前置节点IDs"
|
||||
)
|
||||
estimated_days: Mapped[int] = mapped_column(
|
||||
Integer, default=7, nullable=False, comment="预计学习天数"
|
||||
)
|
||||
|
||||
# 关联关系
|
||||
growth_path: Mapped["GrowthPath"] = relationship(
|
||||
"GrowthPath", back_populates="nodes"
|
||||
)
|
||||
course: Mapped["Course"] = relationship("Course")
|
||||
user_completions: Mapped[List["UserNodeCompletion"]] = relationship(
|
||||
"UserNodeCompletion", back_populates="node"
|
||||
)
|
||||
|
||||
|
||||
class UserGrowthPathProgress(BaseModel):
|
||||
"""
|
||||
用户成长路径进度表
|
||||
记录用户在某条成长路径上的整体进度
|
||||
"""
|
||||
__tablename__ = "user_growth_path_progress"
|
||||
|
||||
# 关联
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("users.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="用户ID"
|
||||
)
|
||||
growth_path_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("growth_paths.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="成长路径ID"
|
||||
)
|
||||
|
||||
# 进度信息
|
||||
current_node_id: Mapped[Optional[int]] = mapped_column(
|
||||
Integer, nullable=True, comment="当前学习节点ID"
|
||||
)
|
||||
completed_node_ids: Mapped[Optional[List[int]]] = mapped_column(
|
||||
JSON, nullable=True, comment="已完成节点IDs"
|
||||
)
|
||||
total_progress: Mapped[Decimal] = mapped_column(
|
||||
DECIMAL(5, 2), default=0.00, nullable=False, comment="总进度百分比"
|
||||
)
|
||||
|
||||
# 状态
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(20),
|
||||
default=GrowthPathStatus.NOT_STARTED.value,
|
||||
nullable=False,
|
||||
comment="状态"
|
||||
)
|
||||
|
||||
# 时间记录
|
||||
started_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="开始时间"
|
||||
)
|
||||
completed_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="完成时间"
|
||||
)
|
||||
last_activity_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="最后活动时间"
|
||||
)
|
||||
|
||||
# 关联关系
|
||||
user: Mapped["User"] = relationship("User")
|
||||
growth_path: Mapped["GrowthPath"] = relationship("GrowthPath")
|
||||
|
||||
|
||||
class UserNodeCompletion(BaseModel):
|
||||
"""
|
||||
用户节点完成记录表
|
||||
详细记录用户在每个节点上的学习状态
|
||||
"""
|
||||
__tablename__ = "user_node_completions"
|
||||
|
||||
# 关联
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("users.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="用户ID"
|
||||
)
|
||||
growth_path_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("growth_paths.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="成长路径ID"
|
||||
)
|
||||
node_id: Mapped[int] = mapped_column(
|
||||
Integer,
|
||||
ForeignKey("growth_path_nodes.id", ondelete="CASCADE"),
|
||||
nullable=False,
|
||||
comment="节点ID"
|
||||
)
|
||||
|
||||
# 进度信息
|
||||
course_progress: Mapped[Decimal] = mapped_column(
|
||||
DECIMAL(5, 2), default=0.00, nullable=False, comment="课程学习进度"
|
||||
)
|
||||
status: Mapped[str] = mapped_column(
|
||||
String(20),
|
||||
default=NodeStatus.LOCKED.value,
|
||||
nullable=False,
|
||||
comment="状态"
|
||||
)
|
||||
|
||||
# 时间记录
|
||||
unlocked_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="解锁时间"
|
||||
)
|
||||
started_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="开始学习时间"
|
||||
)
|
||||
completed_at: Mapped[Optional[datetime]] = mapped_column(
|
||||
DateTime(timezone=True), nullable=True, comment="完成时间"
|
||||
)
|
||||
|
||||
# 关联关系
|
||||
user: Mapped["User"] = relationship("User")
|
||||
node: Mapped["GrowthPathNode"] = relationship(
|
||||
"GrowthPathNode", back_populates="user_completions"
|
||||
)
|
||||
growth_path: Mapped["GrowthPath"] = relationship("GrowthPath")
|
||||
Reference in New Issue
Block a user