style: providers selection, remove fallback form

This commit is contained in:
jialin
2026-02-03 18:21:08 +08:00
parent 5fcdf4ea00
commit 15cd9795d5
18 changed files with 200 additions and 124 deletions
+1 -1
View File
@@ -29,7 +29,7 @@ export const StatusColorMap: Record<
},
inactive: {
text: `var(--ant-color-text-tertiary)`,
border: `rgba(200,200,200,1)`,
border: `var(--ant-color-border)`,
bg: `var(--ant-color-fill)`
}
};
+2 -1
View File
@@ -2,5 +2,6 @@ export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share'
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback'
};
+2 -1
View File
@@ -2,5 +2,6 @@ export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share'
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback'
};
+2 -1
View File
@@ -2,5 +2,6 @@ export default {
'accesses.title': 'Accesses',
'accesses.button.add': 'Add Access',
'accesses.table.accessPoints': 'Access Points',
'accesses.table.traffic': 'Traffic Share'
'accesses.table.traffic': 'Traffic Share',
'accesses.table.setAsFallback': 'Set as Fallback'
};
+2 -1
View File
@@ -2,5 +2,6 @@ export default {
'accesses.title': '接入',
'accesses.button.add': '添加接入',
'accesses.table.accessPoints': '接入点',
'accesses.table.traffic': '流量'
'accesses.table.traffic': '流量',
'accesses.table.setAsFallback': '设为备选'
};
@@ -1,3 +1,4 @@
import AutoTooltip from '@/components/auto-tooltip';
import { modelCategoriesMap } from '@/pages/llmodels/config';
import {
CheckCircleOutlined,
@@ -54,17 +55,28 @@ const ProviderModels: React.FC<ProviderModelProps> = () => {
<Tag
key={model.name}
icon={iconsMap[model.status]}
variant="outlined"
styles={{
root: {
display: 'flex',
alignItems: 'center'
}
}}
color={
model.status === 'accessible'
? 'success'
: model.status === 'inaccessible'
? 'red'
: 'gray'
: 'default'
}
>
{model.name}
<span style={{ marginLeft: 8 }}>
{categoryConfig[model.type]?.icon}
<span className="flex-center">
<AutoTooltip ghost maxWidth={'120px'}>
{model.name}
</AutoTooltip>
<span style={{ marginLeft: 8 }}>
{categoryConfig[model.type]?.icon}
</span>
</span>
</Tag>
))}
+4 -39
View File
@@ -1,47 +1,12 @@
import icons from '@/components/icon-font/icons';
import { StatusMaps } from '@/config';
import { StatusType } from '@/config/types';
import { ProviderEnum } from './providers';
export { maasProviderLabelMap, maasProviderOptions } from './providers';
export type maasProviderType =
| 'doubao'
| 'qwen'
| 'openai'
| 'deepseek'
| 'anthropic';
export type maasProviderType = ProviderEnum[keyof ProviderEnum];
export const maasProviderValueMap = {
Doubao: 'doubao',
Qwen: 'qwen',
OpenAI: 'openai',
Deepseek: 'deepseek',
Anthropic: 'anthropic'
};
export const maasProviderLabelMap = {
[maasProviderValueMap.Doubao]: 'Doubao',
[maasProviderValueMap.Qwen]: 'Qwen',
[maasProviderValueMap.OpenAI]: 'OpenAI',
[maasProviderValueMap.Deepseek]: 'DeepSeek',
[maasProviderValueMap.Anthropic]: 'Anthropic'
};
export const providerIconsMap = {
[maasProviderValueMap.Doubao]: 'icon-doubao',
[maasProviderValueMap.Qwen]: 'icon-qwen',
[maasProviderValueMap.OpenAI]: 'icon-openai',
[maasProviderValueMap.Deepseek]: 'icon-deepseek',
[maasProviderValueMap.Anthropic]: 'icon-anthropic'
};
export const maasProviderOptions = Object.entries(maasProviderValueMap).map(
([key, value]) => ({
label: maasProviderLabelMap[value],
value: value,
key: value,
locale: false,
icon: providerIconsMap[value]
})
);
export const maasProviderValueMap = ProviderEnum;
export const ProviderStatusValueMap: Record<string, string> = {
Ready: 'ready',
+9 -5
View File
@@ -9,7 +9,8 @@ export const mockDataList: MaasProviderItem[] = [
models: 5,
state_message: '',
provider: 'doubao',
proxy_config: {},
api_tokens: ['token1', 'token2'],
proxy_url: 'http://proxy.example.com',
builtIn: false
},
{
@@ -19,7 +20,8 @@ export const mockDataList: MaasProviderItem[] = [
state: 'inactive',
state_message: 'Provider is inactive',
provider: 'qwen',
proxy_config: false,
proxy_url: 'http://proxy2.example.com',
builtIn: true
},
{
@@ -28,7 +30,8 @@ export const mockDataList: MaasProviderItem[] = [
name: 'OpenAI',
state: 'ready',
state_message: '',
proxy_config: null,
proxy_url: null,
api_tokens: ['tokenA'],
provider: 'openai',
builtIn: false
},
@@ -39,7 +42,8 @@ export const mockDataList: MaasProviderItem[] = [
state: 'ready',
state_message: '',
provider: 'deepseek',
proxy_config: null,
proxy_url: null,
api_tokens: ['tokenX', 'tokenY'],
builtIn: false
},
{
@@ -49,7 +53,7 @@ export const mockDataList: MaasProviderItem[] = [
state: 'inactive',
state_message: 'Provider is inactive',
provider: 'anthropic',
proxy_config: {},
proxy_url: {},
builtIn: true
}
];
@@ -0,0 +1,56 @@
export enum ProviderEnum {
AI360 = 'ai360',
AZURE = 'azure',
BAICHUAN = 'baichuan',
BAIDU = 'baidu',
BEDROCK = 'bedrock',
CLAUDE = 'claude',
CLOUDFLARE = 'cloudflare',
COHERE = 'cohere',
COZE = 'coze',
DEEPL = 'deepl',
DEEPSEEK = 'deepseek',
DIFY = 'dify',
DOUBAO = 'doubao',
FIREWORKS = 'fireworks',
GEMINI = 'gemini',
GITHUB = 'github',
GROK = 'grok',
GROQ = 'groq',
HUNYUAN = 'hunyuan',
LONGCAT = 'longcat',
MINIMAX = 'minimax',
MISTRAL = 'mistral',
MOONSHOT = 'moonshot',
OLLAMA = 'ollama',
OPENAI = 'openai',
OPENROUTER = 'openrouter',
QWEN = 'qwen',
SPARK = 'spark',
STEPFUN = 'stepfun',
TOGETHERAI = 'together-ai',
TRITON = 'triton',
YI = 'yi',
ZHIPUAI = 'zhipuai'
}
// generate provider list: {label: string;value:string}[]
export const maasProviderOptions = Object.entries(ProviderEnum).map(
([key, value]) => ({
locale: false,
label: key,
value: value,
key: value
})
);
// generate provider value to label map
export const maasProviderLabelMap: Record<string, string> = Object.entries(
ProviderEnum
).reduce(
(acc, [key, value]) => {
acc[value] = key;
return acc;
},
{} as Record<string, string>
);
+22 -6
View File
@@ -2,15 +2,31 @@ import { maasProviderType } from '.';
export interface MaasProviderItem {
id: number;
created_at: string;
updated_at: string;
deleted_at: string;
name: string;
models?: number;
state: string;
state_message: string;
provider: maasProviderType;
proxy_config?: any;
builtIn: boolean;
description: string;
api_tokens: string[];
timeout: number;
config: {
type: maasProviderType;
[key: string]: any;
};
support_models: unknown[];
proxy_url: string;
proxy_timeout: number;
builtin: boolean;
provider_model_count: number;
api_token_count: number;
}
export interface FormData {
name: string;
description: string;
api_tokens: string[];
config: {
type: maasProviderType;
[key: string]: any;
};
}
+7 -4
View File
@@ -1,6 +1,8 @@
import SealInput from '@/components/seal-form/seal-input';
import SealSelect from '@/components/seal-form/seal-select';
import { useIntl } from '@umijs/max';
import { Form } from 'antd';
import { maasProviderOptions } from '../config/providers';
import { FormData } from '../config/types';
const Basic = () => {
@@ -8,7 +10,7 @@ const Basic = () => {
const form = Form.useFormInstance<FormData>();
return (
<>
<Form.Item name="name" data-field="name">
<Form.Item<FormData> name="name" data-field="name">
<SealInput.Input
required
label={intl.formatMessage({
@@ -16,14 +18,15 @@ const Basic = () => {
})}
/>
</Form.Item>
<Form.Item name="provider" hidden>
<SealInput.Input
<Form.Item<FormData> name={['config', 'type']}>
<SealSelect
options={maasProviderOptions}
label={intl.formatMessage({
id: 'providers.table.providerName'
})}
/>
</Form.Item>
<Form.Item name="description">
<Form.Item<FormData> name="description">
<SealInput.TextArea
scaleSize={true}
label={intl.formatMessage({
@@ -1,20 +1,16 @@
// columns.ts
import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import { SealColumnProps } from '@/components/seal-table/types';
import StatusTag from '@/components/status-tag';
import { StatusMaps } from '@/config';
import { tableSorter } from '@/config/settings';
import { CheckCircleOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max';
import { Tag } from 'antd';
import dayjs from 'dayjs';
import { useMemo } from 'react';
import {
maasProviderLabelMap,
providerIconsMap,
ProviderStatus,
rowActionList
} from '../config';
import { maasProviderLabelMap, rowActionList } from '../config';
import { MaasProviderItem } from '../config/types';
const useProviderColumns = (
@@ -35,7 +31,7 @@ const useProviderColumns = (
<AutoTooltip ghost title={text}>
{text}
</AutoTooltip>
{record.builtIn && (
{record.builtin && (
<Tag color="blue" style={{ marginLeft: 8 }}>
BuiltIn
</Tag>
@@ -50,10 +46,6 @@ const useProviderColumns = (
span: 4,
render: (value: string) => (
<>
<IconFont
type={providerIconsMap[value]}
style={{ marginRight: 8, fontSize: 16 }}
></IconFont>
<AutoTooltip ghost minWidth={20}>
{maasProviderLabelMap[value]}
</AutoTooltip>
@@ -69,19 +61,30 @@ const useProviderColumns = (
},
{
title: intl.formatMessage({ id: 'providers.table.proxy' }),
dataIndex: 'proxy_config',
dataIndex: 'proxy_url',
span: 3,
render: (value: number) => <span>{value ? 'Configured' : 'None'}</span>
render: (value: number) => (
<span>
{value ? (
<CheckCircleOutlined
style={{ color: 'var(--ant-color-success)' }}
/>
) : (
'-'
)}
</span>
)
},
{
title: 'Token Settings',
dataIndex: 'tokens',
dataIndex: 'api_tokens',
span: 3,
render: (value: string, record: MaasProviderItem) => (
<StatusTag
statusValue={{
status: ProviderStatus['ready'],
text: 'Configured',
status:
value?.length > 0 ? StatusMaps.success : StatusMaps.inactive,
text: value?.length > 0 ? 'Configured' : 'Unconfigured',
message: ''
}}
/>
-1
View File
@@ -166,7 +166,6 @@ const MaasProvider: React.FC = () => {
<>
<PageBox>
<FilterBar
actionType="dropdown"
showSelect={false}
marginBottom={22}
marginTop={30}
@@ -3,11 +3,12 @@ import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import RowChildren from '@/components/seal-table/components/row-children';
import StatusTag from '@/components/status-tag';
import { DeleteOutlined } from '@ant-design/icons';
import { DeleteOutlined, StarFilled, StarOutlined } from '@ant-design/icons';
import { Col, Row } from 'antd';
import dayjs from 'dayjs';
import React from 'react';
import styled from 'styled-components';
import { mockAccessPointList } from '../config/mock';
const CellContent = styled.div`
display: flex;
@@ -35,9 +36,8 @@ export const childActionList = [
},
{
key: 'fallback',
label: 'Fallback settings',
localel: false,
icon: <IconFont type="icon-captive_portal" />
label: 'accesses.table.setAsFallback',
icon: <StarOutlined />
},
{
key: 'delete',
@@ -61,6 +61,11 @@ const AccessItem: React.FC<AccessItemProps> = ({ onSelect, data }) => {
}}
>
<AutoTooltip ghost>qwen3-0.6b-zduxy</AutoTooltip>
{data.is_fallback && (
<StarFilled
style={{ color: 'var(--ant-color-warning)', marginLeft: 8 }}
/>
)}
</CellContent>
</Col>
<Col span={5}>
@@ -106,11 +111,9 @@ const AccessPoints: React.FC<ProviderModelProps> = ({ dataList, onSelect }) => {
console.log('AccessPoints dataList:', dataList);
return (
<div>
{Array(2)
.fill(1)
.map((item, index) => (
<AccessItem data={item} key={index} onSelect={onSelect}></AccessItem>
))}
{mockAccessPointList.map((item, index) => (
<AccessItem data={item} key={index} onSelect={onSelect}></AccessItem>
))}
</div>
);
};
+20 -1
View File
@@ -1,4 +1,4 @@
import { AccessItem } from './types';
import { AccessItem, AccessPointItem } from './types';
// mock data for AccessItem 5 items
export const mockDataList: AccessItem[] = [
@@ -33,3 +33,22 @@ export const mockDataList: AccessItem[] = [
accessPoints: 4
}
];
// mock data for AccessPointItem 2 items
export const mockAccessPointList: AccessPointItem[] = [
{
id: 1,
name: 'Access Point 1',
type: 'API',
is_fallback: true,
endpoint: 'https://api.example.com/endpoint1',
created_at: '2024-01-01T12:00:00Z'
},
{
id: 2,
name: 'Access Point 2',
type: 'SDK',
is_fallback: false,
created_at: '2024-02-01T12:00:00Z'
}
];
+23 -2
View File
@@ -1,8 +1,14 @@
export interface AccessItem {
id: number;
created_at: string;
updated_at: string;
deleted_at: string;
name: string;
source: string;
accessPoints?: number;
description: string;
categories: string[];
meta: Record<string, any>;
created_by_model: boolean;
endpoint_count: number;
}
export interface FormData {
@@ -17,3 +23,18 @@ export interface FormData {
provider_id: number;
}[];
}
export interface AccessPointItem {
id: number;
created_at: string;
updated_at: string;
deleted_at: string;
provider_model_name: string;
weight: number;
model_id: number;
provider_id: number;
name: string;
access_id: number;
state: string;
fallback_status_codes: string[];
}
@@ -1,18 +1,12 @@
// columns.ts
import AutoTooltip from '@/components/auto-tooltip';
import DropdownButtons from '@/components/drop-down-buttons';
import IconFont from '@/components/icon-font';
import { SealColumnProps } from '@/components/seal-table/types';
import { tableSorter } from '@/config/settings';
import { useIntl } from '@umijs/max';
import { Tag } from 'antd';
import dayjs from 'dayjs';
import { useMemo } from 'react';
import {
maasProviderLabelMap,
providerIconsMap,
rowActionList
} from '../config';
import { maasProviderLabelMap, rowActionList } from '../config';
import { AccessItem } from '../config/types';
const useAccessColumns = (
@@ -33,11 +27,6 @@ const useAccessColumns = (
<AutoTooltip ghost title={text}>
{text}
</AutoTooltip>
{record.builtIn && (
<Tag color="blue" style={{ marginLeft: 8 }}>
BuiltIn
</Tag>
)}
</>
)
},
@@ -47,10 +36,6 @@ const useAccessColumns = (
span: 5,
render: (value: string) => (
<>
<IconFont
type={providerIconsMap[value]}
style={{ marginRight: 8, fontSize: 16 }}
></IconFont>
<AutoTooltip ghost minWidth={20}>
{maasProviderLabelMap[value]}
</AutoTooltip>
+1 -15
View File
@@ -26,13 +26,11 @@ import {
} from './apis';
import AccessPoints from './components/access-points';
import AddAccessModal from './components/add-access-modal';
import FallbackModal from './components/fallback-modal';
import { maasProviderOptions } from './config';
import { mockDataList } from './config/mock';
import { FormData, AccessItem as ListItem } from './config/types';
import useAccessColumns from './hooks/use-access-columns';
import useCreateAccess from './hooks/use-create-access';
import useFallbackSettings from './hooks/use-fallback-settings';
const Accesses: React.FC = () => {
const {
@@ -62,12 +60,6 @@ const Accesses: React.FC = () => {
const { openAccessModalStatus, openAccessModal, closeAccessModal } =
useCreateAccess();
const {
openFallbackSettingsModalStatus,
openFallbackSettingsModal,
closeFallbackSettingsModal
} = useFallbackSettings();
const handleClickDropdown = () => {
openAccessModal(
PageAction.CREATE,
@@ -147,7 +139,7 @@ const Accesses: React.FC = () => {
const onChildSelect = useMemoizedFn((val: any, record: any) => {
if (val === 'fallback') {
openFallbackSettingsModal(PageAction.EDIT, 'Fallback Settings', record);
console.log('open fallback settings modal', record);
}
});
@@ -247,12 +239,6 @@ const Accesses: React.FC = () => {
onCancel={handleModalCancel}
onOk={handleModalOk}
></AddAccessModal>
<FallbackModal
title={openFallbackSettingsModalStatus.title}
open={openFallbackSettingsModalStatus.open}
onCancel={closeFallbackSettingsModal}
onOk={closeFallbackSettingsModal}
></FallbackModal>
<DeleteModal ref={modalRef}></DeleteModal>
</>
);