package handler import ( "errors" "net/http" "strings" "time" "github.com/gin-gonic/gin" "wx_service/internal/middleware" "wx_service/internal/model" smokeservice "wx_service/internal/smoke/service" ) func (h *SmokeHandler) Stats(c *gin.Context) { user := middleware.MustCurrentUser(c) rangeType := strings.ToLower(strings.TrimSpace(c.DefaultQuery("range", "week"))) asOf := time.Now().In(time.Local) if v := strings.TrimSpace(c.Query("date")); v != "" { parsed, err := time.ParseInLocation(dateLayout, v, time.Local) if err != nil { c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "date 格式错误,应为 YYYY-MM-DD")) return } asOf = time.Date(parsed.Year(), parsed.Month(), parsed.Day(), 23, 59, 59, 0, time.Local) } req, err := buildStatsRequest(rangeType, asOf) if err != nil { c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, err.Error())) return } profile, err := h.smokeProfileService.Get(c.Request.Context(), int(user.ID)) if err != nil { c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取基础信息失败,请稍后重试")) return } result, err := h.smokeLogService.Stats(c.Request.Context(), int(user.ID), req, profile) if err != nil { c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取统计数据失败,请稍后重试")) return } c.JSON(http.StatusOK, model.Success(result)) } func buildStatsRequest(rangeType string, anchor time.Time) (smokeservice.SmokeStatsRequest, error) { local := anchor.In(time.Local) switch rangeType { case "week": start, end := weekRange(local) return smokeservice.SmokeStatsRequest{ Range: "week", Start: start, End: end, PrevStart: start.AddDate(0, 0, -7), PrevEnd: end.AddDate(0, 0, -7), TrendUnit: "day", AsOf: local, }, nil case "month": start := time.Date(local.Year(), local.Month(), 1, 0, 0, 0, 0, time.Local) end := start.AddDate(0, 1, 0).AddDate(0, 0, -1) prevEnd := start.AddDate(0, 0, -1) prevStart := time.Date(prevEnd.Year(), prevEnd.Month(), 1, 0, 0, 0, 0, time.Local) return smokeservice.SmokeStatsRequest{ Range: "month", Start: start, End: end, PrevStart: prevStart, PrevEnd: prevEnd, TrendUnit: "day", AsOf: local, }, nil case "year": start := time.Date(local.Year(), time.January, 1, 0, 0, 0, 0, time.Local) end := time.Date(local.Year(), time.December, 31, 0, 0, 0, 0, time.Local) prevStart := time.Date(local.Year()-1, time.January, 1, 0, 0, 0, 0, time.Local) prevEnd := time.Date(local.Year()-1, time.December, 31, 0, 0, 0, 0, time.Local) return smokeservice.SmokeStatsRequest{ Range: "year", Start: start, End: end, PrevStart: prevStart, PrevEnd: prevEnd, TrendUnit: "month", AsOf: local, }, nil default: return smokeservice.SmokeStatsRequest{}, errors.New("range 应为 week|month|year") } } func weekRange(anchor time.Time) (time.Time, time.Time) { local := anchor.In(time.Local) weekday := local.Weekday() daysSinceMonday := int(weekday) - int(time.Monday) if daysSinceMonday < 0 { daysSinceMonday += 7 } start := time.Date(local.Year(), local.Month(), local.Day(), 0, 0, 0, 0, time.Local). AddDate(0, 0, -daysSinceMonday) end := start.AddDate(0, 0, 6) return start, end }