package service import ( "context" roomv1 "hyapp.local/api/proto/room/v1" "hyapp/pkg/appcode" "hyapp/pkg/xerr" ) // AdminGetRoomRocketConfig 暴露 room-service owner 内部配置读模型,避免后台跨库读取 room_rocket_configs。 func (s *Service) AdminGetRoomRocketConfig(ctx context.Context, _ *roomv1.AdminGetRoomRocketConfigRequest) (*roomv1.AdminGetRoomRocketConfigResponse, error) { config, err := s.roomRocketConfig(ctx) if err != nil { return nil, err } return &roomv1.AdminGetRoomRocketConfigResponse{ Config: roomRocketConfigToAdminProto(config), ServerTimeMs: s.clock.Now().UnixMilli(), }, nil } // AdminUpdateRoomRocketConfig 保存后台火箭配置;版本号在 room-service 内递增,admin 不能直写 owner 表。 func (s *Service) AdminUpdateRoomRocketConfig(ctx context.Context, req *roomv1.AdminUpdateRoomRocketConfigRequest) (*roomv1.AdminUpdateRoomRocketConfigResponse, error) { if req == nil || req.GetConfig() == nil { return nil, xerr.New(xerr.InvalidArgument, "room rocket config is required") } current, exists, err := s.repository.GetRoomRocketConfig(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 := normalizeRoomRocketConfig(RoomRocketConfig{ AppCode: appcode.FromContext(ctx), Enabled: input.GetEnabled(), ConfigVersion: current.ConfigVersion + 1, FuelSource: input.GetFuelSource(), LaunchDelayMS: input.GetLaunchDelayMs(), BroadcastEnabled: input.GetBroadcastEnabled(), BroadcastScope: input.GetBroadcastScope(), BroadcastDelayMS: input.GetBroadcastDelayMs(), RewardStackPolicy: input.GetRewardStackPolicy(), Levels: roomRocketLevelsFromProto(input.GetLevels()), GiftFuelRules: roomRocketFuelRulesFromProto(input.GetGiftFuelRules()), UpdatedByAdminID: req.GetAdminId(), CreatedAtMS: createdAtMS, UpdatedAtMS: nowMS, }) if err != nil { return nil, err } if err := s.repository.UpsertRoomRocketConfig(ctx, config); err != nil { return nil, err } return &roomv1.AdminUpdateRoomRocketConfigResponse{ Config: roomRocketConfigToAdminProto(config), ServerTimeMs: nowMS, }, nil } func roomRocketConfigToAdminProto(config RoomRocketConfig) *roomv1.AdminRoomRocketConfig { return &roomv1.AdminRoomRocketConfig{ AppCode: config.AppCode, Enabled: config.Enabled, ConfigVersion: config.ConfigVersion, FuelSource: config.FuelSource, LaunchDelayMs: config.LaunchDelayMS, BroadcastEnabled: config.BroadcastEnabled, BroadcastScope: config.BroadcastScope, BroadcastDelayMs: config.BroadcastDelayMS, RewardStackPolicy: config.RewardStackPolicy, Levels: roomRocketLevelsToProto(config.Levels), GiftFuelRules: roomRocketFuelRulesToProto(config.GiftFuelRules), UpdatedByAdminId: config.UpdatedByAdminID, CreatedAtMs: config.CreatedAtMS, UpdatedAtMs: config.UpdatedAtMS, } } func roomRocketLevelsFromProto(input []*roomv1.RoomRocketLevel) []RoomRocketLevelConfig { out := make([]RoomRocketLevelConfig, 0, len(input)) for _, level := range input { if level == nil { continue } out = append(out, RoomRocketLevelConfig{ Level: level.GetLevel(), FuelThreshold: level.GetFuelThreshold(), CoverURL: level.GetCoverUrl(), AnimationURL: level.GetAnimationUrl(), LaunchAnimationURL: level.GetLaunchAnimationUrl(), LaunchedImageURL: level.GetLaunchedImageUrl(), InRoomRewards: roomRocketRewardsFromProto(level.GetInRoomRewards()), Top1Rewards: roomRocketRewardsFromProto(level.GetTop1Rewards()), IgniterRewards: roomRocketRewardsFromProto(level.GetIgniterRewards()), }) } return out } func roomRocketRewardsFromProto(input []*roomv1.RoomRocketRewardItem) []RoomRocketRewardItem { out := make([]RoomRocketRewardItem, 0, len(input)) for _, reward := range input { if reward == nil { continue } out = append(out, RoomRocketRewardItem{ RewardItemID: reward.GetRewardItemId(), ResourceGroupID: reward.GetResourceGroupId(), Weight: reward.GetWeight(), DisplayName: reward.GetDisplayName(), IconURL: reward.GetIconUrl(), }) } return out } func roomRocketFuelRulesToProto(input []GiftFuelRuleConfig) []*roomv1.RoomRocketGiftFuelRule { out := make([]*roomv1.RoomRocketGiftFuelRule, 0, len(input)) for _, rule := range input { out = append(out, &roomv1.RoomRocketGiftFuelRule{ RuleId: rule.RuleID, GiftId: rule.GiftID, GiftTypeCode: rule.GiftTypeCode, MultiplierPpm: rule.MultiplierPPM, FixedFuel: rule.FixedFuel, Excluded: rule.Excluded, }) } return out } func roomRocketFuelRulesFromProto(input []*roomv1.RoomRocketGiftFuelRule) []GiftFuelRuleConfig { out := make([]GiftFuelRuleConfig, 0, len(input)) for _, rule := range input { if rule == nil { continue } out = append(out, GiftFuelRuleConfig{ RuleID: rule.GetRuleId(), GiftID: rule.GetGiftId(), GiftTypeCode: rule.GetGiftTypeCode(), MultiplierPPM: rule.GetMultiplierPpm(), FixedFuel: rule.GetFixedFuel(), Excluded: rule.GetExcluded(), }) } return out }