feat: 戒烟成就、梦想图标预设、打卡统计与依赖注入调整
- 成就系统、连续打卡天数计算、管理后台成就 CRUD - 梦想目标图标预设 DreamPreset 与用户端 dream-presets 接口 - 管理后台梦想图标 CRUD;戒烟打卡 summary 修正 - 忽略根目录编译产物 /api Made-with: Cursor
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"wx_service/internal/achievement"
|
||||
"wx_service/internal/middleware"
|
||||
"wx_service/internal/model"
|
||||
)
|
||||
|
||||
func (h *SmokeHandler) ListAchievementThemes(c *gin.Context) {
|
||||
themes, err := h.achievementService.ListActiveThemes(c.Request.Context())
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取成就主题失败"))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusOK, model.Success(gin.H{"themes": themes}))
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) GetAchievement(c *gin.Context) {
|
||||
user := middleware.MustCurrentUser(c)
|
||||
ctx := c.Request.Context()
|
||||
uid := int(user.ID)
|
||||
now := time.Now()
|
||||
|
||||
profile, err := h.smokeProfileService.Get(ctx, uid)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取用户信息失败"))
|
||||
return
|
||||
}
|
||||
if profile == nil || profile.AchievementThemeID == nil {
|
||||
c.JSON(http.StatusOK, model.Success(gin.H{"achievement": nil}))
|
||||
return
|
||||
}
|
||||
|
||||
var days int
|
||||
if profile.Mode == "quit" {
|
||||
homeData, err := h.quitCheckinService.Home(ctx, uid, now)
|
||||
if err != nil {
|
||||
log.Printf("achievement: quitcheckin home err uid=%d: %v", uid, err)
|
||||
days = 0
|
||||
} else {
|
||||
days = homeData.Summary.CurrentStreakDays
|
||||
}
|
||||
} else {
|
||||
streakDays, err := h.smokeLogService.GetStreakDays(ctx, uid, now)
|
||||
if err != nil {
|
||||
log.Printf("achievement: smoke streak err uid=%d: %v", uid, err)
|
||||
days = 0
|
||||
}
|
||||
days = streakDays
|
||||
}
|
||||
|
||||
ach, err := h.achievementService.GetUserAchievement(ctx, *profile.AchievementThemeID, days)
|
||||
if err != nil {
|
||||
if err == achievement.ErrThemeNotFound {
|
||||
c.JSON(http.StatusOK, model.Success(gin.H{"achievement": nil}))
|
||||
return
|
||||
}
|
||||
c.JSON(http.StatusInternalServerError, model.Error(http.StatusInternalServerError, "获取成就信息失败"))
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, model.Success(gin.H{"achievement": ach}))
|
||||
}
|
||||
@@ -10,8 +10,10 @@ import (
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"wx_service/internal/achievement"
|
||||
"wx_service/internal/middleware"
|
||||
"wx_service/internal/model"
|
||||
quitcheckinservice "wx_service/internal/quitcheckin/service"
|
||||
smokeservice "wx_service/internal/smoke/service"
|
||||
)
|
||||
|
||||
@@ -22,6 +24,8 @@ type SmokeHandler struct {
|
||||
smokeNextService *smokeservice.SmokeNextService
|
||||
smokeAINextService *smokeservice.SmokeAINextSmokeService
|
||||
smokeShareService *smokeservice.SmokeShareService
|
||||
achievementService *achievement.Service
|
||||
quitCheckinService *quitcheckinservice.Service
|
||||
}
|
||||
|
||||
func NewSmokeHandler(
|
||||
@@ -31,6 +35,8 @@ func NewSmokeHandler(
|
||||
smokeNextService *smokeservice.SmokeNextService,
|
||||
smokeAINextService *smokeservice.SmokeAINextSmokeService,
|
||||
smokeShareService *smokeservice.SmokeShareService,
|
||||
achievementService *achievement.Service,
|
||||
quitCheckinService *quitcheckinservice.Service,
|
||||
) *SmokeHandler {
|
||||
return &SmokeHandler{
|
||||
smokeLogService: smokeLogService,
|
||||
@@ -39,6 +45,8 @@ func NewSmokeHandler(
|
||||
smokeNextService: smokeNextService,
|
||||
smokeAINextService: smokeAINextService,
|
||||
smokeShareService: smokeShareService,
|
||||
achievementService: achievementService,
|
||||
quitCheckinService: quitCheckinService,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,8 @@ type upsertSmokeProfileRequest struct {
|
||||
SleepTime *string `json:"sleep_time"`
|
||||
|
||||
QuitDate *string `json:"quit_date"`
|
||||
|
||||
AchievementThemeID *uint `json:"achievement_theme_id"`
|
||||
}
|
||||
|
||||
func (h *SmokeHandler) GetProfile(c *gin.Context) {
|
||||
@@ -95,17 +97,21 @@ func (h *SmokeHandler) UpsertProfile(c *gin.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
achievementThemeIDProvided := req.AchievementThemeID != nil
|
||||
|
||||
view, err := h.smokeProfileService.Upsert(c.Request.Context(), int(user.ID), smokeservice.UpsertSmokeProfileRequest{
|
||||
BaselineCigsPerDay: req.BaselineCigsPerDay,
|
||||
SmokingYears: req.SmokingYears,
|
||||
PackPriceCent: req.PackPriceCent,
|
||||
Mode: req.Mode,
|
||||
SmokeMotivations: req.SmokeMotivations,
|
||||
QuitMotivations: req.QuitMotivations,
|
||||
WakeUpTime: req.WakeUpTime,
|
||||
SleepTime: req.SleepTime,
|
||||
QuitDateProvided: quitDateProvided,
|
||||
QuitDate: quitDate,
|
||||
BaselineCigsPerDay: req.BaselineCigsPerDay,
|
||||
SmokingYears: req.SmokingYears,
|
||||
PackPriceCent: req.PackPriceCent,
|
||||
Mode: req.Mode,
|
||||
SmokeMotivations: req.SmokeMotivations,
|
||||
QuitMotivations: req.QuitMotivations,
|
||||
WakeUpTime: req.WakeUpTime,
|
||||
SleepTime: req.SleepTime,
|
||||
QuitDateProvided: quitDateProvided,
|
||||
QuitDate: quitDate,
|
||||
AchievementThemeIDProvided: achievementThemeIDProvided,
|
||||
AchievementThemeID: req.AchievementThemeID,
|
||||
})
|
||||
if err != nil {
|
||||
if errors.Is(err, smokeservice.ErrSmokeProfileInvalidTime) {
|
||||
|
||||
Reference in New Issue
Block a user