mirror of
https://github.com/DrizzleTime/Foxel.git
synced 2026-09-05 15:47:00 +08:00
feat: add client authorization feature in TopHeader and update localization files
This commit is contained in:
@@ -27,6 +27,7 @@
|
|||||||
"Register failed": "Register failed",
|
"Register failed": "Register failed",
|
||||||
"Please input email!": "Please input email!",
|
"Please input email!": "Please input email!",
|
||||||
"Profile": "Profile",
|
"Profile": "Profile",
|
||||||
|
"Client Authorization": "Client Authorization",
|
||||||
"Account Settings": "Account Settings",
|
"Account Settings": "Account Settings",
|
||||||
"Language": "Language",
|
"Language": "Language",
|
||||||
"Chinese": "中文",
|
"Chinese": "中文",
|
||||||
|
|||||||
@@ -50,6 +50,7 @@
|
|||||||
"Register failed": "注册失败",
|
"Register failed": "注册失败",
|
||||||
"Please input email!": "请输入邮箱!",
|
"Please input email!": "请输入邮箱!",
|
||||||
"Profile": "个人资料",
|
"Profile": "个人资料",
|
||||||
|
"Client Authorization": "客户端授权",
|
||||||
"Account Settings": "账户设置",
|
"Account Settings": "账户设置",
|
||||||
"Language": "语言",
|
"Language": "语言",
|
||||||
"Chinese": "中文",
|
"Chinese": "中文",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { Layout, Button, Dropdown, theme, Flex, Avatar, Typography, Tooltip } from 'antd';
|
import { Layout, Button, Dropdown, theme, Flex, Avatar, Typography, Tooltip, Modal, QRCode } from 'antd';
|
||||||
import { SearchOutlined, MenuUnfoldOutlined, LogoutOutlined, UserOutlined, RobotOutlined, BellOutlined } from '@ant-design/icons';
|
import { SearchOutlined, MenuUnfoldOutlined, LogoutOutlined, UserOutlined, RobotOutlined, BellOutlined, QrcodeOutlined } from '@ant-design/icons';
|
||||||
import { memo, useState } from 'react';
|
import { memo, useMemo, useState } from 'react';
|
||||||
import SearchDialog from './SearchDialog.tsx';
|
import SearchDialog from './SearchDialog.tsx';
|
||||||
import { authApi } from '../api/auth.ts';
|
import { authApi } from '../api/auth.ts';
|
||||||
import { useNavigate } from 'react-router';
|
import { useNavigate } from 'react-router';
|
||||||
@@ -26,11 +26,16 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
|
|||||||
const [searchOpen, setSearchOpen] = useState(false);
|
const [searchOpen, setSearchOpen] = useState(false);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const { user } = useAuth();
|
const { user, token: authToken } = useAuth();
|
||||||
const [profileOpen, setProfileOpen] = useState(false);
|
const [profileOpen, setProfileOpen] = useState(false);
|
||||||
|
const [clientAuthOpen, setClientAuthOpen] = useState(false);
|
||||||
const [noticesOpen, setNoticesOpen] = useState(false);
|
const [noticesOpen, setNoticesOpen] = useState(false);
|
||||||
const status = useSystemStatus();
|
const status = useSystemStatus();
|
||||||
const { isMobile } = useResponsive();
|
const { isMobile } = useResponsive();
|
||||||
|
const clientAuthPayload = useMemo(() => JSON.stringify({
|
||||||
|
base_url: window.location.origin,
|
||||||
|
token: authToken || '',
|
||||||
|
}), [authToken]);
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
authApi.logout();
|
authApi.logout();
|
||||||
@@ -38,6 +43,7 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
|
|||||||
};
|
};
|
||||||
|
|
||||||
const openProfile = () => setProfileOpen(true);
|
const openProfile = () => setProfileOpen(true);
|
||||||
|
const openClientAuth = () => setClientAuthOpen(true);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Header
|
<Header
|
||||||
@@ -96,6 +102,7 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
|
|||||||
menu={{
|
menu={{
|
||||||
items: [
|
items: [
|
||||||
{ key: 'profile', label: t('Profile'), icon: <UserOutlined />, onClick: openProfile },
|
{ key: 'profile', label: t('Profile'), icon: <UserOutlined />, onClick: openProfile },
|
||||||
|
{ key: 'client-auth', label: t('Client Authorization'), icon: <QrcodeOutlined />, onClick: openClientAuth },
|
||||||
{ key: 'logout', label: t('Log Out'), icon: <LogoutOutlined />, onClick: handleLogout },
|
{ key: 'logout', label: t('Log Out'), icon: <LogoutOutlined />, onClick: handleLogout },
|
||||||
],
|
],
|
||||||
}}
|
}}
|
||||||
@@ -114,6 +121,18 @@ const TopHeader = memo(function TopHeader({ collapsed, onToggle, onOpenAiAgent,
|
|||||||
</Button>
|
</Button>
|
||||||
</Dropdown>
|
</Dropdown>
|
||||||
<ProfileModal open={profileOpen} onClose={() => setProfileOpen(false)} />
|
<ProfileModal open={profileOpen} onClose={() => setProfileOpen(false)} />
|
||||||
|
<Modal
|
||||||
|
title={t('Client Authorization')}
|
||||||
|
open={clientAuthOpen}
|
||||||
|
onCancel={() => setClientAuthOpen(false)}
|
||||||
|
footer={null}
|
||||||
|
width={320}
|
||||||
|
centered
|
||||||
|
>
|
||||||
|
<Flex justify="center" style={{ padding: '8px 0' }}>
|
||||||
|
<QRCode value={clientAuthPayload} size={220} />
|
||||||
|
</Flex>
|
||||||
|
</Modal>
|
||||||
<NoticesModal open={noticesOpen} onClose={() => setNoticesOpen(false)} version={status?.version || ''} />
|
<NoticesModal open={noticesOpen} onClose={() => setNoticesOpen(false)} version={status?.version || ''} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Header>
|
</Header>
|
||||||
|
|||||||
Reference in New Issue
Block a user