package controller import ( "fmt" "math" "strings" "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/model" "github.com/QuantumNous/new-api/service" "github.com/QuantumNous/new-api/setting/ratio_setting" "github.com/gin-gonic/gin" ) // resolveCurrentUser 从 gin.Context 解析当前登录用户信息。 // 未登录或查询失败时 loggedIn=false,groupRatio=1.0。 func resolveCurrentUser(c *gin.Context) (loggedIn bool, userId int, userGroup string, groupRatio float64) { groupRatio = 1.0 raw, exists := c.Get("id") if !exists { return } userId = raw.(int) user, err := model.GetUserCache(userId) if err != nil { return } loggedIn = true userGroup = user.Group groupRatio = service.GetUserGroupRatio(userGroup, userGroup) return } func filterPricingByUsableGroups(pricing []model.Pricing, usableGroup map[string]string) []model.Pricing { if len(pricing) == 0 { return pricing } if len(usableGroup) == 0 { return []model.Pricing{} } filtered := make([]model.Pricing, 0, len(pricing)) for _, item := range pricing { if common.StringsContains(item.EnableGroup, "all") { filtered = append(filtered, item) continue } for _, group := range item.EnableGroup { if _, ok := usableGroup[group]; ok { filtered = append(filtered, item) break } } } return filtered } func GetPricing(c *gin.Context) { pricing := model.GetPricing() userId, exists := c.Get("id") usableGroup := map[string]string{} groupRatio := map[string]float64{} for s, f := range ratio_setting.GetGroupRatioCopy() { groupRatio[s] = f } var group string if exists { user, err := model.GetUserCache(userId.(int)) if err == nil { group = user.Group for g := range groupRatio { ratio, ok := ratio_setting.GetGroupGroupRatio(group, g) if ok { groupRatio[g] = ratio } } } } usableGroup = service.GetUserUsableGroups(group) pricing = filterPricingByUsableGroups(pricing, usableGroup) // check groupRatio contains usableGroup for group := range ratio_setting.GetGroupRatioCopy() { if _, ok := usableGroup[group]; !ok { delete(groupRatio, group) } } c.JSON(200, gin.H{ "success": true, "data": pricing, "vendors": model.GetVendors(), "group_ratio": groupRatio, "usable_group": usableGroup, "supported_endpoint": model.GetSupportedEndpointMap(), "auto_groups": service.GetUserAutoGroup(group), "_": "a42d372ccf0b5dd13ecf71203521f9d2", }) } // GetUserPricing 获取用户对指定模型的价格信息(原价 vs 用户价) func GetUserPricing(c *gin.Context) { modelName := c.Param("model") // *model 通配符返回值带前导 /,需要去掉 modelName = strings.TrimPrefix(modelName, "/") if modelName == "" { common.ApiErrorMsg(c, "模型名不能为空") return } pricingData := model.GetPricingByModel(modelName) if pricingData == nil { common.ApiErrorMsg(c, "未找到该模型的定价信息") return } loggedIn, userId, userGroup, groupRatio := resolveCurrentUser(c) if !loggedIn { respondOriginalPrice(c, pricingData) return } bestUserChannelRatio := model.GetBestUserChannelRatio(userId, modelName) totalRatio := groupRatio * bestUserChannelRatio savingsPercent := int(math.Round((1 - totalRatio) * 100)) result := gin.H{ "success": true, "model_name": pricingData.ModelName, "quota_type": pricingData.QuotaType, "group": userGroup, "group_ratio": groupRatio, "user_channel_ratio": bestUserChannelRatio, "savings_percent": savingsPercent, "logged_in": true, } if pricingData.QuotaType == model.QuotaTypeByTokens { originalInput := pricingData.ModelRatio * 2 originalOutput := pricingData.ModelRatio * pricingData.CompletionRatio * 2 result["original_input"] = originalInput result["original_output"] = originalOutput result["user_input"] = originalInput * totalRatio result["user_output"] = originalOutput * totalRatio } else { result["original_price"] = pricingData.ModelPrice result["user_price"] = pricingData.ModelPrice * totalRatio } if savingsPercent > 0 { result["discount"] = formatDiscount(totalRatio) } c.JSON(200, result) } // respondOriginalPrice 未登录或用户查询失败时,只返回原价 func respondOriginalPrice(c *gin.Context, pricingData *model.Pricing) { result := gin.H{ "success": true, "model_name": pricingData.ModelName, "quota_type": pricingData.QuotaType, "logged_in": false, } if pricingData.QuotaType == model.QuotaTypeByTokens { result["original_input"] = pricingData.ModelRatio * 2 result["original_output"] = pricingData.ModelRatio * pricingData.CompletionRatio * 2 } else { result["original_price"] = pricingData.ModelPrice } c.JSON(200, result) } // formatDiscount 将倍率转换为中文折扣格式 func formatDiscount(ratio float64) string { if ratio <= 0 { return "免费" } discount := int(math.Round(ratio * 10)) if discount >= 10 { return "" } remainder := int(math.Round(ratio*100)) % 10 if remainder == 0 { return fmt.Sprintf("%d折", discount) } return fmt.Sprintf("%.1f折", ratio*10) } func ResetModelRatio(c *gin.Context) { defaultStr := ratio_setting.DefaultModelRatio2JSONString() err := model.UpdateOption("ModelRatio", defaultStr) if err != nil { c.JSON(200, gin.H{ "success": false, "message": err.Error(), }) return } err = ratio_setting.UpdateModelRatioByJSONString(defaultStr) if err != nil { c.JSON(200, gin.H{ "success": false, "message": err.Error(), }) return } c.JSON(200, gin.H{ "success": true, "message": "重置模型倍率成功", }) }