Files
012-kaopeilian/backend/app/models/training.py
111 998211c483 feat: 初始化考培练系统项目
- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
2026-01-24 19:33:28 +08:00

264 lines
7.6 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
from enum import Enum
from sqlalchemy import (
Column,
String,
Integer,
ForeignKey,
Text,
JSON,
Enum as SQLEnum,
Float,
Boolean,
DateTime,
func,
)
from sqlalchemy.orm import relationship, Mapped, mapped_column
from app.models.base import BaseModel, SoftDeleteMixin, AuditMixin
class TrainingSceneStatus(str, Enum):
"""陪练场景状态枚举"""
DRAFT = "draft" # 草稿
ACTIVE = "active" # 已激活
INACTIVE = "inactive" # 已停用
class TrainingSessionStatus(str, Enum):
"""陪练会话状态枚举"""
CREATED = "created" # 已创建
IN_PROGRESS = "in_progress" # 进行中
COMPLETED = "completed" # 已完成
CANCELLED = "cancelled" # 已取消
ERROR = "error" # 异常结束
class MessageType(str, Enum):
"""消息类型枚举"""
TEXT = "text" # 文本消息
VOICE = "voice" # 语音消息
SYSTEM = "system" # 系统消息
class MessageRole(str, Enum):
"""消息角色枚举"""
USER = "user" # 用户
ASSISTANT = "assistant" # AI助手
SYSTEM = "system" # 系统
class TrainingScene(BaseModel, SoftDeleteMixin, AuditMixin):
"""
陪练场景模型
定义不同的陪练场景,如面试训练、演讲训练等
"""
__tablename__ = "training_scenes"
__allow_unmapped__ = True
# 基础信息
name: Mapped[str] = mapped_column(String(100), nullable=False, comment="场景名称")
description: Mapped[Optional[str]] = mapped_column(
Text, nullable=True, comment="场景描述"
)
category: Mapped[str] = mapped_column(String(50), nullable=False, comment="场景分类")
# 配置信息
ai_config: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="AI配置如Coze Bot ID等"
)
prompt_template: Mapped[Optional[str]] = mapped_column(
Text, nullable=True, comment="提示词模板"
)
evaluation_criteria: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="评估标准"
)
# 状态和权限
status: Mapped[TrainingSceneStatus] = mapped_column(
SQLEnum(TrainingSceneStatus),
default=TrainingSceneStatus.DRAFT,
nullable=False,
comment="场景状态",
)
is_public: Mapped[bool] = mapped_column(
Boolean, default=True, nullable=False, comment="是否公开"
)
required_level: Mapped[Optional[int]] = mapped_column(
Integer, nullable=True, comment="所需用户等级"
)
# 关联
sessions: Mapped[list["TrainingSession"]] = relationship(
"TrainingSession", back_populates="scene", cascade="all, delete-orphan"
)
class TrainingSession(BaseModel, AuditMixin):
"""
陪练会话模型
记录每次陪练会话的信息
"""
__tablename__ = "training_sessions"
__allow_unmapped__ = True
# 基础信息
user_id: Mapped[int] = mapped_column(
Integer, nullable=False, index=True, comment="用户ID"
)
scene_id: Mapped[int] = mapped_column(
Integer, ForeignKey("training_scenes.id"), nullable=False, comment="场景ID"
)
# 会话信息
coze_conversation_id: Mapped[Optional[str]] = mapped_column(
String(100), nullable=True, comment="Coze会话ID"
)
start_time: Mapped[datetime] = mapped_column(
DateTime, server_default=func.now(), nullable=False, comment="开始时间(北京时间)"
)
end_time: Mapped[Optional[datetime]] = mapped_column(
DateTime, nullable=True, comment="结束时间(北京时间)"
)
duration_seconds: Mapped[Optional[int]] = mapped_column(
Integer, nullable=True, comment="持续时长(秒)"
)
# 状态和配置
status: Mapped[TrainingSessionStatus] = mapped_column(
SQLEnum(TrainingSessionStatus),
default=TrainingSessionStatus.CREATED,
nullable=False,
comment="会话状态",
)
session_config: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="会话配置"
)
# 评估信息
total_score: Mapped[Optional[float]] = mapped_column(
Float, nullable=True, comment="总分"
)
evaluation_result: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="评估结果详情"
)
# 关联
scene: Mapped["TrainingScene"] = relationship(
"TrainingScene", back_populates="sessions"
)
messages: Mapped[list["TrainingMessage"]] = relationship(
"TrainingMessage",
back_populates="session",
cascade="all, delete-orphan",
order_by="TrainingMessage.created_at",
)
report: Mapped[Optional["TrainingReport"]] = relationship(
"TrainingReport", back_populates="session", uselist=False
)
class TrainingMessage(BaseModel):
"""
陪练消息模型
记录会话中的每条消息
"""
__tablename__ = "training_messages"
__allow_unmapped__ = True
# 基础信息
session_id: Mapped[int] = mapped_column(
Integer, ForeignKey("training_sessions.id"), nullable=False, comment="会话ID"
)
# 消息内容
role: Mapped[MessageRole] = mapped_column(
SQLEnum(MessageRole), nullable=False, comment="消息角色"
)
type: Mapped[MessageType] = mapped_column(
SQLEnum(MessageType), nullable=False, comment="消息类型"
)
content: Mapped[str] = mapped_column(Text, nullable=False, comment="消息内容")
# 语音消息相关
voice_url: Mapped[Optional[str]] = mapped_column(
String(500), nullable=True, comment="语音文件URL"
)
voice_duration: Mapped[Optional[float]] = mapped_column(
Float, nullable=True, comment="语音时长(秒)"
)
# 元数据
message_metadata: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="消息元数据"
)
coze_message_id: Mapped[Optional[str]] = mapped_column(
String(100), nullable=True, comment="Coze消息ID"
)
# 关联
session: Mapped["TrainingSession"] = relationship(
"TrainingSession", back_populates="messages"
)
class TrainingReport(BaseModel, AuditMixin):
"""
陪练报告模型
存储陪练会话的分析报告
"""
__tablename__ = "training_reports"
__allow_unmapped__ = True
# 基础信息
session_id: Mapped[int] = mapped_column(
Integer,
ForeignKey("training_sessions.id"),
unique=True,
nullable=False,
comment="会话ID",
)
user_id: Mapped[int] = mapped_column(
Integer, nullable=False, index=True, comment="用户ID"
)
# 评分信息
overall_score: Mapped[float] = mapped_column(Float, nullable=False, comment="总体得分")
dimension_scores: Mapped[dict] = mapped_column(
JSON, nullable=False, comment="各维度得分"
)
# 分析内容
strengths: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="优势点")
weaknesses: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="待改进点")
suggestions: Mapped[list[str]] = mapped_column(JSON, nullable=False, comment="改进建议")
# 详细内容
detailed_analysis: Mapped[Optional[str]] = mapped_column(
Text, nullable=True, comment="详细分析"
)
transcript: Mapped[Optional[str]] = mapped_column(
Text, nullable=True, comment="对话文本记录"
)
# 统计信息
statistics: Mapped[Optional[dict]] = mapped_column(
JSON, nullable=True, comment="统计数据"
)
# 关联
session: Mapped["TrainingSession"] = relationship(
"TrainingSession", back_populates="report"
)