💄 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
This commit is contained in:
t0ng7u
2025-08-11 15:53:55 +08:00
parent 4ad8eefaec
commit da17bdb688
3 changed files with 48 additions and 55 deletions

View File

@@ -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]}

View File

@@ -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 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='teal' size='small' shape='circle'>
{t('按次计费')}
<Tag key={`${qt}-${idx}`} color='white' size='small' shape='circle'>
{qt}
</Tag>
);
}
if (qt === 0) {
return (
<Tag key={`${qt}-${idx}`} color='violet' size='small' shape='circle'>
{t('按量计费')}
</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