init
This commit is contained in:
639
serve/api/handlers/reading_handler.go
Normal file
639
serve/api/handlers/reading_handler.go
Normal file
@@ -0,0 +1,639 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"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"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ReadingHandler 阅读理解处理器
|
||||
type ReadingHandler struct {
|
||||
readingService *services.ReadingService
|
||||
}
|
||||
|
||||
// NewReadingHandler 创建阅读理解处理器实例
|
||||
func NewReadingHandler(readingService *services.ReadingService) *ReadingHandler {
|
||||
return &ReadingHandler{
|
||||
readingService: readingService,
|
||||
}
|
||||
}
|
||||
|
||||
// ===== 请求结构体定义 =====
|
||||
|
||||
// CreateReadingMaterialRequest 创建阅读材料请求
|
||||
type CreateReadingMaterialRequest struct {
|
||||
Title string `json:"title" binding:"required"`
|
||||
Content string `json:"content" binding:"required"`
|
||||
Summary string `json:"summary"`
|
||||
Level string `json:"level" binding:"required,oneof=beginner intermediate advanced"`
|
||||
Category string `json:"category" binding:"required"`
|
||||
WordCount int `json:"word_count"`
|
||||
Tags string `json:"tags"`
|
||||
Source string `json:"source"`
|
||||
Author string `json:"author"`
|
||||
}
|
||||
|
||||
// UpdateReadingMaterialRequest 更新阅读材料请求
|
||||
type UpdateReadingMaterialRequest struct {
|
||||
Title *string `json:"title"`
|
||||
Content *string `json:"content"`
|
||||
Summary *string `json:"summary"`
|
||||
Level *string `json:"level"`
|
||||
Category *string `json:"category"`
|
||||
WordCount *int `json:"word_count"`
|
||||
Tags *string `json:"tags"`
|
||||
Source *string `json:"source"`
|
||||
Author *string `json:"author"`
|
||||
}
|
||||
|
||||
// CreateReadingRecordRequest 创建阅读记录请求
|
||||
type CreateReadingRecordRequest struct {
|
||||
MaterialID string `json:"material_id" binding:"required"`
|
||||
}
|
||||
|
||||
// UpdateReadingRecordRequest 更新阅读记录请求
|
||||
type UpdateReadingRecordRequest struct {
|
||||
ReadingTime *int `json:"reading_time"`
|
||||
ComprehensionScore *float64 `json:"comprehension_score"`
|
||||
ReadingSpeed *float64 `json:"reading_speed"`
|
||||
Notes *string `json:"notes"`
|
||||
CompletedAt *time.Time `json:"completed_at"`
|
||||
}
|
||||
|
||||
// ===== 阅读材料管理接口 =====
|
||||
|
||||
// GetReadingMaterials 获取阅读材料列表
|
||||
// @Summary 获取阅读材料列表
|
||||
// @Description 获取阅读材料列表,支持按难度级别和分类筛选
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param level query string false "难度级别"
|
||||
// @Param category query string false "分类"
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(10)
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/materials [get]
|
||||
func (h *ReadingHandler) GetReadingMaterials(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"))
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
materials, total, err := h.readingService.GetReadingMaterials(level, category, page, pageSize)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "获取阅读材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": materials,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetReadingMaterial 获取单个阅读材料
|
||||
// @Summary 获取单个阅读材料
|
||||
// @Description 根据ID获取阅读材料详情
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "材料ID"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/materials/{id} [get]
|
||||
func (h *ReadingHandler) GetReadingMaterial(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "材料ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
material, err := h.readingService.GetReadingMaterial(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "阅读材料不存在",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": material})
|
||||
}
|
||||
|
||||
// CreateReadingMaterial 创建阅读材料
|
||||
// @Summary 创建阅读材料
|
||||
// @Description 创建新的阅读材料
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body CreateReadingMaterialRequest true "创建请求"
|
||||
// @Success 201 {object} Response
|
||||
// @Router /reading/materials [post]
|
||||
func (h *ReadingHandler) CreateReadingMaterial(c *gin.Context) {
|
||||
var req CreateReadingMaterialRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "请求参数错误",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
material := &models.ReadingMaterial{
|
||||
Title: req.Title,
|
||||
Content: req.Content,
|
||||
Summary: &req.Summary,
|
||||
WordCount: req.WordCount,
|
||||
Level: req.Level,
|
||||
Category: req.Category,
|
||||
Tags: &req.Tags,
|
||||
Source: &req.Source,
|
||||
Author: &req.Author,
|
||||
IsActive: true,
|
||||
}
|
||||
|
||||
if err := h.readingService.CreateReadingMaterial(material); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "创建阅读材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"message": "阅读材料创建成功",
|
||||
"data": material,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateReadingMaterial 更新阅读材料
|
||||
// @Summary 更新阅读材料
|
||||
// @Description 更新阅读材料信息
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "材料ID"
|
||||
// @Param request body UpdateReadingMaterialRequest true "更新请求"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/materials/{id} [put]
|
||||
func (h *ReadingHandler) UpdateReadingMaterial(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "材料ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateReadingMaterialRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "请求参数错误",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
updates := make(map[string]interface{})
|
||||
if req.Title != nil {
|
||||
updates["title"] = *req.Title
|
||||
}
|
||||
if req.Content != nil {
|
||||
updates["content"] = *req.Content
|
||||
}
|
||||
if req.Summary != nil {
|
||||
updates["summary"] = *req.Summary
|
||||
}
|
||||
if req.Level != nil {
|
||||
updates["level"] = *req.Level
|
||||
}
|
||||
if req.Category != nil {
|
||||
updates["category"] = *req.Category
|
||||
}
|
||||
if req.WordCount != nil {
|
||||
updates["word_count"] = *req.WordCount
|
||||
}
|
||||
if req.Tags != nil {
|
||||
updates["tags"] = *req.Tags
|
||||
}
|
||||
if req.Source != nil {
|
||||
updates["source"] = *req.Source
|
||||
}
|
||||
if req.Author != nil {
|
||||
updates["author"] = *req.Author
|
||||
}
|
||||
|
||||
if len(updates) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "没有提供更新字段"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.readingService.UpdateReadingMaterial(id, updates); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "更新阅读材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "阅读材料更新成功"})
|
||||
}
|
||||
|
||||
// DeleteReadingMaterial 删除阅读材料
|
||||
// @Summary 删除阅读材料
|
||||
// @Description 软删除阅读材料
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "材料ID"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/materials/{id} [delete]
|
||||
func (h *ReadingHandler) DeleteReadingMaterial(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "材料ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.readingService.DeleteReadingMaterial(id); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "删除阅读材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "阅读材料删除成功"})
|
||||
}
|
||||
|
||||
// SearchReadingMaterials 搜索阅读材料
|
||||
// @Summary 搜索阅读材料
|
||||
// @Description 根据关键词搜索阅读材料
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param keyword query string true "搜索关键词"
|
||||
// @Param level query string false "难度级别"
|
||||
// @Param category query string false "分类"
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(10)
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/materials/search [get]
|
||||
func (h *ReadingHandler) SearchReadingMaterials(c *gin.Context) {
|
||||
keyword := c.Query("keyword")
|
||||
if keyword == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "搜索关键词不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
level := c.Query("level")
|
||||
category := c.Query("category")
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
materials, total, err := h.readingService.SearchReadingMaterials(keyword, level, category, page, pageSize)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "搜索阅读材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": materials,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// ===== 阅读记录管理接口 =====
|
||||
|
||||
// CreateReadingRecord 创建阅读记录
|
||||
// @Summary 创建阅读记录
|
||||
// @Description 开始阅读材料,创建阅读记录
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param request body CreateReadingRecordRequest true "创建请求"
|
||||
// @Success 201 {object} Response
|
||||
// @Router /reading/records [post]
|
||||
func (h *ReadingHandler) CreateReadingRecord(c *gin.Context) {
|
||||
userID, ok := utils.GetUserIDFromContext(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
var req CreateReadingRecordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "请求参数错误",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// 检查是否已有该材料的阅读记录
|
||||
existingRecord, err := h.readingService.GetReadingProgress(utils.Int64ToString(userID), req.MaterialID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "检查阅读记录失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if existingRecord != nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"message": "阅读记录已存在",
|
||||
"data": existingRecord,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
record := &models.ReadingRecord{
|
||||
UserID: utils.Int64ToString(userID),
|
||||
MaterialID: req.MaterialID,
|
||||
}
|
||||
|
||||
if err := h.readingService.CreateReadingRecord(record); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "创建阅读记录失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"message": "阅读记录创建成功",
|
||||
"data": record,
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateReadingRecord 更新阅读记录
|
||||
// @Summary 更新阅读记录
|
||||
// @Description 更新阅读进度和成绩
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "记录ID"
|
||||
// @Param request body UpdateReadingRecordRequest true "更新请求"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/records/{id} [put]
|
||||
func (h *ReadingHandler) UpdateReadingRecord(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "记录ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
var req UpdateReadingRecordRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
c.JSON(http.StatusBadRequest, gin.H{
|
||||
"error": "请求参数错误",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
updates := make(map[string]interface{})
|
||||
if req.ReadingTime != nil {
|
||||
updates["reading_time"] = *req.ReadingTime
|
||||
}
|
||||
if req.ComprehensionScore != nil {
|
||||
updates["comprehension_score"] = *req.ComprehensionScore
|
||||
}
|
||||
if req.ReadingSpeed != nil {
|
||||
updates["reading_speed"] = *req.ReadingSpeed
|
||||
}
|
||||
if req.Notes != nil {
|
||||
updates["notes"] = *req.Notes
|
||||
}
|
||||
if req.CompletedAt != nil {
|
||||
updates["completed_at"] = *req.CompletedAt
|
||||
}
|
||||
|
||||
if len(updates) == 0 {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "没有提供更新字段"})
|
||||
return
|
||||
}
|
||||
|
||||
if err := h.readingService.UpdateReadingRecord(id, updates); err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "更新阅读记录失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"message": "阅读记录更新成功"})
|
||||
}
|
||||
|
||||
// GetUserReadingRecords 获取用户阅读记录
|
||||
// @Summary 获取用户阅读记录
|
||||
// @Description 获取当前用户的阅读记录列表
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param page query int false "页码" default(1)
|
||||
// @Param page_size query int false "每页数量" default(10)
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/records [get]
|
||||
func (h *ReadingHandler) GetUserReadingRecords(c *gin.Context) {
|
||||
userID, ok := utils.GetUserIDFromContext(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))
|
||||
|
||||
if page < 1 {
|
||||
page = 1
|
||||
}
|
||||
if pageSize < 1 || pageSize > 100 {
|
||||
pageSize = 10
|
||||
}
|
||||
|
||||
records, total, err := h.readingService.GetUserReadingRecords(utils.Int64ToString(userID), page, pageSize)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "获取阅读记录失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": records,
|
||||
"pagination": gin.H{
|
||||
"page": page,
|
||||
"page_size": pageSize,
|
||||
"total": total,
|
||||
"total_pages": (total + int64(pageSize) - 1) / int64(pageSize),
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// GetReadingRecord 获取单个阅读记录
|
||||
// @Summary 获取单个阅读记录
|
||||
// @Description 根据ID获取阅读记录详情
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param id path string true "记录ID"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/records/{id} [get]
|
||||
func (h *ReadingHandler) GetReadingRecord(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
if id == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "记录ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
record, err := h.readingService.GetReadingRecord(id)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusNotFound, gin.H{
|
||||
"error": "阅读记录不存在",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": record})
|
||||
}
|
||||
|
||||
// GetReadingProgress 获取阅读进度
|
||||
// @Summary 获取阅读进度
|
||||
// @Description 获取用户对特定材料的阅读进度
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param material_id path string true "材料ID"
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/progress/{material_id} [get]
|
||||
func (h *ReadingHandler) GetReadingProgress(c *gin.Context) {
|
||||
userID, ok := utils.GetUserIDFromContext(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
materialID := c.Param("material_id")
|
||||
if materialID == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"error": "材料ID不能为空"})
|
||||
return
|
||||
}
|
||||
|
||||
record, err := h.readingService.GetReadingProgress(utils.Int64ToString(userID), materialID)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "获取阅读进度失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if record == nil {
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"data": nil,
|
||||
"message": "暂无阅读记录",
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": record})
|
||||
}
|
||||
|
||||
// ===== 阅读统计接口 =====
|
||||
|
||||
// GetReadingStats 获取阅读统计
|
||||
// @Summary 获取阅读统计
|
||||
// @Description 获取用户阅读统计信息
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/stats [get]
|
||||
func (h *ReadingHandler) GetReadingStats(c *gin.Context) {
|
||||
userID, ok := utils.GetUserIDFromContext(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
stats, err := h.readingService.GetUserReadingStats(utils.Int64ToString(userID))
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "获取阅读统计失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": stats})
|
||||
}
|
||||
|
||||
// GetRecommendedMaterials 获取推荐阅读材料
|
||||
// @Summary 获取推荐阅读材料
|
||||
// @Description 根据用户阅读历史推荐合适的阅读材料
|
||||
// @Tags 阅读理解
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
// @Param limit query int false "推荐数量" default(5)
|
||||
// @Success 200 {object} Response
|
||||
// @Router /reading/recommendations [get]
|
||||
func (h *ReadingHandler) GetRecommendedMaterials(c *gin.Context) {
|
||||
userID, ok := utils.GetUserIDFromContext(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, gin.H{"error": "用户未认证"})
|
||||
return
|
||||
}
|
||||
|
||||
limit, _ := strconv.Atoi(c.DefaultQuery("limit", "5"))
|
||||
if limit < 1 || limit > 20 {
|
||||
limit = 5
|
||||
}
|
||||
|
||||
materials, err := h.readingService.GetRecommendedMaterials(utils.Int64ToString(userID), limit)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{
|
||||
"error": "获取推荐材料失败",
|
||||
"details": err.Error(),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{"data": materials})
|
||||
}
|
||||
Reference in New Issue
Block a user