登录页面增加查看密码和记住密码

This commit is contained in:
mtvpls
2025-12-04 10:03:10 +08:00
parent 7df4530bcf
commit 2fc0390209
+75 -11
View File
@@ -2,7 +2,7 @@
'use client'; 'use client';
import { AlertCircle, CheckCircle } from 'lucide-react'; import { AlertCircle, CheckCircle, Eye, EyeOff } from 'lucide-react';
import { useRouter, useSearchParams } from 'next/navigation'; import { useRouter, useSearchParams } from 'next/navigation';
import { Suspense, useEffect, useState } from 'react'; import { Suspense, useEffect, useState } from 'react';
@@ -75,6 +75,8 @@ function LoginPageClient() {
const [error, setError] = useState<string | null>(null); const [error, setError] = useState<string | null>(null);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [shouldAskUsername, setShouldAskUsername] = useState(false); const [shouldAskUsername, setShouldAskUsername] = useState(false);
const [rememberPassword, setRememberPassword] = useState(false);
const [showPassword, setShowPassword] = useState(false);
const { siteName } = useSite(); const { siteName } = useSite();
@@ -82,7 +84,26 @@ function LoginPageClient() {
useEffect(() => { useEffect(() => {
if (typeof window !== 'undefined') { if (typeof window !== 'undefined') {
const storageType = (window as any).RUNTIME_CONFIG?.STORAGE_TYPE; const storageType = (window as any).RUNTIME_CONFIG?.STORAGE_TYPE;
setShouldAskUsername(storageType && storageType !== 'localstorage'); const shouldAsk = storageType && storageType !== 'localstorage';
setShouldAskUsername(shouldAsk);
// 从localStorage读取记住的密码信息
const rememberedCredentials = localStorage.getItem('rememberedCredentials');
if (rememberedCredentials) {
try {
const credentials = JSON.parse(rememberedCredentials);
if (credentials.password) {
setPassword(credentials.password);
}
if (credentials.username && shouldAsk) {
setUsername(credentials.username);
}
setRememberPassword(true);
} catch (error) {
// 清除无效的数据
localStorage.removeItem('rememberedCredentials');
}
}
} }
}, []); }, []);
@@ -104,6 +125,19 @@ function LoginPageClient() {
}); });
if (res.ok) { if (res.ok) {
// 处理记住密码逻辑
if (rememberPassword) {
const credentials: any = { password };
// 如果需要用户名且有用户名,就保存用户名
if (shouldAskUsername && username) {
credentials.username = username;
}
localStorage.setItem('rememberedCredentials', JSON.stringify(credentials));
} else {
// 如果不记住密码,清除已存储的信息
localStorage.removeItem('rememberedCredentials');
}
const redirect = searchParams.get('redirect') || '/'; const redirect = searchParams.get('redirect') || '/';
router.replace(redirect); router.replace(redirect);
} else if (res.status === 401) { } else if (res.status === 401) {
@@ -152,21 +186,51 @@ function LoginPageClient() {
<label htmlFor='password' className='sr-only'> <label htmlFor='password' className='sr-only'>
</label> </label>
<input <div className='relative'>
id='password' <input
type='password' id='password'
autoComplete='current-password' type={showPassword ? 'text' : 'password'}
className='block w-full rounded-lg border-0 py-3 px-4 text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-white/60 dark:ring-white/20 placeholder:text-gray-500 dark:placeholder:text-gray-400 focus:ring-2 focus:ring-green-500 focus:outline-none sm:text-base bg-white/60 dark:bg-zinc-800/60 backdrop-blur' autoComplete='current-password'
placeholder='输入访问密码' className='block w-full rounded-lg border-0 py-3 px-4 pr-12 text-gray-900 dark:text-gray-100 shadow-sm ring-1 ring-white/60 dark:ring-white/20 placeholder:text-gray-500 dark:placeholder:text-gray-400 focus:ring-2 focus:ring-green-500 focus:outline-none sm:text-base bg-white/60 dark:bg-zinc-800/60 backdrop-blur'
value={password} placeholder='输入访问密码'
onChange={(e) => setPassword(e.target.value)} value={password}
/> onChange={(e) => setPassword(e.target.value)}
/>
<button
type='button'
className='absolute inset-y-0 right-0 flex items-center pr-3 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200'
onClick={() => setShowPassword(!showPassword)}
>
{showPassword ? (
<EyeOff className='h-5 w-5' />
) : (
<Eye className='h-5 w-5' />
)}
</button>
</div>
</div> </div>
{error && ( {error && (
<p className='text-sm text-red-600 dark:text-red-400'>{error}</p> <p className='text-sm text-red-600 dark:text-red-400'>{error}</p>
)} )}
{/* 记住密码复选框 */}
<div className='flex items-center'>
<input
id='remember-password'
type='checkbox'
className='h-4 w-4 rounded border-gray-300 text-green-600 focus:ring-green-500 dark:border-gray-600 dark:bg-gray-700'
checked={rememberPassword}
onChange={(e) => setRememberPassword(e.target.checked)}
/>
<label
htmlFor='remember-password'
className='ml-2 block text-sm text-gray-700 dark:text-gray-300'
>
</label>
</div>
{/* 登录按钮 */} {/* 登录按钮 */}
<button <button
type='submit' type='submit'