Complete main UI #37

Merged
FatttSnake merged 192 commits from FatttSnake into dev 2024-02-23 16:31:17 +08:00
4 changed files with 143 additions and 47 deletions
Showing only changes of commit edf5f08828 - Show all commits

View File

@@ -30,6 +30,7 @@ export const SYSTEM_TIMEOUT = 10051
export const SYSTEM_REQUEST_ILLEGAL = 10052
export const SYSTEM_ARGUMENT_NOT_VALID = 10053
export const SYSTEM_INVALID_CAPTCHA_CODE = 10054
export const SYSTEM_REQUEST_TOO_FREQUENT = 10055
export const PERMISSION_LOGIN_SUCCESS = 20000
export const PERMISSION_PASSWORD_CHANGE_SUCCESS = 20001

3
src/global.d.ts vendored
View File

@@ -62,6 +62,7 @@ interface RegisterParam {
username: string
email: string
password: string
captchaCode: string
}
interface VerifyParam {
@@ -72,11 +73,13 @@ interface VerifyParam {
interface ForgetParam {
email: string
captchaCode: string
}
interface RetrieveParam {
code: string
password: string
captchaCode: string
}
interface LoginParam {

View File

@@ -1,7 +1,7 @@
import React, { useState } from 'react'
import { useNavigate } from 'react-router'
import Icon from '@ant-design/icons'
import { Turnstile } from '@marsidev/react-turnstile'
import { Turnstile, TurnstileInstance } from '@marsidev/react-turnstile'
import '@/assets/css/pages/sign.scss'
import {
COLOR_BACKGROUND,
@@ -41,9 +41,11 @@ import { r_api_avatar_random_base64 } from '@/services/api/avatar.tsx'
const SignUp: React.FC = () => {
const location = useLocation()
const navigate = useNavigate()
const turnstileRef = useRef<TurnstileInstance>()
const [isSigningUp, setIsSigningUp] = useState(false)
const [isFinish, setIsFinish] = useState(false)
const [isSending, setIsSending] = useState(false)
const [captchaCode, setCaptchaCode] = useState('')
useUpdatedEffect(() => {
if (location.pathname !== '/register') {
@@ -54,6 +56,9 @@ const SignUp: React.FC = () => {
replace: true
})
}
setTimeout(() => {
turnstileRef.current?.execute()
}, 200)
}, [location.pathname])
const handleOnFinish = (registerParam: RegisterParam) => {
@@ -61,10 +66,18 @@ const SignUp: React.FC = () => {
return
}
setIsSigningUp(true)
if (!captchaCode) {
void message.warning('请先通过验证')
setIsSigningUp(false)
return
}
void r_auth_register({
username: registerParam.username,
email: registerParam.email,
password: registerParam.password
password: registerParam.password,
captchaCode
})
.then((res) => {
const response = res.data
@@ -78,6 +91,9 @@ const SignUp: React.FC = () => {
void message.error('用户名或邮箱已被注册,请重试')
setIsSigningUp(false)
break
case SYSTEM_INVALID_CAPTCHA_CODE:
void message.error('验证码有误,请刷新重试')
break
default:
void message.error('服务器出错了,请稍后重试')
setIsSigningUp(false)
@@ -97,7 +113,6 @@ const SignUp: React.FC = () => {
void r_auth_resend()
.then((res) => {
const response = res.data
message.destroy('sending')
if (response.success) {
void message.success('已发送验证邮件,请查收')
} else {
@@ -105,6 +120,7 @@ const SignUp: React.FC = () => {
}
})
.finally(() => {
message.destroy('sending')
setIsSending(false)
})
}
@@ -189,6 +205,15 @@ const SignUp: React.FC = () => {
disabled={isSigningUp}
/>
</AntdForm.Item>
<AntdForm.Item>
<Turnstile
id={'sign-up-turnstile'}
ref={turnstileRef}
siteKey={H_CAPTCHA_SITE_KEY}
options={{ theme: 'light', execution: 'execute' }}
onSuccess={setCaptchaCode}
/>
</AntdForm.Item>
<AntdForm.Item>
<AntdButton
style={{ width: '100%' }}
@@ -286,7 +311,6 @@ const Verify: React.FC = () => {
void r_auth_resend()
.then((res) => {
const response = res.data
message.destroy('sending')
if (response.success) {
void message.success('已发送验证邮件,请查收')
} else {
@@ -294,6 +318,7 @@ const Verify: React.FC = () => {
}
})
.finally(() => {
message.destroy('sending')
setIsSending(false)
})
}
@@ -435,10 +460,28 @@ const Verify: React.FC = () => {
const Forget: React.FC = () => {
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const turnstileRef = useRef<TurnstileInstance>()
const retrieveTurnstileRef = useRef<TurnstileInstance>()
const [isSending, setIsSending] = useState(false)
const [isSent, setIsSent] = useState(false)
const [isChanging, setIsChanging] = useState(false)
const [isChanged, setIsChanged] = useState(false)
const [captchaCode, setCaptchaCode] = useState('')
const [retrieveCpatchaCode, setRetrieveCpatchaCode] = useState('')
useUpdatedEffect(() => {
if (location.pathname !== '/forget') {
return
}
setTimeout(() => {
if (!searchParams.get('code')) {
turnstileRef.current?.execute()
} else {
retrieveTurnstileRef.current?.execute()
}
}, 200)
}, [location.pathname])
const handleOnSend = (forgetParam: ForgetParam) => {
if (isSending) {
@@ -446,28 +489,40 @@ const Forget: React.FC = () => {
}
setIsSending(true)
void r_auth_forget(forgetParam)
.then((res) => {
if (!captchaCode) {
void message.warning('请先通过验证')
setIsSending(false)
return
}
void r_auth_forget({ email: forgetParam.email, captchaCode }).then((res) => {
const response = res.data
switch (response.code) {
case PERMISSION_FORGET_SUCCESS:
void message.success('已发送验证邮件,请查收')
setIsSent(true)
setIsSending(false)
break
case PERMISSION_USER_NOT_FOUND:
void message.error('用户不存在')
setIsSending(false)
break
case SYSTEM_INVALID_CAPTCHA_CODE:
void message.error('验证码有误,请刷新重试')
break
default:
void message.error('出错了,请稍后重试')
}
})
.finally(() => {
setIsSending(false)
}
})
}
const handleOnRetry = () => {
setIsSent(false)
setTimeout(() => {
turnstileRef.current?.execute()
}, 200)
}
const handleOnChange = (retrieveParam: RetrieveParam) => {
@@ -478,25 +533,28 @@ const Forget: React.FC = () => {
void r_auth_retrieve({
code: searchParams.get('code') ?? '',
password: retrieveParam.password
})
.then((res) => {
password: retrieveParam.password,
captchaCode: retrieveCpatchaCode
}).then((res) => {
const response = res.data
switch (response.code) {
case PERMISSION_RETRIEVE_SUCCESS:
void message.success('密码已更新')
setIsChanged(true)
setIsChanging(false)
break
case PERMISSION_RETRIEVE_CODE_ERROR_OR_EXPIRED:
void message.error('验证码有误,请重新获取')
void message.error('请重新获取邮件')
setIsChanging(false)
break
case SYSTEM_INVALID_CAPTCHA_CODE:
void message.error('验证码有误,请刷新重试')
break
default:
void message.error('出错了,请稍后重试')
}
})
.finally(() => {
setIsChanging(false)
}
})
}
@@ -526,6 +584,15 @@ const Forget: React.FC = () => {
disabled={isSending}
/>
</AntdForm.Item>
<AntdForm.Item>
<Turnstile
id={'forget-turnstile'}
ref={turnstileRef}
siteKey={H_CAPTCHA_SITE_KEY}
options={{ theme: 'light', execution: 'execute' }}
onSuccess={setCaptchaCode}
/>
</AntdForm.Item>
<AntdForm.Item>
<AntdButton
style={{ width: '100%' }}
@@ -589,6 +656,15 @@ const Forget: React.FC = () => {
disabled={isChanging}
/>
</AntdForm.Item>
<AntdForm.Item>
<Turnstile
id={'retrieve-turnstile'}
ref={retrieveTurnstileRef}
siteKey={H_CAPTCHA_SITE_KEY}
options={{ theme: 'light', execution: 'execute' }}
onSuccess={setRetrieveCpatchaCode}
/>
</AntdForm.Item>
<AntdForm.Item>
<AntdButton
style={{ width: '100%' }}
@@ -621,12 +697,18 @@ const SignIn: React.FC = () => {
const { refreshRouter } = useContext(AppContext)
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const turnstileRef = useRef<TurnstileInstance>()
const [isSigningIn, setIsSigningIn] = useState(false)
const [captchaCode, setCaptchaCode] = useState('')
const handleOnTurnstileSuccess = (token: string) => {
setCaptchaCode(token)
useUpdatedEffect(() => {
if (location.pathname !== '/login') {
return
}
setTimeout(() => {
turnstileRef.current?.execute()
}, 200)
}, [location.pathname])
const handleOnFinish = (loginParam: LoginParam) => {
if (isSigningIn) {
@@ -749,9 +831,11 @@ const SignIn: React.FC = () => {
</AntdForm.Item>
<AntdForm.Item>
<Turnstile
id={'sign-in-turnstile'}
ref={turnstileRef}
siteKey={H_CAPTCHA_SITE_KEY}
options={{ theme: 'light' }}
onSuccess={handleOnTurnstileSuccess}
options={{ theme: 'light', execution: 'execute' }}
onSuccess={setCaptchaCode}
/>
</AntdForm.Item>
<FlexBox direction={'horizontal'} className={'addition'}>

View File

@@ -5,7 +5,8 @@ import {
PERMISSION_TOKEN_HAS_EXPIRED,
PERMISSION_TOKEN_ILLEGAL,
PERMISSION_TOKEN_RENEW_SUCCESS,
PERMISSION_UNAUTHORIZED
PERMISSION_UNAUTHORIZED,
SYSTEM_REQUEST_TOO_FREQUENT
} from '@/constants/common.constants'
import { getRedirectUrl } from '@/util/route'
import { getToken, setToken, removeToken } from '@/util/auth'
@@ -97,6 +98,13 @@ service.interceptors.response.use(
</>
)
throw response?.data
case SYSTEM_REQUEST_TOO_FREQUENT:
void message.warning(
<>
<strong></strong>
</>
)
throw response?.data
}
return response
},