package handler import ( "net/http" "strconv" "github.com/gin-gonic/gin" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/services" "github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/models" ) type SpeakingHandler struct { speakingService *services.SpeakingService } func NewSpeakingHandler(speakingService *services.SpeakingService) *SpeakingHandler { return &SpeakingHandler{speakingService: speakingService} } // GetSpeakingScenarios 获取口语场景列表 func (h *SpeakingHandler) GetSpeakingScenarios(c *gin.Context) { level := c.Query("level") category := c.Query("category") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10")) scenarios, total, err := h.speakingService.GetSpeakingScenarios(level, category, page, pageSize) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"scenarios": scenarios, "total": total}) } // GetSpeakingScenario 获取单个口语场景 func (h *SpeakingHandler) GetSpeakingScenario(c *gin.Context) { id := c.Param("id") scenario, err := h.speakingService.GetSpeakingScenario(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Speaking scenario not found"}) return } c.JSON(http.StatusOK, gin.H{"scenario": scenario}) } // CreateSpeakingScenario 创建口语场景 func (h *SpeakingHandler) CreateSpeakingScenario(c *gin.Context) { var scenario models.SpeakingScenario if err := c.ShouldBindJSON(&scenario); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.speakingService.CreateSpeakingScenario(&scenario); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"scenario": scenario}) } // UpdateSpeakingScenario 更新口语场景 func (h *SpeakingHandler) UpdateSpeakingScenario(c *gin.Context) { id := c.Param("id") var updates models.SpeakingScenario if err := c.ShouldBindJSON(&updates); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.speakingService.UpdateSpeakingScenario(id, &updates); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } scenario, err := h.speakingService.GetSpeakingScenario(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"scenario": scenario}) } // DeleteSpeakingScenario 删除口语场景 func (h *SpeakingHandler) DeleteSpeakingScenario(c *gin.Context) { id := c.Param("id") if err := h.speakingService.DeleteSpeakingScenario(id); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Speaking scenario deleted successfully"}) } // SearchSpeakingScenarios 搜索口语场景 func (h *SpeakingHandler) SearchSpeakingScenarios(c *gin.Context) { keyword := c.Query("keyword") level := c.Query("level") category := c.Query("category") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10")) scenarios, total, err := h.speakingService.SearchSpeakingScenarios(keyword, level, category, page, pageSize) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"scenarios": scenarios, "total": total}) } // GetRecommendedScenarios 获取推荐口语场景 func (h *SpeakingHandler) GetRecommendedScenarios(c *gin.Context) { userID := c.GetString("user_id") limit, _ := strconv.Atoi(c.DefaultQuery("limit", "5")) scenarios, err := h.speakingService.GetRecommendedScenarios(userID, limit) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"scenarios": scenarios}) } // CreateSpeakingRecord 创建口语记录 func (h *SpeakingHandler) CreateSpeakingRecord(c *gin.Context) { var record models.SpeakingRecord if err := c.ShouldBindJSON(&record); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } record.UserID = c.GetString("user_id") if err := h.speakingService.CreateSpeakingRecord(&record); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, gin.H{"record": record}) } // UpdateSpeakingRecord 更新口语记录 func (h *SpeakingHandler) UpdateSpeakingRecord(c *gin.Context) { id := c.Param("id") var updates models.SpeakingRecord if err := c.ShouldBindJSON(&updates); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.speakingService.UpdateSpeakingRecord(id, &updates); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } record, err := h.speakingService.GetSpeakingRecord(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"record": record}) } // GetSpeakingRecord 获取口语记录详情 func (h *SpeakingHandler) GetSpeakingRecord(c *gin.Context) { id := c.Param("id") record, err := h.speakingService.GetSpeakingRecord(id) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Speaking record not found"}) return } c.JSON(http.StatusOK, gin.H{"record": record}) } // GetUserSpeakingRecords 获取用户口语记录列表 func (h *SpeakingHandler) GetUserSpeakingRecords(c *gin.Context) { userID := c.GetString("user_id") page, _ := strconv.Atoi(c.DefaultQuery("page", "1")) pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10")) records, total, err := h.speakingService.GetUserSpeakingRecords(userID, page, pageSize) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{ "records": records, "total": total, }) } // SubmitSpeaking 提交口语练习 func (h *SpeakingHandler) SubmitSpeaking(c *gin.Context) { id := c.Param("id") var req struct { AudioURL string `json:"audio_url"` Transcript string `json:"transcript"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.speakingService.SubmitSpeaking(id, req.AudioURL, req.Transcript); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Speaking submitted successfully"}) } // GradeSpeaking AI评分口语练习 func (h *SpeakingHandler) GradeSpeaking(c *gin.Context) { id := c.Param("id") var req struct { Pronunciation float64 `json:"pronunciation"` Fluency float64 `json:"fluency"` Accuracy float64 `json:"accuracy"` Score float64 `json:"score"` Feedback string `json:"feedback"` Suggestions string `json:"suggestions"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if err := h.speakingService.GradeSpeaking(id, req.Pronunciation, req.Fluency, req.Accuracy, req.Score, req.Feedback, req.Suggestions); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Speaking graded successfully"}) } // GetUserSpeakingStats 获取用户口语统计 func (h *SpeakingHandler) GetUserSpeakingStats(c *gin.Context) { userID := c.GetString("user_id") stats, err := h.speakingService.GetUserSpeakingStats(userID) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"stats": stats}) } // GetSpeakingProgress 获取口语进度 func (h *SpeakingHandler) GetSpeakingProgress(c *gin.Context) { userID := c.GetString("user_id") scenarioID := c.Param("scenario_id") progress, err := h.speakingService.GetSpeakingProgress(userID, scenarioID) if err != nil { c.JSON(http.StatusNotFound, gin.H{"error": "Speaking progress not found"}) return } c.JSON(http.StatusOK, gin.H{"progress": progress}) }