Enhance smoking tracking API with new features and improvements
- Added a new API endpoint `GET /api/v1/smoke/home` to consolidate core modules for the home dashboard, reducing the need for multiple requests. - Updated the `smoke` routes to include the new home endpoint and improved user profile management with the addition of a `quit_date` field. - Enhanced the algorithm for calculating daily targets and next smoke suggestions, ensuring accurate future time handling and user-specific recommendations. - Improved API documentation to reflect new endpoints, response formats, and detailed field descriptions for better clarity and usability. - Refactored user authentication handling in various handlers to streamline the process and ensure consistent error responses.
This commit is contained in:
@@ -5,6 +5,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -53,11 +54,7 @@ type createSmokeLogRequest struct {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) Create(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
var req createSmokeLogRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
@@ -130,11 +127,7 @@ type resistedSmokeLogRequest struct {
|
||||
|
||||
// Resist 表示“想抽但忍住了”:在 fa_smoke_log 中写入 level=0,num=0。
|
||||
func (h *SmokeHandler) Resist(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
var req resistedSmokeLogRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil && !errors.Is(err, io.EOF) {
|
||||
@@ -178,11 +171,7 @@ func (h *SmokeHandler) Resist(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) Get(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil || id <= 0 {
|
||||
@@ -204,14 +193,15 @@ func (h *SmokeHandler) Get(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) List(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
|
||||
pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "20"))
|
||||
listType := strings.ToLower(strings.TrimSpace(c.DefaultQuery("type", "all")))
|
||||
if listType != "all" && listType != "smoke" && listType != "resisted" {
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "type 应为 all|smoke|resisted"))
|
||||
return
|
||||
}
|
||||
|
||||
var start *time.Time
|
||||
if v := c.Query("start"); v != "" {
|
||||
@@ -237,6 +227,7 @@ func (h *SmokeHandler) List(c *gin.Context) {
|
||||
PageSize: pageSize,
|
||||
Start: start,
|
||||
End: end,
|
||||
Type: listType,
|
||||
})
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "查询列表失败,请稍后重试"))
|
||||
@@ -252,11 +243,7 @@ func (h *SmokeHandler) List(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) Dashboard(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
now := time.Now()
|
||||
defaultStart, defaultEnd := defaultDashboardRange(now)
|
||||
@@ -303,11 +290,7 @@ func (h *SmokeHandler) Dashboard(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) LatestLogs(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
limit, err := strconv.Atoi(c.DefaultQuery("limit", "20"))
|
||||
if err != nil {
|
||||
@@ -341,11 +324,7 @@ type updateSmokeLogRequest struct {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) Update(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil || id <= 0 {
|
||||
@@ -391,8 +370,12 @@ func (h *SmokeHandler) Update(c *gin.Context) {
|
||||
} else {
|
||||
parsed, err := time.ParseInLocation(dateTimeLayout, *req.SmokeAt, time.Local)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "smoke_at 格式错误,应为 YYYY-MM-DD HH:MM:SS"))
|
||||
return
|
||||
parsedRFC, errRFC := time.Parse(time.RFC3339, *req.SmokeAt)
|
||||
if errRFC != nil {
|
||||
c.JSON(http.StatusBadRequest, model.Error(http.StatusBadRequest, "smoke_at 格式错误,应为 YYYY-MM-DD HH:MM:SS 或 RFC3339"))
|
||||
return
|
||||
}
|
||||
parsed = parsedRFC.In(time.Local)
|
||||
}
|
||||
smokeAt = &parsed
|
||||
}
|
||||
@@ -420,11 +403,7 @@ func (h *SmokeHandler) Update(c *gin.Context) {
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) Delete(c *gin.Context) {
|
||||
user, ok := middleware.CurrentUser(c)
|
||||
if !ok {
|
||||
c.JSON(http.StatusUnauthorized, model.Error(http.StatusUnauthorized, "未登录或登录已过期"))
|
||||
return
|
||||
}
|
||||
user := middleware.MustCurrentUser(c)
|
||||
|
||||
id, err := strconv.Atoi(c.Param("id"))
|
||||
if err != nil || id <= 0 {
|
||||
|
||||
Reference in New Issue
Block a user