diff --git a/model/channel_pricing.go b/model/channel_pricing.go new file mode 100644 index 0000000..7b2453a --- /dev/null +++ b/model/channel_pricing.go @@ -0,0 +1,93 @@ +package model + +import ( + "github.com/QuantumNous/new-api/common" + "gorm.io/gorm" +) + +// QuotaType 计费类型 +const ( + QuotaTypeByTokens = 0 // 按量计费 + QuotaTypeByCall = 1 // 按次计费 +) + +// ChannelPricing 渠道定价表 +// 支持同一模型在不同渠道设置不同价格 +type ChannelPricing struct { + Id int `json:"id" gorm:"primaryKey"` + ModelName string `json:"model_name" gorm:"size:128;not null;uniqueIndex:idx_model_channel,priority:1"` + ChannelId int `json:"channel_id" gorm:"not null;uniqueIndex:idx_model_channel,priority:2;index"` + QuotaType int `json:"quota_type" gorm:"default:0"` // 0=按量, 1=按次 + ModelRatio float64 `json:"model_ratio" gorm:"default:0"` + CompletionRatio float64 `json:"completion_ratio" gorm:"default:0"` + ModelPrice float64 `json:"model_price" gorm:"default:0"` + TagIds string `json:"tag_ids" gorm:"type:varchar(255)"` // 逗号分隔的标签ID + CreatedTime int64 `json:"created_time" gorm:"bigint"` + UpdatedTime int64 `json:"updated_time" gorm:"bigint"` + DeletedAt gorm.DeletedAt `json:"-" gorm:"index"` +} + +func (cp *ChannelPricing) Insert() error { + now := common.GetTimestamp() + cp.CreatedTime = now + cp.UpdatedTime = now + return DB.Create(cp).Error +} + +func (cp *ChannelPricing) Update() error { + cp.UpdatedTime = common.GetTimestamp() + return DB.Model(&ChannelPricing{}).Where("id = ?", cp.Id).Updates(map[string]interface{}{ + "quota_type": cp.QuotaType, + "model_ratio": cp.ModelRatio, + "completion_ratio": cp.CompletionRatio, + "model_price": cp.ModelPrice, + "tag_ids": cp.TagIds, + "updated_time": cp.UpdatedTime, + }).Error +} + +func (cp *ChannelPricing) Delete() error { + return DB.Delete(cp).Error +} + +// GetChannelPricing 获取指定模型在指定渠道的定价 +func GetChannelPricing(modelName string, channelId int) (*ChannelPricing, error) { + var cp ChannelPricing + err := DB.Where("model_name = ? AND channel_id = ?", modelName, channelId).First(&cp).Error + if err != nil { + return nil, err + } + return &cp, nil +} + +// GetChannelPricingByModel 获取指定模型的所有渠道定价 +func GetChannelPricingByModel(modelName string) ([]*ChannelPricing, error) { + var list []*ChannelPricing + err := DB.Where("model_name = ?", modelName).Find(&list).Error + return list, err +} + +// GetAllChannelPricing 获取所有渠道定价(分页) +func GetAllChannelPricing(offset int, limit int) ([]*ChannelPricing, int64, error) { + var list []*ChannelPricing + var total int64 + if err := DB.Model(&ChannelPricing{}).Count(&total).Error; err != nil { + return nil, 0, err + } + err := DB.Order("id DESC").Offset(offset).Limit(limit).Find(&list).Error + return list, total, err +} + +// BatchUpsertChannelPricing 批量创建或更新渠道定价 +func BatchUpsertChannelPricing(pricings []*ChannelPricing) error { + if len(pricings) == 0 { + return nil + } + now := common.GetTimestamp() + for _, cp := range pricings { + cp.CreatedTime = now + cp.UpdatedTime = now + } + // GORM 的 GORM:OnConflict 会自动处理唯一键冲突 + return DB.Create(&pricings).Error +}