feat: 初始化考培练系统项目
- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
This commit is contained in:
153
backend/app/models/exam.py
Normal file
153
backend/app/models/exam.py
Normal file
@@ -0,0 +1,153 @@
|
||||
"""
|
||||
考试相关模型定义
|
||||
"""
|
||||
from datetime import datetime
|
||||
from typing import List, Optional
|
||||
from sqlalchemy import Column, Integer, String, Text, DateTime, ForeignKey, JSON, Float, func
|
||||
from sqlalchemy.orm import relationship, Mapped, mapped_column
|
||||
from app.models.base import BaseModel
|
||||
|
||||
|
||||
class Exam(BaseModel):
|
||||
"""考试记录模型"""
|
||||
|
||||
__tablename__ = "exams"
|
||||
__allow_unmapped__ = True
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
user_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("users.id"), nullable=False, index=True
|
||||
)
|
||||
course_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("courses.id"), nullable=False, index=True
|
||||
)
|
||||
|
||||
# 考试信息
|
||||
exam_name: Mapped[str] = mapped_column(String(255), nullable=False)
|
||||
question_count: Mapped[int] = mapped_column(Integer, default=10)
|
||||
total_score: Mapped[float] = mapped_column(Float, default=100.0)
|
||||
pass_score: Mapped[float] = mapped_column(Float, default=60.0)
|
||||
|
||||
# 考试时间
|
||||
start_time: Mapped[datetime] = mapped_column(DateTime, server_default=func.now(), comment="开始时间(北京时间)")
|
||||
end_time: Mapped[Optional[datetime]] = mapped_column(DateTime, nullable=True, comment="结束时间(北京时间)")
|
||||
duration_minutes: Mapped[int] = mapped_column(Integer, default=60) # 考试时长(分钟)
|
||||
|
||||
# 考试结果
|
||||
score: Mapped[Optional[float]] = mapped_column(Float, nullable=True)
|
||||
|
||||
# 三轮考试得分
|
||||
round1_score: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="第一轮得分")
|
||||
round2_score: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="第二轮得分")
|
||||
round3_score: Mapped[Optional[float]] = mapped_column(Float, nullable=True, comment="第三轮得分")
|
||||
|
||||
is_passed: Mapped[Optional[bool]] = mapped_column(nullable=True)
|
||||
|
||||
# 考试状态: started, submitted, timeout
|
||||
status: Mapped[str] = mapped_column(String(20), default="started", index=True)
|
||||
|
||||
# 考试数据(JSON格式存储题目和答案)
|
||||
questions: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
||||
answers: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
||||
|
||||
# 关系
|
||||
user = relationship("User", back_populates="exams")
|
||||
course = relationship("Course", back_populates="exams")
|
||||
results = relationship("ExamResult", back_populates="exam")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Exam(id={self.id}, user_id={self.user_id}, course_id={self.course_id}, status={self.status})>"
|
||||
|
||||
|
||||
class Question(BaseModel):
|
||||
"""题目模型"""
|
||||
|
||||
__tablename__ = "questions"
|
||||
__allow_unmapped__ = True
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
course_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("courses.id"), nullable=False, index=True
|
||||
)
|
||||
|
||||
# 题目类型: single_choice, multiple_choice, true_false, fill_blank, essay
|
||||
question_type: Mapped[str] = mapped_column(String(20), nullable=False, index=True)
|
||||
|
||||
# 题目内容
|
||||
title: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
content: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
||||
|
||||
# 选项(JSON格式,适用于选择题)
|
||||
options: Mapped[Optional[dict]] = mapped_column(JSON, nullable=True)
|
||||
|
||||
# 答案
|
||||
correct_answer: Mapped[str] = mapped_column(Text, nullable=False)
|
||||
explanation: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
||||
|
||||
# 分值
|
||||
score: Mapped[float] = mapped_column(Float, default=10.0)
|
||||
|
||||
# 难度等级: easy, medium, hard
|
||||
difficulty: Mapped[str] = mapped_column(String(10), default="medium", index=True)
|
||||
|
||||
# 标签(JSON格式)
|
||||
tags: Mapped[Optional[list]] = mapped_column(JSON, nullable=True)
|
||||
|
||||
# 使用统计
|
||||
usage_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
correct_count: Mapped[int] = mapped_column(Integer, default=0)
|
||||
|
||||
# 状态
|
||||
is_active: Mapped[bool] = mapped_column(default=True, index=True)
|
||||
|
||||
# 关系
|
||||
course = relationship("Course", back_populates="questions")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<Question(id={self.id}, course_id={self.course_id}, type={self.question_type})>"
|
||||
|
||||
|
||||
class ExamResult(BaseModel):
|
||||
"""考试结果详情模型"""
|
||||
|
||||
__tablename__ = "exam_results"
|
||||
__allow_unmapped__ = True
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True)
|
||||
exam_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("exams.id"), nullable=False, index=True
|
||||
)
|
||||
question_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("questions.id"), nullable=False
|
||||
)
|
||||
|
||||
# 用户答案
|
||||
user_answer: Mapped[Optional[str]] = mapped_column(Text, nullable=True)
|
||||
|
||||
# 是否正确
|
||||
is_correct: Mapped[bool] = mapped_column(default=False)
|
||||
|
||||
# 得分
|
||||
score: Mapped[float] = mapped_column(Float, default=0.0)
|
||||
|
||||
# 答题时长(秒)
|
||||
answer_time: Mapped[Optional[int]] = mapped_column(Integer, nullable=True)
|
||||
|
||||
# 关系
|
||||
exam = relationship("Exam", back_populates="results")
|
||||
question = relationship("Question")
|
||||
|
||||
def __repr__(self):
|
||||
return f"<ExamResult(id={self.id}, exam_id={self.exam_id}, question_id={self.question_id}, is_correct={self.is_correct})>"
|
||||
|
||||
|
||||
# 在模型文件末尾添加关系定义
|
||||
# 需要在User模型中添加
|
||||
# exams = relationship("Exam", back_populates="user")
|
||||
|
||||
# 需要在Course模型中添加
|
||||
# exams = relationship("Exam", back_populates="course")
|
||||
# questions = relationship("Question", back_populates="course")
|
||||
|
||||
# 需要在Exam模型中添加
|
||||
# results = relationship("ExamResult", back_populates="exam")
|
||||
Reference in New Issue
Block a user