- 从服务器拉取完整代码 - 按框架规范整理项目结构 - 配置 Drone CI 测试环境部署 - 包含后端(FastAPI)、前端(Vue3)、管理端 技术栈: Vue3 + TypeScript + FastAPI + MySQL
154 lines
5.5 KiB
Python
154 lines
5.5 KiB
Python
"""
|
||
考试相关模型定义
|
||
"""
|
||
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")
|