Просмотр исходного кода

🔠 refactor: refine group label formatting in price info

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.
t0ng7u 6 месяцев назад
Родитель
Сommit
d1d945eaa0

+ 2 - 2
web/src/components/table/model-pricing/view/card/PricingCardView.jsx

@@ -136,7 +136,7 @@ const PricingCardView = ({
       groupRatio,
       groupRatio,
       tokenUnit,
       tokenUnit,
       displayPrice,
       displayPrice,
-      currency
+      currency,
     });
     });
     return formatPriceInfo(priceData, t);
     return formatPriceInfo(priceData, t);
   };
   };
@@ -302,7 +302,7 @@ const PricingCardView = ({
                           {t('补全')}: {model.quota_type === 0 ? parseFloat(model.completion_ratio.toFixed(3)) : t('无')}
                           {t('补全')}: {model.quota_type === 0 ? parseFloat(model.completion_ratio.toFixed(3)) : t('无')}
                         </div>
                         </div>
                         <div>
                         <div>
-                          {t('分组')}: {groupRatio[selectedGroup]}
+                          {t('分组')}: {priceData.usedGroupRatio}
                         </div>
                         </div>
                       </div>
                       </div>
                     </div>
                     </div>

+ 56 - 18
web/src/helpers/utils.js

@@ -581,13 +581,37 @@ export const calculateModelPrice = ({
   tokenUnit,
   tokenUnit,
   displayPrice,
   displayPrice,
   currency,
   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) {
   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 unitDivisor = tokenUnit === 'K' ? 1000 : 1;
     const unitLabel = tokenUnit === 'K' ? 'K' : 'M';
     const unitLabel = tokenUnit === 'K' ? 'K' : 'M';
@@ -602,22 +626,32 @@ export const calculateModelPrice = ({
       inputPrice: `${currency === 'CNY' ? '¥' : '$'}${numInput.toFixed(precision)}`,
       inputPrice: `${currency === 'CNY' ? '¥' : '$'}${numInput.toFixed(precision)}`,
       completionPrice: `${currency === 'CNY' ? '¥' : '$'}${numCompletion.toFixed(precision)}`,
       completionPrice: `${currency === 'CNY' ? '¥' : '$'}${numCompletion.toFixed(precision)}`,
       unitLabel,
       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) => {
 export const formatPriceInfo = (priceData, t) => {
+  const groupTag = priceData.usedGroup ? (
+    <span style={{ color: 'var(--semi-color-text-1)' }} className="ml-1 text-xs">
+      {t('分组')} {priceData.usedGroup}
+    </span>
+  ) : null;
+
   if (priceData.isPerToken) {
   if (priceData.isPerToken) {
     return (
     return (
       <>
       <>
@@ -627,15 +661,19 @@ export const formatPriceInfo = (priceData, t) => {
         <span style={{ color: 'var(--semi-color-text-1)' }}>
         <span style={{ color: 'var(--semi-color-text-1)' }}>
           {t('补全')} {priceData.completionPrice}/{priceData.unitLabel}
           {t('补全')} {priceData.completionPrice}/{priceData.unitLabel}
         </span>
         </span>
+        {groupTag}
       </>
       </>
     );
     );
-  } else {
-    return (
+  }
+
+  return (
+    <>
       <span style={{ color: 'var(--semi-color-text-1)' }}>
       <span style={{ color: 'var(--semi-color-text-1)' }}>
         {t('模型价格')} {priceData.price}
         {t('模型价格')} {priceData.price}
       </span>
       </span>
-    );
-  }
+      {groupTag}
+    </>
+  );
 };
 };
 
 
 // -------------------------------
 // -------------------------------

+ 13 - 8
web/src/hooks/model-pricing/useModelPricingData.js

@@ -31,7 +31,7 @@ export const useModelPricingData = () => {
   const [selectedRowKeys, setSelectedRowKeys] = useState([]);
   const [selectedRowKeys, setSelectedRowKeys] = useState([]);
   const [modalImageUrl, setModalImageUrl] = useState('');
   const [modalImageUrl, setModalImageUrl] = useState('');
   const [isModalOpenurl, setIsModalOpenurl] = useState(false);
   const [isModalOpenurl, setIsModalOpenurl] = useState(false);
-  const [selectedGroup, setSelectedGroup] = useState('default');
+  const [selectedGroup, setSelectedGroup] = useState('all');
   const [showModelDetail, setShowModelDetail] = useState(false);
   const [showModelDetail, setShowModelDetail] = useState(false);
   const [selectedModel, setSelectedModel] = useState(null);
   const [selectedModel, setSelectedModel] = useState(null);
   const [filterGroup, setFilterGroup] = useState('all'); // 用于 Table 的可用分组筛选,"all" 表示不过滤
   const [filterGroup, setFilterGroup] = useState('all'); // 用于 Table 的可用分组筛选,"all" 表示不过滤
@@ -180,7 +180,7 @@ export const useModelPricingData = () => {
     if (success) {
     if (success) {
       setGroupRatio(group_ratio);
       setGroupRatio(group_ratio);
       setUsableGroup(usable_group);
       setUsableGroup(usable_group);
-      setSelectedGroup(userState.user ? userState.user.group : 'default');
+      setSelectedGroup('all');
       // 构建供应商 Map 方便查找
       // 构建供应商 Map 方便查找
       const vendorMap = {};
       const vendorMap = {};
       if (Array.isArray(vendors)) {
       if (Array.isArray(vendors)) {
@@ -233,12 +233,17 @@ export const useModelPricingData = () => {
     setSelectedGroup(group);
     setSelectedGroup(group);
     // 同时将分组过滤设置为该分组
     // 同时将分组过滤设置为该分组
     setFilterGroup(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) => {
   const openModelDetail = (model) => {

+ 2 - 1
web/src/i18n/locales/en.json

@@ -1916,5 +1916,6 @@
   "前缀名称匹配": "Prefix name matching",
   "前缀名称匹配": "Prefix name matching",
   "后缀名称匹配": "Suffix name matching",
   "后缀名称匹配": "Suffix name matching",
   "包含名称匹配": "Contains name matching",
   "包含名称匹配": "Contains name matching",
-  "展开更多": "Expand more"
+  "展开更多": "Expand more",
+  "已切换至最优倍率视图,每个模型使用其最低倍率分组": "Switched to the optimal ratio view, each model uses its lowest ratio group"
 }
 }