package service import ( "context" "fmt" "sort" "strings" ) // AvailableGroupRef 渠道视图中关联分组的简要信息。 type AvailableGroupRef struct { ID int64 Name string Platform string } // AvailableChannel 可用渠道视图:用于「可用渠道」页面展示渠道基础信息 + // 关联的分组 + 推导出的支持模型列表(无通配符)。 type AvailableChannel struct { ID int64 Name string Description string Status string BillingModelSource string RestrictModels bool Groups []AvailableGroupRef SupportedModels []SupportedModel } // ListAvailable 返回所有渠道的可用视图:每个渠道附带关联分组信息与支持模型列表。 // // 支持模型通过 (*Channel).SupportedModels() 计算得到(见 channel.go)。 // 关联分组信息通过 groupRepo.ListActive 查询后按 ID 映射;渠道 GroupIDs 中未在活跃列表中 // 的分组(已停用或删除)会被忽略。 func (s *ChannelService) ListAvailable(ctx context.Context) ([]AvailableChannel, error) { channels, err := s.repo.ListAll(ctx) if err != nil { return nil, fmt.Errorf("list channels: %w", err) } groupByID := make(map[int64]AvailableGroupRef) if s.groupRepo != nil { groups, err := s.groupRepo.ListActive(ctx) if err != nil { return nil, fmt.Errorf("list active groups: %w", err) } for i := range groups { g := groups[i] groupByID[g.ID] = AvailableGroupRef{ ID: g.ID, Name: g.Name, Platform: g.Platform, } } } out := make([]AvailableChannel, 0, len(channels)) for i := range channels { ch := &channels[i] groups := make([]AvailableGroupRef, 0, len(ch.GroupIDs)) for _, gid := range ch.GroupIDs { if ref, ok := groupByID[gid]; ok { groups = append(groups, ref) } } sort.Slice(groups, func(i, j int) bool { return groups[i].Name < groups[j].Name }) billingSource := ch.BillingModelSource if billingSource == "" { billingSource = BillingModelSourceChannelMapped } out = append(out, AvailableChannel{ ID: ch.ID, Name: ch.Name, Description: ch.Description, Status: ch.Status, BillingModelSource: billingSource, RestrictModels: ch.RestrictModels, Groups: groups, SupportedModels: ch.SupportedModels(), }) } sort.SliceStable(out, func(i, j int) bool { return strings.ToLower(out[i].Name) < strings.ToLower(out[j].Name) }) return out, nil }