@lobehub/chat 1.76.0 → 1.77.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +50 -0
- package/Dockerfile +3 -2
- package/Dockerfile.database +3 -1
- package/Dockerfile.pglite +3 -1
- package/changelog/v1.json +18 -0
- package/locales/ar/common.json +12 -1
- package/locales/ar/error.json +10 -0
- package/locales/ar/models.json +12 -6
- package/locales/ar/setting.json +28 -0
- package/locales/bg-BG/common.json +12 -1
- package/locales/bg-BG/error.json +10 -0
- package/locales/bg-BG/models.json +12 -6
- package/locales/bg-BG/setting.json +28 -0
- package/locales/de-DE/common.json +12 -1
- package/locales/de-DE/error.json +10 -0
- package/locales/de-DE/models.json +12 -6
- package/locales/de-DE/setting.json +28 -0
- package/locales/en-US/common.json +12 -1
- package/locales/en-US/error.json +10 -0
- package/locales/en-US/models.json +12 -6
- package/locales/en-US/setting.json +28 -0
- package/locales/es-ES/common.json +12 -1
- package/locales/es-ES/error.json +10 -0
- package/locales/es-ES/models.json +12 -6
- package/locales/es-ES/setting.json +28 -0
- package/locales/fa-IR/common.json +12 -1
- package/locales/fa-IR/error.json +10 -0
- package/locales/fa-IR/models.json +12 -6
- package/locales/fa-IR/setting.json +28 -0
- package/locales/fr-FR/common.json +12 -1
- package/locales/fr-FR/error.json +10 -0
- package/locales/fr-FR/models.json +12 -6
- package/locales/fr-FR/setting.json +28 -0
- package/locales/it-IT/common.json +12 -1
- package/locales/it-IT/error.json +10 -0
- package/locales/it-IT/models.json +12 -6
- package/locales/it-IT/setting.json +28 -0
- package/locales/ja-JP/common.json +12 -1
- package/locales/ja-JP/error.json +10 -0
- package/locales/ja-JP/models.json +12 -6
- package/locales/ja-JP/setting.json +28 -0
- package/locales/ko-KR/common.json +12 -1
- package/locales/ko-KR/error.json +10 -0
- package/locales/ko-KR/models.json +12 -6
- package/locales/ko-KR/setting.json +28 -0
- package/locales/nl-NL/common.json +12 -1
- package/locales/nl-NL/error.json +10 -0
- package/locales/nl-NL/models.json +12 -6
- package/locales/nl-NL/setting.json +28 -0
- package/locales/pl-PL/common.json +12 -1
- package/locales/pl-PL/error.json +10 -0
- package/locales/pl-PL/models.json +12 -6
- package/locales/pl-PL/setting.json +28 -0
- package/locales/pt-BR/common.json +12 -1
- package/locales/pt-BR/error.json +10 -0
- package/locales/pt-BR/models.json +12 -6
- package/locales/pt-BR/setting.json +28 -0
- package/locales/ru-RU/common.json +12 -1
- package/locales/ru-RU/error.json +10 -0
- package/locales/ru-RU/models.json +12 -6
- package/locales/ru-RU/setting.json +28 -0
- package/locales/tr-TR/common.json +12 -1
- package/locales/tr-TR/error.json +10 -0
- package/locales/tr-TR/models.json +12 -6
- package/locales/tr-TR/setting.json +28 -0
- package/locales/vi-VN/common.json +12 -1
- package/locales/vi-VN/error.json +10 -0
- package/locales/vi-VN/models.json +12 -6
- package/locales/vi-VN/setting.json +28 -0
- package/locales/zh-CN/common.json +12 -1
- package/locales/zh-CN/error.json +10 -0
- package/locales/zh-CN/models.json +12 -6
- package/locales/zh-CN/setting.json +28 -0
- package/locales/zh-TW/common.json +12 -1
- package/locales/zh-TW/error.json +10 -0
- package/locales/zh-TW/models.json +12 -6
- package/locales/zh-TW/setting.json +28 -0
- package/package.json +1 -1
- package/src/app/[variants]/(main)/(mobile)/me/data/features/Category.tsx +1 -1
- package/src/app/[variants]/(main)/chat/features/Migration/UpgradeButton.tsx +2 -1
- package/src/app/[variants]/(main)/settings/common/features/Common.tsx +0 -44
- package/src/app/[variants]/(main)/settings/hooks/useCategory.tsx +40 -14
- package/src/app/[variants]/(main)/settings/storage/Advanced.tsx +133 -0
- package/src/app/[variants]/(main)/settings/storage/IndexedDBStorage.tsx +55 -0
- package/src/app/[variants]/(main)/settings/storage/page.tsx +17 -0
- package/src/app/[variants]/(main)/settings/tts/features/const.tsx +4 -0
- package/src/components/GroupIcon/index.tsx +25 -0
- package/src/components/IndexCard/index.tsx +143 -0
- package/src/components/ProgressItem/index.tsx +75 -0
- package/src/config/aiModels/openai.ts +10 -0
- package/src/database/repositories/dataExporter/index.test.ts +330 -0
- package/src/database/repositories/dataExporter/index.ts +216 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/agents.json +65 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/agentsToSessions.json +541 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/topic.json +269 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/userSettings.json +18 -0
- package/src/database/repositories/dataImporter/__tests__/fixtures/with-client-id.json +778 -0
- package/src/database/repositories/dataImporter/__tests__/index.test.ts +120 -880
- package/src/database/repositories/dataImporter/deprecated/__tests__/index.test.ts +940 -0
- package/src/database/repositories/dataImporter/deprecated/index.ts +326 -0
- package/src/database/repositories/dataImporter/index.ts +684 -289
- package/src/features/DataImporter/ImportDetail.tsx +203 -0
- package/src/features/DataImporter/SuccessResult.tsx +22 -6
- package/src/features/DataImporter/_deprecated.ts +43 -0
- package/src/features/DataImporter/config.ts +21 -0
- package/src/features/DataImporter/index.tsx +112 -31
- package/src/features/DevPanel/PostgresViewer/DataTable/index.tsx +6 -0
- package/src/features/User/UserPanel/useMenu.tsx +0 -35
- package/src/features/User/__tests__/useMenu.test.tsx +0 -2
- package/src/locales/default/common.ts +11 -0
- package/src/locales/default/error.ts +10 -0
- package/src/locales/default/setting.ts +28 -0
- package/src/server/routers/lambda/exporter.ts +25 -0
- package/src/server/routers/lambda/importer.ts +19 -3
- package/src/server/routers/lambda/index.ts +2 -0
- package/src/services/config.ts +80 -135
- package/src/services/export/_deprecated.ts +155 -0
- package/src/services/export/client.ts +15 -0
- package/src/services/export/index.ts +6 -0
- package/src/services/export/server.ts +9 -0
- package/src/services/export/type.ts +5 -0
- package/src/services/import/_deprecated.ts +42 -1
- package/src/services/import/client.test.ts +1 -1
- package/src/services/import/client.ts +30 -1
- package/src/services/import/server.ts +70 -2
- package/src/services/import/type.ts +10 -0
- package/src/store/global/initialState.ts +1 -0
- package/src/types/export.ts +11 -0
- package/src/types/exportConfig.ts +2 -0
- package/src/types/importer.ts +15 -0
- package/src/types/user/settings/tts.ts +1 -1
- package/src/utils/client/exportFile.ts +21 -0
- package/vitest.config.ts +1 -1
- package/src/utils/config.ts +0 -109
- /package/src/database/repositories/dataImporter/{__tests__ → deprecated/__tests__}/fixtures/messages.json +0 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Form, Icon, type ItemGroup } from '@lobehub/ui';
|
4
|
+
import { App, Button, Dropdown, Space } from 'antd';
|
5
|
+
import isEqual from 'fast-deep-equal';
|
6
|
+
import { ChevronDown, HardDriveDownload, HardDriveUpload } from 'lucide-react';
|
7
|
+
import { useCallback } from 'react';
|
8
|
+
import { useTranslation } from 'react-i18next';
|
9
|
+
|
10
|
+
import { FORM_STYLE } from '@/const/layoutTokens';
|
11
|
+
import DataImporter from '@/features/DataImporter';
|
12
|
+
import { configService } from '@/services/config';
|
13
|
+
import { useChatStore } from '@/store/chat';
|
14
|
+
import { useFileStore } from '@/store/file';
|
15
|
+
import { useSessionStore } from '@/store/session';
|
16
|
+
import { useToolStore } from '@/store/tool';
|
17
|
+
import { useUserStore } from '@/store/user';
|
18
|
+
import { settingsSelectors } from '@/store/user/selectors';
|
19
|
+
|
20
|
+
const AdvancedActions = () => {
|
21
|
+
const { t } = useTranslation('setting');
|
22
|
+
const [form] = Form.useForm();
|
23
|
+
const { message, modal } = App.useApp();
|
24
|
+
const [clearSessions, clearSessionGroups] = useSessionStore((s) => [
|
25
|
+
s.clearSessions,
|
26
|
+
s.clearSessionGroups,
|
27
|
+
]);
|
28
|
+
const [clearTopics, clearAllMessages] = useChatStore((s) => [
|
29
|
+
s.removeAllTopics,
|
30
|
+
s.clearAllMessages,
|
31
|
+
]);
|
32
|
+
const [removeAllFiles] = useFileStore((s) => [s.removeAllFiles]);
|
33
|
+
const removeAllPlugins = useToolStore((s) => s.removeAllPlugins);
|
34
|
+
const settings = useUserStore(settingsSelectors.currentSettings, isEqual);
|
35
|
+
|
36
|
+
const handleClear = useCallback(() => {
|
37
|
+
modal.confirm({
|
38
|
+
centered: true,
|
39
|
+
okButtonProps: {
|
40
|
+
danger: true,
|
41
|
+
},
|
42
|
+
onOk: async () => {
|
43
|
+
await clearSessions();
|
44
|
+
await removeAllPlugins();
|
45
|
+
await clearTopics();
|
46
|
+
await removeAllFiles();
|
47
|
+
await clearAllMessages();
|
48
|
+
await clearSessionGroups();
|
49
|
+
|
50
|
+
message.success(t('danger.clear.success'));
|
51
|
+
},
|
52
|
+
title: t('danger.clear.confirm'),
|
53
|
+
});
|
54
|
+
}, []);
|
55
|
+
|
56
|
+
const system: ItemGroup = {
|
57
|
+
children: [
|
58
|
+
{
|
59
|
+
children: (
|
60
|
+
<DataImporter>
|
61
|
+
<Button icon={<Icon icon={HardDriveDownload} />}>
|
62
|
+
{t('storage.actions.import.button')}
|
63
|
+
</Button>
|
64
|
+
</DataImporter>
|
65
|
+
),
|
66
|
+
label: t('storage.actions.import.title'),
|
67
|
+
minWidth: undefined,
|
68
|
+
},
|
69
|
+
{
|
70
|
+
children: (
|
71
|
+
<Space.Compact>
|
72
|
+
<Button
|
73
|
+
icon={<Icon icon={HardDriveUpload} />}
|
74
|
+
onClick={() => {
|
75
|
+
configService.exportAll();
|
76
|
+
}}
|
77
|
+
>
|
78
|
+
{t('storage.actions.export.button')}
|
79
|
+
</Button>
|
80
|
+
<Dropdown
|
81
|
+
menu={{
|
82
|
+
items: [
|
83
|
+
{
|
84
|
+
key: 'allAgent',
|
85
|
+
label: t('storage.actions.export.exportType.allAgent'),
|
86
|
+
onClick: configService.exportAgents,
|
87
|
+
},
|
88
|
+
{
|
89
|
+
key: 'allAgentWithMessage',
|
90
|
+
label: t('storage.actions.export.exportType.allAgentWithMessage'),
|
91
|
+
onClick: configService.exportSessions,
|
92
|
+
},
|
93
|
+
{
|
94
|
+
key: 'globalSetting',
|
95
|
+
label: t('storage.actions.export.exportType.globalSetting'),
|
96
|
+
onClick: configService.exportSettings,
|
97
|
+
},
|
98
|
+
],
|
99
|
+
}}
|
100
|
+
>
|
101
|
+
<Button icon={<Icon icon={ChevronDown} />} />
|
102
|
+
</Dropdown>
|
103
|
+
</Space.Compact>
|
104
|
+
),
|
105
|
+
label: t('storage.actions.export.title'),
|
106
|
+
minWidth: undefined,
|
107
|
+
},
|
108
|
+
{
|
109
|
+
children: (
|
110
|
+
<Button danger onClick={handleClear} type="primary">
|
111
|
+
{t('danger.clear.action')}
|
112
|
+
</Button>
|
113
|
+
),
|
114
|
+
desc: t('danger.clear.desc'),
|
115
|
+
label: t('danger.clear.title'),
|
116
|
+
minWidth: undefined,
|
117
|
+
},
|
118
|
+
],
|
119
|
+
title: t('storage.actions.title'),
|
120
|
+
};
|
121
|
+
return (
|
122
|
+
<Form
|
123
|
+
form={form}
|
124
|
+
initialValues={settings}
|
125
|
+
items={[system]}
|
126
|
+
itemsType={'group'}
|
127
|
+
variant={'pure'}
|
128
|
+
{...FORM_STYLE}
|
129
|
+
/>
|
130
|
+
);
|
131
|
+
};
|
132
|
+
|
133
|
+
export default AdvancedActions;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { Skeleton } from 'antd';
|
4
|
+
import { DatabaseIcon } from 'lucide-react';
|
5
|
+
import { memo } from 'react';
|
6
|
+
import { useTranslation } from 'react-i18next';
|
7
|
+
import { Flexbox } from 'react-layout-kit';
|
8
|
+
import useSWR from 'swr';
|
9
|
+
|
10
|
+
import GroupIcon from '@/components/GroupIcon';
|
11
|
+
import IndexCard from '@/components/IndexCard';
|
12
|
+
import ProgressItem from '@/components/ProgressItem';
|
13
|
+
import { formatSize } from '@/utils/format';
|
14
|
+
|
15
|
+
const IndexedDBStorage = memo(() => {
|
16
|
+
const { t } = useTranslation('setting');
|
17
|
+
const { data, isLoading } = useSWR('fetch-client-usage', async () => {
|
18
|
+
const estimate = await navigator.storage.estimate();
|
19
|
+
const quota = estimate.quota || 0;
|
20
|
+
const usage = estimate.usage || 0;
|
21
|
+
|
22
|
+
const percent = (usage / quota) * 100;
|
23
|
+
|
24
|
+
return { percent: percent < 1 ? 1 : percent, total: quota, used: usage };
|
25
|
+
});
|
26
|
+
|
27
|
+
return (
|
28
|
+
<IndexCard
|
29
|
+
desc={t('storage.desc', { day: 15 })}
|
30
|
+
icon={<GroupIcon icon={DatabaseIcon} />}
|
31
|
+
padding={0}
|
32
|
+
title={t('storage.title')}
|
33
|
+
>
|
34
|
+
{isLoading ? (
|
35
|
+
<Flexbox padding={16}>
|
36
|
+
<Skeleton active paragraph={{ rows: 1, width: '100%' }} title={false} />
|
37
|
+
<Skeleton.Button active style={{ height: 48, width: '100%' }} />
|
38
|
+
</Flexbox>
|
39
|
+
) : (
|
40
|
+
<Flexbox gap={16} paddingBlock={16}>
|
41
|
+
<ProgressItem
|
42
|
+
percent={data?.percent || 0}
|
43
|
+
title={t('storage.used')}
|
44
|
+
usage={{
|
45
|
+
total: data ? formatSize(data.total) : '-',
|
46
|
+
used: data ? formatSize(data.used) : '-',
|
47
|
+
}}
|
48
|
+
/>
|
49
|
+
</Flexbox>
|
50
|
+
)}
|
51
|
+
</IndexCard>
|
52
|
+
);
|
53
|
+
});
|
54
|
+
|
55
|
+
export default IndexedDBStorage;
|
@@ -0,0 +1,17 @@
|
|
1
|
+
'use client';
|
2
|
+
|
3
|
+
import { isServerMode } from '@/const/version';
|
4
|
+
|
5
|
+
import Advanced from './Advanced';
|
6
|
+
import IndexedDBStorage from './IndexedDBStorage';
|
7
|
+
|
8
|
+
const StorageEstimate = () => {
|
9
|
+
return (
|
10
|
+
<>
|
11
|
+
{!isServerMode && <IndexedDBStorage />}
|
12
|
+
<Advanced />
|
13
|
+
</>
|
14
|
+
);
|
15
|
+
};
|
16
|
+
|
17
|
+
export default StorageEstimate;
|
@@ -4,6 +4,10 @@ import { SelectProps } from 'antd';
|
|
4
4
|
import { LabelRenderer } from '@/components/ModelSelect';
|
5
5
|
|
6
6
|
export const opeanaiTTSOptions: SelectProps['options'] = [
|
7
|
+
{
|
8
|
+
label: <LabelRenderer Icon={OpenAI.Avatar} label={'gpt-4o-mini-tts'} />,
|
9
|
+
value: 'gpt-4o-mini-tts',
|
10
|
+
},
|
7
11
|
{
|
8
12
|
label: <LabelRenderer Icon={OpenAI.Avatar} label={'tts-1'} />,
|
9
13
|
value: 'tts-1',
|
@@ -0,0 +1,25 @@
|
|
1
|
+
import { Icon } from '@lobehub/ui';
|
2
|
+
import { createStyles } from 'antd-style';
|
3
|
+
import { LucideIcon } from 'lucide-react';
|
4
|
+
import { memo } from 'react';
|
5
|
+
import { Center } from 'react-layout-kit';
|
6
|
+
|
7
|
+
const useStyles = createStyles(({ css, token }) => ({
|
8
|
+
icon: css`
|
9
|
+
border: 1px solid ${token.colorBorderSecondary};
|
10
|
+
border-radius: 8px;
|
11
|
+
background: ${token.colorBgElevated};
|
12
|
+
`,
|
13
|
+
}));
|
14
|
+
|
15
|
+
const GroupIcon = memo<{ icon: LucideIcon }>(({ icon }) => {
|
16
|
+
const { styles } = useStyles();
|
17
|
+
|
18
|
+
return (
|
19
|
+
<Center className={styles.icon} flex={'none'} height={40} width={40}>
|
20
|
+
<Icon icon={icon} size={{ fontSize: 24 }} />
|
21
|
+
</Center>
|
22
|
+
);
|
23
|
+
});
|
24
|
+
|
25
|
+
export default GroupIcon;
|
@@ -0,0 +1,143 @@
|
|
1
|
+
import { ActionIcon } from '@lobehub/ui';
|
2
|
+
import { createStyles } from 'antd-style';
|
3
|
+
import { ChevronDown, ChevronRight } from 'lucide-react';
|
4
|
+
import { ReactNode, memo } from 'react';
|
5
|
+
import { Center, Flexbox, FlexboxProps } from 'react-layout-kit';
|
6
|
+
|
7
|
+
const useStyles = createStyles(({ css, token, responsive }) => ({
|
8
|
+
card: css`
|
9
|
+
position: relative;
|
10
|
+
|
11
|
+
overflow: hidden;
|
12
|
+
|
13
|
+
border: 1px solid ${token.colorBorderSecondary};
|
14
|
+
border-radius: ${token.borderRadiusLG}px;
|
15
|
+
|
16
|
+
background: ${token.colorBgContainer};
|
17
|
+
`,
|
18
|
+
desc: css`
|
19
|
+
font-size: 14px;
|
20
|
+
line-height: 1.4;
|
21
|
+
color: ${token.colorTextDescription};
|
22
|
+
${responsive.mobile} {
|
23
|
+
font-size: 12px;
|
24
|
+
}
|
25
|
+
`,
|
26
|
+
expend: css`
|
27
|
+
position: absolute;
|
28
|
+
inset-block-end: -12px;
|
29
|
+
inset-inline-start: 50%;
|
30
|
+
transform: translateX(-50%);
|
31
|
+
|
32
|
+
border: 1px solid ${token.colorBorderSecondary};
|
33
|
+
border-radius: 50%;
|
34
|
+
|
35
|
+
background: ${token.colorBgContainer};
|
36
|
+
`,
|
37
|
+
header: css`
|
38
|
+
border-block-end: 1px solid ${token.colorBorderSecondary};
|
39
|
+
background: ${token.colorFillQuaternary};
|
40
|
+
`,
|
41
|
+
more: css`
|
42
|
+
border: 1px solid ${token.colorBorderSecondary};
|
43
|
+
`,
|
44
|
+
title: css`
|
45
|
+
font-size: 16px;
|
46
|
+
font-weight: bold;
|
47
|
+
line-height: 1.4;
|
48
|
+
${responsive.mobile} {
|
49
|
+
font-size: 14px;
|
50
|
+
}
|
51
|
+
`,
|
52
|
+
}));
|
53
|
+
|
54
|
+
interface IndexCardProps extends Omit<FlexboxProps, 'title'> {
|
55
|
+
desc?: ReactNode;
|
56
|
+
expand?: boolean;
|
57
|
+
extra?: ReactNode;
|
58
|
+
icon?: ReactNode;
|
59
|
+
moreTooltip?: string;
|
60
|
+
onExpand?: () => void;
|
61
|
+
onMoreClick?: () => void;
|
62
|
+
title?: ReactNode;
|
63
|
+
}
|
64
|
+
|
65
|
+
const IndexCard = memo<IndexCardProps>(
|
66
|
+
({
|
67
|
+
expand = true,
|
68
|
+
onExpand,
|
69
|
+
icon,
|
70
|
+
className,
|
71
|
+
onMoreClick,
|
72
|
+
title,
|
73
|
+
extra,
|
74
|
+
moreTooltip,
|
75
|
+
desc,
|
76
|
+
children,
|
77
|
+
...rest
|
78
|
+
}) => {
|
79
|
+
const { styles } = useStyles();
|
80
|
+
return (
|
81
|
+
<Flexbox
|
82
|
+
style={{
|
83
|
+
marginBottom: !expand ? 12 : undefined,
|
84
|
+
position: 'relative',
|
85
|
+
}}
|
86
|
+
>
|
87
|
+
<Flexbox
|
88
|
+
className={styles.card}
|
89
|
+
style={{
|
90
|
+
paddingBottom: !expand ? 12 : undefined,
|
91
|
+
}}
|
92
|
+
>
|
93
|
+
{title && (
|
94
|
+
<Flexbox
|
95
|
+
align={'center'}
|
96
|
+
className={styles.header}
|
97
|
+
gap={16}
|
98
|
+
horizontal
|
99
|
+
justify={'space-between'}
|
100
|
+
padding={16}
|
101
|
+
>
|
102
|
+
<Flexbox align={'center'} gap={12} horizontal>
|
103
|
+
{icon}
|
104
|
+
<Flexbox>
|
105
|
+
<div className={styles.title}>{title}</div>
|
106
|
+
{desc && <div className={styles.desc}>{desc}</div>}
|
107
|
+
</Flexbox>
|
108
|
+
</Flexbox>
|
109
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
110
|
+
{extra}
|
111
|
+
{onMoreClick && (
|
112
|
+
<ActionIcon
|
113
|
+
className={styles.more}
|
114
|
+
icon={ChevronRight}
|
115
|
+
onClick={onMoreClick}
|
116
|
+
size={{ blockSize: 32, borderRadius: '50%', fontSize: 16 }}
|
117
|
+
title={moreTooltip}
|
118
|
+
/>
|
119
|
+
)}
|
120
|
+
</Flexbox>
|
121
|
+
</Flexbox>
|
122
|
+
)}
|
123
|
+
<Flexbox className={className} gap={16} padding={16} width={'100%'} {...rest}>
|
124
|
+
{children}
|
125
|
+
</Flexbox>
|
126
|
+
</Flexbox>
|
127
|
+
{!expand && (
|
128
|
+
<Center className={styles.expend} height={24} width={24}>
|
129
|
+
<ActionIcon
|
130
|
+
icon={ChevronDown}
|
131
|
+
onClick={onExpand}
|
132
|
+
size={{ blockSize: 24, borderRadius: '50%', fontSize: 16 }}
|
133
|
+
/>
|
134
|
+
</Center>
|
135
|
+
)}
|
136
|
+
</Flexbox>
|
137
|
+
);
|
138
|
+
},
|
139
|
+
);
|
140
|
+
|
141
|
+
IndexCard.displayName = 'IndexCard';
|
142
|
+
|
143
|
+
export default IndexCard;
|
@@ -0,0 +1,75 @@
|
|
1
|
+
import { Progress } from 'antd';
|
2
|
+
import { createStyles, useResponsive } from 'antd-style';
|
3
|
+
import { CSSProperties, memo } from 'react';
|
4
|
+
import { Flexbox } from 'react-layout-kit';
|
5
|
+
|
6
|
+
const useStyles = createStyles(({ css, token }) => ({
|
7
|
+
desc: css`
|
8
|
+
height: 20px;
|
9
|
+
font-size: 12px;
|
10
|
+
line-height: 20px;
|
11
|
+
color: ${token.colorTextTertiary};
|
12
|
+
`,
|
13
|
+
title: css`
|
14
|
+
font-size: 15px;
|
15
|
+
font-weight: bold;
|
16
|
+
color: ${token.colorTextSecondary};
|
17
|
+
`,
|
18
|
+
}));
|
19
|
+
|
20
|
+
interface ProgressItemProps {
|
21
|
+
className?: string;
|
22
|
+
desc?: string;
|
23
|
+
legend?: string;
|
24
|
+
padding?: number;
|
25
|
+
percent: number;
|
26
|
+
style?: CSSProperties;
|
27
|
+
title: string;
|
28
|
+
usage: {
|
29
|
+
total: string | number;
|
30
|
+
used: string | number;
|
31
|
+
};
|
32
|
+
}
|
33
|
+
|
34
|
+
const ProgressItem = memo<ProgressItemProps>(
|
35
|
+
({ legend, title, desc, usage, percent, style, className }) => {
|
36
|
+
const { mobile } = useResponsive();
|
37
|
+
const { styles, theme } = useStyles();
|
38
|
+
|
39
|
+
return (
|
40
|
+
<Flexbox className={className} paddingInline={16} style={style} width={'100%'}>
|
41
|
+
<Flexbox align={'center'} horizontal justify={'space-between'} width={'100%'}>
|
42
|
+
<Flexbox align={'center'} gap={8} horizontal>
|
43
|
+
{legend && (
|
44
|
+
<Flexbox
|
45
|
+
height={8}
|
46
|
+
style={{
|
47
|
+
background: theme.geekblue,
|
48
|
+
borderRadius: '50%',
|
49
|
+
flex: 'none',
|
50
|
+
}}
|
51
|
+
width={8}
|
52
|
+
/>
|
53
|
+
)}
|
54
|
+
<Flexbox align={'baseline'} gap={mobile ? 0 : 8} horizontal={!mobile}>
|
55
|
+
<div className={styles.title}>{title}</div>
|
56
|
+
{desc && <div className={styles.desc}>{desc}</div>}
|
57
|
+
</Flexbox>
|
58
|
+
</Flexbox>
|
59
|
+
<div>
|
60
|
+
<span style={{ fontWeight: 'bold' }}>{usage.used}</span>
|
61
|
+
{['', '/', usage.total].join(' ')}
|
62
|
+
</div>
|
63
|
+
</Flexbox>
|
64
|
+
<Progress
|
65
|
+
percent={percent}
|
66
|
+
showInfo={false}
|
67
|
+
size={'small'}
|
68
|
+
strokeColor={theme.colorPrimary}
|
69
|
+
/>
|
70
|
+
</Flexbox>
|
71
|
+
);
|
72
|
+
},
|
73
|
+
);
|
74
|
+
|
75
|
+
export default ProgressItem;
|
@@ -480,6 +480,16 @@ export const openaiTTSModels: AITTSModelCard[] = [
|
|
480
480
|
},
|
481
481
|
type: 'tts',
|
482
482
|
},
|
483
|
+
{
|
484
|
+
description:
|
485
|
+
'GPT-4o mini TTS 是一个基于 GPT-4o mini 构建的文本转语音模型,这是一种快速且强大的语言模型。使用它可以将文本转换为自然听起来的语音文本。最大输入标记数为 2000。',
|
486
|
+
displayName: 'GPT-4o Mini TTS',
|
487
|
+
id: 'gpt-4o-mini-tts',
|
488
|
+
pricing: {
|
489
|
+
input: 10,
|
490
|
+
},
|
491
|
+
type: 'tts',
|
492
|
+
},
|
483
493
|
];
|
484
494
|
|
485
495
|
// 语音识别模型
|