diff --git a/controller/channel.go b/controller/channel.go index 1137cfb..f9a0d0c 100644 --- a/controller/channel.go +++ b/controller/channel.go @@ -584,6 +584,10 @@ func validateChannel(channel *model.Channel, isAdd bool) error { return fmt.Errorf("channel cannot be empty") } + if strings.TrimSpace(channel.PublicName) == "" { + return fmt.Errorf("public name cannot be empty") + } + // 检查模型名称长度是否超过 255 for _, m := range channel.GetModels() { if len(m) > 255 { @@ -2110,6 +2114,7 @@ func GetUserChannelsForBinding(c *gin.Context) { result = append(result, gin.H{ "id": ch.Id, "name": ch.Name, + "public_name": ch.PublicName, "type": ch.Type, "remark": ch.Remark, }) diff --git a/model/ability.go b/model/ability.go index cf1ea67..30ae6cb 100644 --- a/model/ability.go +++ b/model/ability.go @@ -84,13 +84,14 @@ func GetModelChannelsForGroup(modelName string, group string) ([]map[string]any, } type channelInfo struct { - Id int `json:"id"` - Name string `json:"name"` + Id int `json:"id"` + Name string `json:"name"` + PublicName string `json:"public_name"` } var channels []channelInfo err = DB.Table("channels"). Where("id IN ? AND status = ?", channelIds, common.ChannelStatusEnabled). - Select("id, name"). + Select("id, name, public_name"). Find(&channels).Error if err != nil { return nil, 0, err @@ -109,8 +110,9 @@ func GetModelChannelsForGroup(modelName string, group string) ([]map[string]any, result := make([]map[string]any, 0, len(channels)) for _, ch := range channels { result = append(result, map[string]any{ - "id": ch.Id, - "name": ch.Name, + "id": ch.Id, + "name": ch.Name, + "public_name": ch.PublicName, }) } diff --git a/model/channel.go b/model/channel.go index 1da3637..a4f680f 100644 --- a/model/channel.go +++ b/model/channel.go @@ -26,6 +26,7 @@ type Channel struct { TestModel *string `json:"test_model"` Status int `json:"status" gorm:"default:1"` Name string `json:"name" gorm:"index"` + PublicName string `json:"public_name" gorm:"size:255;default:''"` Weight *uint `json:"weight" gorm:"default:0"` CreatedTime int64 `json:"created_time" gorm:"bigint"` TestTime int64 `json:"test_time" gorm:"bigint"` @@ -72,6 +73,13 @@ func (c ChannelInfo) Value() (driver.Value, error) { return common.Marshal(&c) } +func ChannelDisplayName(publicName, name string) string { + if publicName != "" { + return publicName + } + return name +} + // Scan implements sql.Scanner interface func (c *ChannelInfo) Scan(value interface{}) error { bytesValue, _ := value.([]byte) @@ -279,7 +287,7 @@ func GetAllChannels(startIdx int, num int, selectAll bool, idSort bool) ([]*Chan // 只返回 id, name, type, remark,不包含敏感信息 func GetAllChannelsForBinding() ([]*Channel, error) { var channels []*Channel - err := DB.Select("id, name, type, remark"). + err := DB.Select("id, name, public_name, type, remark"). Where("status = ?", common.ChannelStatusEnabled). Order("priority desc"). Find(&channels).Error diff --git a/model/channel_pricing.go b/model/channel_pricing.go index 67f861e..2707a9a 100644 --- a/model/channel_pricing.go +++ b/model/channel_pricing.go @@ -252,6 +252,7 @@ type ChannelPricingWithChannel struct { Id int `json:"id"` ChannelId int `json:"channel_id"` ChannelName string `json:"channel_name"` + ChannelPublicName string `json:"channel_public_name"` ChannelType int `json:"channel_type"` TagIds string `json:"tag_ids" gorm:"column:tag_ids"` // 渠道定价的标签ID列表(逗号分隔) Tags []*PricingTag `json:"tags" gorm:"-"` // 渠道定价的标签详情(不参与数据库扫描) @@ -296,7 +297,7 @@ func GetChannelPricingByModelWithChannelInfo(modelName string) ([]*ChannelPricin // 查询所有支持该模型的渠道,左连接渠道定价表 // 高级字段(cache/image/audio)不回退全局值,直接返回 0 err := DB.Table("abilities"). - Select(`abilities.channel_id, channels.name as channel_name, channels.type as channel_type, + Select(`abilities.channel_id, channels.name as channel_name, channels.public_name as channel_public_name, channels.type as channel_type, COALESCE(channel_pricings.quota_type, ?) as quota_type, COALESCE(channel_pricings.model_ratio, ?) as model_ratio, COALESCE(channel_pricings.completion_ratio, ?) as completion_ratio, @@ -316,7 +317,7 @@ func GetChannelPricingByModelWithChannelInfo(modelName string) ([]*ChannelPricin Where("abilities.model = ?", modelName). Where("abilities.enabled = ?", true). Where("channels.status = ?", 1). // 只显示启用的渠道 - Group("abilities.channel_id, channels.name, channels.type, channel_pricings.quota_type, channel_pricings.model_ratio, channel_pricings.completion_ratio, channel_pricings.model_price, channel_pricings.id, channel_pricings.tag_ids, channel_pricings.cache_ratio, channel_pricings.cache_creation_ratio, channel_pricings.image_ratio, channel_pricings.audio_ratio, channel_pricings.audio_completion_ratio, channel_pricings.is_default"). + Group("abilities.channel_id, channels.name, channels.public_name, channels.type, channel_pricings.quota_type, channel_pricings.model_ratio, channel_pricings.completion_ratio, channel_pricings.model_price, channel_pricings.id, channel_pricings.tag_ids, channel_pricings.cache_ratio, channel_pricings.cache_creation_ratio, channel_pricings.image_ratio, channel_pricings.audio_ratio, channel_pricings.audio_completion_ratio, channel_pricings.is_default"). Scan(&results).Error if err != nil { return nil, err diff --git a/model/main.go b/model/main.go index cf4f845..63a4412 100644 --- a/model/main.go +++ b/model/main.go @@ -304,6 +304,8 @@ func migrateDB() error { // 将现有 sort_order=0 的模型和供应商更新为默认大数 DB.Model(&Model{}).Where("sort_order = 0").Update("sort_order", 999999) DB.Model(&Vendor{}).Where("sort_order = 0").Update("sort_order", 999999) + migrateChannelPublicName() + return nil } @@ -693,3 +695,14 @@ func PingDB() error { common.SysLog("Database pinged successfully") return nil } + +func migrateChannelPublicName() { + result := DB.Model(&Channel{}). + Where("public_name = '' OR public_name IS NULL"). + Update("public_name", gorm.Expr("name")) + if result.Error != nil { + common.SysError("[Migration] migrateChannelPublicName failed: " + result.Error.Error()) + } else if result.RowsAffected > 0 { + common.SysLog(fmt.Sprintf("[Migration] migrateChannelPublicName: backfilled %d channels", result.RowsAffected)) + } +} diff --git a/model/pricing.go b/model/pricing.go index b483f61..13d7d9f 100644 --- a/model/pricing.go +++ b/model/pricing.go @@ -289,10 +289,11 @@ func updatePricing() { // 从渠道定价表加载实际定价数据(仅启用渠道),同时获取渠道名称 var allCPs []struct { ChannelPricing - ChannelName string + ChannelName string + ChannelPublicName string } DB.Table("channel_pricings"). - Select("channel_pricings.*, channels.name as channel_name"). + Select("channel_pricings.*, channels.name as channel_name, channels.public_name as channel_public_name"). Joins("JOIN channels ON channel_pricings.channel_id = channels.id"). Where("channels.status = 1 AND channel_pricings.deleted_at IS NULL"). Find(&allCPs) @@ -300,7 +301,7 @@ func updatePricing() { channelNameMap := make(map[int]string) for i := range allCPs { cpMap[allCPs[i].ModelName] = append(cpMap[allCPs[i].ModelName], allCPs[i].ChannelPricing) - channelNameMap[allCPs[i].ChannelId] = allCPs[i].ChannelName + channelNameMap[allCPs[i].ChannelId] = ChannelDisplayName(allCPs[i].ChannelPublicName, allCPs[i].ChannelName) } pricingMap = make([]Pricing, 0) diff --git a/web/src/components/playground/SettingsPanel.jsx b/web/src/components/playground/SettingsPanel.jsx index b9fcc37..ba5d015 100644 --- a/web/src/components/playground/SettingsPanel.jsx +++ b/web/src/components/playground/SettingsPanel.jsx @@ -177,11 +177,11 @@ const SettingsPanel = ({ /> - {/* 渠道选择 */} + {/* 通道选择 */}