Repository navigation
feat: CNY localization, channel UX fixes, and JSON editor improvements #4832
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 13 commits
71ea68f
9435a3d
e749047
bae904b
b9e177f
4c69588
3c35ddb
06fed0e
54fa429
fd90731
bfeaa8d
9e1db04
6357a5b
1ff60b5
45396fb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -40,18 +40,17 @@ func GetSubscription(c *gin.Context) { | |||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| quota := remainQuota + usedQuota | ||||||||||||||||||||||||||||||||||||||||||||
| amount := float64(quota) | ||||||||||||||||||||||||||||||||||||||||||||
| // OpenAI 兼容接口中的 *_USD 字段含义保持“额度单位”对应值: | ||||||||||||||||||||||||||||||||||||||||||||
| // 我们将其解释为以“站点展示类型”为准: | ||||||||||||||||||||||||||||||||||||||||||||
| // - USD: 直接除以 QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| // - CNY: 先转 USD 再乘汇率 | ||||||||||||||||||||||||||||||||||||||||||||
| // 计价基准为人民币:quota / QuotaPerUnit 直接得到 CNY | ||||||||||||||||||||||||||||||||||||||||||||
| // - CNY: 直接除以 QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| // - USD: 除以 QuotaPerUnit 再除以汇率 | ||||||||||||||||||||||||||||||||||||||||||||
| // - TOKENS: 直接使用 tokens 数量 | ||||||||||||||||||||||||||||||||||||||||||||
| switch operation_setting.GetQuotaDisplayType() { | ||||||||||||||||||||||||||||||||||||||||||||
| case operation_setting.QuotaDisplayTypeCNY: | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit * operation_setting.USDExchangeRate | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| case operation_setting.QuotaDisplayTypeTokens: | ||||||||||||||||||||||||||||||||||||||||||||
| // amount 保持 tokens 数值 | ||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit / operation_setting.USDExchangeRate | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
47
to
54
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Description: Check for USDExchangeRate validation in operation_setting
# Search for USDExchangeRate assignments and validation
rg -nP -C5 'USDExchangeRate\s*=' --type=go
# Search for validation patterns (> 0, != 0, etc.)
rg -nP 'USDExchangeRate.*[>!]=\s*0' --type=goRepository: QuantumNous/new-api Length of output: 860 🏁 Script executed: # Check the operation_setting package structure
find . -name "*operation_setting*" -type f | grep -E "\.(go|proto)$"Repository: QuantumNous/new-api Length of output: 112 🏁 Script executed: # Examine billing.go to see the actual code at lines 47-54 and around line 99
rg -n "GetQuotaDisplayType|GetUsage" --type=go -B2 -A10 | head -100Repository: QuantumNous/new-api Length of output: 6307 🏁 Script executed: # Check how USDExchangeRate is initialized and used in operation_setting
rg -n "USDExchangeRate" --type=go -B3 -A3Repository: QuantumNous/new-api Length of output: 3586 🏁 Script executed: # Read the operation_setting.go file to check its contents
cat -n setting/operation_setting/operation_setting.go | head -100Repository: QuantumNous/new-api Length of output: 1081 🏁 Script executed: # Check if USDExchangeRate has any getter function with validation
rg -n "func.*USDExchangeRate|USDExchangeRate\s*>" setting/operation_setting/ --type=goRepository: QuantumNous/new-api Length of output: 45 🏁 Script executed: # Check payment_setting_old.go and any other payment-related files
cat -n setting/operation_setting/payment_setting_old.go | head -50Repository: QuantumNous/new-api Length of output: 1474 🏁 Script executed: # Check the context around the USDExchangeRate assignment in model/option.go
sed -n '365,375p' model/option.goRepository: QuantumNous/new-api Length of output: 469 🏁 Script executed: # Search for any validation or guards around USDExchangeRate usage
rg -n "USDExchangeRate" --type=go -B2 -A2 | grep -E "(<=|>=|>|<|!=|==|if|validate|check|guard)" -B2 -A2Repository: QuantumNous/new-api Length of output: 305 🏁 Script executed: # Check if there's any initialization or validation logic when loading settings
rg -n "LoadOptions|InitOptions|USDExchangeRate" --type=go -B5 -A5 | head -80Repository: QuantumNous/new-api Length of output: 4805 🏁 Script executed: # Check if there are any guards around divisions by USDExchangeRate
rg -n "USDExchangeRate" controller/billing.go logger/logger.go --type=go -B5 | grep -E "(if|guard|validate|<=|>=)"Repository: QuantumNous/new-api Length of output: 45 🏁 Script executed: # Verify the entire context of controller/billing.go around the issue
sed -n '45,60p' controller/billing.go
sed -n '92,105p' controller/billing.goRepository: QuantumNous/new-api Length of output: 1027 Validate The default case divides by 🛡️ Proposed fix to add validation switch operation_setting.GetQuotaDisplayType() {
case operation_setting.QuotaDisplayTypeCNY:
amount = amount / common.QuotaPerUnit
case operation_setting.QuotaDisplayTypeTokens:
// amount 保持 tokens 数值
default:
+ if operation_setting.USDExchangeRate <= 0 {
+ operation_setting.USDExchangeRate = 1.0 // fallback to 1:1 if invalid
+ }
amount = amount / common.QuotaPerUnit / operation_setting.USDExchangeRate
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||
| if token != nil && token.UnlimitedQuota { | ||||||||||||||||||||||||||||||||||||||||||||
| amount = 100000000 | ||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -93,11 +92,11 @@ func GetUsage(c *gin.Context) { | |||||||||||||||||||||||||||||||||||||||||||
| amount := float64(quota) | ||||||||||||||||||||||||||||||||||||||||||||
| switch operation_setting.GetQuotaDisplayType() { | ||||||||||||||||||||||||||||||||||||||||||||
| case operation_setting.QuotaDisplayTypeCNY: | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit * operation_setting.USDExchangeRate | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| case operation_setting.QuotaDisplayTypeTokens: | ||||||||||||||||||||||||||||||||||||||||||||
| // tokens 保持原值 | ||||||||||||||||||||||||||||||||||||||||||||
| default: | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit | ||||||||||||||||||||||||||||||||||||||||||||
| amount = amount / common.QuotaPerUnit / operation_setting.USDExchangeRate | ||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||
| usage := OpenAIUsageResponse{ | ||||||||||||||||||||||||||||||||||||||||||||
| Object: "list", | ||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -118,15 +118,14 @@ func logHelper(ctx context.Context, level string, msg string) { | |
| } | ||
|
|
||
| func LogQuota(quota int) string { | ||
| // 新逻辑:根据额度展示类型输出 | ||
| // 计价基准为人民币,直接除以 QuotaPerUnit 即为 CNY | ||
| q := float64(quota) | ||
| switch operation_setting.GetQuotaDisplayType() { | ||
| case operation_setting.QuotaDisplayTypeCNY: | ||
| usd := q / common.QuotaPerUnit | ||
| cny := usd * operation_setting.USDExchangeRate | ||
| cny := q / common.QuotaPerUnit | ||
| return fmt.Sprintf("¥%.6f 额度", cny) | ||
| case operation_setting.QuotaDisplayTypeCustom: | ||
| usd := q / common.QuotaPerUnit | ||
| base := q / common.QuotaPerUnit | ||
| rate := operation_setting.GetGeneralSetting().CustomCurrencyExchangeRate | ||
| symbol := operation_setting.GetGeneralSetting().CustomCurrencySymbol | ||
| if symbol == "" { | ||
|
|
@@ -135,24 +134,24 @@ func LogQuota(quota int) string { | |
| if rate <= 0 { | ||
| rate = 1 | ||
| } | ||
| v := usd * rate | ||
| v := base * rate | ||
| return fmt.Sprintf("%s%.6f 额度", symbol, v) | ||
| case operation_setting.QuotaDisplayTypeTokens: | ||
| return fmt.Sprintf("%d 点额度", quota) | ||
| default: // USD | ||
| return fmt.Sprintf("$%.6f 额度", q/common.QuotaPerUnit) | ||
| usd := q / common.QuotaPerUnit / operation_setting.USDExchangeRate | ||
| return fmt.Sprintf("$%.6f 额度", usd) | ||
| } | ||
|
Comment on lines
141
to
144
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Validate USDExchangeRate before division. Line 142 (and line 168 in 🛡️ Proposed fix to add validation default: // USD
+ exchangeRate := operation_setting.USDExchangeRate
+ if exchangeRate <= 0 {
+ exchangeRate = 1.0
+ }
- usd := q / common.QuotaPerUnit / operation_setting.USDExchangeRate
+ usd := q / common.QuotaPerUnit / exchangeRate
return fmt.Sprintf("$%.6f 额度", usd)
}Apply a similar fix to 🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| func FormatQuota(quota int) string { | ||
| q := float64(quota) | ||
| switch operation_setting.GetQuotaDisplayType() { | ||
| case operation_setting.QuotaDisplayTypeCNY: | ||
| usd := q / common.QuotaPerUnit | ||
| cny := usd * operation_setting.USDExchangeRate | ||
| cny := q / common.QuotaPerUnit | ||
| return fmt.Sprintf("¥%.6f", cny) | ||
| case operation_setting.QuotaDisplayTypeCustom: | ||
| usd := q / common.QuotaPerUnit | ||
| base := q / common.QuotaPerUnit | ||
| rate := operation_setting.GetGeneralSetting().CustomCurrencyExchangeRate | ||
| symbol := operation_setting.GetGeneralSetting().CustomCurrencySymbol | ||
| if symbol == "" { | ||
|
|
@@ -161,12 +160,13 @@ func FormatQuota(quota int) string { | |
| if rate <= 0 { | ||
| rate = 1 | ||
| } | ||
| v := usd * rate | ||
| v := base * rate | ||
| return fmt.Sprintf("%s%.6f", symbol, v) | ||
| case operation_setting.QuotaDisplayTypeTokens: | ||
| return fmt.Sprintf("%d", quota) | ||
| default: | ||
| return fmt.Sprintf("$%.6f", q/common.QuotaPerUnit) | ||
| default: // USD | ||
| usd := q / common.QuotaPerUnit / operation_setting.USDExchangeRate | ||
| return fmt.Sprintf("$%.6f", usd) | ||
| } | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🌐 Web query:
What is the latest stable version of Go (golang)?💡 Result:
Latest stable version of Go (as of today, 2026-05-19): Go 1.26.3 [1]. This is shown on the official Go download page under “Stable versions”, listing “go1.26.3” as the latest stable release [1].
Citations:
Pin the Go version instead of using
latest.Using
golang:latestbreaks build reproducibility and can cause unexpected failures when a new Go version is released. While this solves the immediate problem of an unavailable tag (golang:1.26.1-alpinedoesn't exist), the proper fix is to use a valid pinned version.📌 Suggested fix
Use a recent pinned version (Go 1.26.3 is the current stable):
or with the full Debian image:
🤖 Prompt for AI Agents