diff --git a/apps/web/app/components/console/agent-launcher.tsx b/apps/web/app/components/console/agent-launcher.tsx index ed3bfd26..b5676da0 100644 --- a/apps/web/app/components/console/agent-launcher.tsx +++ b/apps/web/app/components/console/agent-launcher.tsx @@ -101,6 +101,29 @@ function PulseDot({ className }: { className?: string }) { ); } +/** + * QA U6:页面向下滚动时 FAB 滑出右侧,向上滚动、停在页底或页面很短时回来, + * 滚动途中不再盖住右对齐的开关与状态栏。只看页面级滚动区域(高度 ≥ 半屏),列表内小滚动区不算。 + */ +function useHideOnScroll(): boolean { + const [hidden, setHidden] = useState(false); + useEffect(() => { + const last = new WeakMap(); + const onScroll = (e: Event) => { + const t = e.target === document ? document.scrollingElement : e.target; + if (!(t instanceof HTMLElement) || t.clientHeight < window.innerHeight / 2) return; + const top = t.scrollTop; + const prev = last.get(t) ?? top; + last.set(t, top); + const atBottom = top + t.clientHeight >= t.scrollHeight - 4; + if (atBottom || top < 80 || top - prev < -8) setHidden(false); + else if (top - prev > 8) setHidden(true); + }; + document.addEventListener("scroll", onScroll, { capture: true, passive: true }); + return () => document.removeEventListener("scroll", onScroll, { capture: true }); + }, []); + return hidden; +} /** * 右下角悬浮按钮 + 全局快捷键。挂在 console layout 里一次。 @@ -113,6 +136,7 @@ export function AgentLauncher() { const { open, minimized, runId } = useAgentDrawer(); const { count, summary } = useActiveAgentRuns(); const lift = useFloatingBarLift(); + const scrolledAway = useHideOnScroll(); const shortcut = agentShortcutLabel(); // 挂到 body:外壳是 isolate 的层叠上下文,留在里面的话抽屉打开后"收起"会被遮罩盖住 const [host, setHost] = useState(null); @@ -121,7 +145,7 @@ export function AgentLauncher() { const onAgentPage = /^\/console\/agent(\/|$)/.test(pathname); if (!host || (onAgentPage && !open) || (minimized && runId && !open)) return null; - const label = open ? "收起 Agent" : count ? `打开 Agent(${count} 个会话进行中)` : "打开 Agent"; + const label = open ? "收起 Agent" : count ? `打开 Agent(${count} 个会话进行中)` : "打开 Agent"; return createPortal( , @@ -180,7 +205,7 @@ export function AgentNavEntry({ collapsed = false, onNavigate }: { collapsed?: b {...{ [AGENT_LAUNCHER_ATTR]: "" }} onClick={activate} title={title} - aria-label={count ? `打开 Agent(${count} 个会话进行中)` : "打开 Agent"} + aria-label={count ? `打开 Agent(${count} 个会话进行中)` : "打开 Agent"} aria-keyshortcuts="Control+J Meta+J" className="prism-ring relative mb-2 grid h-10 w-10 shrink-0 cursor-pointer place-items-center rounded-xl text-foreground outline-none transition-transform duration-micro active:scale-[0.95] focus-visible:ring-2 focus-visible:ring-ring" > @@ -207,7 +232,7 @@ export function AgentNavEntry({ collapsed = false, onNavigate }: { collapsed?: b {count ? : null} - {count ? `${count} 个会话进行中` : "交代目标,边做边汇报"} + {count ? `${count} 个会话进行中` : "交代目标,边做边汇报"} {count ? ( @@ -225,9 +250,9 @@ export function AgentNavEntry({ collapsed = false, onNavigate }: { collapsed?: b export function AgentShortcutsHelp() { const shortcut = agentShortcutLabel(); const rows: [string, string][] = [ - [shortcut, "打开 / 收起 Agent,附带当前页面"], + [shortcut, "打开 / 收起 Agent,附带当前页面"], ["Esc", "关闭 Agent"], - ["Enter", "发送目标;Shift+Enter 换行"], + ["Enter", "发送目标;Shift+Enter 换行"], ]; return (