package handler import ( "time" "github.com/gin-gonic/gin" "gorm.io/datatypes" "github.com/sundynix/pets-be/internal/middleware" "github.com/sundynix/pets-be/internal/service" "github.com/sundynix/pets-be/pkg/response" ) type recordReq struct { Type string `json:"type"` Icon string `json:"icon"` Title string `json:"title"` Description string `json:"description"` NumValue float64 `json:"num_value"` Category string `json:"category"` ImageURL string `json:"image_url"` ImageFileID string `json:"image_file_id"` Extra datatypes.JSON `json:"extra"` OccurredAt string `json:"occurred_at"` } // ListRecords GET /api/pets/:id/records?type= func (h *Handler) ListRecords(c *gin.Context) { var pq response.PageQuery _ = c.ShouldBindQuery(&pq) pq.Normalize() records, total, err := h.svc.ListRecords(middleware.UserID(c), idParam(c, "id"), c.Query("type"), pq.Offset(), pq.Limit()) if err != nil { respondErr(c, err) return } response.OK(c, response.NewPage(records, total, pq)) } // CreateRecord POST /api/pets/:id/records func (h *Handler) CreateRecord(c *gin.Context) { var req recordReq if err := c.ShouldBindJSON(&req); err != nil { response.FailParams(c, err.Error()) return } in := service.RecordInput{ Type: req.Type, Icon: req.Icon, Title: req.Title, Description: req.Description, NumValue: req.NumValue, Category: req.Category, ImageURL: req.ImageURL, ImageFileID: req.ImageFileID, Extra: req.Extra, } if req.OccurredAt != "" { if t, err := time.Parse(time.RFC3339, req.OccurredAt); err == nil { in.OccurredAt = &t } } rec, err := h.svc.CreateRecord(middleware.UserID(c), idParam(c, "id"), in) if err != nil { respondErr(c, err) return } response.OK(c, rec) } // DeleteRecord DELETE /api/records/:id func (h *Handler) DeleteRecord(c *gin.Context) { if err := h.svc.DeleteRecord(middleware.UserID(c), idParam(c, "id")); err != nil { respondErr(c, err) return } response.OK(c, gin.H{"deleted": true}) } // WeightTrend GET /api/pets/:id/records/weight-trend func (h *Handler) WeightTrend(c *gin.Context) { points, err := h.svc.WeightTrend(middleware.UserID(c), idParam(c, "id"), 7) if err != nil { respondErr(c, err) return } response.OK(c, points) } // PetInsights GET /api/pets/:id/insights // 把散落的记录变成结论:体重趋势、换粮与软便的关联、异常扎堆、逾期提醒、同龄对比。 func (h *Handler) PetInsights(c *gin.Context) { list, err := h.svc.PetInsights(middleware.UserID(c), idParam(c, "id")) if err != nil { respondErr(c, err) return } response.OK(c, list) }