feat: add VIP badge card resources
This commit is contained in:
parent
6a0ae4793b
commit
0d8e6f599b
@ -4,31 +4,40 @@ import "time"
|
||||
|
||||
// VipLevelConfig stores the operator-managed 30-day VIP level configuration.
|
||||
type VipLevelConfig struct {
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_vip_level_config,priority:1;index:idx_vip_level_config_sys_origin,priority:1"`
|
||||
Level int `gorm:"column:level;uniqueIndex:uk_vip_level_config,priority:2"`
|
||||
LevelCode string `gorm:"column:level_code;size:16"`
|
||||
DisplayName string `gorm:"column:display_name;size:64"`
|
||||
Enabled bool `gorm:"column:enabled"`
|
||||
DurationDays int `gorm:"column:duration_days"`
|
||||
PriceGold int64 `gorm:"column:price_gold"`
|
||||
BadgeResourceID int64 `gorm:"column:badge_resource_id"`
|
||||
BadgeName string `gorm:"column:badge_name;size:128"`
|
||||
BadgeURL string `gorm:"column:badge_url;size:512"`
|
||||
AvatarFrameResourceID int64 `gorm:"column:avatar_frame_resource_id"`
|
||||
AvatarFrameName string `gorm:"column:avatar_frame_name;size:128"`
|
||||
AvatarFrameURL string `gorm:"column:avatar_frame_url;size:512"`
|
||||
EntryEffectResourceID int64 `gorm:"column:entry_effect_resource_id"`
|
||||
EntryEffectName string `gorm:"column:entry_effect_name;size:128"`
|
||||
EntryEffectURL string `gorm:"column:entry_effect_url;size:512"`
|
||||
ChatBubbleResourceID int64 `gorm:"column:chat_bubble_resource_id"`
|
||||
ChatBubbleName string `gorm:"column:chat_bubble_name;size:128"`
|
||||
ChatBubbleURL string `gorm:"column:chat_bubble_url;size:512"`
|
||||
FloatPictureResourceID int64 `gorm:"column:float_picture_resource_id"`
|
||||
FloatPictureName string `gorm:"column:float_picture_name;size:128"`
|
||||
FloatPictureURL string `gorm:"column:float_picture_url;size:512"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
UpdateTime time.Time `gorm:"column:update_time"`
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_vip_level_config,priority:1;index:idx_vip_level_config_sys_origin,priority:1"`
|
||||
Level int `gorm:"column:level;uniqueIndex:uk_vip_level_config,priority:2"`
|
||||
LevelCode string `gorm:"column:level_code;size:16"`
|
||||
DisplayName string `gorm:"column:display_name;size:64"`
|
||||
Enabled bool `gorm:"column:enabled"`
|
||||
DurationDays int `gorm:"column:duration_days"`
|
||||
PriceGold int64 `gorm:"column:price_gold"`
|
||||
BadgeResourceID int64 `gorm:"column:badge_resource_id"`
|
||||
BadgeName string `gorm:"column:badge_name;size:128"`
|
||||
BadgeURL string `gorm:"column:badge_url;size:512"`
|
||||
ShortBadgeResourceID int64 `gorm:"column:short_badge_resource_id"`
|
||||
ShortBadgeName string `gorm:"column:short_badge_name;size:128"`
|
||||
ShortBadgeURL string `gorm:"column:short_badge_url;size:512"`
|
||||
AvatarFrameResourceID int64 `gorm:"column:avatar_frame_resource_id"`
|
||||
AvatarFrameName string `gorm:"column:avatar_frame_name;size:128"`
|
||||
AvatarFrameURL string `gorm:"column:avatar_frame_url;size:512"`
|
||||
EntryEffectResourceID int64 `gorm:"column:entry_effect_resource_id"`
|
||||
EntryEffectName string `gorm:"column:entry_effect_name;size:128"`
|
||||
EntryEffectURL string `gorm:"column:entry_effect_url;size:512"`
|
||||
ChatBubbleResourceID int64 `gorm:"column:chat_bubble_resource_id"`
|
||||
ChatBubbleName string `gorm:"column:chat_bubble_name;size:128"`
|
||||
ChatBubbleURL string `gorm:"column:chat_bubble_url;size:512"`
|
||||
FloatPictureResourceID int64 `gorm:"column:float_picture_resource_id"`
|
||||
FloatPictureName string `gorm:"column:float_picture_name;size:128"`
|
||||
FloatPictureURL string `gorm:"column:float_picture_url;size:512"`
|
||||
BackgroundCardResourceID int64 `gorm:"column:background_card_resource_id"`
|
||||
BackgroundCardName string `gorm:"column:background_card_name;size:128"`
|
||||
BackgroundCardURL string `gorm:"column:background_card_url;size:512"`
|
||||
EffectImageResourceID int64 `gorm:"column:effect_image_resource_id"`
|
||||
EffectImageName string `gorm:"column:effect_image_name;size:128"`
|
||||
EffectImageURL string `gorm:"column:effect_image_url;size:512"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
UpdateTime time.Time `gorm:"column:update_time"`
|
||||
}
|
||||
|
||||
// TableName returns the VIP level config table name.
|
||||
@ -36,32 +45,41 @@ func (VipLevelConfig) TableName() string { return "vip_level_config" }
|
||||
|
||||
// UserVipState stores the single active VIP state for a user.
|
||||
type UserVipState struct {
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_user_vip_state,priority:1;index:idx_user_vip_state_lookup,priority:1"`
|
||||
UserID int64 `gorm:"column:user_id;uniqueIndex:uk_user_vip_state,priority:2;index:idx_user_vip_state_lookup,priority:2"`
|
||||
Level int `gorm:"column:level"`
|
||||
LevelCode string `gorm:"column:level_code;size:16"`
|
||||
DisplayName string `gorm:"column:display_name;size:64"`
|
||||
Status string `gorm:"column:status;size:32;index:idx_user_vip_state_lookup,priority:3"`
|
||||
StartAt time.Time `gorm:"column:start_at"`
|
||||
ExpireAt time.Time `gorm:"column:expire_at;index:idx_user_vip_expire"`
|
||||
BadgeResourceID int64 `gorm:"column:badge_resource_id"`
|
||||
BadgeName string `gorm:"column:badge_name;size:128"`
|
||||
BadgeURL string `gorm:"column:badge_url;size:512"`
|
||||
AvatarFrameResourceID int64 `gorm:"column:avatar_frame_resource_id"`
|
||||
AvatarFrameName string `gorm:"column:avatar_frame_name;size:128"`
|
||||
AvatarFrameURL string `gorm:"column:avatar_frame_url;size:512"`
|
||||
EntryEffectResourceID int64 `gorm:"column:entry_effect_resource_id"`
|
||||
EntryEffectName string `gorm:"column:entry_effect_name;size:128"`
|
||||
EntryEffectURL string `gorm:"column:entry_effect_url;size:512"`
|
||||
ChatBubbleResourceID int64 `gorm:"column:chat_bubble_resource_id"`
|
||||
ChatBubbleName string `gorm:"column:chat_bubble_name;size:128"`
|
||||
ChatBubbleURL string `gorm:"column:chat_bubble_url;size:512"`
|
||||
FloatPictureResourceID int64 `gorm:"column:float_picture_resource_id"`
|
||||
FloatPictureName string `gorm:"column:float_picture_name;size:128"`
|
||||
FloatPictureURL string `gorm:"column:float_picture_url;size:512"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
UpdateTime time.Time `gorm:"column:update_time"`
|
||||
ID int64 `gorm:"column:id;primaryKey"`
|
||||
SysOrigin string `gorm:"column:sys_origin;size:32;uniqueIndex:uk_user_vip_state,priority:1;index:idx_user_vip_state_lookup,priority:1"`
|
||||
UserID int64 `gorm:"column:user_id;uniqueIndex:uk_user_vip_state,priority:2;index:idx_user_vip_state_lookup,priority:2"`
|
||||
Level int `gorm:"column:level"`
|
||||
LevelCode string `gorm:"column:level_code;size:16"`
|
||||
DisplayName string `gorm:"column:display_name;size:64"`
|
||||
Status string `gorm:"column:status;size:32;index:idx_user_vip_state_lookup,priority:3"`
|
||||
StartAt time.Time `gorm:"column:start_at"`
|
||||
ExpireAt time.Time `gorm:"column:expire_at;index:idx_user_vip_expire"`
|
||||
BadgeResourceID int64 `gorm:"column:badge_resource_id"`
|
||||
BadgeName string `gorm:"column:badge_name;size:128"`
|
||||
BadgeURL string `gorm:"column:badge_url;size:512"`
|
||||
ShortBadgeResourceID int64 `gorm:"column:short_badge_resource_id"`
|
||||
ShortBadgeName string `gorm:"column:short_badge_name;size:128"`
|
||||
ShortBadgeURL string `gorm:"column:short_badge_url;size:512"`
|
||||
AvatarFrameResourceID int64 `gorm:"column:avatar_frame_resource_id"`
|
||||
AvatarFrameName string `gorm:"column:avatar_frame_name;size:128"`
|
||||
AvatarFrameURL string `gorm:"column:avatar_frame_url;size:512"`
|
||||
EntryEffectResourceID int64 `gorm:"column:entry_effect_resource_id"`
|
||||
EntryEffectName string `gorm:"column:entry_effect_name;size:128"`
|
||||
EntryEffectURL string `gorm:"column:entry_effect_url;size:512"`
|
||||
ChatBubbleResourceID int64 `gorm:"column:chat_bubble_resource_id"`
|
||||
ChatBubbleName string `gorm:"column:chat_bubble_name;size:128"`
|
||||
ChatBubbleURL string `gorm:"column:chat_bubble_url;size:512"`
|
||||
FloatPictureResourceID int64 `gorm:"column:float_picture_resource_id"`
|
||||
FloatPictureName string `gorm:"column:float_picture_name;size:128"`
|
||||
FloatPictureURL string `gorm:"column:float_picture_url;size:512"`
|
||||
BackgroundCardResourceID int64 `gorm:"column:background_card_resource_id"`
|
||||
BackgroundCardName string `gorm:"column:background_card_name;size:128"`
|
||||
BackgroundCardURL string `gorm:"column:background_card_url;size:512"`
|
||||
EffectImageResourceID int64 `gorm:"column:effect_image_resource_id"`
|
||||
EffectImageName string `gorm:"column:effect_image_name;size:128"`
|
||||
EffectImageURL string `gorm:"column:effect_image_url;size:512"`
|
||||
CreateTime time.Time `gorm:"column:create_time"`
|
||||
UpdateTime time.Time `gorm:"column:update_time"`
|
||||
}
|
||||
|
||||
// TableName returns the user VIP state table name.
|
||||
|
||||
@ -105,7 +105,7 @@ func (s *Service) PageUserStates(
|
||||
Find(&rows).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
resourceIDs := make([]int64, 0, len(rows)*5)
|
||||
resourceIDs := make([]int64, 0, len(rows)*8)
|
||||
for idx := range rows {
|
||||
resourceIDs = appendResourceIDsFromState(resourceIDs, &rows[idx])
|
||||
}
|
||||
@ -133,26 +133,35 @@ func (s *Service) PageUserOrders(ctx context.Context, user AuthUser, cursor int,
|
||||
|
||||
func (s *Service) expireDueStates(ctx context.Context, sysOrigin string, now time.Time) error {
|
||||
updates := map[string]any{
|
||||
"level": 0,
|
||||
"level_code": "",
|
||||
"display_name": "",
|
||||
"status": statusExpired,
|
||||
"badge_resource_id": 0,
|
||||
"badge_name": "",
|
||||
"badge_url": "",
|
||||
"avatar_frame_resource_id": 0,
|
||||
"avatar_frame_name": "",
|
||||
"avatar_frame_url": "",
|
||||
"entry_effect_resource_id": 0,
|
||||
"entry_effect_name": "",
|
||||
"entry_effect_url": "",
|
||||
"chat_bubble_resource_id": 0,
|
||||
"chat_bubble_name": "",
|
||||
"chat_bubble_url": "",
|
||||
"float_picture_resource_id": 0,
|
||||
"float_picture_name": "",
|
||||
"float_picture_url": "",
|
||||
"update_time": now,
|
||||
"level": 0,
|
||||
"level_code": "",
|
||||
"display_name": "",
|
||||
"status": statusExpired,
|
||||
"badge_resource_id": 0,
|
||||
"badge_name": "",
|
||||
"badge_url": "",
|
||||
"short_badge_resource_id": 0,
|
||||
"short_badge_name": "",
|
||||
"short_badge_url": "",
|
||||
"avatar_frame_resource_id": 0,
|
||||
"avatar_frame_name": "",
|
||||
"avatar_frame_url": "",
|
||||
"entry_effect_resource_id": 0,
|
||||
"entry_effect_name": "",
|
||||
"entry_effect_url": "",
|
||||
"chat_bubble_resource_id": 0,
|
||||
"chat_bubble_name": "",
|
||||
"chat_bubble_url": "",
|
||||
"float_picture_resource_id": 0,
|
||||
"float_picture_name": "",
|
||||
"float_picture_url": "",
|
||||
"background_card_resource_id": 0,
|
||||
"background_card_name": "",
|
||||
"background_card_url": "",
|
||||
"effect_image_resource_id": 0,
|
||||
"effect_image_name": "",
|
||||
"effect_image_url": "",
|
||||
"update_time": now,
|
||||
}
|
||||
return s.db.WithContext(ctx).
|
||||
Model(&model.UserVipState{}).
|
||||
|
||||
@ -477,6 +477,9 @@ func applyPlanToState(state *model.UserVipState, plan purchasePlan, now time.Tim
|
||||
state.BadgeResourceID = plan.TargetConfig.BadgeResourceID
|
||||
state.BadgeName = ""
|
||||
state.BadgeURL = ""
|
||||
state.ShortBadgeResourceID = plan.TargetConfig.ShortBadgeResourceID
|
||||
state.ShortBadgeName = ""
|
||||
state.ShortBadgeURL = ""
|
||||
state.AvatarFrameResourceID = plan.TargetConfig.AvatarFrameResourceID
|
||||
state.AvatarFrameName = ""
|
||||
state.AvatarFrameURL = ""
|
||||
@ -489,6 +492,12 @@ func applyPlanToState(state *model.UserVipState, plan purchasePlan, now time.Tim
|
||||
state.FloatPictureResourceID = plan.TargetConfig.FloatPictureResourceID
|
||||
state.FloatPictureName = ""
|
||||
state.FloatPictureURL = ""
|
||||
state.BackgroundCardResourceID = plan.TargetConfig.BackgroundCardResourceID
|
||||
state.BackgroundCardName = ""
|
||||
state.BackgroundCardURL = ""
|
||||
state.EffectImageResourceID = plan.TargetConfig.EffectImageResourceID
|
||||
state.EffectImageName = ""
|
||||
state.EffectImageURL = ""
|
||||
state.UpdateTime = now
|
||||
if state.CreateTime.IsZero() {
|
||||
state.CreateTime = now
|
||||
@ -503,6 +512,9 @@ func expireState(state *model.UserVipState, now time.Time) {
|
||||
state.BadgeResourceID = 0
|
||||
state.BadgeName = ""
|
||||
state.BadgeURL = ""
|
||||
state.ShortBadgeResourceID = 0
|
||||
state.ShortBadgeName = ""
|
||||
state.ShortBadgeURL = ""
|
||||
state.AvatarFrameResourceID = 0
|
||||
state.AvatarFrameName = ""
|
||||
state.AvatarFrameURL = ""
|
||||
@ -515,6 +527,12 @@ func expireState(state *model.UserVipState, now time.Time) {
|
||||
state.FloatPictureResourceID = 0
|
||||
state.FloatPictureName = ""
|
||||
state.FloatPictureURL = ""
|
||||
state.BackgroundCardResourceID = 0
|
||||
state.BackgroundCardName = ""
|
||||
state.BackgroundCardURL = ""
|
||||
state.EffectImageResourceID = 0
|
||||
state.EffectImageName = ""
|
||||
state.EffectImageURL = ""
|
||||
state.UpdateTime = now
|
||||
}
|
||||
|
||||
@ -643,10 +661,12 @@ func (s *Service) alignVIPResourceExpireAt(ctx context.Context, userID int64, re
|
||||
func vipGrantResourcesFromConfig(config model.VipLevelConfig) []vipGrantResource {
|
||||
return compactVIPGrantResources([]vipGrantResource{
|
||||
{ResourceID: config.BadgeResourceID, Badge: true},
|
||||
{ResourceID: config.ShortBadgeResourceID, Badge: true},
|
||||
{ResourceID: config.AvatarFrameResourceID, PropsType: vipPropsTypeAvatarFrame},
|
||||
{ResourceID: config.EntryEffectResourceID, PropsType: vipPropsTypeRide},
|
||||
{ResourceID: config.ChatBubbleResourceID, PropsType: vipPropsTypeChatBubble},
|
||||
{ResourceID: config.FloatPictureResourceID, PropsType: vipPropsTypeFloatPicture},
|
||||
{ResourceID: config.BackgroundCardResourceID, PropsType: vipPropsTypeDataCard},
|
||||
})
|
||||
}
|
||||
|
||||
@ -656,10 +676,12 @@ func vipGrantResourcesFromState(state *model.UserVipState) []vipGrantResource {
|
||||
}
|
||||
return compactVIPGrantResources([]vipGrantResource{
|
||||
{ResourceID: state.BadgeResourceID, Badge: true},
|
||||
{ResourceID: state.ShortBadgeResourceID, Badge: true},
|
||||
{ResourceID: state.AvatarFrameResourceID, PropsType: vipPropsTypeAvatarFrame},
|
||||
{ResourceID: state.EntryEffectResourceID, PropsType: vipPropsTypeRide},
|
||||
{ResourceID: state.ChatBubbleResourceID, PropsType: vipPropsTypeChatBubble},
|
||||
{ResourceID: state.FloatPictureResourceID, PropsType: vipPropsTypeFloatPicture},
|
||||
{ResourceID: state.BackgroundCardResourceID, PropsType: vipPropsTypeDataCard},
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@ -120,11 +120,15 @@ func normalizeSaveLevels(levels []VipLevelPayload) ([]VipLevelPayload, error) {
|
||||
item.DisplayName = levelDisplayName(item.Level)
|
||||
}
|
||||
item.DurationDays = vipDurationDay
|
||||
item.Badge = normalizeResource(item.Badge)
|
||||
item.LongBadge = normalizeResource(firstResource(item.LongBadge, item.Badge))
|
||||
item.Badge = item.LongBadge
|
||||
item.ShortBadge = normalizeResource(item.ShortBadge)
|
||||
item.AvatarFrame = normalizeResource(item.AvatarFrame)
|
||||
item.EntryEffect = normalizeResource(item.EntryEffect)
|
||||
item.ChatBubble = normalizeResource(item.ChatBubble)
|
||||
item.FloatPicture = normalizeResource(item.FloatPicture)
|
||||
item.BackgroundCard = normalizeResource(item.BackgroundCard)
|
||||
item.EffectImage = normalizeResource(item.EffectImage)
|
||||
normalized = append(normalized, item)
|
||||
}
|
||||
|
||||
@ -159,6 +163,16 @@ func normalizeResource(resource VipResourcePayload) VipResourcePayload {
|
||||
return resource
|
||||
}
|
||||
|
||||
func firstResource(preferred VipResourcePayload, fallback VipResourcePayload) VipResourcePayload {
|
||||
if preferred.ResourceID.Int64() > 0 || strings.TrimSpace(preferred.Name) != "" ||
|
||||
strings.TrimSpace(preferred.URL) != "" || strings.TrimSpace(preferred.SourceURL) != "" ||
|
||||
strings.TrimSpace(preferred.ResourceURL) != "" || strings.TrimSpace(preferred.Cover) != "" ||
|
||||
strings.TrimSpace(preferred.CoverURL) != "" {
|
||||
return preferred
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
|
||||
func applyLevelPayloadToConfig(row *model.VipLevelConfig, item VipLevelPayload, now time.Time) {
|
||||
row.Level = item.Level
|
||||
row.LevelCode = levelCode(item.Level)
|
||||
@ -166,9 +180,12 @@ func applyLevelPayloadToConfig(row *model.VipLevelConfig, item VipLevelPayload,
|
||||
row.Enabled = item.Enabled
|
||||
row.DurationDays = vipDurationDay
|
||||
row.PriceGold = item.PriceGold
|
||||
row.BadgeResourceID = item.Badge.ResourceID.Int64()
|
||||
row.BadgeResourceID = item.LongBadge.ResourceID.Int64()
|
||||
row.BadgeName = ""
|
||||
row.BadgeURL = ""
|
||||
row.ShortBadgeResourceID = item.ShortBadge.ResourceID.Int64()
|
||||
row.ShortBadgeName = ""
|
||||
row.ShortBadgeURL = ""
|
||||
row.AvatarFrameResourceID = item.AvatarFrame.ResourceID.Int64()
|
||||
row.AvatarFrameName = ""
|
||||
row.AvatarFrameURL = ""
|
||||
@ -181,6 +198,12 @@ func applyLevelPayloadToConfig(row *model.VipLevelConfig, item VipLevelPayload,
|
||||
row.FloatPictureResourceID = item.FloatPicture.ResourceID.Int64()
|
||||
row.FloatPictureName = ""
|
||||
row.FloatPictureURL = ""
|
||||
row.BackgroundCardResourceID = item.BackgroundCard.ResourceID.Int64()
|
||||
row.BackgroundCardName = ""
|
||||
row.BackgroundCardURL = ""
|
||||
row.EffectImageResourceID = item.EffectImage.ResourceID.Int64()
|
||||
row.EffectImageName = ""
|
||||
row.EffectImageURL = ""
|
||||
row.UpdateTime = now
|
||||
if row.CreateTime.IsZero() {
|
||||
row.CreateTime = now
|
||||
|
||||
@ -166,30 +166,46 @@ func TestApplyPlanToStateKeepsOnlyResourceIDsAndPayloadUsesLookup(t *testing.T)
|
||||
ExpireAt: now.AddDate(0, 0, vipDurationDay),
|
||||
DurationDays: vipDurationDay,
|
||||
TargetConfig: model.VipLevelConfig{
|
||||
Level: 3,
|
||||
DisplayName: "VIP 3",
|
||||
AvatarFrameResourceID: 11,
|
||||
AvatarFrameName: "frame",
|
||||
AvatarFrameURL: "https://example.com/frame.svga",
|
||||
EntryEffectResourceID: 12,
|
||||
EntryEffectName: "ride",
|
||||
EntryEffectURL: "https://example.com/ride.svga",
|
||||
ChatBubbleResourceID: 13,
|
||||
ChatBubbleName: "bubble",
|
||||
ChatBubbleURL: "https://example.com/bubble.svga",
|
||||
FloatPictureResourceID: 14,
|
||||
FloatPictureName: "float",
|
||||
FloatPictureURL: "https://example.com/float.svga",
|
||||
Level: 3,
|
||||
DisplayName: "VIP 3",
|
||||
BadgeResourceID: 10,
|
||||
BadgeName: "long badge",
|
||||
BadgeURL: "https://example.com/long.png",
|
||||
ShortBadgeResourceID: 15,
|
||||
ShortBadgeName: "short badge",
|
||||
ShortBadgeURL: "https://example.com/short.png",
|
||||
AvatarFrameResourceID: 11,
|
||||
AvatarFrameName: "frame",
|
||||
AvatarFrameURL: "https://example.com/frame.svga",
|
||||
EntryEffectResourceID: 12,
|
||||
EntryEffectName: "ride",
|
||||
EntryEffectURL: "https://example.com/ride.svga",
|
||||
ChatBubbleResourceID: 13,
|
||||
ChatBubbleName: "bubble",
|
||||
ChatBubbleURL: "https://example.com/bubble.svga",
|
||||
FloatPictureResourceID: 14,
|
||||
FloatPictureName: "float",
|
||||
FloatPictureURL: "https://example.com/float.svga",
|
||||
BackgroundCardResourceID: 16,
|
||||
BackgroundCardName: "profile card",
|
||||
BackgroundCardURL: "https://example.com/card.pag",
|
||||
EffectImageResourceID: 17,
|
||||
EffectImageName: "effect image",
|
||||
EffectImageURL: "https://example.com/effect.svga",
|
||||
},
|
||||
}
|
||||
|
||||
state := &model.UserVipState{UserID: 1001, SysOrigin: "LIKEI"}
|
||||
applyPlanToState(state, plan, now)
|
||||
|
||||
if state.AvatarFrameResourceID != plan.TargetConfig.AvatarFrameResourceID ||
|
||||
if state.BadgeResourceID != plan.TargetConfig.BadgeResourceID ||
|
||||
state.ShortBadgeResourceID != plan.TargetConfig.ShortBadgeResourceID ||
|
||||
state.AvatarFrameResourceID != plan.TargetConfig.AvatarFrameResourceID ||
|
||||
state.EntryEffectResourceID != plan.TargetConfig.EntryEffectResourceID ||
|
||||
state.ChatBubbleResourceID != plan.TargetConfig.ChatBubbleResourceID ||
|
||||
state.FloatPictureResourceID != plan.TargetConfig.FloatPictureResourceID {
|
||||
state.FloatPictureResourceID != plan.TargetConfig.FloatPictureResourceID ||
|
||||
state.BackgroundCardResourceID != plan.TargetConfig.BackgroundCardResourceID ||
|
||||
state.EffectImageResourceID != plan.TargetConfig.EffectImageResourceID {
|
||||
t.Fatalf("state resource ids were not copied from target config")
|
||||
}
|
||||
if state.AvatarFrameName != "" || state.AvatarFrameURL != "" {
|
||||
@ -197,15 +213,24 @@ func TestApplyPlanToStateKeepsOnlyResourceIDsAndPayloadUsesLookup(t *testing.T)
|
||||
}
|
||||
|
||||
payload := statePayloadFromModelWithResources(state, now, vipResourceLookup{
|
||||
10: {ID: 10, Name: "long badge", Cover: "https://example.com/long.png", SourceURL: "https://example.com/long.svga"},
|
||||
11: {ID: 11, Name: "frame", Cover: "https://example.com/frame.png", SourceURL: "https://example.com/frame.svga"},
|
||||
12: {ID: 12, Name: "ride", Cover: "https://example.com/ride.png", SourceURL: "https://example.com/ride.svga"},
|
||||
13: {ID: 13, Name: "bubble", Cover: "https://example.com/bubble.png", SourceURL: "https://example.com/bubble.svga"},
|
||||
14: {ID: 14, Name: "float", Cover: "https://example.com/float.png", SourceURL: "https://example.com/float.svga"},
|
||||
15: {ID: 15, Name: "short badge", Cover: "https://example.com/short.png", SourceURL: "https://example.com/short.svga"},
|
||||
16: {ID: 16, Name: "profile card", Cover: "https://example.com/card.png", SourceURL: "https://example.com/card.pag"},
|
||||
17: {ID: 17, Name: "effect image", Cover: "https://example.com/effect.png", SourceURL: "https://example.com/effect.svga"},
|
||||
})
|
||||
if payload.AvatarFrame.Cover != "https://example.com/frame.png" ||
|
||||
if payload.LongBadge.Cover != "https://example.com/long.png" ||
|
||||
payload.Badge.Cover != "https://example.com/long.png" ||
|
||||
payload.ShortBadge.Cover != "https://example.com/short.png" ||
|
||||
payload.AvatarFrame.Cover != "https://example.com/frame.png" ||
|
||||
payload.EntryEffect.Cover != "https://example.com/ride.png" ||
|
||||
payload.ChatBubble.Cover != "https://example.com/bubble.png" ||
|
||||
payload.FloatPicture.Cover != "https://example.com/float.png" {
|
||||
payload.FloatPicture.Cover != "https://example.com/float.png" ||
|
||||
payload.BackgroundCard.Cover != "https://example.com/card.png" ||
|
||||
payload.EffectImage.Cover != "https://example.com/effect.png" {
|
||||
t.Fatalf("state payload covers were not loaded from resource lookup")
|
||||
}
|
||||
}
|
||||
@ -239,16 +264,19 @@ func TestMapWalletPurchaseErrorGatewayFailure(t *testing.T) {
|
||||
|
||||
func TestVIPGrantResourcesFromConfigMapsBackpackTypes(t *testing.T) {
|
||||
config := model.VipLevelConfig{
|
||||
BadgeResourceID: 10,
|
||||
AvatarFrameResourceID: 11,
|
||||
EntryEffectResourceID: 12,
|
||||
ChatBubbleResourceID: 13,
|
||||
FloatPictureResourceID: 14,
|
||||
BadgeResourceID: 10,
|
||||
ShortBadgeResourceID: 15,
|
||||
AvatarFrameResourceID: 11,
|
||||
EntryEffectResourceID: 12,
|
||||
ChatBubbleResourceID: 13,
|
||||
FloatPictureResourceID: 14,
|
||||
BackgroundCardResourceID: 16,
|
||||
EffectImageResourceID: 17,
|
||||
}
|
||||
|
||||
resources := vipGrantResourcesFromConfig(config)
|
||||
if len(resources) != 5 {
|
||||
t.Fatalf("resources len = %d, want 5", len(resources))
|
||||
if len(resources) != 7 {
|
||||
t.Fatalf("resources len = %d, want 7", len(resources))
|
||||
}
|
||||
assertGrant := func(index int, resourceID int64, propsType string, badge bool) {
|
||||
t.Helper()
|
||||
@ -258,10 +286,12 @@ func TestVIPGrantResourcesFromConfigMapsBackpackTypes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
assertGrant(0, 10, "", true)
|
||||
assertGrant(1, 11, vipPropsTypeAvatarFrame, false)
|
||||
assertGrant(2, 12, vipPropsTypeRide, false)
|
||||
assertGrant(3, 13, vipPropsTypeChatBubble, false)
|
||||
assertGrant(4, 14, vipPropsTypeFloatPicture, false)
|
||||
assertGrant(1, 15, "", true)
|
||||
assertGrant(2, 11, vipPropsTypeAvatarFrame, false)
|
||||
assertGrant(3, 12, vipPropsTypeRide, false)
|
||||
assertGrant(4, 13, vipPropsTypeChatBubble, false)
|
||||
assertGrant(5, 14, vipPropsTypeFloatPicture, false)
|
||||
assertGrant(6, 16, vipPropsTypeDataCard, false)
|
||||
}
|
||||
|
||||
func TestVIPGrantDaysUntilCeilsPartialDay(t *testing.T) {
|
||||
|
||||
@ -54,7 +54,7 @@ func compactResourceIDs(resourceIDs []int64) []int64 {
|
||||
}
|
||||
|
||||
func resourceIDsFromConfigRows(rows []model.VipLevelConfig) []int64 {
|
||||
ids := make([]int64, 0, len(rows)*5)
|
||||
ids := make([]int64, 0, len(rows)*8)
|
||||
for _, row := range rows {
|
||||
ids = appendResourceIDsFromConfig(ids, row)
|
||||
}
|
||||
@ -62,7 +62,7 @@ func resourceIDsFromConfigRows(rows []model.VipLevelConfig) []int64 {
|
||||
}
|
||||
|
||||
func resourceIDsFromConfigMap(configs map[int]model.VipLevelConfig) []int64 {
|
||||
ids := make([]int64, 0, len(configs)*5)
|
||||
ids := make([]int64, 0, len(configs)*8)
|
||||
for _, row := range configs {
|
||||
ids = appendResourceIDsFromConfig(ids, row)
|
||||
}
|
||||
@ -73,10 +73,13 @@ func appendResourceIDsFromConfig(ids []int64, row model.VipLevelConfig) []int64
|
||||
return append(
|
||||
ids,
|
||||
row.BadgeResourceID,
|
||||
row.ShortBadgeResourceID,
|
||||
row.AvatarFrameResourceID,
|
||||
row.EntryEffectResourceID,
|
||||
row.ChatBubbleResourceID,
|
||||
row.FloatPictureResourceID,
|
||||
row.BackgroundCardResourceID,
|
||||
row.EffectImageResourceID,
|
||||
)
|
||||
}
|
||||
|
||||
@ -87,9 +90,12 @@ func appendResourceIDsFromState(ids []int64, row *model.UserVipState) []int64 {
|
||||
return append(
|
||||
ids,
|
||||
row.BadgeResourceID,
|
||||
row.ShortBadgeResourceID,
|
||||
row.AvatarFrameResourceID,
|
||||
row.EntryEffectResourceID,
|
||||
row.ChatBubbleResourceID,
|
||||
row.FloatPictureResourceID,
|
||||
row.BackgroundCardResourceID,
|
||||
row.EffectImageResourceID,
|
||||
)
|
||||
}
|
||||
|
||||
@ -40,6 +40,7 @@ const (
|
||||
vipPropsTypeRide = "RIDE"
|
||||
vipPropsTypeChatBubble = "CHAT_BUBBLE"
|
||||
vipPropsTypeFloatPicture = "FLOAT_PICTURE"
|
||||
vipPropsTypeDataCard = "DATA_CARD"
|
||||
)
|
||||
|
||||
type AppError = common.AppError
|
||||
@ -82,19 +83,23 @@ type ConfigResponse struct {
|
||||
}
|
||||
|
||||
type VipLevelPayload struct {
|
||||
ID int64 `json:"id"`
|
||||
Level int `json:"level"`
|
||||
LevelCode string `json:"levelCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Enabled bool `json:"enabled"`
|
||||
DurationDays int `json:"durationDays"`
|
||||
PriceGold int64 `json:"priceGold"`
|
||||
Badge VipResourcePayload `json:"badge"`
|
||||
AvatarFrame VipResourcePayload `json:"avatarFrame"`
|
||||
EntryEffect VipResourcePayload `json:"entryEffect"`
|
||||
ChatBubble VipResourcePayload `json:"chatBubble"`
|
||||
FloatPicture VipResourcePayload `json:"floatPicture"`
|
||||
UpdateTime string `json:"updateTime,omitempty"`
|
||||
ID int64 `json:"id"`
|
||||
Level int `json:"level"`
|
||||
LevelCode string `json:"levelCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
Enabled bool `json:"enabled"`
|
||||
DurationDays int `json:"durationDays"`
|
||||
PriceGold int64 `json:"priceGold"`
|
||||
Badge VipResourcePayload `json:"badge"`
|
||||
LongBadge VipResourcePayload `json:"longBadge"`
|
||||
ShortBadge VipResourcePayload `json:"shortBadge"`
|
||||
AvatarFrame VipResourcePayload `json:"avatarFrame"`
|
||||
EntryEffect VipResourcePayload `json:"entryEffect"`
|
||||
ChatBubble VipResourcePayload `json:"chatBubble"`
|
||||
FloatPicture VipResourcePayload `json:"floatPicture"`
|
||||
BackgroundCard VipResourcePayload `json:"backgroundCard"`
|
||||
EffectImage VipResourcePayload `json:"effectImage"`
|
||||
UpdateTime string `json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
type VipResourcePayload struct {
|
||||
@ -183,21 +188,25 @@ type VipLevelHomePayload struct {
|
||||
}
|
||||
|
||||
type UserVipStatePayload struct {
|
||||
UserID int64 `json:"userId"`
|
||||
SysOrigin string `json:"sysOrigin"`
|
||||
Active bool `json:"active"`
|
||||
Status string `json:"status"`
|
||||
Level int `json:"level"`
|
||||
LevelCode string `json:"levelCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
StartAt string `json:"startAt,omitempty"`
|
||||
ExpireAt string `json:"expireAt,omitempty"`
|
||||
Badge VipResourcePayload `json:"badge,omitempty"`
|
||||
AvatarFrame VipResourcePayload `json:"avatarFrame,omitempty"`
|
||||
EntryEffect VipResourcePayload `json:"entryEffect,omitempty"`
|
||||
ChatBubble VipResourcePayload `json:"chatBubble,omitempty"`
|
||||
FloatPicture VipResourcePayload `json:"floatPicture,omitempty"`
|
||||
UpdateTime string `json:"updateTime,omitempty"`
|
||||
UserID int64 `json:"userId"`
|
||||
SysOrigin string `json:"sysOrigin"`
|
||||
Active bool `json:"active"`
|
||||
Status string `json:"status"`
|
||||
Level int `json:"level"`
|
||||
LevelCode string `json:"levelCode"`
|
||||
DisplayName string `json:"displayName"`
|
||||
StartAt string `json:"startAt,omitempty"`
|
||||
ExpireAt string `json:"expireAt,omitempty"`
|
||||
Badge VipResourcePayload `json:"badge,omitempty"`
|
||||
LongBadge VipResourcePayload `json:"longBadge,omitempty"`
|
||||
ShortBadge VipResourcePayload `json:"shortBadge,omitempty"`
|
||||
AvatarFrame VipResourcePayload `json:"avatarFrame,omitempty"`
|
||||
EntryEffect VipResourcePayload `json:"entryEffect,omitempty"`
|
||||
ChatBubble VipResourcePayload `json:"chatBubble,omitempty"`
|
||||
FloatPicture VipResourcePayload `json:"floatPicture,omitempty"`
|
||||
BackgroundCard VipResourcePayload `json:"backgroundCard,omitempty"`
|
||||
EffectImage VipResourcePayload `json:"effectImage,omitempty"`
|
||||
UpdateTime string `json:"updateTime,omitempty"`
|
||||
}
|
||||
|
||||
type VipOrderPayload struct {
|
||||
@ -356,19 +365,23 @@ func payloadFromConfigWithResources(row model.VipLevelConfig, resources vipResou
|
||||
code = levelCode(row.Level)
|
||||
}
|
||||
return VipLevelPayload{
|
||||
ID: row.ID,
|
||||
Level: row.Level,
|
||||
LevelCode: code,
|
||||
DisplayName: displayName,
|
||||
Enabled: row.Enabled,
|
||||
DurationDays: duration,
|
||||
PriceGold: row.PriceGold,
|
||||
Badge: resourcePayloadWithLookup(row.BadgeResourceID, row.BadgeName, row.BadgeURL, "", resources),
|
||||
AvatarFrame: resourcePayloadWithLookup(row.AvatarFrameResourceID, row.AvatarFrameName, row.AvatarFrameURL, "", resources),
|
||||
EntryEffect: resourcePayloadWithLookup(row.EntryEffectResourceID, row.EntryEffectName, row.EntryEffectURL, "", resources),
|
||||
ChatBubble: resourcePayloadWithLookup(row.ChatBubbleResourceID, row.ChatBubbleName, row.ChatBubbleURL, "", resources),
|
||||
FloatPicture: resourcePayloadWithLookup(row.FloatPictureResourceID, row.FloatPictureName, row.FloatPictureURL, "", resources),
|
||||
UpdateTime: formatTime(row.UpdateTime),
|
||||
ID: row.ID,
|
||||
Level: row.Level,
|
||||
LevelCode: code,
|
||||
DisplayName: displayName,
|
||||
Enabled: row.Enabled,
|
||||
DurationDays: duration,
|
||||
PriceGold: row.PriceGold,
|
||||
Badge: resourcePayloadWithLookup(row.BadgeResourceID, row.BadgeName, row.BadgeURL, "", resources),
|
||||
LongBadge: resourcePayloadWithLookup(row.BadgeResourceID, row.BadgeName, row.BadgeURL, "", resources),
|
||||
ShortBadge: resourcePayloadWithLookup(row.ShortBadgeResourceID, row.ShortBadgeName, row.ShortBadgeURL, "", resources),
|
||||
AvatarFrame: resourcePayloadWithLookup(row.AvatarFrameResourceID, row.AvatarFrameName, row.AvatarFrameURL, "", resources),
|
||||
EntryEffect: resourcePayloadWithLookup(row.EntryEffectResourceID, row.EntryEffectName, row.EntryEffectURL, "", resources),
|
||||
ChatBubble: resourcePayloadWithLookup(row.ChatBubbleResourceID, row.ChatBubbleName, row.ChatBubbleURL, "", resources),
|
||||
FloatPicture: resourcePayloadWithLookup(row.FloatPictureResourceID, row.FloatPictureName, row.FloatPictureURL, "", resources),
|
||||
BackgroundCard: resourcePayloadWithLookup(row.BackgroundCardResourceID, row.BackgroundCardName, row.BackgroundCardURL, "", resources),
|
||||
EffectImage: resourcePayloadWithLookup(row.EffectImageResourceID, row.EffectImageName, row.EffectImageURL, "", resources),
|
||||
UpdateTime: formatTime(row.UpdateTime),
|
||||
}
|
||||
}
|
||||
|
||||
@ -402,10 +415,14 @@ func statePayloadFromModelWithResources(row *model.UserVipState, now time.Time,
|
||||
return payload
|
||||
}
|
||||
payload.Badge = resourcePayloadWithLookup(row.BadgeResourceID, row.BadgeName, row.BadgeURL, "", resources)
|
||||
payload.LongBadge = payload.Badge
|
||||
payload.ShortBadge = resourcePayloadWithLookup(row.ShortBadgeResourceID, row.ShortBadgeName, row.ShortBadgeURL, "", resources)
|
||||
payload.AvatarFrame = resourcePayloadWithLookup(row.AvatarFrameResourceID, row.AvatarFrameName, row.AvatarFrameURL, "", resources)
|
||||
payload.EntryEffect = resourcePayloadWithLookup(row.EntryEffectResourceID, row.EntryEffectName, row.EntryEffectURL, "", resources)
|
||||
payload.ChatBubble = resourcePayloadWithLookup(row.ChatBubbleResourceID, row.ChatBubbleName, row.ChatBubbleURL, "", resources)
|
||||
payload.FloatPicture = resourcePayloadWithLookup(row.FloatPictureResourceID, row.FloatPictureName, row.FloatPictureURL, "", resources)
|
||||
payload.BackgroundCard = resourcePayloadWithLookup(row.BackgroundCardResourceID, row.BackgroundCardName, row.BackgroundCardURL, "", resources)
|
||||
payload.EffectImage = resourcePayloadWithLookup(row.EffectImageResourceID, row.EffectImageName, row.EffectImageURL, "", resources)
|
||||
return payload
|
||||
}
|
||||
|
||||
|
||||
253
migrations/042_vip_badge_card_effect_resources.sql
Normal file
253
migrations/042_vip_badge_card_effect_resources.sql
Normal file
@ -0,0 +1,253 @@
|
||||
SET @current_schema := DATABASE();
|
||||
|
||||
SET @add_vip_level_short_badge_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'short_badge_resource_id'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `short_badge_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''短徽章资源ID'' AFTER `badge_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_short_badge_resource_id_stmt FROM @add_vip_level_short_badge_resource_id_sql;
|
||||
EXECUTE add_vip_level_short_badge_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_short_badge_resource_id_stmt;
|
||||
|
||||
SET @add_vip_level_short_badge_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'short_badge_name'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `short_badge_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''短徽章名称'' AFTER `short_badge_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_short_badge_name_stmt FROM @add_vip_level_short_badge_name_sql;
|
||||
EXECUTE add_vip_level_short_badge_name_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_short_badge_name_stmt;
|
||||
|
||||
SET @add_vip_level_short_badge_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'short_badge_url'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `short_badge_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''短徽章资源URL'' AFTER `short_badge_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_short_badge_url_stmt FROM @add_vip_level_short_badge_url_sql;
|
||||
EXECUTE add_vip_level_short_badge_url_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_short_badge_url_stmt;
|
||||
|
||||
SET @add_vip_level_background_card_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'background_card_resource_id'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `background_card_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''背景卡资源ID'' AFTER `float_picture_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_background_card_resource_id_stmt FROM @add_vip_level_background_card_resource_id_sql;
|
||||
EXECUTE add_vip_level_background_card_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_background_card_resource_id_stmt;
|
||||
|
||||
SET @add_vip_level_background_card_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'background_card_name'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `background_card_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''背景卡名称'' AFTER `background_card_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_background_card_name_stmt FROM @add_vip_level_background_card_name_sql;
|
||||
EXECUTE add_vip_level_background_card_name_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_background_card_name_stmt;
|
||||
|
||||
SET @add_vip_level_background_card_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'background_card_url'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `background_card_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''背景卡资源URL'' AFTER `background_card_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_background_card_url_stmt FROM @add_vip_level_background_card_url_sql;
|
||||
EXECUTE add_vip_level_background_card_url_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_background_card_url_stmt;
|
||||
|
||||
SET @add_vip_level_effect_image_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'effect_image_resource_id'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `effect_image_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''动效图资源ID'' AFTER `background_card_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_effect_image_resource_id_stmt FROM @add_vip_level_effect_image_resource_id_sql;
|
||||
EXECUTE add_vip_level_effect_image_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_effect_image_resource_id_stmt;
|
||||
|
||||
SET @add_vip_level_effect_image_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'effect_image_name'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `effect_image_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''动效图名称'' AFTER `effect_image_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_effect_image_name_stmt FROM @add_vip_level_effect_image_name_sql;
|
||||
EXECUTE add_vip_level_effect_image_name_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_effect_image_name_stmt;
|
||||
|
||||
SET @add_vip_level_effect_image_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'vip_level_config'
|
||||
AND column_name = 'effect_image_url'
|
||||
),
|
||||
'ALTER TABLE `vip_level_config` ADD COLUMN `effect_image_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''动效图资源URL'' AFTER `effect_image_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_vip_level_effect_image_url_stmt FROM @add_vip_level_effect_image_url_sql;
|
||||
EXECUTE add_vip_level_effect_image_url_stmt;
|
||||
DEALLOCATE PREPARE add_vip_level_effect_image_url_stmt;
|
||||
|
||||
SET @add_user_vip_short_badge_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'short_badge_resource_id'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `short_badge_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''当前短徽章资源ID'' AFTER `badge_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_short_badge_resource_id_stmt FROM @add_user_vip_short_badge_resource_id_sql;
|
||||
EXECUTE add_user_vip_short_badge_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_short_badge_resource_id_stmt;
|
||||
|
||||
SET @add_user_vip_short_badge_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'short_badge_name'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `short_badge_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''当前短徽章名称'' AFTER `short_badge_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_short_badge_name_stmt FROM @add_user_vip_short_badge_name_sql;
|
||||
EXECUTE add_user_vip_short_badge_name_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_short_badge_name_stmt;
|
||||
|
||||
SET @add_user_vip_short_badge_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'short_badge_url'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `short_badge_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''当前短徽章资源URL'' AFTER `short_badge_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_short_badge_url_stmt FROM @add_user_vip_short_badge_url_sql;
|
||||
EXECUTE add_user_vip_short_badge_url_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_short_badge_url_stmt;
|
||||
|
||||
SET @add_user_vip_background_card_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'background_card_resource_id'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `background_card_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''当前背景卡资源ID'' AFTER `float_picture_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_background_card_resource_id_stmt FROM @add_user_vip_background_card_resource_id_sql;
|
||||
EXECUTE add_user_vip_background_card_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_background_card_resource_id_stmt;
|
||||
|
||||
SET @add_user_vip_background_card_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'background_card_name'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `background_card_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''当前背景卡名称'' AFTER `background_card_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_background_card_name_stmt FROM @add_user_vip_background_card_name_sql;
|
||||
EXECUTE add_user_vip_background_card_name_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_background_card_name_stmt;
|
||||
|
||||
SET @add_user_vip_background_card_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'background_card_url'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `background_card_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''当前背景卡资源URL'' AFTER `background_card_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_background_card_url_stmt FROM @add_user_vip_background_card_url_sql;
|
||||
EXECUTE add_user_vip_background_card_url_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_background_card_url_stmt;
|
||||
|
||||
SET @add_user_vip_effect_image_resource_id_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'effect_image_resource_id'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `effect_image_resource_id` bigint NOT NULL DEFAULT 0 COMMENT ''当前动效图资源ID'' AFTER `background_card_url`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_effect_image_resource_id_stmt FROM @add_user_vip_effect_image_resource_id_sql;
|
||||
EXECUTE add_user_vip_effect_image_resource_id_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_effect_image_resource_id_stmt;
|
||||
|
||||
SET @add_user_vip_effect_image_name_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'effect_image_name'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `effect_image_name` varchar(128) NOT NULL DEFAULT '''' COMMENT ''当前动效图名称'' AFTER `effect_image_resource_id`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_effect_image_name_stmt FROM @add_user_vip_effect_image_name_sql;
|
||||
EXECUTE add_user_vip_effect_image_name_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_effect_image_name_stmt;
|
||||
|
||||
SET @add_user_vip_effect_image_url_sql := IF(
|
||||
NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.columns
|
||||
WHERE table_schema = @current_schema
|
||||
AND table_name = 'user_vip_state'
|
||||
AND column_name = 'effect_image_url'
|
||||
),
|
||||
'ALTER TABLE `user_vip_state` ADD COLUMN `effect_image_url` varchar(512) NOT NULL DEFAULT '''' COMMENT ''当前动效图资源URL'' AFTER `effect_image_name`',
|
||||
'SELECT 1'
|
||||
);
|
||||
PREPARE add_user_vip_effect_image_url_stmt FROM @add_user_vip_effect_image_url_sql;
|
||||
EXECUTE add_user_vip_effect_image_url_stmt;
|
||||
DEALLOCATE PREPARE add_user_vip_effect_image_url_stmt;
|
||||
Loading…
x
Reference in New Issue
Block a user