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