diff --git a/frontend/src/store/store.ts b/frontend/src/store/store.ts index 9162eb1..52c323d 100644 --- a/frontend/src/store/store.ts +++ b/frontend/src/store/store.ts @@ -1,7 +1,10 @@ +import { atom } from 'jotai' import { atomWithStorage } from 'jotai/utils' export const token = atomWithStorage("token", "") export const user = atomWithStorage("username", { name: "", uuid: "" -}) \ No newline at end of file +}) + +export const LayoutAlertErr = atom("") diff --git a/frontend/src/views/Layout.tsx b/frontend/src/views/Layout.tsx index f3a73df..a6bff43 100644 --- a/frontend/src/views/Layout.tsx +++ b/frontend/src/views/Layout.tsx @@ -13,15 +13,13 @@ 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 { token, user } from '@/store/store'; -import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai'; +import { LayoutAlertErr, token, user } from '@/store/store'; +import { useAtom, useAtomValue, useSetAtom } from 'jotai'; import Button from '@mui/material/Button'; import { useNavigate } from "react-router-dom"; import { useRequest, useMemoizedFn } from 'ahooks'; @@ -30,12 +28,13 @@ import Snackbar from '@mui/material/Snackbar'; import Alert from '@mui/material/Alert'; import { memo } from 'react'; import useMediaQuery from '@mui/material/useMediaQuery'; -import useTilg from 'tilg' import { ApiErr } from '@/apis/error'; import Typography from '@mui/material/Typography'; import Container from '@mui/material/Container'; - -export const AlertErr = atom("") +import PersonIcon from '@mui/icons-material/Person'; +import SecurityIcon from '@mui/icons-material/Security'; +import SettingsIcon from '@mui/icons-material/Settings'; +import useTilg from 'tilg' const drawerWidth = 240; @@ -48,16 +47,21 @@ const DrawerHeader = styled('div')(({ theme }) => ({ justifyContent: 'flex-end', })); +interface ListItem { + icon: JSX.Element + title: string + link: string +} -export default function Layout() { + +const Layout = memo(function Layout() { const theme = useTheme(); const isLg = useMediaQuery(theme.breakpoints.up('lg')) const [open, setOpen] = React.useState(false); const nowToken = useAtomValue(token) - const [err, setErr] = useAtom(AlertErr) + const [err, setErr] = useAtom(LayoutAlertErr) const navigate = useNavigate(); - const userinfo = useRequest(() => userInfo(nowToken), { refreshDeps: [nowToken], cacheKey: "/api/v1/user", @@ -71,7 +75,32 @@ export default function Layout() { } }) - useTilg(isLg, open) + const userDrawerList = React.useMemo(() => [ + { + icon: , + title: '个人信息', + link: '/profile' + }, + { + icon: , + title: '皮肤设置', + link: '/textures' + }, + { + icon: , + title: '安全设置', + link: '/setting' + } + ] as ListItem[], []) + + const adminDrawerList = React.useMemo(() => [ + { + icon: , + title: 'test' + } + ] as ListItem[], []) + + useTilg() return (<> @@ -103,33 +132,11 @@ export default function Layout() { - - {['Inbox', 'Starred', 'Send email', 'Drafts'].map((text, index) => ( - - - - {index % 2 === 0 ? : } - - - - - ))} - + {userinfo.data?.is_admin && ( <> - - {['All mail', 'Trash', 'Spam'].map((text, index) => ( - - - - {index % 2 === 0 ? : } - - - - - ))} - + )} )} @@ -149,14 +156,14 @@ export default function Layout() { ) -} +}) -const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => { +const MyToolbar = memo(function MyToolbar(p: { setOpen: (v: boolean) => void }) { const [nowUser, setNowUser] = useAtom(user) const [anchorEl, setAnchorEl] = React.useState(null); const navigate = useNavigate(); const [, setToken] = useAtom(token) - const setErr = useSetAtom(AlertErr) + const setErr = useSetAtom(LayoutAlertErr) const server = useRequest(serverInfo, { cacheKey: "/api/yggdrasil", @@ -168,7 +175,6 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => { }) - const handleLogOut = useMemoizedFn(() => { setAnchorEl(null); setNowUser({ name: "", uuid: "" }) @@ -176,8 +182,6 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => { navigate("/") }) - - return ( <> @@ -234,3 +238,38 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => { ) }) + +const MyList = memo(function MyList(p: { list: ListItem[] }) { + useTilg() + + return ( + <> + + {p.list.map(item => + + )} + + + ) +}) + +const MyListItem = memo(function MyListItem(p: ListItem) { + const navigate = useNavigate(); + + const handleClick = useMemoizedFn(() => { + navigate(p.link) + }) + + return ( + + + + {p.icon} + + + + + ) +}) + +export default Layout \ No newline at end of file diff --git a/frontend/src/views/profile/Profile.tsx b/frontend/src/views/profile/Profile.tsx index 431aaac..8bd6e36 100644 --- a/frontend/src/views/profile/Profile.tsx +++ b/frontend/src/views/profile/Profile.tsx @@ -6,10 +6,9 @@ import Typography from '@mui/material/Typography'; import CardHeader from '@mui/material/CardHeader'; import { useHover, useRequest } from 'ahooks'; import { ApiErr } from '@/apis/error'; -import { token } from '@/store/store'; +import { LayoutAlertErr, token } from '@/store/store'; import { useAtomValue, useSetAtom } from 'jotai'; import { userInfo, yggProfile } from '@/apis/apis'; -import { AlertErr } from '@/views/Layout'; import { useNavigate } from 'react-router-dom'; import Box from '@mui/material/Box'; import { memo, useEffect, useRef, useState } from 'react'; @@ -19,12 +18,11 @@ import type { ReactSkinview3dOptions } from "react-skinview3d" import { WalkingAnimation } from "skinview3d" import type { SkinViewer } from "skinview3d" import Skeleton from '@mui/material/Skeleton'; -import useTilg from 'tilg'; -const Profile = () => { +const Profile = memo(function Profile() { const nowToken = useAtomValue(token) const navigate = useNavigate(); - const setErr = useSetAtom(AlertErr) + const setErr = useSetAtom(LayoutAlertErr) const [textures, setTextures] = useState({ skin: "", cape: "", model: "default" }) const userinfo = useRequest(() => userInfo(nowToken), { @@ -67,10 +65,10 @@ const Profile = () => { - 用户名 - {SkinInfo.loading || userinfo.loading ? : SkinInfo.data?.name} uid {userinfo.loading ? : userinfo.data?.uid} + name + {SkinInfo.loading || userinfo.loading ? : SkinInfo.data?.name} uuid {userinfo.loading ? : userinfo.data?.uuid} @@ -94,25 +92,24 @@ const Profile = () => { } - + 本站 Yggdrasil API 地址 - {import.meta.env.VITE_APIADDR + "/api/yggdrasil"} + {getYggRoot()} ) -} +}) - -const MySkin = memo((p: ReactSkinview3dOptions) => { +const MySkin = memo(function MySkin(p: ReactSkinview3dOptions) { const refSkinview3d = useRef(null); const skinisHovering = useHover(refSkinview3d); const skinview3dView = useRef(null); @@ -126,7 +123,6 @@ const MySkin = memo((p: ReactSkinview3dOptions) => { } }, [skinisHovering]) - useTilg(`refSkinview3d= `, refSkinview3d, `skinisHovering=${skinisHovering}`); return
{
}) +function getYggRoot() { + const u = new URL((import.meta.env.VITE_APIADDR ?? location.origin) + "/api/yggdrasil") + return u.toString() +} + export default Profile \ No newline at end of file diff --git a/frontend/src/views/profile/Textures.tsx b/frontend/src/views/profile/Textures.tsx new file mode 100644 index 0000000..e69de29