feat: 添加错误状态处理和错误标记组件,增强验证码功能

This commit is contained in:
2025-09-10 21:20:45 +08:00
parent 4781d81869
commit d69bf6c968
2 changed files with 20 additions and 3 deletions

View File

@ -23,7 +23,6 @@ export default function RootLayout({
<Navbar /> <Navbar />
</header> </header>
</motion.nav> </motion.nav>
<BackgroundProvider> <BackgroundProvider>
<div className='container mx-auto pt-16 px-4 sm:px-6 lg:px-10 max-w-7xl'>{children}</div> <div className='container mx-auto pt-16 px-4 sm:px-6 lg:px-10 max-w-7xl'>{children}</div>
</BackgroundProvider> </BackgroundProvider>

View File

@ -25,6 +25,18 @@ function CheckMark() {
); );
} }
// 错误的叉
function ErrorMark() {
return (
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', height: 40 }}>
<svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#ef4444" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round">
<line x1="18" y1="6" x2="6" y2="18" />
<line x1="6" y1="6" x2="18" y2="18" />
</svg>
</div>
);
}
export function OfficialTurnstileWidget(props: CaptchaProps) { export function OfficialTurnstileWidget(props: CaptchaProps) {
return <div> return <div>
<Turnstile className="w-full" options={{ size: "invisible" }} siteKey={props.siteKey} onSuccess={props.onSuccess} /> <Turnstile className="w-full" options={{ size: "invisible" }} siteKey={props.siteKey} onSuccess={props.onSuccess} />
@ -34,20 +46,26 @@ export function OfficialTurnstileWidget(props: CaptchaProps) {
// 自定义包装组件 // 自定义包装组件
export function TurnstileWidget(props: CaptchaProps) { export function TurnstileWidget(props: CaptchaProps) {
const t = useTranslations("Captcha"); const t = useTranslations("Captcha");
const [status, setStatus] = useState<'loading' | 'success'>('loading'); const [status, setStatus] = useState<'loading' | 'success' | 'error'>('loading');
// 只在验证通过时才显示勾 // 只在验证通过时才显示勾
const handleSuccess = (token: string) => { const handleSuccess = (token: string) => {
setStatus('success'); setStatus('success');
props.onSuccess(token); props.onSuccess(token);
}; };
const handleError = (error: string) => {
setStatus('error');
props.onError && props.onError(error);
};
return ( return (
<div className="flex items-center justify-evenly w-full border border-gray-300 rounded-md px-4 py-2 relative"> <div className="flex items-center justify-evenly w-full border border-gray-300 rounded-md px-4 py-2 relative">
{status === 'loading' && <Spinner />} {status === 'loading' && <Spinner />}
{status === 'success' && <CheckMark />} {status === 'success' && <CheckMark />}
<div className="flex-1 text-center">{status === 'success' ? t("success") :t("doing")}</div> <div className="flex-1 text-center">{status === 'success' ? t("success") :t("doing")}</div>
<div className="absolute inset-0 opacity-0 pointer-events-none"> <div className="absolute inset-0 opacity-0 pointer-events-none">
<OfficialTurnstileWidget {...props} onSuccess={handleSuccess} /> <OfficialTurnstileWidget {...props} onSuccess={handleSuccess} onError={handleError} />
</div> </div>
</div> </div>
); );