This commit is contained in:
xmdhs 2023-09-20 17:15:46 +08:00
parent 2febce1c3a
commit 0406612a5a
No known key found for this signature in database
GPG Key ID: E809D6D43DEFCC95
6 changed files with 179 additions and 30 deletions

View File

@ -1,13 +1,30 @@
import { Routes, Route, Outlet } from "react-router-dom"; import { Routes, Route, Outlet, createBrowserRouter, RouterProvider } from "react-router-dom";
import Login from '@/views/Login' import Login from '@/views/Login'
import Register from '@/views/Register'
import { ScrollRestoration } from "react-router-dom";
export function PageRoute() { const router = createBrowserRouter([
{ path: "*", Component: Root },
]);
function Root() {
return ( return (
<> <>
<Routes> <Routes>
<Route path="/" element={<Layout />}></Route> <Route path="/" element={<Layout />}></Route>
<Route path="/login" element={<Login />} /> <Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Routes> </Routes>
<ScrollRestoration />
</>
)
}
export function PageRoute() {
return (
<>
<RouterProvider router={router} />;
</> </>
) )
} }

21
frontend/src/apis/apis.ts Normal file
View File

@ -0,0 +1,21 @@
interface tokenData {
accessToken: string
selectedProfile: {
name: string
}
}
export async function login(username: string, password: string) {
const v = await fetch(import.meta.env.VITE_APIADDR + "/api/yggdrasil/authserver/authenticate", {
method: "POST",
body: JSON.stringify({
"username": username,
"password": password,
})
})
const data = await v.json()
if (!v.ok) {
throw data?.errorMessage
}
return data as tokenData
}

View File

@ -1,15 +1,12 @@
import React from 'react' import React from 'react'
import ReactDOM from 'react-dom/client' import ReactDOM from 'react-dom/client'
import App from './App.tsx' import App from './App.tsx'
import { BrowserRouter } from "react-router-dom";
import CssBaseline from '@mui/material/CssBaseline'; import CssBaseline from '@mui/material/CssBaseline';
ReactDOM.createRoot(document.getElementById('root')!).render( ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode> <React.StrictMode>
<BrowserRouter>
<CssBaseline> <CssBaseline>
<App /> <App />
</CssBaseline> </CssBaseline>
</BrowserRouter>
</React.StrictMode> </React.StrictMode>
) )

View File

@ -0,0 +1,3 @@
export function checkEmail(email: string) {
return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email);
}

View File

@ -15,7 +15,9 @@ import Backdrop from '@mui/material/Backdrop';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import { useSetAtom } from 'jotai'; import { useSetAtom } from 'jotai';
import { token, username } from '@/store/store' import { token, username } from '@/store/store'
import { login } from '@/apis/apis'
import { checkEmail } from '@/utils/email'
import { Link as RouterLink } from "react-router-dom";
function Loading() { function Loading() {
return ( return (
@ -30,27 +32,6 @@ function Loading() {
) )
} }
interface tokenData {
accessToken: string
selectedProfile: {
name: string
}
}
async function tologin(username: string, password: string) {
const v = await fetch(import.meta.env.VITE_APIADDR + "/api/yggdrasil/authserver/authenticate", {
method: "POST",
body: JSON.stringify({
"username": username,
"password": password,
})
})
const data = await v.json()
if (!v.ok) {
throw data?.errorMessage
}
return data as tokenData
}
export default function SignIn() { export default function SignIn() {
@ -67,13 +48,13 @@ export default function SignIn() {
email: data.get('email')?.toString(), email: data.get('email')?.toString(),
password: data.get('password')?.toString(), password: data.get('password')?.toString(),
} }
if (!postData.email?.includes("@")) { if (!checkEmail(postData.email ?? "")) {
setEmailErr("需要为邮箱") setEmailErr("需要为邮箱")
return return
} }
if (loading) return if (loading) return
setLoading(true) setLoading(true)
tologin(postData.email, postData.password ?? ""). login(postData.email!, postData.password ?? "").
then(v => { then(v => {
if (!v) return if (!v) return
setToken(v.accessToken) setToken(v.accessToken)
@ -137,7 +118,7 @@ export default function SignIn() {
</Link> </Link>
</Grid> </Grid>
<Grid item> <Grid item>
<Link href="#" variant="body2"> <Link component={RouterLink} to="/register" variant="body2">
{"注册"} {"注册"}
</Link> </Link>
</Grid> </Grid>

View File

@ -0,0 +1,130 @@
import * as React from 'react';
import Avatar from '@mui/material/Avatar';
import Button from '@mui/material/Button';
import CssBaseline from '@mui/material/CssBaseline';
import TextField from '@mui/material/TextField';
import Link from '@mui/material/Link';
import Grid from '@mui/material/Grid';
import Box from '@mui/material/Box';
import LockOutlinedIcon from '@mui/icons-material/LockOutlined';
import Typography from '@mui/material/Typography';
import Container from '@mui/material/Container';
import { useState } from 'react';
import { checkEmail } from '@/utils/email';
import { Link as RouterLink } from "react-router-dom";
export default function SignUp() {
const [emailErr, setEmailErr] = useState("");
const [passErr, setpassErr] = useState("");
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
setEmailErr("")
setpassErr("")
event.preventDefault();
const data = new FormData(event.currentTarget);
const d = {
email: data.get('email')?.toString(),
password: data.get('password')?.toString(),
password1: data.get('password1')?.toString(),
username: data.get("username")?.toString()
}
if (!checkEmail(d.email ?? "")) {
setEmailErr("需要为邮箱")
return
}
if (d.password != d.password1) {
setpassErr("密码不一致")
return
}
if (d.password == "") {
setpassErr("密码为空")
return
}
};
return (
<Container component="main" maxWidth="xs">
<CssBaseline />
<Box
sx={{
marginTop: 8,
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
}}
>
<Avatar sx={{ m: 1, bgcolor: 'secondary.main' }}>
<LockOutlinedIcon />
</Avatar>
<Typography component="h1" variant="h5">
</Typography>
<Box component="form" noValidate onSubmit={handleSubmit} sx={{ mt: 3 }}>
<Grid container spacing={2}>
<Grid item xs={12}>
<TextField
error={emailErr != ""}
helperText={emailErr}
required
fullWidth
name="email"
label="邮箱"
autoComplete="email"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
name="username"
label="角色名"
autoComplete="email"
/>
</Grid>
<Grid item xs={12}>
<TextField
error={passErr != ""}
helperText={passErr}
required
fullWidth
label="密码"
type="password"
name="password"
autoComplete="new-password"
/>
</Grid>
<Grid item xs={12}>
<TextField
required
fullWidth
label="确认密码"
type="password"
name="password1"
autoComplete="new-password"
/>
</Grid>
</Grid>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
</Button>
<Grid container justifyContent="flex-end">
<Grid item>
<Link component={RouterLink} to={"/login"} variant="body2">
</Link>
</Grid>
</Grid>
</Box>
</Box>
</Container>
);
}