登录页面增加查看密码和记住密码
This commit is contained in:
+75
-11
@@ -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'
|
||||||
|
|||||||
Reference in New Issue
Block a user