- 新增「简记memo」一体化小程序产品原型设计文档 - 新增简记memo完整版UI视觉设计规范和界面细节 - 添加IDEA项目配置文件.gitignore - 创建404页面HTML文件,包含响应式布局和错误提示 - 添加关于页面HTML文件,展示品牌介绍和团队信息 - 实现AES加解密工具函数,支持请求体加密 - 添加用户协议页面基础框架
207 lines
5.3 KiB
Go
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)
|
|
}
|