c9ebfd5873
- Added unified backend calculations for health recovery, savings, and motivation generation in the algorithm documentation. - Updated API documentation to include new endpoints for retrieving statistics and motivation messages, enhancing clarity on data retrieval processes. - Revised product documentation to reflect changes in API usage for health recovery and savings calculations, ensuring consistency across all related files.
114 lines
3.4 KiB
Go
114 lines
3.4 KiB
Go
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, ok := middleware.CurrentUser(c)
|
|
if !ok {
|
|
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
|
return
|
|
}
|
|
|
|
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
|
|
}
|