From 43f45cc09c4d5cc7de65bba85ccceb4025d3d0e7 Mon Sep 17 00:00:00 2001 From: thzxx Date: Wed, 8 Apr 2026 16:35:54 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=B7=A5=E4=BD=9C=E7=A9=BA?= =?UTF-8?q?=E9=97=B4=E6=94=B9=E4=B8=BA=E5=8D=95=E4=B8=80=E7=BB=88=E7=AB=AF?= =?UTF-8?q?=EF=BC=8C=E7=A7=BB=E9=99=A4=E5=A4=9A=20Tab=20=E6=9C=BA=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除新建终端按钮和 Tab 栏,只保留唯一默认终端 - AI 命令始终发往唯一终端,避免多终端时目标不确定 - 删除 createTerminalSession/closeTerminalTab/renderTerminalTabs 等多 Tab 相关代码 --- src/renderer/components/workspace-panel.ts | 98 ++++------------------ src/renderer/index.html | 6 -- 2 files changed, 16 insertions(+), 88 deletions(-) diff --git a/src/renderer/components/workspace-panel.ts b/src/renderer/components/workspace-panel.ts index d69dc1b..0b72a84 100644 --- a/src/renderer/components/workspace-panel.ts +++ b/src/renderer/components/workspace-panel.ts @@ -31,8 +31,7 @@ interface FileNode { let panelVisible = true; // 常驻显示,不可关闭 let activeTab: 'terminal' | 'files' = 'terminal'; -let terminalSessions: TerminalSession[] = []; -let activeTerminalId = ''; +let terminal: TerminalSession | null = null; // 唯一终端 let workspaceDir = ''; let currentFileDir = ''; let fileTree: FileNode[] = []; @@ -196,8 +195,14 @@ export async function initWorkspacePanel(): Promise { // 绑定 UI 事件 bindEvents(); - // 创建默认终端 - createTerminalSession('终端 1'); + // 创建唯一终端 + terminal = { + id: genId(), + title: '终端', + lines: [], + running: false, + autoScroll: true + }; logInfo('工作空间面板已初始化'); } @@ -213,12 +218,6 @@ function bindEvents(): void { // 清空按钮 document.querySelector('#wsClearBtn')?.addEventListener('click', clearTerminal); - // 新建终端 Tab - document.querySelector('#wsNewTabBtn')?.addEventListener('click', () => { - const num = terminalSessions.length + 1; - createTerminalSession(`终端 ${num}`); - }); - // 文件刷新 document.querySelector('#wsFileRefreshBtn')?.addEventListener('click', () => { loadFiles(currentFileDir || workspaceDir); @@ -250,22 +249,8 @@ function switchTab(tab: 'terminal' | 'files'): void { } // ── 终端管理 ── -function createTerminalSession(title: string): string { - const session: TerminalSession = { - id: genId(), - title, - lines: [], - running: false, - autoScroll: true - }; - terminalSessions.push(session); - activeTerminalId = session.id; - renderPanel(); - return session.id; -} - function getActiveSession(): TerminalSession | undefined { - return terminalSessions.find(s => s.id === activeTerminalId); + return terminal ?? undefined; } /** AI Tool Calling 实时输出 → 流式追加到活跃终端 */ @@ -318,11 +303,11 @@ function handleToolDone(command: string, exitCode: number | null): void { } function appendTerminalOutput(sessionId: string, type: 'stdout' | 'stderr', data: string): void { - const session = terminalSessions.find(s => s.id === sessionId); - if (!session) { - logDebug('工作空间输出丢失', `未找到会话: ${sessionId}`); + if (!terminal || terminal.id !== sessionId) { + logDebug('工作空间输出丢失', `未匹配终端: ${sessionId}`); return; } + const session = terminal; // 按行分割,处理 \r 进度更新 const lines = data.split('\n'); @@ -354,11 +339,11 @@ function appendTerminalOutput(sessionId: string, type: 'stdout' | 'stderr', data } function handleProcessExit(sessionId: string, code: number | null): void { - const session = terminalSessions.find(s => s.id === sessionId); - if (!session) { - logDebug('工作空间退出信号丢失', `未找到会话: ${sessionId}`); + if (!terminal || terminal.id !== sessionId) { + logDebug('工作空间退出信号丢失', `未匹配终端: ${sessionId}`); return; } + const session = terminal; session.running = false; const exitMsg = code === 0 ? '✓ 进程正常退出' : `✗ 进程退出 (code: ${code})`; @@ -408,21 +393,6 @@ function clearTerminal(): void { renderTerminal(); } -function closeTerminalTab(sessionId: string): void { - if (terminalSessions.length <= 1) return; // 至少保留一个 - - const session = terminalSessions.find(s => s.id === sessionId); - if (session?.running) { - window.metonaDesktop?.workspace.kill(sessionId); - } - - terminalSessions = terminalSessions.filter(s => s.id !== sessionId); - if (activeTerminalId === sessionId) { - activeTerminalId = terminalSessions[0].id; - } - renderPanel(); -} - // ── 文件浏览器 ── async function loadFiles(dirPath: string): Promise { const bridge = window.metonaDesktop; @@ -489,7 +459,6 @@ export function renderPanel(): void { if (activeTab === 'terminal') { renderTerminal(); - renderTerminalTabs(); } else { renderFileList(); } @@ -532,41 +501,6 @@ function renderTerminal(): void { }; } -function renderTerminalTabs(): void { - const tabBar = document.querySelector('#wsTermTabBar') as HTMLElement; - if (!tabBar) return; - - tabBar.innerHTML = terminalSessions.map(s => { - const active = s.id === activeTerminalId; - const running = s.running ? ' ●' : ''; - const closeBtn = terminalSessions.length > 1 - ? `` - : ''; - return `
- ${escapeHtml(s.title)}${running} - ${closeBtn} -
`; - }).join(''); - - // 绑定 tab 点击事件 - tabBar.querySelectorAll('.ws-tab').forEach(tab => { - tab.addEventListener('click', (e) => { - const target = e.target as HTMLElement; - const closeBtn = target.closest('.ws-tab-close') as HTMLElement; - if (closeBtn) { - e.stopPropagation(); - closeTerminalTab(closeBtn.dataset.close!); - return; - } - const sessionId = (tab as HTMLElement).dataset.session; - if (sessionId) { - activeTerminalId = sessionId; - renderPanel(); - } - }); - }); -} - function renderFileList(): void { const container = document.querySelector('#wsFileList') as HTMLElement; if (!container) return; diff --git a/src/renderer/index.html b/src/renderer/index.html index 7c320d8..37c15d9 100644 --- a/src/renderer/index.html +++ b/src/renderer/index.html @@ -179,7 +179,6 @@
-
等待 AI 执行命令... @@ -195,11 +194,6 @@ -