# 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` 模式: ```go func MiddlewareName() gin.HandlerFunc { return func(c *gin.Context) { // 预处理 c.Next() // 后处理 } } ``` 中间件在 [main.go:15](main.go#L15) 中使用 `r.Use()` 注册。 ### 模块结构 - **main.go** - 应用程序入口点,服务器配置和路由设置 - **internal/handlers/** - HTTP 请求处理器,全部使用 `*gin.Context` 并返回 JSON 响应 - [user.go](internal/handlers/user.go) - 用户登录注册相关 - [practice_handler.go](internal/handlers/practice_handler.go) - 练习题相关 - [handlers.go](internal/handlers/handlers.go) - 通用处理器(健康检查等) - **internal/middleware/** - Gin 中间件链(当前:自定义日志记录器、CORS) - **internal/models/** - 数据模型 - [user.go](internal/models/user.go) - 用户模型 - [practice_question.go](internal/models/practice_question.go) - 练习题模型 - **internal/services/** - 业务服务 - [ai_grading.go](internal/services/ai_grading.go) - AI评分服务 - **internal/database/** - 数据库连接和初始化 - **pkg/config/** - 配置管理(数据库配置、AI配置等) - **scripts/** - 工具脚本 - [import_questions.go](scripts/import_questions.go) - 题目数据导入脚本 ## 常用命令 ### 开发 ```bash # 运行服务器 go run main.go # 安装/更新依赖 go mod tidy # 格式化代码 go fmt ./... # 检查代码常见问题 go vet ./... # 导入练习题数据(首次运行需要) go run scripts/import_questions.go ``` ### 构建 ```bash # 构建二进制文件到 bin/server go build -o bin/server.exe main.go # 运行构建的二进制文件 (Windows) .\bin\server.exe # 运行构建的二进制文件 (Unix) ./bin/server ``` ### 测试 ```bash # 运行所有测试 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](pkg/config/config.go)) - **AI服务**: 使用 go-openai SDK v1.41.2,配置在 [pkg/config/config.go](pkg/config/config.go) - **服务器端口**: :8080 (在 [main.go:42](main.go#L42) 中配置) - **处理器签名**: 所有处理器使用 `func(c *gin.Context)` 模式 - **JSON 响应**: 使用 `c.JSON()` 方法配合 `gin.H{}` 或结构体 - **导入路径**: 使用模块名 `ankao` (在 go.mod 中定义) - **路由注册**: 路由在 [main.go](main.go) 中使用 `r.GET()`、`r.POST()` 等注册 - **中间件**: 使用 `r.Use()` 全局应用或通过路由分组应用到特定路由 - **密码加密**: 使用 bcrypt 加密存储用户密码 - **AI评分**: 简答题使用AI智能评分,提供分数、评语和改进建议 ## 添加新功能 ### 添加新处理器 1. 在 `internal/handlers/` 中创建处理器函数,签名为 `func(c *gin.Context)` 2. 使用 `c.JSON()` 返回响应 3. 在 [main.go](main.go) 中注册路由(例如:`r.GET("/path", handlers.YourHandler)`) ### 添加中间件 1. 在 `internal/middleware/` 中创建返回 `gin.HandlerFunc` 的中间件 2. 使用 `r.Use(middleware.YourMiddleware())` 全局应用或应用到路由组 ### 数据库集成 项目已集成 PostgreSQL 数据库: - **配置**: 数据库配置在 [pkg/config/config.go](pkg/config/config.go) - **初始化**: 数据库初始化在 [internal/database/database.go](internal/database/database.go) - **模型定义**: 在 `internal/models/` 中添加 GORM 模型 - **迁移**: 使用 `DB.AutoMigrate()` 自动迁移表结构 - **使用方式**: 通过 `database.GetDB()` 获取数据库实例 ### 添加新的数据模型 1. 在 `internal/models/` 中创建模型文件 2. 定义结构体,使用 GORM 标签 3. 在 [internal/database/database.go](internal/database/database.go) 的 `InitDB()` 中添加 `AutoMigrate` 4. 在处理器中使用 `database.GetDB()` 进行数据库操作 ### 导入数据到数据库 **示例**: 练习题数据导入 1. **准备JSON数据文件**: 如 [practice_question_pool.json](practice_question_pool.json) 2. **创建数据模型**: 在 `internal/models/` 中定义数据结构 3. **创建导入脚本**: 在 `scripts/` 目录创建导入脚本,如 [import_questions.go](scripts/import_questions.go) 4. **解析JSON并插入**: ```go // 读取JSON文件 data, _ := os.ReadFile("data.json") // 解析JSON var items []YourStruct json.Unmarshal(data, &items) // 插入数据库 db := database.GetDB() for _, item := range items { db.Create(&item) } ``` 5. **运行导入脚本**: `go run scripts/import_questions.go` **注意事项**: - JSON中复杂数据(如数组、对象)需要序列化为字符串存储 - 使用唯一索引防止重复导入 - 大批量导入建议使用事务提高性能 ## AI评分系统 项目集成了AI智能评分功能,专门用于对简答题进行评分和反馈。 ### AI评分配置 AI服务配置位于 [pkg/config/config.go](pkg/config/config.go): ```go type AIConfig struct { BaseURL string // AI API地址 APIKey string // API密钥 Model string // 使用的模型名称 } ``` **配置方式**: 1. **默认配置**: 直接在代码中设置默认值 2. **环境变量**: 通过环境变量覆盖默认配置 ```bash 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](internal/services/ai_grading.go): **主要功能**: - `NewAIGradingService()` - 创建AI评分服务实例 - `GradeShortAnswer(question, standardAnswer, userAnswer)` - 对简答题进行AI评分 **返回结果**: ```go type AIGradingResult struct { Score float64 // 得分 (0-100) IsCorrect bool // 是否正确 (Score >= 60 视为正确) Feedback string // 评语 Suggestion string // 改进建议 } ``` ### 集成方式 在 [practice_handler.go](internal/handlers/practice_handler.go) 的 `SubmitPracticeAnswer` 函数中: ```go // 对简答题使用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` 字段: ```json { "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](internal/services/ai_grading.go) 中的 `prompt` 变量: ```go prompt := fmt.Sprintf(`你是一位专业的阅卷老师,请对以下简答题进行评分。 题目:%s 标准答案:%s 学生答案:%s 请按照以下要求进行评分: 1. 给出一个0-100的分数 2. 判断答案是否正确(60分及以上为正确) 3. 给出简短的评语(不超过50字) 4. 如果答案不完善,给出改进建议(不超过50字) ... `, question, standardAnswer, userAnswer) ``` ## 前端开发规范 ### 包管理和开发 **重要**: 前端项目使用 **yarn** 作为包管理工具。 - **包管理器**: 使用 `yarn` 而非 `npm` - **常用命令**: ```bash # 安装依赖 yarn install # 启动开发服务器 (运行在 http://localhost:3000) yarn dev # 构建生产版本 yarn build # 添加依赖 yarn add # 添加开发依赖 yarn add -D ``` ### API 代理配置 - **开发环境**: Vite 已配置代理,前端请求 `/api/*` 会被代理到后端 `http://localhost:8080` - **配置位置**: [web/vite.config.ts](web/vite.config.ts) - **使用方式**: 前端代码中使用相对路径调用API,例如 `fetch('/api/login')` - **后端服务器**: 确保后端服务运行在 `http://localhost:8080` ### UI 组件使用原则 **重要**: 在开发前端页面时,必须优先使用 UI 框架的组件。 - **优先使用 Ant Design 组件**: 项目使用 **antd (Ant Design)** 作为 UI 框架,开发时应优先查找并使用框架提供的组件 - **常用组件示例**: - 表单输入: 使用 `Input` 组件,而非原生 `` - 按钮: 使用 `Button` 组件,而非原生 `