AnCao/main.go
yanlongqi 52fff11f07 feat: 实现模拟考试功能
## 后端实现
- 添加考试数据模型 (Exam)
- 实现考试生成API (/api/exam/generate)
- 实现获取考试详情API (/api/exam/:id)
- 实现提交考试API (/api/exam/:id/submit)
- 支持按题型随机抽取题目
- AI智能评分(简答题和论述题)
- 自动计算总分和详细评分

## 前端实现
- 首页添加"模拟考试"入口
- 考试准备页:显示考试说明,选择在线/打印模式
- 在线答题页:按题型分组显示,支持论述题二选一
- 试卷打印页:A4排版,支持打印试卷/答案
- 成绩报告页:显示总分、详细评分、错题分析

## 核心特性
- 随机组卷:填空10题、判断10题、单选10题、多选10题、简答2题、论述题2选1
- 智能评分:使用AI评分论述题,给出分数、评语和建议
- 答题进度保存:使用localStorage防止刷新丢失
- 打印优化:A4纸张、黑白打印、合理排版
- 响应式设计:适配移动端、平板和PC端

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-08 20:45:30 +08:00

111 lines
4.3 KiB
Go
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.

package main
import (
"ankao/internal/database"
"ankao/internal/handlers"
"ankao/internal/middleware"
"log"
"github.com/gin-gonic/gin"
)
func main() {
// 初始化数据库连接
if err := database.InitDB(); err != nil {
log.Fatal("数据库初始化失败:", err)
}
log.Println("数据库连接成功")
// 创建Gin路由器
r := gin.Default()
// 应用自定义中间件
r.Use(middleware.CORS())
r.Use(middleware.Logger())
// API路由组必须在静态文件服务之前注册
api := r.Group("/api")
{
// 健康检查
api.GET("/health", handlers.HealthCheckHandler)
// 用户相关API
api.POST("/login", handlers.Login) // 用户登录
api.POST("/register", handlers.Register) // 用户注册
// 公开的练习题相关API
api.GET("/practice/types", handlers.GetPracticeQuestionTypes) // 获取题型列表
// 需要认证的路由
auth := api.Group("", middleware.Auth())
{
// 用户相关API
auth.PUT("/user/type", handlers.UpdateUserType) // 更新用户类型
auth.PUT("/user/profile", handlers.UpdateProfile) // 更新用户信息
auth.PUT("/user/password", handlers.ChangePassword) // 修改密码
// 排行榜API
auth.GET("/ranking/daily", handlers.GetDailyRanking) // 获取今日排行榜
// 练习题相关API需要登录
auth.GET("/practice/questions", handlers.GetPracticeQuestions) // 获取练习题目列表
auth.GET("/practice/questions/:id", handlers.GetPracticeQuestionByID) // 获取指定练习题目
auth.POST("/practice/explain", handlers.ExplainQuestion) // 生成题目解析AI
// 练习题提交(需要登录才能记录错题)
auth.POST("/practice/submit", handlers.SubmitPracticeAnswer) // 提交练习答案
auth.GET("/practice/statistics", handlers.GetStatistics) // 获取统计数据
// 错题本相关API
auth.GET("/wrong-questions", handlers.GetWrongQuestions) // 获取错题列表(支持筛选和排序)
auth.GET("/wrong-questions/stats", handlers.GetWrongQuestionStats) // 获取错题统计(含趋势)
auth.GET("/wrong-questions/recommended", handlers.GetRecommendedWrongQuestions) // 获取推荐错题
auth.GET("/wrong-questions/:id", handlers.GetWrongQuestionDetail) // 获取错题详情
auth.DELETE("/wrong-questions/:id", handlers.DeleteWrongQuestion) // 删除错题
auth.DELETE("/wrong-questions", handlers.ClearWrongQuestions) // 清空错题本
auth.PUT("/wrong-questions/:id/tags", handlers.UpdateWrongQuestionTags) // 更新错题标签
// 标签管理API
auth.GET("/wrong-question-tags", handlers.GetWrongQuestionTags) // 获取标签列表
auth.POST("/wrong-question-tags", handlers.CreateWrongQuestionTag) // 创建标签
auth.PUT("/wrong-question-tags/:id", handlers.UpdateWrongQuestionTag) // 更新标签
auth.DELETE("/wrong-question-tags/:id", handlers.DeleteWrongQuestionTag) // 删除标签
// 考试相关API
auth.POST("/exam/generate", handlers.GenerateExam) // 生成考试
auth.GET("/exam/:id", handlers.GetExam) // 获取考试详情
auth.POST("/exam/:id/submit", handlers.SubmitExam) // 提交考试
}
// 题库管理API需要管理员权限
admin := api.Group("", middleware.Auth(), middleware.AdminAuth())
{
admin.POST("/practice/questions", handlers.CreatePracticeQuestion) // 创建题目
admin.PUT("/practice/questions/:id", handlers.UpdatePracticeQuestion) // 更新题目
admin.DELETE("/practice/questions/:id", handlers.DeletePracticeQuestion) // 删除题目
}
// 用户管理API仅yanlongqi用户可访问
userAdmin := api.Group("", middleware.Auth(), middleware.AdminOnly())
{
userAdmin.GET("/admin/users", handlers.GetAllUsersWithStats) // 获取所有用户及统计
userAdmin.GET("/admin/users/:id", handlers.GetUserDetailStats) // 获取用户详细统计
}
}
// 静态文件服务(必须在 API 路由之后)
// 提供静态资源CSS、JS、图片等
r.Static("/assets", "./web/static")
// SPA 支持:所有非 API 路由都返回 index.html让前端路由处理
r.NoRoute(func(c *gin.Context) {
c.File("./web/index.html")
})
// 启动服务器
port := ":8080"
if err := r.Run(port); err != nil {
panic("服务器启动失败: " + err.Error())
}
}