// 首页聚合数据接口 package app import ( "simple-memo/global" "simple-memo/models" "simple-memo/utils" "time" "gorm.io/gorm" "github.com/gin-gonic/gin" ) // -------------------------- 1. 定义 Handler 接口 -------------------------- type DashboardHandler interface { DailyDashboard(c *gin.Context) // 首页聚合数据 } // -------------------------- 2. 实现结构体 -------------------------- type dashboardHandler struct { db *gorm.DB } func NewDashboardHandler() DashboardHandler { return &dashboardHandler{ db: global.DB, } } // -------------------------- 3. 请求结构体 -------------------------- type DailyDashboardReq struct { Date string `json:"date"` // YYYY-MM-DD,不传默认今天 } // -------------------------- 4. 接口实现 -------------------------- // DailyDashboard 首页聚合数据 func (h *dashboardHandler) DailyDashboard(c *gin.Context) { userID := c.GetUint("userID") var req DailyDashboardReq if err := c.ShouldBindJSON(&req); err != nil { utils.Fail(c, "参数解析失败") return } // 日期处理 var targetDate string if req.Date == "" { targetDate = time.Now().Format("2006-01-02") } else { targetDate = req.Date } // ========== 1. 待办数据 ========== var todoTotal, todoDone, todoUndone int64 h.db.Model(&models.Todo{}). Where("user_id = ? AND date = ?", userID, targetDate). Count(&todoTotal) h.db.Model(&models.Todo{}). Where("user_id = ? AND date = ? AND done = 1", userID, targetDate). Count(&todoDone) todoUndone = todoTotal - todoDone // 待办列表(最近3条) var todoList []models.Todo h.db.Model(&models.Todo{}). Where("user_id = ? AND date = ?", userID, targetDate). Order("priority ASC, id ASC"). Limit(3). Find(&todoList) todoData := gin.H{ "total": todoTotal, "done": todoDone, "undone": todoUndone, "list": todoList, } // ========== 2. 账单数据 ========== var billExpend, billIncome float64 h.db.Model(&models.Bill{}). Where("user_id = ? AND date = ? AND type = 1", userID, targetDate). Select("COALESCE(SUM(money), 0)").Scan(&billExpend) h.db.Model(&models.Bill{}). Where("user_id = ? AND date = ? AND type = 2", userID, targetDate). Select("COALESCE(SUM(money), 0)").Scan(&billIncome) // 账单列表(最近3条) var billList []models.Bill h.db.Model(&models.Bill{}). Where("user_id = ? AND date = ?", userID, targetDate). Order("id DESC"). Limit(3). Find(&billList) billData := gin.H{ "expend": billExpend, "income": billIncome, "balance": billIncome - billExpend, "list": billList, } // ========== 3. 心情数据 ========== type MoodResult struct { ID uint `json:"id"` Date string `json:"date"` Emoji string `json:"emoji"` Content string `json:"content"` AIStatus int `json:"ai_status"` AIText string `json:"ai_text"` AIImageURL string `json:"ai_image_url"` AIGenerateCount int `json:"ai_generate_count"` } var moodResult MoodResult h.db.Model(&models.Mood{}). Select(` sm_mood.id, sm_mood.date, sm_mood.emoji, sm_mood.content, COALESCE(sm_mood_ai_generations.status, 0) as ai_status, COALESCE(sm_mood_ai_generations.ai_text, '') as ai_text, COALESCE(sm_mood_ai_generations.ai_image_url, '') as ai_image_url, COALESCE(sm_mood_ai_generations.generate_count, 0) as ai_generate_count `). Joins("LEFT JOIN sm_mood_ai_generations ON sm_mood.id = sm_mood_ai_generations.mood_id"). Where("sm_mood.user_id = ? AND sm_mood.date = ?", userID, targetDate). Scan(&moodResult) moodData := gin.H{ "recorded": moodResult.ID > 0, "emoji": moodResult.Emoji, "content": moodResult.Content, "ai_generated": moodResult.AIStatus == 2, "ai_text": moodResult.AIText, } if moodResult.ID == 0 { moodData = gin.H{ "recorded": false, "emoji": "", "content": "", "ai_generated": false, "ai_text": "", } } // ========== 4. 复盘数据 ========== var review models.Review err := h.db.Where("user_id = ? AND date = ?", userID, targetDate).First(&review).Error reviewData := gin.H{ "recorded": err == nil, "method": "kpt", } if err == nil { reviewData["id"] = review.ID reviewData["keep"] = review.Keep reviewData["problem"] = review.Problem reviewData["try"] = review.Try // 生成简短摘要 summary := "" if review.Keep != "" { s := review.Keep if len(s) > 30 { s = s[:30] + "..." } summary = s } reviewData["summary"] = summary } // ========== 5. 成长数据 ========== growthHandler := NewGrowthHandler() growthInfo := growthHandler.GetGrowthInfoInternal(userID) growthData := gin.H{ "todayExp": 0, // 今日经验,需要从 ExpChangeLog 查询 "maxDailyExp": 120, "streakDays": growthInfo["streak_days"], } // 查询今日经验 var todayExp int today := time.Now().Format("2006-01-02") if targetDate == today { h.db.Model(&models.ExpChangeLog{}). Where("user_id = ? AND DATE(created_at) = ?", userID, today). Select("COALESCE(SUM(exp), 0)"). Scan(&todayExp) growthData["todayExp"] = todayExp } // ========== 组装结果 ========== result := gin.H{ "date": targetDate, "todo": todoData, "bill": billData, "mood": moodData, "review": reviewData, "growth": growthData, } utils.Ok(c, result) }