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 // 关联关系 Shares []ExamShare `gorm:"foreignKey:ExamID" json:"-"` // 该试卷的分享记录(作为被分享试卷) SharedToMe []ExamShare `gorm:"foreignKey:SharedToID" json:"-"` // 分享给我的记录(作为接收者) } // IsAccessibleBy 检查用户是否有权限访问试卷 func (e *Exam) IsAccessibleBy(userID int64, db *gorm.DB) bool { // 用户是试卷创建者 if int64(e.UserID) == userID { return true } // 检查是否被分享给该用户 var count int64 db.Model(&ExamShare{}).Where("exam_id = ? AND shared_to_id = ?", e.ID, userID).Count(&count) return count > 0 } // GetAccessibleExams 获取用户可访问的所有试卷(拥有的+被分享的) func GetAccessibleExams(userID int64, db *gorm.DB) ([]Exam, error) { var exams []Exam // 子查询:被分享的试卷ID subQuery := db.Model(&ExamShare{}).Select("exam_id").Where("shared_to_id = ?", userID) // 查询:用户拥有的 OR 被分享的试卷 err := db.Where("user_id = ? OR id IN (?)", uint(userID), subQuery). Order("created_at DESC"). Find(&exams).Error return exams, err } // 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分 }