Переглянути джерело

fix: 修复排行榜时区问题导致数据不显示

- 使用时间戳范围比较替代 DATE 函数转换,避免服务器时区与数据库时区不一致问题
- 任务排行榜改用 audit_time(审核时间)作为筛选字段
- 修复周计算逻辑,改为周一作为一周开始
- 简化 SQL 查询,移除嵌套子查询
- 修复 GORM 字段映射(添加 gorm column tag)
urbanu 1 місяць тому
батько
коміт
8d0b7ea697
1 змінених файлів з 75 додано та 63 видалено
  1. 75 63
      apis/daytask/rank.go

+ 75 - 63
apis/daytask/rank.go

@@ -2,6 +2,7 @@ package daytask
 
 import (
 	"app/commons/model/entity"
+	"fmt"
 	"github.com/gin-gonic/gin"
 	"time"
 )
@@ -22,84 +23,90 @@ func (s *Server) RankList(c *gin.Context) {
 
 	type RankInfo struct {
 		Rank     int    `json:"rank"`
-		UserId   int64  `json:"userId"`
+		UserId   int64  `json:"userId" gorm:"column:user_id"`
 		Uid      string `json:"uid"`
 		Nickname string `json:"nickname"`
 		Avatar   string `json:"avatar"`
-		Count    int    `json:"count"`
+		Count    int    `json:"count" gorm:"column:cnt"`
 	}
 
-	ranks := make([]*RankInfo, 0)
-
-	// 时间条件
-	var timeCondition string
-	switch timeType {
-	case "daily":
-		timeCondition = "DATE(FROM_UNIXTIME(t.created_at)) = '" + time.Now().Format("2006-01-02") + "'"
-	case "weekly":
-		weekStart := time.Now().AddDate(0, 0, -int(time.Now().Weekday())).Format("2006-01-02")
-		timeCondition = "DATE(FROM_UNIXTIME(t.created_at)) >= '" + weekStart + "'"
-	case "monthly":
-		month := time.Now().Format("2006-01")
-		timeCondition = "DATE_FORMAT(FROM_UNIXTIME(t.created_at), '%Y-%m') = '" + month + "'"
-	default:
-		timeCondition = "DATE(FROM_UNIXTIME(t.created_at)) = '" + time.Now().Format("2006-01-02") + "'"
+	ranks := make([]RankInfo, 0)
+
+	// 使用东八区时区
+	loc, _ := time.LoadLocation("Asia/Shanghai")
+	now := time.Now().In(loc)
+
+	// 生成时间条件的辅助函数 - 直接使用时间戳范围比较,避免时区问题
+	getTimeCondition := func(timeField string) string {
+		var startTime, endTime int64
+		switch timeType {
+		case "daily":
+			// 今天 00:00:00 到 23:59:59
+			startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
+			startTime = startOfDay.Unix()
+			endTime = startOfDay.Add(24*time.Hour - time.Second).Unix()
+		case "weekly":
+			// 本周一 00:00:00 到现在
+			weekday := int(now.Weekday())
+			if weekday == 0 {
+				weekday = 7
+			}
+			startOfWeek := time.Date(now.Year(), now.Month(), now.Day()-(weekday-1), 0, 0, 0, 0, loc)
+			startTime = startOfWeek.Unix()
+			endTime = now.Unix()
+		case "monthly":
+			// 本月1号 00:00:00 到现在
+			startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
+			startTime = startOfMonth.Unix()
+			endTime = now.Unix()
+		default:
+			startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
+			startTime = startOfDay.Unix()
+			endTime = startOfDay.Add(24*time.Hour - time.Second).Unix()
+		}
+		return fmt.Sprintf("%s >= %d AND %s <= %d", timeField, startTime, timeField, endTime)
 	}
 
 	// 根据类型查询不同的排行榜
 	switch rankType {
 	case "task":
-		// 任务完成数量排行
+		// 任务完成数量排行 - 使用审核通过时间(audit_time)
+		taskTimeCondition := getTimeCondition("t.audit_time")
 		db.Raw(`
 			SELECT
-				ROW_NUMBER() OVER(ORDER BY cnt DESC) as `+"`rank`"+`,
-				user_id,
-				uid,
-				nickname,
-				avatar,
-				cnt as count
-			FROM (
-				SELECT
-					u.id as user_id,
-					u.uid,
-					u.nickname,
-					u.avatar,
-					COUNT(t.id) as cnt
-				FROM dt_user u
-				INNER JOIN dt_user_task t ON u.id = t.user_id
-					AND t.status = ?
-					AND `+timeCondition+`
-				WHERE u.status = 1
-				GROUP BY u.id, u.uid, u.nickname, u.avatar
-				HAVING cnt > 0
-			) ranked
+				u.id as user_id,
+				u.uid,
+				u.nickname,
+				u.avatar,
+				COUNT(t.id) as cnt
+			FROM dt_user u
+			INNER JOIN dt_user_task t ON u.id = t.user_id
+				AND t.status = ?
+				AND `+taskTimeCondition+`
+			WHERE u.status = 1
+			GROUP BY u.id, u.uid, u.nickname, u.avatar
+			HAVING cnt > 0
+			ORDER BY cnt DESC
 			LIMIT ?
 		`, entity.UserTaskStatusCompleted, limit).Scan(&ranks)
 
 	case "invite":
-		// 邀请人数排行
+		// 邀请人数排行 - 使用下级用户注册时间(created_at)
+		inviteTimeCondition := getTimeCondition("t.created_at")
 		db.Raw(`
 			SELECT
-				ROW_NUMBER() OVER(ORDER BY cnt DESC) as `+"`rank`"+`,
-				user_id,
-				uid,
-				nickname,
-				avatar,
-				cnt as count
-			FROM (
-				SELECT
-					u.id as user_id,
-					u.uid,
-					u.nickname,
-					u.avatar,
-					COUNT(t.id) as cnt
-				FROM dt_user u
-				INNER JOIN dt_user t ON u.id = t.parent_id
-					AND `+timeCondition+`
-				WHERE u.status = 1
-				GROUP BY u.id, u.uid, u.nickname, u.avatar
-				HAVING cnt > 0
-			) ranked
+				u.id as user_id,
+				u.uid,
+				u.nickname,
+				u.avatar,
+				COUNT(t.id) as cnt
+			FROM dt_user u
+			INNER JOIN dt_user t ON u.id = t.parent_id
+				AND `+inviteTimeCondition+`
+			WHERE u.status = 1
+			GROUP BY u.id, u.uid, u.nickname, u.avatar
+			HAVING cnt > 0
+			ORDER BY cnt DESC
 			LIMIT ?
 		`, limit).Scan(&ranks)
 
@@ -108,11 +115,16 @@ func (s *Server) RankList(c *gin.Context) {
 		return
 	}
 
+	// 手动设置排名序号
+	for i := range ranks {
+		ranks[i].Rank = i + 1
+	}
+
 	// 查询当前用户排名
 	var myRank *RankInfo
-	for _, rank := range ranks {
-		if rank.UserId == userId {
-			myRank = rank
+	for i := range ranks {
+		if ranks[i].UserId == userId {
+			myRank = &ranks[i]
 			break
 		}
 	}