fix captcha show
This commit is contained in:
parent
fe4fbf0ea1
commit
f779a277a8
@ -58,7 +58,12 @@ function SignInContent() {
|
||||
|
||||
const handleEmailSignInClick = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
if (!email) return
|
||||
if (!email.trim()) return
|
||||
|
||||
// 清除之前的消息
|
||||
setMessage("")
|
||||
|
||||
// 显示验证码弹窗
|
||||
setShowCaptcha(true)
|
||||
}
|
||||
|
||||
@ -68,7 +73,7 @@ function SignInContent() {
|
||||
|
||||
try {
|
||||
const result = await signIn("nodemailer", {
|
||||
email,
|
||||
email: email.trim(),
|
||||
redirect: false,
|
||||
})
|
||||
|
||||
@ -78,6 +83,7 @@ function SignInContent() {
|
||||
setMessage("登录链接已发送到您的邮箱,请查收")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Email sign in error:", error)
|
||||
setMessage("登录失败,请重试")
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
@ -86,14 +92,24 @@ function SignInContent() {
|
||||
|
||||
const handleCaptchaCancel = () => {
|
||||
setMessage("")
|
||||
setIsLoading(false)
|
||||
}
|
||||
|
||||
const handleCaptchaOpenChange = (open: boolean) => {
|
||||
setShowCaptcha(open)
|
||||
if (!open) {
|
||||
setIsLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const handleGoogleSignIn = async () => {
|
||||
setIsLoading(true)
|
||||
setMessage("")
|
||||
try {
|
||||
const callbackUrl = searchParams.get("callbackUrl") || "/"
|
||||
await signIn("google", { callbackUrl })
|
||||
} catch (error) {
|
||||
console.error("Google sign in error:", error)
|
||||
setMessage("Google登录失败,请重试")
|
||||
setIsLoading(false)
|
||||
}
|
||||
@ -145,12 +161,13 @@ function SignInContent() {
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
required
|
||||
className="bg-background border-input"
|
||||
disabled={isLoading}
|
||||
/>
|
||||
</div>
|
||||
<Button
|
||||
type="submit"
|
||||
className="w-full"
|
||||
disabled={isLoading || !email}
|
||||
disabled={isLoading || !email.trim()}
|
||||
>
|
||||
<Mail className="mr-2 h-4 w-4" />
|
||||
{isLoading ? "发送中..." : "发送登录链接"}
|
||||
@ -169,7 +186,7 @@ function SignInContent() {
|
||||
{/* 验证码弹窗 */}
|
||||
<CaptchaDialog
|
||||
open={showCaptcha}
|
||||
onOpenChange={setShowCaptcha}
|
||||
onOpenChange={handleCaptchaOpenChange}
|
||||
onVerify={handleCaptchaVerify}
|
||||
onCancel={handleCaptchaCancel}
|
||||
/>
|
||||
|
@ -8,12 +8,15 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogPortal,
|
||||
DialogOverlay,
|
||||
} from "@/components/ui/dialog"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert"
|
||||
import { Shield, RefreshCw, AlertCircle } from "lucide-react"
|
||||
import * as DialogPrimitive from "@radix-ui/react-dialog"
|
||||
|
||||
interface CaptchaDialogProps {
|
||||
open: boolean
|
||||
@ -76,88 +79,104 @@ export function CaptchaDialog({
|
||||
}
|
||||
}
|
||||
|
||||
// 防止第一次打开时的遮罩层问题
|
||||
const handleOpenChange = (newOpen: boolean) => {
|
||||
if (!newOpen) {
|
||||
setUserAnswer("")
|
||||
setError("")
|
||||
onCancel()
|
||||
}
|
||||
onOpenChange(newOpen)
|
||||
}
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="sm:max-w-md">
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2 text-foreground">
|
||||
<Shield className="h-5 w-5 text-blue-500 dark:text-blue-400" />
|
||||
安全验证
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
为了防止恶意使用,请完成以下验证码验证后再发送登录邮件
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||
<DialogPortal>
|
||||
<DialogOverlay className="fixed inset-0 z-[100] bg-black/80" />
|
||||
<DialogPrimitive.Content
|
||||
className="fixed left-[50%] top-[50%] z-[101] grid w-full max-w-md translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg focus:outline-none"
|
||||
onPointerDownOutside={(e) => e.preventDefault()}
|
||||
>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="flex items-center gap-2 text-foreground">
|
||||
<Shield className="h-5 w-5 text-blue-500 dark:text-blue-400" />
|
||||
安全验证
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
为了防止恶意使用,请完成以下验证码验证后再发送登录邮件
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className="space-y-4">
|
||||
<Alert className="border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-950/50">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
<strong>提示:</strong>计算下面的数学题,输入答案完成验证
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
<div className="space-y-4">
|
||||
<Alert className="border-blue-200 bg-blue-50 dark:border-blue-800 dark:bg-blue-950/50">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>
|
||||
<strong>提示:</strong>计算下面的数学题,输入答案完成验证
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-center p-6 bg-muted/50 rounded-lg border">
|
||||
<div className="text-center">
|
||||
<div className="text-2xl font-bold text-foreground mb-2">
|
||||
{num1} + {num2} = ?
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={generateCaptcha}
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<RefreshCw className="h-4 w-4 mr-1" />
|
||||
换一题
|
||||
</Button>
|
||||
<div className="space-y-3">
|
||||
<div className="flex items-center justify-center p-6 bg-muted/50 rounded-lg border">
|
||||
<div className="text-center">
|
||||
<div className="text-2xl font-bold text-foreground mb-2">
|
||||
{num1} + {num2} = ?
|
||||
</div>
|
||||
<div className="flex items-center justify-center gap-2">
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={generateCaptcha}
|
||||
className="text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
<RefreshCw className="h-4 w-4 mr-1" />
|
||||
换一题
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="captcha-answer" className="text-foreground">
|
||||
请输入答案
|
||||
</Label>
|
||||
<Input
|
||||
id="captcha-answer"
|
||||
type="number"
|
||||
placeholder="输入计算结果"
|
||||
value={userAnswer}
|
||||
onChange={(e) => setUserAnswer(e.target.value)}
|
||||
onKeyPress={handleKeyPress}
|
||||
className="text-center text-lg font-medium"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="captcha-answer" className="text-foreground">
|
||||
请输入答案
|
||||
</Label>
|
||||
<Input
|
||||
id="captcha-answer"
|
||||
type="number"
|
||||
placeholder="输入计算结果"
|
||||
value={userAnswer}
|
||||
onChange={(e) => setUserAnswer(e.target.value)}
|
||||
onKeyDown={handleKeyPress}
|
||||
className="text-center text-lg font-medium"
|
||||
autoFocus
|
||||
/>
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<Alert className="border-red-200 bg-red-50 text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
{error && (
|
||||
<Alert className="border-red-200 bg-red-50 text-red-800 dark:border-red-800 dark:bg-red-950 dark:text-red-200">
|
||||
<AlertCircle className="h-4 w-4" />
|
||||
<AlertDescription>{error}</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<DialogFooter className="flex justify-between">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleVerify}
|
||||
disabled={!userAnswer.trim()}
|
||||
className="bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700"
|
||||
>
|
||||
验证并发送邮件
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
<DialogFooter className="flex justify-between">
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={handleCancel}
|
||||
>
|
||||
取消
|
||||
</Button>
|
||||
<Button
|
||||
onClick={handleVerify}
|
||||
disabled={!userAnswer.trim()}
|
||||
className="bg-blue-600 hover:bg-blue-700 dark:bg-blue-600 dark:hover:bg-blue-700"
|
||||
>
|
||||
验证并发送邮件
|
||||
</Button>
|
||||
</DialogFooter>
|
||||
</DialogPrimitive.Content>
|
||||
</DialogPortal>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
Loading…
Reference in New Issue
Block a user