实现了基于OpenAI的流式题目解析系统,支持答题后查看AI生成的详细解析。 主要功能: - 流式输出:采用SSE (Server-Sent Events) 实现实时流式输出,用户可看到解析逐字生成 - Markdown渲染:使用react-markdown渲染解析内容,支持标题、列表、代码块等格式 - 智能提示词:根据题目类型(选择题/填空题/判断题等)动态调整提示词 - 选择题优化:对选择题提供逐项分析和记忆口诀 - 重新生成:支持重新生成解析,temperature设为0确保输出一致性 - 优化加载:加载指示器显示在内容下方,不遮挡流式输出 技术实现: - 后端:新增ExplainQuestionStream方法支持流式响应 - 前端:使用ReadableStream API接收SSE流式数据 - UI:优化加载状态显示,避免阻塞内容展示 - 清理:删除不再使用的scripts脚本文件 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
83 lines
3.0 KiB
Go
83 lines
3.0 KiB
Go
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/questions", handlers.GetPracticeQuestions) // 获取练习题目列表
|
||
api.GET("/practice/questions/random", handlers.GetRandomPracticeQuestion) // 获取随机练习题目
|
||
api.GET("/practice/questions/:id", handlers.GetPracticeQuestionByID) // 获取指定练习题目
|
||
api.GET("/practice/types", handlers.GetPracticeQuestionTypes) // 获取题型列表
|
||
api.POST("/practice/explain", handlers.ExplainQuestion) // 生成题目解析(AI)
|
||
|
||
// 需要认证的路由
|
||
auth := api.Group("", middleware.Auth())
|
||
{
|
||
// 练习题提交(需要登录才能记录错题)
|
||
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/random", handlers.GetRandomWrongQuestion) // 获取随机错题
|
||
auth.DELETE("/wrong-questions/:id", handlers.DeleteWrongQuestion) // 删除单个错题
|
||
auth.PUT("/wrong-questions/:id/mastered", handlers.MarkWrongQuestionMastered) // 标记已掌握
|
||
auth.DELETE("/wrong-questions", handlers.ClearWrongQuestions) // 清空错题本
|
||
}
|
||
|
||
// 题库管理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 路由之后)
|
||
// 提供静态资源(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())
|
||
}
|
||
}
|