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