refactor: streamline model card to show only logo, name, description, and IO prices
This commit is contained in:
parent
4fbdafee1c
commit
77b885b190
|
|
@ -378,7 +378,6 @@ const HomeModelList = () => {
|
|||
<PricingCardView
|
||||
filteredModels={pricingData.filteredModels}
|
||||
loading={pricingData.loading}
|
||||
rowSelection={null}
|
||||
pageSize={pricingData.pageSize}
|
||||
setPageSize={pricingData.setPageSize}
|
||||
currentPage={pricingData.currentPage}
|
||||
|
|
@ -387,9 +386,6 @@ const HomeModelList = () => {
|
|||
groupRatio={pricingData.groupRatio}
|
||||
groupModelPrice={pricingData.groupModelPrice}
|
||||
groupModelRatio={pricingData.groupModelRatio}
|
||||
copyText={pricingData.copyText}
|
||||
setModalImageUrl={pricingData.setModalImageUrl}
|
||||
setIsModalOpenurl={pricingData.setIsModalOpenurl}
|
||||
currency={pricingData.currency}
|
||||
siteDisplayType={pricingData.siteDisplayType}
|
||||
tokenUnit={pricingData.tokenUnit}
|
||||
|
|
@ -399,10 +395,7 @@ const HomeModelList = () => {
|
|||
pricingData.channelVideoCompletionRatio
|
||||
}
|
||||
channelVideoPrice={pricingData.channelVideoPrice}
|
||||
showRatio={false}
|
||||
t={pricingData.t}
|
||||
selectedRowKeys={[]}
|
||||
setSelectedRowKeys={() => {}}
|
||||
openModelDetail={pricingData.openModelDetail}
|
||||
showSizeChanger={false}
|
||||
blurPricing={blurPricing}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,6 @@ import { Card, Skeleton } from '@douyinfe/semi-ui';
|
|||
|
||||
const PricingCardSkeleton = ({
|
||||
skeletonCount = 100,
|
||||
rowSelection = false,
|
||||
showRatio = false,
|
||||
}) => {
|
||||
const placeholder = (
|
||||
<div className='px-2 pt-2'>
|
||||
|
|
@ -34,8 +32,8 @@ const PricingCardSkeleton = ({
|
|||
className='!rounded-2xl border border-gray-200'
|
||||
bodyStyle={{ padding: '24px' }}
|
||||
>
|
||||
{/* 头部:图标 + 模型名称 + 操作按钮 */}
|
||||
<div className='flex items-start justify-between mb-3'>
|
||||
{/* 头部:图标 + 模型名称 */}
|
||||
<div className='flex items-start mb-3'>
|
||||
<div className='flex items-start space-x-3 flex-1 min-w-0'>
|
||||
{/* 模型图标骨架 */}
|
||||
<div className='w-12 h-12 rounded-2xl flex items-center justify-center relative shadow-sm'>
|
||||
|
|
@ -44,41 +42,17 @@ const PricingCardSkeleton = ({
|
|||
style={{ width: 48, height: 48, borderRadius: 16 }}
|
||||
/>
|
||||
</div>
|
||||
{/* 模型名称和价格区域 */}
|
||||
{/* 模型名称 */}
|
||||
<div className='flex-1 min-w-0'>
|
||||
{/* 模型名称骨架 */}
|
||||
<Skeleton.Title
|
||||
style={{
|
||||
width: `${120 + (index % 3) * 30}px`,
|
||||
height: 20,
|
||||
marginBottom: 8,
|
||||
}}
|
||||
/>
|
||||
{/* 价格信息骨架 */}
|
||||
<Skeleton.Title
|
||||
style={{
|
||||
width: `${160 + (index % 4) * 20}px`,
|
||||
height: 20,
|
||||
marginBottom: 0,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center space-x-2 ml-3'>
|
||||
{/* 复制按钮骨架 */}
|
||||
<Skeleton.Button
|
||||
size='small'
|
||||
style={{ width: 16, height: 16, borderRadius: 4 }}
|
||||
/>
|
||||
{/* 勾选框骨架 */}
|
||||
{rowSelection && (
|
||||
<Skeleton.Button
|
||||
size='small'
|
||||
style={{ width: 16, height: 16, borderRadius: 2 }}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 模型描述骨架 */}
|
||||
|
|
@ -90,43 +64,25 @@ const PricingCardSkeleton = ({
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* 标签区域骨架 */}
|
||||
<div className='flex flex-wrap gap-2'>
|
||||
{Array.from({ length: 2 + (index % 3) }).map((_, tagIndex) => (
|
||||
<Skeleton.Button
|
||||
key={tagIndex}
|
||||
size='small'
|
||||
style={{
|
||||
width: 64,
|
||||
height: 18,
|
||||
borderRadius: 10,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{/* 倍率信息骨架(可选) */}
|
||||
{showRatio && (
|
||||
<div className='mt-4 pt-3 border-t border-gray-100'>
|
||||
<div className='flex items-center space-x-1 mb-2'>
|
||||
{/* 价格骨架:输入 + 输出并排 */}
|
||||
<div className='flex gap-3'>
|
||||
<div className='flex-1 rounded-xl px-3 py-2.5' style={{backgroundColor: 'var(--semi-color-fill-0)'}}>
|
||||
<Skeleton.Title
|
||||
style={{ width: 60, height: 12, marginBottom: 0 }}
|
||||
style={{ width: '80%', height: 14, marginBottom: 8 }}
|
||||
/>
|
||||
<Skeleton.Button
|
||||
size='small'
|
||||
style={{ width: 14, height: 14, borderRadius: 7 }}
|
||||
/>
|
||||
</div>
|
||||
<div className='grid grid-cols-3 gap-2'>
|
||||
{Array.from({ length: 3 }).map((_, ratioIndex) => (
|
||||
<Skeleton.Title
|
||||
key={ratioIndex}
|
||||
style={{ width: '100%', height: 12, marginBottom: 0 }}
|
||||
style={{ width: '100%', height: 18, marginBottom: 0 }}
|
||||
/>
|
||||
</div>
|
||||
<div className='flex-1 rounded-xl px-3 py-2.5' style={{backgroundColor: 'var(--semi-color-fill-0)'}}>
|
||||
<Skeleton.Title
|
||||
style={{ width: '80%', height: 14, marginBottom: 8 }}
|
||||
/>
|
||||
<Skeleton.Title
|
||||
style={{ width: '100%', height: 18, marginBottom: 0 }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -20,22 +20,15 @@ For commercial licensing, please contact support@quantumnous.com
|
|||
import React from 'react';
|
||||
import {
|
||||
Card,
|
||||
Tag,
|
||||
Tooltip,
|
||||
Checkbox,
|
||||
Empty,
|
||||
Pagination,
|
||||
Button,
|
||||
Avatar,
|
||||
} from '@douyinfe/semi-ui';
|
||||
import { IconHelpCircle } from '@douyinfe/semi-icons';
|
||||
import { Copy } from 'lucide-react';
|
||||
import {
|
||||
IllustrationNoResult,
|
||||
IllustrationNoResultDark,
|
||||
} from '@douyinfe/semi-illustrations';
|
||||
import {
|
||||
stringToColor,
|
||||
calculateModelPrice,
|
||||
getModelPriceItems,
|
||||
getLobeHubIcon,
|
||||
|
|
@ -45,7 +38,6 @@ import {
|
|||
} from '../../../../../helpers';
|
||||
import PricingCardSkeleton from './PricingCardSkeleton';
|
||||
import { useMinimumLoadingTime } from '../../../../../hooks/common/useMinimumLoadingTime';
|
||||
import { renderLimitedItems } from '../../../../common/ui/RenderUtils';
|
||||
import { useIsMobile } from '../../../../../hooks/common/useIsMobile';
|
||||
const CARD_STYLES = {
|
||||
container:
|
||||
|
|
@ -60,7 +52,6 @@ const escapeRegExp = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|||
const PricingCardView = ({
|
||||
filteredModels,
|
||||
loading,
|
||||
rowSelection,
|
||||
pageSize,
|
||||
setPageSize,
|
||||
currentPage,
|
||||
|
|
@ -69,17 +60,11 @@ const PricingCardView = ({
|
|||
groupRatio,
|
||||
groupModelPrice,
|
||||
groupModelRatio,
|
||||
copyText,
|
||||
setModalImageUrl,
|
||||
setIsModalOpenurl,
|
||||
currency,
|
||||
siteDisplayType,
|
||||
tokenUnit,
|
||||
displayPrice,
|
||||
showRatio,
|
||||
t,
|
||||
selectedRowKeys = [],
|
||||
setSelectedRowKeys,
|
||||
openModelDetail,
|
||||
showSizeChanger = true,
|
||||
blurPricing = false,
|
||||
|
|
@ -122,62 +107,6 @@ const PricingCardView = ({
|
|||
);
|
||||
};
|
||||
|
||||
const handleCheckboxChange = (model, checked) => {
|
||||
if (!setSelectedRowKeys) return;
|
||||
const modelKey = getModelKey(model);
|
||||
const newKeys = checked
|
||||
? Array.from(new Set([...selectedRowKeys, modelKey]))
|
||||
: selectedRowKeys.filter((key) => key !== modelKey);
|
||||
setSelectedRowKeys(newKeys);
|
||||
rowSelection?.onChange?.(newKeys, null);
|
||||
};
|
||||
|
||||
// 根据 supplier_type 返回对应的 Tag 颜色
|
||||
const getSupplierTypeColor = (supplierType) => {
|
||||
switch (supplierType) {
|
||||
case '公有云':
|
||||
return 'green';
|
||||
case 'AIDC':
|
||||
return 'light-green';
|
||||
case '企业中转站':
|
||||
return 'lime';
|
||||
case '个人中转站':
|
||||
return 'yellow';
|
||||
default:
|
||||
return stringToColor(supplierType);
|
||||
}
|
||||
};
|
||||
|
||||
// 根据模型的 channel_list 推导可展示的供应商项。
|
||||
// 无 logo 时不展示 supplier_alias,仅保留供应商类型标签。
|
||||
const getSupplierLogos = (model) => {
|
||||
if (!model?.channel_list || model.channel_list.length === 0) return [];
|
||||
const seen = new Set();
|
||||
const items = [];
|
||||
model.channel_list.forEach((ch, idx) => {
|
||||
const logo =
|
||||
(ch?.company_logo_url && String(ch.company_logo_url).trim()) || '';
|
||||
const supplierType =
|
||||
(ch?.supplier_type && String(ch.supplier_type).trim()) || '';
|
||||
const alias =
|
||||
(ch?.supplier_alias && String(ch.supplier_alias).trim()) || '';
|
||||
const name = ch?.channel_name || '';
|
||||
if (!logo && !supplierType) return;
|
||||
const displayAlias = logo ? alias : '';
|
||||
const dedupKey = `${logo}|${supplierType}|${displayAlias}`;
|
||||
if (seen.has(dedupKey)) return;
|
||||
seen.add(dedupKey);
|
||||
items.push({
|
||||
key: ch?.channel_id ?? `${dedupKey}-${idx}`,
|
||||
logo,
|
||||
supplierType,
|
||||
alias: displayAlias,
|
||||
name,
|
||||
});
|
||||
});
|
||||
return items;
|
||||
};
|
||||
|
||||
const calculateChannelPrices = (model, opts = {}) => {
|
||||
const { skipSimpleVideoFlat = false, skipSimpleFixed = false } = opts;
|
||||
if (!model.channel_list || model.channel_list.length === 0) {
|
||||
|
|
@ -766,77 +695,11 @@ const PricingCardView = ({
|
|||
return record.description || '';
|
||||
};
|
||||
|
||||
// 渲染标签
|
||||
const renderTags = (record) => {
|
||||
// 计费类型标签(左边)- 使用 channel_list[0].quota_type
|
||||
const channelQuotaType =
|
||||
record.channel_list && record.channel_list.length > 0
|
||||
? record.channel_list[0].quota_type
|
||||
: record.quota_type;
|
||||
|
||||
let billingTag = (
|
||||
<Tag key='billing' shape='circle' color='white' size='small'>
|
||||
-
|
||||
</Tag>
|
||||
);
|
||||
if (channelQuotaType === 1) {
|
||||
billingTag = (
|
||||
<Tag key='billing' shape='circle' color='teal' size='small'>
|
||||
{t('按次计费')}
|
||||
</Tag>
|
||||
);
|
||||
} else if (channelQuotaType === 0) {
|
||||
billingTag = (
|
||||
<Tag key='billing' shape='circle' color='violet' size='small'>
|
||||
{t('按量计费')}
|
||||
</Tag>
|
||||
);
|
||||
}
|
||||
|
||||
// 自定义标签(右边)
|
||||
const customTags = [];
|
||||
if (record.tags) {
|
||||
const tagArr = record.tags.split(',').filter(Boolean);
|
||||
tagArr.forEach((tg, idx) => {
|
||||
customTags.push(
|
||||
<Tag
|
||||
key={`custom-${idx}`}
|
||||
shape='circle'
|
||||
color={stringToColor(tg)}
|
||||
size='small'
|
||||
>
|
||||
{renderHighlightedText(tg)}
|
||||
</Tag>,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='flex items-center justify-between'>
|
||||
<div className='flex items-center gap-2'>{billingTag}</div>
|
||||
<div className='flex items-center gap-1'>
|
||||
{customTags.length > 0 &&
|
||||
renderLimitedItems({
|
||||
items: customTags.map((tag, idx) => ({
|
||||
key: `custom-${idx}`,
|
||||
element: tag,
|
||||
})),
|
||||
renderItem: (item, idx) => item.element,
|
||||
maxDisplay: 3,
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
// 显示骨架屏
|
||||
if (showSkeleton) {
|
||||
return (
|
||||
<>
|
||||
<PricingCardSkeleton
|
||||
rowSelection={!!rowSelection}
|
||||
showRatio={showRatio}
|
||||
/>
|
||||
<PricingCardSkeleton />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
@ -863,7 +726,6 @@ const PricingCardView = ({
|
|||
<div className={gridCols > 0 ? 'grid gap-4' : 'flex flex-wrap gap-4'} style={gridCols > 0 ? { gridTemplateColumns: `repeat(${gridCols}, 1fr)` } : undefined}>
|
||||
{paginatedModels.map((model, index) => {
|
||||
const modelKey = getModelKey(model);
|
||||
const isSelected = selectedRowKeys.includes(modelKey);
|
||||
|
||||
const priceData = calculateModelPrice({
|
||||
record: model,
|
||||
|
|
@ -877,166 +739,31 @@ const PricingCardView = ({
|
|||
quotaDisplayType: siteDisplayType,
|
||||
});
|
||||
|
||||
const supplierLogos = getSupplierLogos(model);
|
||||
const hasChannelList =
|
||||
Array.isArray(model.channel_list) &&
|
||||
model.channel_list.length > 0;
|
||||
|
||||
return (
|
||||
<Card
|
||||
key={modelKey || index}
|
||||
className={`${gridCols > 0 ? '!w-full' : 'flex-1 min-w-[350px] max-w-[600px]'} !rounded-2xl transition-all duration-200 hover:shadow-lg border ${blurPricing ? '' : 'cursor-pointer'} ${isSelected ? CARD_STYLES.selected : CARD_STYLES.default}`}
|
||||
className={`${gridCols > 0 ? '!w-full' : 'flex-1 min-w-[350px] max-w-[600px]'} !rounded-2xl transition-all duration-200 hover:shadow-lg border ${blurPricing ? '' : 'cursor-pointer'} ${CARD_STYLES.default}`}
|
||||
bodyStyle={{ height: '100%' }}
|
||||
onClick={() =>
|
||||
!blurPricing && openModelDetail && openModelDetail(model)
|
||||
}
|
||||
>
|
||||
<div className='flex flex-col h-full'>
|
||||
{/* 头部:图标 + 模型名称 + 操作按钮 */}
|
||||
<div className='flex items-start justify-between mb-3'>
|
||||
{/* 头部:图标 + 模型名称 */}
|
||||
<div className='flex items-start mb-3'>
|
||||
<div className='flex items-start space-x-3 flex-1 min-w-0'>
|
||||
{getModelIcon(model)}
|
||||
<div className='flex-1 min-w-0'>
|
||||
<h3 className='text-lg font-bold text-gray-900 truncate'>
|
||||
{renderHighlightedText(model.model_name)}
|
||||
</h3>
|
||||
<div
|
||||
className='flex flex-col gap-1 text-xs mt-1'
|
||||
style={
|
||||
blurPricing
|
||||
? {
|
||||
filter: 'blur(6px)',
|
||||
userSelect: 'none',
|
||||
pointerEvents: 'none',
|
||||
}
|
||||
: undefined
|
||||
}
|
||||
>
|
||||
{getModelPriceItemsForCard(model, priceData).map(
|
||||
(item) => (
|
||||
<div key={item.key} className='flex items-center'>
|
||||
<span className='w-20 flex-shrink-0'>
|
||||
{item.label}
|
||||
</span>
|
||||
<span className='flex-1 font-bold text-black inline-flex items-center flex-wrap gap-1'>
|
||||
{item.valueNode ? (
|
||||
item.valueNode
|
||||
) : item.original ? (
|
||||
<>
|
||||
<span className='line-through text-gray-400 font-normal text-[10px]'>
|
||||
<span
|
||||
style={{
|
||||
color: 'var(--semi-color-primary)',
|
||||
}}
|
||||
>
|
||||
官方
|
||||
</span>{' '}
|
||||
{item.original.text}
|
||||
</span>
|
||||
<Tag
|
||||
color='red'
|
||||
size='small'
|
||||
shape='circle'
|
||||
>
|
||||
-{item.original.discount}%
|
||||
</Tag>
|
||||
<span>
|
||||
<span
|
||||
style={{
|
||||
color: 'var(--semi-color-warning)',
|
||||
}}
|
||||
>
|
||||
我们
|
||||
</span>{' '}
|
||||
{item.value}
|
||||
{item.suffix}
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<span>
|
||||
{item.value}
|
||||
{item.suffix}
|
||||
</span>
|
||||
)}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
)}
|
||||
<div className='flex items-center'>
|
||||
<span className='w-20 flex-shrink-0'>
|
||||
{t('供应商')}
|
||||
</span>
|
||||
<div className='flex-1 flex items-center flex-wrap gap-1'>
|
||||
{supplierLogos.length === 0 ? (
|
||||
hasChannelList ? null : (
|
||||
<span className='font-bold text-black'>
|
||||
{t('官方')}
|
||||
</span>
|
||||
)
|
||||
) : (
|
||||
supplierLogos.map((s) => (
|
||||
<div
|
||||
key={s.key}
|
||||
className='h-7 rounded-md flex items-center overflow-hidden'
|
||||
style={{backgroundColor: 'var(--semi-color-fill-0)'}}
|
||||
>
|
||||
{s.logo ? (
|
||||
<img
|
||||
src={s.logo}
|
||||
alt={s.alias || s.name || ''}
|
||||
className='w-7 h-7 object-contain rounded-md'
|
||||
/>
|
||||
) : null}
|
||||
{s.supplierType && (
|
||||
<Tag
|
||||
size='small'
|
||||
shape='circle'
|
||||
color={getSupplierTypeColor(
|
||||
s.supplierType,
|
||||
)}
|
||||
className='mx-1'
|
||||
>
|
||||
{s.supplierType}
|
||||
</Tag>
|
||||
)}
|
||||
</div>
|
||||
))
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className='flex items-center space-x-2 ml-3'>
|
||||
{/* 复制按钮 */}
|
||||
<Button
|
||||
size='small'
|
||||
theme='outline'
|
||||
type='tertiary'
|
||||
icon={<Copy size={12} />}
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
copyText(model.model_name);
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* 选择框 */}
|
||||
{rowSelection && (
|
||||
<Checkbox
|
||||
checked={isSelected}
|
||||
onChange={(e) => {
|
||||
e.stopPropagation();
|
||||
handleCheckboxChange(model, e.target.checked);
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 模型描述 - 占据剩余空间 */}
|
||||
{/* 模型描述 */}
|
||||
<div
|
||||
className='flex-1 mb-4'
|
||||
className='mb-4'
|
||||
style={
|
||||
blurPricing
|
||||
? {
|
||||
|
|
@ -1055,7 +782,7 @@ const PricingCardView = ({
|
|||
</p>
|
||||
</div>
|
||||
|
||||
{/* 底部区域 */}
|
||||
{/* 价格:输入 + 输出并排 */}
|
||||
<div
|
||||
className='mt-auto'
|
||||
style={
|
||||
|
|
@ -1068,49 +795,39 @@ const PricingCardView = ({
|
|||
: undefined
|
||||
}
|
||||
>
|
||||
{/* 标签区域 */}
|
||||
{renderTags(model)}
|
||||
|
||||
{/* 倍率信息(可选) */}
|
||||
{showRatio && (
|
||||
<div className='pt-3'>
|
||||
<div className='flex items-center space-x-1 mb-2'>
|
||||
<span className='text-xs font-medium text-gray-700'>
|
||||
{t('倍率信息')}
|
||||
</span>
|
||||
<Tooltip
|
||||
content={t('倍率是为了方便换算不同价格的模型')}
|
||||
>
|
||||
<IconHelpCircle
|
||||
className='text-blue-500 cursor-pointer'
|
||||
size='small'
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
setModalImageUrl('/ratio.png');
|
||||
setIsModalOpenurl(true);
|
||||
}}
|
||||
/>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className='grid grid-cols-3 gap-2 text-xs text-gray-600'>
|
||||
<div>
|
||||
{t('模型')}:{' '}
|
||||
{model.quota_type === 0
|
||||
? (priceData?.inputRatio ?? model.model_ratio)
|
||||
: t('无')}
|
||||
</div>
|
||||
<div>
|
||||
{t('输出')}:{' '}
|
||||
{model.quota_type === 0
|
||||
? parseFloat(model.completion_ratio.toFixed(2))
|
||||
: t('无')}
|
||||
</div>
|
||||
<div>
|
||||
{t('分组')}: {priceData?.usedGroupRatio ?? '-'}
|
||||
</div>
|
||||
{(() => {
|
||||
const items = getModelPriceItemsForCard(model, priceData);
|
||||
const inputItem = items.find(i => i.key === 'input');
|
||||
const outputItem = items.find(i => i.key === 'output');
|
||||
return (
|
||||
<div className='flex gap-3'>
|
||||
{inputItem && (
|
||||
<div className='flex-1 rounded-xl px-3 py-2.5' style={{backgroundColor: 'var(--semi-color-fill-0)'}}>
|
||||
<div className='text-[10px] mb-0.5' style={{color: 'var(--semi-color-text-2)'}}>{inputItem.label}</div>
|
||||
<div className='text-sm font-bold text-gray-900'>
|
||||
{inputItem.value}{inputItem.suffix}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{outputItem && (
|
||||
<div className='flex-1 rounded-xl px-3 py-2.5' style={{backgroundColor: 'var(--semi-color-fill-0)'}}>
|
||||
<div className='text-[10px] mb-0.5' style={{color: 'var(--semi-color-text-2)'}}>{outputItem.label}</div>
|
||||
<div className='text-sm font-bold text-gray-900'>
|
||||
{outputItem.value}{outputItem.suffix}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
{!inputItem && !outputItem && items.map(item => (
|
||||
<div key={item.key} className='flex-1 rounded-xl px-3 py-2.5' style={{backgroundColor: 'var(--semi-color-fill-0)'}}>
|
||||
<div className='text-[10px] mb-0.5' style={{color: 'var(--semi-color-text-2)'}}>{item.label}</div>
|
||||
<div className='text-sm font-bold text-gray-900'>
|
||||
{item.valueNode || (item.value + (item.suffix || ''))}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
})()}
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
|
|
|||
Loading…
Reference in New Issue