Recode login page

This commit is contained in:
2023-12-21 18:36:31 +08:00
parent 1b78cd4163
commit 85aba29ced
7 changed files with 540 additions and 6 deletions

View File

@@ -1,5 +1,5 @@
import React from 'react'
import '@/assets/css/pages/login.scss'
import '@/assets/css/pages/login-.scss'
import {
PERMISSION_LOGIN_SUCCESS,
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,

347
src/pages/Sign.tsx Normal file
View 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}
>
&ensp;&ensp;&ensp;&ensp;
</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}
>
&ensp;&ensp;&ensp;&ensp;
</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

View File

@@ -16,15 +16,20 @@ const ToolsFramework: React.FC = () => {
<Sidebar
title={'个人中心'}
bottomFixed={
hasPathPermission('/system') ? (
<SidebarItemList>
<SidebarItemList>
{hasPathPermission('/system') ? (
<SidebarItem
path={'/system'}
icon={IconFatwebSetting}
text={'系统配置'}
/>
</SidebarItemList>
) : undefined
) : undefined}
<SidebarItem
path={'/tools'}
icon={IconFatwebBack}
text={'回到氮工具'}
/>
</SidebarItemList>
}
>
<SidebarItemList>