From 7f2aa1d450c87ee3bb1f3e2b2856a48cc1a4c271 Mon Sep 17 00:00:00 2001 From: zhx Date: Tue, 21 Jul 2026 19:44:58 +0800 Subject: [PATCH] =?UTF-8?q?=E9=A3=98=E7=AA=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../internal/domain/resource/constants.go | 14 ++++++++------ .../internal/domain/resource/shop.go | 3 ++- .../mysql/resource_entitlement_repository.go | 4 +++- .../storage/mysql/resource_shop_repository.go | 4 +++- 4 files changed, 16 insertions(+), 9 deletions(-) diff --git a/services/wallet-service/internal/domain/resource/constants.go b/services/wallet-service/internal/domain/resource/constants.go index 69bcc320..f919a038 100644 --- a/services/wallet-service/internal/domain/resource/constants.go +++ b/services/wallet-service/internal/domain/resource/constants.go @@ -1,12 +1,14 @@ package resource const ( - TypeAvatarFrame = "avatar_frame" - TypeProfileCard = "profile_card" - TypeCoin = "coin" - TypeVehicle = "vehicle" - TypeChatBubble = "chat_bubble" - TypeBadge = "badge" + TypeAvatarFrame = "avatar_frame" + TypeProfileCard = "profile_card" + TypeCoin = "coin" + TypeVehicle = "vehicle" + TypeChatBubble = "chat_bubble" + TypeBadge = "badge" + // TypeFloatingScreen 是用户单选佩戴的飘窗皮肤;素材消费方读取装备快照, + // 商店和背包仍复用通用资源 SKU、entitlement 与 equipment 契约。 TypeFloatingScreen = "floating_screen" TypeGift = "gift" // TypeGiftTraySkin 复用 VIP 权益的稳定编码;目录素材与 gift 礼物本体分开, diff --git a/services/wallet-service/internal/domain/resource/shop.go b/services/wallet-service/internal/domain/resource/shop.go index 29005801..8a9858ad 100644 --- a/services/wallet-service/internal/domain/resource/shop.go +++ b/services/wallet-service/internal/domain/resource/shop.go @@ -106,7 +106,8 @@ type ResourceShopPurchaseReceipt struct { func ResourceTypeSellableInShop(value string) bool { switch NormalizeResourceType(value) { - case TypeAvatarFrame, TypeProfileCard, TypeVehicle, TypeChatBubble, TypeBadge, TypeMicSeatIcon, TypeMicSeatAnimation: + // 飘窗是有期限的用户装扮,购买后下发 entitlement;不能按 gift 等消耗品处理。 + case TypeAvatarFrame, TypeProfileCard, TypeVehicle, TypeChatBubble, TypeBadge, TypeFloatingScreen, TypeMicSeatIcon, TypeMicSeatAnimation: return true default: return false diff --git a/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go b/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go index 989d5d38..e762bf41 100644 --- a/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_entitlement_repository.go @@ -1021,7 +1021,9 @@ func (r *Repository) pruneExpiredUserResourceEquipment(ctx context.Context, user func isEquipableResourceType(resourceType string) bool { switch resourcedomain.NormalizeResourceType(resourceType) { - case resourcedomain.TypeAvatarFrame, resourcedomain.TypeProfileCard, resourcedomain.TypeVehicle, resourcedomain.TypeChatBubble, resourcedomain.TypeBadge, resourcedomain.TypeMicSeatAnimation, resourcedomain.TypeVIPTrialCard: + // 飘窗与头像框等用户装扮保持同一资源类型单选槽,切换时事务会替换同类型旧装备; + // badge 的多选和 VIP 体验卡的专用状态机仍由各自分支处理。 + case resourcedomain.TypeAvatarFrame, resourcedomain.TypeProfileCard, resourcedomain.TypeVehicle, resourcedomain.TypeChatBubble, resourcedomain.TypeBadge, resourcedomain.TypeFloatingScreen, resourcedomain.TypeMicSeatAnimation, resourcedomain.TypeVIPTrialCard: return true default: return false diff --git a/services/wallet-service/internal/storage/mysql/resource_shop_repository.go b/services/wallet-service/internal/storage/mysql/resource_shop_repository.go index cfb9c540..97527622 100644 --- a/services/wallet-service/internal/storage/mysql/resource_shop_repository.go +++ b/services/wallet-service/internal/storage/mysql/resource_shop_repository.go @@ -743,7 +743,9 @@ func resourceShopPurchaseOrderSelectSQL() string { } func resourceShopItemsWhereSQL(query resourcedomain.ListResourceShopItemsQuery) (string, []any) { - where := `WHERE si.app_code = ? AND r.resource_type IN ('avatar_frame', 'profile_card', 'vehicle', 'chat_bubble', 'badge', 'mic_seat_icon', 'mic_seat_animation')` + // 固定类型白名单只增加一个等值分支,仍由 resource_shop_items 的 App/SKU 索引驱动并按 + // (app_code, resource_id) 关联 resources,不引入全表扫描或额外查询。 + where := `WHERE si.app_code = ? AND r.resource_type IN ('avatar_frame', 'profile_card', 'vehicle', 'chat_bubble', 'badge', 'floating_screen', 'mic_seat_icon', 'mic_seat_animation')` args := []any{query.AppCode} if query.ActiveOnly { nowMs := time.Now().UnixMilli()