""" 定义前后端之间传输的数据格式 """ from __future__ import annotations from datetime import datetime from typing import Optional from uuid import UUID from pydantic import BaseModel from app.models import UserRole #认证模块(auth) class TokenResponse(BaseModel): access_token: str token_type: str = "bearer" class RegisterRequest(BaseModel): username: str password: str role: UserRole #用户模块(users) class UserPublic(BaseModel): id: UUID username: str role: UserRole created_at: datetime #知识图谱模块(knowledge_graph) class KnowledgeQueryResponse(BaseModel): knowledge_code: str name: Optional[str] = None grade: Optional[str] = None category: Optional[str] = None definition: Optional[str] = None related: list[str] = [] # 递进:(前置)-[:PREREQUISITE]->(后置) prerequisites: list[str] = [] # 必须先掌握的前置(指向当前知识点) next_steps: list[str] = [] # 以当前知识点为前置的后续知识点 class PrerequisiteLinkRequest(BaseModel): # 创建/删除递进关系 prerequisite_code: str dependent_code: str class KnowledgePointInGraph(BaseModel): # 图中知识点列表项 code: str name: Optional[str] = None grade: Optional[str] = None class GraphBackfillResponse(BaseModel): total: int updated: int skipped: int class GraphSeedResponse(BaseModel): upserted: int #习题/测评模块(assessment) class ExerciseImportSummary(BaseModel): total: int created: int skipped: int errors: list[str] = [] class ExerciseImportPreviewItem(BaseModel): title: str body: str knowledge_code: Optional[str] = None difficulty: Optional[int] = None question_type: Optional[str] = None correct_answer: Optional[str] = None resolution: Optional[str] = None class ExerciseImportPreviewResponse(BaseModel): total: int valid: int invalid: int sample: list[ExerciseImportPreviewItem] errors: list[str] = [] class ExerciseCreateRequest(BaseModel): #创建/查询题目 title: str body: str knowledge_code: Optional[str] = None difficulty: Optional[int] = None question_type: Optional[str] = None correct_answer: Optional[str] = None resolution: Optional[str] = None weight: int = 0 class ExerciseBatchRequest(BaseModel): ids: list[UUID] class ExercisePublic(BaseModel): #前端创建题目时传的数据 id: UUID title: str body: str knowledge_code: Optional[str] = None difficulty: Optional[int] = None question_type: Optional[str] = None correct_answer: Optional[str] = None resolution: Optional[str] = None knowledge_grade: Optional[str] = None knowledge_category: Optional[str] = None knowledge_point_name: Optional[str] = None weight: Optional[int] = None class AttemptSubmitRequest(BaseModel): #返回给前端的完整题目信息 answer: str class AttemptPublic(BaseModel): id: UUID user_id: UUID exercise_id: UUID answer: str is_correct: Optional[bool] = None score: Optional[float] = None created_at: datetime #AI数字人模块(digital_human) class AskRequest(BaseModel): session_id: Optional[UUID] = None question: str knowledge_code: Optional[str] = None model_name: Optional[str] = None model_provider: Optional[str] = None model_id: Optional[str] = None class AskResponse(BaseModel): session_id: UUID answer: str sources: list[str] = [] tts_status: Optional[str] = None audio_base64: Optional[str] = None audio_mime: Optional[str] = None class VoiceAssetItem(BaseModel): name: str size: int url: str #推荐系统模块(recommendation) class RecommendRequest(BaseModel): knowledge_code: Optional[str] = None limit: int = 10 # topic_weight=开始组卷(按勾选知识点 + 权重);personalized=个性推荐(错题优先,忽略知识点) mode: Optional[str] = None # 组卷题量补足时限定范围,避免从全库随机混入其他类别(如代数组卷出现几何题) knowledge_grade: Optional[str] = None knowledge_category: Optional[str] = None class RecommendItem(BaseModel): item_type: str item_ref: str reason: Optional[str] = None class RecommendResponse(BaseModel): items: list[RecommendItem] #学习分析模块(learning_analytics) class LearningStatsResponse(BaseModel): user_id: UUID attempts_total: int correct_total: int accuracy: float class LearningBreakdownResponse(BaseModel): by_grade: list[GradeBreakdownItem] by_category: list[CategoryBreakdownItem] by_topic: list[TopicBreakdownItem] class GradeBreakdownItem(BaseModel): #按年级统计做题情况 grade: str attempts: int correct: int wrong: int accuracy: float class CategoryBreakdownItem(BaseModel): #按知识分类统计 grade: str category: str attempts: int correct: int wrong: int accuracy: float class TopicBreakdownItem(BaseModel): #按知识点统计 knowledge_code: str knowledge_point_name: Optional[str] = None knowledge_grade: Optional[str] = None knowledge_category: Optional[str] = None attempts: int correct: int wrong: int accuracy: float class StudentLearningStatsItem(BaseModel): user_id: UUID username: str attempts_total: int correct_total: int accuracy: float #错题本模块(assessment) class WrongBookItemPublic(BaseModel): id: UUID user_id: UUID exercise_id: UUID knowledge_code: str wrong_answer: str correct_answer: Optional[str] = None created_at: datetime # 关联习题展示(与习题测评一致) title: Optional[str] = None body: Optional[str] = None question_type: Optional[str] = None resolution: Optional[str] = None knowledge_grade: Optional[str] = None knowledge_category: Optional[str] = None knowledge_point_name: Optional[str] = None class WrongBookSummaryItem(BaseModel): knowledge_code: str wrong_count: int #模块管理模块(modules) class ModuleRegisterRequest(BaseModel): name: str base_url: str is_enabled: bool = True class ModulePublic(BaseModel): id: UUID name: str base_url: str is_enabled: bool updated_at: datetime