package handler import ( "errors" "strconv" "github.com/gin-gonic/gin" "github.com/sundynix/pets-be/internal/middleware" "github.com/sundynix/pets-be/internal/service" "github.com/sundynix/pets-be/pkg/response" ) // ListArticles GET /api/articles func (h *Handler) ListArticles(c *gin.Context) { articles, err := h.svc.ListArticles() if err != nil { response.FailErr(c, err) return } response.OK(c, articles) } // GetArticle GET /api/articles/:id func (h *Handler) GetArticle(c *gin.Context) { article, err := h.svc.GetArticle(idParam(c, "id")) if err != nil { respondErr(c, err) return } response.OK(c, article) } // GetPro GET /api/pro func (h *Handler) GetPro(c *gin.Context) { info, err := h.svc.GetPro(middleware.UserID(c)) if err != nil { response.FailErr(c, err) return } response.OK(c, info) } // ActivatePro POST /api/pro/activate func (h *Handler) ActivatePro(c *gin.Context) { info, err := h.svc.ActivatePro(middleware.UserID(c)) if err != nil { // 支付未接入不是服务器错误,按参数错返回,前端直接展示提示文案 if errors.Is(err, service.ErrPayNotReady) { response.FailParams(c, err.Error()) return } response.FailErr(c, err) return } response.OK(c, info) } type aiChatReq struct { PetID *string `json:"pet_id"` Session string `json:"session"` Text string `json:"text"` } // AIChat POST /api/ai/chat func (h *Handler) AIChat(c *gin.Context) { var req aiChatReq if err := c.ShouldBindJSON(&req); err != nil { response.FailParams(c, err.Error()) return } if req.Text == "" { response.FailParams(c, "问题不能为空") return } reply, err := h.svc.AIChat(middleware.UserID(c), req.PetID, req.Session, req.Text) if err != nil { if errors.Is(err, service.ErrAIQuotaExceeded) { response.Fail(c, 42900, err.Error()) return } response.FailErr(c, err) return } response.OK(c, gin.H{"reply": reply}) } // HomeSummary GET /api/pets/:id/home-summary func (h *Handler) HomeSummary(c *gin.Context) { res, err := h.svc.GetHomeSummary(middleware.UserID(c), idParam(c, "id")) if err != nil { respondErr(c, err) return } response.OK(c, res) } // UserSummary GET /api/user/summary func (h *Handler) UserSummary(c *gin.Context) { res, err := h.svc.GetUserSummary(middleware.UserID(c)) if err != nil { response.FailErr(c, err) return } response.OK(c, res) } type assessSymptomReq struct { Symptoms []string `json:"symptoms"` Duration string `json:"duration"` Spirit string `json:"spirit"` } // AssessSymptom POST /api/pets/:id/ai/assess-symptom func (h *Handler) AssessSymptom(c *gin.Context) { var req assessSymptomReq if err := c.ShouldBindJSON(&req); err != nil { response.FailParams(c, err.Error()) return } res, err := h.svc.AssessSymptom(middleware.UserID(c), idParam(c, "id"), service.SymptomInput{ Symptoms: req.Symptoms, Duration: req.Duration, Spirit: req.Spirit, }) if err != nil { respondErr(c, err) return } response.OK(c, res) } type feedbackReq struct { Content string `json:"content"` Contact string `json:"contact"` } // CreateFeedback POST /api/feedback func (h *Handler) CreateFeedback(c *gin.Context) { var req feedbackReq if err := c.ShouldBindJSON(&req); err != nil { response.FailParams(c, err.Error()) return } f, err := h.svc.CreateFeedback(middleware.UserID(c), req.Content, req.Contact) if err != nil { response.FailParams(c, err.Error()) return } response.OK(c, f) } // AdminListFeedback GET /api/admin/feedback func (h *Handler) AdminListFeedback(c *gin.Context) { var req adminListReq _ = c.ShouldBindQuery(&req) req.Normalize() list, total, err := h.svc.ListFeedbackAdmin(req.Offset(), req.Limit()) if err != nil { response.FailErr(c, err) return } response.OK(c, response.NewPage(list, total, req.PageQuery)) } type handledReq struct { Handled bool `json:"handled"` } // AdminSetFeedbackHandled PUT /api/admin/feedback/:id/handled func (h *Handler) AdminSetFeedbackHandled(c *gin.Context) { var req handledReq if err := c.ShouldBindJSON(&req); err != nil { response.FailParams(c, err.Error()) return } if err := h.svc.SetFeedbackHandled(idParam(c, "id"), req.Handled); err != nil { respondErr(c, err) return } response.OK(c, gin.H{"ok": true}) } // ListAIMessages GET /api/ai/messages?session=&limit= func (h *Handler) ListAIMessages(c *gin.Context) { limit := 0 if v := c.Query("limit"); v != "" { limit, _ = strconv.Atoi(v) } msgs, err := h.svc.ListAIMessages(middleware.UserID(c), c.Query("session"), limit) if err != nil { response.FailErr(c, err) return } response.OK(c, msgs) } // AIQuota GET /api/ai/quota 今日剩余次数 func (h *Handler) AIQuota(c *gin.Context) { response.OK(c, h.svc.AIQuotaLeft(middleware.UserID(c))) }