From 3294dd585c211248bdfca82f9180b2c9b3f7d3fa Mon Sep 17 00:00:00 2001 From: thzxx Date: Thu, 28 May 2026 15:10:46 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E6=A0=87=E7=AD=BE=E6=A0=8F=E6=BB=9A?= =?UTF-8?q?=E8=BD=AE=E6=BB=9A=E5=8A=A8=E9=87=8D=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - wheel 事件直接绑定到 #tab-list 元素(而非父容器) - 支持触控板 deltaX 和鼠标滚轮 deltaY - 自动滚动到活动标签改为手动计算位置(不依赖 scrollIntoView) - CSS: #tab-bar 添加 overflow: hidden 防止溢出 - CSS: 滚动条更明显(4px 高,灰色轨道) --- src/renderer/components/TabBar/TabBar.tsx | 76 ++++++++++++----------- src/renderer/styles/global.css | 15 +++-- 2 files changed, 47 insertions(+), 44 deletions(-) diff --git a/src/renderer/components/TabBar/TabBar.tsx b/src/renderer/components/TabBar/TabBar.tsx index 5a6eebc..0748a4f 100644 --- a/src/renderer/components/TabBar/TabBar.tsx +++ b/src/renderer/components/TabBar/TabBar.tsx @@ -20,51 +20,55 @@ export function TabBar() { const closeAllTabs = useTabStore(s => s.closeAllTabs) const closeTabsToRight = useTabStore(s => s.closeTabsToRight) - const tabBarRef = useRef(null) const tabListRef = useRef(null) const [menu, setMenu] = useState({ visible: false, x: 0, y: 0, tabId: '' }) - // 支持鼠标滚轮水平滚动标签栏 - useEffect(() => { - const tabBar = tabBarRef.current - if (!tabBar) return + // 滚动到活动标签 + const scrollToActiveTab = useCallback(() => { + const tabList = tabListRef.current + if (!tabList) return + const activeTab = tabList.querySelector('.tab-item.active') as HTMLElement + if (!activeTab) return - const handleWheel = (e: WheelEvent) => { - const tabList = tabListRef.current - if (!tabList) return + const listRect = tabList.getBoundingClientRect() + const tabRect = activeTab.getBoundingClientRect() - // 只有当标签列表有水平滚动空间时才处理 - const hasHorizontalScroll = tabList.scrollWidth > tabList.clientWidth - if (!hasHorizontalScroll) return - - // 阻止默认的垂直滚动 - e.preventDefault() - e.stopPropagation() - - // 计算滚动量:优先使用 deltaX(触控板左右滑动),否则用 deltaY(鼠标滚轮) - const scrollAmount = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY - - // 应用滚动 - tabList.scrollLeft += scrollAmount + // 如果标签在可视区域左侧之外 + if (tabRect.left < listRect.left) { + tabList.scrollLeft -= (listRect.left - tabRect.left + 20) + } + // 如果标签在可视区域右侧之外 + else if (tabRect.right > listRect.right) { + tabList.scrollLeft += (tabRect.right - listRect.right + 20) } - - // 绑定到 #tab-bar 上,确保能捕获所有滚轮事件 - tabBar.addEventListener('wheel', handleWheel, { passive: false }) - return () => tabBar.removeEventListener('wheel', handleWheel) }, []) // 自动滚动到活动标签 useEffect(() => { - if (!tabListRef.current || !activeTabId) return - - // 使用 requestAnimationFrame 确保 DOM 已更新 - requestAnimationFrame(() => { - const activeTab = tabListRef.current?.querySelector('.tab-item.active') - if (activeTab) { - activeTab.scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'nearest' }) - } - }) - }, [activeTabId]) + requestAnimationFrame(scrollToActiveTab) + }, [activeTabId, scrollToActiveTab]) + + // 支持鼠标滚轮水平滚动标签栏 + useEffect(() => { + const tabList = tabListRef.current + if (!tabList) return + + const handleWheel = (e: WheelEvent) => { + // 检查是否有水平溢出 + if (tabList.scrollWidth <= tabList.clientWidth) return + + // 阻止默认滚动 + e.preventDefault() + + // 计算滚动量:支持触控板 deltaX 和鼠标滚轮 deltaY + const delta = Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY + tabList.scrollLeft += delta + } + + // 直接绑定到 tabList,使用 passive: false 允许 preventDefault + tabList.addEventListener('wheel', handleWheel, { passive: false }) + return () => tabList.removeEventListener('wheel', handleWheel) + }, []) const handleClose = useCallback((e: React.MouseEvent, tabId: string) => { e.stopPropagation() @@ -144,7 +148,7 @@ export function TabBar() { if (tabs.length === 0) return null return ( -
+
{tabs.map(tab => (