feat: 初始化考培练系统项目

- 从服务器拉取完整代码
- 按框架规范整理项目结构
- 配置 Drone CI 测试环境部署
- 包含后端(FastAPI)、前端(Vue3)、管理端

技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
111
2026-01-24 19:33:28 +08:00
commit 998211c483
1197 changed files with 228429 additions and 0 deletions

View File

@@ -0,0 +1,263 @@
"""陪练模块数据模型"""
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"
)