diff --git a/web/src/i18n/locales/en.json b/web/src/i18n/locales/en.json
index 7ed7482..51c4fd1 100644
--- a/web/src/i18n/locales/en.json
+++ b/web/src/i18n/locales/en.json
@@ -27,6 +27,7 @@
"Register failed": "Register failed",
"Please input email!": "Please input email!",
"Profile": "Profile",
+ "Client Authorization": "Client Authorization",
"Account Settings": "Account Settings",
"Language": "Language",
"Chinese": "中文",
diff --git a/web/src/i18n/locales/zh.json b/web/src/i18n/locales/zh.json
index 553fa21..5961144 100644
--- a/web/src/i18n/locales/zh.json
+++ b/web/src/i18n/locales/zh.json
@@ -50,6 +50,7 @@
"Register failed": "注册失败",
"Please input email!": "请输入邮箱!",
"Profile": "个人资料",
+ "Client Authorization": "客户端授权",
"Account Settings": "账户设置",
"Language": "语言",
"Chinese": "中文",
diff --git a/web/src/layout/TopHeader.tsx b/web/src/layout/TopHeader.tsx
index 64f7785..93ca8d1 100644
--- a/web/src/layout/TopHeader.tsx
+++ b/web/src/layout/TopHeader.tsx
@@ -1,6 +1,6 @@
-import { Layout, Button, Dropdown, theme, Flex, Avatar, Typography, Tooltip } from 'antd';
-import { SearchOutlined, MenuUnfoldOutlined, LogoutOutlined, UserOutlined, RobotOutlined, BellOutlined } from '@ant-design/icons';
-import { memo, useState } from 'react';
+import { Layout, Button, Dropdown, theme, Flex, Avatar, Typography, Tooltip, Modal, QRCode } from 'antd';
+import { SearchOutlined, MenuUnfoldOutlined, LogoutOutlined, UserOutlined, RobotOutlined, BellOutlined, QrcodeOutlined } from '@ant-design/icons';
+import { memo, useMemo, useState } from 'react';
import SearchDialog from './SearchDialog.tsx';
import { authApi } from '../api/auth.ts';
import { useNavigate } from 'react-router';
@@ -26,11 +26,16 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
const [searchOpen, setSearchOpen] = useState(false);
const navigate = useNavigate();
const { t } = useI18n();
- const { user } = useAuth();
+ const { user, token: authToken } = useAuth();
const [profileOpen, setProfileOpen] = useState(false);
+ const [clientAuthOpen, setClientAuthOpen] = useState(false);
const [noticesOpen, setNoticesOpen] = useState(false);
const status = useSystemStatus();
const { isMobile } = useResponsive();
+ const clientAuthPayload = useMemo(() => JSON.stringify({
+ base_url: window.location.origin,
+ token: authToken || '',
+ }), [authToken]);
const handleLogout = () => {
authApi.logout();
@@ -38,6 +43,7 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
};
const openProfile = () => setProfileOpen(true);
+ const openClientAuth = () => setClientAuthOpen(true);
return (
, onClick: openProfile },
+ { key: 'client-auth', label: t('Client Authorization'), icon: , onClick: openClientAuth },
{ key: 'logout', label: t('Log Out'), icon: , onClick: handleLogout },
],
}}
@@ -114,6 +121,18 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
setProfileOpen(false)} />
+ setClientAuthOpen(false)}
+ footer={null}
+ width={320}
+ centered
+ >
+
+
+
+
setNoticesOpen(false)} version={status?.version || ''} />