Files
simple-memo/api/app/dashboard.go
T
sunct 3c3bf53ae4 docs(website): 添加简记memo产品原型和UI设计规范文档
- 新增「简记memo」一体化小程序产品原型设计文档
- 新增简记memo完整版UI视觉设计规范和界面细节
- 添加IDEA项目配置文件.gitignore
- 创建404页面HTML文件,包含响应式布局和错误提示
- 添加关于页面HTML文件,展示品牌介绍和团队信息
- 实现AES加解密工具函数,支持请求体加密
- 添加用户协议页面基础框架
2026-07-31 14:12:32 +08:00

207 lines
5.3 KiB
Go

// 首页聚合数据接口
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)
}