Update evolution indices and enhance user experience in mini program

- Added new entries for content ranking algorithm adjustments and cross-platform reuse in the evolution indices for backend, team, and mini program development.
- Improved user interface elements in the mini program, including the addition of a hidden settings entry and refined guidance for profile modifications.
- Enhanced reading statistics display with formatted numbers for better clarity and user engagement.
- Updated reading tracker logic to prevent duplicate duration accumulation and ensure accurate reporting of reading progress.
This commit is contained in:
Alex-larget
2026-03-14 17:13:06 +08:00
parent c936371165
commit 1edceda4db
33 changed files with 773 additions and 75 deletions

View File

@@ -451,20 +451,44 @@ func UserReadingProgressGet(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"success": true, "data": out})
}
// parseDuration 从 JSON 解析 duration兼容数字与字符串防止客户端传字符串导致累加异常
func parseDuration(v interface{}) int {
if v == nil {
return 0
}
switch x := v.(type) {
case float64:
return int(x)
case int:
return x
case int64:
return int(x)
case string:
n, _ := strconv.Atoi(x)
return n
default:
return 0
}
}
// UserReadingProgressPost POST /api/user/reading-progress
func UserReadingProgressPost(c *gin.Context) {
var body struct {
UserID string `json:"userId" binding:"required"`
SectionID string `json:"sectionId" binding:"required"`
Progress int `json:"progress"`
Duration int `json:"duration"`
Status string `json:"status"`
CompletedAt *string `json:"completedAt"`
UserID string `json:"userId" binding:"required"`
SectionID string `json:"sectionId" binding:"required"`
Progress int `json:"progress"`
Duration interface{} `json:"duration"` // 兼容 int/float64/string防止字符串导致累加异常
Status string `json:"status"`
CompletedAt *string `json:"completedAt"`
}
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"success": false, "error": "缺少必要参数"})
return
}
duration := parseDuration(body.Duration)
if duration < 0 {
duration = 0
}
db := database.DB()
now := time.Now()
var existing model.ReadingProgress
@@ -474,7 +498,7 @@ func UserReadingProgressPost(c *gin.Context) {
if body.Progress > newProgress {
newProgress = body.Progress
}
newDuration := existing.Duration + body.Duration
newDuration := existing.Duration + duration
newStatus := body.Status
if newStatus == "" {
newStatus = "reading"
@@ -501,7 +525,7 @@ func UserReadingProgressPost(c *gin.Context) {
completedAt = &t
}
db.Create(&model.ReadingProgress{
UserID: body.UserID, SectionID: body.SectionID, Progress: body.Progress, Duration: body.Duration,
UserID: body.UserID, SectionID: body.SectionID, Progress: body.Progress, Duration: duration,
Status: status, CompletedAt: completedAt, FirstOpenAt: &now, LastOpenAt: &now,
})
}
@@ -681,6 +705,10 @@ func UserDashboardStats(c *gin.Context) {
if totalReadSeconds > 0 && totalReadMinutes == 0 {
totalReadMinutes = 1
}
// 异常数据保护:历史 bug 导致累加错误可能产生超大值, cap 到 99999 分钟(约 69 天)
if totalReadMinutes > 99999 {
totalReadMinutes = 99999
}
// 3. 批量查 chapters 获取真实标题与 mid
chapterMap := make(map[string]model.Chapter)