徽章
This commit is contained in:
parent
0d8e6f599b
commit
8ace95f78f
@ -21,6 +21,7 @@ func (UserBadgeBackpack) TableName() string { return "user_badge_backpack" }
|
||||
type SysBadgeConfig struct {
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
Type string `gorm:"column:type;size:64"`
|
||||
DisplayType string `gorm:"column:display_type;size:16"`
|
||||
BadgeLevel int `gorm:"column:badge_level"`
|
||||
Milestone int64 `gorm:"column:milestone"`
|
||||
BadgeName string `gorm:"column:badge_name;size:128"`
|
||||
|
||||
@ -16,6 +16,7 @@ import (
|
||||
type badgePictureRow struct {
|
||||
BadgeID int64 `gorm:"column:badge_id"`
|
||||
SourceType sql.NullString `gorm:"column:source_type"`
|
||||
DisplayType sql.NullString `gorm:"column:display_type"`
|
||||
BadgeLevel sql.NullInt64 `gorm:"column:badge_level"`
|
||||
Milestone sql.NullInt64 `gorm:"column:milestone"`
|
||||
BadgeName sql.NullString `gorm:"column:badge_name"`
|
||||
@ -56,14 +57,16 @@ func (s *Service) Other(ctx context.Context, viewer AuthUser, targetUserID int64
|
||||
|
||||
func (s *Service) currentForUser(ctx context.Context, sysOrigin string, userID int64) (*CurrentBadgeListResponse, error) {
|
||||
now := s.now()
|
||||
longBadges, vipBadgeID, err := s.loadLongBadges(ctx, sysOrigin, userID, now)
|
||||
vipLongBadges, vipShortBadges, vipBadgeIDs, err := s.loadVIPStateBadges(ctx, sysOrigin, userID, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
shortBadges, err := s.loadShortBadges(ctx, sysOrigin, userID, vipBadgeID, now)
|
||||
backpackLongBadges, backpackShortBadges, err := s.loadBackpackBadges(ctx, sysOrigin, userID, vipBadgeIDs, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
longBadges := append(vipLongBadges, backpackLongBadges...)
|
||||
shortBadges := append(vipShortBadges, backpackShortBadges...)
|
||||
|
||||
badges := make([]CurrentBadgeItem, 0, len(longBadges)+len(shortBadges))
|
||||
badges = append(badges, longBadges...)
|
||||
@ -78,57 +81,90 @@ func (s *Service) currentForUser(ctx context.Context, sysOrigin string, userID i
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *Service) loadLongBadges(ctx context.Context, sysOrigin string, userID int64, now time.Time) ([]CurrentBadgeItem, int64, error) {
|
||||
func (s *Service) loadVIPStateBadges(ctx context.Context, sysOrigin string, userID int64, now time.Time) ([]CurrentBadgeItem, []CurrentBadgeItem, map[int64]struct{}, error) {
|
||||
var state model.UserVipState
|
||||
err := s.db.WithContext(ctx).
|
||||
Where("sys_origin = ? AND user_id = ?", sysOrigin, userID).
|
||||
First(&state).Error
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []CurrentBadgeItem{}, 0, nil
|
||||
return []CurrentBadgeItem{}, []CurrentBadgeItem{}, nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
if !isActiveVIPState(state, now) || state.BadgeResourceID <= 0 {
|
||||
return []CurrentBadgeItem{}, 0, nil
|
||||
if !isActiveVIPState(state, now) {
|
||||
return []CurrentBadgeItem{}, []CurrentBadgeItem{}, nil, nil
|
||||
}
|
||||
|
||||
row, err := s.loadBadgePicture(ctx, sysOrigin, state.BadgeResourceID)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
type vipStateBadgeResource struct {
|
||||
id int64
|
||||
defaultType string
|
||||
name string
|
||||
url string
|
||||
}
|
||||
item := CurrentBadgeItem{
|
||||
ID: formatID(state.BadgeResourceID),
|
||||
BadgeID: formatID(state.BadgeResourceID),
|
||||
Type: badgeDisplayTypeLong,
|
||||
SourceType: badgeSourceTypeVIP,
|
||||
BadgeLevel: nullInt(row.BadgeLevel),
|
||||
BadgeKey: nullString(row.BadgeKey),
|
||||
Level: state.Level,
|
||||
LevelCode: state.LevelCode,
|
||||
DisplayName: state.DisplayName,
|
||||
Use: true,
|
||||
ExpireTime: formatMillis(state.ExpireAt),
|
||||
ExpireAt: formatTime(state.ExpireAt),
|
||||
UpdateTime: formatMillis(firstNonZeroTime(state.UpdateTime, state.StartAt, state.CreateTime)),
|
||||
UpdatedAt: formatTime(firstNonZeroTime(state.UpdateTime, state.StartAt, state.CreateTime)),
|
||||
resources := []vipStateBadgeResource{
|
||||
{id: state.BadgeResourceID, defaultType: badgeDisplayTypeLong, name: state.BadgeName, url: state.BadgeURL},
|
||||
{id: state.ShortBadgeResourceID, defaultType: badgeDisplayTypeShort, name: state.ShortBadgeName, url: state.ShortBadgeURL},
|
||||
}
|
||||
item.BadgeName = firstNonEmpty(nullString(row.BadgeName), state.BadgeName, state.DisplayName)
|
||||
item.Name = item.BadgeName
|
||||
item.SelectURL = firstNonEmpty(nullString(row.SelectURL), state.BadgeURL)
|
||||
item.NotSelectURL = nullString(row.NotSelectURL)
|
||||
item.AnimationURL = nullString(row.AnimationURL)
|
||||
item.URL = firstNonEmpty(item.SelectURL, state.BadgeURL)
|
||||
if row.Milestone.Valid && row.Milestone.Int64 > 0 {
|
||||
item.Milestone = formatID(row.Milestone.Int64)
|
||||
|
||||
longBadges := make([]CurrentBadgeItem, 0, 1)
|
||||
shortBadges := make([]CurrentBadgeItem, 0, 1)
|
||||
excludeIDs := make(map[int64]struct{}, len(resources))
|
||||
updateAt := firstNonZeroTime(state.UpdateTime, state.StartAt, state.CreateTime)
|
||||
for _, resource := range resources {
|
||||
if resource.id <= 0 {
|
||||
continue
|
||||
}
|
||||
if _, exists := excludeIDs[resource.id]; exists {
|
||||
continue
|
||||
}
|
||||
excludeIDs[resource.id] = struct{}{}
|
||||
row, err := s.loadBadgePicture(ctx, sysOrigin, resource.id)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
displayType := normalizeBadgeDisplayType(nullString(row.DisplayType), nullString(row.SourceType), resource.defaultType)
|
||||
if displayType == "" {
|
||||
continue
|
||||
}
|
||||
item := CurrentBadgeItem{
|
||||
ID: formatID(resource.id),
|
||||
BadgeID: formatID(resource.id),
|
||||
Type: displayType,
|
||||
SourceType: nullString(row.SourceType),
|
||||
BadgeLevel: nullInt(row.BadgeLevel),
|
||||
BadgeKey: nullString(row.BadgeKey),
|
||||
Level: state.Level,
|
||||
LevelCode: state.LevelCode,
|
||||
DisplayName: state.DisplayName,
|
||||
Use: true,
|
||||
ExpireTime: formatMillis(state.ExpireAt),
|
||||
ExpireAt: formatTime(state.ExpireAt),
|
||||
UpdateTime: formatMillis(updateAt),
|
||||
UpdatedAt: formatTime(updateAt),
|
||||
}
|
||||
item.BadgeName = firstNonEmpty(nullString(row.BadgeName), resource.name, state.DisplayName)
|
||||
item.Name = item.BadgeName
|
||||
item.SelectURL = firstNonEmpty(nullString(row.SelectURL), resource.url)
|
||||
item.NotSelectURL = nullString(row.NotSelectURL)
|
||||
item.AnimationURL = nullString(row.AnimationURL)
|
||||
item.URL = firstNonEmpty(item.SelectURL, resource.url)
|
||||
if row.Milestone.Valid && row.Milestone.Int64 > 0 {
|
||||
item.Milestone = formatID(row.Milestone.Int64)
|
||||
}
|
||||
if item.Name == "" && item.URL == "" {
|
||||
continue
|
||||
}
|
||||
if displayType == badgeDisplayTypeLong {
|
||||
longBadges = append(longBadges, item)
|
||||
} else {
|
||||
shortBadges = append(shortBadges, item)
|
||||
}
|
||||
}
|
||||
if item.Name == "" && item.URL == "" {
|
||||
return []CurrentBadgeItem{}, state.BadgeResourceID, nil
|
||||
}
|
||||
return []CurrentBadgeItem{item}, state.BadgeResourceID, nil
|
||||
return longBadges, shortBadges, excludeIDs, nil
|
||||
}
|
||||
|
||||
func (s *Service) loadShortBadges(ctx context.Context, sysOrigin string, userID int64, excludeBadgeID int64, now time.Time) ([]CurrentBadgeItem, error) {
|
||||
func (s *Service) loadBackpackBadges(ctx context.Context, sysOrigin string, userID int64, excludeBadgeIDs map[int64]struct{}, now time.Time) ([]CurrentBadgeItem, []CurrentBadgeItem, error) {
|
||||
rows := make([]badgePictureRow, 0)
|
||||
query := s.db.WithContext(ctx).
|
||||
Table("user_badge_backpack AS backpack").
|
||||
@ -137,6 +173,7 @@ func (s *Service) loadShortBadges(ctx context.Context, sysOrigin string, userID
|
||||
backpack.expire_time AS expire_time,
|
||||
backpack.update_time AS update_time,
|
||||
config.type AS source_type,
|
||||
config.display_type AS display_type,
|
||||
config.badge_level AS badge_level,
|
||||
config.milestone AS milestone,
|
||||
config.badge_name AS badge_name,
|
||||
@ -150,22 +187,30 @@ func (s *Service) loadShortBadges(ctx context.Context, sysOrigin string, userID
|
||||
Where("backpack.user_id = ?", userID).
|
||||
Where("backpack.is_use_props = ?", true).
|
||||
Where("config.is_del = ?", false).
|
||||
Where("config.type IN ?", []string{badgeSourceTypeActivity, badgeSourceTypeAchievement}).
|
||||
Where("(backpack.expire_type = ? OR backpack.expire_time > ?)", expireTypePermanent, now).
|
||||
Order("backpack.update_time DESC, backpack.id DESC")
|
||||
if excludeBadgeID > 0 {
|
||||
query = query.Where("backpack.badge_id <> ?", excludeBadgeID)
|
||||
if len(excludeBadgeIDs) > 0 {
|
||||
ids := make([]int64, 0, len(excludeBadgeIDs))
|
||||
for id := range excludeBadgeIDs {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
query = query.Where("backpack.badge_id NOT IN ?", ids)
|
||||
}
|
||||
if err := query.Scan(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
items := make([]CurrentBadgeItem, 0, len(rows))
|
||||
longBadges := make([]CurrentBadgeItem, 0)
|
||||
shortBadges := make([]CurrentBadgeItem, 0, len(rows))
|
||||
for _, row := range rows {
|
||||
displayType := normalizeBadgeDisplayType(nullString(row.DisplayType), nullString(row.SourceType), "")
|
||||
if displayType == "" {
|
||||
continue
|
||||
}
|
||||
item := CurrentBadgeItem{
|
||||
ID: formatID(row.BadgeID),
|
||||
BadgeID: formatID(row.BadgeID),
|
||||
Type: badgeDisplayTypeShort,
|
||||
Type: displayType,
|
||||
SourceType: nullString(row.SourceType),
|
||||
Name: nullString(row.BadgeName),
|
||||
BadgeName: nullString(row.BadgeName),
|
||||
@ -184,9 +229,13 @@ func (s *Service) loadShortBadges(ctx context.Context, sysOrigin string, userID
|
||||
if row.Milestone.Valid && row.Milestone.Int64 > 0 {
|
||||
item.Milestone = formatID(row.Milestone.Int64)
|
||||
}
|
||||
items = append(items, item)
|
||||
if displayType == badgeDisplayTypeLong {
|
||||
longBadges = append(longBadges, item)
|
||||
} else {
|
||||
shortBadges = append(shortBadges, item)
|
||||
}
|
||||
}
|
||||
return items, nil
|
||||
return longBadges, shortBadges, nil
|
||||
}
|
||||
|
||||
func (s *Service) loadBadgePicture(ctx context.Context, sysOrigin string, badgeID int64) (badgePictureRow, error) {
|
||||
@ -196,6 +245,7 @@ func (s *Service) loadBadgePicture(ctx context.Context, sysOrigin string, badgeI
|
||||
Select(`
|
||||
config.id AS badge_id,
|
||||
config.type AS source_type,
|
||||
config.display_type AS display_type,
|
||||
config.badge_level AS badge_level,
|
||||
config.milestone AS milestone,
|
||||
config.badge_name AS badge_name,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user