diff --git a/frontend/src/components/layout/FrontLayout.css b/frontend/src/components/layout/FrontLayout.css index 140d629..fee02b2 100644 --- a/frontend/src/components/layout/FrontLayout.css +++ b/frontend/src/components/layout/FrontLayout.css @@ -1,16 +1,18 @@ -/* ===== Front Layout ===== */ +/* ===== Front Layout V3 - Light Theme ===== */ .front-layout { display: flex; height: 100vh; overflow: hidden; + background: #F5F7FC; + color: #1A1F36; } /* Sidebar */ .front-sidebar { width: var(--sidebar-width); min-width: var(--sidebar-width); - background: var(--color-sidebar-bg); - border-right: 1px solid var(--color-border-light); + background: linear-gradient(180deg, #FFFFFF 0%, #FAFBFE 100%); + border-right: 1px solid rgba(0, 0, 0, 0.08); display: flex; flex-direction: column; transition: width var(--transition-slow), min-width var(--transition-slow); @@ -29,7 +31,7 @@ justify-content: space-between; padding: var(--space-lg) var(--space-lg); height: var(--header-height); - border-bottom: 1px solid var(--color-border-light); + border-bottom: 1px solid rgba(0, 0, 0, 0.08); } .sidebar-logo { @@ -41,7 +43,7 @@ .sidebar-brand { font-size: var(--text-lg); font-weight: 700; - color: var(--color-text-primary); + color: #1A1F36; letter-spacing: -0.02em; white-space: nowrap; } @@ -53,13 +55,14 @@ width: 32px; height: 32px; border-radius: var(--radius-md); - color: var(--color-text-tertiary); + color: #8892B0; transition: all var(--transition-fast); + cursor: pointer; } .collapse-btn:hover { - background: var(--color-bg-hover); - color: var(--color-text-primary); + background: rgba(0, 0, 0, 0.08); + color: #8892B0; } /* Navigation */ @@ -68,7 +71,7 @@ display: flex; flex-direction: column; justify-content: space-between; - padding: var(--space-sm) var(--space-sm); + padding: var(--space-sm); overflow-y: auto; } @@ -77,14 +80,23 @@ flex-direction: column; gap: 2px; } +.nav-group-title { + padding: 14px var(--space-md) 6px; + font-size: 11px; + font-weight: 600; + letter-spacing: 0.06em; + text-transform: uppercase; + color: #9CA3AF; +} .nav-item { + position: relative; display: flex; align-items: center; gap: var(--space-md); - padding: var(--space-md) var(--space-md); + padding: 10px var(--space-md); border-radius: var(--radius-md); - color: var(--color-text-secondary); + color: #8892B0; text-decoration: none; font-size: var(--text-base); font-weight: 500; @@ -93,13 +105,13 @@ } .nav-item:hover { - background: var(--color-sidebar-hover); - color: var(--color-text-primary); + background: rgba(91, 95, 237, 0.06); + color: #1A1F36; } .nav-item.active { - background: var(--color-sidebar-active); - color: var(--color-accent); + background: rgba(91, 95, 237, 0.12); + color: #5B5FED; } .nav-icon { @@ -115,10 +127,30 @@ flex: 1; } +/* Active dot indicator */ +.nav-active-dot { + display: none; +} + +.nav-item.active .nav-active-dot { + display: block; + position: absolute; + right: 8px; + width: 6px; + height: 6px; + border-radius: 50%; + background: #5B5FED; + box-shadow: 0 0 8px rgba(91, 95, 237, 0.5); +} + /* Sidebar Footer */ .sidebar-footer { padding: var(--space-md); - border-top: 1px solid var(--color-border-light); + border-top: 1px solid rgba(0, 0, 0, 0.08); +} + +.sidebar-footer .nav-item { + margin-top: 2px; } .user-info-mini { @@ -126,13 +158,14 @@ align-items: center; gap: var(--space-md); padding: var(--space-sm); + margin-bottom: 4px; } .user-avatar-sm { width: 32px; height: 32px; border-radius: var(--radius-full); - background: linear-gradient(135deg, var(--color-accent), #8185F5); + background: linear-gradient(135deg, #5B5FED, #4A4ECC); color: white; display: flex; align-items: center; @@ -151,16 +184,21 @@ .user-name { font-size: var(--text-sm); font-weight: 600; - color: var(--color-text-primary); + color: #1A1F36; line-height: 1.3; } .user-plan { font-size: var(--text-xs); - color: var(--color-accent); + color: #5B5FED; line-height: 1.3; } +.logout-btn:hover { + color: #EF4444 !important; + background: rgba(239, 68, 68, 0.1) !important; +} + /* Main Content */ .front-main { flex: 1; @@ -168,6 +206,12 @@ display: flex; flex-direction: column; min-width: 0; + background: #F5F7FC; +} + +/* Forward-slash route for apps - hidden default route */ +.front-main > * { + height: 100%; } /* Responsive */ @@ -187,3 +231,11 @@ transform: translateX(0); } } + + +/* Home & Admin links */ +.nav-home-link { + margin-bottom: 4px; + border-bottom: 1px solid rgba(0, 0, 0, 0.06); + padding-bottom: 8px; +} diff --git a/frontend/src/components/layout/FrontLayout.tsx b/frontend/src/components/layout/FrontLayout.tsx index bbaebb9..5eb83a3 100644 --- a/frontend/src/components/layout/FrontLayout.tsx +++ b/frontend/src/components/layout/FrontLayout.tsx @@ -1,146 +1,183 @@ -import React, { useState } from 'react'; -import { Outlet, NavLink, useNavigate } from 'react-router-dom'; -import { useAuth } from '@/contexts/AuthContext'; -import './FrontLayout.css'; - -const navItems = [ - { path: '/chat', icon: 'chat', label: 'AI聊天' }, - { path: '/channels', icon: 'channel', label: '频道' }, - { path: '/knowledge', icon: 'knowledge', label: '知识库' }, - { path: '/market', icon: 'market', label: '应用市场' }, - { path: '/token', icon: 'token', label: 'Token驾驶舱' }, - { path: '/pricing', icon: 'pricing', label: '付费中心' }, - { path: '/assets', icon: 'assets', label: '资产' }, - { path: '/evolution', icon: 'evolution', label: 'AI进化' }, -]; - -const bottomItems = [ - { path: '/profile', icon: 'profile', label: '个人中心' }, - { path: '/notifications', icon: 'notify', label: '消息通知' }, -]; - -const iconPaths: Record = { - chat: , - channel: , - knowledge: , - market: , - token: , - pricing: , - profile: , - notify: , - assets: , - evolution: , -}; - -const FrontLayout: React.FC = () => { - const { user, logout } = useAuth(); - const navigate = useNavigate(); - const [collapsed, setCollapsed] = useState(false); - - if (!user) { - navigate('/login'); - return null; - } - - return ( -
- {/* Sidebar */} - - - {/* Main Content */} -
- -
-
- ); -}; - -export default FrontLayout; +import React, { useState } from 'react'; +import { Outlet, NavLink, useNavigate } from 'react-router-dom'; +import { useAuth } from '@/contexts/AuthContext'; +import './FrontLayout.css'; + +const navGroups = [ + { + title: '智能体', + items: [ + { path: '/chat', icon: 'chat', label: 'AI聊天' }, + { path: '/knowledge', icon: 'knowledge', label: '知识库' }, + { path: '/market', icon: 'market', label: '技能市场' }, + { path: '/evolution', icon: 'evolution', label: 'AI自进化' }, + ], + }, + { + title: 'IM Bot', + items: [ + { path: '/channels', icon: 'channel', label: '频道管理' }, + { path: '/wechat-bot', icon: 'wechat', label: '微信机器人' }, + ], + }, + { + title: '资源中心', + items: [ + { path: '/assets', icon: 'assets', label: '资产文件' }, + { path: '/token', icon: 'token', label: 'Token驾驶舱' }, + { path: '/pricing', icon: 'pricing', label: '付费中心' }, + ], + }, +]; + +const bottomItems = [ + { path: '/profile', icon: 'profile', label: '个人中心' }, + { path: '/notifications', icon: 'notify', label: '消息通知' }, +]; + +const iconPaths: Record = { + chat: , + channel: , + knowledge: , + market: , + apps: , + token: , + pricing: , + profile: , + notify: , + assets: , + evolution: , + wechat: , +}; + +const FrontLayout: React.FC = () => { + const { user, logout } = useAuth(); + const navigate = useNavigate(); + const [collapsed, setCollapsed] = useState(false); + + if (!user) { + navigate('/login'); + return null; + } + + return ( +
+ {/* Sidebar */} + + + {/* Main Content */} +
+ +
+
+ ); +}; + +export default FrontLayout;