This commit is contained in:
sjk
2025-11-17 13:39:05 +08:00
commit d4cfe2b9de
479 changed files with 109324 additions and 0 deletions

View File

@@ -0,0 +1,276 @@
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})
}