2026-03-17 13:17:02 +08:00

260 lines
11 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use client"
import type React from "react"
import { useState } from "react"
import Link from "next/link"
import { useRouter } from "next/navigation"
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Label } from "@/components/ui/label"
import { Sparkles, Mail, Phone, ArrowRight, Loader2, CheckCircle2 } from "lucide-react"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
export default function ForgotPasswordPage() {
const router = useRouter()
const [isLoading, setIsLoading] = useState(false)
const [resetMethod, setResetMethod] = useState<"email" | "phone">("email")
const [email, setEmail] = useState("")
const [phone, setPhone] = useState("")
const [verificationCode, setVerificationCode] = useState("")
const [isSendingCode, setIsSendingCode] = useState(false)
const [countdown, setCountdown] = useState(0)
const [isSuccess, setIsSuccess] = useState(false)
const handleResetPassword = async (e: React.FormEvent) => {
e.preventDefault()
setIsLoading(true)
try {
// 模拟重置密码请求
await new Promise((resolve) => setTimeout(resolve, 1500))
// 显示成功信息
setIsSuccess(true)
// 3秒后跳转到登录页
setTimeout(() => {
router.push("/login")
}, 3000)
} catch (error) {
console.error("重置密码失败", error)
} finally {
setIsLoading(false)
}
}
const handleSendVerificationCode = async () => {
if (!phone || phone.length !== 11 || isSendingCode) return
setIsSendingCode(true)
try {
// 模拟发送验证码请求
await new Promise((resolve) => setTimeout(resolve, 1000))
// 开始倒计时
setCountdown(60)
const timer = setInterval(() => {
setCountdown((prev) => {
if (prev <= 1) {
clearInterval(timer)
setIsSendingCode(false)
return 0
}
return prev - 1
})
}, 1000)
} catch (error) {
console.error("发送验证码失败", error)
setIsSendingCode(false)
}
}
if (isSuccess) {
return (
<div className="min-h-screen w-full flex items-center justify-center bg-gradient-to-br from-gray-50 to-white p-4">
<div className="absolute top-0 right-0 w-1/2 h-64 bg-gradient-to-bl from-pink-200 via-purple-200 to-transparent opacity-20 rounded-bl-full" />
<div className="absolute bottom-0 left-0 w-1/2 h-64 bg-gradient-to-tr from-blue-200 via-purple-200 to-transparent opacity-20 rounded-tr-full" />
<Card className="w-full max-w-md border-none shadow-xl bg-white/80 backdrop-blur-sm">
<CardHeader className="space-y-2 text-center">
<div className="flex justify-center mb-2">
<div className="h-12 w-12 rounded-full bg-gradient-to-br from-green-500 to-teal-600 flex items-center justify-center">
<CheckCircle2 className="h-6 w-6 text-white" />
</div>
</div>
<CardTitle className="text-2xl font-bold text-green-600"></CardTitle>
<CardDescription>
{resetMethod === "email" ? "的邮箱" : "的手机"}
{resetMethod === "email" ? "链接" : "验证码"}
{resetMethod === "email" ? "查看您的邮箱" : "注意查收短信"}
</CardDescription>
</CardHeader>
<CardContent className="text-center">
<p className="text-gray-500 mb-4">3...</p>
<Button
onClick={() => router.push("/login")}
className="bg-gradient-to-r from-green-500 to-teal-600 hover:from-green-600 hover:to-teal-700 transition-all duration-300 shadow-md hover:shadow-lg"
>
<ArrowRight className="ml-2 h-4 w-4" />
</Button>
</CardContent>
</Card>
</div>
)
}
return (
<div className="min-h-screen w-full flex items-center justify-center bg-gradient-to-br from-gray-50 to-white p-4">
<div className="absolute top-0 right-0 w-1/2 h-64 bg-gradient-to-bl from-pink-200 via-purple-200 to-transparent opacity-20 rounded-bl-full" />
<div className="absolute bottom-0 left-0 w-1/2 h-64 bg-gradient-to-tr from-blue-200 via-purple-200 to-transparent opacity-20 rounded-tr-full" />
<Card className="w-full max-w-md border-none shadow-xl bg-white/80 backdrop-blur-sm">
<CardHeader className="space-y-2 text-center">
<div className="flex justify-center mb-2">
<div className="h-12 w-12 rounded-full bg-gradient-to-br from-pink-500 to-purple-600 flex items-center justify-center">
<Sparkles className="h-6 w-6 text-white" />
</div>
</div>
<CardTitle className="text-2xl font-bold bg-clip-text text-transparent bg-gradient-to-r from-pink-600 to-purple-600">
</CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<Tabs defaultValue="email" onValueChange={(value) => setResetMethod(value as "email" | "phone")}>
<TabsList className="grid w-full grid-cols-2 mb-6">
<TabsTrigger
value="email"
className="data-[state=active]:bg-gradient-to-r data-[state=active]:from-pink-500 data-[state=active]:to-purple-600 data-[state=active]:text-white"
>
</TabsTrigger>
<TabsTrigger
value="phone"
className="data-[state=active]:bg-gradient-to-r data-[state=active]:from-pink-500 data-[state=active]:to-purple-600 data-[state=active]:text-white"
>
</TabsTrigger>
</TabsList>
<TabsContent value="email">
<form onSubmit={handleResetPassword} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="email"></Label>
<div className="relative">
<Mail className="absolute left-3 top-3 h-4 w-4 text-gray-400" />
<Input
id="email"
type="email"
placeholder="请输入您的注册邮箱"
className="pl-10 border-gray-300 focus-visible:ring-pink-500"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
</div>
<p className="text-xs text-gray-500"></p>
</div>
<Button
type="submit"
className="w-full bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 transition-all duration-300 shadow-md hover:shadow-lg"
disabled={isLoading}
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<ArrowRight className="ml-2 h-4 w-4" />
</>
)}
</Button>
</form>
</TabsContent>
<TabsContent value="phone">
<form onSubmit={handleResetPassword} className="space-y-4">
<div className="space-y-2">
<Label htmlFor="phone"></Label>
<div className="relative">
<Phone className="absolute left-3 top-3 h-4 w-4 text-gray-400" />
<Input
id="phone"
type="tel"
placeholder="请输入您的注册手机号"
className="pl-10 border-gray-300 focus-visible:ring-pink-500"
value={phone}
onChange={(e) => setPhone(e.target.value)}
required
/>
</div>
</div>
<div className="space-y-2">
<Label htmlFor="verificationCode"></Label>
<div className="flex space-x-2">
<div className="relative flex-1">
<Input
id="verificationCode"
type="text"
placeholder="请输入验证码"
className="border-gray-300 focus-visible:ring-pink-500"
value={verificationCode}
onChange={(e) => setVerificationCode(e.target.value)}
required
/>
</div>
<Button
type="button"
variant="outline"
className="min-w-[120px] hover:bg-pink-50 hover:text-pink-700 transition-all duration-200"
onClick={handleSendVerificationCode}
disabled={isSendingCode || !phone || phone.length !== 11}
>
{countdown > 0 ? `${countdown}秒后重发` : "获取验证码"}
</Button>
</div>
</div>
<Button
type="submit"
className="w-full bg-gradient-to-r from-pink-500 to-purple-600 hover:from-pink-600 hover:to-purple-700 transition-all duration-300 shadow-md hover:shadow-lg"
disabled={isLoading}
>
{isLoading ? (
<>
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
...
</>
) : (
<>
<ArrowRight className="ml-2 h-4 w-4" />
</>
)}
</Button>
</form>
</TabsContent>
</Tabs>
</CardContent>
<CardFooter className="flex flex-col space-y-4 pt-0">
<div className="text-center text-sm text-gray-500">
?{" "}
<Link href="/login" className="text-pink-600 hover:text-pink-700 hover:underline">
</Link>
</div>
</CardFooter>
</Card>
</div>
)
}