package handlers import ( "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/common" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/services" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/utils" ) // TestHandler 测试处理器 type TestHandler struct { testService *services.TestService } // NewTestHandler 创建测试处理器实例 func NewTestHandler(testService *services.TestService) *TestHandler { return &TestHandler{ testService: testService, } } // GetTestTemplates 获取测试模板列表 // @Summary 获取测试模板列表 // @Tags Test // @Param type query string false "测试类型" // @Param difficulty query string false "难度" // @Param page query int false "页码" // @Param page_size query int false "每页数量" // @Success 200 {object} common.Response // @Router /api/v1/tests/templates [get] func (h *TestHandler) GetTestTemplates(c *gin.Context) { typeStr := c.Query("type") difficultyStr := c.Query("difficulty") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20")) var testType *models.TestType if typeStr != "" { t := models.TestType(typeStr) testType = &t } var difficulty *models.TestDifficulty if difficultyStr != "" { d := models.TestDifficulty(difficultyStr) difficulty = &d } templates, total, err := h.testService.GetTestTemplates(testType, difficulty, page, pageSize) if err != nil { common.ErrorResponse(c, http.StatusInternalServerError, "获取测试模板失败") return } common.SuccessResponse(c, gin.H{ "templates": templates, "pagination": gin.H{ "page": page, "page_size": pageSize, "total": total, "total_page": (total + int64(pageSize) - 1) / int64(pageSize), }, }) } // GetTestTemplateByID 获取测试模板详情 // @Summary 获取测试模板详情 // @Tags Test // @Param id path string true "模板ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/templates/{id} [get] func (h *TestHandler) GetTestTemplateByID(c *gin.Context) { id := c.Param("id") template, err := h.testService.GetTestTemplateByID(id) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试模板不存在") return } common.SuccessResponse(c, gin.H{"data": template}) } // CreateTestSession 创建测试会话 // @Summary 创建测试会话 // @Tags Test // @Param body body object true "请求体" // @Success 201 {object} common.Response // @Router /api/v1/tests/sessions [post] func (h *TestHandler) CreateTestSession(c *gin.Context) { userID, exists := utils.GetUserIDFromContext(c) if !exists { common.BadRequestResponse(c, "请先登录") return } var req struct { TemplateID string `json:"template_id" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { common.BadRequestResponse(c, "请求参数错误") return } session, err := h.testService.CreateTestSession(req.TemplateID, utils.Int64ToString(userID)) if err != nil { common.ErrorResponse(c, http.StatusInternalServerError, "创建测试会话失败: "+err.Error()) return } common.SuccessResponseWithStatus(c, http.StatusCreated, gin.H{"data": session}) } // GetTestSession 获取测试会话 // @Summary 获取测试会话 // @Tags Test // @Param id path string true "会话ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id} [get] func (h *TestHandler) GetTestSession(c *gin.Context) { sessionID := c.Param("id") session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } // 验证用户权限 userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权访问此测试会话") return } common.SuccessResponse(c, gin.H{"data": session}) } // StartTest 开始测试 // @Summary 开始测试 // @Tags Test // @Param id path string true "会话ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id}/start [put] func (h *TestHandler) StartTest(c *gin.Context) { sessionID := c.Param("id") // 验证用户权限 session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权操作此测试会话") return } updatedSession, err := h.testService.StartTest(sessionID) if err != nil { common.ErrorResponse(c, http.StatusBadRequest, err.Error()) return } common.SuccessResponse(c, gin.H{"data": updatedSession}) } // SubmitAnswer 提交答案 // @Summary 提交答案 // @Tags Test // @Param id path string true "会话ID" // @Param body body object true "请求体" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id}/answers [post] func (h *TestHandler) SubmitAnswer(c *gin.Context) { sessionID := c.Param("id") var req struct { QuestionID string `json:"question_id" binding:"required"` Answer string `json:"answer" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { common.BadRequestResponse(c, "请求参数错误") return } // 验证用户权限 session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权操作此测试会话") return } updatedSession, err := h.testService.SubmitAnswer(sessionID, req.QuestionID, req.Answer) if err != nil { common.ErrorResponse(c, http.StatusBadRequest, err.Error()) return } common.SuccessResponse(c, gin.H{"data": updatedSession}) } // PauseTest 暂停测试 // @Summary 暂停测试 // @Tags Test // @Param id path string true "会话ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id}/pause [put] func (h *TestHandler) PauseTest(c *gin.Context) { sessionID := c.Param("id") // 验证用户权限 session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权操作此测试会话") return } updatedSession, err := h.testService.PauseTest(sessionID) if err != nil { common.ErrorResponse(c, http.StatusBadRequest, err.Error()) return } common.SuccessResponse(c, gin.H{"data": updatedSession}) } // ResumeTest 恢复测试 // @Summary 恢复测试 // @Tags Test // @Param id path string true "会话ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id}/resume [put] func (h *TestHandler) ResumeTest(c *gin.Context) { sessionID := c.Param("id") // 验证用户权限 session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权操作此测试会话") return } updatedSession, err := h.testService.ResumeTest(sessionID) if err != nil { common.ErrorResponse(c, http.StatusBadRequest, err.Error()) return } common.SuccessResponse(c, gin.H{"data": updatedSession}) } // CompleteTest 完成测试 // @Summary 完成测试 // @Tags Test // @Param id path string true "会话ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions/{id}/complete [put] func (h *TestHandler) CompleteTest(c *gin.Context) { sessionID := c.Param("id") // 验证用户权限 session, err := h.testService.GetTestSession(sessionID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试会话不存在") return } userID, _ := utils.GetUserIDFromContext(c) if session.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权操作此测试会话") return } result, err := h.testService.CompleteTest(sessionID) if err != nil { common.ErrorResponse(c, http.StatusBadRequest, err.Error()) return } common.SuccessResponse(c, gin.H{"data": result}) } // GetUserTestHistory 获取用户测试历史 // @Summary 获取用户测试历史 // @Tags Test // @Param page query int false "页码" // @Param page_size query int false "每页数量" // @Success 200 {object} common.Response // @Router /api/v1/tests/sessions [get] func (h *TestHandler) GetUserTestHistory(c *gin.Context) { userID, exists := utils.GetUserIDFromContext(c) if !exists { common.BadRequestResponse(c, "请先登录") return } page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10")) results, total, err := h.testService.GetUserTestHistory(utils.Int64ToString(userID), page, pageSize) if err != nil { common.ErrorResponse(c, http.StatusInternalServerError, "获取测试历史失败") return } common.SuccessResponse(c, gin.H{ "sessions": results, "pagination": gin.H{ "page": page, "page_size": pageSize, "total": total, "total_page": (total + int64(pageSize) - 1) / int64(pageSize), }, }) } // GetTestResultByID 获取测试结果详情 // @Summary 获取测试结果详情 // @Tags Test // @Param id path string true "结果ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/results/{id} [get] func (h *TestHandler) GetTestResultByID(c *gin.Context) { resultID := c.Param("id") result, err := h.testService.GetTestResultByID(resultID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试结果不存在") return } // 验证用户权限 userID, _ := utils.GetUserIDFromContext(c) if result.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权访问此测试结果") return } common.SuccessResponse(c, gin.H{"data": result}) } // GetUserTestStats 获取用户测试统计 // @Summary 获取用户测试统计 // @Tags Test // @Success 200 {object} common.Response // @Router /api/v1/tests/stats [get] func (h *TestHandler) GetUserTestStats(c *gin.Context) { userID, exists := utils.GetUserIDFromContext(c) if !exists { common.BadRequestResponse(c, "请先登录") return } stats, err := h.testService.GetUserTestStats(utils.Int64ToString(userID)) if err != nil { common.ErrorResponse(c, http.StatusInternalServerError, "获取测试统计失败") return } common.SuccessResponse(c, stats) } // DeleteTestResult 删除测试结果 // @Summary 删除测试结果 // @Tags Test // @Param id path string true "结果ID" // @Success 200 {object} common.Response // @Router /api/v1/tests/results/{id} [delete] func (h *TestHandler) DeleteTestResult(c *gin.Context) { resultID := c.Param("id") // 验证用户权限 result, err := h.testService.GetTestResultByID(resultID) if err != nil { common.ErrorResponse(c, http.StatusNotFound, "测试结果不存在") return } userID, _ := utils.GetUserIDFromContext(c) if result.UserID != utils.Int64ToString(userID) { common.ErrorResponse(c, http.StatusForbidden, "无权删除此测试结果") return } if err := h.testService.DeleteTestResult(resultID); err != nil { common.ErrorResponse(c, http.StatusInternalServerError, "删除测试结果失败") return } common.SuccessResponse(c, gin.H{"message": "删除成功"}) }