Finish sign page

This commit is contained in:
2023-12-26 17:45:03 +08:00
parent 6510567fdf
commit 647b203b6a
6 changed files with 187 additions and 44 deletions

View File

@@ -5,6 +5,10 @@
background-color: #D2D0DD; background-color: #D2D0DD;
user-select: none; user-select: none;
a {
cursor: pointer;
}
a:hover { a:hover {
color: constants.$production-color; color: constants.$production-color;
} }
@@ -67,6 +71,7 @@
.form { .form {
width: 300px; width: 300px;
font-size: 14px;
button { button {
font-weight: bolder; font-weight: bolder;
@@ -107,7 +112,7 @@
} }
.sign-up, .forget { .sign-up, .forget {
.retry { .retry, .success {
margin-bottom: 16px; margin-bottom: 16px;
a { a {

View File

@@ -37,6 +37,8 @@ export const PERMISSION_TOKEN_RENEW_SUCCESS = 20003
export const PERMISSION_REGISTER_SUCCESS = 20004 export const PERMISSION_REGISTER_SUCCESS = 20004
export const PERMISSION_RESEND_SUCCESS = 20005 export const PERMISSION_RESEND_SUCCESS = 20005
export const PERMISSION_VERIFY_SUCCESS = 20006 export const PERMISSION_VERIFY_SUCCESS = 20006
export const PERMISSION_FORGET_SUCCESS = 20007
export const PERMISSION_RETRIEVE_SUCCESS = 20008
export const PERMISSION_UNAUTHORIZED = 20050 export const PERMISSION_UNAUTHORIZED = 20050
export const PERMISSION_USERNAME_NOT_FOUND = 20051 export const PERMISSION_USERNAME_NOT_FOUND = 20051
@@ -53,6 +55,9 @@ export const PERMISSION_TOKEN_HAS_EXPIRED = 20061
export const PERMISSION_NO_VERIFICATION_REQUIRED = 20062 export const PERMISSION_NO_VERIFICATION_REQUIRED = 20062
export const PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED = 20063 export const PERMISSION_VERIFY_CODE_ERROR_OR_EXPIRED = 20063
export const PERMISSION_ACCOUNT_NEED_INIT = 20064 export const PERMISSION_ACCOUNT_NEED_INIT = 20064
export const PERMISSION_USER_NOT_FOUND = 20065
export const PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED = 20066
export const PERMISSION_ACCOUNT_NEED_RESET_PASSWORD = 20067
export const DATABASE_SELECT_SUCCESS = 30000 export const DATABASE_SELECT_SUCCESS = 30000
export const DATABASE_SELECT_FAILED = 30005 export const DATABASE_SELECT_FAILED = 30005

View File

@@ -1,6 +1,8 @@
export const URL_REGISTER = '/register' export const URL_REGISTER = '/register'
export const URL_RESEND = '/resend' export const URL_RESEND = '/resend'
export const URL_VERIFY = '/verify' export const URL_VERIFY = '/verify'
export const URL_FORGET = '/forget'
export const URL_RETRIEVE = '/retrieve'
export const URL_LOGIN = '/login' export const URL_LOGIN = '/login'
export const URL_TOKEN = '/token' export const URL_TOKEN = '/token'
export const URL_LOGOUT = '/logout' export const URL_LOGOUT = '/logout'

9
src/global.d.ts vendored
View File

@@ -69,6 +69,15 @@ interface VerifyParam {
avatar?: string avatar?: string
} }
interface ForgetParam {
email: string
}
interface RetrieveParam {
code: string
password: string
}
interface LoginParam { interface LoginParam {
account: string account: string
password: string password: string

View File

@@ -10,6 +10,8 @@ import {
PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR, PERMISSION_LOGIN_USERNAME_PASSWORD_ERROR,
PERMISSION_NO_VERIFICATION_REQUIRED, PERMISSION_NO_VERIFICATION_REQUIRED,
PERMISSION_REGISTER_SUCCESS, PERMISSION_REGISTER_SUCCESS,
PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED,
PERMISSION_RETRIEVE_SUCCESS,
PERMISSION_USER_DISABLE, PERMISSION_USER_DISABLE,
PERMISSION_USERNAME_NOT_FOUND PERMISSION_USERNAME_NOT_FOUND
} from '@/constants/common.constants.ts' } from '@/constants/common.constants.ts'
@@ -17,7 +19,14 @@ import { getLoginStatus, getUserInfo, requestUserInfo, setToken } from '@/util/a
import { AppContext } from '@/App' import { AppContext } from '@/App'
import { utcToLocalTime } from '@/util/datetime' import { utcToLocalTime } from '@/util/datetime'
import { useUpdatedEffect } from '@/util/hooks' import { useUpdatedEffect } from '@/util/hooks'
import { r_auth_login, r_auth_register, r_auth_resend, r_auth_verify } from '@/services/auth' import {
r_auth_forget,
r_auth_login,
r_auth_register,
r_auth_resend,
r_auth_retrieve,
r_auth_verify
} from '@/services/auth'
import FitFullscreen from '@/components/common/FitFullscreen' import FitFullscreen from '@/components/common/FitFullscreen'
import FitCenter from '@/components/common/FitCenter' import FitCenter from '@/components/common/FitCenter'
import FlexBox from '@/components/common/FlexBox' import FlexBox from '@/components/common/FlexBox'
@@ -433,15 +442,65 @@ const Verify: React.FC = () => {
const Forget: React.FC = () => { const Forget: React.FC = () => {
const navigate = useNavigate() const navigate = useNavigate()
const [isLoading, setIsLoading] = useState(false) const [searchParams] = useSearchParams()
const [isFinish, setIsFinish] = useState(false) const [isSending, setIsSending] = useState(false)
const [isSent, setIsSent] = useState(false)
const [isChanging, setIsChanging] = useState(false)
const [isChanged, setIsChanged] = useState(false)
const handleOnFinish = () => { const handleOnSend = (forgetParam: ForgetParam) => {
setIsFinish(true) if (isSending) {
return
}
setIsSending(true)
void r_auth_forget(forgetParam)
.then((res) => {
const response = res.data
if (response.success) {
void message.success('已发送验证邮件,请查收')
setIsSent(true)
} else {
void message.error('出错了,请稍后重试')
}
})
.finally(() => {
setIsSending(false)
})
} }
const handleOnRetry = () => { const handleOnRetry = () => {
setIsFinish(false) setIsSent(false)
}
const handleOnChange = (retrieveParam: RetrieveParam) => {
if (isChanging) {
return
}
setIsChanging(true)
void r_auth_retrieve({
code: searchParams.get('code') ?? '',
password: retrieveParam.password
})
.then((res) => {
const response = res.data
switch (response.code) {
case PERMISSION_RETRIEVE_SUCCESS:
void message.success('密码已更新')
setIsChanged(true)
break
case PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED:
void message.error('验证码有误,请重新获取')
break
default:
void message.error('出错了,请稍后重试')
}
})
.finally(() => {
setIsChanging(false)
})
} }
return ( return (
@@ -452,11 +511,13 @@ const Forget: React.FC = () => {
<div className={'primary'}></div> <div className={'primary'}></div>
<div className={'secondary'}>Retrieve password</div> <div className={'secondary'}>Retrieve password</div>
</div> </div>
<AntdForm autoComplete={'on'} onFinish={handleOnFinish} className={'form'}> <div className={'form'}>
{!isFinish ? ( {!searchParams.get('code') ? (
!isSent ? (
<> <>
<AntdForm autoComplete={'on'} onFinish={handleOnSend}>
<AntdForm.Item <AntdForm.Item
name={'account'} name={'email'}
rules={[ rules={[
{ required: true, message: '请输入邮箱' }, { required: true, message: '请输入邮箱' },
{ type: 'email', message: '不是有效的邮箱地址' } { type: 'email', message: '不是有效的邮箱地址' }
@@ -465,7 +526,7 @@ const Forget: React.FC = () => {
<AntdInput <AntdInput
prefix={<Icon component={IconFatwebEmail} />} prefix={<Icon component={IconFatwebEmail} />}
placeholder={'邮箱'} placeholder={'邮箱'}
disabled={isLoading} disabled={isSending}
/> />
</AntdForm.Item> </AntdForm.Item>
<AntdForm.Item> <AntdForm.Item>
@@ -473,31 +534,86 @@ const Forget: React.FC = () => {
style={{ width: '100%' }} style={{ width: '100%' }}
type={'primary'} type={'primary'}
htmlType={'submit'} htmlType={'submit'}
disabled={isLoading} disabled={isSending}
loading={isLoading} loading={isSending}
> >
&ensp;&ensp;&ensp;&ensp; &ensp;&ensp;&ensp;&ensp;
</AntdButton> </AntdButton>
</AntdForm.Item> </AntdForm.Item>
</AntdForm>
</> </>
) : ( ) : (
<div className={'retry'}> <div className={'retry'}>
<a onClick={handleOnRetry}></a> <a onClick={handleOnRetry}></a>
</div> </div>
)
) : !isChanged ? (
<>
<AntdForm autoComplete={'on'} onFinish={handleOnChange}>
<AntdForm.Item
name={'password'}
rules={[
{ required: true, message: '请输入密码' },
{ min: 10, message: '密码至少为10位' },
{ max: 30, message: '密码最多为30位' }
]}
>
<AntdInput.Password
addonBefore={
<span>&nbsp;&nbsp;&nbsp;&nbsp;</span>
}
placeholder={'密码'}
disabled={isChanging}
/>
</AntdForm.Item>
<AntdForm.Item
name={'passwordConfirm'}
rules={[
{ required: true, message: '请确认密码' },
({ getFieldValue }) => ({
validator(_, value) {
if (
!value ||
getFieldValue('password') === value
) {
return Promise.resolve()
}
return Promise.reject(
new Error('两次密码输入必须一致')
)
}
})
]}
>
<AntdInput.Password
addonBefore={'确认密码'}
placeholder={'确认密码'}
disabled={isChanging}
/>
</AntdForm.Item>
<AntdForm.Item>
<AntdButton
style={{ width: '100%' }}
type={'primary'}
htmlType={'submit'}
disabled={isChanging}
loading={isChanging}
>
&ensp;&ensp;&ensp;&ensp;
</AntdButton>
</AntdForm.Item>
</AntdForm>
</>
) : (
<div className={'success'}></div>
)} )}
<div className={'footer'}> <div className={'footer'}>
<a <a onClick={() => navigate(`/login`, { replace: true })}></a>
onClick={() => </div>
navigate(`/login${location.search}`, { replace: true })
}
>
</a>
</div> </div>
</AntdForm>
</FlexBox> </FlexBox>
</FitCenter> </FitCenter>
</div> </div>

View File

@@ -1,8 +1,10 @@
import { import {
URL_FORGET,
URL_LOGIN, URL_LOGIN,
URL_LOGOUT, URL_LOGOUT,
URL_REGISTER, URL_REGISTER,
URL_RESEND, URL_RESEND,
URL_RETRIEVE,
URL_VERIFY URL_VERIFY
} from '@/constants/urls.constants' } from '@/constants/urls.constants'
import request from '@/services' import request from '@/services'
@@ -13,6 +15,10 @@ export const r_auth_resend = () => request.post(URL_RESEND)
export const r_auth_verify = (param: VerifyParam) => request.post(URL_VERIFY, param) export const r_auth_verify = (param: VerifyParam) => request.post(URL_VERIFY, param)
export const r_auth_forget = (param: ForgetParam) => request.post(URL_FORGET, param)
export const r_auth_retrieve = (param: RetrieveParam) => request.post(URL_RETRIEVE, param)
export const r_auth_login = (param: LoginParam) => request.post<TokenVo>(URL_LOGIN, param) export const r_auth_login = (param: LoginParam) => request.post<TokenVo>(URL_LOGIN, param)
export const r_auth_logout = () => request.post(URL_LOGOUT) export const r_auth_logout = () => request.post(URL_LOGOUT)