import { useCallback, useEffect, useState } from 'react' import { Alert, Button, Input, Skeleton } from 'antd' import http from '../api/http' interface CaptchaChoice { id: string label: string } interface CaptchaChallenge { captchaId: string type: 'TextImage' | 'MathImage' | 'Selection' | 'OneClick' prompt?: string choices?: CaptchaChoice[] imageData?: string } interface LoginCaptchaProps { refreshKey: number onChange: (captchaId: string, code: string) => void } export default function LoginCaptcha({ refreshKey, onChange }: LoginCaptchaProps) { const [captcha, setCaptcha] = useState(null) const [code, setCode] = useState('') const [loading, setLoading] = useState(false) const [loadError, setLoadError] = useState(false) const refresh = useCallback(async () => { setLoading(true) setLoadError(false) setCode('') onChange('', '') try { const { data } = await http.post('/auth/login/captcha', {}, { skipAuthSession: true }) setCaptcha(data) } catch { setCaptcha(null) setLoadError(true) } finally { setLoading(false) } }, [onChange]) useEffect(() => { void refresh() }, [refresh, refreshKey]) useEffect(() => { onChange(captcha?.captchaId ?? '', code) }, [captcha, code, onChange]) const isImageCaptcha = captcha?.type === 'TextImage' || captcha?.type === 'MathImage' return (
验证码
{loadError ? ( void refresh()}>重新加载} /> ) : loading && !captcha ? : (
{isImageCaptcha && ( <> {captcha?.imageData && ( 验证码图片,点击可更换 void refresh()} /> )} setCode(event.target.value)} /> )} {captcha && !isImageCaptcha && (

{captcha.prompt}

{captcha.imageData && ( 验证码图片,点击可更换 void refresh()} /> )} {captcha.type === 'Selection' ? (
{(captcha.choices ?? []).map((choice) => ( ))}
) : ( )}
)}
)}
) }