AnCao/CLAUDE.md

618 lines
19 KiB
Markdown
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.

# 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()` 进行数据库操作
## 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)
```
## 错题本系统
**重要更新**: 错题本系统已全面重构为 新版本,提供更强大的功能和更好的用户体验。
### 核心特性
1. **多次错误记录历史** - 保存每次答错的完整记录,而非仅保留最后一次
2. **智能复习系统** - 基于艾宾浩斯遗忘曲线的间隔重复算法
3. **标签管理系统** - 支持自定义标签,灵活分类错题
4. **智能推荐引擎** - 优先推荐需要复习的高频错题
5. **掌握度追踪** - 自动计算和更新每道题的掌握度0-100%
6. **详细统计分析** - 错题趋势、掌握度分布、薄弱知识点分析
### 数据模型设计
#### 错题记录表 (`wrong_questions`)
```go
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`)
```go
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](internal/models/wrong_question_v2.go#L156)
```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](internal/services/wrong_question_service.go#L228)
### 统计数据
错题统计 提供更丰富的数据:
```json
{
"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](web/src/types/question.ts)
```typescript
// 错题记录
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](web/src/api/question.ts)
```typescript
// 获取错题列表(支持筛选和排序)
getWrongQuestionsV2(filter?: WrongQuestionFilter)
// 获取推荐错题
getRecommendedWrongQuestions(limit: number = 10)
// 获取错题统计
getWrongQuestionStats()
```
### 注意事项
- API 与旧版 API 完全兼容,可以同时使用
- 答题时会自动使用 API 记录错题
- 答对错题本中的题目时,会自动更新连续答对次数
- 掌握度达到 100% 时,题目会被标记为"已掌握"
- 标签功能支持自定义,建议按知识点或难度分类
## 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,确保评分结果稳定可靠
## 前端开发规范
### 包管理和开发
**重要**: 前端项目使用 **yarn** 作为包管理工具。
- **包管理器**: 使用 `yarn` 而非 `npm`
- **常用命令**:
```bash
# 安装依赖
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](web/vite.config.ts)
- **使用方式**: 前端代码中使用相对路径调用API,例如 `fetch('/api/login')`
- **后端服务器**: 确保后端服务运行在 `http://localhost:8080`
### UI 组件使用原则
**重要**: 在开发前端页面时,必须优先使用 UI 框架的组件。
- **优先使用 Ant Design 组件**: 项目使用 **antd (Ant Design)** 作为 UI 框架,开发时应优先查找并使用框架提供的组件
- **常用组件示例**:
- 表单输入: 使用 `Input` 组件,而非原生 `<input>`
- 按钮: 使用 `Button` 组件,而非原生 `<button>`
- 表单: 使用 `Form` 和 `Form.Item` 组件
- 提示信息: 使用 `message` 组件,而非自定义提示框
- 对话框: 使用 `Modal` 组件
- 列表: 使用 `List` 组件
- 布局: 使用 `Row`、`Col`、`Layout` 等布局组件
- 图标: 使用 `@ant-design/icons` 包中的图标
- **仅在必要时自定义**: 只有当 antd 没有提供对应组件时,才使用自定义组件
- **样式处理**: 使用 CSS Modules (`.module.less`) 编写组件样式,避免全局样式污染
- **主题定制**: 在 [web/vite.config.ts](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 系统 (`Row`、`Col`) 实现响应式布局
- **移动端优化**:
- 底部导航栏仅在移动端显示
- 触摸区域大小适中(最小 44x44px)
- 禁止双指缩放
- **PC端优化**:
- 内容居中,最大宽度限制
- 隐藏移动端特有的底部导航栏
- 更大的字体和间距