diff --git a/frontend/src/components/login/AuroraView.tsx b/frontend/src/components/login/AuroraView.tsx
new file mode 100644
index 0000000..8c53ad6
--- /dev/null
+++ b/frontend/src/components/login/AuroraView.tsx
@@ -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 (
+ <>
+
+
+ {/* ═══════════════ 全屏背景容器 ═══════════════ */}
+
+ {/* ────────── 极光光带 1:紫罗兰色 ────────── */}
+
+
+ {/* ────────── 极光光带 2:翠绿色 ────────── */}
+
+
+ {/* ────────── 极光光带 3:青蓝色 ────────── */}
+
+
+ {/* ────────── 极光光带 4:紫绿混合 ────────── */}
+
+
+ {/* ────────── 星光点缀 ────────── */}
+ {STARS.map((star, i) => (
+
+ ))}
+
+ {/* ═══════════════ 登录卡片 ═══════════════ */}
+
+ {/* ──────── 品牌区域 ──────── */}
+
+ {/* Logo */}
+
+
+ {/* 标题 */}
+
+ SQL审核平台
+
+
+ {/* 副标题 */}
+
+ 企业级数据库审核与合规管理
+
+
+
+ {/* ──────── 表单区域 ──────── */}
+
+
+ {/* ──────── 版权信息 ──────── */}
+
+ © 2025 SQL审核平台
+
+
+
+ {/* ──────── 底部辉光装饰 ──────── */}
+
+
+
+ {/* 全局旋转动画 */}
+
+ >
+ );
+}
diff --git a/frontend/src/components/login/CosmosView.tsx b/frontend/src/components/login/CosmosView.tsx
new file mode 100644
index 0000000..09329f6
--- /dev/null
+++ b/frontend/src/components/login/CosmosView.tsx
@@ -0,0 +1,547 @@
+import React, { useMemo } from 'react';
+import { useLogin } from '@/hooks/useLogin';
+
+/* ── 动画关键帧 ── */
+const KEYFRAMES = `
+@keyframes star-twinkle {
+ 0%, 100% { opacity: 0.3; transform: scale(0.8); }
+ 50% { opacity: 1; transform: scale(1.2); }
+}
+
+@keyframes meteor-fly {
+ 0% { transform: translateX(0) translateY(0) rotate(-45deg); opacity: 1; }
+ 100% { transform: translateX(600px) translateY(600px) rotate(-45deg); opacity: 0; }
+}
+
+@keyframes planet-rotate {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(360deg); }
+}
+
+@keyframes float-particle {
+ 0%, 100% { transform: translateY(0) translateX(0); opacity: 0.4; }
+ 25% { transform: translateY(-20px) translateX(10px); opacity: 0.8; }
+ 50% { transform: translateY(-40px) translateX(-5px); opacity: 0.5; }
+ 75% { transform: translateY(-20px) translateX(15px); opacity: 0.9; }
+}
+
+@keyframes nebula-drift {
+ 0%, 100% { transform: translate(0, 0) scale(1); }
+ 33% { transform: translate(30px, -20px) scale(1.05); }
+ 66% { transform: translate(-20px, 15px) scale(0.95); }
+}
+
+@keyframes card-glow {
+ 0%, 100% { box-shadow: 0 0 0 1px rgba(255,255,255,0.03), 0 24px 80px rgba(0,0,0,0.5), 0 0 60px rgba(79,70,229,0.08); }
+ 50% { box-shadow: 0 0 0 1px rgba(255,255,255,0.05), 0 24px 80px rgba(0,0,0,0.5), 0 0 80px rgba(139,92,246,0.12); }
+}
+
+@keyframes shooting-star {
+ 0% { transform: translateX(0) translateY(0) rotate(-35deg) scaleX(1); opacity: 1; }
+ 70% { opacity: 0.6; }
+ 100% { transform: translateX(500px) translateY(500px) rotate(-35deg) scaleX(0.5); opacity: 0; }
+}
+`;
+
+/* ── 类型 ── */
+interface Star {
+ id: number;
+ x: number;
+ y: number;
+ size: number;
+ opacity: number;
+ color: string;
+ twinkle: boolean;
+ delay: number;
+ duration: number;
+}
+
+interface Particle {
+ id: number;
+ x: number;
+ y: number;
+ size: number;
+ delay: number;
+ duration: number;
+}
+
+/* ── 组件 ── */
+export default function CosmosView(): JSX.Element {
+ const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin();
+
+ /* 生成静态星星数据 */
+ const stars = useMemo(() => {
+ const colors = ['#ffffff', '#dbeafe', '#e0e7ff', '#f3e8ff', '#ede9fe'];
+ return Array.from({ length: 45 }, (_, i) => ({
+ id: i,
+ x: Math.random() * 100,
+ y: Math.random() * 100,
+ size: Math.random() * 2.5 + 0.5,
+ opacity: Math.random() * 0.7 + 0.3,
+ color: colors[Math.floor(Math.random() * colors.length)],
+ twinkle: Math.random() > 0.4,
+ delay: Math.random() * 5,
+ duration: Math.random() * 2 + 1.5,
+ }));
+ }, []);
+
+ /* 生成漂浮粒子数据 */
+ const particles = useMemo(() => {
+ return Array.from({ length: 15 }, (_, i) => ({
+ id: i,
+ x: Math.random() * 100,
+ y: Math.random() * 100,
+ size: Math.random() * 2 + 1,
+ delay: Math.random() * 6,
+ duration: Math.random() * 4 + 4,
+ }));
+ }, []);
+
+ /* 输入框基础样式 */
+ const inputStyle: React.CSSProperties = {
+ width: '100%',
+ height: 48,
+ padding: '0 16px',
+ background: 'rgba(255,255,255,0.05)',
+ border: '1px solid rgba(255,255,255,0.08)',
+ borderRadius: 12,
+ color: '#fff',
+ fontSize: 14,
+ outline: 'none',
+ transition: 'all 0.25s ease',
+ boxSizing: 'border-box',
+ };
+
+ const isFormValid = username.length > 0 && password.length > 0;
+
+ return (
+
+
+
+ {/* ── 星云色块 ── */}
+
+
+
+
+ {/* ── 星星层 ── */}
+ {stars.map((star) => (
+
+ ))}
+
+ {/* ── 流星 ── */}
+
+
+
+ {/* ── 漂浮粒子星尘 ── */}
+ {particles.map((p) => (
+
+ ))}
+
+ {/* ── 行星装饰(左下角) ── */}
+
+ {/* 行星本体 */}
+
+ {/* 行星光环 */}
+
+ {/* 内环 */}
+
+
+
+ {/* ── 小行星(右上角装饰) ── */}
+
+
+ {/* ── 登录卡片 ── */}
+
+ {/* 品牌区域 */}
+
+ {/* Logo */}
+
+
+ SQL审核平台
+
+
+ 企业级数据库审核与合规管理
+
+
+
+ {/* 表单区域 */}
+
+
+ {/* 底部版权 */}
+
+ © 2025 SQL审核平台 — 企业级数据库安全合规
+
+
+
+ {/* 全局旋转动画补充 */}
+
+
+ );
+}
diff --git a/frontend/src/components/login/GradientMeshView.tsx b/frontend/src/components/login/GradientMeshView.tsx
new file mode 100644
index 0000000..96779a9
--- /dev/null
+++ b/frontend/src/components/login/GradientMeshView.tsx
@@ -0,0 +1,362 @@
+import React, { useState } from 'react';
+import { useLogin } from '@/hooks/useLogin';
+
+/* ------------------------------------------------------------------ */
+/* KEYFRAMES */
+/* ------------------------------------------------------------------ */
+const KEYFRAMES = `
+@keyframes mesh-drift-1 {
+ 0%, 100% { transform: translate(0, 0); }
+ 50% { transform: translate(30px, 20px); }
+}
+@keyframes mesh-drift-2 {
+ 0%, 100% { transform: translate(0, 0); }
+ 50% { transform: translate(-25px, -30px); }
+}
+@keyframes mesh-drift-3 {
+ 0%, 100% { transform: translate(0, 0); }
+ 50% { transform: translate(20px, -25px); }
+}
+@keyframes mesh-drift-4 {
+ 0%, 100% { transform: translate(0, 0); }
+ 50% { transform: translate(-30px, 20px); }
+}
+@keyframes mesh-drift-5 {
+ 0%, 100% { transform: translate(0, 0); }
+ 50% { transform: translate(25px, 30px); }
+}
+@keyframes card-glow {
+ 0%, 100% { opacity: 0.4; }
+ 50% { opacity: 0.7; }
+}
+@keyframes input-glow-pulse {
+ 0%, 100% { opacity: 0.3; }
+ 50% { opacity: 0.6; }
+}
+`;
+
+/* ------------------------------------------------------------------ */
+/* COMPONENT */
+/* ------------------------------------------------------------------ */
+export default function GradientMeshView(): React.JSX.Element {
+ const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin();
+ const [focusedField, setFocusedField] = useState(null);
+ const [hoverBtn, setHoverBtn] = useState(false);
+
+ const isReady = username.trim().length > 0 && password.trim().length > 0;
+
+ /* ---- gradient mesh blobs ---- */
+ const blobs: React.CSSProperties[] = [
+ {
+ position: 'fixed', top: '-100px', left: '-100px',
+ width: '600px', height: '600px',
+ background: 'radial-gradient(circle, rgba(99, 102, 241, 0.3), transparent 70%)',
+ filter: 'blur(80px)', pointerEvents: 'none',
+ animation: 'mesh-drift-1 12s ease-in-out infinite',
+ },
+ {
+ position: 'fixed', bottom: '-80px', right: '-80px',
+ width: '500px', height: '500px',
+ background: 'radial-gradient(circle, rgba(244, 63, 94, 0.2), transparent 70%)',
+ filter: 'blur(90px)', pointerEvents: 'none',
+ animation: 'mesh-drift-2 10s ease-in-out infinite',
+ },
+ {
+ position: 'fixed', top: '40%', right: '10%',
+ width: '400px', height: '400px',
+ background: 'radial-gradient(circle, rgba(16, 185, 129, 0.15), transparent 70%)',
+ filter: 'blur(100px)', pointerEvents: 'none',
+ animation: 'mesh-drift-3 14s ease-in-out infinite',
+ },
+ {
+ position: 'fixed', bottom: '5%', left: '5%',
+ width: '450px', height: '450px',
+ background: 'radial-gradient(circle, rgba(245, 158, 11, 0.1), transparent 70%)',
+ filter: 'blur(85px)', pointerEvents: 'none',
+ animation: 'mesh-drift-4 11s ease-in-out infinite',
+ },
+ {
+ position: 'fixed', top: '-50px', right: '20%',
+ width: '550px', height: '550px',
+ background: 'radial-gradient(circle, rgba(139, 92, 246, 0.2), transparent 70%)',
+ filter: 'blur(95px)', pointerEvents: 'none',
+ animation: 'mesh-drift-5 13s ease-in-out infinite',
+ },
+ ];
+
+ /* ---- input base style ---- */
+ const inputBase: React.CSSProperties = {
+ width: '100%',
+ background: 'rgba(255,255,255,0.04)',
+ border: '1px solid rgba(255,255,255,0.06)',
+ borderRadius: 12,
+ padding: '14px 18px',
+ color: '#fff',
+ fontSize: 15,
+ outline: 'none',
+ transition: 'all 0.25s ease',
+ boxSizing: 'border-box',
+ };
+
+ const getInputStyle = (field: string): React.CSSProperties => ({
+ ...inputBase,
+ borderColor: focusedField === field ? 'rgba(99,102,241,0.5)' : 'rgba(255,255,255,0.06)',
+ background: focusedField === field ? 'rgba(255,255,255,0.07)' : 'rgba(255,255,255,0.04)',
+ });
+
+ /* ---- card top accent line ---- */
+ const topAccent: React.CSSProperties = {
+ position: 'absolute',
+ top: 0, left: 24, right: 24,
+ height: 2,
+ borderRadius: 1,
+ background: 'linear-gradient(90deg, #6366f1, #f43f5e, #10b981)',
+ opacity: 0.6,
+ };
+
+ /* ---- subtle glow inside card bottom ---- */
+ const innerGlow: React.CSSProperties = {
+ position: 'absolute',
+ bottom: -60, left: '50%',
+ transform: 'translateX(-50%)',
+ width: '70%', height: 120,
+ background: 'radial-gradient(ellipse, rgba(99,102,241,0.08), transparent 70%)',
+ filter: 'blur(40px)',
+ pointerEvents: 'none',
+ animation: 'card-glow 8s ease-in-out infinite',
+ };
+
+ return (
+ <>
+
+
+ {/* ===================== ROOT CONTAINER ===================== */}
+
+ {/* ---- gradient mesh blobs ---- */}
+ {blobs.map((b, i) => (
+
+ ))}
+
+ {/* ---- subtle dot-grid texture ---- */}
+
+
+ {/* ===================== LOGIN CARD ===================== */}
+
+ {/* top accent line */}
+
+
+ {/* inner glow */}
+
+
+ {/* ---- brand ---- */}
+
+ {/* Logo */}
+
+
+
+ SQL审核平台
+
+
+ 企业级数据库审核与合规管理
+
+
+
+ {/* ---- form ---- */}
+
+
+ {/* ---- copyright ---- */}
+
+ © 2025 SQL审核平台
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/components/login/InkWashView.tsx b/frontend/src/components/login/InkWashView.tsx
new file mode 100644
index 0000000..0f9a84b
--- /dev/null
+++ b/frontend/src/components/login/InkWashView.tsx
@@ -0,0 +1,479 @@
+import React from 'react';
+import { useLogin } from '@/hooks/useLogin';
+
+/* ------------------------------------------------------------------ */
+/* KEYFRAMES */
+/* ------------------------------------------------------------------ */
+const KEYFRAMES = `
+@keyframes ink-spread {
+ 0%, 100% {
+ transform: scale(1);
+ opacity: 0.45;
+ }
+ 50% {
+ transform: scale(1.15);
+ opacity: 0.6;
+ }
+}
+
+@keyframes mist-flow {
+ 0% {
+ transform: translateX(-8%);
+ }
+ 50% {
+ transform: translateX(4%);
+ }
+ 100% {
+ transform: translateX(-8%);
+ }
+}
+
+@keyframes gold-shimmer {
+ 0%, 100% {
+ opacity: 0.35;
+ transform: scaleX(1);
+ }
+ 50% {
+ opacity: 0.8;
+ transform: scaleX(1.06);
+ }
+}
+`;
+
+/* ------------------------------------------------------------------ */
+/* Component */
+/* ------------------------------------------------------------------ */
+export default function InkWashView(): JSX.Element {
+ const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin();
+
+ return (
+ <>
+
+
+ {/* ===================== 全屏容器 ===================== */}
+
+ {/* ────────── 水墨晕染装饰 ────────── */}
+ {/* 左上角淡墨点 */}
+
+ {/* 右下角浓墨点 */}
+
+ {/* 中央偏上淡淡墨痕 */}
+
+
+ {/* ────────── 远山轮廓 ────────── */}
+ {/* 最远山 */}
+
+ {/* 中山 */}
+
+ {/* 近山 */}
+
+
+ {/* ────────── 雾气效果 ────────── */}
+
+
+ {/* ────────── 金色点缀线(水面微光) ────────── */}
+
+
+
+ {/* ────────── 竖排 SQL 背景装饰 ────────── */}
+
+ SQL
+
+
+ AUDIT
+
+
+ {/* ===================== 登录卡片 ===================== */}
+
+ {/* ──── 品牌区域 ──── */}
+
+ {/* Logo */}
+
+
+ {/* 标题 */}
+
+ SQL审核平台
+
+
+ {/* 副标题 */}
+
+ 企业级数据库审核与合规管理
+
+
+
+ {/* ──── 中国风细线装饰(上方) ──── */}
+
+
+ {/* ──── 表单 ──── */}
+
+
+ {/* ──── 中国风细线装饰(下方) ──── */}
+
+
+ {/* ──── 版权信息 ──── */}
+
+ © SQL Audit Platform. All rights reserved.
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/components/login/NeonCityView.tsx b/frontend/src/components/login/NeonCityView.tsx
new file mode 100644
index 0000000..754f22a
--- /dev/null
+++ b/frontend/src/components/login/NeonCityView.tsx
@@ -0,0 +1,505 @@
+import React from 'react';
+import { useLogin } from '@/hooks/useLogin';
+
+const KEYFRAMES = `
+@keyframes neon-pulse {
+ 0%, 100% { opacity: 0.6; box-shadow: 0 0 10px currentColor, 0 0 20px currentColor, 0 0 40px currentColor; }
+ 50% { opacity: 1; box-shadow: 0 0 20px currentColor, 0 0 40px currentColor, 0 0 80px currentColor; }
+}
+
+@keyframes neon-flicker {
+ 0%, 100% { opacity: 1; }
+ 3% { opacity: 0.4; }
+ 6% { opacity: 1; }
+ 7% { opacity: 0.2; }
+ 8% { opacity: 1; }
+ 92% { opacity: 1; }
+ 93% { opacity: 0.3; }
+ 94% { opacity: 1; }
+}
+
+@keyframes rain-fall {
+ 0% { transform: translateY(-100vh) translateX(0); opacity: 0; }
+ 10% { opacity: 0.6; }
+ 90% { opacity: 0.6; }
+ 100% { transform: translateY(100vh) translateX(20px); opacity: 0; }
+}
+
+@keyframes grid-move {
+ 0% { transform: perspective(500px) rotateX(60deg) translateY(0); }
+ 100% { transform: perspective(500px) rotateX(60deg) translateY(40px); }
+}
+
+@keyframes city-breathe {
+ 0%, 100% { transform: scaleY(1); }
+ 50% { transform: scaleY(1.02); }
+}
+
+@keyframes neon-glow-text {
+ 0%, 100% { text-shadow: 0 0 10px rgba(236, 72, 153, 0.5), 0 0 20px rgba(236, 72, 153, 0.3); }
+ 50% { text-shadow: 0 0 20px rgba(236, 72, 153, 0.8), 0 0 40px rgba(236, 72, 153, 0.5); }
+}
+`;
+
+// Building data: [width, heightPercent, leftPercent, glowColor]
+const BUILDINGS: [number, number, number, string][] = [
+ [40, 18, 0, 'rgba(236, 72, 153, 0.4)'],
+ [55, 28, 4, 'rgba(168, 85, 247, 0.35)'],
+ [35, 15, 9, 'rgba(6, 182, 212, 0.3)'],
+ [70, 35, 12, 'rgba(236, 72, 153, 0.45)'],
+ [45, 22, 19, 'rgba(168, 85, 247, 0.4)'],
+ [50, 30, 23, 'rgba(6, 182, 212, 0.35)'],
+ [30, 16, 28, 'rgba(236, 72, 153, 0.3)'],
+ [80, 38, 31, 'rgba(168, 85, 247, 0.5)'],
+ [42, 20, 39, 'rgba(6, 182, 212, 0.4)'],
+ [60, 32, 43, 'rgba(236, 72, 153, 0.45)'],
+ [38, 17, 49, 'rgba(168, 85, 247, 0.3)'],
+ [75, 36, 52, 'rgba(6, 182, 212, 0.5)'],
+ [48, 25, 60, 'rgba(236, 72, 153, 0.4)'],
+ [55, 30, 65, 'rgba(168, 85, 247, 0.45)'],
+ [33, 14, 70, 'rgba(6, 182, 212, 0.3)'],
+ [85, 40, 73, 'rgba(236, 72, 153, 0.5)'],
+ [44, 21, 82, 'rgba(168, 85, 247, 0.4)'],
+ [58, 33, 86, 'rgba(6, 182, 212, 0.45)'],
+ [36, 16, 92, 'rgba(236, 72, 153, 0.35)'],
+ [50, 27, 95, 'rgba(168, 85, 247, 0.4)'],
+];
+
+// Neon tube data: [topPercent, color, animationDelay, animationDuration]
+const NEON_TUBES: [number, string, string, string][] = [
+ [22, '#ec4899', '0s', '3s'],
+ [38, '#06b6d4', '1s', '4s'],
+ [52, '#a855f7', '2s', '3.5s'],
+];
+
+// Rain drop data: [leftPercent, delay, duration]
+const RAIN_DROPS: [number, string, string][] = [
+ [5, '0s', '1.5s'],
+ [15, '0.3s', '1.8s'],
+ [25, '0.7s', '1.3s'],
+ [35, '0.2s', '1.6s'],
+ [45, '0.9s', '1.4s'],
+ [55, '0.5s', '1.7s'],
+ [65, '0.1s', '1.5s'],
+ [75, '0.8s', '1.9s'],
+ [85, '0.4s', '1.3s'],
+ [95, '0.6s', '1.6s'],
+ [10, '1.1s', '1.4s'],
+ [30, '1.3s', '1.7s'],
+ [50, '1.0s', '1.5s'],
+ [70, '1.5s', '1.8s'],
+ [90, '1.2s', '1.4s'],
+ [20, '0.15s', '2.0s'],
+ [40, '0.85s', '1.35s'],
+ [60, '1.25s', '1.65s'],
+ [80, '0.45s', '1.75s'],
+ [8, '0.95s', '1.55s'],
+];
+
+export default function NeonCityView(): JSX.Element {
+ const { username, password, loading, error, setUsername, setPassword, handleLogin } = useLogin();
+
+ return (
+ <>
+
+
+ {/* Grid floor background */}
+
+
+ {/* Neon tubes */}
+ {NEON_TUBES.map(([top, color, delay, duration], i) => (
+
+ ))}
+
+ {/* City skyline buildings */}
+
+ {BUILDINGS.map(([width, heightPct, leftPct, glowColor], i) => (
+
+ ))}
+
+
+ {/* Rain drops */}
+ {RAIN_DROPS.map(([left, delay, duration], i) => (
+
+ ))}
+
+ {/* Fog layer */}
+
+
+ {/* Top glow */}
+
+
+ {/* Login card */}
+
+ {/* Top neon line decoration */}
+
+
+ {/* Brand area */}
+
+ {/* Logo */}
+
+
+ {/* Title */}
+
+ SQL审核平台
+
+
+ {/* Subtitle */}
+
+ 企业级数据库审核与合规管理
+
+
+
+ {/* Login form */}
+
+
+ {/* Copyright */}
+
+ © SQL审核平台 · 安全合规的数据库管理
+
+
+
+ >
+ );
+}
diff --git a/frontend/src/pages/AppearanceSettings.tsx b/frontend/src/pages/AppearanceSettings.tsx
index f79a511..80b11b9 100644
--- a/frontend/src/pages/AppearanceSettings.tsx
+++ b/frontend/src/pages/AppearanceSettings.tsx
@@ -12,6 +12,11 @@ const LOGIN_PREVIEW_COLORS: Record
)}
+ {opt.id === 'aurora' && (
+
+
+
+ {[15, 30, 55, 75].map(t => (
+
+ ))}
+
+
+ )}
+ {opt.id === 'cosmos' && (
+
+
+
+ {[10, 25, 40, 60, 80].map(t => (
+
+ ))}
+
+
+
+ )}
+ {opt.id === 'inkwash' && (
+
+ )}
+ {opt.id === 'neoncity' && (
+
+
+
+ {[10, 25, 40, 55, 70, 85].map((l, i) => (
+
+ ))}
+
+
+ )}
+ {opt.id === 'gradientmesh' && (
+
+ )}
{/* Active check mark */}
diff --git a/frontend/src/pages/LoginPage.tsx b/frontend/src/pages/LoginPage.tsx
index 515bf46..3b08226 100644
--- a/frontend/src/pages/LoginPage.tsx
+++ b/frontend/src/pages/LoginPage.tsx
@@ -4,8 +4,13 @@ import CenteredCard from '@/components/login/CenteredCard';
import SidePanel from '@/components/login/SidePanel';
import FullImage from '@/components/login/FullImage';
import MinimalDark from '@/components/login/MinimalDark';
+import AuroraView from '@/components/login/AuroraView';
+import CosmosView from '@/components/login/CosmosView';
+import InkWashView from '@/components/login/InkWashView';
+import NeonCityView from '@/components/login/NeonCityView';
+import GradientMeshView from '@/components/login/GradientMeshView';
-export type LoginStyle = 'split' | 'centered' | 'sidepanel' | 'fullimage' | 'minimal';
+export type LoginStyle = 'split' | 'centered' | 'sidepanel' | 'fullimage' | 'minimal' | 'aurora' | 'cosmos' | 'inkwash' | 'neoncity' | 'gradientmesh';
const LOGIN_STYLES: Record = {
split: SplitView,
@@ -13,14 +18,24 @@ const LOGIN_STYLES: Record = {
sidepanel: SidePanel,
fullimage: FullImage,
minimal: MinimalDark,
+ aurora: AuroraView,
+ cosmos: CosmosView,
+ inkwash: InkWashView,
+ neoncity: NeonCityView,
+ gradientmesh: GradientMeshView,
};
export const LOGIN_STYLE_OPTIONS: { id: LoginStyle; name: string; desc: string }[] = [
- { id: 'split', name: '经典分屏', desc: '发光网格晶格,Tron 科技感' },
+ { id: 'split', name: '经典分屏', desc: '左黑右白,晶格科技感' },
{ id: 'centered', name: '居中卡片', desc: '黎明光柱,金色晨曦氛围' },
{ id: 'sidepanel', name: '侧边面板', desc: '深海波浪,生物发光粒子' },
{ id: 'fullimage', name: '全屏背景', desc: '科技背景,毛玻璃卡片' },
{ id: 'minimal', name: '深蓝紫曲线', desc: '优雅暗黑,粉紫流动曲线' },
+ { id: 'aurora', name: '极光之境', desc: '北极光动态渐变,紫绿流光' },
+ { id: 'cosmos', name: '星际漫游', desc: '深邃星空星云,银白粒子' },
+ { id: 'inkwash', name: '水墨山水', desc: '东方水墨意境,动态墨痕' },
+ { id: 'neoncity', name: '霓虹都市', desc: '赛博朋克城市,彩色霓虹' },
+ { id: 'gradientmesh', name: '渐变网格', desc: '柔和渐变网格,现代呼吸感' },
];
export default function LoginPage() {