feat(sidebar): 新增 Sidebar 慢 SQL 历史浮动入口

- 新建 SlowQueryRailButton:独立小组件,从 store 直接读 tabs/connections 解析激活连接
- 挂载方式:浮动在 Sidebar 右下角,不修改 Sidebar.tsx 内部代码(避免改 10275 行的大文件)
- 体验优化:无激活连接时按钮自动禁用并 tooltip 提示;与 Ctrl+Shift+L 快捷键路径并存
- bundle 保持:SlowQueryPanel 继续走 lazy 加载独立 chunk,不进入主 bundle
This commit is contained in:
Syngnat
2026-06-19 13:56:15 +08:00
parent 8457f6c4b7
commit dc54d24d2b
2 changed files with 112 additions and 0 deletions

View File

@@ -4,6 +4,7 @@ import { Layout, Button, ConfigProvider, theme, message, Spin, Slider, Progress,
import { PlusOutlined, ConsoleSqlOutlined, UploadOutlined, DownloadOutlined, CloudDownloadOutlined, BugOutlined, ToolOutlined, GlobalOutlined, InfoCircleOutlined, GithubOutlined, SkinOutlined, CheckOutlined, MinusOutlined, BorderOutlined, CloseOutlined, SettingOutlined, LinkOutlined, BgColorsOutlined, AppstoreOutlined, RobotOutlined, FolderOpenOutlined, HddOutlined, SafetyCertificateOutlined, SwitcherOutlined, CodeOutlined, RightOutlined } from '@ant-design/icons';
import { BrowserOpenURL, Environment, EventsOn, Quit, WindowFullscreen, WindowGetPosition, WindowGetSize, WindowIsFullscreen, WindowIsMaximised, WindowIsMinimised, WindowIsNormal, WindowMaximise, WindowMinimise, WindowSetPosition, WindowSetSize, WindowUnfullscreen, WindowUnmaximise } from '../wailsjs/runtime';
import Sidebar from './components/Sidebar';
import SlowQueryRailButton from './components/sidebar/SlowQueryRailButton';
import TabManager from './components/TabManager';
import ConnectionModal from './components/ConnectionModal';
import SnippetSettingsModal from './components/SnippetSettingsModal';
@@ -3692,6 +3693,18 @@ function App() {
onFocusCommandSearch={handleFocusSidebarSearch}
/>
</div>
{/* 慢 SQL 历史入口:浮动在 Sidebar 右下角,独立组件不依赖 Sidebar 内部 state */}
<SlowQueryRailButton
style={{
position: 'absolute',
right: 8,
bottom: isV2Ui ? 8 : 66,
zIndex: 10,
background: 'var(--gn-card-bg, rgba(255,255,255,0.9))',
borderRadius: 6,
boxShadow: '0 1px 4px rgba(0,0,0,0.1)',
}}
/>
{!connectionWorkbenchState.ready && (
<div
style={{

View File

@@ -0,0 +1,99 @@
import { lazy, Suspense, useMemo, useState } from 'react'
import { Tooltip } from 'antd'
import { HistoryOutlined } from '@ant-design/icons'
import { useStore } from '../../store'
import type { ConnectionConfig } from '../../types'
// lazy 加载避免 SlowQueryPanelreact-flow + dagre 约 200KB进入主 bundle
const SlowQueryPanel = lazy(() => import('../explain/SlowQueryPanel'))
// Sidebar 顶部的慢 SQL 历史入口。
//
// 设计要点:
// - 完全独立组件,不依赖 Sidebar.tsx 内部 state避免改 Sidebar Props
// - 自己从 store 读取 tabs/connections解析当前激活 tab 的连接配置
// - 通过 lazy import SlowQueryPanelreact-flow/dagre 不进入主 bundle
// - 没有激活的连接时按钮禁用hover 给提示
//
// 挂载位置由调用方决定App.tsx 把它放在 Sidebar 容器内)
interface SlowQueryRailButtonProps {
/** 自定义 className 用于外层定位 */
className?: string
/** 自定义 style用于绝对定位到 Sidebar 角落) */
style?: React.CSSProperties
}
export default function SlowQueryRailButton({ className, style }: SlowQueryRailButtonProps) {
const [open, setOpen] = useState(false)
const tabs = useStore(s => s.tabs)
const activeTabId = useStore(s => s.activeTabId)
const connections = useStore(s => s.connections)
// 解析当前激活 tab 的 ConnectionConfig
const activeConfig = useMemo<ConnectionConfig | null>(() => {
if (!activeTabId) return null
const tab = tabs.find(t => t.id === activeTabId)
if (!tab?.connectionId) return null
const conn = connections.find(c => c.id === tab.connectionId)
if (!conn) return null
return {
...conn.config,
port: Number(conn.config.port),
password: conn.config.password || '',
database: conn.config.database || '',
useSSH: conn.config.useSSH || false,
ssh: conn.config.ssh || { host: '', port: 22, user: '', password: '', keyPath: '' },
} as ConnectionConfig
}, [tabs, activeTabId, connections])
const activeTab = tabs.find(t => t.id === activeTabId)
const dbName = activeTab?.dbName || ''
const buttonDisabled = !activeConfig
const tooltipText = buttonDisabled
? '请先打开一个数据库连接的查询标签'
: '查看当前连接的慢 SQL 历史Ctrl+Shift+L'
return (
<>
<Tooltip title={tooltipText} placement="right">
<button
type="button"
className={className}
onClick={() => !buttonDisabled && setOpen(true)}
disabled={buttonDisabled}
style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
width: 32,
height: 32,
border: 'none',
background: 'transparent',
cursor: buttonDisabled ? 'not-allowed' : 'pointer',
color: buttonDisabled
? 'var(--gn-text-muted, #adb5bd)'
: 'var(--gn-text, #495057)',
opacity: buttonDisabled ? 0.5 : 1,
transition: 'opacity 0.15s, color 0.15s',
...style,
}}
aria-label="慢 SQL 历史"
>
<HistoryOutlined style={{ fontSize: 16 }} />
</button>
</Tooltip>
{open && activeConfig && (
<Suspense fallback={null}>
<SlowQueryPanel
open={open}
onClose={() => setOpen(false)}
config={activeConfig}
dbName={dbName}
/>
</Suspense>
)}
</>
)
}