package model import ( "context" "encoding/json" "fmt" "github.com/go-redis/redis/v8" "gorm.io/gorm" "samba/pkg/log" "samba/pkg/xtime" "samba/proto" "samba/stub" "samba/util/rdbkey" ) type UserInfo struct { UID int64 `gorm:"column:uid" json:"uid"` UType int `gorm:"column:utype" json:"utype"` // 用户类型,1-游客2-FB API int `gorm:"column:api" json:"api"` SItemID string `gorm:"column:sitemid" json:"sitemid"` Device string `gorm:"column:device" json:"device"` MNick string `gorm:"column:mnick" json:"mnick"` // 昵称 Sex int `gorm:"column:sex" json:"sex"` // 性别 HeadURL string `gorm:"column:head_url" json:"head_url"` // 头像 IconId int `gorm:"column:iconid" json:"iconid"` // 系统头像 MTime int64 `gorm:"column:mtime" json:"mtime"` Phone string `gorm:"column:phone" json:"phone"` Address string `gorm:"column:address" json:"address"` MStatus int `gorm:"column:mstatus" json:"mstatus"` // 状态,1-封号,0-正常 UTMSource int `gorm:"column:utm_source" json:"utm_source"` AvatarFrame int `gorm:"column:avatar_frame" json:"avatar_frame"` // 头像框 TakeCoin int64 `gorm:"-" json:"-"` // 携带金币 TakeClubCoin int64 `gorm:"-" json:"-"` // 携带俱乐部币 Region string `gorm:"column:region" json:"region"` // 手机地区码 Location string `gorm:"column:location" json:"location"` // 定位信息 Bandesc string `gorm:"column:bandesc" json:"bandesc"` // 封禁备注 Bankrupt int `gorm:"column:bankrupt" json:"bankrupt"` // 破产补贴已领取次数 BankruptTime int `gorm:"column:bankrupt_time" json:"bankrupt_time"` // 最后一次破产领取时间 } func (t *UserInfo) TableName() string { return "t_user_info" } type UserInfoOp struct { rdb *redis.Client db *gorm.DB } func NewUserInfoOp() *UserInfoOp { return &UserInfoOp{rdb: rdbBaseInfo, db: userDB} } func (op *UserInfoOp) Count() (count int64, err error) { err = op.db.Model(&UserInfo{}).Count(&count).Error return count, err } func (op *UserInfoOp) Load(uid int64) (*UserInfo, error) { var user UserInfo val, err := op.rdb.Get(context.Background(), rdbkey.BaseUserKey(uid)).Result() if err == nil { err = json.Unmarshal([]byte(val), &user) user.TakeCoin = 0 if err == nil { return &user, nil } } log.Error(fmt.Sprintf("Load user info err:%v. key:%v", err.Error(), rdbkey.BaseUserKey(uid))) result := op.db.Where("uid = ?", uid).First(&user) if result.Error != nil { return nil, result.Error } // 回写redis var bytesUser []byte bytesUser, err = json.Marshal(&user) if err != nil { return nil, err } //log.Debug(string(bytesUser)) err = op.rdb.Set(context.Background(), rdbkey.BaseUserKey(uid), bytesUser, redis30day).Err() if err != nil { log.Error(fmt.Sprintf("set user info err:%v. key:%v", err.Error(), rdbkey.BaseUserKey(uid))) } return &user, result.Error } func (op *UserInfoOp) LoadFromRedis(uid int64) (*UserInfo, error) { var user UserInfo val, err := op.rdb.Get(context.Background(), rdbkey.BaseUserKey(uid)).Result() if err == nil { err = json.Unmarshal([]byte(val), &user) if err == nil { user.TakeCoin = 0 return &user, nil } } return nil, err } // UpdateBankruptCount 更新破产补贴领取次数 func (op *UserInfoOp) UpdateBankruptCount(uid int64, count int) error { err := op.db.Model(&UserInfo{}).Where("uid = ?", uid). Updates(map[string]any{ "bankrupt": count, "bankrupt_time": xtime.Now().Timestamp(), }). Error if err != nil { return err } // 回写redis var user UserInfo // 若数据库支持RETURNING操作,可以避免再次查询 err = op.db.Where("uid = ?", uid).First(&user).Error if err != nil { return err } b, err := json.Marshal(&user) if err != nil { return err } err = op.rdb.Set(context.Background(), rdbkey.BaseUserKey(uid), b, redis30day).Err() if err != nil { log.Error(fmt.Sprintf("set user info err:%v. key:%v", err.Error(), rdbkey.BaseUserKey(uid))) } return nil } // GetVipLevelByUserId uid对应的VIP等级 func GetVipLevelByUserId(uid int64) int { // TODO 根据userId获取对应的vip等级 return 0 } // NewBankruptNtfMsg 生成破产通知 func NewBankruptNtfMsg(uid int64) (*proto.NtfBankrupt, error) { uInfo, err := NewUserInfoOp().Load(uid) if err != nil { return nil, err } if !xtime.IsTodayTimestamp(uInfo.BankruptTime) { // 时间戳非今天,重置为0 uInfo.Bankrupt = 0 } brConf := stub.GetBankruptConf(GetVipLevelByUserId(uid)) log.Debug(fmt.Sprintf("破产通知 uid:%d, 当日已领:%d, 免费补贴次数:%d, 补贴金额:%d", uInfo.UID, uInfo.Bankrupt, brConf.FreeCount, brConf.Quota)) return &proto.NtfBankrupt{ UsedSubsidyCount: uInfo.Bankrupt, SubsidyCount: brConf.FreeCount, SubsidyAmount: int64(brConf.Quota), }, nil }