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 }) } // 增加用户上麦时长 // 事务操作 func IncrUserOnMicV2(model *domain.Model, userId mysql.ID) error { for _, tz := range timezone_e.Timezones { day := time.Now().In(timezone_e.TimezoneLocMap[tz]).Format("2006-01-02") 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 + ?", 60), }), }).Create(&UserOnMic{ Date: day, UserId: userId, Seconds: 60, Tz: tz, }).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 }