From 6883e31331af4633d1b7d74ea7deb5f972afa05d Mon Sep 17 00:00:00 2001 From: skyouc Date: 星期五, 23 五月 2025 20:02:19 +0800 Subject: [PATCH] 新增移库功能 --- rsf-admin/src/page/login/Register.jsx | 151 ++++++++++++++++++++++++++++++++------------------ 1 files changed, 96 insertions(+), 55 deletions(-) diff --git a/rsf-admin/src/page/login/Register.jsx b/rsf-admin/src/page/login/Register.jsx index 881f5be..c4169db 100644 --- a/rsf-admin/src/page/login/Register.jsx +++ b/rsf-admin/src/page/login/Register.jsx @@ -15,11 +15,13 @@ useTranslate, useLogin, useNotify, + email as validEmail, } from 'react-admin'; import { useForm, Controller } from 'react-hook-form'; import ProviderChoices from "./ProviderChoices"; import Visibility from '@mui/icons-material/Visibility'; import VisibilityOff from '@mui/icons-material/VisibilityOff'; +import { sendEmailCode, register } from '@/api/auth'; const Register = (props) => { const translate = useTranslate(); @@ -28,82 +30,116 @@ const location = useLocation(); const { systemInfo } = props; - const { control, watch, handleSubmit, setValue } = useForm(); + const { control, watch, handleSubmit, setValue, setError, clearErrors } = useForm(); const email = watch('email'); const username = watch('username'); const password = watch('password'); const confirmPassword = watch('confirmPassword'); + const code = watch('code'); const [loading, setLoading] = useState(false); + const [codeLoading, setCodeLoading] = useState(false); const [showPassword, setShowPassword] = useState(true); - - const [isCounting, setIsCounting] = useState(false); const [countdown, setCountdown] = useState(60); - // 澶勭悊楠岃瘉鐮佹寜閽偣鍑� + // send code const handleSendCode = async () => { - // 杩欓噷鍋囪鍙戦�侀獙璇佺爜鐨勮姹� - const response = await fetch('/api/send-code'); - if (response.ok) { - setIsCounting(true); - localStorage.setItem('codeCountdown', 60); // 瀛樺偍鍊掕鏃跺埌鏈湴 + if (!email) { + setError("email", { + message: translate('ra.validation.required') + }) + return; } + const emailError = validEmail()(email); + if (emailError) { + setError("email", { + message: translate("ra.validation.email") + }) + return; + } + clearErrors("email"); + setCodeLoading(true); + sendEmailCode({ email }).then(res => { + setCodeLoading(false); + const { code, msg, data } = res; + if (code === 200) { + notify(msg, { type: 'success', messageArgs: { _: msg } }); + + const timestamp = Math.floor(Date.now() / 1000); + const expirationTime = timestamp + 60; + localStorage.setItem('codeExpirationTime', expirationTime); + + setIsCounting(true); + setCountdown(60); + } else if (code === 10005 || code === 10006) { + setError('email', { + message: msg + }) + } else { + notify(msg, { type: 'error', messageArgs: { _: msg } }); + } + }).catch((error) => { + setCodeLoading(false); + notify(error.message, { type: 'error', messageArgs: { _: error.message } }); + console.error(error); + }) }; - // 鍊掕鏃跺姛鑳� + // countdown useEffect(() => { - const savedCountdown = localStorage.getItem('codeCountdown'); - if (savedCountdown && !isCounting) { - setCountdown(Number(savedCountdown)); - setIsCounting(true); + const codeExpirationTime = localStorage.getItem('codeExpirationTime'); + if (codeExpirationTime) { + const currentTimestamp = Math.floor(Date.now() / 1000); + const remainingTime = codeExpirationTime - currentTimestamp; + if (remainingTime > 0) { + setCountdown(remainingTime); + setIsCounting(true); + } } const interval = setInterval(() => { if (isCounting && countdown > 0) { setCountdown(prev => prev - 1); - localStorage.setItem('codeCountdown', countdown - 1); } else if (countdown <= 0) { clearInterval(interval); setIsCounting(false); - localStorage.removeItem('codeCountdown'); // 閲嶇疆 + localStorage.removeItem('codeExpirationTime'); } }, 1000); return () => clearInterval(interval); }, [countdown, isCounting]); - - const onSubmit = (data) => { - notify("Registration is not open yet"); - return; + // register + const onSubmit = (params) => { setLoading(true); - // js native confirm && root - login( - data, - location.state ? (location.state).nextPathname : '/' - ).catch((error) => { + register(params).then(res => { setLoading(false); - notify( - typeof error === 'string' - ? error - : typeof error === 'undefined' || !error.message - ? 'ra.auth.sign_in_error' - : error.message, - { - type: 'error', - messageArgs: { - _: - typeof error === 'string' - ? error - : error && error.message - ? error.message - : undefined, - }, - } - ); - }); + const { code, msg, data } = res; + if (code === 200) { + notify(msg, { type: 'success', messageArgs: { _: msg } }); + // to login + login( + params, + location.state ? (location.state).nextPathname : '/' + ).catch(({ code, msg }) => { + setLoading(false); + notify(msg, { type: 'error', messageArgs: { _: msg } }); + }); + } else if (code === 10002) { + setError("username", { + message: msg + }) + } else { + notify(msg, { type: 'error', messageArgs: { _: msg } }); + } + }).catch((error) => { + setLoading(false); + notify(error.message, { type: 'error', messageArgs: { _: error.message } }); + console.error(error); + }) }; return ( @@ -120,7 +156,7 @@ control={control} defaultValue="" rules={{ required: true }} - render={({ field }) => ( + render={({ field, fieldState: { error } }) => ( <TextField {...field} label={translate("page.login.username")} @@ -128,6 +164,8 @@ disabled={loading} autoFocus autoComplete="off" + error={!!error} + helperText={error?.message || ""} /> )} /> @@ -260,19 +298,22 @@ <Button variant="outlined" onClick={handleSendCode} - disabled={isCounting || loading} + disabled={codeLoading || isCounting} sx={{ + width: '35%', mt: 1, + whiteSpace: 'nowrap', }} > - {isCounting ? ( - <> - <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} /> - {`${countdown}s`} - </> - ) : ( - translate('page.login.button.code') - )} + {codeLoading ? ( + <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} /> + ) : + isCounting ? ( + `${countdown}s` + ) : ( + translate('page.login.button.code') + ) + } </Button> </Box> @@ -281,7 +322,7 @@ <Button type="submit" variant="contained" - disabled={loading || !(email && username && password && confirmPassword)} + disabled={loading || !(email && username && password && confirmPassword && code)} sx={{ backgroundColor: "#3D4BA7" }} -- Gitblit v1.9.1