533 lines
17 KiB
Go
533 lines
17 KiB
Go
|
|
package handler
|
||
|
|
|
||
|
|
import (
|
||
|
|
"log"
|
||
|
|
"net/http"
|
||
|
|
"strconv"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"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"
|
||
|
|
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/common"
|
||
|
|
)
|
||
|
|
|
||
|
|
type VocabularyHandler struct {
|
||
|
|
vocabularyService *services.VocabularyService
|
||
|
|
}
|
||
|
|
|
||
|
|
func NewVocabularyHandler(vocabularyService *services.VocabularyService) *VocabularyHandler {
|
||
|
|
return &VocabularyHandler{vocabularyService: vocabularyService}
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetCategories 获取词汇分类列表
|
||
|
|
func (h *VocabularyHandler) GetCategories(c *gin.Context) {
|
||
|
|
level := c.Query("level")
|
||
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||
|
|
|
||
|
|
categories, err := h.vocabularyService.GetCategories(page, pageSize, level)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"categories": categories})
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateCategory 创建词汇分类
|
||
|
|
func (h *VocabularyHandler) CreateCategory(c *gin.Context) {
|
||
|
|
var category models.VocabularyCategory
|
||
|
|
if err := c.ShouldBindJSON(&category); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 将模型转换为服务所需参数
|
||
|
|
desc := ""
|
||
|
|
if category.Description != nil {
|
||
|
|
desc = *category.Description
|
||
|
|
}
|
||
|
|
|
||
|
|
createdCategory, err := h.vocabularyService.CreateCategory(category.Name, desc, category.Level)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusCreated, gin.H{"category": createdCategory})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabulariesByCategory 根据分类获取词汇列表
|
||
|
|
func (h *VocabularyHandler) GetVocabulariesByCategory(c *gin.Context) {
|
||
|
|
categoryID := c.Param("id")
|
||
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||
|
|
level := c.Query("level")
|
||
|
|
|
||
|
|
vocabularies, err := h.vocabularyService.GetVocabulariesByCategory(categoryID, page, pageSize, level)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"vocabularies": vocabularies})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabularyByID 获取词汇详情
|
||
|
|
func (h *VocabularyHandler) GetVocabularyByID(c *gin.Context) {
|
||
|
|
vocabularyID := c.Param("id")
|
||
|
|
|
||
|
|
vocabulary, err := h.vocabularyService.GetVocabularyByID(vocabularyID)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"vocabulary": vocabulary})
|
||
|
|
}
|
||
|
|
|
||
|
|
// SearchVocabularies 搜索词汇
|
||
|
|
func (h *VocabularyHandler) SearchVocabularies(c *gin.Context) {
|
||
|
|
keyword := c.Query("keyword")
|
||
|
|
level := c.Query("level")
|
||
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
|
|
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||
|
|
|
||
|
|
vocabularies, err := h.vocabularyService.SearchVocabularies(keyword, level, page, pageSize)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"vocabularies": vocabularies})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetUserVocabularyProgress 获取用户词汇学习进度
|
||
|
|
func (h *VocabularyHandler) GetUserVocabularyProgress(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
vocabularyID := c.Param("id")
|
||
|
|
|
||
|
|
progress, err := h.vocabularyService.GetUserVocabularyProgress(userID, vocabularyID)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"progress": progress})
|
||
|
|
}
|
||
|
|
|
||
|
|
// UpdateUserVocabularyProgress 更新用户词汇学习进度
|
||
|
|
func (h *VocabularyHandler) UpdateUserVocabularyProgress(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
vocabularyID := c.Param("id")
|
||
|
|
|
||
|
|
var updates map[string]interface{}
|
||
|
|
if err := c.ShouldBindJSON(&updates); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
progress, err := h.vocabularyService.UpdateUserVocabularyProgress(userID, vocabularyID, updates)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"progress": progress})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetUserVocabularyStats 获取用户词汇学习统计
|
||
|
|
func (h *VocabularyHandler) GetUserVocabularyStats(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
|
||
|
|
stats, err := h.vocabularyService.GetUserVocabularyStats(userID)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"stats": stats})
|
||
|
|
}
|
||
|
|
|
||
|
|
// UpdateCategory 更新词汇分类
|
||
|
|
func (h *VocabularyHandler) UpdateCategory(c *gin.Context) {
|
||
|
|
categoryID := c.Param("id")
|
||
|
|
if categoryID == "" {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "分类ID不能为空"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var updates map[string]interface{}
|
||
|
|
if err := c.ShouldBindJSON(&updates); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
category, err := h.vocabularyService.UpdateCategory(categoryID, updates)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"category": category})
|
||
|
|
}
|
||
|
|
|
||
|
|
// DeleteCategory 删除词汇分类
|
||
|
|
func (h *VocabularyHandler) DeleteCategory(c *gin.Context) {
|
||
|
|
categoryID := c.Param("id")
|
||
|
|
if categoryID == "" {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "分类ID不能为空"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := h.vocabularyService.DeleteCategory(categoryID); err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"message": "分类已删除"})
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateVocabulary 创建词汇
|
||
|
|
func (h *VocabularyHandler) CreateVocabulary(c *gin.Context) {
|
||
|
|
type reqBody struct {
|
||
|
|
Word string `json:"word"`
|
||
|
|
Phonetic string `json:"phonetic"`
|
||
|
|
Level string `json:"level"`
|
||
|
|
Frequency int `json:"frequency"`
|
||
|
|
CategoryID string `json:"category_id"`
|
||
|
|
Definitions []string `json:"definitions"`
|
||
|
|
Examples []string `json:"examples"`
|
||
|
|
Images []string `json:"images"`
|
||
|
|
}
|
||
|
|
|
||
|
|
var req reqBody
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
vocab, err := h.vocabularyService.CreateVocabulary(
|
||
|
|
req.Word, req.Phonetic, req.Level, req.Frequency, req.CategoryID,
|
||
|
|
req.Definitions, req.Examples, req.Images,
|
||
|
|
)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusCreated, gin.H{"vocabulary": vocab})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetDailyVocabularyStats 获取每日学习单词统计
|
||
|
|
func (h *VocabularyHandler) GetDailyVocabularyStats(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
userIDStr := strconv.FormatInt(userID, 10)
|
||
|
|
|
||
|
|
stats, err := h.vocabularyService.GetDailyStats(userIDStr)
|
||
|
|
if err != nil {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"stats": stats})
|
||
|
|
}
|
||
|
|
|
||
|
|
// CreateVocabularyTest 创建词汇测试
|
||
|
|
func (h *VocabularyHandler) CreateVocabularyTest(c *gin.Context) {
|
||
|
|
type reqBody struct {
|
||
|
|
TestType string `json:"test_type"`
|
||
|
|
Level string `json:"level"`
|
||
|
|
TotalWords int `json:"total_words"`
|
||
|
|
}
|
||
|
|
var req reqBody
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
|
||
|
|
test, err := h.vocabularyService.CreateVocabularyTest(userID, req.TestType, req.Level, req.TotalWords)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusCreated, gin.H{"test": test})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabularyTest 获取词汇测试
|
||
|
|
func (h *VocabularyHandler) GetVocabularyTest(c *gin.Context) {
|
||
|
|
testID := c.Param("id")
|
||
|
|
if testID == "" {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "测试ID不能为空"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
test, err := h.vocabularyService.GetVocabularyTest(testID)
|
||
|
|
if err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"test": test})
|
||
|
|
}
|
||
|
|
|
||
|
|
// UpdateVocabularyTestResult 更新词汇测试结果
|
||
|
|
func (h *VocabularyHandler) UpdateVocabularyTestResult(c *gin.Context) {
|
||
|
|
testID := c.Param("id")
|
||
|
|
if testID == "" {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": "测试ID不能为空"})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
type reqBody struct {
|
||
|
|
CorrectWords int `json:"correct_words"`
|
||
|
|
Score float64 `json:"score"`
|
||
|
|
Duration int `json:"duration"`
|
||
|
|
}
|
||
|
|
var req reqBody
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := h.vocabularyService.UpdateVocabularyTestResult(testID, req.CorrectWords, req.Score, req.Duration); err != nil {
|
||
|
|
if common.IsBusinessError(err) {
|
||
|
|
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
||
|
|
} else {
|
||
|
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||
|
|
}
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
c.JSON(http.StatusOK, gin.H{"message": "测试结果更新成功"})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetTodayStudyWords 获取今日学习单词
|
||
|
|
func (h *VocabularyHandler) GetTodayStudyWords(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||
|
|
|
||
|
|
words, err := h.vocabularyService.GetTodayStudyWords(userID, limit)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取今日单词失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 确保返回空数组而不是null
|
||
|
|
if words == nil {
|
||
|
|
words = []map[string]interface{}{}
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, gin.H{"words": words})
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetStudyStatistics 获取学习统计
|
||
|
|
func (h *VocabularyHandler) GetStudyStatistics(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
date := c.Query("date")
|
||
|
|
|
||
|
|
stats, err := h.vocabularyService.GetStudyStatistics(userID, date)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取学习统计失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, stats)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetStudyStatisticsHistory 获取学习统计历史
|
||
|
|
func (h *VocabularyHandler) GetStudyStatisticsHistory(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
startDate := c.Query("startDate")
|
||
|
|
endDate := c.Query("endDate")
|
||
|
|
|
||
|
|
history, err := h.vocabularyService.GetStudyStatisticsHistory(userID, startDate, endDate)
|
||
|
|
if err != nil {
|
||
|
|
log.Printf("[ERROR] GetStudyStatisticsHistory failed: userID=%d, startDate=%s, endDate=%s, error=%v", userID, startDate, endDate, err)
|
||
|
|
common.ErrorResponse(c, 500, "获取学习历史失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, history)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetSystemVocabularyBooks 获取系统词汇书列表
|
||
|
|
func (h *VocabularyHandler) GetSystemVocabularyBooks(c *gin.Context) {
|
||
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
|
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||
|
|
category := c.Query("category")
|
||
|
|
|
||
|
|
books, total, err := h.vocabularyService.GetSystemVocabularyBooks(page, limit, category)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取系统词汇书失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
totalPages := (int(total) + limit - 1) / limit
|
||
|
|
pagination := &common.Pagination{
|
||
|
|
Page: page,
|
||
|
|
PageSize: limit,
|
||
|
|
Total: int(total),
|
||
|
|
TotalPages: totalPages,
|
||
|
|
}
|
||
|
|
common.PaginationSuccessResponse(c, books, pagination)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabularyBookCategories 获取词汇书分类列表
|
||
|
|
func (h *VocabularyHandler) GetVocabularyBookCategories(c *gin.Context) {
|
||
|
|
categories, err := h.vocabularyService.GetVocabularyBookCategories()
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取词汇书分类失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, categories)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabularyBookProgress 获取词汇书学习进度
|
||
|
|
func (h *VocabularyHandler) GetVocabularyBookProgress(c *gin.Context) {
|
||
|
|
bookID := c.Param("id")
|
||
|
|
if bookID == "" {
|
||
|
|
common.ErrorResponse(c, 400, "词汇书ID不能为空")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
|
||
|
|
progress, err := h.vocabularyService.GetVocabularyBookProgress(userID, bookID)
|
||
|
|
if err != nil {
|
||
|
|
// 如果没有进度记录,返回默认进度
|
||
|
|
now := time.Now()
|
||
|
|
defaultProgress := &models.UserVocabularyBookProgress{
|
||
|
|
ID: 0,
|
||
|
|
UserID: userID,
|
||
|
|
BookID: bookID,
|
||
|
|
LearnedWords: 0,
|
||
|
|
MasteredWords: 0,
|
||
|
|
ProgressPercentage: 0.0,
|
||
|
|
StreakDays: 0,
|
||
|
|
TotalStudyDays: 0,
|
||
|
|
AverageDailyWords: 0.0,
|
||
|
|
EstimatedCompletionDate: nil,
|
||
|
|
IsCompleted: false,
|
||
|
|
CompletedAt: nil,
|
||
|
|
StartedAt: now,
|
||
|
|
LastStudiedAt: now,
|
||
|
|
}
|
||
|
|
common.SuccessResponse(c, defaultProgress)
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, progress)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetVocabularyBookWords 获取词汇书单词列表
|
||
|
|
func (h *VocabularyHandler) GetVocabularyBookWords(c *gin.Context) {
|
||
|
|
bookID := c.Param("id")
|
||
|
|
if bookID == "" {
|
||
|
|
common.ErrorResponse(c, 400, "词汇书ID不能为空")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||
|
|
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "100"))
|
||
|
|
|
||
|
|
words, total, err := h.vocabularyService.GetVocabularyBookWords(bookID, page, limit)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取词汇书单词失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
totalPages := (int(total) + limit - 1) / limit
|
||
|
|
pagination := &common.Pagination{
|
||
|
|
Page: page,
|
||
|
|
PageSize: limit,
|
||
|
|
Total: int(total),
|
||
|
|
TotalPages: totalPages,
|
||
|
|
}
|
||
|
|
common.PaginationSuccessResponse(c, words, pagination)
|
||
|
|
}
|
||
|
|
|
||
|
|
// GetUserWordProgress 获取用户单词学习进度
|
||
|
|
func (h *VocabularyHandler) GetUserWordProgress(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
wordIDStr := c.Param("id")
|
||
|
|
|
||
|
|
wordID, err := strconv.ParseInt(wordIDStr, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 400, "无效的单词ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 查询用户单词进度
|
||
|
|
progress, err := h.vocabularyService.GetUserWordProgress(userID, wordID)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "获取单词进度失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, progress)
|
||
|
|
}
|
||
|
|
|
||
|
|
// UpdateUserWordProgress 更新用户单词学习进度
|
||
|
|
func (h *VocabularyHandler) UpdateUserWordProgress(c *gin.Context) {
|
||
|
|
userID := c.GetInt64("user_id")
|
||
|
|
wordIDStr := c.Param("id")
|
||
|
|
|
||
|
|
wordID, err := strconv.ParseInt(wordIDStr, 10, 64)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 400, "无效的单词ID")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
var req struct {
|
||
|
|
Status string `json:"status"`
|
||
|
|
IsCorrect *bool `json:"isCorrect"`
|
||
|
|
}
|
||
|
|
|
||
|
|
if err := c.ShouldBindJSON(&req); err != nil {
|
||
|
|
common.ErrorResponse(c, 400, "无效的请求参数")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
// 更新单词进度
|
||
|
|
progress, err := h.vocabularyService.UpdateUserWordProgress(userID, wordID, req.Status, req.IsCorrect)
|
||
|
|
if err != nil {
|
||
|
|
common.ErrorResponse(c, 500, "更新单词进度失败")
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
common.SuccessResponse(c, progress)
|
||
|
|
}
|