From d1d945eaa0b149111ba7749a7843a509247d36f7 Mon Sep 17 00:00:00 2001 From: t0ng7u Date: Sun, 10 Aug 2025 17:17:49 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=94=A0=20refactor:=20refine=20group=20lab?= =?UTF-8?q?el=20formatting=20in=20price=20info?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: • Updated `helpers/utils.js` to display the “group” label without a colon, ensuring consistent typography with other price elements. Details: 1. `formatPriceInfo` – Changed `{t('分组')}:` to `{t('分组')}` for a cleaner look. – Keeps spacing intact between label and selected group name. 2. No functional impact; purely visual polish. --- .../view/card/PricingCardView.jsx | 4 +- web/src/helpers/utils.js | 74 ++++++++++++++----- .../model-pricing/useModelPricingData.js | 21 ++++-- web/src/i18n/locales/en.json | 3 +- 4 files changed, 73 insertions(+), 29 deletions(-) diff --git a/web/src/components/table/model-pricing/view/card/PricingCardView.jsx b/web/src/components/table/model-pricing/view/card/PricingCardView.jsx index 1be1b9fb..2a3e4109 100644 --- a/web/src/components/table/model-pricing/view/card/PricingCardView.jsx +++ b/web/src/components/table/model-pricing/view/card/PricingCardView.jsx @@ -136,7 +136,7 @@ const PricingCardView = ({ groupRatio, tokenUnit, displayPrice, - currency + currency, }); return formatPriceInfo(priceData, t); }; @@ -302,7 +302,7 @@ const PricingCardView = ({ {t('补全')}: {model.quota_type === 0 ? parseFloat(model.completion_ratio.toFixed(3)) : t('无')}
- {t('分组')}: {groupRatio[selectedGroup]} + {t('分组')}: {priceData.usedGroupRatio}
diff --git a/web/src/helpers/utils.js b/web/src/helpers/utils.js index 5612b5ad..71903ab8 100644 --- a/web/src/helpers/utils.js +++ b/web/src/helpers/utils.js @@ -581,13 +581,37 @@ export const calculateModelPrice = ({ tokenUnit, displayPrice, currency, - precision = 4 + precision = 4, }) => { + // 1. 选择实际使用的分组 + let usedGroup = selectedGroup; + let usedGroupRatio = groupRatio[selectedGroup]; + + if (selectedGroup === 'all' || usedGroupRatio === undefined) { + // 在模型可用分组中选择倍率最小的分组,若无则使用 1 + let minRatio = Number.POSITIVE_INFINITY; + if (Array.isArray(record.enable_groups) && record.enable_groups.length > 0) { + record.enable_groups.forEach((g) => { + const r = groupRatio[g]; + if (r !== undefined && r < minRatio) { + minRatio = r; + usedGroup = g; + usedGroupRatio = r; + } + }); + } + + // 如果找不到合适分组倍率,回退为 1 + if (usedGroupRatio === undefined) { + usedGroupRatio = 1; + } + } + + // 2. 根据计费类型计算价格 if (record.quota_type === 0) { // 按量计费 - const inputRatioPriceUSD = record.model_ratio * 2 * groupRatio[selectedGroup]; - const completionRatioPriceUSD = - record.model_ratio * record.completion_ratio * 2 * groupRatio[selectedGroup]; + 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'; @@ -602,22 +626,32 @@ export const calculateModelPrice = ({ inputPrice: `${currency === 'CNY' ? '¥' : '$'}${numInput.toFixed(precision)}`, completionPrice: `${currency === 'CNY' ? '¥' : '$'}${numCompletion.toFixed(precision)}`, unitLabel, - isPerToken: true - }; - } else { - // 按次计费 - const priceUSD = parseFloat(record.model_price) * groupRatio[selectedGroup]; - const displayVal = displayPrice(priceUSD); - - return { - price: displayVal, - isPerToken: false + isPerToken: true, + usedGroup, + usedGroupRatio, }; } + + // 按次计费 + const priceUSD = parseFloat(record.model_price) * usedGroupRatio; + const displayVal = displayPrice(priceUSD); + + return { + price: displayVal, + isPerToken: false, + usedGroup, + usedGroupRatio, + }; }; // 格式化价格信息(用于卡片视图) export const formatPriceInfo = (priceData, t) => { + const groupTag = priceData.usedGroup ? ( + + {t('分组')} {priceData.usedGroup} + + ) : null; + if (priceData.isPerToken) { return ( <> @@ -627,15 +661,19 @@ export const formatPriceInfo = (priceData, t) => { {t('补全')} {priceData.completionPrice}/{priceData.unitLabel} + {groupTag} ); - } else { - return ( + } + + return ( + <> {t('模型价格')} {priceData.price} - ); - } + {groupTag} + + ); }; // ------------------------------- diff --git a/web/src/hooks/model-pricing/useModelPricingData.js b/web/src/hooks/model-pricing/useModelPricingData.js index a2df8d37..c285cf4d 100644 --- a/web/src/hooks/model-pricing/useModelPricingData.js +++ b/web/src/hooks/model-pricing/useModelPricingData.js @@ -31,7 +31,7 @@ export const useModelPricingData = () => { const [selectedRowKeys, setSelectedRowKeys] = useState([]); const [modalImageUrl, setModalImageUrl] = useState(''); const [isModalOpenurl, setIsModalOpenurl] = useState(false); - const [selectedGroup, setSelectedGroup] = useState('default'); + const [selectedGroup, setSelectedGroup] = useState('all'); const [showModelDetail, setShowModelDetail] = useState(false); const [selectedModel, setSelectedModel] = useState(null); const [filterGroup, setFilterGroup] = useState('all'); // 用于 Table 的可用分组筛选,"all" 表示不过滤 @@ -180,7 +180,7 @@ export const useModelPricingData = () => { if (success) { setGroupRatio(group_ratio); setUsableGroup(usable_group); - setSelectedGroup(userState.user ? userState.user.group : 'default'); + setSelectedGroup('all'); // 构建供应商 Map 方便查找 const vendorMap = {}; if (Array.isArray(vendors)) { @@ -233,12 +233,17 @@ export const useModelPricingData = () => { setSelectedGroup(group); // 同时将分组过滤设置为该分组 setFilterGroup(group); - showInfo( - t('当前查看的分组为:{{group}},倍率为:{{ratio}}', { - group: group, - ratio: groupRatio[group], - }), - ); + + if (group === 'all') { + showInfo(t('已切换至最优倍率视图,每个模型使用其最低倍率分组')); + } else { + showInfo( + t('当前查看的分组为:{{group}},倍率为:{{ratio}}', { + group: group, + ratio: groupRatio[group] ?? 1, + }), + ); + } }; const openModelDetail = (model) => { diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json index 267f90c3..3e56aa43 100644 --- a/web/src/i18n/locales/en.json +++ b/web/src/i18n/locales/en.json @@ -1916,5 +1916,6 @@ "前缀名称匹配": "Prefix name matching", "后缀名称匹配": "Suffix name matching", "包含名称匹配": "Contains name matching", - "展开更多": "Expand more" + "展开更多": "Expand more", + "已切换至最优倍率视图,每个模型使用其最低倍率分组": "Switched to the optimal ratio view, each model uses its lowest ratio group" } \ No newline at end of file