feat: provider lsit

This commit is contained in:
jialin
2026-02-03 18:21:08 +08:00
parent 2dfdd4a0d9
commit 34331063eb
16 changed files with 135 additions and 55 deletions
+1 -1
View File
@@ -106,7 +106,7 @@ export default [
component: './llmodels/index' component: './llmodels/index'
}, },
{ {
name: 'provider', name: 'providers',
path: '/models/providers', path: '/models/providers',
key: 'modelProviders', key: 'modelProviders',
icon: 'icon-extension-outline', icon: 'icon-extension-outline',
+1 -3
View File
@@ -157,9 +157,7 @@ export const FilterBar: React.FC<FilterBarProps> = (props) => {
actionType === 'dropdown' ? ( actionType === 'dropdown' ? (
<DropDownActions <DropDownActions
styles={{ styles={{
root: { root: { minWidth: '125px' }
minWidth: 140
}
}} }}
menu={{ menu={{
items: actionItems, items: actionItems,
+1
View File
@@ -17,6 +17,7 @@ export default {
'menu.models.benchmark': 'Benchmarks', 'menu.models.benchmark': 'Benchmarks',
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.models.provider': 'Provider', 'menu.models.provider': 'Provider',
'menu.models.providers': 'Provider',
'menu.modelCatalog': 'Catalog', 'menu.modelCatalog': 'Catalog',
'menu.resources': 'Resources', 'menu.resources': 'Resources',
'menu.apikeys': 'API Keys', 'menu.apikeys': 'API Keys',
+6
View File
@@ -0,0 +1,6 @@
export default {
'providers.title': 'Providers',
'providers.button.add': 'Add Provider',
'providers.table.providerName': 'Provider',
'providers.table.modelsCounts': 'Models Count'
};
+2 -1
View File
@@ -16,7 +16,7 @@ export default {
'menu.models.benchmark': 'Benchmarks', 'menu.models.benchmark': 'Benchmarks',
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.modelCatalog': 'カタログ', 'menu.modelCatalog': 'カタログ',
'menu.models.provider': 'Provider', 'menu.models.providers': 'Provider',
'menu.resources': 'リソース', 'menu.resources': 'リソース',
'menu.apikeys': 'APIキー', 'menu.apikeys': 'APIキー',
'menu.users': 'ユーザー', 'menu.users': 'ユーザー',
@@ -56,4 +56,5 @@ export default {
// 14. 'menu.resources.backendsList': 'Inference Backends', // 14. 'menu.resources.backendsList': 'Inference Backends',
// 15. 'menu.models.benchmark': 'Benchmarks', // 15. 'menu.models.benchmark': 'Benchmarks',
// 15. 'menu.models.provider': 'Provider', // 15. 'menu.models.provider': 'Provider',
// 15. 'menu.models.providers': 'Provider',
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+6
View File
@@ -0,0 +1,6 @@
export default {
'providers.title': 'Providers',
'providers.button.add': 'Add Provider',
'providers.table.providerName': 'Provider',
'providers.table.modelsCounts': 'Models Count'
};
+5
View File
@@ -16,6 +16,7 @@ export default {
'menu.models.benchmark': 'Benchmarks', 'menu.models.benchmark': 'Benchmarks',
'menu.models.benchmarkDetail': 'Benchmark Details', 'menu.models.benchmarkDetail': 'Benchmark Details',
'menu.models.provider': 'Provider', 'menu.models.provider': 'Provider',
'menu.models.providers': 'Provider',
'menu.modelCatalog': 'Каталог', 'menu.modelCatalog': 'Каталог',
'menu.resources': 'Ресурсы', 'menu.resources': 'Ресурсы',
'menu.apikeys': 'API-ключи', 'menu.apikeys': 'API-ключи',
@@ -40,7 +41,11 @@ export default {
}; };
// ========== To-Do: Translate Keys (Remove After Translation) ========== // ========== To-Do: Translate Keys (Remove After Translation) ==========
<<<<<<< HEAD
// 1. 'menu.models.benchmark': 'Benchmarks', // 1. 'menu.models.benchmark': 'Benchmarks',
// 2. 'menu.models.benchmarkDetail': 'Benchmark Details', // 2. 'menu.models.benchmarkDetail': 'Benchmark Details',
// 1. 'menu.models.provider': 'Provider', // 1. 'menu.models.provider': 'Provider',
=======
// 1. 'menu.models.providers': 'Provider',
>>>>>>> ddf1a270 (feat: provider lsit)
// ========== End of To-Do List ========== // ========== End of To-Do List ==========
+6
View File
@@ -0,0 +1,6 @@
export default {
'providers.title': 'Providers',
'providers.button.add': 'Add Provider',
'providers.table.providerName': 'Provider',
'providers.table.modelsCounts': 'Models Count'
};
+1
View File
@@ -16,6 +16,7 @@ export default {
'menu.models.benchmark': '基准测试', 'menu.models.benchmark': '基准测试',
'menu.models.benchmarkDetail': '基准测试详情', 'menu.models.benchmarkDetail': '基准测试详情',
'menu.models.provider': '渠道', 'menu.models.provider': '渠道',
'menu.models.providers': '渠道',
'menu.modelCatalog': '模型库', 'menu.modelCatalog': '模型库',
'menu.models.catalog': '模型库', 'menu.models.catalog': '模型库',
'menu.resources': '资源', 'menu.resources': '资源',
+6
View File
@@ -0,0 +1,6 @@
export default {
'providers.title': '渠道',
'providers.button.add': '添加渠道',
'providers.table.providerName': '渠道',
'providers.table.modelsCounts': '模型数量'
};
@@ -1,7 +1,9 @@
import React from 'react'; import React from 'react';
interface ProviderModelProps { interface ProviderModelProps {
name: string; dataList: any[];
provider: string;
providerId: number;
} }
const ProviderModels: React.FC<ProviderModelProps> = () => { const ProviderModels: React.FC<ProviderModelProps> = () => {
+8 -5
View File
@@ -25,7 +25,7 @@ export const maasProviderLabelMap = {
[maasProviderValueMap.Anthropic]: 'Anthropic' [maasProviderValueMap.Anthropic]: 'Anthropic'
}; };
export const IconsMap = { export const providerIconsMap = {
[maasProviderValueMap.Doubao]: 'icon-doubao', [maasProviderValueMap.Doubao]: 'icon-doubao',
[maasProviderValueMap.Qwen]: 'icon-qwen', [maasProviderValueMap.Qwen]: 'icon-qwen',
[maasProviderValueMap.OpenAI]: 'icon-openai', [maasProviderValueMap.OpenAI]: 'icon-openai',
@@ -33,10 +33,13 @@ export const IconsMap = {
[maasProviderValueMap.Anthropic]: 'icon-anthropic' [maasProviderValueMap.Anthropic]: 'icon-anthropic'
}; };
export const maasProviderOptions = Object.keys(maasProviderValueMap).map( export const maasProviderOptions = Object.entries(maasProviderValueMap).map(
(key) => ({ ([key, value]) => ({
label: maasProviderLabelMap[key], label: maasProviderLabelMap[value],
value: maasProviderValueMap[key as keyof typeof maasProviderValueMap] value: value,
key: value,
locale: false,
icon: providerIconsMap[value]
}) })
); );
+50
View File
@@ -0,0 +1,50 @@
import { MaasProviderItem } from '../config/types';
// mock data for MaasProviderItem 5 items
export const mockDataList: MaasProviderItem[] = [
{
id: 1,
name: 'Doubao',
state: 'Ready',
models: 5,
state_message: '',
provider: 'doubao',
builtIn: false
},
{
id: 2,
models: 3,
name: 'Qwen',
state: 'Inactive',
state_message: 'Provider is inactive',
provider: 'qwen',
builtIn: true
},
{
id: 3,
models: 8,
name: 'OpenAI',
state: 'Ready',
state_message: '',
provider: 'openai',
builtIn: false
},
{
id: 4,
models: 2,
name: 'Deepseek',
state: 'Ready',
state_message: '',
provider: 'deepseek',
builtIn: false
},
{
id: 5,
models: 4,
name: 'Anthropic',
state: 'Inactive',
state_message: 'Provider is inactive',
provider: 'anthropic',
builtIn: true
}
];
+2
View File
@@ -3,9 +3,11 @@ import { maasProviderType } from '.';
export interface MaasProviderItem { export interface MaasProviderItem {
id: number; id: number;
name: string; name: string;
models?: number;
state: string; state: string;
state_message: string; state_message: string;
provider: maasProviderType; provider: maasProviderType;
builtIn: boolean;
} }
export interface FormData { export interface FormData {
@@ -1,15 +1,17 @@
// columns.ts // columns.ts
import AutoTooltip from '@/components/auto-tooltip'; import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons'; import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import { SealColumnProps } from '@/components/seal-table/types'; import { SealColumnProps } from '@/components/seal-table/types';
import StatusTag from '@/components/status-tag'; import StatusTag from '@/components/status-tag';
import { tableSorter } from '@/config/settings'; import { tableSorter } from '@/config/settings';
import { StarFilled } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Tooltip } from 'antd'; import { Tag } from 'antd';
import dayjs from 'dayjs'; import dayjs from 'dayjs';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { import {
maasProviderLabelMap,
providerIconsMap,
ProviderStatus, ProviderStatus,
ProviderStatusLabelMap, ProviderStatusLabelMap,
rowActionList rowActionList
@@ -28,66 +30,48 @@ const useProviderColumns = (
title: intl.formatMessage({ id: 'common.table.name' }), title: intl.formatMessage({ id: 'common.table.name' }),
dataIndex: 'name', dataIndex: 'name',
sorter: tableSorter(1), sorter: tableSorter(1),
span: 3, span: 5,
render: (text: string, record: MaasProviderItem) => ( render: (text: string, record: MaasProviderItem) => (
<> <>
<AutoTooltip ghost title={text}> <AutoTooltip ghost title={text}>
{text} {text}
</AutoTooltip> </AutoTooltip>
{record.is_default && ( {record.builtIn && (
<Tooltip <Tag color="blue" style={{ marginLeft: 8 }}>
title={intl.formatMessage({ BuiltIn
id: 'clusters.form.setDefault.tips' </Tag>
})}
>
<StarFilled
style={{ color: 'var(--ant-gold-4)', marginLeft: 4 }}
/>
</Tooltip>
)} )}
</> </>
) )
}, },
{ {
title: intl.formatMessage({ id: 'clusters.table.provider' }), title: intl.formatMessage({ id: 'providers.table.providerName' }),
dataIndex: 'provider', dataIndex: 'provider',
sorter: tableSorter(2), sorter: tableSorter(2),
span: 3, span: 4,
render: (value: string) => ( render: (value: string) => (
<AutoTooltip ghost minWidth={20}> <>
{ProviderStatusLabelMap[value]} <IconFont
</AutoTooltip> type={providerIconsMap[value]}
style={{ marginRight: 8, fontSize: 16 }}
></IconFont>
<AutoTooltip ghost minWidth={20}>
{maasProviderLabelMap[value]}
</AutoTooltip>
</>
) )
}, },
{ {
title: 'GPUs', title: intl.formatMessage({ id: 'providers.table.modelsCounts' }),
dataIndex: 'gpus', dataIndex: 'models',
span: 2, span: 3,
sorter: tableSorter(3), sorter: tableSorter(3),
render: (value: number) => <span>{value}</span> render: (value: number) => <span>{value}</span>
}, },
{
title: intl.formatMessage({ id: 'clusters.table.deployments' }),
dataIndex: 'models',
sorter: tableSorter(4),
span: 3,
render: (value: number) => <span>{value}</span>
},
{
title: intl.formatMessage({ id: 'resources.nodes' }),
dataIndex: 'workers',
sorter: tableSorter(5),
span: 3,
render: (value: number, record: MaasProviderItem) => (
<span>
{record.ready_workers} / {record.workers}
</span>
)
},
{ {
title: intl.formatMessage({ id: 'common.table.status' }), title: intl.formatMessage({ id: 'common.table.status' }),
dataIndex: 'state', dataIndex: 'state',
span: 3, span: 4,
render: (value: string, record: MaasProviderItem) => ( render: (value: string, record: MaasProviderItem) => (
<StatusTag <StatusTag
statusValue={{ statusValue={{
+13 -4
View File
@@ -27,6 +27,8 @@ import {
} from './apis'; } from './apis';
import AddMaasProvider from './components/add-provider-modal'; import AddMaasProvider from './components/add-provider-modal';
import ProviderModels from './components/provider-models'; import ProviderModels from './components/provider-models';
import { maasProviderOptions } from './config';
import { mockDataList } from './config/mock';
import { import {
FormData, FormData,
MaasProviderItem as ListItem, MaasProviderItem as ListItem,
@@ -53,7 +55,7 @@ const MaasProvider: React.FC = () => {
deleteAPI: deleteProvider, deleteAPI: deleteProvider,
watch: true, watch: true,
API: MAAS_PROVIDERS_API, API: MAAS_PROVIDERS_API,
contentForDelete: 'menu.clusterManagement.clusters' contentForDelete: 'menu.models.providers'
}); });
const { watchDataList: allProviderModels } = const { watchDataList: allProviderModels } =
useWatchList(PROVIDER_MODELS_API); useWatchList(PROVIDER_MODELS_API);
@@ -166,7 +168,7 @@ const MaasProvider: React.FC = () => {
<ProviderModels <ProviderModels
dataList={list} dataList={list}
provider={options.parent?.provider} provider={options.parent?.provider}
clusterId={options.parent?.id} providerId={options.parent?.id}
/> />
); );
}; };
@@ -177,16 +179,23 @@ const MaasProvider: React.FC = () => {
<> <>
<PageBox> <PageBox>
<FilterBar <FilterBar
actionType="dropdown"
showSelect={false} showSelect={false}
marginBottom={22} marginBottom={22}
marginTop={30} marginTop={30}
widths={{ input: 300 }} widths={{ input: 300 }}
buttonText={intl.formatMessage({ id: 'clusters.button.add' })} buttonText={intl.formatMessage({ id: 'providers.button.add' })}
rowSelection={rowSelection} rowSelection={rowSelection}
handleInputChange={handleNameChange} handleInputChange={handleNameChange}
handleSearch={handleSearch} handleSearch={handleSearch}
handleDeleteByBatch={handleDeleteBatch} handleDeleteByBatch={handleDeleteBatch}
handleClickPrimary={handleClickDropdown} handleClickPrimary={handleClickDropdown}
actionItems={maasProviderOptions.map((option) => ({
...option,
icon: (
<IconFont type={option.icon as string} style={{ fontSize: 14 }} />
)
}))}
></FilterBar> ></FilterBar>
<TableContext.Provider <TableContext.Provider
value={{ value={{
@@ -203,7 +212,7 @@ const MaasProvider: React.FC = () => {
renderChildren={renderChildren} renderChildren={renderChildren}
onTableSort={handleOnSortChange} onTableSort={handleOnSortChange}
showSorterTooltip={false} showSorterTooltip={false}
dataSource={dataSource.dataList} dataSource={mockDataList}
loading={dataSource.loading} loading={dataSource.loading}
loadend={dataSource.loadend} loadend={dataSource.loadend}
rowSelection={rowSelection} rowSelection={rowSelection}