diff --git a/next.config.mjs b/next.config.mjs
index a9fd4d4d..0aaa214b 100644
--- a/next.config.mjs
+++ b/next.config.mjs
@@ -20,8 +20,7 @@ const nextConfig = {
compress: isProd,
pageExtensions: ['tsx', 'ts'],
experimental: {
- optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki'],
- webVitalsAttribution: ['CLS', 'LCP'],
+ optimizePackageImports: ['@lobehub/ui', '@lobehub/icons', 'chroma-js', 'shiki', '@icons-pack/react-simple-icons','gpt-tokenizer'],
},
reactStrictMode: true,
webpack(config) {
diff --git a/package.json b/package.json
index a1afa583..6c13f191 100644
--- a/package.json
+++ b/package.json
@@ -65,6 +65,7 @@
"@dnd-kit/core": "^6.1.0",
"@dnd-kit/utilities": "^3.2.2",
"@gltf-transform/core": "^3.10.1",
+ "@icons-pack/react-simple-icons": "^9.5.0",
"@lobehub/tts": "^1.24.1",
"@lobehub/ui": "^1.138.17",
"@pixiv/three-vrm": "^2.1.1",
diff --git a/src/app/chat/Apps.tsx b/src/app/chat/Apps.tsx
index 4b6f064c..dfee8570 100644
--- a/src/app/chat/Apps.tsx
+++ b/src/app/chat/Apps.tsx
@@ -1,5 +1,5 @@
import { DancePanel, MarketPanel } from '@/panels';
-import { useConfigStore } from '@/store/config';
+import { useGlobalStore } from '@/store/global';
import { PanelKey } from '@/types/config';
export const apps = [
@@ -16,7 +16,7 @@ export const apps = [
];
export default () => {
- const [panel] = useConfigStore((s) => [s.panel]);
+ const [panel] = useGlobalStore((s) => [s.panel]);
return (
<>
diff --git a/src/app/error.tsx b/src/app/error.tsx
new file mode 100644
index 00000000..07149103
--- /dev/null
+++ b/src/app/error.tsx
@@ -0,0 +1,5 @@
+'use client';
+
+import dynamic from 'next/dynamic';
+
+export default dynamic(() => import('@/components/Error'));
diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx
new file mode 100644
index 00000000..5f6fc47d
--- /dev/null
+++ b/src/app/global-error.tsx
@@ -0,0 +1,22 @@
+'use client';
+
+import Error from 'next/error';
+import { useEffect } from 'react';
+
+export default function GlobalError({
+ error,
+}: {
+ error: Error & { digest?: string };
+ reset: () => void;
+}) {
+ useEffect(() => {
+ console.log('error', error);
+ }, [error]);
+ return (
+
+
+
+
+
+ );
+}
diff --git a/src/app/layout.tsx b/src/app/layout.tsx
index 44eea653..8cd5742d 100644
--- a/src/app/layout.tsx
+++ b/src/app/layout.tsx
@@ -1,22 +1,18 @@
import { Analytics } from '@vercel/analytics/react';
-import { cookies } from 'next/headers';
import { PropsWithChildren } from 'react';
-import { VIDOL_THEME_APPEARANCE } from '@/constants/theme';
import Layout from '@/layout';
import StyleRegistry from './StyleRegistry';
const RootLayout = ({ children }: PropsWithChildren) => {
// get default theme config to use with ssr
- const cookieStore = cookies();
- const appearance = cookieStore.get(VIDOL_THEME_APPEARANCE);
return (
- {children}
+ {children}
diff --git a/src/app/role/style.ts b/src/app/role/style.ts
index 2d780607..b9c25802 100644
--- a/src/app/role/style.ts
+++ b/src/app/role/style.ts
@@ -4,7 +4,7 @@ export const useStyles = createStyles(({ css }) => ({
preview: css`
overflow: auto;
width: 80rem;
- margin: 32px auto;
+ margin: 0 auto;
`,
edit: css`
padding: 0 24px;
diff --git a/src/components/Avatar.tsx b/src/components/Avatar.tsx
new file mode 100644
index 00000000..a730528f
--- /dev/null
+++ b/src/components/Avatar.tsx
@@ -0,0 +1,43 @@
+import { createStyles } from 'antd-style';
+import NextImage from 'next/image';
+
+import { AVATAR_IMAGE_SIZE, DEFAULT_USER_AVATAR_URL } from '@/constants/common';
+
+const useStyle = createStyles(
+ ({ css, token }) => css`
+ cursor: pointer;
+ overflow: hidden;
+ border-radius: 50%;
+ transition:
+ scale 400ms ${token.motionEaseOut},
+ box-shadow 100ms ${token.motionEaseOut};
+
+ &:hover {
+ box-shadow: 0 0 0 3px ${token.colorText};
+ }
+
+ &:active {
+ scale: 0.8;
+ }
+ `,
+);
+
+interface Props {
+ avatar?: string;
+ size?: number;
+}
+
+export default (props: Props) => {
+ const { size = AVATAR_IMAGE_SIZE, avatar } = props;
+ const { styles } = useStyle();
+ return (
+
+ );
+};
diff --git a/src/components/Error/index.tsx b/src/components/Error/index.tsx
new file mode 100644
index 00000000..44a72044
--- /dev/null
+++ b/src/components/Error/index.tsx
@@ -0,0 +1,61 @@
+'use client';
+
+import { FluentEmoji } from '@lobehub/ui';
+import { Button } from 'antd';
+import Link from 'next/link';
+import { memo, useEffect } from 'react';
+import { Flexbox } from 'react-layout-kit';
+
+import { MAX_WIDTH } from '@/constants/common';
+import ResetConfig from '@/features/Actions/ClearSession';
+import ClearChat from '@/features/Actions/ResetConfig';
+
+interface ErrorCaptureProps {
+ error: Error & { digest?: string };
+ reset: () => void;
+}
+
+const ErrorCapture = memo(({ reset, error }) => {
+ useEffect(() => {
+ // Log the error to an error reporting service
+ console.error(error);
+ }, [error]);
+
+ return (
+
+
+ ERROR
+
+
+
+ 页面遇到一点问题...
+
+
+ 项目当前正在施工中,不保证数据稳定性,如果遇到问题可以尝试
+
+ 或
+ ,造成地不便敬请谅解
+
+
+
+
+
+
+
+
+ );
+});
+
+ErrorCapture.displayName = 'ErrorCapture';
+
+export default ErrorCapture;
diff --git a/src/components/Menu/index.tsx b/src/components/Menu/index.tsx
new file mode 100644
index 00000000..4a3d89da
--- /dev/null
+++ b/src/components/Menu/index.tsx
@@ -0,0 +1,97 @@
+import { Menu as AntdMenu, MenuProps as AntdMenuProps, ConfigProvider } from 'antd';
+import { createStyles } from 'antd-style';
+import { memo } from 'react';
+
+const useStyles = createStyles(({ css, token, prefixCls }) => ({
+ compact: css`
+ display: flex;
+ flex-direction: column;
+ gap: 0.125rem;
+ `,
+ menu: css`
+ flex: 1;
+ background: transparent;
+ border: none !important;
+
+ .${prefixCls}-menu-item-divider {
+ margin-block: 0.125rem;
+ border-color: ${token.colorFillTertiary};
+
+ &:first-child {
+ margin-top: 0;
+ }
+
+ &:last-child {
+ margin-bottom: 0;
+ }
+ }
+
+ .${prefixCls}-menu-item, .${prefixCls}-menu-submenu-title {
+ display: flex;
+ gap: 0.75rem;
+ align-items: center;
+
+ height: unset;
+ min-height: 2rem;
+ padding: 0.375rem 0.75rem;
+
+ line-height: 2;
+
+ .anticon + .${prefixCls}-menu-title-content {
+ margin-inline-start: 0;
+ }
+ }
+
+ .${prefixCls}-menu-item-selected {
+ .${prefixCls}-menu-item-icon svg {
+ color: ${token.colorText};
+ }
+ }
+
+ .${prefixCls}-menu-item-icon svg {
+ color: ${token.colorTextSecondary};
+ }
+
+ .${prefixCls}-menu-title-content {
+ flex: 1;
+ }
+ `,
+}));
+
+export interface MenuProps extends AntdMenuProps {
+ variant?: 'default' | 'compact';
+}
+
+const Menu = memo(({ className, selectable = false, variant, ...rest }) => {
+ const isCompact = variant === 'compact';
+ const { cx, styles, theme } = useStyles();
+ return (
+
+
+
+ );
+});
+
+export default Menu;
diff --git a/src/components/PageLoading/index.tsx b/src/components/PageLoading/index.tsx
index 0873482d..2c0a42b3 100644
--- a/src/components/PageLoading/index.tsx
+++ b/src/components/PageLoading/index.tsx
@@ -5,12 +5,13 @@ import { Center, Flexbox } from 'react-layout-kit';
interface PageLoadingProps {
className?: string;
+ description?: string;
style?: React.CSSProperties;
title: string;
}
const PageLoading = (props: PageLoadingProps) => {
- const { title, className, style } = props;
+ const { title, className, style, description } = props;
return (
@@ -19,6 +20,7 @@ const PageLoading = (props: PageLoadingProps) => {
{title}
+ {description && {description}}
);
diff --git a/src/constants/common.ts b/src/constants/common.ts
index 511e59e8..81047fb4 100644
--- a/src/constants/common.ts
+++ b/src/constants/common.ts
@@ -9,6 +9,8 @@ export const LOADING_FLAG = '...';
export const DEFAULT_USER_AVATAR = '😀';
export const MAX_NAME_LENGTH = 20;
+
+export const MAX_WIDTH = 1024;
export const MAX_DESCRIPTION_LENGTH = 100;
export const MAX_GREETING_LENGTH = 200;
export const MAX_README_LENGTH = 800;
diff --git a/src/constants/settings.ts b/src/constants/settings.ts
deleted file mode 100644
index e218ec52..00000000
--- a/src/constants/settings.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { DEFAULT_USER_AVATAR } from '@/constants/common';
-import { DEFAULT_PRIMARY_COLOR } from '@/constants/theme';
-import { Config } from '@/types/config';
-
-export const DEFAULT_SETTINGS: Config = {
- backgroundEffect: 'glow',
- languageModel: {
- openAI: {
- apikey: '',
- endpoint: '',
- model: 'gpt-3.5-turbo',
- },
- },
- primaryColor: DEFAULT_PRIMARY_COLOR,
- avatar: DEFAULT_USER_AVATAR,
- nickName: '',
-};
diff --git a/src/features/Actions/ClearSession.tsx b/src/features/Actions/ClearSession.tsx
new file mode 100644
index 00000000..213715dd
--- /dev/null
+++ b/src/features/Actions/ClearSession.tsx
@@ -0,0 +1,41 @@
+import { App, Button } from 'antd';
+import { ButtonType } from 'antd/es/button';
+import React from 'react';
+
+import { useAgentStore } from '@/store/agent';
+import { useSessionStore } from '@/store/session';
+
+interface Props {
+ text?: string;
+ type?: ButtonType;
+}
+export default (props: Props) => {
+ const { text = '立即清除', type = 'primary' } = props;
+ const clearAgentStorage = useAgentStore((s) => s.clearAgentStorage);
+ const clearSessions = useSessionStore((s) => s.clearSessions);
+ const { message, modal } = App.useApp();
+
+ const handleClear = () => {
+ modal.confirm({
+ cancelText: '取消',
+ centered: true,
+ content: '操作无法撤销,清除后数据将无法恢复,请慎重操作',
+ okButtonProps: {
+ danger: true,
+ },
+ okText: '确定',
+ onOk: () => {
+ clearSessions();
+ clearAgentStorage();
+ message.success('清除成功');
+ },
+ title: '确认清除所有会话消息?',
+ });
+ };
+
+ return (
+
+ );
+};
diff --git a/src/features/Actions/Dance.tsx b/src/features/Actions/Dance.tsx
index e153baae..9691a1d0 100644
--- a/src/features/Actions/Dance.tsx
+++ b/src/features/Actions/Dance.tsx
@@ -1,10 +1,10 @@
import { ActionIcon } from '@lobehub/ui';
import { Music2 } from 'lucide-react';
-import { useConfigStore } from '@/store/config';
+import { useGlobalStore } from '@/store/global';
export default () => {
- const [openPanel] = useConfigStore((s) => [s.openPanel]);
+ const [openPanel] = useGlobalStore((s) => [s.openPanel]);
return (
{
+ return {
+ icon: css`
+ svg {
+ fill: ${token.colorTextDescription};
+ }
+
+ &:hover {
+ svg {
+ fill: ${token.colorText};
+ }
+ }
+ `,
+ };
+});
+
+export default () => {
+ const { styles } = useStyles();
+ const theme = useTheme();
+ return (
+ window.open('https://discord.gg/AYFPHvv2jT', '_blank')}
+ style={{ border: `1px solid ${theme.colorFillSecondary}` }}
+ />
+ );
+};
diff --git a/src/features/Actions/Github.tsx b/src/features/Actions/Github.tsx
new file mode 100644
index 00000000..996847d5
--- /dev/null
+++ b/src/features/Actions/Github.tsx
@@ -0,0 +1,35 @@
+import { SiGithub } from '@icons-pack/react-simple-icons';
+import { ActionIcon } from '@lobehub/ui';
+import { createStyles, useTheme } from 'antd-style';
+
+const useStyles = createStyles(({ css, token }) => {
+ return {
+ icon: css`
+ svg {
+ fill: ${token.colorTextDescription};
+ }
+
+ &:hover {
+ svg {
+ fill: ${token.colorText};
+ }
+ }
+ `,
+ };
+});
+
+export default () => {
+ const theme = useTheme();
+
+ const { styles } = useStyles();
+ return (
+ window.open('https://github.com/lobehub/lobe-vidol', '_blank')}
+ style={{ border: `1px solid ${theme.colorFillSecondary}` }}
+ />
+ );
+};
diff --git a/src/features/Actions/Market.tsx b/src/features/Actions/Market.tsx
index f795708e..40e3f59b 100644
--- a/src/features/Actions/Market.tsx
+++ b/src/features/Actions/Market.tsx
@@ -2,10 +2,10 @@ import { ActionIcon } from '@lobehub/ui';
import { PlusCircle } from 'lucide-react';
import { DESKTOP_HEADER_ICON_SIZE } from '@/constants/token';
-import { useConfigStore } from '@/store/config';
+import { useGlobalStore } from '@/store/global';
export default () => {
- const openPanel = useConfigStore((s) => s.openPanel);
+ const openPanel = useGlobalStore((s) => s.openPanel);
return (
{
+ const { text = '立即重置', type = 'primary' } = props;
+ const resetConfig = useSettingStore((s) => s.resetConfig);
+ const { message, modal } = App.useApp();
+
+ const handleReset = () => {
+ modal.confirm({
+ cancelText: '取消',
+ centered: true,
+ content: '操作无法撤销,重置后数据将无法恢复,请慎重操作',
+ okButtonProps: {
+ danger: true,
+ },
+ okText: '确定',
+ onOk: () => {
+ resetConfig();
+ message.success('重置成功');
+ },
+ title: '确认重置所有系统设置?',
+ });
+ };
+
+ return (
+
+ );
+};
diff --git a/src/features/Actions/ThemeMode/index.tsx b/src/features/Actions/ThemeMode/index.tsx
new file mode 100644
index 00000000..6c8925bb
--- /dev/null
+++ b/src/features/Actions/ThemeMode/index.tsx
@@ -0,0 +1,61 @@
+import { ActionIcon, Icon } from '@lobehub/ui';
+import { Popover } from 'antd';
+import { useTheme } from 'antd-style';
+import { Monitor, Moon, Sun } from 'lucide-react';
+import { memo, useMemo } from 'react';
+
+import Menu, { type MenuProps } from '@/components/Menu';
+import { useGlobalStore } from '@/store/global';
+
+const themeIcons = {
+ auto: Monitor,
+ dark: Moon,
+ light: Sun,
+};
+
+const ThemeButton = memo(() => {
+ const theme = useTheme();
+ const [themeMode, switchThemeMode] = useGlobalStore((s) => [s.themeMode, s.setThemeMode]);
+
+ const items: MenuProps['items'] = useMemo(
+ () => [
+ {
+ icon: ,
+ key: 'auto',
+ label: '跟随系统',
+ onClick: () => switchThemeMode('auto'),
+ },
+ {
+ icon: ,
+ key: 'light',
+ label: '亮色模式',
+ onClick: () => switchThemeMode('light'),
+ },
+ {
+ icon: ,
+ key: 'dark',
+ label: '暗黑模式',
+ onClick: () => switchThemeMode('dark'),
+ },
+ ],
+ [],
+ );
+
+ return (
+ }
+ overlayInnerStyle={{
+ padding: 0,
+ }}
+ trigger={['click', 'hover']}
+ >
+
+
+ );
+});
+
+export default ThemeButton;
diff --git a/src/features/Actions/Token.tsx b/src/features/Actions/Token.tsx
index 92c28232..f73b0967 100644
--- a/src/features/Actions/Token.tsx
+++ b/src/features/Actions/Token.tsx
@@ -3,10 +3,10 @@ import { isEqual } from 'lodash-es';
import { OPENAI_MODEL_LIST } from '@/constants/openai';
import { useCalculateToken } from '@/hooks/useCalculateToken';
-import { configSelectors, useConfigStore } from '@/store/config';
+import { configSelectors, useSettingStore } from '@/store/setting';
const Token = () => {
- const config = useConfigStore((s) => configSelectors.currentOpenAIConfig(s), isEqual);
+ const config = useSettingStore((s) => configSelectors.currentOpenAIConfig(s), isEqual);
const usedTokens = useCalculateToken();
return (
diff --git a/src/features/Actions/TokenMini.tsx b/src/features/Actions/TokenMini.tsx
index 1489ccbf..46183b1f 100644
--- a/src/features/Actions/TokenMini.tsx
+++ b/src/features/Actions/TokenMini.tsx
@@ -3,10 +3,10 @@ import { isEqual } from 'lodash-es';
import { OPENAI_MODEL_LIST } from '@/constants/openai';
import { useCalculateToken } from '@/hooks/useCalculateToken';
-import { configSelectors, useConfigStore } from '@/store/config';
+import { configSelectors, useSettingStore } from '@/store/setting';
const TokenMini = () => {
- const config = useConfigStore((s) => configSelectors.currentOpenAIConfig(s), isEqual);
+ const config = useSettingStore((s) => configSelectors.currentOpenAIConfig(s), isEqual);
const usedTokens = useCalculateToken();
const maxValue = OPENAI_MODEL_LIST.find((item) => item.name === config?.model)?.maxToken || 4096;
diff --git a/src/features/Actions/UserAvatar.tsx b/src/features/Actions/UserAvatar.tsx
new file mode 100644
index 00000000..f96b4e93
--- /dev/null
+++ b/src/features/Actions/UserAvatar.tsx
@@ -0,0 +1,15 @@
+import { Space, Typography } from 'antd';
+
+import Avatar from '@/components/Avatar';
+import { useSettingStore } from '@/store/setting';
+
+export default () => {
+ const [avatar, nickName] = useSettingStore((s) => [s.config.avatar, s.config.nickName]);
+
+ return (
+
+
+ {nickName}
+
+ );
+};
diff --git a/src/features/ChatInfo/Operations/index.tsx b/src/features/ChatInfo/Operations/index.tsx
index d7461643..4fec801d 100644
--- a/src/features/ChatInfo/Operations/index.tsx
+++ b/src/features/ChatInfo/Operations/index.tsx
@@ -3,7 +3,7 @@ import { Modal } from 'antd';
import { Eraser, Music } from 'lucide-react';
import React, { memo } from 'react';
-import { useConfigStore } from '@/store/config';
+import { useGlobalStore } from '@/store/global';
import { useSessionStore } from '@/store/session';
import Item from './Item';
@@ -15,7 +15,7 @@ export interface MyListProps {
}
const Operations = memo(({ mobile }) => {
- const [openPanel] = useConfigStore((s) => [s.openPanel]);
+ const [openPanel] = useGlobalStore((s) => [s.openPanel]);
const [clearHistory] = useSessionStore((s) => [s.clearHistory]);
const items = [
diff --git a/src/features/ChatItem/Error/ApiKeyForm.tsx b/src/features/ChatItem/Error/ApiKeyForm.tsx
index 19bf7c2a..a6e1b17f 100644
--- a/src/features/ChatItem/Error/ApiKeyForm.tsx
+++ b/src/features/ChatItem/Error/ApiKeyForm.tsx
@@ -4,8 +4,8 @@ import { Network } from 'lucide-react';
import { memo, useState } from 'react';
import { Center, Flexbox } from 'react-layout-kit';
-import { configSelectors, useConfigStore } from '@/store/config';
import { useSessionStore } from '@/store/session';
+import { configSelectors, useSettingStore } from '@/store/setting';
import { FormAction } from './style';
@@ -16,7 +16,7 @@ interface APIKeyFormProps {
const APIKeyForm = ({ id }: APIKeyFormProps) => {
const [showProxy, setShow] = useState(false);
- const [currentOpenAIConfig, setConfig] = useConfigStore((s) => [
+ const [currentOpenAIConfig, setConfig] = useSettingStore((s) => [
configSelectors.currentOpenAIConfig(s),
s.setOpenAIConfig,
]);
diff --git a/src/features/DebugUI/index.tsx b/src/features/DebugUI/index.tsx
new file mode 100644
index 00000000..6ebe6bf9
--- /dev/null
+++ b/src/features/DebugUI/index.tsx
@@ -0,0 +1,20 @@
+'use client';
+
+import { Icon } from '@lobehub/ui';
+import { FloatButton } from 'antd';
+import { LucideBugPlay } from 'lucide-react';
+import { memo } from 'react';
+
+const DebugUI = memo(() => {
+ return (
+ }
+ onClick={async () => {
+ throw new Error('触发错误');
+ }}
+ tooltip={'触发错误'}
+ />
+ );
+});
+
+export default DebugUI;
diff --git a/src/features/MarketInfo/index.tsx b/src/features/MarketInfo/index.tsx
index 1b9d1d08..fb967267 100644
--- a/src/features/MarketInfo/index.tsx
+++ b/src/features/MarketInfo/index.tsx
@@ -9,7 +9,7 @@ import AgentCard from '@/components/agent/AgentCard';
import SystemRole from '@/components/agent/SystemRole';
import { SIDEBAR_MAX_WIDTH, SIDEBAR_WIDTH } from '@/constants/token';
import { agentSelectors, useAgentStore } from '@/store/agent';
-import { useConfigStore } from '@/store/config';
+import { useGlobalStore } from '@/store/global';
import { marketStoreSelectors, useMarketStore } from '@/store/market';
import { useSessionStore } from '@/store/session';
@@ -37,7 +37,7 @@ const Header = () => {
marketStoreSelectors.currentAgentItem(s),
],
);
- const [closePanel] = useConfigStore((s) => [s.closePanel]);
+ const [closePanel] = useGlobalStore((s) => [s.closePanel]);
const [subscribe, unsubscribe, subscribed] = useAgentStore((s) => [
s.subscribe,
s.unsubscribe,
diff --git a/src/features/Settings/common.tsx b/src/features/Settings/common.tsx
index 482ab053..0db070fb 100644
--- a/src/features/Settings/common.tsx
+++ b/src/features/Settings/common.tsx
@@ -1,19 +1,15 @@
import { Form, FormGroup, FormItem } from '@lobehub/ui';
-import { App, Button, Input, Segmented } from 'antd';
-import { ThemeMode, createStyles } from 'antd-style';
+import { createStyles } from 'antd-style';
import classNames from 'classnames';
-import { isEqual } from 'lodash-es';
import { Monitor, Settings2, User2Icon } from 'lucide-react';
import React from 'react';
-import { MAX_NAME_LENGTH } from '@/constants/common';
+import ResetConfig from '@/features/Actions/ClearSession';
+import ClearChat from '@/features/Actions/ResetConfig';
+import BackgroundEffect from '@/features/Settings/features/BackgroundEffect';
+import NickName from '@/features/Settings/features/NickName';
+import ThemeSwatchesNetural from '@/features/Settings/features/ThemeSwatchesNetural';
import ThemeSwatchesPrimary from '@/features/Settings/features/ThemeSwatchesPrimary';
-import { useSyncSettings } from '@/features/Settings/useSyncSettings';
-import { useAgentStore } from '@/store/agent';
-import { useConfigStore } from '@/store/config';
-import { useSessionStore } from '@/store/session';
-import { useThemeStore } from '@/store/theme';
-import { BackgroundEffect } from '@/types/config';
import AvatarWithUpload from './features/AvatarWithUpload';
@@ -37,124 +33,32 @@ const useStyles = createStyles(({ css }) => ({
const CommonConfig = (props: CommonConfigProps) => {
const { style, className } = props;
const { styles } = useStyles();
- const [config, setConfig] = useConfigStore((s) => [s.config, s.setConfig], isEqual);
- const clearAgentStorage = useAgentStore((s) => s.clearAgentStorage);
- const [themeMode, setThemeMode] = useThemeStore((s) => [s.themeMode, s.setThemeMode]);
- const clearSessions = useSessionStore((s) => s.clearSessions);
- const resetConfig = useConfigStore((s) => s.resetConfig);
- const { message, modal } = App.useApp();
-
- const [form] = Form.useForm();
-
- useSyncSettings(form);
-
- const handleClear = () => {
- modal.confirm({
- cancelText: '取消',
- centered: true,
- content: '操作无法撤销,清除后数据将无法恢复,请慎重操作',
- okButtonProps: {
- danger: true,
- },
- okText: '确定',
- onOk: () => {
- clearSessions();
- clearAgentStorage();
- message.success('清除成功');
- },
- title: '确认清除所有会话消息?',
- });
- };
-
- const handleReset = () => {
- modal.confirm({
- cancelText: '取消',
- centered: true,
- content: '操作无法撤销,重置后数据将无法恢复,请慎重操作',
- okButtonProps: {
- danger: true,
- },
- okText: '确定',
- onOk: () => {
- resetConfig();
- message.success('重置成功');
- },
- title: '确认重置所有系统设置?',
- });
- };
return (