sign.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package daytask
  2. import (
  3. "app/commons/model/entity"
  4. "github.com/gin-gonic/gin"
  5. "time"
  6. )
  7. // SignInfo 签到信息
  8. func (s *Server) SignInfo(c *gin.Context) {
  9. ctx := s.FromContext(c)
  10. db := s.DB()
  11. userId := ctx.UserId()
  12. // 获取用户信息
  13. user := &entity.DtUser{}
  14. if err := db.Where("id = ?", userId).First(user).Error; err != nil {
  15. ctx.Fail("user_not_found")
  16. return
  17. }
  18. // 获取今日签到记录
  19. today := time.Now().Format("2006-01-02")
  20. var todaySign entity.DtUserSign
  21. todaySigned := false
  22. if err := db.Where("user_id = ? AND sign_date = ?", userId, today).First(&todaySign).Error; err == nil {
  23. todaySigned = true
  24. }
  25. // 获取本月签到记录
  26. month := time.Now().Format("2006-01")
  27. var monthSigns []entity.DtUserSign
  28. db.Where("user_id = ? AND month = ?", userId, month).
  29. Order("sign_date ASC").
  30. Find(&monthSigns)
  31. // 构建签到日历
  32. signDates := make([]string, 0)
  33. for _, sign := range monthSigns {
  34. signDates = append(signDates, sign.SignDate)
  35. }
  36. // 构建奖励配置
  37. rewards := make([]gin.H, 0)
  38. for i, reward := range entity.SignRewardConfig {
  39. rewards = append(rewards, gin.H{
  40. "day": i + 1,
  41. "reward": reward,
  42. })
  43. }
  44. ctx.OK(gin.H{
  45. "continuousDays": user.ContinuousSignDays,
  46. "totalDays": user.TotalSignDays,
  47. "todaySigned": todaySigned,
  48. "signDates": signDates,
  49. "rewards": rewards,
  50. })
  51. }
  52. // SignDo 执行签到
  53. func (s *Server) SignDo(c *gin.Context) {
  54. ctx := s.FromContext(c)
  55. db := s.DB()
  56. userId := ctx.UserId()
  57. // 检查今日是否已签到
  58. today := time.Now().Format("2006-01-02")
  59. month := time.Now().Format("2006-01")
  60. var existSign entity.DtUserSign
  61. if err := db.Where("user_id = ? AND sign_date = ?", userId, today).First(&existSign).Error; err == nil {
  62. ctx.Fail("already_signed")
  63. return
  64. }
  65. // 获取用户信息
  66. user := &entity.DtUser{}
  67. if err := db.Where("id = ?", userId).First(user).Error; err != nil {
  68. ctx.Fail("user_not_found")
  69. return
  70. }
  71. // 检查昨天是否签到,判断是否连续
  72. yesterday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
  73. var yesterdaySign entity.DtUserSign
  74. isContinuous := false
  75. if err := db.Where("user_id = ? AND sign_date = ?", userId, yesterday).First(&yesterdaySign).Error; err == nil {
  76. isContinuous = true
  77. }
  78. // 计算连续签到天数
  79. continuousDays := 1
  80. if isContinuous {
  81. continuousDays = user.ContinuousSignDays + 1
  82. }
  83. // 根据连续天数获取奖励(8天循环)
  84. dayIndex := (continuousDays - 1) % len(entity.SignRewardConfig)
  85. reward := entity.SignRewardConfig[dayIndex]
  86. // 开启事务
  87. tx := db.Begin()
  88. // 创建签到记录
  89. sign := &entity.DtUserSign{
  90. UserId: userId,
  91. SignDate: today,
  92. SignDay: continuousDays,
  93. RewardAmount: reward,
  94. Month: month,
  95. }
  96. if err := tx.Create(sign).Error; err != nil {
  97. tx.Rollback()
  98. ctx.Fail("sign_failed")
  99. return
  100. }
  101. // 更新用户签到信息和余额(原子操作)
  102. updates := map[string]interface{}{
  103. "continuous_sign_days": continuousDays,
  104. "total_sign_days": db.Raw("total_sign_days + 1"),
  105. "balance": db.Raw("balance + ?", reward),
  106. }
  107. if err := tx.Model(&entity.DtUser{}).Where("id = ?", userId).Updates(updates).Error; err != nil {
  108. tx.Rollback()
  109. ctx.Fail("sign_failed")
  110. return
  111. }
  112. // 重新查询更新后的余额
  113. var updatedUser entity.DtUser
  114. tx.Where("id = ?", userId).First(&updatedUser)
  115. // 记录余额变动
  116. balanceLog := &entity.DtBalanceLog{
  117. UserId: userId,
  118. Type: entity.BalanceLogTypeSignReward,
  119. Amount: reward,
  120. BeforeBalance: updatedUser.Balance - reward,
  121. AfterBalance: updatedUser.Balance,
  122. Remark: ctx.I18n("sign_reward"),
  123. }
  124. if err := tx.Create(balanceLog).Error; err != nil {
  125. tx.Rollback()
  126. ctx.Fail("sign_failed")
  127. return
  128. }
  129. tx.Commit()
  130. ctx.OK(gin.H{
  131. "reward": reward,
  132. "continuousDays": continuousDays,
  133. "totalDays": user.TotalSignDays + 1,
  134. })
  135. }