侧栏
This commit is contained in:
parent
bf5e5cae87
commit
72fa9876a7
@ -1,23 +1,24 @@
|
|||||||
import { Routes, Route, Outlet, createBrowserRouter, RouterProvider } from "react-router-dom";
|
import { Routes, Route, createBrowserRouter, RouterProvider } from "react-router-dom";
|
||||||
import { ScrollRestoration } from "react-router-dom";
|
import { ScrollRestoration } from "react-router-dom";
|
||||||
import Login from '@/views/Login'
|
import Login from '@/views/Login'
|
||||||
import Register from '@/views/Register'
|
import Register from '@/views/Register'
|
||||||
import User from '@/views/User'
|
import User from '@/views/User'
|
||||||
|
import Layout from '@/views/Layout'
|
||||||
|
|
||||||
const router = createBrowserRouter([
|
const router = createBrowserRouter([
|
||||||
{ path: "*", Component: Root },
|
{ path: "*", Component: Root },
|
||||||
]);
|
])
|
||||||
|
|
||||||
function Root() {
|
function Root() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Layout />}>
|
<Route path="/" element={<Layout />}>
|
||||||
<Route path="/user" element={<User />} />
|
|
||||||
|
|
||||||
</Route>
|
|
||||||
<Route path="/login" element={<Login />} />
|
<Route path="/login" element={<Login />} />
|
||||||
<Route path="/register" element={<Register />} />
|
<Route path="/register" element={<Register />} />
|
||||||
|
<Route path="/profile" element={<User />}>
|
||||||
|
</Route>
|
||||||
|
</Route>
|
||||||
</Routes>
|
</Routes>
|
||||||
<ScrollRestoration />
|
<ScrollRestoration />
|
||||||
</>
|
</>
|
||||||
@ -28,17 +29,9 @@ function Root() {
|
|||||||
export function PageRoute() {
|
export function PageRoute() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<RouterProvider router={router} />;
|
<RouterProvider router={router} />
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function Layout() {
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>我是头部</p>
|
|
||||||
<Outlet />
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
@ -2,6 +2,7 @@ export interface tokenData {
|
|||||||
accessToken: string
|
accessToken: string
|
||||||
selectedProfile: {
|
selectedProfile: {
|
||||||
name: string
|
name: string
|
||||||
|
uuid: string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,7 @@ import CssBaseline from '@mui/material/CssBaseline';
|
|||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById('root')!).render(
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<CssBaseline>
|
<CssBaseline />
|
||||||
<App />
|
<App />
|
||||||
</CssBaseline>
|
|
||||||
</React.StrictMode>
|
</React.StrictMode>
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
import { atomWithStorage } from 'jotai/utils'
|
import { atomWithStorage } from 'jotai/utils'
|
||||||
|
|
||||||
export const token = atomWithStorage("token", "")
|
export const token = atomWithStorage("token", "")
|
||||||
export const username = atomWithStorage("username", "")
|
export const user = atomWithStorage("username", {
|
||||||
|
name: "",
|
||||||
|
uuid: ""
|
||||||
|
})
|
153
frontend/src/views/Layout.tsx
Normal file
153
frontend/src/views/Layout.tsx
Normal file
@ -0,0 +1,153 @@
|
|||||||
|
import * as React from 'react';
|
||||||
|
import { styled, useTheme } from '@mui/material/styles';
|
||||||
|
import Box from '@mui/material/Box';
|
||||||
|
import Drawer from '@mui/material/Drawer';
|
||||||
|
import Toolbar from '@mui/material/Toolbar';
|
||||||
|
import List from '@mui/material/List';
|
||||||
|
import Divider from '@mui/material/Divider';
|
||||||
|
import IconButton from '@mui/material/IconButton';
|
||||||
|
import MenuIcon from '@mui/icons-material/Menu';
|
||||||
|
import ChevronLeftIcon from '@mui/icons-material/ChevronLeft';
|
||||||
|
import ChevronRightIcon from '@mui/icons-material/ChevronRight';
|
||||||
|
import ListItem from '@mui/material/ListItem';
|
||||||
|
import ListItemButton from '@mui/material/ListItemButton';
|
||||||
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
|
import ListItemText from '@mui/material/ListItemText';
|
||||||
|
import InboxIcon from '@mui/icons-material/MoveToInbox';
|
||||||
|
import MailIcon from '@mui/icons-material/Mail';
|
||||||
|
import AppBar from '@mui/material/AppBar';
|
||||||
|
import { Outlet } from 'react-router-dom';
|
||||||
|
import { AccountCircle } from '@mui/icons-material';
|
||||||
|
import Menu from '@mui/material/Menu';
|
||||||
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
|
import { user } from '@/store/store';
|
||||||
|
import { useAtom } from 'jotai';
|
||||||
|
import Button from '@mui/material/Button';
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
|
||||||
|
const drawerWidth = 240;
|
||||||
|
|
||||||
|
const DrawerHeader = styled('div')(({ theme }) => ({
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
padding: theme.spacing(0, 1),
|
||||||
|
// necessary for content to be below app bar
|
||||||
|
...theme.mixins.toolbar,
|
||||||
|
justifyContent: 'flex-end',
|
||||||
|
}));
|
||||||
|
|
||||||
|
|
||||||
|
export default function Layout() {
|
||||||
|
const theme = useTheme();
|
||||||
|
const [open, setOpen] = React.useState(false);
|
||||||
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||||
|
const [nowUser, setNowUser] = useAtom(user)
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleLogOut = () => {
|
||||||
|
setAnchorEl(null);
|
||||||
|
setNowUser({ name: "", uuid: "" })
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
return (<>
|
||||||
|
<Box sx={{ flexGrow: 1 }}>
|
||||||
|
<AppBar position="static">
|
||||||
|
<Toolbar>
|
||||||
|
<IconButton
|
||||||
|
size="large"
|
||||||
|
edge="start"
|
||||||
|
color="inherit"
|
||||||
|
aria-label="menu"
|
||||||
|
sx={{ mr: 2 }}
|
||||||
|
onClick={() => setOpen(true)}
|
||||||
|
>
|
||||||
|
<MenuIcon />
|
||||||
|
</IconButton >
|
||||||
|
<Box sx={{ flexGrow: 1 }}></Box>
|
||||||
|
{nowUser.name != "" && (
|
||||||
|
<div>
|
||||||
|
<IconButton
|
||||||
|
size="large"
|
||||||
|
aria-label="account of current user"
|
||||||
|
aria-controls="menu-appbar"
|
||||||
|
aria-haspopup="true"
|
||||||
|
onClick={event => setAnchorEl(event.currentTarget)}
|
||||||
|
color="inherit"
|
||||||
|
>
|
||||||
|
<AccountCircle />
|
||||||
|
</IconButton>
|
||||||
|
<Menu
|
||||||
|
id="menu-appbar"
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
keepMounted
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'right',
|
||||||
|
}}
|
||||||
|
open={Boolean(anchorEl)}
|
||||||
|
onClose={() => setAnchorEl(null)}
|
||||||
|
>
|
||||||
|
<MenuItem onClick={handleLogOut}>登出</MenuItem>
|
||||||
|
</Menu>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
{nowUser.name == "" && (
|
||||||
|
<Button color="inherit" onClick={()=> navigate("/login")} >登录</Button>
|
||||||
|
)}
|
||||||
|
</Toolbar>
|
||||||
|
</AppBar>
|
||||||
|
</Box>
|
||||||
|
<Drawer
|
||||||
|
sx={{
|
||||||
|
width: drawerWidth,
|
||||||
|
flexShrink: 0,
|
||||||
|
'& .MuiDrawer-paper': {
|
||||||
|
width: drawerWidth,
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
variant="persistent"
|
||||||
|
anchor="left"
|
||||||
|
open={open}
|
||||||
|
>
|
||||||
|
<DrawerHeader>
|
||||||
|
<IconButton onClick={() => setOpen(false)}>
|
||||||
|
{theme.direction === 'ltr' ? <ChevronLeftIcon /> : <ChevronRightIcon />}
|
||||||
|
</IconButton>
|
||||||
|
</DrawerHeader>
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
{['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => (
|
||||||
|
<ListItem key={text} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={text} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
<Divider />
|
||||||
|
<List>
|
||||||
|
{['All mail', 'Trash', 'Spam'].map((text, index) => (
|
||||||
|
<ListItem key={text} disablePadding>
|
||||||
|
<ListItemButton>
|
||||||
|
<ListItemIcon>
|
||||||
|
{index % 2 === 0 ? <InboxIcon /> : <MailIcon />}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={text} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
))}
|
||||||
|
</List>
|
||||||
|
</Drawer>
|
||||||
|
<Outlet />
|
||||||
|
</>)
|
||||||
|
}
|
@ -12,7 +12,7 @@ import Container from '@mui/material/Container';
|
|||||||
import Snackbar from '@mui/material/Snackbar';
|
import Snackbar from '@mui/material/Snackbar';
|
||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import { useSetAtom } from 'jotai';
|
import { useSetAtom } from 'jotai';
|
||||||
import { token, username } from '@/store/store'
|
import { token, user } from '@/store/store'
|
||||||
import { login } from '@/apis/apis'
|
import { login } from '@/apis/apis'
|
||||||
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
import { Link as RouterLink, useNavigate } from "react-router-dom";
|
||||||
import Loading from '@/components/Loading'
|
import Loading from '@/components/Loading'
|
||||||
@ -24,7 +24,7 @@ export default function SignIn() {
|
|||||||
const [err, setErr] = useState("");
|
const [err, setErr] = useState("");
|
||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const setToken = useSetAtom(token)
|
const setToken = useSetAtom(token)
|
||||||
const setUsername = useSetAtom(username)
|
const setUserInfo = useSetAtom(user)
|
||||||
const checkList = React.useRef<Map<string, refType>>(new Map<string, refType>())
|
const checkList = React.useRef<Map<string, refType>>(new Map<string, refType>())
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
@ -46,7 +46,10 @@ export default function SignIn() {
|
|||||||
then(v => {
|
then(v => {
|
||||||
if (!v) return
|
if (!v) return
|
||||||
setToken(v.accessToken)
|
setToken(v.accessToken)
|
||||||
setUsername(v.selectedProfile.name)
|
setUserInfo({
|
||||||
|
uuid: v.selectedProfile.uuid,
|
||||||
|
name: v.selectedProfile.name,
|
||||||
|
})
|
||||||
navigate("/user")
|
navigate("/user")
|
||||||
}).
|
}).
|
||||||
catch(v => [setErr(String(v)), console.warn(v)]).
|
catch(v => [setErr(String(v)), console.warn(v)]).
|
||||||
|
@ -1,28 +1,38 @@
|
|||||||
import { token, username } from "@/store/store"
|
|
||||||
import { useRequest } from "ahooks"
|
|
||||||
import { useAtomValue } from "jotai"
|
|
||||||
import { userInfo } from '@/apis/apis'
|
|
||||||
|
|
||||||
export default function User(){
|
export default function User(){
|
||||||
const nowToken = useAtomValue(token)
|
return (<>
|
||||||
const nowUsername = useAtomValue(username)
|
</>)
|
||||||
|
|
||||||
const { data, error } = useRequest(() => userInfo(nowToken), {
|
|
||||||
refreshDeps: [nowToken],
|
|
||||||
cacheKey: "/api/v1/user/reg",
|
|
||||||
cacheTime: 10000
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<p>你好: {nowUsername}</p>
|
|
||||||
<p>token: {nowToken} </p>
|
|
||||||
{error && String(error)}
|
|
||||||
{!error && <>
|
|
||||||
<p>uid: {data?.data.uid}</p>
|
|
||||||
<p>uuid: {data?.data.uuid}</p>
|
|
||||||
</>}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// import { token, username } from "@/store/store"
|
||||||
|
// import { useRequest } from "ahooks"
|
||||||
|
// import { useAtomValue } from "jotai"
|
||||||
|
// import { userInfo } from '@/apis/apis'
|
||||||
|
|
||||||
|
|
||||||
|
// export default function User() {
|
||||||
|
// const nowToken = useAtomValue(token)
|
||||||
|
// const nowUsername = useAtomValue(username)
|
||||||
|
|
||||||
|
// const { data, error } = useRequest(() => userInfo(nowToken), {
|
||||||
|
// refreshDeps: [nowToken],
|
||||||
|
// cacheKey: "/api/v1/user/reg",
|
||||||
|
// cacheTime: 10000
|
||||||
|
// })
|
||||||
|
|
||||||
|
|
||||||
|
// return (
|
||||||
|
// <>
|
||||||
|
// <p>你好: {nowUsername}</p>
|
||||||
|
// <p>token: {nowToken} </p>
|
||||||
|
// {error && String(error)}
|
||||||
|
// {!error && <>
|
||||||
|
// <p>uid: {data?.data.uid}</p>
|
||||||
|
// <p>uuid: {data?.data.uuid}</p>
|
||||||
|
// </>}
|
||||||
|
// </>
|
||||||
|
// )
|
||||||
|
// }
|
0
frontend/src/views/profile/Profile.tsx
Normal file
0
frontend/src/views/profile/Profile.tsx
Normal file
Loading…
x
Reference in New Issue
Block a user