From 2fd817916072018b631c4f608c75ff455efb42a6 Mon Sep 17 00:00:00 2001
From: vincentlu <t1341870251@gmail.com>
Date: 星期四, 13 二月 2025 16:36:11 +0800
Subject: [PATCH] #
---
rsf-admin/src/page/login/Register.jsx | 173 ++++++++++++++++++++++++++++++++-----------
rsf-admin/src/i18n/zh.js | 5 +
rsf-admin/src/i18n/en.js | 3
3 files changed, 136 insertions(+), 45 deletions(-)
diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js
index d3640ec..808c6b5 100644
--- a/rsf-admin/src/i18n/en.js
+++ b/rsf-admin/src/i18n/en.js
@@ -229,9 +229,11 @@
title: 'Welcome',
footer: 'Footer Goes Here',
tenant: 'Company',
+ email: 'Email Address',
username: 'Username',
password: 'Password',
confirmPwd: 'Confirm Password',
+ code: 'Verification Code',
tab: {
login: 'SIGN IN',
register: 'SIGN UP',
@@ -239,6 +241,7 @@
button: {
login: 'SIGN IN',
register: 'SIGN UP',
+ code: 'Send Code',
},
},
settings: {
diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js
index 4b5ae98..905a832 100644
--- a/rsf-admin/src/i18n/zh.js
+++ b/rsf-admin/src/i18n/zh.js
@@ -229,9 +229,11 @@
title: '娆㈣繋浣跨敤',
footer: 'Footer Goes Here',
tenant: '鍏徃',
- username: '璐﹀彿',
+ email: '閭鍦板潃',
+ username: '鐧诲綍璐﹀彿',
password: '瀵嗙爜',
confirmPwd: '纭瀵嗙爜',
+ code: '楠岃瘉鐮�',
tab: {
login: '鐧诲綍',
register: '娉ㄥ唽',
@@ -239,6 +241,7 @@
button: {
login: '鐧诲綍',
register: '娉ㄥ唽',
+ code: '鑾峰彇楠岃瘉鐮�',
},
},
settings: {
diff --git a/rsf-admin/src/page/login/Register.jsx b/rsf-admin/src/page/login/Register.jsx
index 3e19a4f..881f5be 100644
--- a/rsf-admin/src/page/login/Register.jsx
+++ b/rsf-admin/src/page/login/Register.jsx
@@ -26,23 +26,54 @@
const notify = useNotify();
const login = useLogin();
const location = useLocation();
- const { systemInfo, tenantList } = props;
+ const { systemInfo } = props;
const { control, watch, handleSubmit, setValue } = useForm();
+
+ const email = watch('email');
+ const username = watch('username');
+ const password = watch('password');
+ const confirmPassword = watch('confirmPassword');
const [loading, setLoading] = useState(false);
const [showPassword, setShowPassword] = useState(true);
- const username = watch('username');
- const password = watch('password');
- const confirmPassword = watch('confirmPassword');
- const tenantId = watch('tenantId');
- useEffect(() => {
- if (tenantList.length > 0 && !tenantId) {
- setValue('tenantId', tenantList[0].id);
+ const [isCounting, setIsCounting] = useState(false);
+ const [countdown, setCountdown] = useState(60);
+
+ // 澶勭悊楠岃瘉鐮佹寜閽偣鍑�
+ const handleSendCode = async () => {
+ // 杩欓噷鍋囪鍙戦�侀獙璇佺爜鐨勮姹�
+ const response = await fetch('/api/send-code');
+ if (response.ok) {
+ setIsCounting(true);
+ localStorage.setItem('codeCountdown', 60); // 瀛樺偍鍊掕鏃跺埌鏈湴
}
- }, [tenantList, setValue]);
+ };
+
+ // 鍊掕鏃跺姛鑳�
+ useEffect(() => {
+ const savedCountdown = localStorage.getItem('codeCountdown');
+ if (savedCountdown && !isCounting) {
+ setCountdown(Number(savedCountdown));
+ 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'); // 閲嶇疆
+ }
+ }, 1000);
+
+ return () => clearInterval(interval);
+ }, [countdown, isCounting]);
+
const onSubmit = (data) => {
notify("Registration is not open yet");
@@ -85,34 +116,6 @@
>
<Stack spacing={2}>
<Controller
- name="tenantId"
- control={control}
- rules={{ required: true }}
- defaultValue={tenantList.length > 0 ? tenantList[0].id : ''}
- render={({ field: { onChange, value, ref } }) => {
- const selectedTenant = tenantList.find(tenant => tenant.id === value) || null;
- return (
- <Autocomplete
- options={tenantList}
- getOptionLabel={(option) => option.name}
- value={selectedTenant}
- onChange={(_, newValue) => {
- onChange(newValue ? newValue.id : '');
- }}
- renderInput={(params) => (
- <TextField
- {...params}
- label={translate("page.login.tenant")}
- variant="standard"
- inputRef={ref}
- />
- )}
- />
- );
- }}
- />
-
- <Controller
name="username"
control={control}
defaultValue=""
@@ -120,7 +123,7 @@
render={({ field }) => (
<TextField
{...field}
- label={translate('ra.auth.username')}
+ label={translate("page.login.username")}
variant="standard"
disabled={loading}
autoFocus
@@ -133,15 +136,23 @@
name="password"
control={control}
defaultValue=""
- rules={{ required: true }}
- render={({ field }) => (
+ rules={{
+ required: translate('ra.validation.required'),
+ pattern: {
+ value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d\.]{6,13}$/,
+ message: translate('page.settings.resetPwd.tip.pwdInputLimit'),
+ },
+ }}
+ render={({ field, fieldState: { error } }) => (
<TextField
{...field}
- label={translate('ra.auth.password')}
+ label={translate("page.login.password")}
type={showPassword ? 'text' : 'password'}
variant="standard"
disabled={loading}
autoComplete="off"
+ error={!!error}
+ helperText={error?.message || ""}
InputProps={{
endAdornment: (
<InputAdornment position="end">
@@ -164,8 +175,12 @@
name="confirmPassword"
control={control}
defaultValue=""
- rules={{ required: true }}
- render={({ field }) => (
+ rules={{
+ required: translate('ra.validation.required'),
+ validate: value =>
+ value === password || translate('page.settings.resetPwd.tip.pwdNotMatch'),
+ }}
+ render={({ field, fieldState: { error } }) => (
<TextField
{...field}
label={translate('page.login.confirmPwd')}
@@ -173,6 +188,8 @@
variant="standard"
disabled={loading}
autoComplete="off"
+ error={!!error}
+ helperText={error?.message || ""}
InputProps={{
endAdornment: (
<InputAdornment position="end">
@@ -191,12 +208,80 @@
)}
/>
+ <Controller
+ name="email"
+ control={control}
+ defaultValue=""
+ rules={{
+ required: translate('ra.validation.required'),
+ pattern: {
+ value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
+ message: translate("ra.validation.email"),
+ },
+ }}
+ render={({ field, fieldState: { error } }) => (
+ <TextField
+ {...field}
+ label={translate('page.login.email')}
+ variant="standard"
+ disabled={loading}
+ // autoComplete="off"
+ error={!!error}
+ helperText={error ? error.message : ""}
+ />
+ )}
+ />
+
+ <Box display="flex" alignItems="center" justifyContent='center' width="100%">
+ <Controller
+ name="code"
+ control={control}
+ defaultValue=""
+ rules={{
+ required: translate('ra.validation.required'),
+ }}
+ render={({ field, fieldState: { error } }) => (
+ <TextField
+ {...field}
+ label={translate('page.login.code')}
+ variant="standard"
+ disabled={loading}
+ autoComplete="off"
+ error={!!error}
+ helperText={error ? error.message : ""}
+ sx={{
+ width: '65%',
+ mr: 2,
+ }}
+ />
+ )}
+ />
+
+ <Button
+ variant="outlined"
+ onClick={handleSendCode}
+ disabled={isCounting || loading}
+ sx={{
+ mt: 1,
+ }}
+ >
+ {isCounting ? (
+ <>
+ <CircularProgress size={20} color="primary" sx={{ marginRight: 1 }} />
+ {`${countdown}s`}
+ </>
+ ) : (
+ translate('page.login.button.code')
+ )}
+ </Button>
+ </Box>
+
<Box />
<Button
type="submit"
variant="contained"
- disabled={loading || !(tenantId && username && password && confirmPassword)}
+ disabled={loading || !(email && username && password && confirmPassword)}
sx={{
backgroundColor: "#3D4BA7"
}}
--
Gitblit v1.9.1