package service import ( "context" roomv1 "hyapp.local/api/proto/room/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" ) // AdminGetRoomTreasureConfig 暴露 room-service owner 内部配置读模型,避免后台跨库读取 room_treasure_configs。 func (s *Service) AdminGetRoomTreasureConfig(ctx context.Context, _ *roomv1.AdminGetRoomTreasureConfigRequest) (*roomv1.AdminGetRoomTreasureConfigResponse, error) { config, err := s.roomTreasureConfig(ctx) if err != nil { return nil, err } return &roomv1.AdminGetRoomTreasureConfigResponse{ Config: roomTreasureConfigToAdminProto(config), ServerTimeMs: s.clock.Now().UnixMilli(), }, nil } // AdminUpdateRoomTreasureConfig 保存后台宝箱配置;版本号在 room-service 内递增,admin 不能直写 owner 表。 func (s *Service) AdminUpdateRoomTreasureConfig(ctx context.Context, req *roomv1.AdminUpdateRoomTreasureConfigRequest) (*roomv1.AdminUpdateRoomTreasureConfigResponse, error) { if req == nil || req.GetConfig() == nil { return nil, xerr.New(xerr.InvalidArgument, "room treasure config is required") } current, exists, err := s.repository.GetRoomTreasureConfig(ctx) if err != nil { return nil, err } nowMS := s.clock.Now().UTC().UnixMilli() createdAtMS := current.CreatedAtMS if !exists || createdAtMS <= 0 { createdAtMS = nowMS } input := req.GetConfig() config, err := normalizeRoomTreasureConfig(RoomTreasureConfig{ AppCode: appcode.FromContext(ctx), Enabled: input.GetEnabled(), ConfigVersion: current.ConfigVersion + 1, EnergySource: input.GetEnergySource(), OpenDelayMS: input.GetOpenDelayMs(), BroadcastEnabled: input.GetBroadcastEnabled(), BroadcastScope: input.GetBroadcastScope(), BroadcastDelayMS: input.GetBroadcastDelayMs(), RewardStackPolicy: input.GetRewardStackPolicy(), Levels: roomTreasureLevelsFromProto(input.GetLevels()), GiftEnergyRules: roomTreasureEnergyRulesFromProto(input.GetGiftEnergyRules()), UpdatedByAdminID: req.GetAdminId(), CreatedAtMS: createdAtMS, UpdatedAtMS: nowMS, }) if err != nil { return nil, err } if err := s.repository.UpsertRoomTreasureConfig(ctx, config); err != nil { return nil, err } return &roomv1.AdminUpdateRoomTreasureConfigResponse{ Config: roomTreasureConfigToAdminProto(config), ServerTimeMs: nowMS, }, nil } func roomTreasureConfigToAdminProto(config RoomTreasureConfig) *roomv1.AdminRoomTreasureConfig { return &roomv1.AdminRoomTreasureConfig{ AppCode: config.AppCode, Enabled: config.Enabled, ConfigVersion: config.ConfigVersion, EnergySource: config.EnergySource, OpenDelayMs: config.OpenDelayMS, BroadcastEnabled: config.BroadcastEnabled, BroadcastScope: config.BroadcastScope, BroadcastDelayMs: config.BroadcastDelayMS, RewardStackPolicy: config.RewardStackPolicy, Levels: roomTreasureLevelsToProto(config.Levels), GiftEnergyRules: roomTreasureEnergyRulesToProto(config.GiftEnergyRules), UpdatedByAdminId: config.UpdatedByAdminID, CreatedAtMs: config.CreatedAtMS, UpdatedAtMs: config.UpdatedAtMS, } } func roomTreasureLevelsFromProto(input []*roomv1.RoomTreasureLevel) []RoomTreasureLevelConfig { out := make([]RoomTreasureLevelConfig, 0, len(input)) for _, level := range input { if level == nil { continue } out = append(out, RoomTreasureLevelConfig{ Level: level.GetLevel(), EnergyThreshold: level.GetEnergyThreshold(), CoverURL: level.GetCoverUrl(), AnimationURL: level.GetAnimationUrl(), OpeningAnimationURL: level.GetOpeningAnimationUrl(), OpenedImageURL: level.GetOpenedImageUrl(), InRoomRewards: roomTreasureRewardsFromProto(level.GetInRoomRewards()), Top1Rewards: roomTreasureRewardsFromProto(level.GetTop1Rewards()), IgniterRewards: roomTreasureRewardsFromProto(level.GetIgniterRewards()), }) } return out } func roomTreasureRewardsFromProto(input []*roomv1.RoomTreasureRewardItem) []RoomTreasureRewardItem { out := make([]RoomTreasureRewardItem, 0, len(input)) for _, reward := range input { if reward == nil { continue } out = append(out, RoomTreasureRewardItem{ RewardItemID: reward.GetRewardItemId(), ResourceGroupID: reward.GetResourceGroupId(), Weight: reward.GetWeight(), DisplayName: reward.GetDisplayName(), IconURL: reward.GetIconUrl(), }) } return out } func roomTreasureEnergyRulesToProto(input []GiftEnergyRuleConfig) []*roomv1.RoomTreasureGiftEnergyRule { out := make([]*roomv1.RoomTreasureGiftEnergyRule, 0, len(input)) for _, rule := range input { out = append(out, &roomv1.RoomTreasureGiftEnergyRule{ RuleId: rule.RuleID, GiftId: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPpm: rule.MultiplierPPM, FixedEnergy: rule.FixedEnergy, Excluded: rule.Excluded, }) } return out } func roomTreasureEnergyRulesFromProto(input []*roomv1.RoomTreasureGiftEnergyRule) []GiftEnergyRuleConfig { out := make([]GiftEnergyRuleConfig, 0, len(input)) for _, rule := range input { if rule == nil { continue } out = append(out, GiftEnergyRuleConfig{ RuleID: rule.GetRuleId(), GiftID: rule.GetGiftId(), GiftTypeCode: rule.GetGiftTypeCode(), MultiplierPPM: rule.GetMultiplierPpm(), FixedEnergy: rule.GetFixedEnergy(), Excluded: rule.GetExcluded(), }) } return out }