Explorar o código

💄 style: Use segmented renderer for billing types in Models table; keep Pricing view unchanged

Frontend
- Models table (model management):
  - Render billing types with the same segmented list component (renderLimitedItems) used by tags and endpoints
  - Display quota_types as an array with capped items (maxDisplay: 3) and graceful fallback for unknown types
- Pricing view (unchanged by request):
  - Revert to single-value quota_type rendering and sorter
  - Keep ratio display logic based on quota_type only

Files
- web/src/components/table/models/ModelsColumnDefs.js
- web/src/components/table/model-pricing/view/table/PricingTableColumns.js

Notes
- This commit only adjusts the model management UI rendering; pricing views remain as-is
t0ng7u hai 6 meses
pai
achega
da17bdb688

+ 1 - 1
web/src/components/common/ui/CardTable.js

@@ -41,7 +41,7 @@ const CardTable = ({
 }) => {
   const isMobile = useIsMobile();
   const { t } = useTranslation();
-  
+
   const showSkeleton = useMinimumLoadingTime(loading);
 
   const getRowKey = (record, index) => {

+ 24 - 29
web/src/components/table/model-pricing/view/table/PricingTableColumns.js

@@ -23,31 +23,23 @@ import { IconHelpCircle } from '@douyinfe/semi-icons';
 import { renderModelTag, stringToColor, calculateModelPrice, getLobeHubIcon } from '../../../../../helpers';
 import { renderLimitedItems, renderDescription } from '../../../../common/ui/RenderUtils';
 
-function renderQuotaTypes(types, t) {
-  if (!Array.isArray(types) || types.length === 0) return '-';
-  const renderOne = (type, idx) => {
-    switch (type) {
-      case 1:
-        return (
-          <Tag key={`qt-${type}-${idx}`} color='teal' shape='circle'>
-            {t('按次计费')}
-          </Tag>
-        );
-      case 0:
-        return (
-          <Tag key={`qt-${type}-${idx}`} color='violet' shape='circle'>
-            {t('按量计费')}
-          </Tag>
-        );
-      default:
-        return (
-          <Tag key={`qt-${type}-${idx}`} color='white' shape='circle'>
-            {type}
-          </Tag>
-        );
-    }
-  };
-  return <Space wrap>{types.map((t0, idx) => renderOne(t0, idx))}</Space>;
+function renderQuotaType(type, t) {
+  switch (type) {
+    case 1:
+      return (
+        <Tag color='teal' shape='circle'>
+          {t('按次计费')}
+        </Tag>
+      );
+    case 0:
+      return (
+        <Tag color='violet' shape='circle'>
+          {t('按量计费')}
+        </Tag>
+      );
+    default:
+      return t('未知');
+  }
 }
 
 // Render vendor name
@@ -130,8 +122,11 @@ export const getPricingTableColumns = ({
 
   const quotaColumn = {
     title: t('计费类型'),
-    dataIndex: 'quota_types',
-    render: (text, record, index) => renderQuotaTypes(text, t),
+    dataIndex: 'quota_type',
+    render: (text, record, index) => {
+      return renderQuotaType(parseInt(text), t);
+    },
+    sorter: (a, b) => a.quota_type - b.quota_type,
   };
 
   const descriptionColumn = {
@@ -175,11 +170,11 @@ export const getPricingTableColumns = ({
       const content = (
         <div className="space-y-1">
           <div className="text-gray-700">
-            {t('模型倍率')}:{Array.isArray(record.quota_types) && record.quota_types.includes(0) ? text : t('无')}
+            {t('模型倍率')}:{record.quota_type === 0 ? text : t('无')}
           </div>
           <div className="text-gray-700">
             {t('补全倍率')}:
-            {Array.isArray(record.quota_types) && record.quota_types.includes(0) ? completionRatio : t('无')}
+            {record.quota_type === 0 ? completionRatio : t('无')}
           </div>
           <div className="text-gray-700">
             {t('分组倍率')}:{groupRatio[selectedGroup]}

+ 23 - 25
web/src/components/table/models/ModelsColumnDefs.js

@@ -121,36 +121,34 @@ const renderEndpoints = (value) => {
   }
 };
 
-// Render quota types (array)
+// Render quota types (array) using common limited items renderer
 const renderQuotaTypes = (arr, t) => {
   if (!Array.isArray(arr) || arr.length === 0) return '-';
-  const renderOne = (qt, idx) => {
-    if (qt === 1) {
-      return (
-        <Tag key={`${qt}-${idx}`} color='teal' size='small' shape='circle'>
-          {t('按次计费')}
-        </Tag>
-      );
-    }
-    if (qt === 0) {
+  return renderLimitedItems({
+    items: arr,
+    renderItem: (qt, idx) => {
+      if (qt === 1) {
+        return (
+          <Tag key={`${qt}-${idx}`} color='teal' size='small' shape='circle'>
+            {t('按次计费')}
+          </Tag>
+        );
+      }
+      if (qt === 0) {
+        return (
+          <Tag key={`${qt}-${idx}`} color='violet' size='small' shape='circle'>
+            {t('按量计费')}
+          </Tag>
+        );
+      }
       return (
-        <Tag key={`${qt}-${idx}`} color='violet' size='small' shape='circle'>
-          {t('按量计费')}
+        <Tag key={`${qt}-${idx}`} color='white' size='small' shape='circle'>
+          {qt}
         </Tag>
       );
-    }
-    // 未来新增模式的兜底展示
-    return (
-      <Tag key={`${qt}-${idx}`} color='white' size='small' shape='circle'>
-        {qt}
-      </Tag>
-    );
-  };
-  return (
-    <Space wrap>
-      {arr.map((qt, idx) => renderOne(qt, idx))}
-    </Space>
-  );
+    },
+    maxDisplay: 3,
+  });
 };
 
 // Render bound channels