yanlongqi e651910e74 refactor: 数据库模型优化和答题逻辑重构
主要变更:
- 数据库ID字段统一从 uint 改为 int64,提升数据容量和兼容性
- 重构答题检查逻辑,采用策略模式替代 switch-case
- 新增 PracticeProgress 模型,支持练习进度持久化
- 优化错题本系统,自动记录答题进度和错误历史
- 添加 lib/pq PostgreSQL 驱动依赖
- 移除错题标签管理 API(待后续迁移)
- 前端类型定义同步更新,适配后端模型变更

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-13 03:28:39 +08:00

131 lines
6.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package models
import (
"time"
"gorm.io/datatypes"
"gorm.io/gorm"
)
// Exam 试卷模型
type Exam struct {
ID uint `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
UserID uint `gorm:"not null;index" json:"user_id"` // 创建者ID
Title string `gorm:"type:varchar(200);default:''" json:"title"` // 试卷标题
TotalScore int `gorm:"not null;default:100" json:"total_score"` // 总分
Duration int `gorm:"not null;default:60" json:"duration"` // 考试时长(分钟)
PassScore int `gorm:"not null;default:60" json:"pass_score"` // 及格分数
QuestionIDs datatypes.JSON `gorm:"type:json" json:"question_ids"` // 题目ID列表 (JSON数组)
Status string `gorm:"type:varchar(20);not null;default:'active'" json:"status"` // 状态: active, archived
}
// ExamRecord 考试记录
type ExamRecord struct {
ID uint `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
ExamID uint `gorm:"not null;index" json:"exam_id"` // 试卷ID
UserID uint `gorm:"not null;index" json:"user_id"` // 考生ID
StartTime *time.Time `json:"start_time"` // 开始时间
SubmitTime *time.Time `json:"submit_time"` // 提交时间
TimeSpent int `json:"time_spent"` // 实际用时(秒)
Score float64 `gorm:"type:decimal(5,2)" json:"score"` // 得分
TotalScore int `json:"total_score"` // 总分
Status string `gorm:"type:varchar(20);not null;default:'in_progress'" json:"status"` // 状态: in_progress, submitted, graded
IsPassed bool `json:"is_passed"` // 是否通过
// 关联
Exam *Exam `gorm:"foreignKey:ExamID" json:"exam,omitempty"`
User *User `gorm:"foreignKey:UserID" json:"user,omitempty"`
}
// ExamUserAnswer 用户答案表(记录每道题的答案)
type ExamUserAnswer struct {
ID int64 `gorm:"primaryKey" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
ExamRecordID int64 `gorm:"not null;index:idx_record_question" json:"exam_record_id"` // 考试记录ID
QuestionID int64 `gorm:"not null;index:idx_record_question" json:"question_id"` // 题目ID
UserID int64 `gorm:"not null;index" json:"user_id"` // 用户ID
Answer datatypes.JSON `gorm:"type:json" json:"answer"` // 用户答案 (JSON格式支持各种题型)
IsCorrect *bool `json:"is_correct,omitempty"` // 是否正确(提交后评分)
Score float64 `gorm:"type:decimal(5,2);default:0" json:"score"` // 得分
AIGradingData datatypes.JSON `gorm:"type:json" json:"ai_grading_data,omitempty"` // AI评分数据
AnsweredAt *time.Time `json:"answered_at"` // 答题时间
LastModifiedAt time.Time `json:"last_modified_at"` // 最后修改时间
// 关联
ExamRecord *ExamRecord `gorm:"foreignKey:ExamRecordID" json:"-"`
Question *PracticeQuestion `gorm:"foreignKey:QuestionID" json:"-"`
}
// ExamConfig 试卷配置结构
type ExamConfig struct {
QuestionTypes []QuestionTypeConfig `json:"question_types"` // 题型配置
Categories []string `json:"categories"` // 题目分类筛选
Difficulty []string `json:"difficulty"` // 难度筛选
RandomOrder bool `json:"random_order"` // 是否随机顺序
}
// QuestionTypeConfig 题型配置
type QuestionTypeConfig struct {
Type string `json:"type"` // 题目类型
Count int `json:"count"` // 题目数量
Score float64 `json:"score"` // 每题分数
}
// ExamAnswer 考试答案结构
type ExamAnswer struct {
QuestionID int64 `json:"question_id"`
Answer interface{} `json:"answer"` // 用户答案
CorrectAnswer interface{} `json:"correct_answer"` // 正确答案
IsCorrect bool `json:"is_correct"`
Score float64 `json:"score"`
AIGrading *AIGrading `json:"ai_grading,omitempty"`
}
// ExamQuestionConfig 考试题目配置
type ExamQuestionConfig struct {
FillInBlank int `json:"fill_in_blank"` // 填空题数量
TrueFalse int `json:"true_false"` // 判断题数量
MultipleChoice int `json:"multiple_choice"` // 单选题数量
MultipleSelection int `json:"multiple_selection"` // 多选题数量
ShortAnswer int `json:"short_answer"` // 简答题数量
OrdinaryEssay int `json:"ordinary_essay"` // 普通涉密人员论述题数量
ManagementEssay int `json:"management_essay"` // 保密管理人员论述题数量
}
// DefaultExamConfig 默认考试配置
var DefaultExamConfig = ExamQuestionConfig{
FillInBlank: 10, // 填空题10道
TrueFalse: 10, // 判断题10道
MultipleChoice: 10, // 单选题10道
MultipleSelection: 10, // 多选题10道
ShortAnswer: 2, // 简答题2道
OrdinaryEssay: 1, // 普通论述题1道
ManagementEssay: 1, // 管理论述题1道
}
// ExamScoreConfig 考试分值配置
type ExamScoreConfig struct {
FillInBlank float64 `json:"fill_in_blank"` // 填空题分值
TrueFalse float64 `json:"true_false"` // 判断题分值
MultipleChoice float64 `json:"multiple_choice"` // 单选题分值
MultipleSelection float64 `json:"multiple_selection"` // 多选题分值
Essay float64 `json:"essay"` // 论述题分值
}
// DefaultScoreConfig 默认分值配置
var DefaultScoreConfig = ExamScoreConfig{
FillInBlank: 2.0, // 填空题每题2分 (共20分)
TrueFalse: 2.0, // 判断题每题2分 (共20分)
MultipleChoice: 1.0, // 单选题每题1分 (共10分)
MultipleSelection: 2.5, // 多选题每题2.5分 (共25分)
Essay: 25.0, // 论述题25分
}