fix(): 1. 流畅动画: 所有交互都使用 cubic-bezier(0.4, 0, 0.2, 1) 缓动函数

2. 层次分明: 通过阴影、渐变、透明度营造深度感
         3. 色彩统一: 以紫蓝色系为主色调,保持视觉一致性
         4. 细节丰富: Logo 流光、卡片条纹、图标动效等微交互
This commit is contained in:
yuj
2025-12-04 18:02:37 +08:00
parent 83a614bd75
commit b995427882
3 changed files with 274 additions and 41 deletions

View File

@@ -29,18 +29,32 @@
box-shadow: 0 8px 20px rgba(0,0,0,0.25); box-shadow: 0 8px 20px rgba(0,0,0,0.25);
} }
.form-split { color: var(--muted); } .form-split { color: var(--muted); }
:root{ :root{ /* 深色科技风主题 - 参考 x.ai */
--bg: #f5f7fb; --bg: #0a0a0f;
--panel: #ffffff; --bg-secondary: #12121a;
--soft: #f1f3f7; --panel: rgba(20, 20, 30, 0.6);
--text: #171a1f; --panel-solid: #14141e;
--muted: #4d5562; --soft: rgba(30, 30, 45, 0.5);
--accent: #5f97d2; --text: #e8e8f0;
--good: #2fb167; --text-secondary: #a0a0b0;
--warn: #caa410; --muted: #6a6a7a;
--bad: #b6404a; --accent: #7c5cff;
--border: #e5e7ef; --accent-glow: rgba(124, 92, 255, 0.3);
--shadow: 0 10px 25px rgba(10,16,25,.08); --accent-gradient: linear-gradient(135deg, #7c5cff 0%, #a084ff 100%);
--primary-gradient: linear-gradient(135deg, #7c5cff 0%, #5d3fd3 100%);
--secondary-gradient: linear-gradient(135deg, #ff6b9d 0%, #c06cf5 100%);
--success-gradient: linear-gradient(135deg, #00d4ff 0%, #0088ff 100%);
--warning-gradient: linear-gradient(135deg, #ff9f1c 0%, #ffbf69 100%);
--info-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
--good: #00d4aa;
--warn: #ffb347;
--bad: #ff6b9d;
--border: rgba(124, 92, 255, 0.15);
--border-subtle: rgba(255, 255, 255, 0.05);
--shadow: 0 10px 40px rgba(0, 0, 0, 0.4);
--shadow-lg: 0 20px 60px rgba(0, 0, 0, 0.6);
--shadow-colored: 0 10px 30px rgba(124, 92, 255, 0.3);
--glow: 0 0 20px rgba(124, 92, 255, 0.4);
} }
:root.light{ :root.light{
--bg: #f5f7fb; --bg: #f5f7fb;
@@ -61,30 +75,115 @@ html,body{height:100%; width:100%; margin:0; padding:0}
body{ body{
margin:0; margin:0;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol"; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
background:var(--bg); background: var(--bg);
color:var(--text); color:var(--text);
display:flex; display:flex;
min-height:100vh; min-height:100vh;
width:100%; width:100%;
overflow:hidden; overflow:hidden;
position: relative;
}
/* 科技感网格背景 - 类似 x.ai */
body::before {
content: '';
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image:
linear-gradient(rgba(124, 92, 255, 0.03) 1px, transparent 1px),
linear-gradient(90deg, rgba(124, 92, 255, 0.03) 1px, transparent 1px);
background-size: 50px 50px;
pointer-events: none;
z-index: 0;
}
/* 光晕效果 */
body::after {
content: '';
position: fixed;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: radial-gradient(
circle at 50% 50%,
rgba(124, 92, 255, 0.08) 0%,
transparent 50%
);
pointer-events: none;
z-index: 0;
animation: pulse 8s ease-in-out infinite;
}
@keyframes pulse {
0%, 100% { opacity: 0.5; transform: scale(1); }
50% { opacity: 1; transform: scale(1.1); }
} }
a{color:inherit; text-decoration:none} a{color:inherit; text-decoration:none}
.container{display:flex; flex:1; width:100vw; height:100vh; max-width:none; margin:0; padding:0} .container{display:flex; flex:1; width:100vw; height:100vh; max-width:none; margin:0; padding:0}
.sidebar{ .sidebar{
border-right:1px solid var(--border); border-right:1px solid rgba(102, 126, 234, 0.1);
background:linear-gradient(180deg, var(--panel), var(--soft)); background: linear-gradient(180deg,
rgba(102, 126, 234, 0.05) 0%,
rgba(118, 75, 162, 0.03) 50%,
var(--panel) 100%
);
backdrop-filter: blur(10px);
padding:20px; height:100vh; flex-shrink:0; padding:20px; height:100vh; flex-shrink:0;
display:flex; flex-direction:column; display:flex; flex-direction:column;
overflow: hidden; overflow: hidden;
position: relative;
} }
.brand{ display:flex; align-items:center; gap:10px; padding:8px 6px; margin-bottom:16px; } .sidebar::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
height: 200px;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.05) 100%);
border-radius: 0 0 50% 50%;
pointer-events: none;
}
.brand{ display:flex; align-items:center; gap:10px; padding:8px 6px; margin-bottom:16px; position: relative; z-index: 1; }
.brand .logo{ .brand .logo{
width:28px; height:28px; border-radius:8px; width:32px; height:32px; border-radius:10px;
background: radial-gradient(120% 120% at 0% 0%, var(--accent) 0%, #9dc3e7 48%, #9394e7 100%); background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
box-shadow:var(--shadow); box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
position: relative;
overflow: hidden;
}
.brand .logo::before {
content: '';
position: absolute;
top: -50%;
left: -50%;
width: 200%;
height: 200%;
background: linear-gradient(
45deg,
transparent,
rgba(255, 255, 255, 0.3),
transparent
);
transform: rotate(45deg);
animation: shimmer 3s infinite;
}
@keyframes shimmer {
0%, 100% { transform: translateX(-100%) translateY(-100%) rotate(45deg); }
50% { transform: translateX(100%) translateY(100%) rotate(45deg); }
}
.brand h1{
font-size:17px;
letter-spacing:.4px;
margin:0;
font-weight:800;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
} }
.brand h1{font-size:16px; letter-spacing:.4px; margin:0; font-weight:700}
.sidegroup{margin-top:16px} .sidegroup{margin-top:16px}
.sidegroup h2{ font-size:11px; text-transform:uppercase; color:var(--muted); letter-spacing:.8px; margin:12px 8px; } .sidegroup h2{ font-size:11px; text-transform:uppercase; color:var(--muted); letter-spacing:.8px; margin:12px 8px; }
@@ -97,14 +196,58 @@ a{color:inherit; text-decoration:none}
.nav a.active{background:var(--soft); border-color:var(--border)} .nav a.active{background:var(--soft); border-color:var(--border)}
.header{ .header{
display:flex; align-items:center; justify-content:space-between; padding:16px 22px; display:flex; align-items:center; justify-content:space-between; padding:18px 24px;
border-bottom:1px solid var(--border); background:var(--panel); z-index:6; flex-shrink:0; border-bottom:1px solid rgba(102, 126, 234, 0.1);
background: linear-gradient(90deg, rgba(255,255,255,0.95) 0%, rgba(255,255,255,0.98) 100%);
backdrop-filter: blur(10px);
z-index:6;
flex-shrink:0;
box-shadow: 0 2px 8px rgba(0,0,0,0.03);
}
.search{
display:flex;
align-items:center;
gap:10px;
background: linear-gradient(135deg, rgba(102, 126, 234, 0.05) 0%, rgba(118, 75, 162, 0.03) 100%);
padding:10px 16px;
border-radius:14px;
border:1px solid rgba(102, 126, 234, 0.15);
transition: all 0.3s ease;
}
.search:focus-within {
border-color: rgba(102, 126, 234, 0.4);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
transform: translateY(-1px);
}
.search input{background:transparent; border:none; outline:none; color:var(--text); width:280px; font-size: 14px;}
.actions{display:flex; align-items:center; gap:12px}
.btn{
padding:10px 18px;
border-radius:12px;
border:1px solid rgba(102, 126, 234, 0.2);
background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.7) 100%);
color:var(--text);
cursor:pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
font-weight: 500;
font-size: 14px;
}
.btn:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.15);
border-color: rgba(102, 126, 234, 0.4);
}
.btn.primary{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
border-color:transparent;
color:white;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
font-weight: 600;
}
.btn.primary:hover {
box-shadow: 0 8px 20px rgba(102, 126, 234, 0.4);
transform: translateY(-3px);
} }
.search{ display:flex; align-items:center; gap:10px; background:var(--soft); padding:8px 12px; border-radius:12px; border:1px solid var(--border); }
.search input{background:transparent; border:none; outline:none; color:var(--text); width:280px}
.actions{display:flex; align-items:center; gap:10px}
.btn{ padding:8px 12px; border-radius:10px; border:1px solid var(--border); background:var(--soft); color:var(--text); cursor:pointer; }
.btn.primary{background:var(--accent); border-color:transparent; color:white; box-shadow:var(--shadow)}
.main{flex:1; display:flex; flex-direction:column; min-width:0; height:100vh; overflow:hidden; width:100%} .main{flex:1; display:flex; flex-direction:column; min-width:0; height:100vh; overflow:hidden; width:100%}
.subnav{ .subnav{
@@ -135,12 +278,50 @@ a{color:inherit; text-decoration:none}
.flex-3{display:grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap:16px} .flex-3{display:grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap:16px}
.full{display:block; width:100%; box-sizing:border-box} .full{display:block; width:100%; box-sizing:border-box}
.kpis{display:grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap:12px} .kpis{display:grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap:14px}
.kpi{ .kpi{
background:var(--soft); border:1px solid var(--border); border-radius:14px; padding:14px; background: linear-gradient(135deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.7) 100%);
border:1px solid rgba(102, 126, 234, 0.1);
border-radius:16px;
padding:18px;
position: relative;
overflow: hidden;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
cursor: pointer;
}
.kpi::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 4px;
background: var(--primary-gradient);
opacity: 0;
transition: opacity 0.3s ease;
}
.kpi:hover {
transform: translateY(-4px);
box-shadow: 0 12px 24px rgba(102, 126, 234, 0.15);
border-color: rgba(102, 126, 234, 0.3);
}
.kpi:hover::before {
opacity: 1;
}
.kpi:nth-child(1)::before { background: var(--primary-gradient); }
.kpi:nth-child(2)::before { background: var(--success-gradient); }
.kpi:nth-child(3)::before { background: var(--warning-gradient); }
.kpi:nth-child(4)::before { background: var(--secondary-gradient); }
.kpi h3{margin:0; font-size:13px; color:var(--muted); font-weight: 600; letter-spacing: 0.3px;}
.kpi .num{
font-size:28px;
font-weight:900;
margin-top:8px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
} }
.kpi h3{margin:0; font-size:12px; color:var(--muted)}
.kpi .num{font-size:26px; font-weight:800; margin-top:6px}
.kpi .delta{font-size:12px; margin-left:8px; padding:2px 6px; border-radius:8px; background:var(--panel); border:1px solid var(--border)} .kpi .delta{font-size:12px; margin-left:8px; padding:2px 6px; border-radius:8px; background:var(--panel); border:1px solid var(--border)}
.table{width:100%; border-collapse:collapse; font-size:14px; min-width:800px; table-layout:fixed; box-sizing:border-box} .table{width:100%; border-collapse:collapse; font-size:14px; min-width:800px; table-layout:fixed; box-sizing:border-box}

View File

@@ -10,23 +10,50 @@
.dynamic-menu-wrapper .ant-menu-item, .dynamic-menu-wrapper .ant-menu-item,
.dynamic-menu-wrapper .ant-menu-submenu-title { .dynamic-menu-wrapper .ant-menu-submenu-title {
border-radius: 10px; border-radius: 12px;
margin: 4px 0; margin: 4px 0;
padding-left: 16px !important; padding-left: 16px !important;
height: 40px; height: 42px;
line-height: 40px; line-height: 42px;
transition: all 0.2s; transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
border: 1px solid transparent; border: 1px solid transparent;
position: relative;
overflow: hidden;
}
.dynamic-menu-wrapper .ant-menu-item::before,
.dynamic-menu-wrapper .ant-menu-submenu-title::before {
content: '';
position: absolute;
left: 0;
top: 0;
height: 100%;
width: 3px;
background: var(--primary-gradient);
opacity: 0;
transition: opacity 0.3s ease;
} }
.dynamic-menu-wrapper .ant-menu-item:hover, .dynamic-menu-wrapper .ant-menu-item:hover,
.dynamic-menu-wrapper .ant-menu-submenu-title:hover { .dynamic-menu-wrapper .ant-menu-submenu-title:hover {
background: var(--soft) !important; background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.05) 100%) !important;
transform: translateX(4px);
border-color: rgba(102, 126, 234, 0.15) !important;
}
.dynamic-menu-wrapper .ant-menu-item:hover::before,
.dynamic-menu-wrapper .ant-menu-submenu-title:hover::before {
opacity: 1;
} }
.dynamic-menu-wrapper .ant-menu-item-selected { .dynamic-menu-wrapper .ant-menu-item-selected {
background: var(--soft) !important; background: linear-gradient(135deg, rgba(102, 126, 234, 0.12) 0%, rgba(118, 75, 162, 0.08) 100%) !important;
border-color: var(--border) !important; border-color: rgba(102, 126, 234, 0.2) !important;
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.15);
}
.dynamic-menu-wrapper .ant-menu-item-selected::before {
opacity: 1;
} }
.dynamic-menu-wrapper .ant-menu-item-selected::after { .dynamic-menu-wrapper .ant-menu-item-selected::after {
@@ -36,8 +63,16 @@
/* 图标样式 */ /* 图标样式 */
.dynamic-menu-wrapper .ant-menu-item .anticon, .dynamic-menu-wrapper .ant-menu-item .anticon,
.dynamic-menu-wrapper .ant-menu-submenu-title .anticon { .dynamic-menu-wrapper .ant-menu-submenu-title .anticon {
font-size: 16px; font-size: 18px;
color: var(--text); color: var(--text);
transition: all 0.3s ease;
}
.dynamic-menu-wrapper .ant-menu-item:hover .anticon,
.dynamic-menu-wrapper .ant-menu-submenu-title:hover .anticon,
.dynamic-menu-wrapper .ant-menu-item-selected .anticon {
transform: scale(1.1);
color: #667eea;
} }
/* 折叠时的样式 */ /* 折叠时的样式 */
@@ -62,8 +97,8 @@
.dynamic-menu-wrapper .ant-menu-inline-collapsed > .ant-menu-item .anticon, .dynamic-menu-wrapper .ant-menu-inline-collapsed > .ant-menu-item .anticon,
.dynamic-menu-wrapper .ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title .anticon { .dynamic-menu-wrapper .ant-menu-inline-collapsed > .ant-menu-submenu > .ant-menu-submenu-title .anticon {
font-size: 20px; font-size: 22px;
line-height: 40px; line-height: 42px;
margin: 0 !important; margin: 0 !important;
} }
@@ -93,11 +128,17 @@
/* 展开箭头样式 */ /* 展开箭头样式 */
.dynamic-menu-wrapper .ant-menu-submenu-arrow { .dynamic-menu-wrapper .ant-menu-submenu-arrow {
color: var(--muted); color: var(--muted);
transition: all 0.3s ease;
}
.dynamic-menu-wrapper .ant-menu-submenu-title:hover .ant-menu-submenu-arrow {
color: #667eea;
} }
/* 子菜单展开时的样式 */ /* 子菜单展开时的样式 */
.dynamic-menu-wrapper .ant-menu-submenu-open > .ant-menu-submenu-title { .dynamic-menu-wrapper .ant-menu-submenu-open > .ant-menu-submenu-title {
color: var(--text); color: var(--text);
background: linear-gradient(135deg, rgba(102, 126, 234, 0.08) 0%, rgba(118, 75, 162, 0.05) 100%) !important;
} }
/* 文字超出隐藏 */ /* 文字超出隐藏 */
@@ -105,4 +146,14 @@
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;
font-weight: 500;
font-size: 14px;
} }
/* 菜单项文字悬停效果 */
.dynamic-menu-wrapper .ant-menu-item:hover .ant-menu-title-content,
.dynamic-menu-wrapper .ant-menu-item-selected .ant-menu-title-content {
color: #667eea;
font-weight: 600;
}

View File

@@ -3,6 +3,7 @@ import { createRoot } from 'react-dom/client'
import { Provider } from 'jotai' import { Provider } from 'jotai'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import './App.css' import './App.css'
import './darkTheme.css'
import 'antd/dist/reset.css' import 'antd/dist/reset.css'
import App from './App.tsx' import App from './App.tsx'
import AuthGuard from './components/AuthGuard' import AuthGuard from './components/AuthGuard'