| | |
| | | const [mounted, setMounted] = useState(false); |
| | | const [countdown, setCountdown] = useState(0); |
| | | |
| | | // 添加滚动锁定 |
| | | useEffect(() => { |
| | | document.body.style.overflow = 'hidden'; |
| | | return () => { |
| | | document.body.style.overflow = 'unset'; |
| | | }; |
| | | }, []); |
| | | |
| | | // 倒计时逻辑 |
| | | useEffect(() => { |
| | | if (countdown > 0) { |
| | |
| | | } |
| | | }, [countdown]); |
| | | |
| | | // 确保组件挂载后再显示动画效果 |
| | | // 优化动画性能 |
| | | useEffect(() => { |
| | | // 使用 requestAnimationFrame 确保在下一帧执行,提高动画流畅度 |
| | | const animationFrame = requestAnimationFrame(() => { |
| | | setMounted(true); |
| | | }); |
| | |
| | | }; |
| | | |
| | | return ( |
| | | <div className="h-screen w-full flex items-center justify-center relative overflow-hidden"> |
| | | {/* 背景效果 */} |
| | | <div className="fixed inset-0 bg-gradient-to-br from-[#0A1033] via-[#1E2B63] to-[#131C41] z-0"></div> |
| | | <div className="h-screen w-full flex items-center justify-center relative overflow-hidden fixed"> |
| | | {/* 背景效果 - 优化性能 */} |
| | | <div className="fixed inset-0 bg-gradient-to-br from-[#0A1033] via-[#1E2B63] to-[#131C41] z-0 will-change-transform"></div> |
| | | |
| | | {/* 神经网络线条背景 */} |
| | | <div className="fixed inset-0 z-0 opacity-30"> |
| | | <div className="absolute top-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/70 to-transparent"></div> |
| | | <div className="absolute bottom-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/70 to-transparent"></div> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[1px] bg-gradient-to-b from-transparent via-[#6ADBFF]/70 to-transparent"></div> |
| | | <div className="absolute top-0 bottom-0 right-0 w-[1px] bg-gradient-to-b from-transparent via-[#6ADBFF]/70 to-transparent"></div> |
| | | {/* 神经网络线条背景 - 优化性能 */} |
| | | <div className="fixed inset-0 z-0 opacity-30 will-change-transform"> |
| | | <div className="absolute top-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/70 to-transparent transform-gpu"></div> |
| | | <div className="absolute bottom-0 left-0 right-0 h-[1px] bg-gradient-to-r from-transparent via-[#6ADBFF]/70 to-transparent transform-gpu"></div> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[1px] bg-gradient-to-b from-transparent via-[#6ADBFF]/70 to-transparent transform-gpu"></div> |
| | | <div className="absolute top-0 bottom-0 right-0 w-[1px] bg-gradient-to-b from-transparent via-[#6ADBFF]/70 to-transparent transform-gpu"></div> |
| | | |
| | | {/* 神经网络连接点 */} |
| | | <div className="absolute top-[20%] left-[15%] w-1.5 h-1.5 rounded-full bg-[#6ADBFF]/80 animate-pulse"></div> |
| | | <div className="absolute top-[60%] left-[75%] w-1.5 h-1.5 rounded-full bg-[#6ADBFF]/80 animate-pulse" style={{ animationDelay: '1.5s' }}></div> |
| | | {/* 神经网络连接点 - 优化性能 */} |
| | | <div className="absolute top-[20%] left-[15%] w-1.5 h-1.5 rounded-full bg-[#6ADBFF]/80 animate-pulse transform-gpu"></div> |
| | | <div className="absolute top-[60%] left-[75%] w-1.5 h-1.5 rounded-full bg-[#6ADBFF]/80 animate-pulse transform-gpu" style={{ animationDelay: '1.5s' }}></div> |
| | | |
| | | {/* 连接线 */} |
| | | <div className="absolute top-[20%] left-[15%] w-[70%] h-[1px] bg-gradient-to-r from-[#6ADBFF]/80 to-transparent animate-pulse"></div> |
| | | {/* 连接线 - 优化性能 */} |
| | | <div className="absolute top-[20%] left-[15%] w-[70%] h-[1px] bg-gradient-to-r from-[#6ADBFF]/80 to-transparent animate-pulse transform-gpu"></div> |
| | | |
| | | {/* 数据点背景 */} |
| | | <div className="absolute inset-0" style={{ |
| | | {/* 数据点背景 - 优化性能 */} |
| | | <div className="absolute inset-0 transform-gpu" style={{ |
| | | backgroundImage: 'radial-gradient(circle, rgba(106, 219, 255, 0.15) 1px, transparent 1px)', |
| | | backgroundSize: '20px 20px' |
| | | }}></div> |
| | | |
| | | {/* 扫描线 */} |
| | | <div className="absolute inset-0"> |
| | | <div className="absolute top-0 left-0 w-full h-full bg-gradient-to-b from-transparent via-[#6ADBFF]/5 to-transparent animate-scanline" style={{ animationDuration: '12s' }}></div> |
| | | {/* 扫描线 - 优化性能 */} |
| | | <div className="absolute inset-0 transform-gpu"> |
| | | <div className="absolute top-0 left-0 w-full h-full bg-gradient-to-b from-transparent via-[#6ADBFF]/5 to-transparent animate-scanline transform-gpu" style={{ animationDuration: '12s' }}></div> |
| | | </div> |
| | | </div> |
| | | |
| | | {/* 注册卡片 */} |
| | | {/* 注册卡片 - 优化动画性能 */} |
| | | <motion.div |
| | | initial={{ opacity: 0, y: 20 }} |
| | | animate={{ opacity: mounted ? 1 : 0, y: mounted ? 0 : 20 }} |
| | | transition={{ |
| | | duration: 0.5, |
| | | ease: [0.25, 0.1, 0.25, 1], |
| | | staggerChildren: 0.1 |
| | | ease: [0.23, 1, 0.32, 1] |
| | | }} |
| | | className="relative z-10 w-full max-w-3xl flex rounded-2xl backdrop-blur-lg bg-[#1E2B63]/40 border border-[#6ADBFF]/20 shadow-xl overflow-hidden gpu-accelerated" |
| | | > |
| | |
| | | {/* 注册表单 */} |
| | | <form onSubmit={handleSubmit} className="space-y-4"> |
| | | {/* 用户名 */} |
| | | <div className="space-y-1"> |
| | | <label className="block text-xs text-[#6ADBFF]/80 mb-1">用户名</label> |
| | | <div className="relative group"> |
| | | <input |
| | | type="text" |
| | | value={username} |
| | | onChange={(e) => setUsername(e.target.value)} |
| | | className="w-full px-4 py-2 bg-[#131C41]/70 border border-[#6ADBFF]/30 rounded-lg text-white focus:outline-none focus:border-[#6ADBFF]/70 transition-all" |
| | | className="block w-full px-4 py-2 bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md focus:outline-none focus:ring-1 focus:ring-[#6ADBFF]/60 focus:border-[#6ADBFF]/60 text-white text-xs placeholder-[#6ADBFF]/50 transition-all duration-300" |
| | | placeholder="请输入用户名" |
| | | required |
| | | /> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[2px] bg-gradient-to-b from-transparent via-[#6ADBFF]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> |
| | | </div> |
| | | <div className="absolute bottom-0 left-0 w-full h-[1px] bg-gradient-to-r from-[#6ADBFF] to-transparent scale-x-0 origin-left transition-transform duration-300 ease-out group-focus-within:scale-x-100"></div> |
| | | </div> |
| | | |
| | | {/* 密码 */} |
| | | <div className="space-y-1"> |
| | | <label className="block text-xs text-[#6ADBFF]/80 mb-1">密码</label> |
| | | <div className="relative group"> |
| | | <input |
| | | type="password" |
| | | value={password} |
| | | onChange={(e) => setPassword(e.target.value)} |
| | | className="w-full px-4 py-2 bg-[#131C41]/70 border border-[#6ADBFF]/30 rounded-lg text-white focus:outline-none focus:border-[#6ADBFF]/70 transition-all" |
| | | className="block w-full px-4 py-2 bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md focus:outline-none focus:ring-1 focus:ring-[#6ADBFF]/60 focus:border-[#6ADBFF]/60 text-white text-xs placeholder-[#6ADBFF]/50 transition-all duration-300" |
| | | placeholder="请输入密码" |
| | | required |
| | | /> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[2px] bg-gradient-to-b from-transparent via-[#6ADBFF]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> |
| | | </div> |
| | | <div className="absolute bottom-0 left-0 w-full h-[1px] bg-gradient-to-r from-[#6ADBFF] to-transparent scale-x-0 origin-left transition-transform duration-300 ease-out group-focus-within:scale-x-100"></div> |
| | | </div> |
| | | |
| | | {/* 确认密码 */} |
| | | <div className="space-y-1"> |
| | | <label className="block text-xs text-[#6ADBFF]/80 mb-1">确认密码</label> |
| | | <div className="relative group"> |
| | | <input |
| | | type="password" |
| | | value={confirmPassword} |
| | | onChange={(e) => setConfirmPassword(e.target.value)} |
| | | className="w-full px-4 py-2 bg-[#131C41]/70 border border-[#6ADBFF]/30 rounded-lg text-white focus:outline-none focus:border-[#6ADBFF]/70 transition-all" |
| | | className="block w-full px-4 py-2 bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md focus:outline-none focus:ring-1 focus:ring-[#6ADBFF]/60 focus:border-[#6ADBFF]/60 text-white text-xs placeholder-[#6ADBFF]/50 transition-all duration-300" |
| | | placeholder="请确认密码" |
| | | required |
| | | /> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[2px] bg-gradient-to-b from-transparent via-[#6ADBFF]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> |
| | | </div> |
| | | <div className="absolute bottom-0 left-0 w-full h-[1px] bg-gradient-to-r from-[#6ADBFF] to-transparent scale-x-0 origin-left transition-transform duration-300 ease-out group-focus-within:scale-x-100"></div> |
| | | </div> |
| | | |
| | | {/* 手机号码 */} |
| | | <div className="space-y-1"> |
| | | <label className="block text-xs text-[#6ADBFF]/80 mb-1">手机号码</label> |
| | | <div className="relative group"> |
| | | <input |
| | | type="tel" |
| | | value={phone} |
| | | onChange={(e) => setPhone(e.target.value)} |
| | | className="w-full px-4 py-2 bg-[#131C41]/70 border border-[#6ADBFF]/30 rounded-lg text-white focus:outline-none focus:border-[#6ADBFF]/70 transition-all" |
| | | className="block w-full px-4 py-2 bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md focus:outline-none focus:ring-1 focus:ring-[#6ADBFF]/60 focus:border-[#6ADBFF]/60 text-white text-xs placeholder-[#6ADBFF]/50 transition-all duration-300" |
| | | placeholder="请输入手机号码" |
| | | pattern="[0-9]{11}" |
| | | required |
| | | /> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[2px] bg-gradient-to-b from-transparent via-[#6ADBFF]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> |
| | | </div> |
| | | <div className="absolute bottom-0 left-0 w-full h-[1px] bg-gradient-to-r from-[#6ADBFF] to-transparent scale-x-0 origin-left transition-transform duration-300 ease-out group-focus-within:scale-x-100"></div> |
| | | </div> |
| | | |
| | | {/* 验证码 */} |
| | | <div className="space-y-1"> |
| | | <label className="block text-xs text-[#6ADBFF]/80 mb-1">验证码</label> |
| | | <div className="flex space-x-2"> |
| | | <div className="relative group flex-1"> |
| | | <div className="relative group flex"> |
| | | <input |
| | | type="text" |
| | | value={verifyCode} |
| | | onChange={(e) => setVerifyCode(e.target.value)} |
| | | className="w-full px-4 py-2 bg-[#131C41]/70 border border-[#6ADBFF]/30 rounded-lg text-white focus:outline-none focus:border-[#6ADBFF]/70 transition-all" |
| | | className="block w-full px-4 py-2 bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md focus:outline-none focus:ring-1 focus:ring-[#6ADBFF]/60 focus:border-[#6ADBFF]/60 text-white text-xs placeholder-[#6ADBFF]/50 transition-all duration-300" |
| | | placeholder="请输入验证码" |
| | | required |
| | | /> |
| | | <div className="absolute top-0 bottom-0 left-0 w-[2px] bg-gradient-to-b from-transparent via-[#6ADBFF]/50 to-transparent opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div> |
| | | </div> |
| | | <button |
| | | type="button" |
| | | onClick={sendVerifyCode} |
| | | disabled={countdown > 0 || !phone || phone.length !== 11} |
| | | className={`px-4 py-2 rounded-lg border text-sm transition-all duration-300 whitespace-nowrap ${ |
| | | countdown > 0 || !phone || phone.length !== 11 |
| | | ? 'border-[#6ADBFF]/20 text-[#6ADBFF]/40 bg-[#131C41]/20 cursor-not-allowed' |
| | | : 'border-[#6ADBFF]/40 text-[#6ADBFF] bg-[#131C41]/40 hover:bg-[#131C41]/70 hover:border-[#6ADBFF]/60' |
| | | className={`ml-2 px-3 py-2 text-xs text-[#6ADBFF] bg-[#131C41]/80 border border-[#6ADBFF]/30 rounded-md hover:bg-[#131C41] hover:border-[#6ADBFF]/60 transition-all duration-300 whitespace-nowrap ${ |
| | | countdown > 0 || !phone || phone.length !== 11 ? 'opacity-50 cursor-not-allowed' : '' |
| | | }`} |
| | | > |
| | | {countdown > 0 ? `${countdown}秒后重试` : '获取验证码'} |
| | | </button> |
| | | </div> |
| | | <div className="absolute bottom-0 left-0 w-[calc(100%-4rem)] h-[1px] bg-gradient-to-r from-[#6ADBFF] to-transparent scale-x-0 origin-left transition-transform duration-300 ease-out group-focus-within:scale-x-100"></div> |
| | | </div> |
| | | |
| | | {/* 隐私声明 */} |