From 77b885b1908495fe7a9d03579f704eb5668f925a Mon Sep 17 00:00:00 2001 From: xiezhouwei Date: Thu, 18 Jun 2026 16:50:02 +0800 Subject: [PATCH] refactor: streamline model card to show only logo, name, description, and IO prices --- web/src/components/home/HomeModelList.jsx | 7 - .../view/card/PricingCardSkeleton.jsx | 84 +--- .../view/card/PricingCardView.jsx | 361 ++---------------- 3 files changed, 59 insertions(+), 393 deletions(-) diff --git a/web/src/components/home/HomeModelList.jsx b/web/src/components/home/HomeModelList.jsx index e6d44da..2051722 100644 --- a/web/src/components/home/HomeModelList.jsx +++ b/web/src/components/home/HomeModelList.jsx @@ -378,7 +378,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} diff --git a/web/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx b/web/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx index 75514d1..822c879 100644 --- a/web/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx +++ b/web/src/components/table/model-pricing/view/card/PricingCardSkeleton.jsx @@ -22,8 +22,6 @@ import { Card, Skeleton } from '@douyinfe/semi-ui'; const PricingCardSkeleton = ({ skeletonCount = 100, - rowSelection = false, - showRatio = false, }) => { const placeholder = (
@@ -34,8 +32,8 @@ const PricingCardSkeleton = ({ className='!rounded-2xl border border-gray-200' bodyStyle={{ padding: '24px' }} > - {/* 头部:图标 + 模型名称 + 操作按钮 */} -
+ {/* 头部:图标 + 模型名称 */} +
{/* 模型图标骨架 */}
@@ -44,41 +42,17 @@ const PricingCardSkeleton = ({ style={{ width: 48, height: 48, borderRadius: 16 }} />
- {/* 模型名称和价格区域 */} + {/* 模型名称 */}
- {/* 模型名称骨架 */} - {/* 价格信息骨架 */} -
- -
- {/* 复制按钮骨架 */} - - {/* 勾选框骨架 */} - {rowSelection && ( - - )} -
{/* 模型描述骨架 */} @@ -90,43 +64,25 @@ const PricingCardSkeleton = ({ />
- {/* 标签区域骨架 */} -
- {Array.from({ length: 2 + (index % 3) }).map((_, tagIndex) => ( - +
+ + - ))} -
- - {/* 倍率信息骨架(可选) */} - {showRatio && ( -
-
- - -
-
- {Array.from({ length: 3 }).map((_, ratioIndex) => ( - - ))} -
- )} +
+ + +
+
))}
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 7feba9e..98260da 100644 --- a/web/src/components/table/model-pricing/view/card/PricingCardView.jsx +++ b/web/src/components/table/model-pricing/view/card/PricingCardView.jsx @@ -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 = ( - - - - - ); - if (channelQuotaType === 1) { - billingTag = ( - - {t('按次计费')} - - ); - } else if (channelQuotaType === 0) { - billingTag = ( - - {t('按量计费')} - - ); - } - - // 自定义标签(右边) - const customTags = []; - if (record.tags) { - const tagArr = record.tags.split(',').filter(Boolean); - tagArr.forEach((tg, idx) => { - customTags.push( - - {renderHighlightedText(tg)} - , - ); - }); - } - - return ( -
-
{billingTag}
-
- {customTags.length > 0 && - renderLimitedItems({ - items: customTags.map((tag, idx) => ({ - key: `custom-${idx}`, - element: tag, - })), - renderItem: (item, idx) => item.element, - maxDisplay: 3, - })} -
-
- ); - }; - // 显示骨架屏 if (showSkeleton) { return ( <> - + ); } @@ -863,7 +726,6 @@ const PricingCardView = ({
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 ( 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) } >
- {/* 头部:图标 + 模型名称 + 操作按钮 */} -
+ {/* 头部:图标 + 模型名称 */} +
{getModelIcon(model)}

{renderHighlightedText(model.model_name)}

-
- {getModelPriceItemsForCard(model, priceData).map( - (item) => ( -
- - {item.label} - - - {item.valueNode ? ( - item.valueNode - ) : item.original ? ( - <> - - - 官方 - {' '} - {item.original.text} - - - -{item.original.discount}% - - - - 我们 - {' '} - {item.value} - {item.suffix} - - - ) : ( - - {item.value} - {item.suffix} - - )} - -
- ), - )} -
- - {t('供应商')} - -
- {supplierLogos.length === 0 ? ( - hasChannelList ? null : ( - - {t('官方')} - - ) - ) : ( - supplierLogos.map((s) => ( -
- {s.logo ? ( - {s.alias - ) : null} - {s.supplierType && ( - - {s.supplierType} - - )} -
- )) - )} -
-
-
- -
- {/* 复制按钮 */} -
- {/* 模型描述 - 占据剩余空间 */} + {/* 模型描述 */}
- {/* 底部区域 */} + {/* 价格:输入 + 输出并排 */}
- {/* 标签区域 */} - {renderTags(model)} - - {/* 倍率信息(可选) */} - {showRatio && ( -
-
- - {t('倍率信息')} - - - { - e.stopPropagation(); - setModalImageUrl('/ratio.png'); - setIsModalOpenurl(true); - }} - /> - + {(() => { + const items = getModelPriceItemsForCard(model, priceData); + const inputItem = items.find(i => i.key === 'input'); + const outputItem = items.find(i => i.key === 'output'); + return ( +
+ {inputItem && ( +
+
{inputItem.label}
+
+ {inputItem.value}{inputItem.suffix} +
+
+ )} + {outputItem && ( +
+
{outputItem.label}
+
+ {outputItem.value}{outputItem.suffix} +
+
+ )} + {!inputItem && !outputItem && items.map(item => ( +
+
{item.label}
+
+ {item.valueNode || (item.value + (item.suffix || ''))} +
+
+ ))}
-
-
- {t('模型')}:{' '} - {model.quota_type === 0 - ? (priceData?.inputRatio ?? model.model_ratio) - : t('无')} -
-
- {t('输出')}:{' '} - {model.quota_type === 0 - ? parseFloat(model.completion_ratio.toFixed(2)) - : t('无')} -
-
- {t('分组')}: {priceData?.usedGroupRatio ?? '-'} -
-
-
- )} + ); + })()}