更新管理端迁移Mycontent-temp的菜单与布局规范,确保主导航收敛并优化隐藏页面入口。新增相关会议记录与文档,反映团队讨论的最新决策与实施建议。
This commit is contained in:
@@ -639,3 +639,91 @@ func UserUpdate(c *gin.Context) {
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"success": true, "message": "更新成功"})
|
||||
}
|
||||
|
||||
// UserDashboardStats GET /api/miniprogram/user/dashboard-stats?userId=
|
||||
// 小程序「我的」页聚合统计:已读章节列表、最近阅读、总阅读时长、匹配历史数
|
||||
func UserDashboardStats(c *gin.Context) {
|
||||
userID := c.Query("userId")
|
||||
if userID == "" {
|
||||
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "缺少 userId 参数"})
|
||||
return
|
||||
}
|
||||
|
||||
db := database.DB()
|
||||
|
||||
// 1. 拉取该用户所有阅读进度记录,按最近打开时间倒序
|
||||
var progressList []model.ReadingProgress
|
||||
if err := db.Where("user_id = ?", userID).Order("last_open_at DESC").Find(&progressList).Error; err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"success": false, "error": "读取阅读统计失败"})
|
||||
return
|
||||
}
|
||||
|
||||
// 2. 遍历:统计 readSectionIds / totalReadSeconds,同时去重取最近 5 个不重复章节
|
||||
readCount := len(progressList)
|
||||
totalReadSeconds := 0
|
||||
recentIDs := make([]string, 0, 5)
|
||||
seenRecent := make(map[string]bool)
|
||||
readSectionIDs := make([]string, 0, len(progressList))
|
||||
for _, item := range progressList {
|
||||
totalReadSeconds += item.Duration
|
||||
if item.SectionID != "" {
|
||||
readSectionIDs = append(readSectionIDs, item.SectionID)
|
||||
// 去重:同一章节只保留最近一次
|
||||
if !seenRecent[item.SectionID] && len(recentIDs) < 5 {
|
||||
seenRecent[item.SectionID] = true
|
||||
recentIDs = append(recentIDs, item.SectionID)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 不足 60 秒但有阅读记录时,至少显示 1 分钟
|
||||
totalReadMinutes := totalReadSeconds / 60
|
||||
if totalReadSeconds > 0 && totalReadMinutes == 0 {
|
||||
totalReadMinutes = 1
|
||||
}
|
||||
|
||||
// 3. 批量查 chapters 获取真实标题与 mid
|
||||
chapterMap := make(map[string]model.Chapter)
|
||||
if len(recentIDs) > 0 {
|
||||
var chapters []model.Chapter
|
||||
if err := db.Select("id", "mid", "section_title").Where("id IN ?", recentIDs).Find(&chapters).Error; err == nil {
|
||||
for _, ch := range chapters {
|
||||
chapterMap[ch.ID] = ch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 按最近阅读顺序组装,标题 fallback 为 section_id
|
||||
recentChapters := make([]gin.H, 0, len(recentIDs))
|
||||
for _, id := range recentIDs {
|
||||
ch, ok := chapterMap[id]
|
||||
title := id
|
||||
mid := 0
|
||||
if ok {
|
||||
if ch.SectionTitle != "" {
|
||||
title = ch.SectionTitle
|
||||
}
|
||||
mid = ch.MID
|
||||
}
|
||||
recentChapters = append(recentChapters, gin.H{
|
||||
"id": id,
|
||||
"mid": mid,
|
||||
"title": title,
|
||||
})
|
||||
}
|
||||
|
||||
// 4. 匹配历史数(该用户发起的匹配次数)
|
||||
var matchHistory int64
|
||||
db.Model(&model.MatchRecord{}).Where("user_id = ?", userID).Count(&matchHistory)
|
||||
|
||||
c.JSON(http.StatusOK, gin.H{
|
||||
"success": true,
|
||||
"data": gin.H{
|
||||
"readCount": readCount,
|
||||
"totalReadMinutes": totalReadMinutes,
|
||||
"recentChapters": recentChapters,
|
||||
"matchHistory": matchHistory,
|
||||
"readSectionIds": readSectionIDs,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user