- 后端功能: * 新增练习题数据模型和数据库表结构 * 实现题目列表、随机题目、提交答案等API接口 * 支持5种题型:单选、多选、判断、填空、简答 * 判断题自动生成"对/错"选项 * 前后端类型映射(single/multiple/judge/fill/short) - 前端功能: * 新增首页,展示5种题型选择卡片和统计信息 * 完善答题页面,支持所有题型的渲染和答题 * 填空题特殊渲染:将****替换为横线输入框 * 实现题目列表、筛选、随机练习等功能 * 优化底部导航,添加首页、答题、我的三个标签 - 工具脚本: * 新增题目数据导入脚本 * 支持从JSON文件批量导入题库 - 文档更新: * 更新CLAUDE.md和README.md,记录新增功能 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
114 lines
2.7 KiB
Go
114 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"ankao/internal/database"
|
|
"ankao/internal/models"
|
|
"encoding/json"
|
|
"log"
|
|
"os"
|
|
)
|
|
|
|
// JSONQuestion JSON中的题目结构
|
|
type JSONQuestion struct {
|
|
ID string `json:"id"`
|
|
Question string `json:"question"`
|
|
Answers interface{} `json:"answers"`
|
|
Options interface{} `json:"options,omitempty"`
|
|
}
|
|
|
|
// JSONQuestionGroup JSON中的题目组结构
|
|
type JSONQuestionGroup struct {
|
|
Type string `json:"type"`
|
|
TypeName string `json:"typeName"`
|
|
List []JSONQuestion `json:"list"`
|
|
}
|
|
|
|
func main() {
|
|
log.Println("开始导入题目数据...")
|
|
|
|
// 初始化数据库
|
|
if err := database.InitDB(); err != nil {
|
|
log.Fatal("数据库初始化失败:", err)
|
|
}
|
|
|
|
// 读取JSON文件
|
|
data, err := os.ReadFile("practice_question_pool.json")
|
|
if err != nil {
|
|
log.Fatal("读取JSON文件失败:", err)
|
|
}
|
|
|
|
// 解析JSON
|
|
var groups []JSONQuestionGroup
|
|
if err := json.Unmarshal(data, &groups); err != nil {
|
|
log.Fatal("解析JSON失败:", err)
|
|
}
|
|
|
|
// 导入数据
|
|
db := database.GetDB()
|
|
totalCount := 0
|
|
|
|
for _, group := range groups {
|
|
log.Printf("导入题型: %s (%s), 题目数量: %d", group.TypeName, group.Type, len(group.List))
|
|
|
|
for _, q := range group.List {
|
|
// 将答案转换为JSON字符串存储
|
|
answerJSON, err := json.Marshal(q.Answers)
|
|
if err != nil {
|
|
log.Printf("序列化答案失败 (ID: %s): %v", q.ID, err)
|
|
continue
|
|
}
|
|
|
|
// 将选项转换为JSON字符串存储
|
|
optionsJSON := ""
|
|
if q.Options != nil {
|
|
optJSON, err := json.Marshal(q.Options)
|
|
if err != nil {
|
|
log.Printf("序列化选项失败 (ID: %s): %v", q.ID, err)
|
|
continue
|
|
}
|
|
optionsJSON = string(optJSON)
|
|
}
|
|
|
|
// 处理题型映射
|
|
questionType := mapQuestionType(group.Type)
|
|
|
|
// 创建题目记录
|
|
question := models.PracticeQuestion{
|
|
QuestionID: q.ID,
|
|
Type: questionType,
|
|
TypeName: group.TypeName,
|
|
Question: q.Question,
|
|
AnswerData: string(answerJSON),
|
|
OptionsData: optionsJSON,
|
|
}
|
|
|
|
// 插入数据库
|
|
if err := db.Create(&question).Error; err != nil {
|
|
log.Printf("插入题目失败 (ID: %s): %v", q.ID, err)
|
|
continue
|
|
}
|
|
totalCount++
|
|
}
|
|
}
|
|
|
|
log.Printf("数据导入完成! 共导入 %d 道题目", totalCount)
|
|
}
|
|
|
|
// mapQuestionType 映射题型
|
|
func mapQuestionType(jsonType string) models.PracticeQuestionType {
|
|
switch jsonType {
|
|
case "fill-in-blank":
|
|
return models.FillInBlank
|
|
case "true-false":
|
|
return models.TrueFalseType
|
|
case "multiple-choice":
|
|
return models.MultipleChoiceQ
|
|
case "multiple-selection":
|
|
return models.MultipleSelection
|
|
case "short-answer":
|
|
return models.ShortAnswer
|
|
default:
|
|
return models.PracticeQuestionType(jsonType)
|
|
}
|
|
}
|