From d06df946ee95dfb99a6ead6e85f6769cc253e315 Mon Sep 17 00:00:00 2001 From: luxiaotao1123 <t1341870251@gmail.com> Date: 星期日, 09 二月 2025 23:11:49 +0800 Subject: [PATCH] # --- rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java | 2 rsf-admin/src/page/settings/SecuritySettings.jsx | 224 +++++++++++++++++++------------------------- rsf-admin/src/page/settings/BaseSettings.jsx | 14 ++ rsf-admin/src/i18n/zh.js | 17 +++ rsf-admin/src/i18n/en.js | 13 ++ 5 files changed, 137 insertions(+), 133 deletions(-) diff --git a/rsf-admin/src/i18n/en.js b/rsf-admin/src/i18n/en.js index 658395c..d35a323 100644 --- a/rsf-admin/src/i18n/en.js +++ b/rsf-admin/src/i18n/en.js @@ -231,6 +231,19 @@ register: 'REGISTER', }, }, + settings: { + resetPwd: { + currPwd: 'Current Password', + newPwd: 'New Password', + confirmNewPwd: 'Confirm Password', + resetBtn: 'Reset', + tip: { + pwdInputLimit: "New Password must be 6-13 characters long and include both letters and numbers.", + pwdNotSameAsOld: "New Password cannot be the same as the Current Password.", + pwdNotMatch: "New Password and Confirm Password do not match.", + } + } + }, } }; diff --git a/rsf-admin/src/i18n/zh.js b/rsf-admin/src/i18n/zh.js index d724f43..3f15f93 100644 --- a/rsf-admin/src/i18n/zh.js +++ b/rsf-admin/src/i18n/zh.js @@ -227,10 +227,23 @@ tenant: '鍏徃', confirmPwd: '纭瀵嗙爜', button: { - login: 'LOG IN', - register: 'REGISTER', + login: '鐧诲綍', + register: '娉ㄥ唽', }, }, + settings: { + resetPwd: { + currPwd: '褰撳墠瀵嗙爜', + newPwd: '鏂板瘑鐮�', + confirmNewPwd: '纭鏂板瘑鐮�', + resetBtn: '閲嶇疆瀵嗙爜', + tip: { + pwdInputLimit: "瀵嗙爜蹇呴』涓�6-13浣�,涓斿繀椤诲寘鍚瓧姣嶅拰鏁板瓧", + pwdNotSameAsOld: "鏂板瘑鐮佷笉鑳戒笌褰撳墠瀵嗙爜鐩稿悓", + pwdNotMatch: "纭瀵嗙爜涓嶄竴鑷�", + } + } + }, } }; diff --git a/rsf-admin/src/page/settings/BaseSettings.jsx b/rsf-admin/src/page/settings/BaseSettings.jsx index bb680be..775e0d5 100644 --- a/rsf-admin/src/page/settings/BaseSettings.jsx +++ b/rsf-admin/src/page/settings/BaseSettings.jsx @@ -26,7 +26,19 @@ const notify = useNotify(); const { children, userInfo } = props; - const { control, handleSubmit, watch, setValue, getValues, formState: { isDirty } } = useForm(); + const { + control, + handleSubmit, + watch, + setValue, + getValues, + reset, + formState: { + errors, + isDirty, + } + } = useForm(); + const [loading, setLoading] = useState(false); useEffect(() => { diff --git a/rsf-admin/src/page/settings/SecuritySettings.jsx b/rsf-admin/src/page/settings/SecuritySettings.jsx index 0943613..9ef9bd9 100644 --- a/rsf-admin/src/page/settings/SecuritySettings.jsx +++ b/rsf-admin/src/page/settings/SecuritySettings.jsx @@ -6,58 +6,55 @@ import { useForm, Controller, useWatch, FormProvider, useFormContext } from "react-hook-form"; import { Stack, - Grid, Box, Typography, TextField, Button, - FormControl, - InputLabel, - Select, - MenuItem, - FormHelperText, CircularProgress, + InputAdornment, + IconButton, } from '@mui/material'; import { updateUserInfo } from '@/api/auth'; -import avatar from '/avatar.jpg' +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; const SecuritySettings = (props) => { const translate = useTranslate(); const notify = useNotify(); - const { children, userInfo } = props; + const { userInfo } = props; - const { control, handleSubmit, watch, setValue, getValues, formState: { isDirty } } = useForm(); + const { control, handleSubmit, watch, setValue, getValues, reset, formState: { errors }, setError } = useForm(); + + const oldPasswordVal = watch('oldPassword'); + const newPasswordVal = watch('newPassword'); + const confirmPasswordVal = watch('confirmPassword'); + const [loading, setLoading] = useState(false); + const [showOldPassword, setShowOldPassword] = useState(false); + const [showNewPassword, setShowNewPassword] = useState(false); useEffect(() => { if (userInfo) { - setValue("username", userInfo.username || "", { shouldDirty: false }); - setValue("nickname", userInfo.nickname || "", { shouldDirty: false }); - setValue("sex", userInfo.sex ?? "", { shouldDirty: false }); - setValue("code", userInfo.code || "", { shouldDirty: false }); - setValue("phone", userInfo.phone || "", { shouldDirty: false }); - setValue("email", userInfo.email || "", { shouldDirty: false }); - setValue("realName", userInfo.realName || "", { shouldDirty: false }); - setValue("idCard", userInfo.idCard || "", { shouldDirty: false }); } }, [userInfo, setValue]) const onSubmit = (data) => { + console.log(data); + return false; + setLoading(true); updateUserInfo({ id: userInfo.id, ...data }).then(res => { setLoading(false); const { code, msg, data } = res; if (code === 200) { notify(msg, { type: 'success', messageArgs: { _: msg } }); - const userToPersist = { - avatar: avatar, - fullName: data.nickname, - id: data.id, - username: data.username - } - localStorage.setItem("user", JSON.stringify(userToPersist)); + reset(); } else { notify(msg, { type: 'error', messageArgs: { _: msg } }); + setError('oldPassword', { + type: 'server', // make no sense + message: res.msg, + }); } }).catch((error) => { setLoading(false); @@ -84,156 +81,125 @@ }} > <Controller - name="username" + name="oldPassword" control={control} defaultValue="" - rules={{ required: true }} + rules={{ required: translate('ra.validation.required') }} render={({ field, fieldState: { error } }) => ( <TextField {...field} - label={translate('table.field.user.username')} + label={translate('page.settings.resetPwd.currPwd')} + type={showOldPassword ? 'text' : 'password'} variant="outlined" autoComplete="off" - helperText={error ? translate('ra.validation.required') : ""} - disabled + error={Boolean(errors.oldPassword)} + helperText={errors.oldPassword?.message || ""} + InputProps={{ + endAdornment: ( + <InputAdornment position="end"> + <IconButton + aria-label="toggle password visibility" + onClick={() => setShowOldPassword((show) => !show)} + onMouseDown={(event) => { event.preventDefault() }} + edge="end" + > + {showOldPassword ? <VisibilityOff /> : <Visibility />} + </IconButton> + </InputAdornment> + ), + }} /> )} /> <Controller - name="nickname" - control={control} - defaultValue="" - rules={{ required: true }} - render={({ field, fieldState: { error } }) => ( - <TextField - {...field} - label={translate('table.field.user.nickname')} - variant="outlined" - autoComplete="off" - error={!!error} - helperText={error ? translate('ra.validation.required') : ""} - /> - )} - /> - <Controller - name="sex" - control={control} - defaultValue="" - rules={{ required: true }} - render={({ field, fieldState: { error } }) => ( - <FormControl fullWidth variant="outlined" error={!!error}> - <InputLabel>{translate('table.field.user.sex')}</InputLabel> - <Select - {...field} - label={translate('table.field.user.sex')} - > - <MenuItem value={0}> - <em>{translate('table.field.user.sexes.unknown')}</em> - </MenuItem> - <MenuItem value={1}>{translate('table.field.user.sexes.male')}</MenuItem> - <MenuItem value={2}>{translate('table.field.user.sexes.female')}</MenuItem> - </Select> - {error && <FormHelperText>{translate('ra.validation.required')}</FormHelperText>} - </FormControl> - )} - /> - <Controller - name="code" - control={control} - defaultValue="" - rules={{ required: false }} - render={({ field, fieldState: { error } }) => ( - <TextField - {...field} - label={translate('table.field.user.code')} - variant="outlined" - autoComplete="off" - error={!!error} - helperText={error ? translate('ra.validation.required') : ""} - /> - )} - /> - <Controller - name="phone" - control={control} - defaultValue="" - rules={{ required: false }} - render={({ field, fieldState: { error } }) => ( - <TextField - {...field} - label={translate('table.field.user.phone')} - variant="outlined" - autoComplete="off" - error={!!error} - helperText={error ? translate('ra.validation.required') : ""} - /> - )} - /> - <Controller - name="email" + name="newPassword" control={control} defaultValue="" rules={{ - required: false, + required: translate('ra.validation.required'), pattern: { - value: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, - message: translate("ra.validation.email"), + value: /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{6,13}$/, + message: translate('page.settings.resetPwd.tip.pwdInputLimit'), }, + validate: (value) => { + if (value === oldPasswordVal) { + return translate('page.settings.resetPwd.tip.pwdNotSameAsOld'); + } + return true; + } }} render={({ field, fieldState: { error } }) => ( <TextField {...field} - label={translate('table.field.user.email')} + label={translate('page.settings.resetPwd.newPwd')} + type={showNewPassword ? 'text' : 'password'} variant="outlined" autoComplete="off" - error={!!error} - helperText={error ? error.message : ""} + error={Boolean(errors.newPassword)} + helperText={errors.newPassword?.message || ""} + InputProps={{ + endAdornment: ( + <InputAdornment position="end"> + <IconButton + aria-label="toggle password visibility" + onClick={() => setShowNewPassword((show) => !show)} + onMouseDown={(event) => { event.preventDefault() }} + edge="end" + > + {showNewPassword ? <VisibilityOff /> : <Visibility />} + </IconButton> + </InputAdornment> + ), + }} /> )} /> <Controller - name="realName" + name="confirmPassword" control={control} defaultValue="" - rules={{ required: false }} + rules={{ + required: translate('ra.validation.required'), + validate: value => + value === newPasswordVal || translate('page.settings.resetPwd.tip.pwdNotMatch'), + }} render={({ field, fieldState: { error } }) => ( <TextField {...field} - label={translate('table.field.user.realName')} + label={translate('page.settings.resetPwd.confirmNewPwd')} + type={showNewPassword ? 'text' : 'password'} variant="outlined" autoComplete="off" - error={!!error} - helperText={error ? translate('ra.validation.required') : ""} - /> - )} - /> - <Controller - name="idCard" - control={control} - defaultValue="" - rules={{ required: false }} - render={({ field, fieldState: { error } }) => ( - <TextField - {...field} - label={translate('table.field.user.idCard')} - variant="outlined" - autoComplete="off" - error={!!error} - helperText={error ? translate('ra.validation.required') : ""} + error={Boolean(errors.confirmPassword)} + helperText={errors.confirmPassword?.message || ""} + InputProps={{ + endAdornment: ( + <InputAdornment position="end"> + <IconButton + aria-label="toggle password visibility" + onClick={() => setShowNewPassword((show) => !show)} + onMouseDown={(event) => { event.preventDefault() }} + edge="end" + > + {showNewPassword ? <VisibilityOff /> : <Visibility />} + </IconButton> + </InputAdornment> + ), + }} /> )} /> <Button type="submit" variant="contained" - disabled={loading || !isDirty} + disabled={loading || !(oldPasswordVal && newPasswordVal && confirmPasswordVal)} sx={{ alignSelf: 'flex-start', width: '120px' }} > {loading && <CircularProgress size={25} thickness={2} />} - {translate('ra.action.save')} + {translate('page.settings.resetPwd.resetBtn')} </Button> </Stack> </form> diff --git a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java index 383a5b0..7e7c009 100644 --- a/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java +++ b/rsf-server/src/main/java/com/vincent/rsf/server/system/controller/AuthController.java @@ -107,7 +107,7 @@ @OperationLog("Reset Password") @PostMapping("/auth/password") - public R updatePassword(@RequestBody UpdatePasswordParam param) { + public R resetPassword(@RequestBody UpdatePasswordParam param) { if (Cools.isEmpty(param.getOldPassword(), param.getPassword())) { return R.error("Parameters Cannot Be Empty"); } -- Gitblit v1.9.1