-
- {t('输入')} {priceData.inputPrice} / 1{priceData.unitLabel} tokens
+ return (
+
+ {priceItems.map((item) => (
+
+ {item.label} {item.value}
+ {item.suffix}
-
- {t('输出')} {priceData.completionPrice} / 1{priceData.unitLabel}{' '}
- tokens
-
-
- );
- } else {
- return (
-
- {t('模型价格')}:{priceData.price}
-
- );
- }
+ ))}
+
+ );
},
};
diff --git a/web/src/helpers/utils.jsx b/web/src/helpers/utils.jsx
index 5ce83e67..6fea484d 100644
--- a/web/src/helpers/utils.jsx
+++ b/web/src/helpers/utils.jsx
@@ -648,20 +648,9 @@ export const calculateModelPrice = ({
if (record.quota_type === 0) {
// 按量计费
const inputRatioPriceUSD = record.model_ratio * 2 * usedGroupRatio;
- const completionRatioPriceUSD =
- record.model_ratio * record.completion_ratio * 2 * usedGroupRatio;
-
const unitDivisor = tokenUnit === 'K' ? 1000 : 1;
const unitLabel = tokenUnit === 'K' ? 'K' : 'M';
- const rawDisplayInput = displayPrice(inputRatioPriceUSD);
- const rawDisplayCompletion = displayPrice(completionRatioPriceUSD);
-
- const numInput =
- parseFloat(rawDisplayInput.replace(/[^0-9.]/g, '')) / unitDivisor;
- const numCompletion =
- parseFloat(rawDisplayCompletion.replace(/[^0-9.]/g, '')) / unitDivisor;
-
let symbol = '$';
if (currency === 'CNY') {
symbol = '¥';
@@ -678,9 +667,48 @@ export const calculateModelPrice = ({
symbol = '¤';
}
}
+
+ const formatTokenPrice = (priceUSD) => {
+ const rawDisplayPrice = displayPrice(priceUSD);
+ const numericPrice =
+ parseFloat(rawDisplayPrice.replace(/[^0-9.]/g, '')) / unitDivisor;
+ return `${symbol}${numericPrice.toFixed(precision)}`;
+ };
+
+ const hasRatioValue = (value) =>
+ value !== undefined &&
+ value !== null &&
+ value !== '' &&
+ Number.isFinite(Number(value));
+
+ const inputPrice = formatTokenPrice(inputRatioPriceUSD);
+ const audioInputPrice = hasRatioValue(record.audio_ratio)
+ ? formatTokenPrice(inputRatioPriceUSD * Number(record.audio_ratio))
+ : null;
+
return {
- inputPrice: `${symbol}${numInput.toFixed(precision)}`,
- completionPrice: `${symbol}${numCompletion.toFixed(precision)}`,
+ inputPrice,
+ completionPrice: formatTokenPrice(
+ inputRatioPriceUSD * Number(record.completion_ratio),
+ ),
+ cachePrice: hasRatioValue(record.cache_ratio)
+ ? formatTokenPrice(inputRatioPriceUSD * Number(record.cache_ratio))
+ : null,
+ createCachePrice: hasRatioValue(record.create_cache_ratio)
+ ? formatTokenPrice(inputRatioPriceUSD * Number(record.create_cache_ratio))
+ : null,
+ imagePrice: hasRatioValue(record.image_ratio)
+ ? formatTokenPrice(inputRatioPriceUSD * Number(record.image_ratio))
+ : null,
+ audioInputPrice,
+ audioOutputPrice:
+ audioInputPrice && hasRatioValue(record.audio_completion_ratio)
+ ? formatTokenPrice(
+ inputRatioPriceUSD *
+ Number(record.audio_ratio) *
+ Number(record.audio_completion_ratio),
+ )
+ : null,
unitLabel,
isPerToken: true,
usedGroup,
@@ -710,26 +738,76 @@ export const calculateModelPrice = ({
};
};
-// 格式化价格信息(用于卡片视图)
-export const formatPriceInfo = (priceData, t) => {
+export const getModelPriceItems = (priceData, t) => {
if (priceData.isPerToken) {
- return (
- <>
-
- {t('输入')} {priceData.inputPrice}/{priceData.unitLabel}
-
-
- {t('输出')} {priceData.completionPrice}/{priceData.unitLabel}
-
- >
- );
+ const unitSuffix = ` / 1${priceData.unitLabel} Tokens`;
+ return [
+ {
+ key: 'input',
+ label: t('输入价格'),
+ value: priceData.inputPrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'completion',
+ label: t('补全价格'),
+ value: priceData.completionPrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'cache',
+ label: t('缓存读取价格'),
+ value: priceData.cachePrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'create-cache',
+ label: t('缓存创建价格'),
+ value: priceData.createCachePrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'image',
+ label: t('图片输入价格'),
+ value: priceData.imagePrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'audio-input',
+ label: t('音频输入价格'),
+ value: priceData.audioInputPrice,
+ suffix: unitSuffix,
+ },
+ {
+ key: 'audio-output',
+ label: t('音频补全价格'),
+ value: priceData.audioOutputPrice,
+ suffix: unitSuffix,
+ },
+ ].filter((item) => item.value !== null && item.value !== undefined && item.value !== '');
}
+ return [
+ {
+ key: 'fixed',
+ label: t('模型价格'),
+ value: priceData.price,
+ suffix: ` / ${t('次')}`,
+ },
+ ].filter((item) => item.value !== null && item.value !== undefined && item.value !== '');
+};
+
+// 格式化价格信息(用于卡片视图)
+export const formatPriceInfo = (priceData, t) => {
+ const items = getModelPriceItems(priceData, t);
return (
<>
-
- {t('模型价格')} {priceData.price}
-
+ {items.map((item) => (
+
+ {item.label} {item.value}
+ {item.suffix}
+
+ ))}
>
);
};
diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index 948ae78a..a4d1060b 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -1398,7 +1398,8 @@
"按价格设置": "Set by price",
"按倍率类型筛选": "Filter by ratio type",
"按倍率设置": "Set by ratio",
- "按次计费": "Pay per view",
+ "按次": "Per request",
+ "按次计费": "Pay per request",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
"按量计费": "Pay as you go",
"按顺序替换content中的变量占位符": "Replace variable placeholders in content in order",
@@ -1846,7 +1847,7 @@
"模板应用失败": "",
"模板示例": "Template example",
"模糊搜索模型名称": "Fuzzy search model name",
- "次": "times",
+ "次": "request",
"欢迎使用,请完成以下设置以开始使用系统": "Welcome! Please complete the following settings to start using the system",
"欧元": "EUR",
"正在加载可用部署位置...": "Loading available deployment locations...",
@@ -3223,7 +3224,7 @@
"扩展价格": "Additional Pricing",
"额外价格项": "Additional price items",
"补全价格": "Completion Price",
- "提示缓存价格": "Input Cache Read Price",
+ "缓存读取价格": "Input Cache Read Price",
"缓存创建价格": "Input Cache Creation Price",
"图片输入价格": "Image Input Price",
"音频输入价格": "Audio Input Price",
diff --git a/web/src/i18n/locales/fr.json b/web/src/i18n/locales/fr.json
index 891a70ba..6f2a6b4e 100644
--- a/web/src/i18n/locales/fr.json
+++ b/web/src/i18n/locales/fr.json
@@ -1398,7 +1398,8 @@
"按价格设置": "Définir par prix",
"按倍率类型筛选": "Filtrer par type de ratio",
"按倍率设置": "Définir par ratio",
- "按次计费": "Paiement à la séance",
+ "按次": "Par requête",
+ "按次计费": "Paiement par requête",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Entrez au format : AccessKey|SecretAccessKey|Region",
"按量计费": "Paiement à l'utilisation",
"按顺序替换content中的变量占位符": "Remplacer les espaces réservés de variable dans le contenu dans l'ordre",
@@ -1835,7 +1836,7 @@
"模板应用失败": "",
"模板示例": "Exemple de modèle",
"模糊搜索模型名称": "Recherche floue de nom de modèle",
- "次": "Fois",
+ "次": "requête",
"欢迎使用,请完成以下设置以开始使用系统": "Bienvenue, veuillez compléter les paramètres suivants pour commencer à utiliser le système",
"欧元": "Euro",
"正在加载可用部署位置...": "Loading available deployment locations...",
@@ -3192,7 +3193,7 @@
"扩展价格": "Prix supplémentaires",
"额外价格项": "Éléments de prix supplémentaires",
"补全价格": "Prix de complétion",
- "提示缓存价格": "Prix de lecture du cache d'entrée",
+ "缓存读取价格": "Prix de lecture du cache d'entrée",
"缓存创建价格": "Prix de création du cache d'entrée",
"图片输入价格": "Prix d'entrée image",
"音频输入价格": "Prix d'entrée audio",
diff --git a/web/src/i18n/locales/ja.json b/web/src/i18n/locales/ja.json
index 6aa49d92..5bdd764f 100644
--- a/web/src/i18n/locales/ja.json
+++ b/web/src/i18n/locales/ja.json
@@ -1381,7 +1381,8 @@
"按价格设置": "料金設定",
"按倍率类型筛选": "倍率タイプで絞り込み",
"按倍率设置": "倍率設定",
- "按次计费": "リクエスト課金",
+ "按次": "リクエストごと",
+ "按次计费": "リクエストごとの課金",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
"按量计费": "従量課金",
"按顺序替换content中的变量占位符": "content内の変数プレースホルダーを順番に置換します",
@@ -1818,7 +1819,7 @@
"模板应用失败": "",
"模板示例": "テンプレートサンプル",
"模糊搜索模型名称": "モデル名であいまい検索",
- "次": "回",
+ "次": "リクエスト",
"欢迎使用,请完成以下设置以开始使用系统": "ようこそ。システムを利用開始するには、以下の設定を完了してください",
"欧元": "EUR",
"正在加载可用部署位置...": "Loading available deployment locations...",
@@ -3173,7 +3174,7 @@
"扩展价格": "追加価格",
"额外价格项": "追加価格項目",
"补全价格": "補完価格",
- "提示缓存价格": "入力キャッシュ読み取り価格",
+ "缓存读取价格": "入力キャッシュ読み取り価格",
"缓存创建价格": "入力キャッシュ作成価格",
"图片输入价格": "画像入力価格",
"音频输入价格": "音声入力価格",
diff --git a/web/src/i18n/locales/ru.json b/web/src/i18n/locales/ru.json
index f003d0a9..f89fe080 100644
--- a/web/src/i18n/locales/ru.json
+++ b/web/src/i18n/locales/ru.json
@@ -1410,7 +1410,8 @@
"按价格设置": "Настроить по цене",
"按倍率类型筛选": "Фильтровать по типу коэффициента",
"按倍率设置": "Настроить по множителю",
- "按次计费": "Оплата за использование",
+ "按次": "За запрос",
+ "按次计费": "Оплата за запрос",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Введите в формате: AccessKey|SecretAccessKey|Region",
"按量计费": "Оплата по объему",
"按顺序替换content中的变量占位符": "Последовательно заменять переменные-заполнители в content",
@@ -1847,7 +1848,7 @@
"模板应用失败": "",
"模板示例": "Пример шаблона",
"模糊搜索模型名称": "Нечеткий поиск по названию модели",
- "次": "раз",
+ "次": "запрос",
"欢迎使用,请完成以下设置以开始使用系统": "Добро пожаловать, пожалуйста, выполните следующие настройки, чтобы начать использовать систему",
"欧元": "Евро",
"正在加载可用部署位置...": "Loading available deployment locations...",
@@ -3206,7 +3207,7 @@
"扩展价格": "Дополнительные цены",
"额外价格项": "Дополнительные ценовые позиции",
"补全价格": "Цена завершения",
- "提示缓存价格": "Цена чтения входного кеша",
+ "缓存读取价格": "Цена чтения входного кеша",
"缓存创建价格": "Цена создания входного кеша",
"图片输入价格": "Цена входного изображения",
"音频输入价格": "Цена входного аудио",
diff --git a/web/src/i18n/locales/vi.json b/web/src/i18n/locales/vi.json
index 20706426..34d4a4c8 100644
--- a/web/src/i18n/locales/vi.json
+++ b/web/src/i18n/locales/vi.json
@@ -1382,7 +1382,8 @@
"按价格设置": "Đặt theo giá",
"按倍率类型筛选": "Lọc theo loại tỷ lệ",
"按倍率设置": "Đặt theo tỷ lệ",
- "按次计费": "Trả tiền cho mỗi lần xem",
+ "按次": "Theo lượt gọi",
+ "按次计费": "Tính phí theo lượt gọi",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "Enter in the format: AccessKey|SecretAccessKey|Region",
"按量计费": "Trả tiền theo mức sử dụng",
"按顺序替换content中的变量占位符": "Thay thế các trình giữ chỗ biến trong nội dung theo thứ tự",
@@ -1839,7 +1840,7 @@
"模板示例": "Ví dụ mẫu",
"模糊匹配": "Khớp mờ",
"模糊搜索模型名称": "Tìm kiếm mờ tên mô hình",
- "次": "lần",
+ "次": "lượt",
"欢迎使用,请完成以下设置以开始使用系统": "Chào mừng! Vui lòng hoàn tất các cài đặt sau để bắt đầu sử dụng hệ thống",
"欢迎回来": "Chào mừng trở lại",
"欢迎回来!": "Chào mừng trở lại!",
@@ -3745,7 +3746,7 @@
"扩展价格": "Giá mở rộng",
"额外价格项": "Mục giá bổ sung",
"补全价格": "Giá hoàn thành",
- "提示缓存价格": "Giá đọc bộ nhớ đệm đầu vào",
+ "缓存读取价格": "Giá đọc bộ nhớ đệm đầu vào",
"缓存创建价格": "Giá tạo bộ nhớ đệm đầu vào",
"图片输入价格": "Giá đầu vào hình ảnh",
"音频输入价格": "Giá đầu vào âm thanh",
diff --git a/web/src/i18n/locales/zh-CN.json b/web/src/i18n/locales/zh-CN.json
index 7e5cec50..a7af51e1 100644
--- a/web/src/i18n/locales/zh-CN.json
+++ b/web/src/i18n/locales/zh-CN.json
@@ -1103,6 +1103,7 @@
"按价格设置": "按价格设置",
"按倍率类型筛选": "按倍率类型筛选",
"按倍率设置": "按倍率设置",
+ "按次": "按次",
"按次计费": "按次计费",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式输入:AccessKey|SecretAccessKey|Region",
"按量计费": "按量计费",
@@ -2850,7 +2851,7 @@
"扩展价格": "扩展价格",
"额外价格项": "额外价格项",
"补全价格": "补全价格",
- "提示缓存价格": "提示缓存价格",
+ "缓存读取价格": "缓存读取价格",
"缓存创建价格": "缓存创建价格",
"图片输入价格": "图片输入价格",
"音频输入价格": "音频输入价格",
diff --git a/web/src/i18n/locales/zh-TW.json b/web/src/i18n/locales/zh-TW.json
index a709bcf9..5567ea8f 100644
--- a/web/src/i18n/locales/zh-TW.json
+++ b/web/src/i18n/locales/zh-TW.json
@@ -1106,6 +1106,7 @@
"按价格设置": "按價格設定",
"按倍率类型筛选": "按倍率類型篩選",
"按倍率设置": "按倍率設定",
+ "按次": "按次",
"按次计费": "按次計費",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式輸入:AccessKey|SecretAccessKey|Region",
"按量计费": "按量計費",
@@ -2843,7 +2844,7 @@
"扩展价格": "擴展價格",
"额外价格项": "額外價格項",
"补全价格": "補全價格",
- "提示缓存价格": "提示快取價格",
+ "缓存读取价格": "快取讀取價格",
"缓存创建价格": "快取建立價格",
"图片输入价格": "圖片輸入價格",
"音频输入价格": "音訊輸入價格",
diff --git a/web/src/pages/Setting/Ratio/components/ModelPricingEditor.jsx b/web/src/pages/Setting/Ratio/components/ModelPricingEditor.jsx
index d4c2ff66..5028a3ff 100644
--- a/web/src/pages/Setting/Ratio/components/ModelPricingEditor.jsx
+++ b/web/src/pages/Setting/Ratio/components/ModelPricingEditor.jsx
@@ -491,7 +491,7 @@ export default function ModelPricingEditor({
}
/>
handleNumericFieldChange('cachePrice', value)}