package service import ( "context" v1 "github.com/go-nunu/nunu-layout-advanced/api/v1" "github.com/go-nunu/nunu-layout-advanced/internal/model" "github.com/go-nunu/nunu-layout-advanced/internal/repository" "github.com/spf13/cast" "strconv" "strings" ) // HostService 接口定义 type HostService interface { GetHost(ctx context.Context, id int64) (*model.Host, error) GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error) GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error) GetTcpLimitConfig(ctx context.Context, hostId int) (v1.TcpLimitRequest, error) GetUdpLimitConfig(ctx context.Context, hostId int) (v1.UdpLimitRequest, error) GetWebLimitConfig(ctx context.Context, hostId int) (v1.WebLimitRequest, error) } func NewHostService( service *Service, hostRepository repository.HostRepository, ) HostService { return &hostService{ Service: service, hostRepository: hostRepository, } } // 常量定义,包含新增的配置项名称 const ( ConfigOnlineDevices = "在线设备数" ConfigRuleEntries = "规则条目" ConfigMaxBandwidth = "高带宽转发规则条目" ConfigSourceMachines = "支持源机" ConfigBps = "带宽" ConfigMaxProtection = "高防防护能力" ConfigPortCount = "防御端口数量" ConfigDomainCount = "防御域名(需要备案)" ConfigOperator = "高防线路" ConfigIpCount = "高防节点IP" ) // unitSuffixMap 存储需要去除的单位后缀 var unitSuffixMap = map[string]string{ ConfigOnlineDevices: "个", ConfigRuleEntries: "个", ConfigMaxBandwidth: "条", ConfigIpCount: "个", } type hostService struct { *Service hostRepository repository.HostRepository } func (s *hostService) GetHost(ctx context.Context, id int64) (*model.Host, error) { return s.hostRepository.GetHost(ctx, id) } // GetHostConfig 保持不变,它是一个通用的底层数据获取方法。 func (s *hostService) GetHostConfig(ctx context.Context, hostId int) ([]map[string]string, error) { configOptions, err := s.hostRepository.GetHostConfig(ctx, hostId) if err != nil { return nil, err } // 2. 收集ID和建立映射关系 (优化部分) var configIDs []int // 只收集那些我们需要查询详情的 option ID var optionIDsToFetch []int optionMap := make(map[int]int) qtyMap := make(map[int]int) for _, item := range configOptions { configIDs = append(configIDs, item.Configid) qtyMap[item.Configid] = item.Qty // 核心优化:只有当数量为0时,我们才需要Option的名称, // 因此才需要记录其ID用于后续查询,并建立 configID -> optionID 的映射。 if item.Qty == 0 { optionIDsToFetch = append(optionIDsToFetch, item.Optionid) optionMap[item.Configid] = item.Optionid } } // 3. 获取配置和选项数据 var configs []v1.ProductConfigOption if len(configIDs) > 0 { configs, err = s.hostRepository.GetProductConfigOption(ctx, configIDs) if err != nil { return nil, err } } // 只有在确实需要查询的情况下才执行 var options []v1.ProductConfigOptionSub if len(optionIDsToFetch) > 0 { options, err = s.hostRepository.GetProductConfigOptionSub(ctx, optionIDsToFetch) if err != nil { return nil, err } } // 4. 转换选项为关联数组 optionsByID := make(map[int]v1.ProductConfigOptionSub) for _, option := range options { optionsByID[option.ID] = option } // 5. 构建结果数据 (逻辑更清晰) var data []map[string]string for _, config := range configs { var optionName string // 直接通过qtyMap判断,逻辑更直接 if qty := qtyMap[config.ID]; qty != 0 { // 如果数量不为0,直接使用数量作为名称 optionName = strconv.Itoa(qty) } else { // 否则,我们知道它一定在 optionMap 和 optionsByID 中 (如果数据一致) optionID := optionMap[config.ID] // 这个查找现在是必要的 if opt, ok := optionsByID[optionID]; ok { optionName = opt.OptionName } } data = append(data, map[string]string{ "config_name": config.OptionName, "option_name": optionName, }) } return data, nil } // cleanConfigOptionName 简化后的清理函数,直接返回清理后的字符串。 func (s *hostService) cleanConfigOptionName(configName string, optionName string) string { // 根据配置名称去除相应的单位后缀 if suffix, ok := unitSuffixMap[configName]; ok { optionName = strings.TrimSuffix(optionName, suffix) } return optionName } // getHostConfigsMap 新增的辅助函数,用于获取所有清理后的配置映射。 func (s *hostService) getHostConfigsMap(ctx context.Context, hostId int) (map[string]string, error) { baseData, err := s.GetHostConfig(ctx, hostId) if err != nil { return nil, err } configsMap := make(map[string]string) for _, item := range baseData { configName := item["config_name"] optionName := item["option_name"] // 将清理后的值存储到 map 中 configsMap[configName] = s.cleanConfigOptionName(configName, optionName) } return configsMap, nil } func (s *hostService) GetGameShieldConfig(ctx context.Context, hostId int) (v1.GameShieldHostBackendConfigResponse, error) { // 调用新辅助函数获取处理好的配置映射 configsMap, err := s.getHostConfigsMap(ctx, hostId) if err != nil { return v1.GameShieldHostBackendConfigResponse{}, err } var data v1.GameShieldHostBackendConfigResponse var parseErr error // 用于统一处理类型转换错误 // 从映射中获取值并进行类型转换 if val, ok := configsMap[ConfigOnlineDevices]; ok { data.OnlineDevicesCount, parseErr = cast.ToInt64E(val) if parseErr != nil { return data, parseErr } } if val, ok := configsMap[ConfigRuleEntries]; ok { data.RuleEntriesCount, parseErr = cast.ToInt64E(val) if parseErr != nil { return data, parseErr } } if val, ok := configsMap[ConfigMaxBandwidth]; ok { data.MaxBandwidthCount, parseErr = cast.ToInt64E(val) if parseErr != nil { return data, parseErr } } if val, ok := configsMap[ConfigSourceMachines]; ok { data.SourceMachinesCount, parseErr = cast.ToInt64E(val) if parseErr != nil { return data, parseErr } } return data, nil } func (s *hostService) GetGlobalLimitConfig(ctx context.Context, hostId int) (v1.GlobalLimitConfigResponse, error) { configsMap, err := s.getHostConfigsMap(ctx, hostId) if err != nil { return v1.GlobalLimitConfigResponse{}, err } data := v1.GlobalLimitConfigResponse{ MaxBytesMonth: "0", Bps: "0", IpCount: 0, Operator: 0, } if val, ok := configsMap[ConfigBps]; ok { data.Bps = val } //if val, ok := configsMap[ConfigMaxBytesMonth]; ok { // data.MaxBytesMonth = val //} if val, ok := configsMap[ConfigPortCount]; ok { data.PortCount, err = cast.ToIntE(val) if err != nil { return data, err } } if val, ok := configsMap[ConfigDomainCount]; ok { data.DomainCount, err = cast.ToIntE(val) if err != nil { return data, err } } if val, ok := configsMap[ConfigOperator]; ok { if val == "电信" { data.IpCount = 1 } if val == "BGP" { data.IpCount = 2 } } if val, ok := configsMap[ConfigIpCount]; ok { data.Operator, err = cast.ToIntE(val) if err != nil { return data, err } } return data, nil } // GetTcpLimitConfig 修正返回类型,并使用新的辅助函数 func (s *hostService) GetTcpLimitConfig(ctx context.Context, hostId int) (v1.TcpLimitRequest, error) { _, err := s.getHostConfigsMap(ctx, hostId) if err != nil { return v1.TcpLimitRequest{}, err } data := v1.TcpLimitRequest{ ConnCount: 0, ConnDuration: "0s", MaxConnCount: 0, } return data, nil // 返回结构体 } // GetUdpLimitConfig func (s *hostService) GetUdpLimitConfig(ctx context.Context, hostId int) (v1.UdpLimitRequest, error) { _, err := s.getHostConfigsMap(ctx, hostId) if err != nil { return v1.UdpLimitRequest{}, err } data := v1.UdpLimitRequest{ QosPacketCount: 0, QosPacketDuration: "0s", MaxConnCount: 0, } return data, nil } // GetWebLimitConfig 修正返回类型,并使用新的辅助函数 func (s *hostService) GetWebLimitConfig(ctx context.Context, hostId int) (v1.WebLimitRequest, error) { _, err := s.getHostConfigsMap(ctx, hostId) if err != nil { return v1.WebLimitRequest{}, err } data := v1.WebLimitRequest{ QpsCount: 0, QpsDuration: "0s", } return data, nil }