package model import ( "context" "git.noahlan.cn/northlan/ntools-go/gorm-zero/gormx" "git.noahlan.cn/northlan/ntools-go/uuid" "github.com/jinzhu/now" "github.com/pkg/errors" "gorm.io/gorm" "live-service/common/nerr" "live-service/common/timex" "time" ) var _ UserTitleModel = (*customUserTitleModel)(nil) const ( TitleTypeDefault = "default" // 默认类型 可购买 TitleTypeRank = "rank" // 排行榜类型 不可购买 TitleTypeCustom = "custom" // 自定义类型 不可购买 ) type ( // UserTitleModel is an interface to be customized, add more methods here, // and implement the added methods in customUserTitleModel. UserTitleModel interface { userTitleModel // FindMaxSort 寻找当前用户的最大Sort 最小值2 FindMaxSort(ctx context.Context, tx *gorm.DB, userId int64) int64 // FindOneByUserIdSort 通过用户和排序号找寻称号 FindOneByUserIdSort(ctx context.Context, tx *gorm.DB, userId int64, sort int64) (*UserTitle, error) // FindByUserId 查找用户所有列表,按sort升序排列 FindByUserId(ctx context.Context, tx *gorm.DB, userId int64) ([]UserTitle, error) // Addon 添加新的或延长时间 Addon(ctx context.Context, tx *gorm.DB, userId, titleId int64, titleType string, duration time.Duration, forever bool) error } customUserTitleModel struct { *defaultUserTitleModel } ) // NewUserTitleModel returns a model for the database table. func NewUserTitleModel(conn *gorm.DB) UserTitleModel { return &customUserTitleModel{ defaultUserTitleModel: newUserTitleModel(conn), } } func (m *customUserTitleModel) FindMaxSort(ctx context.Context, tx *gorm.DB, userId int64) int64 { db := gormx.WithTx(ctx, m.DB, tx) var resp int64 = 0 db.Table(m.table). Select("MAX(sort)"). Where("user_id = ?", userId).Take(&resp) return resp } func (m *customUserTitleModel) FindOneByUserIdSort(ctx context.Context, tx *gorm.DB, userId int64, sort int64) (*UserTitle, error) { db := gormx.WithTx(ctx, m.DB, tx) var resp UserTitle err := db.Model(&UserTitle{}). Where("user_id = ? and sort = ?", userId, sort).Take(&resp).Error err = gormx.WrapSelectErr(err) if err != nil { return nil, err } return &resp, nil } func (m *customUserTitleModel) FindByUserId(ctx context.Context, tx *gorm.DB, userId int64) ([]UserTitle, error) { var resp []UserTitle err := gormx.WithTx(ctx, m.DB, tx).Table(m.table). Where("user_id = ?", userId). Order("sort asc").Find(&resp).Error err = gormx.WrapSelectErr(err) if err != nil { return nil, err } return resp, nil } func (m *customUserTitleModel) Addon(ctx context.Context, tx *gorm.DB, userId, titleId int64, titleType string, duration time.Duration, forever bool) error { return m.TransactCtx(ctx, tx, func(tx *gorm.DB) error { userTitle, err := m.FindOneByUserIdTitleId(ctx, tx, userId, titleId) if err != nil { if !errors.Is(err, gormx.ErrNotFound) { return nerr.NewWithCode(nerr.DBError) } } today := now.BeginningOfDay() if userTitle == nil { // sort maxSort := m.FindMaxSort(ctx, tx, userId) err = m.Insert(ctx, tx, &UserTitle{ Id: uuid.NextId(), UserId: userId, TitleId: titleId, Sort: maxSort + 1, Type: titleType, Forever: BitBool(forever), StartTime: today, EndTime: today.Add(duration), }) if err != nil { return nerr.NewWithCode(nerr.DBError) } } else { // update if !timex.DayExpire(today, userTitle.EndTime, bool(userTitle.Forever)) { // 未过期,endTime直接添加1day userTitle.EndTime = userTitle.EndTime.Add(duration) err = m.Update(ctx, tx, userTitle) if err != nil { return nerr.NewWithCode(nerr.DBError) } } else { // 过期,更新日期 err = m.Update(ctx, tx, &UserTitle{ Id: userTitle.Id, UserId: userId, TitleId: titleId, Sort: userTitle.Sort, Type: titleType, Forever: BitBool(forever), StartTime: today, EndTime: today.Add(duration), }) if err != nil { return nerr.NewWithCode(nerr.DBError) } } } return nil }) }