✨ feat: Add endpoint type filter to model pricing system
- Create PricingEndpointTypes.jsx component for endpoint type filtering - Add filterEndpointType state management in useModelPricingData hook - Integrate endpoint type filtering logic in filteredModels computation - Update PricingSidebar.jsx to include endpoint type filter component - Update PricingFilterModal.jsx to support endpoint type filtering on mobile - Extend resetPricingFilters utility function to include endpoint type reset - Support filtering models by endpoint types (OpenAI, Anthropic, Gemini, etc.) - Display model count for each endpoint type with localized labels - Ensure filter state resets to first page when endpoint type changes This enhancement allows users to filter models by their supported endpoint types, providing more granular control over model selection in the pricing interface.
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright (C) 2025 QuantumNous
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
For commercial licensing, please contact support@quantumnous.com
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import SelectableButtonGroup from '../../../common/ui/SelectableButtonGroup';
|
||||
|
||||
/**
|
||||
* 端点类型筛选组件
|
||||
* @param {string|'all'} filterEndpointType 当前值
|
||||
* @param {Function} setFilterEndpointType setter
|
||||
* @param {Array} models 模型列表
|
||||
* @param {boolean} loading 是否加载中
|
||||
* @param {Function} t i18n
|
||||
*/
|
||||
const PricingEndpointTypes = ({ filterEndpointType, setFilterEndpointType, models = [], loading = false, t }) => {
|
||||
// 获取所有可用的端点类型
|
||||
const getAllEndpointTypes = () => {
|
||||
const endpointTypes = new Set();
|
||||
models.forEach(model => {
|
||||
if (model.supported_endpoint_types && Array.isArray(model.supported_endpoint_types)) {
|
||||
model.supported_endpoint_types.forEach(endpoint => {
|
||||
endpointTypes.add(endpoint);
|
||||
});
|
||||
}
|
||||
});
|
||||
return Array.from(endpointTypes).sort();
|
||||
};
|
||||
|
||||
// 计算每个端点类型的模型数量
|
||||
const getEndpointTypeCount = (endpointType) => {
|
||||
if (endpointType === 'all') {
|
||||
return models.length;
|
||||
}
|
||||
return models.filter(model =>
|
||||
model.supported_endpoint_types &&
|
||||
model.supported_endpoint_types.includes(endpointType)
|
||||
).length;
|
||||
};
|
||||
|
||||
// 端点类型显示名称映射
|
||||
const getEndpointTypeLabel = (endpointType) => {
|
||||
const labelMap = {
|
||||
'openai': 'OpenAI',
|
||||
'openai-response': 'OpenAI Response',
|
||||
'anthropic': 'Anthropic',
|
||||
'gemini': 'Gemini',
|
||||
'jina-rerank': 'Jina Rerank',
|
||||
'image-generation': t('图像生成'),
|
||||
};
|
||||
return labelMap[endpointType] || endpointType;
|
||||
};
|
||||
|
||||
const availableEndpointTypes = getAllEndpointTypes();
|
||||
|
||||
const items = [
|
||||
{ value: 'all', label: t('全部端点'), tagCount: getEndpointTypeCount('all') },
|
||||
...availableEndpointTypes.map(endpointType => ({
|
||||
value: endpointType,
|
||||
label: getEndpointTypeLabel(endpointType),
|
||||
tagCount: getEndpointTypeCount(endpointType)
|
||||
}))
|
||||
];
|
||||
|
||||
return (
|
||||
<SelectableButtonGroup
|
||||
title={t('端点类型')}
|
||||
items={items}
|
||||
activeValue={filterEndpointType}
|
||||
onChange={setFilterEndpointType}
|
||||
loading={loading}
|
||||
t={t}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export default PricingEndpointTypes;
|
||||
@@ -22,6 +22,7 @@ import { Button } from '@douyinfe/semi-ui';
|
||||
import PricingCategories from '../filter/PricingCategories';
|
||||
import PricingGroups from '../filter/PricingGroups';
|
||||
import PricingQuotaTypes from '../filter/PricingQuotaTypes';
|
||||
import PricingEndpointTypes from '../filter/PricingEndpointTypes';
|
||||
import PricingDisplaySettings from '../filter/PricingDisplaySettings';
|
||||
import { resetPricingFilters } from '../../../../helpers/utils';
|
||||
|
||||
@@ -40,6 +41,8 @@ const PricingSidebar = ({
|
||||
setFilterGroup,
|
||||
filterQuotaType,
|
||||
setFilterQuotaType,
|
||||
filterEndpointType,
|
||||
setFilterEndpointType,
|
||||
currentPage,
|
||||
setCurrentPage,
|
||||
loading,
|
||||
@@ -58,6 +61,7 @@ const PricingSidebar = ({
|
||||
setViewMode,
|
||||
setFilterGroup,
|
||||
setFilterQuotaType,
|
||||
setFilterEndpointType,
|
||||
setCurrentPage,
|
||||
});
|
||||
|
||||
@@ -114,6 +118,14 @@ const PricingSidebar = ({
|
||||
loading={loading}
|
||||
t={t}
|
||||
/>
|
||||
|
||||
<PricingEndpointTypes
|
||||
filterEndpointType={filterEndpointType}
|
||||
setFilterEndpointType={setFilterEndpointType}
|
||||
models={categoryProps.models}
|
||||
loading={loading}
|
||||
t={t}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -22,6 +22,7 @@ import { Modal, Button } from '@douyinfe/semi-ui';
|
||||
import PricingCategories from '../filter/PricingCategories';
|
||||
import PricingGroups from '../filter/PricingGroups';
|
||||
import PricingQuotaTypes from '../filter/PricingQuotaTypes';
|
||||
import PricingEndpointTypes from '../filter/PricingEndpointTypes';
|
||||
import PricingDisplaySettings from '../filter/PricingDisplaySettings';
|
||||
import { resetPricingFilters } from '../../../../helpers/utils';
|
||||
|
||||
@@ -46,6 +47,8 @@ const PricingFilterModal = ({
|
||||
setFilterGroup,
|
||||
filterQuotaType,
|
||||
setFilterQuotaType,
|
||||
filterEndpointType,
|
||||
setFilterEndpointType,
|
||||
currentPage,
|
||||
setCurrentPage,
|
||||
loading,
|
||||
@@ -63,6 +66,7 @@ const PricingFilterModal = ({
|
||||
setViewMode,
|
||||
setFilterGroup,
|
||||
setFilterQuotaType,
|
||||
setFilterEndpointType,
|
||||
setCurrentPage,
|
||||
});
|
||||
|
||||
@@ -133,6 +137,14 @@ const PricingFilterModal = ({
|
||||
loading={loading}
|
||||
t={t}
|
||||
/>
|
||||
|
||||
<PricingEndpointTypes
|
||||
filterEndpointType={filterEndpointType}
|
||||
setFilterEndpointType={setFilterEndpointType}
|
||||
models={categoryProps.models}
|
||||
loading={loading}
|
||||
t={t}
|
||||
/>
|
||||
</div>
|
||||
</Modal>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user