Commit aa89ea2d by CaIon

feat: add billing display mode selection and update pricing rendering

Introduce a billing display mode feature allowing users to toggle between price and ratio views. Update relevant components and hooks to support this new functionality, ensuring consistent pricing information is displayed across the application.
parent 8d7d880d
...@@ -337,6 +337,7 @@ export const getLogsColumns = ({ ...@@ -337,6 +337,7 @@ export const getLogsColumns = ({
showUserInfoFunc, showUserInfoFunc,
openChannelAffinityUsageCacheModal, openChannelAffinityUsageCacheModal,
isAdminUser, isAdminUser,
billingDisplayMode = 'price',
}) => { }) => {
return [ return [
{ {
...@@ -761,11 +762,10 @@ export const getLogsColumns = ({ ...@@ -761,11 +762,10 @@ export const getLogsColumns = ({
Boolean(other?.violation_fee_marker) Boolean(other?.violation_fee_marker)
) { ) {
const feeQuota = other?.fee_quota ?? record?.quota; const feeQuota = other?.fee_quota ?? record?.quota;
const ratioText = formatRatio(other?.group_ratio);
const summary = [ const summary = [
t('违规扣费'), t('违规扣费'),
`${t('分组倍率')}${ratioText}`,
`${t('扣费')}${renderQuota(feeQuota, 6)}`, `${t('扣费')}${renderQuota(feeQuota, 6)}`,
`${t('分组倍率')}${formatRatio(other?.group_ratio)}`,
text ? `${t('详情')}${text}` : null, text ? `${t('详情')}${text}` : null,
] ]
.filter(Boolean) .filter(Boolean)
...@@ -808,6 +808,7 @@ export const getLogsColumns = ({ ...@@ -808,6 +808,7 @@ export const getLogsColumns = ({
1.0, 1.0,
other?.is_system_prompt_overwritten, other?.is_system_prompt_overwritten,
'claude', 'claude',
billingDisplayMode,
) )
: renderModelPriceSimple( : renderModelPriceSimple(
other.model_ratio, other.model_ratio,
...@@ -826,6 +827,7 @@ export const getLogsColumns = ({ ...@@ -826,6 +827,7 @@ export const getLogsColumns = ({
1.0, 1.0,
other?.is_system_prompt_overwritten, other?.is_system_prompt_overwritten,
'openai', 'openai',
billingDisplayMode,
); );
return ( return (
<Typography.Paragraph <Typography.Paragraph
......
...@@ -43,6 +43,7 @@ const LogsTable = (logsData) => { ...@@ -43,6 +43,7 @@ const LogsTable = (logsData) => {
openChannelAffinityUsageCacheModal, openChannelAffinityUsageCacheModal,
hasExpandableRows, hasExpandableRows,
isAdminUser, isAdminUser,
billingDisplayMode,
t, t,
COLUMN_KEYS, COLUMN_KEYS,
} = logsData; } = logsData;
...@@ -56,6 +57,7 @@ const LogsTable = (logsData) => { ...@@ -56,6 +57,7 @@ const LogsTable = (logsData) => {
showUserInfoFunc, showUserInfoFunc,
openChannelAffinityUsageCacheModal, openChannelAffinityUsageCacheModal,
isAdminUser, isAdminUser,
billingDisplayMode,
}); });
}, [ }, [
t, t,
...@@ -64,6 +66,7 @@ const LogsTable = (logsData) => { ...@@ -64,6 +66,7 @@ const LogsTable = (logsData) => {
showUserInfoFunc, showUserInfoFunc,
openChannelAffinityUsageCacheModal, openChannelAffinityUsageCacheModal,
isAdminUser, isAdminUser,
billingDisplayMode,
]); ]);
// Filter columns based on visibility settings // Filter columns based on visibility settings
......
...@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com ...@@ -18,7 +18,7 @@ For commercial licensing, please contact support@quantumnous.com
*/ */
import React from 'react'; import React from 'react';
import { Modal, Button, Checkbox } from '@douyinfe/semi-ui'; import { Modal, Button, Checkbox, RadioGroup, Radio } from '@douyinfe/semi-ui';
import { getLogsColumns } from '../UsageLogsColumnDefs'; import { getLogsColumns } from '../UsageLogsColumnDefs';
const ColumnSelectorModal = ({ const ColumnSelectorModal = ({
...@@ -28,6 +28,8 @@ const ColumnSelectorModal = ({ ...@@ -28,6 +28,8 @@ const ColumnSelectorModal = ({
handleColumnVisibilityChange, handleColumnVisibilityChange,
handleSelectAll, handleSelectAll,
initDefaultColumns, initDefaultColumns,
billingDisplayMode,
setBillingDisplayMode,
COLUMN_KEYS, COLUMN_KEYS,
isAdminUser, isAdminUser,
copyText, copyText,
...@@ -41,6 +43,7 @@ const ColumnSelectorModal = ({ ...@@ -41,6 +43,7 @@ const ColumnSelectorModal = ({
copyText, copyText,
showUserInfoFunc, showUserInfoFunc,
isAdminUser, isAdminUser,
billingDisplayMode,
}); });
return ( return (
...@@ -61,6 +64,17 @@ const ColumnSelectorModal = ({ ...@@ -61,6 +64,17 @@ const ColumnSelectorModal = ({
} }
> >
<div style={{ marginBottom: 20 }}> <div style={{ marginBottom: 20 }}>
<div style={{ marginBottom: 16 }}>
<div style={{ marginBottom: 8, fontWeight: 600 }}>{t('计费显示模式')}</div>
<RadioGroup
type='button'
value={billingDisplayMode}
onChange={(event) => setBillingDisplayMode(event.target.value)}
>
<Radio value='price'>{t('价格模式(默认)')}</Radio>
<Radio value='ratio'>{t('倍率模式')}</Radio>
</RadioGroup>
</div>
<Checkbox <Checkbox
checked={Object.values(visibleColumns).every((v) => v === true)} checked={Object.values(visibleColumns).every((v) => v === true)}
indeterminate={ indeterminate={
......
...@@ -78,6 +78,9 @@ export const useLogsData = () => { ...@@ -78,6 +78,9 @@ export const useLogsData = () => {
const STORAGE_KEY = isAdminUser const STORAGE_KEY = isAdminUser
? 'logs-table-columns-admin' ? 'logs-table-columns-admin'
: 'logs-table-columns-user'; : 'logs-table-columns-user';
const BILLING_DISPLAY_MODE_STORAGE_KEY = isAdminUser
? 'logs-billing-display-mode-admin'
: 'logs-billing-display-mode-user';
// Statistics state // Statistics state
const [stat, setStat] = useState({ const [stat, setStat] = useState({
...@@ -102,50 +105,6 @@ export const useLogsData = () => { ...@@ -102,50 +105,6 @@ export const useLogsData = () => {
logType: '0', logType: '0',
}; };
// Column visibility state
const [visibleColumns, setVisibleColumns] = useState({});
const [showColumnSelector, setShowColumnSelector] = useState(false);
// Compact mode
const [compactMode, setCompactMode] = useTableCompactMode('logs');
// User info modal state
const [showUserInfo, setShowUserInfoModal] = useState(false);
const [userInfoData, setUserInfoData] = useState(null);
// Channel affinity usage cache stats modal state (admin only)
const [
showChannelAffinityUsageCacheModal,
setShowChannelAffinityUsageCacheModal,
] = useState(false);
const [channelAffinityUsageCacheTarget, setChannelAffinityUsageCacheTarget] =
useState(null);
// Load saved column preferences from localStorage
useEffect(() => {
const savedColumns = localStorage.getItem(STORAGE_KEY);
if (savedColumns) {
try {
const parsed = JSON.parse(savedColumns);
const defaults = getDefaultColumnVisibility();
const merged = { ...defaults, ...parsed };
// For non-admin users, force-hide admin-only columns (does not touch admin settings)
if (!isAdminUser) {
merged[COLUMN_KEYS.CHANNEL] = false;
merged[COLUMN_KEYS.USERNAME] = false;
merged[COLUMN_KEYS.RETRY] = false;
}
setVisibleColumns(merged);
} catch (e) {
console.error('Failed to parse saved column preferences', e);
initDefaultColumns();
}
} else {
initDefaultColumns();
}
}, []);
// Get default column visibility based on user role // Get default column visibility based on user role
const getDefaultColumnVisibility = () => { const getDefaultColumnVisibility = () => {
return { return {
...@@ -166,6 +125,58 @@ export const useLogsData = () => { ...@@ -166,6 +125,58 @@ export const useLogsData = () => {
}; };
}; };
const getInitialVisibleColumns = () => {
const defaults = getDefaultColumnVisibility();
const savedColumns = localStorage.getItem(STORAGE_KEY);
if (!savedColumns) {
return defaults;
}
try {
const parsed = JSON.parse(savedColumns);
const merged = { ...defaults, ...parsed };
if (!isAdminUser) {
merged[COLUMN_KEYS.CHANNEL] = false;
merged[COLUMN_KEYS.USERNAME] = false;
merged[COLUMN_KEYS.RETRY] = false;
}
return merged;
} catch (e) {
console.error('Failed to parse saved column preferences', e);
return defaults;
}
};
const getInitialBillingDisplayMode = () => {
const savedMode = localStorage.getItem(BILLING_DISPLAY_MODE_STORAGE_KEY);
return savedMode === 'price' || savedMode === 'ratio' ? savedMode : 'price';
};
// Column visibility state
const [visibleColumns, setVisibleColumns] = useState(getInitialVisibleColumns);
const [showColumnSelector, setShowColumnSelector] = useState(false);
const [billingDisplayMode, setBillingDisplayMode] = useState(
getInitialBillingDisplayMode,
);
// Compact mode
const [compactMode, setCompactMode] = useTableCompactMode('logs');
// User info modal state
const [showUserInfo, setShowUserInfoModal] = useState(false);
const [userInfoData, setUserInfoData] = useState(null);
// Channel affinity usage cache stats modal state (admin only)
const [
showChannelAffinityUsageCacheModal,
setShowChannelAffinityUsageCacheModal,
] = useState(false);
const [channelAffinityUsageCacheTarget, setChannelAffinityUsageCacheTarget] =
useState(null);
// Initialize default column visibility // Initialize default column visibility
const initDefaultColumns = () => { const initDefaultColumns = () => {
const defaults = getDefaultColumnVisibility(); const defaults = getDefaultColumnVisibility();
...@@ -207,6 +218,10 @@ export const useLogsData = () => { ...@@ -207,6 +218,10 @@ export const useLogsData = () => {
} }
}, [visibleColumns]); }, [visibleColumns]);
useEffect(() => {
localStorage.setItem(BILLING_DISPLAY_MODE_STORAGE_KEY, billingDisplayMode);
}, [BILLING_DISPLAY_MODE_STORAGE_KEY, billingDisplayMode]);
// 获取表单值的辅助函数,确保所有值都是字符串 // 获取表单值的辅助函数,确保所有值都是字符串
const getFormValues = () => { const getFormValues = () => {
const formValues = formApi ? formApi.getValues() : {}; const formValues = formApi ? formApi.getValues() : {};
...@@ -406,6 +421,7 @@ export const useLogsData = () => { ...@@ -406,6 +421,7 @@ export const useLogsData = () => {
other.cache_creation_ratio_1h || other.cache_creation_ratio_1h ||
other.cache_creation_ratio || other.cache_creation_ratio ||
1.0, 1.0,
billingDisplayMode,
) )
: renderLogContent( : renderLogContent(
other?.model_ratio, other?.model_ratio,
...@@ -420,6 +436,7 @@ export const useLogsData = () => { ...@@ -420,6 +436,7 @@ export const useLogsData = () => {
other.web_search_call_count || 0, other.web_search_call_count || 0,
other.file_search || false, other.file_search || false,
other.file_search_call_count || 0, other.file_search_call_count || 0,
billingDisplayMode,
), ),
}); });
if (logs[i]?.content) { if (logs[i]?.content) {
...@@ -473,6 +490,7 @@ export const useLogsData = () => { ...@@ -473,6 +490,7 @@ export const useLogsData = () => {
other?.user_group_ratio, other?.user_group_ratio,
other?.cache_tokens || 0, other?.cache_tokens || 0,
other?.cache_ratio || 1.0, other?.cache_ratio || 1.0,
billingDisplayMode,
); );
} else if (other?.claude) { } else if (other?.claude) {
content = renderClaudeModelPrice( content = renderClaudeModelPrice(
...@@ -495,6 +513,7 @@ export const useLogsData = () => { ...@@ -495,6 +513,7 @@ export const useLogsData = () => {
other.cache_creation_ratio_1h || other.cache_creation_ratio_1h ||
other.cache_creation_ratio || other.cache_creation_ratio ||
1.0, 1.0,
billingDisplayMode,
); );
} else { } else {
content = renderModelPrice( content = renderModelPrice(
...@@ -521,6 +540,7 @@ export const useLogsData = () => { ...@@ -521,6 +540,7 @@ export const useLogsData = () => {
other?.audio_input_price || 0, other?.audio_input_price || 0,
other?.image_generation_call || false, other?.image_generation_call || false,
other?.image_generation_call_price || 0, other?.image_generation_call_price || 0,
billingDisplayMode,
); );
} }
expandDataLocal.push({ expandDataLocal.push({
...@@ -764,6 +784,8 @@ export const useLogsData = () => { ...@@ -764,6 +784,8 @@ export const useLogsData = () => {
visibleColumns, visibleColumns,
showColumnSelector, showColumnSelector,
setShowColumnSelector, setShowColumnSelector,
billingDisplayMode,
setBillingDisplayMode,
handleColumnVisibilityChange, handleColumnVisibilityChange,
handleSelectAll, handleSelectAll,
initDefaultColumns, initDefaultColumns,
......
...@@ -3200,6 +3200,27 @@ ...@@ -3200,6 +3200,27 @@
"音频补全价格": "Prix de complétion audio", "音频补全价格": "Prix de complétion audio",
"适合 MJ / 任务类等按次收费模型。": "Convient aux modèles MJ et autres modèles facturés à la requête.", "适合 MJ / 任务类等按次收费模型。": "Convient aux modèles MJ et autres modèles facturés à la requête.",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Le ratio de complétion de ce modèle est fixé à {{ratio}} par le backend. Le prix de complétion ne peut pas être modifié ici.", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Le ratio de complétion de ce modèle est fixé à {{ratio}} par le backend. Le prix de complétion ne peut pas être modifié ici.",
"计费显示模式": "Mode d'affichage de la facturation",
"价格模式(默认)": "Mode prix (par défaut)",
"模型价格 {{symbol}}{{price}} / 次": "Prix du modèle {{symbol}}{{price}} / requête",
"模型价格:{{symbol}}{{price}} / 次": "Prix du modèle : {{symbol}}{{price}} / requête",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "Montant facturé réel : {{symbol}}{{total}} (ajustement tarifaire de groupe inclus)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "Prix de lecture du cache : {{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "Prix de lecture du cache {{symbol}}{{price}} / 1M tokens",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Prix de création du cache : {{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Prix de création du cache {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Prix de création du cache 5m : {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Prix de création du cache 5m {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Prix de création du cache 1h : {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Prix de création du cache 1h {{symbol}}{{price}} / 1M tokens",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "Prix d'entrée image : {{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "Prix d'entrée image {{symbol}}{{price}} / 1M tokens",
"输入价格 {{symbol}}{{price}} / 1M tokens": "Prix d'entrée {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "Prix de complétion {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "Prix d'entrée audio : {{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "Prix de complétion audio : {{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Recherche Web appelée {{webSearchCallCount}} fois",
"文件搜索调用 {{fileSearchCallCount}} 次": "Recherche de fichier appelée {{fileSearchCallCount}} fois",
"空": "Vide" "空": "Vide"
} }
} }
...@@ -3181,6 +3181,27 @@ ...@@ -3181,6 +3181,27 @@
"音频补全价格": "音声補完価格", "音频补全价格": "音声補完価格",
"适合 MJ / 任务类等按次收费模型。": "MJ やその他のリクエスト単位課金モデルに適しています。", "适合 MJ / 任务类等按次收费模型。": "MJ やその他のリクエスト単位課金モデルに適しています。",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "このモデルの補完倍率はバックエンドで {{ratio}} に固定されています。ここでは補完価格を変更できません。", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "このモデルの補完倍率はバックエンドで {{ratio}} に固定されています。ここでは補完価格を変更できません。",
"计费显示模式": "課金表示モード",
"价格模式(默认)": "価格モード(デフォルト)",
"模型价格 {{symbol}}{{price}} / 次": "モデル価格 {{symbol}}{{price}} / リクエスト",
"模型价格:{{symbol}}{{price}} / 次": "モデル価格:{{symbol}}{{price}} / リクエスト",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "実際の請求額:{{symbol}}{{total}}(グループ価格調整込み)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "キャッシュ読み取り価格:{{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "キャッシュ読み取り価格 {{symbol}}{{price}} / 1M tokens",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "キャッシュ作成価格:{{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "キャッシュ作成価格 {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "5m キャッシュ作成価格:{{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "5m キャッシュ作成価格 {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "1h キャッシュ作成価格:{{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "1h キャッシュ作成価格 {{symbol}}{{price}} / 1M tokens",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "画像入力価格:{{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "画像入力価格 {{symbol}}{{price}} / 1M tokens",
"输入价格 {{symbol}}{{price}} / 1M tokens": "入力価格 {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "補完価格 {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "音声入力価格:{{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "音声補完価格:{{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Web 検索呼び出し {{webSearchCallCount}} 回",
"文件搜索调用 {{fileSearchCallCount}} 次": "ファイル検索呼び出し {{fileSearchCallCount}} 回",
"空": "空" "空": "空"
} }
} }
...@@ -3214,6 +3214,27 @@ ...@@ -3214,6 +3214,27 @@
"音频补全价格": "Цена завершения аудио", "音频补全价格": "Цена завершения аудио",
"适合 MJ / 任务类等按次收费模型。": "Подходит для MJ и других моделей с тарификацией за запрос.", "适合 MJ / 任务类等按次收费模型。": "Подходит для MJ и других моделей с тарификацией за запрос.",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Коэффициент завершения для этой модели зафиксирован на уровне {{ratio}} на бэкенде. Цену завершения нельзя изменить здесь.", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Коэффициент завершения для этой модели зафиксирован на уровне {{ratio}} на бэкенде. Цену завершения нельзя изменить здесь.",
"计费显示模式": "Режим отображения тарификации",
"价格模式(默认)": "Режим цен (по умолчанию)",
"模型价格 {{symbol}}{{price}} / 次": "Цена модели {{symbol}}{{price}} / запрос",
"模型价格:{{symbol}}{{price}} / 次": "Цена модели: {{symbol}}{{price}} / запрос",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "Фактическое списание: {{symbol}}{{total}} (включая групповую ценовую корректировку)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "Цена чтения кеша: {{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "Цена чтения кеша {{symbol}}{{price}} / 1M tokens",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Цена создания кеша: {{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Цена создания кеша {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Цена создания кеша 5m: {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Цена создания кеша 5m {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Цена создания кеша 1h: {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Цена создания кеша 1h {{symbol}}{{price}} / 1M tokens",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "Цена входного изображения: {{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "Цена входного изображения {{symbol}}{{price}} / 1M tokens",
"输入价格 {{symbol}}{{price}} / 1M tokens": "Цена ввода {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "Цена завершения {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "Цена входного аудио: {{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "Цена завершения аудио: {{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Web-поиск вызван {{webSearchCallCount}} раз",
"文件搜索调用 {{fileSearchCallCount}} 次": "Поиск файлов вызван {{fileSearchCallCount}} раз",
"空": "Пусто" "空": "Пусто"
} }
} }
...@@ -3753,6 +3753,27 @@ ...@@ -3753,6 +3753,27 @@
"音频补全价格": "Giá hoàn thành âm thanh", "音频补全价格": "Giá hoàn thành âm thanh",
"适合 MJ / 任务类等按次收费模型。": "Phù hợp cho MJ và các mô hình tính phí theo lượt gọi tương tự.", "适合 MJ / 任务类等按次收费模型。": "Phù hợp cho MJ và các mô hình tính phí theo lượt gọi tương tự.",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Tỷ lệ hoàn thành của mô hình này được backend cố định ở {{ratio}}. Không thể chỉnh giá hoàn thành tại đây.", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "Tỷ lệ hoàn thành của mô hình này được backend cố định ở {{ratio}}. Không thể chỉnh giá hoàn thành tại đây.",
"计费显示模式": "Chế độ hiển thị tính phí",
"价格模式(默认)": "Chế độ giá (mặc định)",
"模型价格 {{symbol}}{{price}} / 次": "Giá mô hình {{symbol}}{{price}} / lượt gọi",
"模型价格:{{symbol}}{{price}} / 次": "Giá mô hình: {{symbol}}{{price}} / lượt gọi",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "Khoản phí thực tế: {{symbol}}{{total}} (đã bao gồm điều chỉnh giá theo nhóm)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "Giá đọc bộ nhớ đệm: {{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "Giá đọc bộ nhớ đệm {{symbol}}{{price}} / 1M tokens",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm: {{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm 5m: {{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm 5m {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm 1h: {{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "Giá tạo bộ nhớ đệm 1h {{symbol}}{{price}} / 1M tokens",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "Giá đầu vào hình ảnh: {{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "Giá đầu vào hình ảnh {{symbol}}{{price}} / 1M tokens",
"输入价格 {{symbol}}{{price}} / 1M tokens": "Giá đầu vào {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "Giá hoàn thành {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "Giá đầu vào âm thanh: {{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "Giá hoàn thành âm thanh: {{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Đã gọi tìm kiếm Web {{webSearchCallCount}} lần",
"文件搜索调用 {{fileSearchCallCount}} 次": "Đã gọi tìm kiếm tệp {{fileSearchCallCount}} lần",
"空": "Trống" "空": "Trống"
} }
} }
...@@ -1104,6 +1104,7 @@ ...@@ -1104,6 +1104,7 @@
"按倍率类型筛选": "按倍率类型筛选", "按倍率类型筛选": "按倍率类型筛选",
"按倍率设置": "按倍率设置", "按倍率设置": "按倍率设置",
"按次": "按次", "按次": "按次",
"按次 {{price}} / 次": "按次 {{price}} / 次",
"按次计费": "按次计费", "按次计费": "按次计费",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式输入:AccessKey|SecretAccessKey|Region", "按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式输入:AccessKey|SecretAccessKey|Region",
"按量计费": "按量计费", "按量计费": "按量计费",
...@@ -2858,6 +2859,33 @@ ...@@ -2858,6 +2859,33 @@
"音频补全价格": "音频补全价格", "音频补全价格": "音频补全价格",
"适合 MJ / 任务类等按次收费模型。": "适合 MJ / 任务类等按次收费模型。", "适合 MJ / 任务类等按次收费模型。": "适合 MJ / 任务类等按次收费模型。",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。",
"计费显示模式": "计费显示模式",
"价格模式(默认)": "价格模式(默认)",
"模型价格 {{symbol}}{{price}} / 次": "模型价格 {{symbol}}{{price}} / 次",
"模型价格:{{symbol}}{{price}} / 次": "模型价格:{{symbol}}{{price}} / 次",
"输入 {{price}} / 1M tokens": "输入 {{price}} / 1M tokens",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "缓存读取价格:{{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "缓存读取价格 {{symbol}}{{price}} / 1M tokens",
"缓存读取 {{price}}": "缓存读取 {{price}}",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "缓存创建价格:{{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "缓存创建价格 {{symbol}}{{price}} / 1M tokens",
"缓存创建 {{price}}": "缓存创建 {{price}}",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "5m缓存创建价格:{{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "5m缓存创建价格 {{symbol}}{{price}} / 1M tokens",
"5m缓存创建 {{price}}": "5m缓存创建 {{price}}",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "1h缓存创建价格:{{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "1h缓存创建价格 {{symbol}}{{price}} / 1M tokens",
"1h缓存创建 {{price}}": "1h缓存创建 {{price}}",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "图片输入价格:{{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "图片输入价格 {{symbol}}{{price}} / 1M tokens",
"图片输入 {{price}}": "图片输入 {{price}}",
"输入价格 {{symbol}}{{price}} / 1M tokens": "输入价格 {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "补全价格 {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "音频输入价格:{{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "音频补全价格:{{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Web 搜索调用 {{webSearchCallCount}} 次",
"文件搜索调用 {{fileSearchCallCount}} 次": "文件搜索调用 {{fileSearchCallCount}} 次",
"空": "空" "空": "空"
} }
} }
...@@ -1107,6 +1107,7 @@ ...@@ -1107,6 +1107,7 @@
"按倍率类型筛选": "按倍率類型篩選", "按倍率类型筛选": "按倍率類型篩選",
"按倍率设置": "按倍率設定", "按倍率设置": "按倍率設定",
"按次": "按次", "按次": "按次",
"按次 {{price}} / 次": "按次 {{price}} / 次",
"按次计费": "按次計費", "按次计费": "按次計費",
"按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式輸入:AccessKey|SecretAccessKey|Region", "按照如下格式输入:AccessKey|SecretAccessKey|Region": "按照如下格式輸入:AccessKey|SecretAccessKey|Region",
"按量计费": "按量計費", "按量计费": "按量計費",
...@@ -2851,6 +2852,33 @@ ...@@ -2851,6 +2852,33 @@
"音频补全价格": "音訊補全價格", "音频补全价格": "音訊補全價格",
"适合 MJ / 任务类等按次收费模型。": "適合 MJ / 任務類等按次收費模型。", "适合 MJ / 任务类等按次收费模型。": "適合 MJ / 任務類等按次收費模型。",
"该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "該模型補全倍率由後端固定為 {{ratio}}。補全價格不能在這裡修改。", "该模型补全倍率由后端固定为 {{ratio}}。补全价格不能在这里修改。": "該模型補全倍率由後端固定為 {{ratio}}。補全價格不能在這裡修改。",
"计费显示模式": "計費顯示模式",
"价格模式(默认)": "價格模式(預設)",
"模型价格 {{symbol}}{{price}} / 次": "模型價格 {{symbol}}{{price}} / 次",
"模型价格:{{symbol}}{{price}} / 次": "模型價格:{{symbol}}{{price}} / 次",
"输入 {{price}} / 1M tokens": "輸入 {{price}} / 1M tokens",
"实际结算金额:{{symbol}}{{total}}(已包含分组价格调整)": "實際結算金額:{{symbol}}{{total}}(已包含分組價格調整)",
"缓存读取价格:{{symbol}}{{price}} / 1M tokens": "快取讀取價格:{{symbol}}{{price}} / 1M tokens",
"缓存读取价格 {{symbol}}{{price}} / 1M tokens": "快取讀取價格 {{symbol}}{{price}} / 1M tokens",
"缓存读取 {{price}}": "快取讀取 {{price}}",
"缓存创建价格:{{symbol}}{{price}} / 1M tokens": "快取建立價格:{{symbol}}{{price}} / 1M tokens",
"缓存创建价格 {{symbol}}{{price}} / 1M tokens": "快取建立價格 {{symbol}}{{price}} / 1M tokens",
"缓存创建 {{price}}": "快取建立 {{price}}",
"5m缓存创建价格:{{symbol}}{{price}} / 1M tokens": "5m快取建立價格:{{symbol}}{{price}} / 1M tokens",
"5m缓存创建价格 {{symbol}}{{price}} / 1M tokens": "5m快取建立價格 {{symbol}}{{price}} / 1M tokens",
"5m缓存创建 {{price}}": "5m快取建立 {{price}}",
"1h缓存创建价格:{{symbol}}{{price}} / 1M tokens": "1h快取建立價格:{{symbol}}{{price}} / 1M tokens",
"1h缓存创建价格 {{symbol}}{{price}} / 1M tokens": "1h快取建立價格 {{symbol}}{{price}} / 1M tokens",
"1h缓存创建 {{price}}": "1h快取建立 {{price}}",
"图片输入价格:{{symbol}}{{price}} / 1M tokens": "圖片輸入價格:{{symbol}}{{price}} / 1M tokens",
"图片输入价格 {{symbol}}{{price}} / 1M tokens": "圖片輸入價格 {{symbol}}{{price}} / 1M tokens",
"图片输入 {{price}}": "圖片輸入 {{price}}",
"输入价格 {{symbol}}{{price}} / 1M tokens": "輸入價格 {{symbol}}{{price}} / 1M tokens",
"补全价格 {{symbol}}{{price}} / 1M tokens": "補全價格 {{symbol}}{{price}} / 1M tokens",
"音频输入价格:{{symbol}}{{price}} / 1M tokens": "音訊輸入價格:{{symbol}}{{price}} / 1M tokens",
"音频补全价格:{{symbol}}{{price}} / 1M tokens": "音訊補全價格:{{symbol}}{{price}} / 1M tokens",
"Web 搜索调用 {{webSearchCallCount}} 次": "Web 搜尋呼叫 {{webSearchCallCount}} 次",
"文件搜索调用 {{fileSearchCallCount}} 次": "檔案搜尋呼叫 {{fileSearchCallCount}} 次",
"空": "空" "空": "空"
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment