diff --git a/src/App.tsx b/src/App.tsx index b7fb14e..86d86a4 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import { useEffect, useState } from 'react'; import { Routes, Route, Navigate, useLocation, useNavigate } from 'react-router-dom'; -import { Spin } from 'antd'; +import { Button, Drawer, Spin } from 'antd'; +import { MenuOutlined, SearchOutlined } from '@ant-design/icons'; import Sidebar from './components/Sidebar'; import CommandPalette from './components/CommandPalette'; import AgentList from './pages/AgentList'; @@ -25,6 +26,8 @@ export default function App() { const { user } = useAuth(); const location = useLocation(); const [paletteOpen, setPaletteOpen] = useState(false); + const [mobileNavOpen, setMobileNavOpen] = useState(false); + const [isMobile, setIsMobile] = useState(() => (typeof window === 'undefined' ? false : window.innerWidth < 768)); // 全局快捷键 Ctrl/⌘ + K useEffect(() => { @@ -38,6 +41,12 @@ export default function App() { window.addEventListener('keydown', handler); return () => window.removeEventListener('keydown', handler); }, [user]); + + useEffect(() => { + const onResize = () => setIsMobile(window.innerWidth < 768); + window.addEventListener('resize', onResize); + return () => window.removeEventListener('resize', onResize); + }, []); const mainContent = ( @@ -73,13 +82,32 @@ export default function App() { ) : (
{/* 只有编辑器全屏显示,其他页面均保留侧边栏 */} - {!location.pathname.startsWith('/agents/') || location.pathname.includes('/chat') ? ( + {!isMobile && (!location.pathname.startsWith('/agents/') || location.pathname.includes('/chat')) ? ( setPaletteOpen(true)} /> ) : null} -
- {mainContent} +
+ {isMobile && ( +
+
+ )} +
{mainContent}
setPaletteOpen(false)} /> + {isMobile && ( + setMobileNavOpen(false)} + width={280} + styles={{ body: { padding: 0 } }} + > + setPaletteOpen(true)} onNavigate={() => setMobileNavOpen(false)} /> + + )}
)} diff --git a/src/components/Sidebar.tsx b/src/components/Sidebar.tsx index a680737..c1db857 100644 --- a/src/components/Sidebar.tsx +++ b/src/components/Sidebar.tsx @@ -18,6 +18,7 @@ import { useTheme } from '../main'; interface Props { onOpenPalette?: () => void; + onNavigate?: () => void; } const NAV_GROUPS: Array<{ @@ -54,7 +55,7 @@ const NAV_GROUPS: Array<{ } ]; -export default function Sidebar({ onOpenPalette }: Props) { +export default function Sidebar({ onOpenPalette, onNavigate }: Props) { const { user, logout } = useAuth(); const navigate = useNavigate(); const { mode, toggle } = useTheme(); @@ -77,7 +78,10 @@ export default function Sidebar({ onOpenPalette }: Props) {
{ + onOpenPalette?.(); + onNavigate?.(); + }} className="nav-item" style={{ cursor: 'pointer', @@ -103,6 +107,7 @@ export default function Sidebar({ onOpenPalette }: Props) { to={it.to} end={it.end} className={({ isActive }) => `nav-item ${isActive ? 'active' : ''}`} + onClick={onNavigate} > {it.icon} {it.label} @@ -135,6 +140,7 @@ export default function Sidebar({ onOpenPalette }: Props) { onClick: async () => { await logout(); navigate('/login'); + onNavigate?.(); } } ] diff --git a/src/pages/chat/components/ChatOutline.tsx b/src/pages/chat/components/ChatOutline.tsx index 906cbde..5f2ad7c 100644 --- a/src/pages/chat/components/ChatOutline.tsx +++ b/src/pages/chat/components/ChatOutline.tsx @@ -16,7 +16,14 @@ export default function ChatOutline(props: { messages: ChatMessage[]; onJump: (i const { messages, onJump, activeId } = props; const items = messages.filter((m) => ((m as any)?.speaker?.type ? (m as any).speaker.type === 'agent' : m.role === 'assistant')); - if (items.length === 0) return null; + if (items.length === 0) { + return ( + + ); + } return (
diff --git a/src/styles.css b/src/styles.css index f55bf75..1eef0ae 100644 --- a/src/styles.css +++ b/src/styles.css @@ -620,12 +620,42 @@ body { } @media (max-width: 768px) { - .sidebar { + .layout-shell > .sidebar { display: none; } .main { width: 100vw; + display: flex; + flex-direction: column; + overflow: hidden; + } + + .mobile-topbar { + height: 48px; + flex: 0 0 auto; + display: flex; + align-items: center; + gap: 8px; + padding: 0 8px; + border-bottom: 1px solid var(--color-border); + background: var(--color-surface); + } + + .mobile-topbar-title { + flex: 1; + min-width: 0; + font-weight: 700; + color: var(--color-text); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } + + .main-content { + flex: 1; + min-height: 0; + overflow: auto; } .chat-shell { @@ -677,6 +707,10 @@ body { } } +.main-content { + min-height: 0; +} + .chat-body .messages-container { max-width: 780px; width: 100%;