diff --git a/frontend/src/components/login/MinimalDark.tsx b/frontend/src/components/login/MinimalDark.tsx index a4bd472..2181040 100644 --- a/frontend/src/components/login/MinimalDark.tsx +++ b/frontend/src/components/login/MinimalDark.tsx @@ -1,223 +1,260 @@ import { useLogin } from '@/hooks/useLogin'; -/* ---------- static star positions (generated once) ---------- */ -const STARS = [ - { top: '8%', left: '15%', size: 2, opacity: 0.25 }, - { top: '12%', left: '72%', size: 1, opacity: 0.15 }, - { top: '25%', left: '45%', size: 3, opacity: 0.10 }, - { top: '18%', left: '88%', size: 1, opacity: 0.35 }, - { top: '38%', left: '22%', size: 2, opacity: 0.20 }, - { top: '55%', left: '68%', size: 1, opacity: 0.30 }, - { top: '62%', left: '35%', size: 2, opacity: 0.15 }, - { top: '75%', left: '80%', size: 3, opacity: 0.12 }, - { top: '82%', left: '50%', size: 1, opacity: 0.40 }, - { top: '90%', left: '10%', size: 2, opacity: 0.18 }, +/* ---------- Flowing curve configs ---------- */ +const CURVES = [ + { + // Curve 1: Wide pink-to-purple ribbon, top area + width: '140%', height: 320, top: '-5%', left: '-20%', + background: 'linear-gradient(135deg, #ec4899 0%, #a855f7 40%, #6366f1 100%)', + opacity: 0.12, blur: 60, rotate: -12, + animation: 'curve-flow-1 20s ease-in-out infinite', + }, + { + // Curve 2: Thin bright pink ribbon, mid-upper + width: '120%', height: 180, top: '15%', left: '-10%', + background: 'linear-gradient(90deg, transparent 0%, #f472b6 30%, #c084fc 60%, transparent 100%)', + opacity: 0.18, blur: 40, rotate: -8, + animation: 'curve-flow-2 16s ease-in-out infinite', + }, + { + // Curve 3: Deep purple band, center + width: '160%', height: 240, top: '35%', left: '-30%', + background: 'linear-gradient(135deg, #7c3aed 0%, #4f46e5 50%, #2563eb 100%)', + opacity: 0.10, blur: 70, rotate: 5, + animation: 'curve-flow-3 24s ease-in-out infinite', + }, + { + // Curve 4: Bright cyan-pink accent, lower-mid + width: '110%', height: 120, top: '55%', left: '-5%', + background: 'linear-gradient(90deg, transparent 10%, #06b6d4 35%, #a855f7 65%, transparent 90%)', + opacity: 0.15, blur: 35, rotate: -15, + animation: 'curve-flow-4 14s ease-in-out infinite', + }, + { + // Curve 5: Soft pink glow, bottom + width: '130%', height: 200, top: '70%', left: '-15%', + background: 'linear-gradient(135deg, #db2777 0%, #9333ea 60%, #4f46e5 100%)', + opacity: 0.08, blur: 80, rotate: 10, + animation: 'curve-flow-5 22s ease-in-out infinite', + }, + { + // Curve 6: Thin bright line accent + width: '100%', height: 3, top: '40%', left: '0%', + background: 'linear-gradient(90deg, transparent 0%, #f472b6 20%, #c084fc 50%, #818cf8 80%, transparent 100%)', + opacity: 0.35, blur: 8, rotate: -5, + animation: 'curve-line-float 18s ease-in-out infinite', + }, + { + // Curve 7: Another thin accent line + width: '90%', height: 2, top: '65%', left: '5%', + background: 'linear-gradient(90deg, transparent 5%, #818cf8 30%, #e879f9 70%, transparent 95%)', + opacity: 0.25, blur: 6, rotate: 8, + animation: 'curve-line-float 15s ease-in-out infinite reverse', + }, ]; -/* ---------- meteor configs ---------- */ -const METEORS = [ - { width: 140, height: 1, duration: '1.5s', delay: '0s', top: '-20px', right: '10%' }, - { width: 120, height: 2, duration: '1.2s', delay: '2s', top: '-60px', right: '30%' }, - { width: 150, height: 1, duration: '1.8s', delay: '4s', top: '-10px', right: '55%' }, - { width: 110, height: 2, duration: '2s', delay: '6.5s', top: '-80px', right: '20%' }, - { width: 130, height: 1, duration: '1.4s', delay: '9s', top: '-40px', right: '70%' }, - { width: 100, height: 1, duration: '1.6s', delay: '12s', top: '-30px', right: '45%' }, -]; - -const KEYFRAMES = METEORS.map((_, i) => ` - @keyframes meteor-shoot-${i + 1} { - 0% { - opacity: 0; - transform: translate(100vw, -100px) rotate(-35deg); - } - 10% { - opacity: 1; - } - 100% { - opacity: 0; - transform: translate(-100px, 100vh) rotate(-35deg); - } +const KEYFRAMES = ` + @keyframes curve-flow-1 { + 0%, 100% { transform: rotate(-12deg) translateX(0) scaleY(1); } + 33% { transform: rotate(-10deg) translateX(30px) scaleY(1.05); } + 66% { transform: rotate(-14deg) translateX(-20px) scaleY(0.95); } } -`).join('\n'); + @keyframes curve-flow-2 { + 0%, 100% { transform: rotate(-8deg) translateX(0); } + 50% { transform: rotate(-6deg) translateX(40px); } + } + @keyframes curve-flow-3 { + 0%, 100% { transform: rotate(5deg) translateX(0) scaleX(1); } + 40% { transform: rotate(3deg) translateX(-30px) scaleX(1.02); } + 70% { transform: rotate(7deg) translateX(20px) scaleX(0.98); } + } + @keyframes curve-flow-4 { + 0%, 100% { transform: rotate(-15deg) translateX(0); } + 50% { transform: rotate(-13deg) translateX(50px); } + } + @keyframes curve-flow-5 { + 0%, 100% { transform: rotate(10deg) translateX(0); } + 50% { transform: rotate(8deg) translateX(-40px); } + } + @keyframes curve-line-float { + 0%, 100% { transform: rotate(-5deg) translateX(0); opacity: 0.3; } + 25% { opacity: 0.5; } + 50% { transform: rotate(-3deg) translateX(30px); opacity: 0.35; } + 75% { opacity: 0.5; } + } + @keyframes curve-dot-pulse { + 0%, 100% { opacity: 0.15; transform: scale(1); } + 50% { opacity: 0.35; transform: scale(1.5); } + } +`; + +/* ---------- Decorative dots ---------- */ +const DOTS = [ + { top: '18%', left: '75%', size: 4, color: '#f472b6', delay: '0s' }, + { top: '30%', left: '20%', size: 3, color: '#818cf8', delay: '2s' }, + { top: '72%', left: '80%', size: 5, color: '#c084fc', delay: '1s' }, + { top: '85%', left: '30%', size: 3, color: '#ec4899', delay: '3s' }, + { top: '45%', left: '90%', size: 4, color: '#a855f7', delay: '1.5s' }, +]; export default function MinimalDark() { const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin(); return ( <> - {/* Inject keyframes once */}
- {/* -------- Static star dots -------- */} - {STARS.map((s, i) => ( + {/* -------- Background glow orbs -------- */} +
+
+ + {/* -------- Flowing curves -------- */} + {CURVES.map((c, i) => (
))} - {/* -------- Shooting meteors -------- */} - {METEORS.map((m, i) => ( + {/* -------- Decorative dots -------- */} + {DOTS.map((d, i) => (
))} - {/* -------- Central content card -------- */} -
- {/* Gradient diamond */} + {/* -------- Central content -------- */} +
+ {/* Brand logo */}
- - {/* Brand */} -

+ + + + + +

+ + {/* Brand name */} +

SQL审核平台

- - {/* Thin divider */} -
+

+ 企业级数据库审核与合规管理 +

{/* Form */} -
+ {error && ( -
+
{error}
)} - {/* Username */} -
- setUsername(e.target.value)} - className="w-full" - style={{ - padding: '12px 0', - background: 'transparent', - border: 'none', - borderBottom: '1px solid rgba(255,255,255,0.1)', - borderRadius: 0, - color: '#fff', - fontSize: 14, - outline: 'none', - transition: 'border-color 0.25s', - }} - onFocus={(e) => { - e.target.style.borderBottomColor = 'rgba(99,102,241,0.5)'; - }} - onBlur={(e) => { - e.target.style.borderBottomColor = 'rgba(255,255,255,0.1)'; - }} - /> -
+ setUsername(e.target.value)} + className="w-full" + style={{ + padding: '13px 16px', borderRadius: 10, + background: 'rgba(255,255,255,0.05)', + border: '1px solid rgba(255,255,255,0.08)', + color: '#fff', fontSize: 14, outline: 'none', + transition: 'border-color 0.2s, background 0.2s', + }} + onFocus={(e) => { e.target.style.borderColor = 'rgba(168,85,247,0.4)'; e.target.style.background = 'rgba(255,255,255,0.08)'; }} + onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.08)'; e.target.style.background = 'rgba(255,255,255,0.05)'; }} + /> + setPassword(e.target.value)} + className="w-full" + style={{ + padding: '13px 16px', borderRadius: 10, + background: 'rgba(255,255,255,0.05)', + border: '1px solid rgba(255,255,255,0.08)', + color: '#fff', fontSize: 14, outline: 'none', + transition: 'border-color 0.2s, background 0.2s', + }} + onFocus={(e) => { e.target.style.borderColor = 'rgba(168,85,247,0.4)'; e.target.style.background = 'rgba(255,255,255,0.08)'; }} + onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.08)'; e.target.style.background = 'rgba(255,255,255,0.05)'; }} + /> - {/* Password */} -
- setPassword(e.target.value)} - className="w-full" - style={{ - padding: '12px 0', - background: 'transparent', - border: 'none', - borderBottom: '1px solid rgba(255,255,255,0.1)', - borderRadius: 0, - color: '#fff', - fontSize: 14, - outline: 'none', - transition: 'border-color 0.25s', - }} - onFocus={(e) => { - e.target.style.borderBottomColor = 'rgba(99,102,241,0.5)'; - }} - onBlur={(e) => { - e.target.style.borderBottomColor = 'rgba(255,255,255,0.1)'; - }} - /> -
- - {/* Submit */}