diff --git a/src/App.css b/src/App.css index 5c87033..a90d6d0 100644 --- a/src/App.css +++ b/src/App.css @@ -29,18 +29,32 @@ box-shadow: 0 8px 20px rgba(0,0,0,0.25); } .form-split { color: var(--muted); } -:root{ - --bg: #f5f7fb; - --panel: #ffffff; - --soft: #f1f3f7; - --text: #171a1f; - --muted: #4d5562; - --accent: #5f97d2; - --good: #2fb167; - --warn: #caa410; - --bad: #b6404a; - --border: #e5e7ef; - --shadow: 0 10px 25px rgba(10,16,25,.08); +:root{ /* 深色科技风主题 - 参考 x.ai */ + --bg: #0a0a0f; + --bg-secondary: #12121a; + --panel: rgba(20, 20, 30, 0.6); + --panel-solid: #14141e; + --soft: rgba(30, 30, 45, 0.5); + --text: #e8e8f0; + --text-secondary: #a0a0b0; + --muted: #6a6a7a; + --accent: #7c5cff; + --accent-glow: rgba(124, 92, 255, 0.3); + --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{ --bg: #f5f7fb; @@ -61,30 +75,115 @@ html,body{height:100%; width:100%; margin:0; padding:0} body{ margin:0; 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); display:flex; min-height:100vh; width:100%; 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} .container{display:flex; flex:1; width:100vw; height:100vh; max-width:none; margin:0; padding:0} .sidebar{ - border-right:1px solid var(--border); - background:linear-gradient(180deg, var(--panel), var(--soft)); + border-right:1px solid rgba(102, 126, 234, 0.1); + 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; display:flex; flex-direction:column; 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{ - width:28px; height:28px; border-radius:8px; - background: radial-gradient(120% 120% at 0% 0%, var(--accent) 0%, #9dc3e7 48%, #9394e7 100%); - box-shadow:var(--shadow); + width:32px; height:32px; border-radius:10px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + 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 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)} .header{ - display:flex; align-items:center; justify-content:space-between; padding:16px 22px; - border-bottom:1px solid var(--border); background:var(--panel); z-index:6; flex-shrink:0; + display:flex; align-items:center; justify-content:space-between; padding:18px 24px; + 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%} .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} .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{ - 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)} .table{width:100%; border-collapse:collapse; font-size:14px; min-width:800px; table-layout:fixed; box-sizing:border-box} diff --git a/src/components/DynamicMenu.css b/src/components/DynamicMenu.css index e77ebb4..2810975 100644 --- a/src/components/DynamicMenu.css +++ b/src/components/DynamicMenu.css @@ -10,23 +10,50 @@ .dynamic-menu-wrapper .ant-menu-item, .dynamic-menu-wrapper .ant-menu-submenu-title { - border-radius: 10px; + border-radius: 12px; margin: 4px 0; padding-left: 16px !important; - height: 40px; - line-height: 40px; - transition: all 0.2s; + height: 42px; + line-height: 42px; + transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); 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-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 { - background: var(--soft) !important; - border-color: var(--border) !important; + background: linear-gradient(135deg, rgba(102, 126, 234, 0.12) 0%, rgba(118, 75, 162, 0.08) 100%) !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 { @@ -36,8 +63,16 @@ /* 图标样式 */ .dynamic-menu-wrapper .ant-menu-item .anticon, .dynamic-menu-wrapper .ant-menu-submenu-title .anticon { - font-size: 16px; + font-size: 18px; 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-submenu > .ant-menu-submenu-title .anticon { - font-size: 20px; - line-height: 40px; + font-size: 22px; + line-height: 42px; margin: 0 !important; } @@ -93,11 +128,17 @@ /* 展开箭头样式 */ .dynamic-menu-wrapper .ant-menu-submenu-arrow { 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 { 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; text-overflow: ellipsis; 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; +} + diff --git a/src/main.tsx b/src/main.tsx index 828b4b0..19e85b4 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -3,6 +3,7 @@ import { createRoot } from 'react-dom/client' import { Provider } from 'jotai' import { BrowserRouter } from 'react-router-dom' import './App.css' +import './darkTheme.css' import 'antd/dist/reset.css' import App from './App.tsx' import AuthGuard from './components/AuthGuard'