diff --git a/frontend/src/Route.tsx b/frontend/src/Route.tsx index 7726c68..798ca70 100644 --- a/frontend/src/Route.tsx +++ b/frontend/src/Route.tsx @@ -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 Register from '@/views/Register' +import { ScrollRestoration } from "react-router-dom"; -export function PageRoute() { +const router = createBrowserRouter([ + { path: "*", Component: Root }, +]); + +function Root() { return ( <> }> } /> + } /> + + + ) +} + + +export function PageRoute() { + return ( + <> + ; ) } diff --git a/frontend/src/apis/apis.ts b/frontend/src/apis/apis.ts new file mode 100644 index 0000000..d76df1e --- /dev/null +++ b/frontend/src/apis/apis.ts @@ -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 +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index 095cf67..c65c6fd 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,15 +1,12 @@ import React from 'react' import ReactDOM from 'react-dom/client' import App from './App.tsx' -import { BrowserRouter } from "react-router-dom"; import CssBaseline from '@mui/material/CssBaseline'; ReactDOM.createRoot(document.getElementById('root')!).render( - - ) diff --git a/frontend/src/utils/email.ts b/frontend/src/utils/email.ts new file mode 100644 index 0000000..2d88b7d --- /dev/null +++ b/frontend/src/utils/email.ts @@ -0,0 +1,3 @@ +export function checkEmail(email: string) { + return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/.test(email); +} \ No newline at end of file diff --git a/frontend/src/views/Login.tsx b/frontend/src/views/Login.tsx index 4775e8f..097b400 100644 --- a/frontend/src/views/Login.tsx +++ b/frontend/src/views/Login.tsx @@ -15,7 +15,9 @@ import Backdrop from '@mui/material/Backdrop'; import CircularProgress from '@mui/material/CircularProgress'; import { useSetAtom } from 'jotai'; 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() { 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() { @@ -67,13 +48,13 @@ export default function SignIn() { email: data.get('email')?.toString(), password: data.get('password')?.toString(), } - if (!postData.email?.includes("@")) { + if (!checkEmail(postData.email ?? "")) { setEmailErr("需要为邮箱") return } if (loading) return setLoading(true) - tologin(postData.email, postData.password ?? ""). + login(postData.email!, postData.password ?? ""). then(v => { if (!v) return setToken(v.accessToken) @@ -137,7 +118,7 @@ export default function SignIn() { - + {"注册"} diff --git a/frontend/src/views/Register.tsx b/frontend/src/views/Register.tsx new file mode 100644 index 0000000..b58df2d --- /dev/null +++ b/frontend/src/views/Register.tsx @@ -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) => { + 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 ( + + + + + + + + 注册 + + + + + + + + + + + + + + + + + + + + + 登录 + + + + + + + ); +} \ No newline at end of file