Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
  • Loading branch information
arvinxx committed Dec 24, 2024
1 parent 07016fb commit cb93429
Show file tree
Hide file tree
Showing 12 changed files with 217 additions and 84 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ProviderCombine } from '@lobehub/icons';
import { Switch, Typography } from 'antd';
import { createStyles } from 'antd-style';
import Link from 'next/link';
import { memo } from 'react';
import { memo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

Expand All @@ -17,8 +17,6 @@ const useStyles = createStyles(({ css, token, isDarkMode }) => ({
opacity: ${isDarkMode ? 0.9 : 0.4};
`,
container: css`
cursor: pointer;
position: relative;
overflow: hidden;
Expand Down Expand Up @@ -69,39 +67,39 @@ export interface ProviderCardProps extends ModelProviderCard {
}

const ProviderCard = memo<ProviderCardProps>(({ id, description, name }) => {
const { t } = useTranslation(['discover', 'providers']);
const { t } = useTranslation('providers');
const { cx, styles, theme } = useStyles();

const [toggleProviderEnabled] = useUserStore((s) => [s.toggleProviderEnabled]);
const enabled = useUserStore(modelProviderSelectors.isProviderEnabled(id as any));
const [checked, setChecked] = useState(enabled);

return (
<Flexbox className={cx(styles.container)} gap={24}>
<Link href={`/settings/provider/${id}`}>
<Flexbox gap={12} padding={16} width={'100%'}>
<Flexbox
align={'center'}
horizontal
justify={'space-between'}
onClick={(e) => {
// e.stopPropagation();
e.preventDefault();
}}
>
<Flexbox gap={12} padding={16} width={'100%'}>
<Flexbox align={'center'} horizontal justify={'space-between'}>
<Link href={`/settings/provider/${id}`}>
<ProviderCombine
provider={id}
size={24}
style={{ color: theme.colorText }}
title={name}
/>
<Switch checked={enabled} size={'small'} />
</Flexbox>
{description && (
<Paragraph className={styles.desc} ellipsis={{ rows: 1, tooltip: true }}>
{t(`${id}.description`, { ns: 'providers' })}
</Paragraph>
)}
</Link>
<Switch
checked={checked}
onChange={(checked) => {
setChecked(checked);
toggleProviderEnabled(id as any, checked);
}}
size={'small'}
/>
</Flexbox>
</Link>
{description && (
<Paragraph className={styles.desc} ellipsis={{ rows: 1, tooltip: true }}>
{t(`${id}.description`)}
</Paragraph>
)}
</Flexbox>
</Flexbox>
);
});
Expand Down
67 changes: 67 additions & 0 deletions src/app/(main)/settings/provider/(list)/ProviderGrid/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
'use client';

import { Typography } from 'antd';
import { createStyles } from 'antd-style';
import isEqual from 'fast-deep-equal';
import { memo } from 'react';
import { Center, Flexbox } from 'react-layout-kit';

import { useUserStore } from '@/store/user';
import { modelProviderSelectors } from '@/store/user/selectors';

import Card from './Card';

const useStyles = createStyles(({ css, responsive, token }) => ({
container: css`
display: grid;
grid-gap: 12px;
grid-template-columns: repeat(2, 1fr);
width: 100%;
${responsive.mobile} {
display: flex;
flex-direction: column;
}
`,
count: css`
border-radius: 12px;
background: ${token.colorFillSecondary};
color: ${token.colorTextDescription};
height: 20px;
width: 20px;
`,
}));

const List = memo(() => {
const { styles, theme } = useStyles();
const enabledList = useUserStore(modelProviderSelectors.enabledModelProviderList, isEqual);
const disabledList = useUserStore(modelProviderSelectors.disabledModelProviderList, isEqual);

return (
<Flexbox gap={24} padding={'16px 0'}>
<Flexbox gap={8}>
<Flexbox align={'center'} gap={4} horizontal>
<Typography.Text style={{ fontSize: 16, fontWeight: 'bold' }}>
已开启服务商
</Typography.Text>
<Center className={styles.count}>{enabledList.length}</Center>
</Flexbox>
<div className={styles.container}>
{enabledList.map((item) => (
<Card {...item} key={item.id} />
))}
</div>
</Flexbox>
<Flexbox gap={8}>
<Typography.Text style={{ fontSize: 16, fontWeight: 'bold' }}>待开启服务商</Typography.Text>
<div className={styles.container}>
{disabledList.map((item) => (
<Card {...item} key={item.id} />
))}
</div>
</Flexbox>
</Flexbox>
);
});

export default List;
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import { Flexbox } from 'react-layout-kit';

import { isCustomBranding } from '@/const/version';

import Footer from './Footer';
import ProviderGrid from './ProviderGrid';
import Footer from './features/Footer';

const Page = () => {
return (
<Flexbox gap={24} style={{ overflow: 'scroll' }} width={'100%'}>
<Flexbox
gap={24}
paddingInline={16}
style={{ overflow: 'scroll', paddingBottom: 24 }}
width={'100%'}
>
<ProviderGrid />
{!isCustomBranding && <Footer />}
</Flexbox>
);
};

Page.displayName = 'ProviderSettings';
Page.displayName = 'ProviderGrid';

export default Page;
36 changes: 0 additions & 36 deletions src/app/(main)/settings/provider/ProviderGrid/index.tsx

This file was deleted.

12 changes: 11 additions & 1 deletion src/app/(main)/settings/provider/ProviderMenu/All.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { Icon } from '@lobehub/ui';
import { WalletCards } from 'lucide-react';
import Link from 'next/link';
import { usePathname } from 'next/navigation';
import { memo } from 'react';
import { useTranslation } from 'react-i18next';
import { Center, Flexbox } from 'react-layout-kit';

import { useStyles } from './Item';

const ALL_PATH = '/settings/provider';

const All = memo(() => {
const { t } = useTranslation('modelProvider');
const { styles, cx } = useStyles();
const pathname = usePathname();

return (
<Link className={cx(styles.container, pathname === ALL_PATH && styles.active)} href={ALL_PATH}>
全部
<Flexbox gap={8} horizontal>
<Center width={24}>
<Icon icon={WalletCards} size={{ fontSize: 18 }} />
</Center>
{t('menu.all')}
</Flexbox>
</Link>
);
});
Expand Down
67 changes: 54 additions & 13 deletions src/app/(main)/settings/provider/ProviderMenu/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
'use client';

import { SearchBar } from '@lobehub/ui';
import { Icon, SearchBar } from '@lobehub/ui';
import { Button, Dropdown } from 'antd';
import { useTheme } from 'antd-style';
import { ArrowDownAZ, ArrowUpDown, GripVertical, PlusIcon } from 'lucide-react';
import { useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { Flexbox } from 'react-layout-kit';

import { DEFAULT_MODEL_PROVIDER_LIST } from '@/config/modelProviders';
Expand All @@ -10,8 +14,9 @@ import All from './All';
import ProviderItem from './Item';

const ProviderMenu = () => {
const { t } = useTranslation('modelProvider');
const [searchKeyword, setSearchKeyword] = useState('');

const theme = useTheme();
// 使用 useMemo 优化过滤性能
const filteredProviders = useMemo(() => {
const keyword = searchKeyword.toLowerCase().trim();
Expand All @@ -26,16 +31,46 @@ const ProviderMenu = () => {
}, [searchKeyword]);

return (
<Flexbox padding={'16px 12px'} style={{ minWidth: 280, overflow: 'scroll' }} width={280}>
<SearchBar
allowClear
onChange={(e) => setSearchKeyword(e.target.value)}
placeholder="Search providers..."
style={{ marginBottom: 8 }}
type={'block'}
value={searchKeyword}
/>
<Flexbox gap={4}>
<Flexbox style={{ minWidth: 280, overflow: 'scroll' }} width={280}>
<Flexbox
horizontal
justify={'space-between'}
padding={'16px 12px 12px'}
style={{ background: theme.colorBgLayout, position: 'sticky', top: 0, zIndex: 50 }}
width={'100%'}
>
<SearchBar
allowClear
onChange={(e) => setSearchKeyword(e.target.value)}
placeholder={t('menu.searchProviders')}
type={'block'}
value={searchKeyword}
/>
<Dropdown
menu={{
items: [
{
icon: <Icon icon={ArrowUpDown} />,
key: 'default',
label: t('menu.sort.default'),
},
{
icon: <Icon icon={ArrowDownAZ} />,
key: 'alphabet',
label: t('menu.sort.alphabet'),
},
{
icon: <Icon icon={GripVertical} />,
key: 'custom-order',
label: t('menu.sort.customOrder'),
},
],
}}
>
<Button color={'default'} icon={<Icon icon={ArrowUpDown} />} variant={'filled'} />
</Dropdown>
</Flexbox>
<Flexbox gap={4} padding={'0 12px'}>
{/* 当没有搜索关键词时才显示 All 选项 */}
{!searchKeyword && <All />}
{filteredProviders.map((item) => (
Expand All @@ -44,10 +79,16 @@ const ProviderMenu = () => {
{/* 当搜索无结果时显示提示信息 */}
{searchKeyword && filteredProviders.length === 0 && (
<Flexbox align="center" justify="center" padding={16}>
No providers found
{t('menu.notFound')}
</Flexbox>
)}
</Flexbox>
<Flexbox
padding={'12px 12px'}
style={{ background: theme.colorBgLayout, bottom: 0, position: 'sticky', zIndex: 50 }}
>
<Button icon={<Icon icon={PlusIcon} />}>自定义服务商</Button>
</Flexbox>
</Flexbox>
);
};
Expand Down
12 changes: 8 additions & 4 deletions src/app/(main)/settings/provider/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { notFound } from 'next/navigation';
import { PropsWithChildren } from 'react';
import { Flexbox } from 'react-layout-kit';

import NProgress from '@/components/NProgress';
import { serverFeatureFlags } from '@/config/featureFlags';

import ProviderMenu from './ProviderMenu';
Expand All @@ -11,10 +12,13 @@ const Layout = ({ children }: PropsWithChildren) => {
if (!showLLM) return notFound();

return (
<Flexbox horizontal width={'100%'}>
<ProviderMenu />
{children}
</Flexbox>
<>
<NProgress />
<Flexbox horizontal width={'100%'}>
<ProviderMenu />
{children}
</Flexbox>
</>
);
};
export default Layout;
2 changes: 1 addition & 1 deletion src/app/(main)/settings/provider/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { metadataModule } from '@/server/metadata';
import { translation } from '@/server/translation';

import Page from './index';
import Page from './(list)';

export const generateMetadata = async () => {
const { t } = await translation('setting');
Expand Down
2 changes: 1 addition & 1 deletion src/app/@modal/(.)settings/modal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const SystemAgent = dynamic(() => import('@/app/(main)/settings/system-agent'),
ssr: false,
});
const About = dynamic(() => import('@/app/(main)/settings/about'), { loading, ssr: false });
const LLM = dynamic(() => import('@/app/(main)/settings/provider'), { loading, ssr: false });
const LLM = dynamic(() => import('@/app/(main)/settings/provider/(list)'), { loading, ssr: false });
const TTS = dynamic(() => import('@/app/(main)/settings/tts'), { loading, ssr: false });
const Agent = dynamic(() => import('@/app/(main)/settings/agent'), { loading, ssr: false });
const Sync = dynamic(() => import('@/app/(main)/settings/sync'), { loading, ssr: false });
Expand Down
Loading

0 comments on commit cb93429

Please sign in to comment.