feat: 霓虹都市→白日梦境 + 渐变网格→云石纹理 — 两个白色浅色主题登录页重写
This commit is contained in:
1 parent
b5739ba955
commit
5a61babd33
241 files changed
+58974
-7370
No files matched your search
@@ -0,0 +1,429 @@
|
||||
import React from 'react';
|
||||
import { useLogin } from '@/hooks/useLogin';
|
||||
|
||||
/* ──────────────── 极光之境 · 登录组件 ──────────────── */
|
||||
|
||||
const KEYFRAMES = `
|
||||
@keyframes aurora-drift-1 {
|
||||
0% { transform: translate(-30%, -10%) rotate(-12deg) scaleX(1.2); opacity: 0.35; }
|
||||
25% { transform: translate(-10%, 5%) rotate(-8deg) scaleX(1.5); opacity: 0.5; }
|
||||
50% { transform: translate(10%, -5%) rotate(-14deg) scaleX(1.3); opacity: 0.4; }
|
||||
75% { transform: translate(-5%, 10%) rotate(-10deg) scaleX(1.6); opacity: 0.55; }
|
||||
100% { transform: translate(-30%, -10%) rotate(-12deg) scaleX(1.2); opacity: 0.35; }
|
||||
}
|
||||
|
||||
@keyframes aurora-drift-2 {
|
||||
0% { transform: translate(20%, 15%) rotate(8deg) scaleX(1.3); opacity: 0.25; }
|
||||
30% { transform: translate(-10%, -5%) rotate(12deg) scaleX(1.6); opacity: 0.45; }
|
||||
60% { transform: translate(5%, 10%) rotate(6deg) scaleX(1.4); opacity: 0.35; }
|
||||
100% { transform: translate(20%, 15%) rotate(8deg) scaleX(1.3); opacity: 0.25; }
|
||||
}
|
||||
|
||||
@keyframes aurora-drift-3 {
|
||||
0% { transform: translate(-15%, 25%) rotate(-5deg) scaleX(1.5); opacity: 0.3; }
|
||||
33% { transform: translate(15%, 5%) rotate(-9deg) scaleX(1.8); opacity: 0.5; }
|
||||
66% { transform: translate(0%, 20%) rotate(-3deg) scaleX(1.4); opacity: 0.4; }
|
||||
100% { transform: translate(-15%, 25%) rotate(-5deg) scaleX(1.5); opacity: 0.3; }
|
||||
}
|
||||
|
||||
@keyframes aurora-drift-4 {
|
||||
0% { transform: translate(10%, -15%) rotate(15deg) scaleX(1.4); opacity: 0.2; }
|
||||
40% { transform: translate(-20%, 0%) rotate(10deg) scaleX(1.7); opacity: 0.4; }
|
||||
80% { transform: translate(0%, 8%) rotate(18deg) scaleX(1.5); opacity: 0.3; }
|
||||
100% { transform: translate(10%, -15%) rotate(15deg) scaleX(1.4); opacity: 0.2; }
|
||||
}
|
||||
|
||||
@keyframes twinkle {
|
||||
0%, 100% { opacity: 0.15; transform: scale(0.8); }
|
||||
50% { opacity: 0.9; transform: scale(1.2); }
|
||||
}
|
||||
|
||||
@keyframes float-card {
|
||||
0%, 100% { transform: translateY(0); }
|
||||
50% { transform: translateY(-6px); }
|
||||
}
|
||||
|
||||
@keyframes pulse-glow {
|
||||
0%, 100% { box-shadow: 0 0 20px rgba(124, 58, 237, 0.15), 0 0 60px rgba(5, 150, 105, 0.08); }
|
||||
50% { box-shadow: 0 0 30px rgba(124, 58, 237, 0.25), 0 0 80px rgba(5, 150, 105, 0.15); }
|
||||
}
|
||||
`;
|
||||
|
||||
/* ──────────────── 星星数据 ──────────────── */
|
||||
const STARS = [
|
||||
{ left: '8%', top: '5%', size: 2, delay: 0, duration: 3 },
|
||||
{ left: '18%', top: '15%', size: 1.5, delay: 0.7, duration: 4 },
|
||||
{ left: '5%', top: '35%', size: 1, delay: 1.2, duration: 2.5 },
|
||||
{ left: '25%', top: '8%', size: 2.5, delay: 0.3, duration: 3.5 },
|
||||
{ left: '75%', top: '6%', size: 1.5, delay: 1.5, duration: 4.5 },
|
||||
{ left: '88%', top: '12%', size: 2, delay: 0.5, duration: 3 },
|
||||
{ left: '92%', top: '30%', size: 1, delay: 2, duration: 2.8 },
|
||||
{ left: '82%', top: '45%', size: 1.5, delay: 0.9, duration: 3.8 },
|
||||
{ left: '68%', top: '18%', size: 1, delay: 1.8, duration: 2.2 },
|
||||
{ left: '38%', top: '3%', size: 2, delay: 0.2, duration: 4 },
|
||||
{ left: '55%', top: '10%', size: 1.5, delay: 1.1, duration: 3.2 },
|
||||
{ left: '45%', top: '22%', size: 1, delay: 0.6, duration: 2.6 },
|
||||
{ left: '12%', top: '55%', size: 1, delay: 1.6, duration: 3.6 },
|
||||
{ left: '95%', top: '55%', size: 1.5, delay: 0.4, duration: 2.4 },
|
||||
{ left: '60%', top: '30%', size: 1, delay: 2.2, duration: 4.2 },
|
||||
];
|
||||
|
||||
export default function AuroraView(): JSX.Element {
|
||||
const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin();
|
||||
|
||||
return (
|
||||
<>
|
||||
<style>{KEYFRAMES}</style>
|
||||
|
||||
{/* ═══════════════ 全屏背景容器 ═══════════════ */}
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
minHeight: '100vh',
|
||||
width: '100%',
|
||||
overflow: 'hidden',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif',
|
||||
background: 'linear-gradient(180deg, #050810 0%, #0a0e1a 30%, #0d1425 60%, #080c14 100%)',
|
||||
}}
|
||||
>
|
||||
{/* ────────── 极光光带 1:紫罗兰色 ────────── */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '15%',
|
||||
left: '10%',
|
||||
width: '80%',
|
||||
height: '35%',
|
||||
background: 'linear-gradient(135deg, rgba(168, 85, 247, 0.6) 0%, rgba(124, 58, 237, 0.3) 40%, transparent 80%)',
|
||||
filter: 'blur(60px)',
|
||||
borderRadius: '50%',
|
||||
animation: 'aurora-drift-1 18s ease-in-out infinite',
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ────────── 极光光带 2:翠绿色 ────────── */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '25%',
|
||||
left: '20%',
|
||||
width: '75%',
|
||||
height: '30%',
|
||||
background: 'linear-gradient(120deg, rgba(16, 185, 129, 0.5) 0%, rgba(5, 150, 105, 0.25) 50%, transparent 90%)',
|
||||
filter: 'blur(70px)',
|
||||
borderRadius: '50%',
|
||||
animation: 'aurora-drift-2 22s ease-in-out infinite',
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ────────── 极光光带 3:青蓝色 ────────── */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '35%',
|
||||
left: '5%',
|
||||
width: '70%',
|
||||
height: '28%',
|
||||
background: 'linear-gradient(145deg, rgba(6, 182, 212, 0.4) 0%, rgba(6, 182, 212, 0.15) 45%, transparent 85%)',
|
||||
filter: 'blur(55px)',
|
||||
borderRadius: '50%',
|
||||
animation: 'aurora-drift-3 20s ease-in-out infinite',
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ────────── 极光光带 4:紫绿混合 ────────── */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
top: '10%',
|
||||
left: '30%',
|
||||
width: '65%',
|
||||
height: '40%',
|
||||
background: 'linear-gradient(100deg, rgba(124, 58, 237, 0.35) 0%, rgba(16, 185, 129, 0.2) 50%, rgba(6, 182, 212, 0.15) 100%)',
|
||||
filter: 'blur(75px)',
|
||||
borderRadius: '50%',
|
||||
animation: 'aurora-drift-4 25s ease-in-out infinite',
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* ────────── 星光点缀 ────────── */}
|
||||
{STARS.map((star, i) => (
|
||||
<div
|
||||
key={i}
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: star.left,
|
||||
top: star.top,
|
||||
width: star.size,
|
||||
height: star.size,
|
||||
borderRadius: '50%',
|
||||
background: '#fff',
|
||||
boxShadow: `0 0 ${star.size * 2}px rgba(255,255,255,0.5)`,
|
||||
animation: `twinkle ${star.duration}s ease-in-out ${star.delay}s infinite`,
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
|
||||
{/* ═══════════════ 登录卡片 ═══════════════ */}
|
||||
<div
|
||||
style={{
|
||||
position: 'relative',
|
||||
zIndex: 10,
|
||||
width: '100%',
|
||||
maxWidth: 400,
|
||||
margin: '0 20px',
|
||||
padding: '44px 36px',
|
||||
borderRadius: 20,
|
||||
background: 'rgba(8, 12, 25, 0.65)',
|
||||
backdropFilter: 'blur(24px)',
|
||||
WebkitBackdropFilter: 'blur(24px)',
|
||||
border: '1px solid rgba(255,255,255,0.06)',
|
||||
boxShadow: '0 0 0 1px rgba(255,255,255,0.04), 0 20px 60px rgba(0,0,0,0.4)',
|
||||
animation: 'float-card 8s ease-in-out infinite, pulse-glow 6s ease-in-out infinite',
|
||||
}}
|
||||
>
|
||||
{/* ──────── 品牌区域 ──────── */}
|
||||
<div style={{ textAlign: 'center', marginBottom: 32 }}>
|
||||
{/* Logo */}
|
||||
<div
|
||||
style={{
|
||||
width: 44,
|
||||
height: 44,
|
||||
borderRadius: 12,
|
||||
background: 'linear-gradient(135deg, #7c3aed 0%, #059669 100%)',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
margin: '0 auto 16px',
|
||||
boxShadow: '0 4px 20px rgba(124, 58, 237, 0.3), 0 2px 10px rgba(5, 150, 105, 0.2)',
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
width={22}
|
||||
height={22}
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
stroke="#fff"
|
||||
strokeWidth={2}
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
>
|
||||
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
||||
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
|
||||
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
||||
</svg>
|
||||
</div>
|
||||
|
||||
{/* 标题 */}
|
||||
<h1
|
||||
style={{
|
||||
fontSize: 22,
|
||||
fontWeight: 600,
|
||||
color: '#fff',
|
||||
margin: '0 0 6px',
|
||||
letterSpacing: 0.5,
|
||||
}}
|
||||
>
|
||||
SQL审核平台
|
||||
</h1>
|
||||
|
||||
{/* 副标题 */}
|
||||
<p
|
||||
style={{
|
||||
fontSize: 14,
|
||||
color: 'rgba(255,255,255,0.4)',
|
||||
margin: 0,
|
||||
letterSpacing: 0.3,
|
||||
}}
|
||||
>
|
||||
企业级数据库审核与合规管理
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* ──────── 表单区域 ──────── */}
|
||||
<form onSubmit={handleLogin} noValidate>
|
||||
{/* 错误提示 */}
|
||||
{error && (
|
||||
<div
|
||||
style={{
|
||||
marginBottom: 16,
|
||||
padding: '10px 14px',
|
||||
borderRadius: 10,
|
||||
background: 'rgba(239, 68, 68, 0.12)',
|
||||
border: '1px solid rgba(239, 68, 68, 0.2)',
|
||||
color: '#f87171',
|
||||
fontSize: 13,
|
||||
textAlign: 'center',
|
||||
}}
|
||||
>
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* 用户名输入框 */}
|
||||
<div style={{ marginBottom: 14 }}>
|
||||
<input
|
||||
type="text"
|
||||
placeholder="用户名"
|
||||
value={username}
|
||||
onChange={(e) => setUsername(e.target.value)}
|
||||
disabled={loading}
|
||||
autoComplete="username"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 46,
|
||||
padding: '0 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',
|
||||
boxSizing: 'border-box',
|
||||
transition: 'border-color 0.25s ease, box-shadow 0.25s ease',
|
||||
fontFamily: 'inherit',
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
e.currentTarget.style.borderColor = 'rgba(124, 58, 237, 0.4)';
|
||||
e.currentTarget.style.boxShadow = '0 0 0 3px rgba(124, 58, 237, 0.08)';
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.08)';
|
||||
e.currentTarget.style.boxShadow = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 密码输入框 */}
|
||||
<div style={{ marginBottom: 20 }}>
|
||||
<input
|
||||
type="password"
|
||||
placeholder="密码"
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
disabled={loading}
|
||||
autoComplete="current-password"
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 46,
|
||||
padding: '0 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',
|
||||
boxSizing: 'border-box',
|
||||
transition: 'border-color 0.25s ease, box-shadow 0.25s ease',
|
||||
fontFamily: 'inherit',
|
||||
}}
|
||||
onFocus={(e) => {
|
||||
e.currentTarget.style.borderColor = 'rgba(124, 58, 237, 0.4)';
|
||||
e.currentTarget.style.boxShadow = '0 0 0 3px rgba(124, 58, 237, 0.08)';
|
||||
}}
|
||||
onBlur={(e) => {
|
||||
e.currentTarget.style.borderColor = 'rgba(255,255,255,0.08)';
|
||||
e.currentTarget.style.boxShadow = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 登录按钮 */}
|
||||
<button
|
||||
type="submit"
|
||||
disabled={!username || !password || loading}
|
||||
style={{
|
||||
width: '100%',
|
||||
height: 46,
|
||||
borderRadius: 12,
|
||||
border: 'none',
|
||||
background: 'linear-gradient(135deg, #7c3aed 0%, #059669 100%)',
|
||||
color: '#fff',
|
||||
fontSize: 15,
|
||||
fontWeight: 500,
|
||||
cursor: !username || !password || loading ? 'not-allowed' : 'pointer',
|
||||
opacity: !username || !password ? 0.55 : 1,
|
||||
transition: 'all 0.3s ease',
|
||||
fontFamily: 'inherit',
|
||||
letterSpacing: 0.5,
|
||||
position: 'relative',
|
||||
overflow: 'hidden',
|
||||
}}
|
||||
onMouseEnter={(e) => {
|
||||
if (username && password && !loading) {
|
||||
e.currentTarget.style.transform = 'translateY(-2px)';
|
||||
e.currentTarget.style.boxShadow = '0 8px 30px rgba(124, 58, 237, 0.35), 0 4px 15px rgba(5, 150, 105, 0.25)';
|
||||
}
|
||||
}}
|
||||
onMouseLeave={(e) => {
|
||||
e.currentTarget.style.transform = 'translateY(0)';
|
||||
e.currentTarget.style.boxShadow = 'none';
|
||||
}}
|
||||
>
|
||||
{loading ? (
|
||||
<span style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', gap: 8 }}>
|
||||
<span
|
||||
style={{
|
||||
display: 'inline-block',
|
||||
width: 16,
|
||||
height: 16,
|
||||
border: '2px solid rgba(255,255,255,0.3)',
|
||||
borderTopColor: '#fff',
|
||||
borderRadius: '50%',
|
||||
animation: 'spin 0.8s linear infinite',
|
||||
}}
|
||||
/>
|
||||
登录中...
|
||||
</span>
|
||||
) : (
|
||||
'登 录'
|
||||
)}
|
||||
</button>
|
||||
</form>
|
||||
|
||||
{/* ──────── 版权信息 ──────── */}
|
||||
<div
|
||||
style={{
|
||||
marginTop: 28,
|
||||
textAlign: 'center',
|
||||
fontSize: 12,
|
||||
color: 'rgba(255,255,255,0.2)',
|
||||
letterSpacing: 0.3,
|
||||
}}
|
||||
>
|
||||
© 2025 SQL审核平台
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ──────── 底部辉光装饰 ──────── */}
|
||||
<div
|
||||
style={{
|
||||
position: 'absolute',
|
||||
bottom: '-20%',
|
||||
left: '50%',
|
||||
transform: 'translateX(-50%)',
|
||||
width: '120%',
|
||||
height: '50%',
|
||||
background: 'radial-gradient(ellipse at center, rgba(124, 58, 237, 0.08) 0%, rgba(5, 150, 105, 0.05) 30%, transparent 70%)',
|
||||
pointerEvents: 'none',
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* 全局旋转动画 */}
|
||||
<style>{`
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
`}</style>
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user