Browse Source

feat(channel-pricing): Controller 扩展 API 支持新字段 + 输入校验 + 操作日志

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
master
fengsilin 3 weeks ago
parent
commit
646f37dd4b
1 changed files with 91 additions and 28 deletions
  1. +91
    -28
      controller/channel_pricing.go

+ 91
- 28
controller/channel_pricing.go View File

@@ -1,6 +1,7 @@
package controller

import (
"fmt"
"strconv"
"strings"

@@ -50,14 +51,19 @@ func GetChannelPricingByModel(c *gin.Context) {

// CreateChannelPricingRequest 创建渠道定价请求
type CreateChannelPricingRequest struct {
Id int `json:"id"`
ModelName string `json:"model_name" binding:"required"`
ChannelId int `json:"channel_id" binding:"required"`
QuotaType int `json:"quota_type"`
ModelRatio float64 `json:"model_ratio"`
CompletionRatio float64 `json:"completion_ratio"`
ModelPrice float64 `json:"model_price"`
TagIds string `json:"tag_ids"`
Id int `json:"id"`
ModelName string `json:"model_name" binding:"required"`
ChannelId int `json:"channel_id" binding:"required"`
QuotaType int `json:"quota_type"`
ModelRatio float64 `json:"model_ratio"`
CompletionRatio float64 `json:"completion_ratio"`
ModelPrice float64 `json:"model_price"`
TagIds string `json:"tag_ids"`
CacheRatio float64 `json:"cache_ratio"`
CacheCreationRatio float64 `json:"cache_creation_ratio"`
ImageRatio float64 `json:"image_ratio"`
AudioRatio float64 `json:"audio_ratio"`
AudioCompletionRatio float64 `json:"audio_completion_ratio"`
}

// CreateChannelPricing 创建或更新渠道定价
@@ -68,6 +74,11 @@ func CreateChannelPricing(c *gin.Context) {
return
}

if req.CacheRatio < 0 || req.CacheCreationRatio < 0 || req.ImageRatio < 0 || req.AudioRatio < 0 || req.AudioCompletionRatio < 0 {
common.ApiErrorMsg(c, "ratio values must be >= 0")
return
}

// 检查是否已存在
existing, _ := model.GetChannelPricing(req.ModelName, req.ChannelId)
if existing != nil {
@@ -77,29 +88,43 @@ func CreateChannelPricing(c *gin.Context) {
existing.CompletionRatio = req.CompletionRatio
existing.ModelPrice = req.ModelPrice
existing.TagIds = req.TagIds
existing.CacheRatio = req.CacheRatio
existing.CacheCreationRatio = req.CacheCreationRatio
existing.ImageRatio = req.ImageRatio
existing.AudioRatio = req.AudioRatio
existing.AudioCompletionRatio = req.AudioCompletionRatio
if err := existing.Update(); err != nil {
common.ApiError(c, err)
return
}
common.SysLog(fmt.Sprintf("[ChannelPricing] updated: id=%d model=%s channel=%d", existing.Id, existing.ModelName, existing.ChannelId))
common.ApiSuccess(c, existing)
return
}

// 创建
cp := &model.ChannelPricing{
ModelName: req.ModelName,
ChannelId: req.ChannelId,
QuotaType: req.QuotaType,
ModelRatio: req.ModelRatio,
CompletionRatio: req.CompletionRatio,
ModelPrice: req.ModelPrice,
TagIds: req.TagIds,
ModelName: req.ModelName,
ChannelId: req.ChannelId,
QuotaType: req.QuotaType,
ModelRatio: req.ModelRatio,
CompletionRatio: req.CompletionRatio,
ModelPrice: req.ModelPrice,
TagIds: req.TagIds,
CacheRatio: req.CacheRatio,
CacheCreationRatio: req.CacheCreationRatio,
ImageRatio: req.ImageRatio,
AudioRatio: req.AudioRatio,
AudioCompletionRatio: req.AudioCompletionRatio,
}
if err := cp.Insert(); err != nil {
common.ApiError(c, err)
return
}

common.SysLog(fmt.Sprintf("[ChannelPricing] created: model=%s channel=%d quotaType=%d modelRatio=%.4f completionRatio=%.4f modelPrice=%.4f cacheRatio=%.4f cacheCreationRatio=%.4f imageRatio=%.4f audioRatio=%.4f audioCompletionRatio=%.4f",
req.ModelName, req.ChannelId, req.QuotaType, req.ModelRatio, req.CompletionRatio, req.ModelPrice,
req.CacheRatio, req.CacheCreationRatio, req.ImageRatio, req.AudioRatio, req.AudioCompletionRatio))
common.ApiSuccess(c, cp)
}

@@ -119,13 +144,18 @@ func BatchCreateChannelPricing(c *gin.Context) {
pricings := make([]*model.ChannelPricing, 0, len(req.Items))
for _, item := range req.Items {
pricings = append(pricings, &model.ChannelPricing{
ModelName: item.ModelName,
ChannelId: item.ChannelId,
QuotaType: item.QuotaType,
ModelRatio: item.ModelRatio,
CompletionRatio: item.CompletionRatio,
ModelPrice: item.ModelPrice,
TagIds: item.TagIds,
ModelName: item.ModelName,
ChannelId: item.ChannelId,
QuotaType: item.QuotaType,
ModelRatio: item.ModelRatio,
CompletionRatio: item.CompletionRatio,
ModelPrice: item.ModelPrice,
TagIds: item.TagIds,
CacheRatio: item.CacheRatio,
CacheCreationRatio: item.CacheCreationRatio,
ImageRatio: item.ImageRatio,
AudioRatio: item.AudioRatio,
AudioCompletionRatio: item.AudioCompletionRatio,
})
}

@@ -138,6 +168,11 @@ func BatchCreateChannelPricing(c *gin.Context) {
existing.CompletionRatio = cp.CompletionRatio
existing.ModelPrice = cp.ModelPrice
existing.TagIds = cp.TagIds
existing.CacheRatio = cp.CacheRatio
existing.CacheCreationRatio = cp.CacheCreationRatio
existing.ImageRatio = cp.ImageRatio
existing.AudioRatio = cp.AudioRatio
existing.AudioCompletionRatio = cp.AudioCompletionRatio
if err := existing.Update(); err != nil {
common.ApiError(c, err)
return
@@ -168,6 +203,7 @@ func DeleteChannelPricing(c *gin.Context) {
return
}

common.SysLog(fmt.Sprintf("[ChannelPricing] deleted: id=%d", id))
common.ApiSuccess(c, nil)
}

@@ -204,6 +240,22 @@ func CopyGlobalPricing(c *gin.Context) {
continue
}

// 获取全局扩展比率
globalCacheRatio, hasCacheRatio := ratio_setting.GetCacheRatio(ability.Model)
if !hasCacheRatio {
globalCacheRatio = 0
}
globalCacheCreationRatio, hasCacheCreationRatio := ratio_setting.GetCreateCacheRatio(ability.Model)
if !hasCacheCreationRatio {
globalCacheCreationRatio = 0
}
globalImageRatio, hasImageRatio := ratio_setting.GetImageRatio(ability.Model)
if !hasImageRatio {
globalImageRatio = 0
}
globalAudioRatio := ratio_setting.GetAudioRatio(ability.Model)
globalAudioCompletionRatio := ratio_setting.GetAudioCompletionRatio(ability.Model)

// 确定定价类型
var quotaType int
var ratio, completionRatio, price float64
@@ -228,17 +280,27 @@ func CopyGlobalPricing(c *gin.Context) {
existing.ModelRatio = ratio
existing.CompletionRatio = completionRatio
existing.ModelPrice = price
existing.CacheRatio = globalCacheRatio
existing.CacheCreationRatio = globalCacheCreationRatio
existing.ImageRatio = globalImageRatio
existing.AudioRatio = globalAudioRatio
existing.AudioCompletionRatio = globalAudioCompletionRatio
if err := existing.Update(); err == nil {
imported++
}
} else {
cp := &model.ChannelPricing{
ModelName: ability.Model,
ChannelId: channelId,
QuotaType: quotaType,
ModelRatio: ratio,
CompletionRatio: completionRatio,
ModelPrice: price,
ModelName: ability.Model,
ChannelId: channelId,
QuotaType: quotaType,
ModelRatio: ratio,
CompletionRatio: completionRatio,
ModelPrice: price,
CacheRatio: globalCacheRatio,
CacheCreationRatio: globalCacheCreationRatio,
ImageRatio: globalImageRatio,
AudioRatio: globalAudioRatio,
AudioCompletionRatio: globalAudioCompletionRatio,
}
if err := cp.Insert(); err == nil {
imported++
@@ -246,6 +308,7 @@ func CopyGlobalPricing(c *gin.Context) {
}
}

common.SysLog(fmt.Sprintf("[ChannelPricing] copyGlobalPricing: channel=%d imported=%d/%d", channelId, imported, len(abilities)))
common.ApiSuccess(c, gin.H{
"total": len(abilities),
"imported": imported,


Loading…
Cancel
Save