AnCao/CLAUDE.md

19 KiB
Raw Permalink Blame History

CLAUDE.md

本文件为 Claude Code (claude.ai/code) 在此代码仓库中工作时提供指导。

重要开发规范

文档同步更新规则

关键规则: 当实现新功能、修改现有功能或更改项目配置时,必须同步更新相关文档

  • README.md 更新时机:

    • 添加新的核心功能或特性
    • 修改项目安装、配置或运行方式
    • 更改技术栈或主要依赖
    • 添加新的 API 端点或修改现有端点
    • 更新项目架构或目录结构
  • CLAUDE.md 更新时机:

    • 添加新的开发规范或最佳实践
    • 修改项目配置(如代理、构建工具等)
    • 更改目录结构或文件组织方式
    • 引入新的工具或技术
    • 更新常用命令或开发流程
  • 更新原则:

    • 代码修改和文档更新应在同一次提交中完成
    • 文档要清晰、准确,反映当前代码状态
    • 使用 markdown 链接引用具体文件位置
    • 及时移除过时的说明和示例

项目概述

AnKao 是一个使用 Gin 框架构建的 Go Web 应用程序。该项目遵循整洁架构模式,具有清晰的关注点分离,并设计为支持数据库集成。

架构

请求流程

  1. HTTP 请求到达运行在 8080 端口的 Gin 服务器
  2. 请求通过 Gin 的默认中间件(Logger、Recovery)和自定义中间件
  3. Gin 路由器匹配路由并将请求定向到相应的处理器
  4. 处理器(位于 internal/handlers/)使用 *gin.Context 处理请求并返回 JSON 响应

中间件模式

Gin 中的中间件使用 gin.HandlerFunc 模式:

func MiddlewareName() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 预处理
        c.Next()
        // 后处理
    }
}

中间件在 main.go:15 中使用 r.Use() 注册。

模块结构

  • main.go - 应用程序入口点,服务器配置和路由设置
  • internal/handlers/ - HTTP 请求处理器,全部使用 *gin.Context 并返回 JSON 响应
  • internal/middleware/ - Gin 中间件链(当前:自定义日志记录器、CORS)
  • internal/models/ - 数据模型
  • internal/services/ - 业务服务
  • internal/database/ - 数据库连接和初始化
  • pkg/config/ - 配置管理(数据库配置、AI配置等)

常用命令

开发

# 运行服务器
go run main.go

# 安装/更新依赖
go mod tidy

# 格式化代码
go fmt ./...

# 检查代码常见问题
go vet ./...

构建

# 构建二进制文件到 bin/server
go build -o bin/server.exe main.go

# 运行构建的二进制文件 (Windows)
.\bin\server.exe

# 运行构建的二进制文件 (Unix)
./bin/server

测试

# 运行所有测试
go test ./...

# 运行带覆盖率的测试
go test -cover ./...

# 运行特定包的测试
go test ./internal/handlers/

# 运行详细输出的测试
go test -v ./...

关键实现细节

  • 框架: 使用 Gin v1.11.0
  • ORM: 使用 GORM v1.31.1
  • 数据库: PostgreSQL (配置在 pkg/config/config.go)
  • AI服务: 使用 go-openai SDK v1.41.2,配置在 pkg/config/config.go
  • 服务器端口: :8080 (在 main.go:42 中配置)
  • 处理器签名: 所有处理器使用 func(c *gin.Context) 模式
  • JSON 响应: 使用 c.JSON() 方法配合 gin.H{} 或结构体
  • 导入路径: 使用模块名 ankao (在 go.mod 中定义)
  • 路由注册: 路由在 main.go 中使用 r.GET()r.POST() 等注册
  • 中间件: 使用 r.Use() 全局应用或通过路由分组应用到特定路由
  • 密码加密: 使用 bcrypt 加密存储用户密码
  • AI评分: 简答题使用AI智能评分提供分数、评语和改进建议

添加新功能

添加新处理器

  1. internal/handlers/ 中创建处理器函数,签名为 func(c *gin.Context)
  2. 使用 c.JSON() 返回响应
  3. main.go 中注册路由(例如:r.GET("/path", handlers.YourHandler))

添加中间件

  1. internal/middleware/ 中创建返回 gin.HandlerFunc 的中间件
  2. 使用 r.Use(middleware.YourMiddleware()) 全局应用或应用到路由组

数据库集成

项目已集成 PostgreSQL 数据库:

  • 配置: 数据库配置在 pkg/config/config.go
  • 初始化: 数据库初始化在 internal/database/database.go
  • 模型定义: 在 internal/models/ 中添加 GORM 模型
  • 迁移: 使用 DB.AutoMigrate() 自动迁移表结构
  • 使用方式: 通过 database.GetDB() 获取数据库实例

添加新的数据模型

  1. internal/models/ 中创建模型文件
  2. 定义结构体,使用 GORM 标签
  3. internal/database/database.goInitDB() 中添加 AutoMigrate
  4. 在处理器中使用 database.GetDB() 进行数据库操作

AI评分系统

项目集成了AI智能评分功能专门用于对简答题进行评分和反馈。

AI评分配置

AI服务配置位于 pkg/config/config.go

type AIConfig struct {
    BaseURL string  // AI API地址
    APIKey  string  // API密钥
    Model   string  // 使用的模型名称
}

配置方式

  1. 默认配置: 直接在代码中设置默认值
  2. 环境变量: 通过环境变量覆盖默认配置
    export AI_BASE_URL="https://ai.yuchat.top"
    export AI_API_KEY="你的API密钥"
    export AI_MODEL="deepseek-v3"
    

AI评分服务

AI评分服务实现位于 internal/services/ai_grading.go

主要功能

  • NewAIGradingService() - 创建AI评分服务实例
  • GradeShortAnswer(question, standardAnswer, userAnswer) - 对简答题进行AI评分

返回结果

type AIGradingResult struct {
    Score      float64  // 得分 (0-100)
    IsCorrect  bool     // 是否正确 (Score >= 60 视为正确)
    Feedback   string   // 评语
    Suggestion string   // 改进建议
}

集成方式

practice_handler.goSubmitPracticeAnswer 函数中:

// 对简答题使用AI评分
if question.Type == "short-answer" {
    aiService := services.NewAIGradingService()
    aiResult, err := aiService.GradeShortAnswer(
        question.Question,
        standardAnswerStr,
        userAnswerStr,
    )
    // 使用AI评分结果
    correct = aiResult.IsCorrect
    aiGrading = &models.AIGrading{
        Score:      aiResult.Score,
        Feedback:   aiResult.Feedback,
        Suggestion: aiResult.Suggestion,
    }
}

API响应格式

简答题提交后,响应中会包含 ai_grading 字段:

{
  "success": true,
  "data": {
    "correct": true,
    "user_answer": "用户的答案",
    "correct_answer": "标准答案",
    "ai_grading": {
      "score": 85,
      "feedback": "答案基本正确,要点全面",
      "suggestion": "可以补充一些具体的例子"
    }
  }
}

注意事项

  • AI评分仅对 short-answer 类型的题目生效
  • 其他题型(填空题、判断题、选择题)仍使用传统的精确匹配方式
  • AI评分失败时不影响主流程会记录日志并使用传统评分方式
  • 评分采用温度参数 0.3,确保评分结果稳定可靠

自定义AI评分提示词

如需调整评分标准,修改 ai_grading.go 中的 prompt 变量:

prompt := fmt.Sprintf(`你是一位专业的阅卷老师,请对以下简答题进行评分。

题目:%s
标准答案:%s
学生答案:%s

请按照以下要求进行评分:
1. 给出一个0-100的分数
2. 判断答案是否正确60分及以上为正确
3. 给出简短的评语不超过50字
4. 如果答案不完善给出改进建议不超过50字
...
`, question, standardAnswer, userAnswer)

错题本系统

重要更新: 错题本系统已全面重构为 新版本,提供更强大的功能和更好的用户体验。

核心特性

  1. 多次错误记录历史 - 保存每次答错的完整记录,而非仅保留最后一次
  2. 智能复习系统 - 基于艾宾浩斯遗忘曲线的间隔重复算法
  3. 标签管理系统 - 支持自定义标签,灵活分类错题
  4. 智能推荐引擎 - 优先推荐需要复习的高频错题
  5. 掌握度追踪 - 自动计算和更新每道题的掌握度0-100%
  6. 详细统计分析 - 错题趋势、掌握度分布、薄弱知识点分析

数据模型设计

错题记录表 (wrong_questions)

type WrongQuestion struct {
    ID                 uint           // 主键
    UserID             uint           // 用户ID
    QuestionID         uint           // 题目ID
    FirstWrongTime     time.Time      // 首次错误时间
    LastWrongTime      time.Time      // 最后错误时间
    TotalWrongCount    int            // 总错误次数
    MasteryLevel       int            // 掌握度 (0-100)
    NextReviewTime     *time.Time     // 下次复习时间
    ConsecutiveCorrect int            // 连续答对次数
    IsMastered         bool           // 是否已掌握
}

错误历史表 (wrong_question_history)

type WrongQuestionHistory struct {
    ID              uint      // 主键
    WrongQuestionID uint      // 关联错题记录
    UserAnswer      string    // 用户答案 (JSON)
    CorrectAnswer   string    // 正确答案 (JSON)
    AnsweredAt      time.Time // 答题时间
    TimeSpent       int       // 答题用时(秒)
    IsCorrect       bool      // 本次是否正确
}

间隔重复算法(艾宾浩斯遗忘曲线)

系统采用科学的间隔重复算法,根据用户答题情况自动安排复习时间:

复习间隔策略: [1天, 3天, 7天, 15天, 30天, 60天]

  • 答错时:重置连续答对次数,重新从第一个间隔开始
  • 答对时:连续答对次数+1进入下一个复习间隔
  • 完全掌握连续答对6次后标记为"已掌握"

实现位置: internal/models/wrong_question_v2.go

// 默认复习策略
var DefaultReviewStrategy = ReviewStrategy{
    Intervals: []int{1, 3, 7, 15, 30, 60},
}

// 自动计算下次复习时间
func (wq *WrongQuestion) CalculateNextReviewTime() {
    strategy := DefaultReviewStrategy
    level := wq.ConsecutiveCorrect

    if level >= len(strategy.Intervals) {
        wq.IsMastered = true // 已完全掌握
        wq.MasteryLevel = 100
        wq.NextReviewTime = nil
        return
    }

    days := strategy.Intervals[level]
    nextTime := time.Now().Add(time.Duration(days) * 24 * time.Hour)
    wq.NextReviewTime = &nextTime
    wq.MasteryLevel = (level * 100) / len(strategy.Intervals)
}

API 接口

所有 API 都在 /api/v2 路径下,与旧版 API 共存以保持向后兼容。

错题管理 API

方法 路由 功能 查询参数
GET /api/wrong-questions 获取错题列表 is_mastered, tag, type, sort
GET /api/wrong-questions/:id 获取错题详情 -
GET /api/wrong-questions/stats 获取错题统计 -
GET /api/wrong-questions/recommended 获取推荐错题 limit
DELETE /api/wrong-questions/:id 删除错题 -
DELETE /api/wrong-questions 清空错题本 -

排序选项 (sort 参数):

  • review_time - 按复习时间排序(最需要复习的在前)
  • wrong_count - 按错误次数排序(错误最多的在前)
  • mastery_level - 按掌握度排序(掌握度最低的在前)
  • time - 按最后错误时间排序(默认)

智能推荐算法

推荐系统采用三级策略,优先推荐最需要复习的题目:

  1. 优先级 1: 到期需要复习的题目(next_review_time <= NOW()
  2. 优先级 2: 高频错题且掌握度低(wrong_count DESC, mastery_level ASC
  3. 优先级 3: 最近答错的题目(last_wrong_time DESC

实现位置: internal/services/wrong_question_service.go

统计数据

错题统计 提供更丰富的数据:

{
  "total_wrong": 50,
  "mastered": 10,
  "not_mastered": 40,
  "need_review": 15,
  "type_stats": { "single-choice": 20, "multiple-choice": 15, "fill-in-blank": 15 },
  "category_stats": { "数学": 25, "语文": 15, "英语": 10 },
  "mastery_level_dist": { "很差": 10, "较差": 15, "一般": 10, "良好": 10, "优秀": 5 },
  "tag_stats": { "重点": 20, "难点": 15 },
  "trend_data": [
    { "date": "01-01", "count": 5 },
    { "date": "01-02", "count": 3 },
    ...
  ]
}

前端集成

前端 TypeScript 类型定义位于 web/src/types/question.ts

// 错题记录
interface WrongQuestion {
  id: number
  question_id: number
  question?: Question
  first_wrong_time: string
  last_wrong_time: string
  total_wrong_count: number
  mastery_level: number        // 0-100
  next_review_time?: string
  consecutive_correct: number
  is_mastered: boolean
  recent_history?: WrongQuestionHistory[]
}

API 调用方法位于 web/src/api/question.ts

// 获取错题列表(支持筛选和排序)
getWrongQuestionsV2(filter?: WrongQuestionFilter)

// 获取推荐错题
getRecommendedWrongQuestions(limit: number = 10)

// 获取错题统计
getWrongQuestionStats()

注意事项

  • API 与旧版 API 完全兼容,可以同时使用
  • 答题时会自动使用 API 记录错题
  • 答对错题本中的题目时,会自动更新连续答对次数
  • 掌握度达到 100% 时,题目会被标记为"已掌握"
  • 标签功能支持自定义,建议按知识点或难度分类

AI评分系统

项目集成了AI智能评分功能专门用于对简答题进行评分和反馈。

AI评分配置

AI服务配置位于 pkg/config/config.go

type AIConfig struct {
    BaseURL string  // AI API地址
    APIKey  string  // API密钥
    Model   string  // 使用的模型名称
}

配置方式

  1. 默认配置: 直接在代码中设置默认值
  2. 环境变量: 通过环境变量覆盖默认配置
    export AI_BASE_URL="https://ai.yuchat.top"
    export AI_API_KEY="你的API密钥"
    export AI_MODEL="deepseek-v3"
    

AI评分服务

AI评分服务实现位于 internal/services/ai_grading.go

主要功能

  • NewAIGradingService() - 创建AI评分服务实例
  • GradeShortAnswer(question, standardAnswer, userAnswer) - 对简答题进行AI评分

返回结果

type AIGradingResult struct {
    Score      float64  // 得分 (0-100)
    IsCorrect  bool     // 是否正确 (Score >= 60 视为正确)
    Feedback   string   // 评语
    Suggestion string   // 改进建议
}

集成方式

practice_handler.goSubmitPracticeAnswer 函数中:

// 对简答题使用AI评分
if question.Type == "short-answer" {
    aiService := services.NewAIGradingService()
    aiResult, err := aiService.GradeShortAnswer(
        question.Question,
        standardAnswerStr,
        userAnswerStr,
    )
    // 使用AI评分结果
    correct = aiResult.IsCorrect
    aiGrading = &models.AIGrading{
        Score:      aiResult.Score,
        Feedback:   aiResult.Feedback,
        Suggestion: aiResult.Suggestion,
    }
}

API响应格式

简答题提交后,响应中会包含 ai_grading 字段:

{
  "success": true,
  "data": {
    "correct": true,
    "user_answer": "用户的答案",
    "correct_answer": "标准答案",
    "ai_grading": {
      "score": 85,
      "feedback": "答案基本正确,要点全面",
      "suggestion": "可以补充一些具体的例子"
    }
  }
}

注意事项

  • AI评分仅对 short-answer 类型的题目生效
  • 其他题型(填空题、判断题、选择题)仍使用传统的精确匹配方式
  • AI评分失败时不影响主流程会记录日志并使用传统评分方式
  • 评分采用温度参数 0.3,确保评分结果稳定可靠

前端开发规范

包管理和开发

重要: 前端项目使用 yarn 作为包管理工具。

  • 包管理器: 使用 yarn 而非 npm
  • 常用命令:
    # 安装依赖
    yarn install
    
    # 启动开发服务器 (运行在 http://localhost:3000)
    yarn dev
    
    # 构建生产版本
    yarn build
    
    # 添加依赖
    yarn add <package-name>
    
    # 添加开发依赖
    yarn add -D <package-name>
    

API 代理配置

  • 开发环境: Vite 已配置代理,前端请求 /api/* 会被代理到后端 http://localhost:8080
  • 配置位置: web/vite.config.ts
  • 使用方式: 前端代码中使用相对路径调用API,例如 fetch('/api/login')
  • 后端服务器: 确保后端服务运行在 http://localhost:8080

UI 组件使用原则

重要: 在开发前端页面时,必须优先使用 UI 框架的组件。

  • 优先使用 Ant Design 组件: 项目使用 antd (Ant Design) 作为 UI 框架,开发时应优先查找并使用框架提供的组件
  • 常用组件示例:
    • 表单输入: 使用 Input 组件,而非原生 <input>
    • 按钮: 使用 Button 组件,而非原生 <button>
    • 表单: 使用 FormForm.Item 组件
    • 提示信息: 使用 message 组件,而非自定义提示框
    • 对话框: 使用 Modal 组件
    • 列表: 使用 List 组件
    • 布局: 使用 RowColLayout 等布局组件
    • 图标: 使用 @ant-design/icons 包中的图标
  • 仅在必要时自定义: 只有当 antd 没有提供对应组件时,才使用自定义组件
  • 样式处理: 使用 CSS Modules (.module.less) 编写组件样式,避免全局样式污染
  • 主题定制: 在 web/vite.config.ts 中通过 modifyVars 定制 antd 主题

前端项目结构

  • web/src/pages/ - 页面组件
  • web/src/components/ - 可复用组件
  • web/src/pages/*.module.less - 页面样式文件 (CSS Modules)
  • web/vite.config.ts - Vite 配置文件(包含代理配置和 antd 主题定制)

响应式设计

重要: 应用采用响应式设计,同时适配移动端和PC端。

  • 响应式断点:
    • 移动端: max-width: 768px
    • 平板: 769px ~ 1024px
    • PC端: min-width: 1025px
  • 布局适配: 使用 antd 的 Grid 系统 (RowCol) 实现响应式布局
  • 移动端优化:
    • 底部导航栏仅在移动端显示
    • 触摸区域大小适中(最小 44x44px)
    • 禁止双指缩放
  • PC端优化:
    • 内容居中,最大宽度限制
    • 隐藏移动端特有的底部导航栏
    • 更大的字体和间距