646 lines
20 KiB
Markdown
646 lines
20 KiB
Markdown
# 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 // 是否已掌握
|
||
Tags []string // 标签列表 (JSON)
|
||
}
|
||
```
|
||
|
||
#### 错误历史表 (`wrong_question_history`)
|
||
|
||
```go
|
||
type WrongQuestionHistory struct {
|
||
ID uint // 主键
|
||
WrongQuestionID uint // 关联错题记录
|
||
UserAnswer string // 用户答案 (JSON)
|
||
CorrectAnswer string // 正确答案 (JSON)
|
||
AnsweredAt time.Time // 答题时间
|
||
TimeSpent int // 答题用时(秒)
|
||
IsCorrect bool // 本次是否正确
|
||
}
|
||
```
|
||
|
||
#### 错题标签表 (`wrong_question_tags`)
|
||
|
||
```go
|
||
type WrongQuestionTag struct {
|
||
ID uint // 主键
|
||
UserID uint // 用户ID
|
||
Name string // 标签名
|
||
Color string // 标签颜色
|
||
Description string // 描述
|
||
}
|
||
```
|
||
|
||
### 间隔重复算法(艾宾浩斯遗忘曲线)
|
||
|
||
系统采用科学的间隔重复算法,根据用户答题情况自动安排复习时间:
|
||
|
||
**复习间隔策略**: `[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` | 清空错题本 | - |
|
||
| PUT | `/api/wrong-questions/:id/tags` | 更新标签 | - |
|
||
|
||
**排序选项** (`sort` 参数):
|
||
- `review_time` - 按复习时间排序(最需要复习的在前)
|
||
- `wrong_count` - 按错误次数排序(错误最多的在前)
|
||
- `mastery_level` - 按掌握度排序(掌握度最低的在前)
|
||
- `time` - 按最后错误时间排序(默认)
|
||
|
||
#### 标签管理 API
|
||
|
||
| 方法 | 路由 | 功能 |
|
||
|------|------|------|
|
||
| GET | `/api/wrong-question-tags` | 获取标签列表 |
|
||
| POST | `/api/wrong-question-tags` | 创建标签 |
|
||
| PUT | `/api/wrong-question-tags/:id` | 更新标签 |
|
||
| DELETE | `/api/wrong-question-tags/:id` | 删除标签 |
|
||
|
||
### 智能推荐算法
|
||
|
||
推荐系统采用三级策略,优先推荐最需要复习的题目:
|
||
|
||
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
|
||
tags: string[]
|
||
recent_history?: WrongQuestionHistory[]
|
||
}
|
||
```
|
||
|
||
API 调用方法位于 [web/src/api/question.ts](web/src/api/question.ts):
|
||
|
||
```typescript
|
||
// 获取错题列表(支持筛选和排序)
|
||
getWrongQuestionsV2(filter?: WrongQuestionFilter)
|
||
|
||
// 获取推荐错题
|
||
getRecommendedWrongQuestions(limit: number = 10)
|
||
|
||
// 获取错题统计
|
||
getWrongQuestionStats()
|
||
|
||
// 标签管理
|
||
getWrongQuestionTags()
|
||
createWrongQuestionTag(data)
|
||
updateWrongQuestionTag(id, data)
|
||
deleteWrongQuestionTag(id)
|
||
```
|
||
|
||
### 注意事项
|
||
|
||
- 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端优化**:
|
||
- 内容居中,最大宽度限制
|
||
- 隐藏移动端特有的底部导航栏
|
||
- 更大的字体和间距
|
||
|