refactor: 移除顶部栏,设置按钮移至底部栏右侧,StatusBar 全面改 MUI Table
- StatusBar: 全 MUI Table 布局,左侧状态/Provider/Token,右侧版本+设置 - Header: 已删除(功能合并到 StatusBar) - App.tsx: 移除 Header 引用
This commit is contained in:
@@ -9,7 +9,6 @@
|
||||
|
||||
import { ThemeProvider, CssBaseline } from '@mui/material';
|
||||
import { useEffect } from 'react';
|
||||
import { Header } from '@renderer/components/layout/Header';
|
||||
import { Sidebar } from '@renderer/components/layout/Sidebar';
|
||||
import { DetailPanel } from '@renderer/components/layout/DetailPanel';
|
||||
import { StatusBar } from '@renderer/components/layout/StatusBar';
|
||||
@@ -55,7 +54,6 @@ export default function App(): React.JSX.Element {
|
||||
className="h-screen w-screen flex flex-col overflow-hidden select-none"
|
||||
style={{ background: muiTheme.palette.background.default, color: muiTheme.palette.text.primary }}
|
||||
>
|
||||
<Header />
|
||||
<div className="flex-1 flex overflow-hidden min-h-0">
|
||||
<Sidebar />
|
||||
<ChatPanel />
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/**
|
||||
* Header — 标题栏
|
||||
*
|
||||
* Logo + 会话标题 + 设置按钮。
|
||||
*/
|
||||
|
||||
import { Box, IconButton, Tooltip, Stack, Typography } from '@mui/material';
|
||||
import { Settings } from 'lucide-react';
|
||||
import { useUIStore } from '@renderer/stores/ui-store';
|
||||
import { useSessionStore } from '@renderer/stores/session-store';
|
||||
|
||||
type WebkitCSS = React.CSSProperties & { WebkitAppRegion?: string };
|
||||
|
||||
export function Header(): React.JSX.Element {
|
||||
const openSettings = useUIStore((s) => s.openSettings);
|
||||
const currentSessionId = useSessionStore((s) => s.currentSessionId);
|
||||
const sessions = useSessionStore((s) => s.sessions);
|
||||
const currentSession = sessions.find((s) => s.id === currentSessionId);
|
||||
|
||||
return (
|
||||
<header
|
||||
style={{
|
||||
flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
padding: '0 16px', height: 40, userSelect: 'none',
|
||||
background: 'var(--bg-secondary)', borderBottom: '1px solid var(--border-color)',
|
||||
WebkitAppRegion: 'drag',
|
||||
} as WebkitCSS}
|
||||
>
|
||||
<Stack direction="row" spacing={1} alignItems="center" sx={{ minWidth: 0 }}>
|
||||
<Box component="img" src="./assets/logo.png" alt="Metona" sx={{ width: 20, height: 20, borderRadius: 0.5 }} />
|
||||
<Typography variant="body2" sx={{ fontWeight: 600, color: 'primary.main', fontSize: 13 }}>MetonaAI</Typography>
|
||||
{currentSession && (
|
||||
<>
|
||||
<Typography variant="body2" sx={{ color: 'divider' }}>·</Typography>
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{currentSession.title}</Typography>
|
||||
</>
|
||||
)}
|
||||
</Stack>
|
||||
<Stack direction="row" spacing={0.5} sx={{ WebkitAppRegion: 'no-drag' } as WebkitCSS}>
|
||||
<Tooltip title="设置 (Ctrl+,)"><IconButton size="small" onClick={openSettings} sx={{ color: 'text.secondary' }}><Settings size={14} /></IconButton></Tooltip>
|
||||
</Stack>
|
||||
</header>
|
||||
);
|
||||
}
|
||||
@@ -1,11 +1,13 @@
|
||||
/**
|
||||
* StatusBar — 底部状态栏
|
||||
*
|
||||
* 显示 Agent 状态指示灯、Provider 名称、Token 统计、版本号。
|
||||
* 完全使用 MUI 组件:Table 展示状态/Provider/Token,右侧设置按钮。
|
||||
*/
|
||||
|
||||
import { Box, Typography, Stack, Chip } from '@mui/material';
|
||||
import { Box, Typography, IconButton, Tooltip, Table, TableBody, TableRow, TableCell } from '@mui/material';
|
||||
import { Settings } from 'lucide-react';
|
||||
import { useAgentStore } from '@renderer/stores/agent-store';
|
||||
import { useUIStore } from '@renderer/stores/ui-store';
|
||||
import { AGENT_STATUS_COLORS, AGENT_STATUS_LABELS, PROVIDER_LABELS } from '@renderer/lib/constants';
|
||||
import { formatTokens } from '@renderer/lib/formatters';
|
||||
|
||||
@@ -14,42 +16,63 @@ export function StatusBar(): React.JSX.Element {
|
||||
const provider = useAgentStore((s) => s.provider);
|
||||
const model = useAgentStore((s) => s.model);
|
||||
const tokenUsage = useAgentStore((s) => s.tokenUsage);
|
||||
const openSettings = useUIStore((s) => s.openSettings);
|
||||
|
||||
return (
|
||||
<Box
|
||||
component="footer"
|
||||
sx={{
|
||||
flexShrink: 0, display: 'flex', alignItems: 'center', justifyContent: 'space-between',
|
||||
px: 2, height: 24, bgcolor: 'background.paper', borderTop: 1, borderColor: 'divider', userSelect: 'none',
|
||||
flexShrink: 0, display: 'flex', alignItems: 'center',
|
||||
px: 1.5, height: 28, bgcolor: 'background.paper',
|
||||
borderTop: 1, borderColor: 'divider', userSelect: 'none',
|
||||
}}
|
||||
>
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
<Stack direction="row" spacing={0.75} alignItems="center">
|
||||
{/* 左侧:状态信息表格 */}
|
||||
<Table size="small" sx={{
|
||||
flex: 1, width: 'auto',
|
||||
'& .MuiTableCell-root': { border: 0, py: 0, px: 1, fontSize: 10, whiteSpace: 'nowrap' },
|
||||
}}>
|
||||
<TableBody>
|
||||
<TableRow>
|
||||
<TableCell sx={{ width: 'auto', py: 0, px: 1 }}>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.75 }}>
|
||||
<Box
|
||||
sx={{
|
||||
width: 8, height: 8, borderRadius: '50%', flexShrink: 0,
|
||||
width: 7, height: 7, borderRadius: '50%', flexShrink: 0,
|
||||
bgcolor: AGENT_STATUS_COLORS[agentStatus],
|
||||
animation: (agentStatus === 'thinking' || agentStatus === 'executing') ? 'pulse 2s infinite' : 'none',
|
||||
}}
|
||||
/>
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 11, lineHeight: 1 }}>
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 10, lineHeight: 1 }}>
|
||||
{AGENT_STATUS_LABELS[agentStatus]}
|
||||
</Typography>
|
||||
</Stack>
|
||||
<Typography variant="caption" sx={{ color: 'divider' }}>|</Typography>
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 11 }}>
|
||||
</Box>
|
||||
</TableCell>
|
||||
<TableCell sx={{ color: 'divider', width: 1, p: 0 }}>|</TableCell>
|
||||
<TableCell sx={{ color: 'text.secondary', fontSize: 10 }}>
|
||||
{PROVIDER_LABELS[provider] ?? provider} {model}
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
<Stack direction="row" spacing={1.5} alignItems="center">
|
||||
</TableCell>
|
||||
{tokenUsage.totalTokens > 0 && (
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 11 }}>
|
||||
Tokens: {formatTokens(tokenUsage.inputTokens)}↓ {formatTokens(tokenUsage.outputTokens)}↑
|
||||
</Typography>
|
||||
<>
|
||||
<TableCell sx={{ color: 'divider', width: 1, p: 0 }}>|</TableCell>
|
||||
<TableCell sx={{ fontFamily: 'monospace', color: 'text.secondary', fontSize: 10 }}>
|
||||
{formatTokens(tokenUsage.inputTokens)}↓ {formatTokens(tokenUsage.outputTokens)}↑
|
||||
</TableCell>
|
||||
</>
|
||||
)}
|
||||
<Typography variant="caption" sx={{ color: 'text.secondary', fontSize: 11 }}>MetonaAI v0.1.0</Typography>
|
||||
</Stack>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
|
||||
{/* 右侧:版本 + 设置 */}
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 0.5, flexShrink: 0 }}>
|
||||
<Typography variant="caption" sx={{ color: 'text.disabled', fontSize: 9 }}>v0.1.0</Typography>
|
||||
<Tooltip title="设置 (Ctrl+,)">
|
||||
<IconButton size="small" onClick={openSettings} sx={{ color: 'text.secondary', width: 24, height: 24 }}>
|
||||
<Settings size={12} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user