Files
ai_english/serve/internal/handler/study_plan_handler.go
2025-11-17 14:09:17 +08:00

271 lines
7.0 KiB
Go

package handler
import (
"strconv"
"time"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/common"
"github.com/Nanqipro/YunQue-Tech-Projects/ai_english_learning/serve/internal/services"
"github.com/gin-gonic/gin"
)
// StudyPlanHandler 学习计划处理器
type StudyPlanHandler struct {
studyPlanService *services.StudyPlanService
}
func NewStudyPlanHandler(studyPlanService *services.StudyPlanService) *StudyPlanHandler {
return &StudyPlanHandler{studyPlanService: studyPlanService}
}
// CreateStudyPlan 创建学习计划
// POST /api/v1/study-plans
func (h *StudyPlanHandler) CreateStudyPlan(c *gin.Context) {
userID := c.GetInt64("user_id")
var req struct {
PlanName string `json:"plan_name" binding:"required,min=1,max=200"`
Description *string `json:"description"`
DailyGoal int `json:"daily_goal" binding:"required,min=1,max=200"`
BookID *string `json:"book_id"`
StartDate string `json:"start_date" binding:"required"` // YYYY-MM-DD
EndDate *string `json:"end_date"` // YYYY-MM-DD
RemindTime *string `json:"remind_time"` // HH:mm
RemindDays *string `json:"remind_days"` // "1,2,3,4,5" 表示周一到周五
}
if err := c.ShouldBindJSON(&req); err != nil {
common.ErrorResponse(c, 400, "参数错误: "+err.Error())
return
}
// 解析日期
startDate, err := time.Parse("2006-01-02", req.StartDate)
if err != nil {
common.ErrorResponse(c, 400, "开始日期格式错误")
return
}
var endDate *time.Time
if req.EndDate != nil {
parsedEndDate, err := time.Parse("2006-01-02", *req.EndDate)
if err != nil {
common.ErrorResponse(c, 400, "结束日期格式错误")
return
}
endDate = &parsedEndDate
}
plan, err := h.studyPlanService.CreateStudyPlan(
userID,
req.PlanName,
req.Description,
req.DailyGoal,
req.BookID,
startDate,
endDate,
req.RemindTime,
req.RemindDays,
)
if err != nil {
common.ErrorResponse(c, 500, "创建学习计划失败: "+err.Error())
return
}
common.SuccessResponse(c, plan)
}
// GetUserStudyPlans 获取用户的学习计划列表
// GET /api/v1/study-plans
func (h *StudyPlanHandler) GetUserStudyPlans(c *gin.Context) {
userID := c.GetInt64("user_id")
status := c.DefaultQuery("status", "all") // all, active, paused, completed, cancelled
plans, err := h.studyPlanService.GetUserStudyPlans(userID, status)
if err != nil {
common.ErrorResponse(c, 500, "获取学习计划失败: "+err.Error())
return
}
common.SuccessResponse(c, gin.H{
"plans": plans,
"total": len(plans),
})
}
// GetStudyPlanByID 获取学习计划详情
// GET /api/v1/study-plans/:id
func (h *StudyPlanHandler) GetStudyPlanByID(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
plan, err := h.studyPlanService.GetStudyPlanByID(planID, userID)
if err != nil {
common.ErrorResponse(c, 404, "学习计划不存在")
return
}
common.SuccessResponse(c, plan)
}
// UpdateStudyPlan 更新学习计划
// PUT /api/v1/study-plans/:id
func (h *StudyPlanHandler) UpdateStudyPlan(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
var updates map[string]interface{}
if err := c.ShouldBindJSON(&updates); err != nil {
common.ErrorResponse(c, 400, "参数错误: "+err.Error())
return
}
plan, err := h.studyPlanService.UpdateStudyPlan(planID, userID, updates)
if err != nil {
common.ErrorResponse(c, 500, "更新学习计划失败: "+err.Error())
return
}
common.SuccessResponse(c, plan)
}
// DeleteStudyPlan 删除学习计划
// DELETE /api/v1/study-plans/:id
func (h *StudyPlanHandler) DeleteStudyPlan(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
err = h.studyPlanService.DeleteStudyPlan(planID, userID)
if err != nil {
common.ErrorResponse(c, 500, "删除学习计划失败: "+err.Error())
return
}
common.SuccessResponse(c, gin.H{
"message": "学习计划已删除",
})
}
// UpdatePlanStatus 更新计划状态
// PATCH /api/v1/study-plans/:id/status
func (h *StudyPlanHandler) UpdatePlanStatus(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
var req struct {
Status string `json:"status" binding:"required,oneof=active paused completed cancelled"`
}
if err := c.ShouldBindJSON(&req); err != nil {
common.ErrorResponse(c, 400, "参数错误: "+err.Error())
return
}
err = h.studyPlanService.UpdatePlanStatus(planID, userID, req.Status)
if err != nil {
common.ErrorResponse(c, 500, "更新状态失败: "+err.Error())
return
}
common.SuccessResponse(c, gin.H{
"message": "状态更新成功",
"status": req.Status,
})
}
// RecordStudyProgress 记录学习进度
// POST /api/v1/study-plans/:id/progress
func (h *StudyPlanHandler) RecordStudyProgress(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
var req struct {
WordsStudied int `json:"words_studied" binding:"required,min=1"`
StudyDuration int `json:"study_duration"` // 学习时长(分钟)
}
if err := c.ShouldBindJSON(&req); err != nil {
common.ErrorResponse(c, 400, "参数错误: "+err.Error())
return
}
err = h.studyPlanService.RecordStudyProgress(planID, userID, req.WordsStudied, req.StudyDuration)
if err != nil {
common.ErrorResponse(c, 500, "记录进度失败: "+err.Error())
return
}
common.SuccessResponse(c, gin.H{
"message": "进度记录成功",
})
}
// GetStudyPlanStatistics 获取学习计划统计
// GET /api/v1/study-plans/:id/statistics
func (h *StudyPlanHandler) GetStudyPlanStatistics(c *gin.Context) {
userID := c.GetInt64("user_id")
planIDStr := c.Param("id")
planID, err := strconv.ParseInt(planIDStr, 10, 64)
if err != nil {
common.ErrorResponse(c, 400, "无效的计划ID")
return
}
stats, err := h.studyPlanService.GetStudyPlanStatistics(planID, userID)
if err != nil {
common.ErrorResponse(c, 500, "获取统计信息失败: "+err.Error())
return
}
common.SuccessResponse(c, stats)
}
// GetTodayStudyPlans 获取今日需要执行的学习计划
// GET /api/v1/study-plans/today
func (h *StudyPlanHandler) GetTodayStudyPlans(c *gin.Context) {
userID := c.GetInt64("user_id")
plans, err := h.studyPlanService.GetTodayStudyPlans(userID)
if err != nil {
common.ErrorResponse(c, 500, "获取今日计划失败: "+err.Error())
return
}
common.SuccessResponse(c, gin.H{
"plans": plans,
"total": len(plans),
})
}