Recode login page
This commit is contained in:
161
src/assets/css/pages/sign.scss
Normal file
161
src/assets/css/pages/sign.scss
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
@use "@/assets/css/mixins" as mixins;
|
||||||
|
@use "@/assets/css/constants" as constants;
|
||||||
|
|
||||||
|
[data-component=sign] {
|
||||||
|
background-color: #D2D0DD;
|
||||||
|
user-select: none;
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: constants.$production-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-box {
|
||||||
|
position: relative;
|
||||||
|
background-color: constants.$origin-color;
|
||||||
|
width: 900px;
|
||||||
|
height: 600px;
|
||||||
|
overflow: hidden;
|
||||||
|
border-radius: 12px;
|
||||||
|
|
||||||
|
.left, .right {
|
||||||
|
opacity: 1;
|
||||||
|
animation: 1s ease;
|
||||||
|
@include mixins.unique-keyframes {
|
||||||
|
0% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.hidden {
|
||||||
|
opacity: 0;
|
||||||
|
animation: 1s ease;
|
||||||
|
@include mixins.unique-keyframes {
|
||||||
|
0% {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
.title {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
transform: translateY(-10px);
|
||||||
|
|
||||||
|
.primary {
|
||||||
|
font-size: 2.4em;
|
||||||
|
font-weight: bolder;
|
||||||
|
color: constants.$production-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.secondary {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.form {
|
||||||
|
width: 300px;
|
||||||
|
|
||||||
|
.addition {
|
||||||
|
justify-content: space-between;
|
||||||
|
margin-bottom: 14px;
|
||||||
|
|
||||||
|
> * {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: constants.$production-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.sign-up {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.sign-in {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.cover {
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 50%;
|
||||||
|
background-color: #F3F4F8;
|
||||||
|
animation: 0.8s ease;
|
||||||
|
@include mixins.unique-keyframes {
|
||||||
|
0% {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ball-box {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
background-color: #F1F2F7;
|
||||||
|
|
||||||
|
.ball {
|
||||||
|
position: absolute;
|
||||||
|
width: 128px;
|
||||||
|
height: 128px;
|
||||||
|
background-color: constants.$production-color;
|
||||||
|
border-radius: 50%;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%) translateY(50%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mask {
|
||||||
|
transform: rotateZ(180deg);
|
||||||
|
filter: blur(12px);
|
||||||
|
|
||||||
|
.ball {
|
||||||
|
width: 140px;
|
||||||
|
height: 140px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.switch {
|
||||||
|
.cover {
|
||||||
|
left: 50%;
|
||||||
|
animation: 0.8s ease;
|
||||||
|
@include mixins.unique-keyframes {
|
||||||
|
0% {
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
left: 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/assets/svg/password.svg
Normal file
1
src/assets/svg/password.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1024 1024"><path d="M768 426.666667V341.333333A256 256 0 0 0 256 341.333333v85.333334a85.333333 85.333333 0 0 0-85.333333 85.333333v341.333333a85.333333 85.333333 0 0 0 85.333333 85.333334h512a85.333333 85.333333 0 0 0 85.333333-85.333334v-341.333333a85.333333 85.333333 0 0 0-85.333333-85.333333zM341.333333 341.333333a170.666667 170.666667 0 0 1 341.333334 0v85.333334H341.333333z m298.666667 320a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333h-42.666667a21.333333 21.333333 0 0 1-21.333333-21.333333z m-170.666667 0a21.333333 21.333333 0 0 1 21.333334-21.333333h42.666666a21.333333 21.333333 0 0 1 21.333334 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333334 21.333333h-42.666666a21.333333 21.333333 0 0 1-21.333334-21.333333z m-170.666666 42.666667v-42.666667a21.333333 21.333333 0 0 1 21.333333-21.333333h42.666667a21.333333 21.333333 0 0 1 21.333333 21.333333v42.666667a21.333333 21.333333 0 0 1-21.333333 21.333333h-42.666667a21.333333 21.333333 0 0 1-21.333333-21.333333z" /></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -1,5 +1,5 @@
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import '@/assets/css/pages/login.scss'
|
import '@/assets/css/pages/login-.scss'
|
||||||
import {
|
import {
|
||||||
PERMISSION_LOGIN_SUCCESS,
|
PERMISSION_LOGIN_SUCCESS,
|
||||||
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,
|
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,
|
||||||
347
src/pages/Sign.tsx
Normal file
347
src/pages/Sign.tsx
Normal file
@@ -0,0 +1,347 @@
|
|||||||
|
import React, { useState } from 'react'
|
||||||
|
import '@/assets/css/pages/sign.scss'
|
||||||
|
import FitFullscreen from '@/components/common/FitFullscreen'
|
||||||
|
import FitCenter from '@/components/common/FitCenter'
|
||||||
|
import FlexBox from '@/components/common/FlexBox'
|
||||||
|
import { useNavigate } from 'react-router'
|
||||||
|
import Icon from '@ant-design/icons'
|
||||||
|
import { getUserInfo, login, setToken } from '@/util/auth.tsx'
|
||||||
|
import {
|
||||||
|
PERMISSION_LOGIN_SUCCESS,
|
||||||
|
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,
|
||||||
|
PERMISSION_USER_DISABLE,
|
||||||
|
PERMISSION_USERNAME_NOT_FOUND
|
||||||
|
} from '@/constants/common.constants.ts'
|
||||||
|
import { AppContext } from '@/App.tsx'
|
||||||
|
import { utcToLocalTime } from '@/util/datetime.tsx'
|
||||||
|
import { useUpdatedEffect } from '@/util/hooks.tsx'
|
||||||
|
|
||||||
|
const SignUp: React.FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'sign-up'}>
|
||||||
|
<FitCenter>
|
||||||
|
<FlexBox>
|
||||||
|
<div>Welcome join us</div>
|
||||||
|
<AntdButton
|
||||||
|
onClick={() =>
|
||||||
|
navigate(
|
||||||
|
`/login${
|
||||||
|
searchParams.toString() ? `?${searchParams.toString()}` : ''
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
登录
|
||||||
|
</AntdButton>
|
||||||
|
<AntdForm>
|
||||||
|
<AntdForm.Item></AntdForm.Item>
|
||||||
|
</AntdForm>
|
||||||
|
</FlexBox>
|
||||||
|
</FitCenter>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Forget: React.FC = () => {
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
const [isLoading, setIsLoading] = useState(false)
|
||||||
|
const [isFinish, setIsFinish] = useState(false)
|
||||||
|
|
||||||
|
const handleOnFinish = () => {
|
||||||
|
setIsFinish(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleOnRetry = () => {
|
||||||
|
setIsFinish(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'forget'}>
|
||||||
|
<FitCenter>
|
||||||
|
<FlexBox>
|
||||||
|
<div className={'title'}>
|
||||||
|
<div className={'primary'}>找回密码</div>
|
||||||
|
<div className={'secondary'}>Retrieve password</div>
|
||||||
|
</div>
|
||||||
|
<AntdForm autoComplete={'on'} onFinish={handleOnFinish} className={'form'}>
|
||||||
|
{!isFinish ? (
|
||||||
|
<>
|
||||||
|
<AntdForm.Item
|
||||||
|
name={'account'}
|
||||||
|
rules={[{ required: true, message: '请输入邮箱' }]}
|
||||||
|
>
|
||||||
|
<AntdInput
|
||||||
|
prefix={<Icon component={IconFatwebEmail} />}
|
||||||
|
placeholder={'邮箱'}
|
||||||
|
disabled={isLoading}
|
||||||
|
/>
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item>
|
||||||
|
<AntdButton
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'primary'}
|
||||||
|
htmlType={'submit'}
|
||||||
|
disabled={isLoading}
|
||||||
|
loading={isLoading}
|
||||||
|
>
|
||||||
|
确    定
|
||||||
|
</AntdButton>
|
||||||
|
</AntdForm.Item>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<div style={{ marginBottom: 10 }}>
|
||||||
|
我们发送了一封包含找回密码链接的邮件到您的邮箱里,如未收到,可能被归为垃圾邮件,请仔细检查。
|
||||||
|
<a onClick={handleOnRetry}>重新发送</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div className={'footer'}>
|
||||||
|
找到了?
|
||||||
|
<a
|
||||||
|
onClick={() =>
|
||||||
|
navigate(
|
||||||
|
`/login${
|
||||||
|
searchParams.toString()
|
||||||
|
? `?${searchParams.toString()}`
|
||||||
|
: ''
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
登录
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</AntdForm>
|
||||||
|
</FlexBox>
|
||||||
|
</FitCenter>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const SignIn: React.FC = () => {
|
||||||
|
const { refreshRouter } = useContext(AppContext)
|
||||||
|
const navigate = useNavigate()
|
||||||
|
const [searchParams] = useSearchParams()
|
||||||
|
const [isSigningIn, setIsSigningIn] = useState(false)
|
||||||
|
|
||||||
|
const handleOnFinish = (loginForm: LoginForm) => {
|
||||||
|
if (isSigningIn) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
setIsSigningIn(true)
|
||||||
|
|
||||||
|
void login(loginForm.account, loginForm.password)
|
||||||
|
.then((res) => {
|
||||||
|
const response = res.data
|
||||||
|
const { code, data } = response
|
||||||
|
switch (code) {
|
||||||
|
case PERMISSION_LOGIN_SUCCESS:
|
||||||
|
setToken(data?.token ?? '')
|
||||||
|
void message.success('登录成功')
|
||||||
|
setTimeout(() => {
|
||||||
|
void getUserInfo().then((user) => {
|
||||||
|
refreshRouter()
|
||||||
|
if (searchParams.has('redirect')) {
|
||||||
|
navigate(searchParams.get('redirect') ?? '/')
|
||||||
|
} else {
|
||||||
|
navigate('/')
|
||||||
|
}
|
||||||
|
|
||||||
|
notification.success({
|
||||||
|
message: '欢迎回来',
|
||||||
|
description: (
|
||||||
|
<>
|
||||||
|
<span>
|
||||||
|
你好 <strong>{user.userInfo.nickname}</strong>
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<span>
|
||||||
|
最近登录:
|
||||||
|
{user.lastLoginTime
|
||||||
|
? `${utcToLocalTime(user.lastLoginTime)}【${
|
||||||
|
user.lastLoginIp
|
||||||
|
}】`
|
||||||
|
: '无'}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
),
|
||||||
|
placement: 'topRight'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}, 1500)
|
||||||
|
break
|
||||||
|
case PERMISSION_USERNAME_NOT_FOUND:
|
||||||
|
case PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR:
|
||||||
|
void message.error(
|
||||||
|
<>
|
||||||
|
<strong>账号</strong>或<strong>密码</strong>错误,请重试
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
setIsSigningIn(false)
|
||||||
|
break
|
||||||
|
case PERMISSION_USER_DISABLE:
|
||||||
|
void message.error(
|
||||||
|
<>
|
||||||
|
该用户已被<strong>禁用</strong>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
setIsSigningIn(false)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
void message.error(
|
||||||
|
<>
|
||||||
|
<strong>服务器出错了</strong>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
setIsSigningIn(false)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
setIsSigningIn(false)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={'sign-in'}>
|
||||||
|
<FitCenter>
|
||||||
|
<FlexBox>
|
||||||
|
<div className={'title'}>
|
||||||
|
<div className={'primary'}>欢迎回来</div>
|
||||||
|
<div className={'secondary'}>Welcome back</div>
|
||||||
|
</div>
|
||||||
|
<AntdForm autoComplete={'on'} onFinish={handleOnFinish} className={'form'}>
|
||||||
|
<AntdForm.Item
|
||||||
|
name={'account'}
|
||||||
|
rules={[{ required: true, message: '账号为空' }]}
|
||||||
|
>
|
||||||
|
<AntdInput
|
||||||
|
prefix={<Icon component={IconFatwebUser} />}
|
||||||
|
placeholder={'邮箱/用户名'}
|
||||||
|
disabled={isSigningIn}
|
||||||
|
/>
|
||||||
|
</AntdForm.Item>
|
||||||
|
<AntdForm.Item
|
||||||
|
name={'password'}
|
||||||
|
rules={[{ required: true, message: '密码为空' }]}
|
||||||
|
>
|
||||||
|
<AntdInput.Password
|
||||||
|
prefix={<Icon component={IconFatwebPassword} />}
|
||||||
|
placeholder={'密码'}
|
||||||
|
disabled={isSigningIn}
|
||||||
|
/>
|
||||||
|
</AntdForm.Item>
|
||||||
|
<FlexBox direction={'horizontal'} className={'addition'}>
|
||||||
|
<AntdCheckbox disabled={isSigningIn}>记住密码</AntdCheckbox>
|
||||||
|
<a
|
||||||
|
onClick={() => {
|
||||||
|
navigate(
|
||||||
|
`/forget${
|
||||||
|
searchParams.toString()
|
||||||
|
? `?${searchParams.toString()}`
|
||||||
|
: ''
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
忘记密码?
|
||||||
|
</a>
|
||||||
|
</FlexBox>
|
||||||
|
<AntdForm.Item>
|
||||||
|
<AntdButton
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'primary'}
|
||||||
|
htmlType={'submit'}
|
||||||
|
disabled={isSigningIn}
|
||||||
|
loading={isSigningIn}
|
||||||
|
>
|
||||||
|
登    录
|
||||||
|
</AntdButton>
|
||||||
|
</AntdForm.Item>
|
||||||
|
<div className={'footer'}>
|
||||||
|
还没有账户?
|
||||||
|
<a
|
||||||
|
onClick={() =>
|
||||||
|
navigate(
|
||||||
|
`/register${
|
||||||
|
searchParams.toString()
|
||||||
|
? `?${searchParams.toString()}`
|
||||||
|
: ''
|
||||||
|
}`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
注册
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</AntdForm>
|
||||||
|
</FlexBox>
|
||||||
|
</FitCenter>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const Sign: React.FC = () => {
|
||||||
|
const lastPage = useRef('none')
|
||||||
|
const currentPage = useRef('none')
|
||||||
|
const match = useMatches().reduce((_, second) => second)
|
||||||
|
const [isSwitch, setIsSwitch] = useState(false)
|
||||||
|
|
||||||
|
const leftPage = ['register', 'forget']
|
||||||
|
|
||||||
|
useUpdatedEffect(() => {
|
||||||
|
lastPage.current = currentPage.current
|
||||||
|
currentPage.current = match.id
|
||||||
|
|
||||||
|
setIsSwitch(leftPage.includes(currentPage.current))
|
||||||
|
}, [match.id])
|
||||||
|
|
||||||
|
const leftComponent = () => {
|
||||||
|
switch (leftPage.includes(currentPage.current) ? currentPage.current : lastPage.current) {
|
||||||
|
case 'forget':
|
||||||
|
return <Forget />
|
||||||
|
default:
|
||||||
|
return <SignUp />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const rightComponent = () => {
|
||||||
|
switch (leftPage.includes(currentPage.current) ? lastPage.current : currentPage.current) {
|
||||||
|
default:
|
||||||
|
return <SignIn />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<FitFullscreen data-component={'sign'}>
|
||||||
|
<FitCenter>
|
||||||
|
<FlexBox
|
||||||
|
direction={'horizontal'}
|
||||||
|
className={`sign-box${isSwitch ? ' switch' : ''}`}
|
||||||
|
>
|
||||||
|
<div className={`left${!isSwitch ? ' hidden' : ''}`}>{leftComponent()}</div>
|
||||||
|
<div className={`right${isSwitch ? ' hidden' : ''}`}>
|
||||||
|
{rightComponent()}
|
||||||
|
</div>
|
||||||
|
<FlexBox className={'cover'}>
|
||||||
|
<div className={'ball-box'}>
|
||||||
|
<div className={'ball'} />
|
||||||
|
</div>
|
||||||
|
<div className={'ball-box'}>
|
||||||
|
<div className={'mask'}>
|
||||||
|
<div className={'ball'} />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</FlexBox>
|
||||||
|
</FlexBox>
|
||||||
|
</FitCenter>
|
||||||
|
</FitFullscreen>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Sign
|
||||||
@@ -16,15 +16,20 @@ const ToolsFramework: React.FC = () => {
|
|||||||
<Sidebar
|
<Sidebar
|
||||||
title={'个人中心'}
|
title={'个人中心'}
|
||||||
bottomFixed={
|
bottomFixed={
|
||||||
hasPathPermission('/system') ? (
|
<SidebarItemList>
|
||||||
<SidebarItemList>
|
{hasPathPermission('/system') ? (
|
||||||
<SidebarItem
|
<SidebarItem
|
||||||
path={'/system'}
|
path={'/system'}
|
||||||
icon={IconFatwebSetting}
|
icon={IconFatwebSetting}
|
||||||
text={'系统配置'}
|
text={'系统配置'}
|
||||||
/>
|
/>
|
||||||
</SidebarItemList>
|
) : undefined}
|
||||||
) : undefined
|
<SidebarItem
|
||||||
|
path={'/tools'}
|
||||||
|
icon={IconFatwebBack}
|
||||||
|
text={'回到氮工具'}
|
||||||
|
/>
|
||||||
|
</SidebarItemList>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<SidebarItemList>
|
<SidebarItemList>
|
||||||
|
|||||||
@@ -6,17 +6,37 @@ import user from '@/router/user'
|
|||||||
import tools from '@/router/tools'
|
import tools from '@/router/tools'
|
||||||
import { getAuthRoute, mapJsonToRoute, setTitle } from '@/util/route'
|
import { getAuthRoute, mapJsonToRoute, setTitle } from '@/util/route'
|
||||||
|
|
||||||
|
const lazySignPage = React.lazy(() => import('@/pages/Sign'))
|
||||||
|
|
||||||
const root: RouteJsonObject[] = [
|
const root: RouteJsonObject[] = [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
absolutePath: '/',
|
absolutePath: '/',
|
||||||
component: React.lazy(() => import('@/AuthRoute')),
|
component: React.lazy(() => import('@/AuthRoute')),
|
||||||
children: [
|
children: [
|
||||||
|
{
|
||||||
|
path: 'register',
|
||||||
|
absolutePath: '/register',
|
||||||
|
id: 'register',
|
||||||
|
component: lazySignPage
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'confirm',
|
||||||
|
absolutePath: '/confirm',
|
||||||
|
id: 'confirm',
|
||||||
|
component: lazySignPage
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'forget',
|
||||||
|
absolutePath: '/forget',
|
||||||
|
id: 'forget',
|
||||||
|
component: lazySignPage
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'login',
|
path: 'login',
|
||||||
absolutePath: '/login',
|
absolutePath: '/login',
|
||||||
id: 'login',
|
id: 'login',
|
||||||
component: React.lazy(() => import('@/pages/Login'))
|
component: lazySignPage
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'loading',
|
path: 'loading',
|
||||||
|
|||||||
Reference in New Issue
Block a user