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

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

261 lines
8.3 KiB
Python

"""陪练模块Pydantic模式"""
from typing import Optional, List, Dict, Any, Generic, TypeVar
from datetime import datetime
from pydantic import BaseModel, Field, ConfigDict
# 定义泛型类型变量
DataT = TypeVar("DataT")
from app.models.training import (
TrainingSceneStatus,
TrainingSessionStatus,
MessageType,
MessageRole,
)
from app.schemas.base import BaseSchema, TimestampMixin, IDMixin
# ========== 陪练场景相关 ==========
class TrainingSceneBase(BaseSchema):
"""陪练场景基础模式"""
name: str = Field(..., max_length=100, description="场景名称")
description: Optional[str] = Field(None, description="场景描述")
category: str = Field(..., max_length=50, description="场景分类")
ai_config: Optional[Dict[str, Any]] = Field(None, description="AI配置")
prompt_template: Optional[str] = Field(None, description="提示词模板")
evaluation_criteria: Optional[Dict[str, Any]] = Field(None, description="评估标准")
is_public: bool = Field(True, description="是否公开")
required_level: Optional[int] = Field(None, description="所需用户等级")
class TrainingSceneCreate(TrainingSceneBase):
"""创建陪练场景模式"""
status: TrainingSceneStatus = Field(
default=TrainingSceneStatus.DRAFT, description="场景状态"
)
class TrainingSceneUpdate(BaseSchema):
"""更新陪练场景模式"""
name: Optional[str] = Field(None, max_length=100)
description: Optional[str] = None
category: Optional[str] = Field(None, max_length=50)
ai_config: Optional[Dict[str, Any]] = None
prompt_template: Optional[str] = None
evaluation_criteria: Optional[Dict[str, Any]] = None
status: Optional[TrainingSceneStatus] = None
is_public: Optional[bool] = None
required_level: Optional[int] = None
class TrainingSceneInDB(TrainingSceneBase, IDMixin, TimestampMixin):
"""数据库中的陪练场景模式"""
status: TrainingSceneStatus
is_deleted: bool = False
created_by: Optional[int] = None
updated_by: Optional[int] = None
class TrainingSceneResponse(TrainingSceneInDB):
"""陪练场景响应模式"""
pass
# ========== 陪练会话相关 ==========
class TrainingSessionBase(BaseSchema):
"""陪练会话基础模式"""
scene_id: int = Field(..., description="场景ID")
session_config: Optional[Dict[str, Any]] = Field(None, description="会话配置")
class TrainingSessionCreate(TrainingSessionBase):
"""创建陪练会话模式"""
pass
class TrainingSessionUpdate(BaseSchema):
"""更新陪练会话模式"""
status: Optional[TrainingSessionStatus] = None
end_time: Optional[datetime] = None
duration_seconds: Optional[int] = None
total_score: Optional[float] = None
evaluation_result: Optional[Dict[str, Any]] = None
class TrainingSessionInDB(TrainingSessionBase, IDMixin, TimestampMixin):
"""数据库中的陪练会话模式"""
user_id: int
coze_conversation_id: Optional[str] = None
start_time: datetime
end_time: Optional[datetime] = None
duration_seconds: Optional[int] = None
status: TrainingSessionStatus
total_score: Optional[float] = None
evaluation_result: Optional[Dict[str, Any]] = None
created_by: Optional[int] = None
updated_by: Optional[int] = None
class TrainingSessionResponse(TrainingSessionInDB):
"""陪练会话响应模式"""
scene: Optional["TrainingSceneResponse"] = None
message_count: Optional[int] = Field(None, description="消息数量")
# ========== 消息相关 ==========
class TrainingMessageBase(BaseSchema):
"""陪练消息基础模式"""
role: MessageRole = Field(..., description="消息角色")
type: MessageType = Field(..., description="消息类型")
content: str = Field(..., description="消息内容")
voice_url: Optional[str] = Field(None, max_length=500, description="语音文件URL")
voice_duration: Optional[float] = Field(None, description="语音时长(秒)")
metadata: Optional[Dict[str, Any]] = Field(None, description="消息元数据")
class TrainingMessageCreate(TrainingMessageBase):
"""创建陪练消息模式"""
session_id: int = Field(..., description="会话ID")
coze_message_id: Optional[str] = Field(None, max_length=100, description="Coze消息ID")
class TrainingMessageInDB(TrainingMessageBase, IDMixin, TimestampMixin):
"""数据库中的陪练消息模式"""
session_id: int
coze_message_id: Optional[str] = None
class TrainingMessageResponse(TrainingMessageInDB):
"""陪练消息响应模式"""
pass
# ========== 报告相关 ==========
class TrainingReportBase(BaseSchema):
"""陪练报告基础模式"""
overall_score: float = Field(..., ge=0, le=100, description="总体得分")
dimension_scores: Dict[str, float] = Field(..., description="各维度得分")
strengths: List[str] = Field(..., description="优势点")
weaknesses: List[str] = Field(..., description="待改进点")
suggestions: List[str] = Field(..., description="改进建议")
detailed_analysis: Optional[str] = Field(None, description="详细分析")
transcript: Optional[str] = Field(None, description="对话文本记录")
statistics: Optional[Dict[str, Any]] = Field(None, description="统计数据")
class TrainingReportCreate(TrainingReportBase):
"""创建陪练报告模式"""
session_id: int = Field(..., description="会话ID")
user_id: int = Field(..., description="用户ID")
class TrainingReportInDB(TrainingReportBase, IDMixin, TimestampMixin):
"""数据库中的陪练报告模式"""
session_id: int
user_id: int
created_by: Optional[int] = None
updated_by: Optional[int] = None
class TrainingReportResponse(TrainingReportInDB):
"""陪练报告响应模式"""
session: Optional[TrainingSessionResponse] = None
# ========== 会话操作相关 ==========
class StartTrainingRequest(BaseSchema):
"""开始陪练请求"""
scene_id: int = Field(..., description="场景ID")
config: Optional[Dict[str, Any]] = Field(None, description="会话配置")
class StartTrainingResponse(BaseSchema):
"""开始陪练响应"""
session_id: int = Field(..., description="会话ID")
coze_conversation_id: Optional[str] = Field(None, description="Coze会话ID")
scene: TrainingSceneResponse = Field(..., description="场景信息")
websocket_url: Optional[str] = Field(None, description="WebSocket连接URL")
class EndTrainingRequest(BaseSchema):
"""结束陪练请求"""
generate_report: bool = Field(True, description="是否生成报告")
class EndTrainingResponse(BaseSchema):
"""结束陪练响应"""
session: TrainingSessionResponse = Field(..., description="会话信息")
report: Optional[TrainingReportResponse] = Field(None, description="陪练报告")
# ========== 列表查询相关 ==========
class TrainingSceneListQuery(BaseSchema):
"""陪练场景列表查询参数"""
category: Optional[str] = Field(None, description="场景分类")
status: Optional[TrainingSceneStatus] = Field(None, description="场景状态")
is_public: Optional[bool] = Field(None, description="是否公开")
search: Optional[str] = Field(None, description="搜索关键词")
page: int = Field(1, ge=1, description="页码")
page_size: int = Field(20, ge=1, le=100, description="每页数量")
class TrainingSessionListQuery(BaseSchema):
"""陪练会话列表查询参数"""
scene_id: Optional[int] = Field(None, description="场景ID")
status: Optional[TrainingSessionStatus] = Field(None, description="会话状态")
start_date: Optional[datetime] = Field(None, description="开始日期")
end_date: Optional[datetime] = Field(None, description="结束日期")
page: int = Field(1, ge=1, description="页码")
page_size: int = Field(20, ge=1, le=100, description="每页数量")
class PaginatedResponse(BaseModel, Generic[DataT]):
"""分页响应模式"""
items: List[DataT] = Field(..., description="数据列表")
total: int = Field(..., description="总数量")
page: int = Field(..., description="当前页码")
page_size: int = Field(..., description="每页数量")
pages: int = Field(..., description="总页数")
# 更新前向引用
TrainingSessionResponse.model_rebuild()
TrainingReportResponse.model_rebuild()