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), }) }