fix: show login failure feedback

This commit is contained in:
hectorzhao
2026-07-09 15:18:19 +08:00
parent 268392ee9c
commit 64bb3fb430
2 changed files with 24 additions and 5 deletions
+18 -5
View File
@@ -2,7 +2,7 @@ import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { adminApi, clientApi, type CaptchaResponse } from '@/api/adminApi'; import { adminApi, clientApi, type CaptchaResponse } from '@/api/adminApi';
import { writeSession, type Portal } from '@/api/session'; import { writeSession, type Portal } from '@/api/session';
import { Button, Input } from '@/components/ui'; import { Button, Input, Modal } from '@/components/ui';
type LoginPageProps = { type LoginPageProps = {
portal: Portal; portal: Portal;
@@ -28,11 +28,14 @@ export function LoginPage({ portal }: LoginPageProps) {
const [captchaText, setCaptchaText] = useState(''); const [captchaText, setCaptchaText] = useState('');
const [captcha, setCaptcha] = useState<CaptchaResponse | null>(null); const [captcha, setCaptcha] = useState<CaptchaResponse | null>(null);
const [error, setError] = useState(''); const [error, setError] = useState('');
const [alertMessage, setAlertMessage] = useState('');
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const isAdmin = portal === 'admin'; const isAdmin = portal === 'admin';
async function refreshCaptcha() { async function refreshCaptcha(options: { clearError?: boolean } = {}) {
setError(''); if (options.clearError ?? true) {
setError('');
}
setCaptchaText(''); setCaptchaText('');
setCaptcha(await (isAdmin ? adminApi.getCaptcha() : clientApi.getCaptcha())); setCaptcha(await (isAdmin ? adminApi.getCaptcha() : clientApi.getCaptcha()));
} }
@@ -55,8 +58,10 @@ export function LoginPage({ portal }: LoginPageProps) {
writeSession(session); writeSession(session);
navigate(isAdmin ? '/admin' : '/client', { replace: true }); navigate(isAdmin ? '/admin' : '/client', { replace: true });
} catch (err) { } catch (err) {
setError(loginErrorMessage(err)); const message = loginErrorMessage(err);
await refreshCaptcha(); setError(message);
setAlertMessage(message);
await refreshCaptcha({ clearError: false });
} finally { } finally {
setLoading(false); setLoading(false);
} }
@@ -85,6 +90,14 @@ export function LoginPage({ portal }: LoginPageProps) {
<Button disabled={loading} onClick={submit}>{loading ? '登录中...' : '登录'}</Button> <Button disabled={loading} onClick={submit}>{loading ? '登录中...' : '登录'}</Button>
</div> </div>
</section> </section>
<Modal
footer={<Button onClick={() => setAlertMessage('')}></Button>}
onClose={() => setAlertMessage('')}
open={Boolean(alertMessage)}
title="登录失败"
>
<p className="login-alert-message">{alertMessage}</p>
</Modal>
</main> </main>
); );
} }
+6
View File
@@ -4142,6 +4142,12 @@ h3 {
background: rgba(239, 68, 68, 0.1); background: rgba(239, 68, 68, 0.1);
} }
.login-alert-message {
margin: 0;
color: var(--color-text-strong);
line-height: 1.7;
}
.system-page { .system-page {
gap: 28px; gap: 28px;
} }