From 7efb07fd1ac9baa20a70da163702004a63de135f Mon Sep 17 00:00:00 2001 From: Aisland Date: Fri, 21 Aug 2026 18:17:59 +0800 Subject: [PATCH] feat: clickable square rail buttons when collapsed + eye icon toggle in manage panel --- 01_content/src/client/index.tsx | 69 +++++++++-- 01_content/src/client/styles.ts | 4 +- .../worklogs/2026-08-16_worktable-v2.md | 18 +++ 04_test/probe-batch17.cjs | 117 ++++++++++++++++++ 04_test/rail-toggle-probe.cjs | 59 +++++++++ 5 files changed, 254 insertions(+), 13 deletions(-) create mode 100644 04_test/probe-batch17.cjs create mode 100644 04_test/rail-toggle-probe.cjs diff --git a/01_content/src/client/index.tsx b/01_content/src/client/index.tsx index 3ef787a..be36593 100644 --- a/01_content/src/client/index.tsx +++ b/01_content/src/client/index.tsx @@ -802,6 +802,25 @@ function syncSessionScope(list: any) { } } +/** 显示/隐藏切换图标:睁眼/闭眼同族 SVG(对称设计,符合可见性规范) */ +function EyeIcon(props: { closed: boolean }) { + return ( + + {props.closed ? ( + <> + + + + ) : ( + <> + + + + )} + + ) +} + /** 管理面板改名输入:本地草稿,blur/Enter 才提交(清空时不会立刻弹回原名) */ function RenameInput(props: { initial: string; placeholder: string; onCommit: (v: string) => void }) { const [val, setVal] = useState(props.initial) @@ -2079,15 +2098,37 @@ function buildCustomLayoutPrompt(req: string): string { : 16 const popTop = clamp(sectionTop, MIN_TOP, Math.max(MIN_TOP, window.innerHeight - 540)) + /** 收起态点击项目图标:视图覆盖/布局 → openSplit;入驻无视图 → 切绑定对话 */ + const openRailProject = (id: string) => { + const pr = projectsRef.current.projects + const layout = pr.layouts.find((l) => l.id === id) + const view = pr.views[id] + if (view || layout) openSplit((view ?? layout) as LayoutSpec) + else { + const bound = pr.bindings[id] + if (bound) { try { sessionBridge?.sessions?.open?.(bound) } catch {} } + } + } + if (!wide) { - const projectIcons = aliveRegisteredIds.map((id) => projects.iconOverrides[id] ?? metas[id]?.icon ?? '📦') - const shortcutIcons = projects.shortcuts.map((s) => s.icon) - const layoutIcons = projects.layouts.map((l) => l.icon ?? '🧱') - const icons = [...projectIcons, ...shortcutIcons, ...layoutIcons] - const railNames = [ - ...aliveRegisteredIds.map((id) => projects.nameOverrides[id] ?? metas[id]?.name ?? id), - ...projects.shortcuts.map((s) => s.name), - ...projects.layouts.map((l) => projects.nameOverrides[l.id] ?? l.title), + // 收起态 = 等行高的正方形圆角按钮,中间只留 emoji;点击 = 进入对应项目 + const railItems: { icon: string; name: string; onClick: (e: any) => void }[] = [ + { icon: CONSOLE_ICON, name: t('console.name'), onClick: (e) => clickConsoleCard(e.currentTarget as HTMLElement) }, + ...aliveRegisteredIds.map((id) => ({ + icon: projects.iconOverrides[id] ?? metas[id]?.icon ?? '📦', + name: projects.nameOverrides[id] ?? metas[id]?.name ?? id, + onClick: () => openRailProject(id), + })), + ...projects.shortcuts.map((s) => ({ + icon: s.icon, + name: s.name, + onClick: () => { try { window.open(s.href, '_blank', 'noopener') } catch {} }, + })), + ...projects.layouts.map((l) => ({ + icon: l.icon ?? '🧱', + name: projects.nameOverrides[l.id] ?? l.title, + onClick: () => openSplit(l), + })), ] // 浮动态:fixed 定位到拖前高度(左/宽取折叠列实测几何);停靠态:文档流原位 const railStyle = isFloat && railRect @@ -2096,9 +2137,13 @@ function buildCustomLayoutPrompt(req: string): string { return (
-
- {icons.length > 0 - ? icons.map((icon, i) => {icon}) +
+ {railItems.length > 0 + ? railItems.map((it, i) => ( + + )) : ≡}
@@ -2302,7 +2347,7 @@ function buildCustomLayoutPrompt(req: string): string { >{projects.iconOverrides[id] ?? meta?.icon ?? '📦'}} renameProject(id, v)} />