rank.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. package daytask
  2. import (
  3. "app/commons/model/entity"
  4. "fmt"
  5. "github.com/gin-gonic/gin"
  6. "time"
  7. )
  8. // RankList 排行榜列表
  9. func (s *Server) RankList(c *gin.Context) {
  10. ctx := s.FromContext(c)
  11. db := s.DB()
  12. userId := ctx.UserId()
  13. rankType := ctx.QueryString("type", "task") // task任务排行/invite邀请排行
  14. timeType := ctx.QueryString("timeType", "daily") // daily/weekly/monthly
  15. limit := ctx.QueryInt64("limit", 50)
  16. if limit > 100 {
  17. limit = 100
  18. }
  19. type RankInfo struct {
  20. Rank int `json:"rank"`
  21. UserId int64 `json:"userId" gorm:"column:user_id"`
  22. Uid string `json:"uid"`
  23. Nickname string `json:"nickname"`
  24. Avatar string `json:"avatar"`
  25. Count int `json:"count" gorm:"column:cnt"`
  26. }
  27. ranks := make([]RankInfo, 0)
  28. // 使用东八区时区
  29. loc, _ := time.LoadLocation("Asia/Shanghai")
  30. now := time.Now().In(loc)
  31. // 生成时间条件的辅助函数 - 直接使用时间戳范围比较,避免时区问题
  32. getTimeCondition := func(timeField string) string {
  33. var startTime, endTime int64
  34. switch timeType {
  35. case "daily":
  36. // 今天 00:00:00 到 23:59:59
  37. startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
  38. startTime = startOfDay.Unix()
  39. endTime = startOfDay.Add(24*time.Hour - time.Second).Unix()
  40. case "weekly":
  41. // 本周一 00:00:00 到现在
  42. weekday := int(now.Weekday())
  43. if weekday == 0 {
  44. weekday = 7
  45. }
  46. startOfWeek := time.Date(now.Year(), now.Month(), now.Day()-(weekday-1), 0, 0, 0, 0, loc)
  47. startTime = startOfWeek.Unix()
  48. endTime = now.Unix()
  49. case "monthly":
  50. // 本月1号 00:00:00 到现在
  51. startOfMonth := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, loc)
  52. startTime = startOfMonth.Unix()
  53. endTime = now.Unix()
  54. default:
  55. startOfDay := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, loc)
  56. startTime = startOfDay.Unix()
  57. endTime = startOfDay.Add(24*time.Hour - time.Second).Unix()
  58. }
  59. return fmt.Sprintf("%s >= %d AND %s <= %d", timeField, startTime, timeField, endTime)
  60. }
  61. // 根据类型查询不同的排行榜
  62. switch rankType {
  63. case "task":
  64. // 任务完成数量排行 - 使用审核通过时间(audit_time)
  65. taskTimeCondition := getTimeCondition("t.audit_time")
  66. db.Raw(`
  67. SELECT
  68. u.id as user_id,
  69. u.uid,
  70. u.nickname,
  71. u.avatar,
  72. COUNT(t.id) as cnt
  73. FROM dt_user u
  74. INNER JOIN dt_user_task t ON u.id = t.user_id
  75. AND t.status = ?
  76. AND `+taskTimeCondition+`
  77. WHERE u.status = 1
  78. GROUP BY u.id, u.uid, u.nickname, u.avatar
  79. HAVING cnt > 0
  80. ORDER BY cnt DESC
  81. LIMIT ?
  82. `, entity.UserTaskStatusCompleted, limit).Scan(&ranks)
  83. case "invite":
  84. // 邀请人数排行 - 使用下级用户注册时间(created_at)
  85. inviteTimeCondition := getTimeCondition("t.created_at")
  86. db.Raw(`
  87. SELECT
  88. u.id as user_id,
  89. u.uid,
  90. u.nickname,
  91. u.avatar,
  92. COUNT(t.id) as cnt
  93. FROM dt_user u
  94. INNER JOIN dt_user t ON u.id = t.parent_id
  95. AND `+inviteTimeCondition+`
  96. WHERE u.status = 1
  97. GROUP BY u.id, u.uid, u.nickname, u.avatar
  98. HAVING cnt > 0
  99. ORDER BY cnt DESC
  100. LIMIT ?
  101. `, limit).Scan(&ranks)
  102. default:
  103. ctx.Fail("invalid_type")
  104. return
  105. }
  106. // 手动设置排名序号
  107. for i := range ranks {
  108. ranks[i].Rank = i + 1
  109. }
  110. // 查询当前用户排名
  111. var myRank *RankInfo
  112. for i := range ranks {
  113. if ranks[i].UserId == userId {
  114. myRank = &ranks[i]
  115. break
  116. }
  117. }
  118. // 如果当前用户不在榜单中,单独查询
  119. if myRank == nil {
  120. var user entity.DtUser
  121. if err := db.Where("id = ?", userId).First(&user).Error; err == nil {
  122. myRank = &RankInfo{
  123. Rank: 0,
  124. UserId: user.Id,
  125. Uid: user.Uid,
  126. Nickname: user.Nickname,
  127. Avatar: user.Avatar,
  128. Count: 0,
  129. }
  130. }
  131. }
  132. ctx.OK(gin.H{
  133. "list": ranks,
  134. "myRank": myRank,
  135. })
  136. }
  137. // RankReward 排行榜奖励配置
  138. func (s *Server) RankReward(c *gin.Context) {
  139. ctx := s.FromContext(c)
  140. db := s.DB()
  141. var configs []entity.DtLeaderboardReward
  142. db.Where("status = ?", 1).
  143. Order("rank_start ASC").
  144. Find(&configs)
  145. type RewardInfo struct {
  146. RankStart int `json:"rankStart"`
  147. RankEnd int `json:"rankEnd"`
  148. Reward float64 `json:"reward"`
  149. }
  150. rewards := make([]*RewardInfo, 0)
  151. for _, config := range configs {
  152. rewards = append(rewards, &RewardInfo{
  153. RankStart: config.RankStart,
  154. RankEnd: config.RankEnd,
  155. Reward: config.Reward,
  156. })
  157. }
  158. ctx.OK(gin.H{
  159. "list": rewards,
  160. })
  161. }