1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
package mic_m
import (
"git.hilo.cn/hilo-common/_const/enum/timezone_e"
"git.hilo.cn/hilo-common/domain"
"git.hilo.cn/hilo-common/resource/mysql"
"git.hilo.cn/hilo-common/utils"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"time"
)
// 用户上麦
type UserOnMic struct {
Date string
UserId mysql.ID
Seconds mysql.Num
LastCalTs int64
CreatedTime time.Time `gorm:"->"`
UpdatedTime time.Time `gorm:"->"`
Tz timezone_e.Timezone
}
// 获取用户当日上麦
// 允许返回gorm.ErrRecordNotFound
func GetUserOnMic(model *domain.Model, userId mysql.ID, tz timezone_e.Timezone) (*UserOnMic, error) {
res := new(UserOnMic)
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
if err := model.DB().Where("date = ? AND user_id = ? AND tz = ?", day, userId, tz).First(res).Error; err != nil {
return nil, err
}
return res, nil
}
// 增加用户上麦时长
// 事务操作
func IncrUserOnMic(model *domain.Model, userId mysql.ID, joinMicTimestamp int64) error {
return model.Transaction(func(model *domain.Model) error {
for _, tz := range timezone_e.Timezones {
omMic, err := GetUserOnMic(model, userId, tz)
if err != nil && err != gorm.ErrRecordNotFound {
return err
}
curTs := joinMicTimestamp
nowTs := time.Now().Unix()
day0Ts := utils.GetZeroTime(time.Now().In(timezone_e.TimezoneLocMap[tz])).Unix()
if omMic != nil && joinMicTimestamp < omMic.LastCalTs { // 加入的时间比上次计算时间小
curTs = omMic.LastCalTs
}
// 跨天
if curTs < day0Ts {
curTs = day0Ts
}
score := nowTs - curTs
day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02")
onMicNew := &UserOnMic{
Date: day,
UserId: userId,
Seconds: mysql.Num(score),
LastCalTs: nowTs,
Tz: tz,
}
if err := model.DB().Model(UserOnMic{}).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "date"}, {Name: "user_id"}, {Name: "tz"}},
DoUpdates: clause.Assignments(map[string]interface{}{
"seconds": gorm.Expr("seconds + ?", onMicNew.Seconds),
"last_cal_ts": nowTs,
}),
}).Create(onMicNew).Error; err != nil {
model.Log.Errorf("IncrUserOnMic fail:%v", err)
return err
}
}
return nil
})
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSeconds(model *domain.Model, day string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date`= ? AND tz = ? AND user_id in ?", day, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
for _, r := range rows {
res[r.UserId] = r.Seconds
}
return res, nil
}
// 批量获取用户上麦时长
// @return userId->seconds
func MGetUserOnMicSecondsRange(model *domain.Model, beginDate, endDate string, tz timezone_e.Timezone, userIds []uint64) (map[mysql.ID]mysql.Num, error) {
var rows []UserOnMic
res := make(map[mysql.ID]mysql.Num)
if err := model.DB().Model(UserOnMic{}).Where("`date` >= ? AND `date` <= ? AND tz = ? AND user_id in ?", beginDate, endDate, tz, userIds).Find(&rows).Error; err != nil {
model.Log.Errorf("MGetUserOnMic fail:%v", err)
return res, err
}
for _, r := range rows {
res[r.UserId] = r.Seconds
}
return res, nil
}