refactor: Restructure model pricing components and improve UX consistency

- **Fix SideSheet double-click issue**: Remove early return for null modelData to prevent rendering blockage during async state updates
- **Component modularization**:
  - Split ModelDetailSideSheet into focused sub-components (ModelHeader, ModelBasicInfo, ModelEndpoints, ModelPricingTable)
  - Refactor PricingFilterModal with FilterModalContent and FilterModalFooter components
  - Remove unnecessary FilterSection wrapper for cleaner interface
- **Improve visual consistency**:
  - Unify avatar/icon logic between ModelHeader and PricingCardView components
  - Standardize tag colors across all pricing components (violet/teal for billing types)
  - Apply consistent dashed border styling using Semi UI theme colors
- **Enhance data accuracy**:
  - Display raw endpoint type names (e.g., "openai", "anthropic") instead of translated descriptions
  - Remove text alignment classes for better responsive layout
  - Add proper null checks to prevent runtime errors
- **Code quality improvements**:
  - Reduce component complexity by 52-74% through modularization
  - Improve maintainability with single responsibility principle
  - Add comprehensive error handling for edge cases

This refactoring improves component reusability, reduces bundle size, and provides a more consistent user experience across the model pricing interface.
This commit is contained in:
t0ng7u
2025-07-26 04:24:22 +08:00
parent 52a9cee0e1
commit 0b1a1ca064
13 changed files with 775 additions and 119 deletions

View File

@@ -54,6 +54,7 @@ const PricingCardView = ({
setSelectedRowKeys,
activeKey,
availableCategories,
openModelDetail,
}) => {
const showSkeleton = useMinimumLoadingTime(loading);
@@ -138,7 +139,7 @@ const PricingCardView = ({
const renderTags = (record) => {
const tags = [];
// 计费类型标签
// 计费类型标签
const billingType = record.quota_type === 1 ? 'teal' : 'violet';
const billingText = record.quota_type === 1 ? t('按次计费') : t('按量计费');
tags.push(
@@ -211,9 +212,10 @@ const PricingCardView = ({
return (
<Card
key={modelKey || index}
className={`!rounded-2xl transition-all duration-200 hover:shadow-lg border ${isSelected ? CARD_STYLES.selected : CARD_STYLES.default
className={`!rounded-2xl transition-all duration-200 hover:shadow-lg border cursor-pointer ${isSelected ? CARD_STYLES.selected : CARD_STYLES.default
}`}
bodyStyle={{ padding: '24px' }}
onClick={() => openModelDetail && openModelDetail(model)}
>
{/* 头部:图标 + 模型名称 + 操作按钮 */}
<div className="flex items-start justify-between mb-3">
@@ -235,14 +237,20 @@ const PricingCardView = ({
size="small"
type="tertiary"
icon={<IconCopy />}
onClick={() => copyText(model.model_name)}
onClick={(e) => {
e.stopPropagation();
copyText(model.model_name);
}}
/>
{/* 选择框 */}
{rowSelection && (
<Checkbox
checked={isSelected}
onChange={(e) => handleCheckboxChange(model, e.target.checked)}
onChange={(e) => {
e.stopPropagation();
handleCheckboxChange(model, e.target.checked);
}}
/>
)}
</div>
@@ -265,14 +273,18 @@ const PricingCardView = ({
{/* 倍率信息(可选) */}
{showRatio && (
<div className="mt-4 pt-3 border-t border-gray-100">
<div
className="mt-4 pt-3 border-t border-dashed"
style={{ borderColor: 'var(--semi-color-border)' }}
>
<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={() => {
onClick={(e) => {
e.stopPropagation();
setModalImageUrl('/ratio.png');
setIsModalOpenurl(true);
}}

View File

@@ -43,6 +43,7 @@ const PricingTable = ({
searchValue,
showRatio,
compactMode = false,
openModelDetail,
t
}) => {
@@ -100,6 +101,10 @@ const PricingTable = ({
rowSelection={rowSelection}
className="custom-table"
scroll={compactMode ? undefined : { x: 'max-content' }}
onRow={(record) => ({
onClick: () => openModelDetail && openModelDetail(record),
style: { cursor: 'pointer' }
})}
empty={
<Empty
image={<IllustrationNoResult style={{ width: 150, height: 150 }} />}
@@ -117,7 +122,7 @@ const PricingTable = ({
}}
/>
</Card>
), [filteredModels, loading, processedColumns, rowSelection, pageSize, setPageSize, t, compactMode]);
), [filteredModels, loading, processedColumns, rowSelection, pageSize, setPageSize, openModelDetail, t, compactMode]);
return ModelTable;
};