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 || ''} />