From 15f65bb55868999cf44bc1fdadbd9fa8f0aeeb3a Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Thu, 17 Jul 2025 23:04:45 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=90=20feat:=20add=20configurable=20USD?= =?UTF-8?q?=20exchange-rate=20support=20across=20backend=20&=20frontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Backend - setting/payment.go: introduce default `USDExchangeRate` (7.3) - model/option.go: • inject `USDExchangeRate` into `InitOptionMap` • persist & sync value in `updateOptionMap` - controller/misc.go: expose `usd_exchange_rate` via `/api/status` Frontend - OperationSetting.js & SettingsGeneral.js: • extend state/inputs with `USDExchangeRate` • add form field “美元汇率 (non-top-up rate, pricing only)” - ModelPricing.js already consumes `status.usd_exchange_rate`; no change needed API - Administrators can update the rate via `PUT /api/option` (key: `USDExchangeRate`) - All clients receive the latest rate through `GET /api/status` This closes the end-to-end flow for displaying model prices in both USD and CNY based on a configurable exchange rate. --- controller/misc.go | 1 + model/option.go | 3 +++ setting/payment.go | 1 + web/src/components/settings/OperationSetting.js | 1 + web/src/i18n/locales/en.json | 4 +++- web/src/pages/Setting/Operation/SettingsGeneral.js | 11 +++++++++++ 6 files changed, 20 insertions(+), 1 deletion(-) diff --git a/controller/misc.go b/controller/misc.go index ea52cbe5..e89909d1 100644 --- a/controller/misc.go +++ b/controller/misc.go @@ -77,6 +77,7 @@ func GetStatus(c *gin.Context) { "self_use_mode_enabled": operation_setting.SelfUseModeEnabled, "default_use_auto_group": setting.DefaultUseAutoGroup, "pay_methods": setting.PayMethods, + "usd_exchange_rate": setting.USDExchangeRate, // 面板启用开关 "api_info_enabled": cs.ApiInfoEnabled, diff --git a/model/option.go b/model/option.go index ea72e5ee..9e58a81d 100644 --- a/model/option.go +++ b/model/option.go @@ -74,6 +74,7 @@ func InitOptionMap() { common.OptionMap["EpayId"] = "" common.OptionMap["EpayKey"] = "" common.OptionMap["Price"] = strconv.FormatFloat(setting.Price, 'f', -1, 64) + common.OptionMap["USDExchangeRate"] = strconv.FormatFloat(setting.USDExchangeRate, 'f', -1, 64) common.OptionMap["MinTopUp"] = strconv.Itoa(setting.MinTopUp) common.OptionMap["TopupGroupRatio"] = common.TopupGroupRatio2JSONString() common.OptionMap["Chats"] = setting.Chats2JsonString() @@ -306,6 +307,8 @@ func updateOptionMap(key string, value string) (err error) { setting.EpayKey = value case "Price": setting.Price, _ = strconv.ParseFloat(value, 64) + case "USDExchangeRate": + setting.USDExchangeRate, _ = strconv.ParseFloat(value, 64) case "MinTopUp": setting.MinTopUp, _ = strconv.Atoi(value) case "TopupGroupRatio": diff --git a/setting/payment.go b/setting/payment.go index 3fc0f14a..7fc5ad3f 100644 --- a/setting/payment.go +++ b/setting/payment.go @@ -8,6 +8,7 @@ var EpayId = "" var EpayKey = "" var Price = 7.3 var MinTopUp = 1 +var USDExchangeRate = 7.3 var PayMethods = []map[string]string{ { diff --git a/web/src/components/settings/OperationSetting.js b/web/src/components/settings/OperationSetting.js index baebe026..899fa30a 100644 --- a/web/src/components/settings/OperationSetting.js +++ b/web/src/components/settings/OperationSetting.js @@ -19,6 +19,7 @@ const OperationSetting = () => { TopUpLink: '', 'general_setting.docs_link': '', QuotaPerUnit: 0, + USDExchangeRate: 0, RetryTimes: 0, DisplayInCurrencyEnabled: false, DisplayTokenStatEnabled: false, diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 9e62d25e..1ff11e1f 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -1779,5 +1779,7 @@ "将仅保留第一个密钥文件,其余文件将被移除,是否继续?": "Only the first key file will be retained, and the remaining files will be removed. Continue?", "自定义模型名称": "Custom model name", "启用全部密钥": "Enable all keys", - "以充值价格显示": "Show with recharge price" + "以充值价格显示": "Show with recharge price", + "美元汇率(非充值汇率,仅用于定价页面换算)": "USD exchange rate (not recharge rate, only used for pricing page conversion)", + "美元汇率": "USD exchange rate" } \ No newline at end of file diff --git a/web/src/pages/Setting/Operation/SettingsGeneral.js b/web/src/pages/Setting/Operation/SettingsGeneral.js index cc774ef8..3ca9c377 100644 --- a/web/src/pages/Setting/Operation/SettingsGeneral.js +++ b/web/src/pages/Setting/Operation/SettingsGeneral.js @@ -26,6 +26,7 @@ export default function GeneralSettings(props) { 'general_setting.docs_link': '', QuotaPerUnit: '', RetryTimes: '', + USDExchangeRate: '', DisplayInCurrencyEnabled: false, DisplayTokenStatEnabled: false, DefaultCollapseSidebar: false, @@ -129,6 +130,16 @@ export default function GeneralSettings(props) { onClick={() => setShowQuotaWarning(true)} /> + + +