From fc0b7b2cc9f0ec0af82c4e1ebccba023878a4aca Mon Sep 17 00:00:00 2001 From: "guangfei.zhao" Date: Tue, 18 Nov 2025 11:15:09 +0800 Subject: [PATCH] feat(login): add password visibility toggle and confirm password field --- src/hooks/login-hooks.ts | 11 ++++++- src/locales/en.ts | 1 + src/locales/zh.ts | 1 + src/pages/login/Login.tsx | 68 +++++++++++++++++++++++++++++++++++++-- 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/src/hooks/login-hooks.ts b/src/hooks/login-hooks.ts index 7594530..89d57fb 100644 --- a/src/hooks/login-hooks.ts +++ b/src/hooks/login-hooks.ts @@ -169,6 +169,7 @@ export interface RegisterFormData { email: string; password: string; nickname: string; + confirmPassword: string; } /** @@ -315,7 +316,8 @@ export const useLoginForm = () => { defaultValues: { email: '', password: '', - nickname: '' + nickname: '', + confirmPassword: '' } }); @@ -395,6 +397,13 @@ export const useLoginForm = () => { value: 8, message: t('setting.passwordMinLength') } + }, + confirmPassword: { + required: t('confirmPasswordRequired'), + validate: (value: string) => { + const pwd = registerForm.getValues('password'); + return value === pwd || t('setting.passwordMismatch'); + } } } }; diff --git a/src/locales/en.ts b/src/locales/en.ts index d149e73..bbe6b36 100644 --- a/src/locales/en.ts +++ b/src/locales/en.ts @@ -258,6 +258,7 @@ export default { registerDescription: 'Glad to have you on board!', emailLabel: 'Email', emailPlaceholder: 'Please input email', + emailInvalid: 'Invalid email address', passwordLabel: 'Password', passwordPlaceholder: 'Please input password', rememberMe: 'Remember me', diff --git a/src/locales/zh.ts b/src/locales/zh.ts index 87a3657..8507dca 100644 --- a/src/locales/zh.ts +++ b/src/locales/zh.ts @@ -240,6 +240,7 @@ export default { registerDescription: '很高兴您加入!', emailLabel: '邮箱', emailPlaceholder: '请输入邮箱地址', + emailInvalid: '无效的邮箱地址', passwordLabel: '密码', passwordPlaceholder: '请输入密码', rememberMe: '记住我', diff --git a/src/pages/login/Login.tsx b/src/pages/login/Login.tsx index a045dcc..11ead59 100644 --- a/src/pages/login/Login.tsx +++ b/src/pages/login/Login.tsx @@ -1,4 +1,5 @@ import { useTranslation } from 'react-i18next'; +import React, { useState } from 'react'; import { Box, Button, @@ -14,13 +15,20 @@ import { CardContent, Alert, Tabs, - Tab + Tab, + InputAdornment, + IconButton, } from '@mui/material'; +import Visibility from '@mui/icons-material/Visibility'; +import VisibilityOff from '@mui/icons-material/VisibilityOff'; import LanguageSwitcher from '../../components/LanguageSwitcher'; import { useLoginPage } from '../../hooks/login-hooks'; const Login = () => { const { t } = useTranslation(); + const [showLoginPassword, setShowLoginPassword] = useState(false); + const [showRegisterPassword, setShowRegisterPassword] = useState(false); + const [showConfirmPassword, setShowConfirmPassword] = useState(false); const { // 表单状态 tabValue, @@ -110,13 +118,27 @@ const Login = () => { + setShowLoginPassword((v) => !v)} + onMouseDown={(e) => e.preventDefault()} + edge="end" + > + {showLoginPassword ? : } + + + ), + }} /> @@ -175,13 +197,53 @@ const Login = () => { + setShowRegisterPassword((v) => !v)} + onMouseDown={(e) => e.preventDefault()} + edge="end" + > + {showRegisterPassword ? : } + + + ), + }} + /> + + + setShowConfirmPassword((v) => !v)} + onMouseDown={(e) => e.preventDefault()} + edge="end" + > + {showConfirmPassword ? : } + + + ), + }} />