修复部分问题
This commit is contained in:
parent
867ca4c9de
commit
221a035507
@ -1,3 +1,4 @@
|
|||||||
|
import { atom } from 'jotai'
|
||||||
import { atomWithStorage } from 'jotai/utils'
|
import { atomWithStorage } from 'jotai/utils'
|
||||||
|
|
||||||
export const token = atomWithStorage("token", "")
|
export const token = atomWithStorage("token", "")
|
||||||
@ -5,3 +6,5 @@ export const user = atomWithStorage("username", {
|
|||||||
name: "",
|
name: "",
|
||||||
uuid: ""
|
uuid: ""
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const LayoutAlertErr = atom("")
|
||||||
|
@ -13,15 +13,13 @@ import ListItem from '@mui/material/ListItem';
|
|||||||
import ListItemButton from '@mui/material/ListItemButton';
|
import ListItemButton from '@mui/material/ListItemButton';
|
||||||
import ListItemIcon from '@mui/material/ListItemIcon';
|
import ListItemIcon from '@mui/material/ListItemIcon';
|
||||||
import ListItemText from '@mui/material/ListItemText';
|
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 AppBar from '@mui/material/AppBar';
|
||||||
import { Outlet } from 'react-router-dom';
|
import { Outlet } from 'react-router-dom';
|
||||||
import { AccountCircle } from '@mui/icons-material';
|
import { AccountCircle } from '@mui/icons-material';
|
||||||
import Menu from '@mui/material/Menu';
|
import Menu from '@mui/material/Menu';
|
||||||
import MenuItem from '@mui/material/MenuItem';
|
import MenuItem from '@mui/material/MenuItem';
|
||||||
import { token, user } from '@/store/store';
|
import { LayoutAlertErr, token, user } from '@/store/store';
|
||||||
import { atom, useAtom, useAtomValue, useSetAtom } from 'jotai';
|
import { useAtom, useAtomValue, useSetAtom } from 'jotai';
|
||||||
import Button from '@mui/material/Button';
|
import Button from '@mui/material/Button';
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { useRequest, useMemoizedFn } from 'ahooks';
|
import { useRequest, useMemoizedFn } from 'ahooks';
|
||||||
@ -30,12 +28,13 @@ import Snackbar from '@mui/material/Snackbar';
|
|||||||
import Alert from '@mui/material/Alert';
|
import Alert from '@mui/material/Alert';
|
||||||
import { memo } from 'react';
|
import { memo } from 'react';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
import useTilg from 'tilg'
|
|
||||||
import { ApiErr } from '@/apis/error';
|
import { ApiErr } from '@/apis/error';
|
||||||
import Typography from '@mui/material/Typography';
|
import Typography from '@mui/material/Typography';
|
||||||
import Container from '@mui/material/Container';
|
import Container from '@mui/material/Container';
|
||||||
|
import PersonIcon from '@mui/icons-material/Person';
|
||||||
export const AlertErr = atom("")
|
import SecurityIcon from '@mui/icons-material/Security';
|
||||||
|
import SettingsIcon from '@mui/icons-material/Settings';
|
||||||
|
import useTilg from 'tilg'
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
@ -48,16 +47,21 @@ const DrawerHeader = styled('div')(({ theme }) => ({
|
|||||||
justifyContent: 'flex-end',
|
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 theme = useTheme();
|
||||||
const isLg = useMediaQuery(theme.breakpoints.up('lg'))
|
const isLg = useMediaQuery(theme.breakpoints.up('lg'))
|
||||||
const [open, setOpen] = React.useState(false);
|
const [open, setOpen] = React.useState(false);
|
||||||
const nowToken = useAtomValue(token)
|
const nowToken = useAtomValue(token)
|
||||||
const [err, setErr] = useAtom(AlertErr)
|
const [err, setErr] = useAtom(LayoutAlertErr)
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
|
||||||
const userinfo = useRequest(() => userInfo(nowToken), {
|
const userinfo = useRequest(() => userInfo(nowToken), {
|
||||||
refreshDeps: [nowToken],
|
refreshDeps: [nowToken],
|
||||||
cacheKey: "/api/v1/user",
|
cacheKey: "/api/v1/user",
|
||||||
@ -71,7 +75,32 @@ export default function Layout() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
useTilg(isLg, open)
|
const userDrawerList = React.useMemo(() => [
|
||||||
|
{
|
||||||
|
icon: <PersonIcon />,
|
||||||
|
title: '个人信息',
|
||||||
|
link: '/profile'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <SettingsIcon />,
|
||||||
|
title: '皮肤设置',
|
||||||
|
link: '/textures'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
icon: <SecurityIcon />,
|
||||||
|
title: '安全设置',
|
||||||
|
link: '/setting'
|
||||||
|
}
|
||||||
|
] as ListItem[], [])
|
||||||
|
|
||||||
|
const adminDrawerList = React.useMemo(() => [
|
||||||
|
{
|
||||||
|
icon: <PersonIcon />,
|
||||||
|
title: 'test'
|
||||||
|
}
|
||||||
|
] as ListItem[], [])
|
||||||
|
|
||||||
|
useTilg()
|
||||||
|
|
||||||
return (<>
|
return (<>
|
||||||
<Box sx={{ display: 'flex' }}>
|
<Box sx={{ display: 'flex' }}>
|
||||||
@ -103,33 +132,11 @@ export default function Layout() {
|
|||||||
</IconButton>
|
</IconButton>
|
||||||
</DrawerHeader>
|
</DrawerHeader>
|
||||||
<Divider />
|
<Divider />
|
||||||
<List>
|
<MyList list={userDrawerList} />
|
||||||
{['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>
|
|
||||||
{userinfo.data?.is_admin && (
|
{userinfo.data?.is_admin && (
|
||||||
<>
|
<>
|
||||||
<Divider />
|
<Divider />
|
||||||
<List>
|
<MyList list={adminDrawerList} />
|
||||||
{['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>
|
</Drawer>
|
||||||
)}
|
)}
|
||||||
@ -149,14 +156,14 @@ export default function Layout() {
|
|||||||
</Box>
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</>)
|
</>)
|
||||||
}
|
})
|
||||||
|
|
||||||
const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => {
|
const MyToolbar = memo(function MyToolbar(p: { setOpen: (v: boolean) => void }) {
|
||||||
const [nowUser, setNowUser] = useAtom(user)
|
const [nowUser, setNowUser] = useAtom(user)
|
||||||
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const [, setToken] = useAtom(token)
|
const [, setToken] = useAtom(token)
|
||||||
const setErr = useSetAtom(AlertErr)
|
const setErr = useSetAtom(LayoutAlertErr)
|
||||||
|
|
||||||
const server = useRequest(serverInfo, {
|
const server = useRequest(serverInfo, {
|
||||||
cacheKey: "/api/yggdrasil",
|
cacheKey: "/api/yggdrasil",
|
||||||
@ -168,7 +175,6 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const handleLogOut = useMemoizedFn(() => {
|
const handleLogOut = useMemoizedFn(() => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
setNowUser({ name: "", uuid: "" })
|
setNowUser({ name: "", uuid: "" })
|
||||||
@ -176,8 +182,6 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => {
|
|||||||
navigate("/")
|
navigate("/")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Toolbar>
|
<Toolbar>
|
||||||
@ -234,3 +238,38 @@ const MyToolbar = memo((p: { setOpen: (v: boolean) => void }) => {
|
|||||||
</Toolbar>
|
</Toolbar>
|
||||||
</>)
|
</>)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const MyList = memo(function MyList(p: { list: ListItem[] }) {
|
||||||
|
useTilg()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<List>
|
||||||
|
{p.list.map(item =>
|
||||||
|
<MyListItem {...item} key={item.title} />
|
||||||
|
)}
|
||||||
|
</List>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
const MyListItem = memo(function MyListItem(p: ListItem) {
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
|
const handleClick = useMemoizedFn(() => {
|
||||||
|
navigate(p.link)
|
||||||
|
})
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ListItem disablePadding>
|
||||||
|
<ListItemButton onClick={handleClick}>
|
||||||
|
<ListItemIcon>
|
||||||
|
{p.icon}
|
||||||
|
</ListItemIcon>
|
||||||
|
<ListItemText primary={p.title} />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default Layout
|
@ -6,10 +6,9 @@ import Typography from '@mui/material/Typography';
|
|||||||
import CardHeader from '@mui/material/CardHeader';
|
import CardHeader from '@mui/material/CardHeader';
|
||||||
import { useHover, useRequest } from 'ahooks';
|
import { useHover, useRequest } from 'ahooks';
|
||||||
import { ApiErr } from '@/apis/error';
|
import { ApiErr } from '@/apis/error';
|
||||||
import { token } from '@/store/store';
|
import { LayoutAlertErr, token } from '@/store/store';
|
||||||
import { useAtomValue, useSetAtom } from 'jotai';
|
import { useAtomValue, useSetAtom } from 'jotai';
|
||||||
import { userInfo, yggProfile } from '@/apis/apis';
|
import { userInfo, yggProfile } from '@/apis/apis';
|
||||||
import { AlertErr } from '@/views/Layout';
|
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import Box from '@mui/material/Box';
|
import Box from '@mui/material/Box';
|
||||||
import { memo, useEffect, useRef, useState } from 'react';
|
import { memo, useEffect, useRef, useState } from 'react';
|
||||||
@ -19,12 +18,11 @@ import type { ReactSkinview3dOptions } from "react-skinview3d"
|
|||||||
import { WalkingAnimation } from "skinview3d"
|
import { WalkingAnimation } from "skinview3d"
|
||||||
import type { SkinViewer } from "skinview3d"
|
import type { SkinViewer } from "skinview3d"
|
||||||
import Skeleton from '@mui/material/Skeleton';
|
import Skeleton from '@mui/material/Skeleton';
|
||||||
import useTilg from 'tilg';
|
|
||||||
|
|
||||||
const Profile = () => {
|
const Profile = memo(function Profile() {
|
||||||
const nowToken = useAtomValue(token)
|
const nowToken = useAtomValue(token)
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const setErr = useSetAtom(AlertErr)
|
const setErr = useSetAtom(LayoutAlertErr)
|
||||||
const [textures, setTextures] = useState({ skin: "", cape: "", model: "default" })
|
const [textures, setTextures] = useState({ skin: "", cape: "", model: "default" })
|
||||||
|
|
||||||
const userinfo = useRequest(() => userInfo(nowToken), {
|
const userinfo = useRequest(() => userInfo(nowToken), {
|
||||||
@ -67,10 +65,10 @@ const Profile = () => {
|
|||||||
<Card sx={{ gridArea: "a" }}>
|
<Card sx={{ gridArea: "a" }}>
|
||||||
<CardHeader title="信息" />
|
<CardHeader title="信息" />
|
||||||
<CardContent sx={{ display: "grid", gridTemplateColumns: "4em auto" }}>
|
<CardContent sx={{ display: "grid", gridTemplateColumns: "4em auto" }}>
|
||||||
<Typography>用户名</Typography>
|
|
||||||
<Typography>{SkinInfo.loading || userinfo.loading ? <Skeleton /> : SkinInfo.data?.name}</Typography>
|
|
||||||
<Typography>uid</Typography>
|
<Typography>uid</Typography>
|
||||||
<Typography sx={{ wordBreak: 'break-all' }}>{userinfo.loading ? <Skeleton /> : userinfo.data?.uid}</Typography>
|
<Typography sx={{ wordBreak: 'break-all' }}>{userinfo.loading ? <Skeleton /> : userinfo.data?.uid}</Typography>
|
||||||
|
<Typography>name</Typography>
|
||||||
|
<Typography>{SkinInfo.loading || userinfo.loading ? <Skeleton /> : SkinInfo.data?.name}</Typography>
|
||||||
<Typography>uuid</Typography>
|
<Typography>uuid</Typography>
|
||||||
<Typography sx={{ wordBreak: 'break-all' }}>{userinfo.loading ? <Skeleton /> : userinfo.data?.uuid}</Typography>
|
<Typography sx={{ wordBreak: 'break-all' }}>{userinfo.loading ? <Skeleton /> : userinfo.data?.uuid}</Typography>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
@ -94,25 +92,24 @@ const Profile = () => {
|
|||||||
}
|
}
|
||||||
</CardContent>
|
</CardContent>
|
||||||
<CardActions>
|
<CardActions>
|
||||||
<Button size="small">更改</Button>
|
<Button onClick={() => navigate('/textures')} size="small">更改</Button>
|
||||||
</CardActions>
|
</CardActions>
|
||||||
</Card>
|
</Card>
|
||||||
<Card sx={{ gridArea: "c" }}>
|
<Card sx={{ gridArea: "c" }}>
|
||||||
<CardHeader title="启动器设置" />
|
<CardHeader title="启动器设置" />
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Typography>本站 Yggdrasil API 地址</Typography>
|
<Typography>本站 Yggdrasil API 地址</Typography>
|
||||||
<code>{import.meta.env.VITE_APIADDR + "/api/yggdrasil"}</code>
|
<code>{getYggRoot()}</code>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
<Box sx={{ gridArea: "d" }}></Box>
|
<Box sx={{ gridArea: "d" }}></Box>
|
||||||
</Box >
|
</Box >
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const MySkin = memo(function MySkin(p: ReactSkinview3dOptions) {
|
||||||
const MySkin = memo((p: ReactSkinview3dOptions) => {
|
|
||||||
const refSkinview3d = useRef(null);
|
const refSkinview3d = useRef(null);
|
||||||
const skinisHovering = useHover(refSkinview3d);
|
const skinisHovering = useHover(refSkinview3d);
|
||||||
const skinview3dView = useRef<SkinViewer | null>(null);
|
const skinview3dView = useRef<SkinViewer | null>(null);
|
||||||
@ -126,7 +123,6 @@ const MySkin = memo((p: ReactSkinview3dOptions) => {
|
|||||||
}
|
}
|
||||||
}, [skinisHovering])
|
}, [skinisHovering])
|
||||||
|
|
||||||
useTilg(`refSkinview3d= `, refSkinview3d, `skinisHovering=${skinisHovering}`);
|
|
||||||
return <div ref={refSkinview3d}>
|
return <div ref={refSkinview3d}>
|
||||||
<ReactSkinview3d
|
<ReactSkinview3d
|
||||||
{...p}
|
{...p}
|
||||||
@ -135,4 +131,9 @@ const MySkin = memo((p: ReactSkinview3dOptions) => {
|
|||||||
</div>
|
</div>
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function getYggRoot() {
|
||||||
|
const u = new URL((import.meta.env.VITE_APIADDR ?? location.origin) + "/api/yggdrasil")
|
||||||
|
return u.toString()
|
||||||
|
}
|
||||||
|
|
||||||
export default Profile
|
export default Profile
|
0
frontend/src/views/profile/Textures.tsx
Normal file
0
frontend/src/views/profile/Textures.tsx
Normal file
Loading…
x
Reference in New Issue
Block a user