From 3f0cc8ae29f5e4d6c6c6bc8d893647a0eba0f314 Mon Sep 17 00:00:00 2001 From: Roe-xin Date: Tue, 30 Dec 2025 16:02:36 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E5=8C=BA=E7=8A=B6=E6=80=81=E6=A3=80=E6=9F=A5=E5=8A=9F=E8=83=BD?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C?= =?UTF-8?q?=20-=20=E7=94=A8=E6=88=B7=E9=BC=A0=E6=A0=87=E8=81=9A=E7=84=A6?= =?UTF-8?q?=E5=88=B0=E8=BE=93=E5=85=A5=E6=A1=86=E4=B8=AD=E5=B0=B1=E5=BC=B9?= =?UTF-8?q?=E7=AA=97=E6=8F=90=E7=A4=BA=E7=94=A8=E6=88=B7=E6=89=93=E5=BC=80?= =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E7=94=A8=E6=88=B7=E4=BD=93=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/panels/ICHelperPanel.ts | 20 +++++++++++++ src/utils/createFiles.ts | 56 ++++++++++++++++++++++++++----------- src/views/inputArea.ts | 23 +++++++++++++-- src/views/webviewContent.ts | 10 +++++-- 4 files changed, 88 insertions(+), 21 deletions(-) diff --git a/src/panels/ICHelperPanel.ts b/src/panels/ICHelperPanel.ts index f9d227e..4aecdca 100644 --- a/src/panels/ICHelperPanel.ts +++ b/src/panels/ICHelperPanel.ts @@ -181,6 +181,26 @@ export async function showICHelperPanel( case "abortDialog": abortCurrentDialog(); break; + // 新增:检查工作区状态 + case "checkWorkspace": + const hasWorkspace = !!(vscode.workspace.workspaceFolders && vscode.workspace.workspaceFolders.length > 0); + if (!hasWorkspace) { + // 弹窗提示用户需要打开工作区 + vscode.window.showWarningMessage( + "请先打开一个文件夹作为工作区,这样我就能更好地为您服务了 😊", + "打开文件夹" + ).then((selection) => { + if (selection === "打开文件夹") { + vscode.commands.executeCommand("vscode.openFolder"); + } + }); + } + // 返回工作区状态给前端 + panel.webview.postMessage({ + command: "workspaceStatus", + hasWorkspace: hasWorkspace + }); + break; } }, undefined, diff --git a/src/utils/createFiles.ts b/src/utils/createFiles.ts index cf1d8a5..c8a089c 100644 --- a/src/utils/createFiles.ts +++ b/src/utils/createFiles.ts @@ -16,7 +16,9 @@ export async function createFile( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法创建相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您创建文件了" + ); } } @@ -28,7 +30,7 @@ export async function createFile( throw new Error(`文件已存在: ${absolutePath}`); } catch (error: any) { // 如果文件不存在,继续创建 - if (error.code !== 'FileNotFound') { + if (error.code !== "FileNotFound") { throw error; } } @@ -65,7 +67,9 @@ export async function createOrOverwriteFile( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法创建相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您创建文件了" + ); } } @@ -99,7 +103,9 @@ export async function createDirectory(dirPath: string): Promise { if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, dirPath); } else { - throw new Error("没有打开的工作区,无法创建相对路径的目录"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您创建目录了" + ); } } @@ -115,7 +121,7 @@ export async function createDirectory(dirPath: string): Promise { } } catch (error: any) { // 如果目录不存在,继续创建 - if (error.code !== 'FileNotFound') { + if (error.code !== "FileNotFound") { throw error; } } @@ -161,7 +167,9 @@ export async function deleteFile(filePath: string): Promise { if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法删除相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您删除文件了" + ); } } @@ -197,7 +205,9 @@ export async function updateFile( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法修改相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您修改文件了" + ); } } @@ -236,7 +246,9 @@ export async function appendToFile( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法追加相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您追加文件内容了" + ); } } @@ -274,7 +286,9 @@ export async function replaceFile( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法修改相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您修改文件了" + ); } } @@ -291,14 +305,17 @@ export async function replaceFile( // 转义特殊字符,将字符串作为字面量处理 const escapeRegExp = (str: string) => { - return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); }; // 替换内容 - 如果是字符串,先转义特殊字符 let newContent: string; - if (typeof searchValue === 'string') { + if (typeof searchValue === "string") { const escapedSearch = escapeRegExp(searchValue); - newContent = fileContent.replace(new RegExp(escapedSearch, "g"), replaceValue); + newContent = fileContent.replace( + new RegExp(escapedSearch, "g"), + replaceValue + ); } else { newContent = fileContent.replace(searchValue, replaceValue); } @@ -330,7 +347,9 @@ export async function insertAtLine( if (workspaceFolders && workspaceFolders.length > 0) { absolutePath = path.join(workspaceFolders[0].uri.fsPath, filePath); } else { - throw new Error("没有打开的工作区,无法修改相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您修改文件了" + ); } } @@ -382,7 +401,9 @@ export async function renameFile( absoluteNewPath = path.join(workspaceRoot, newPath); } } else { - throw new Error("没有打开的工作区,无法重命名相对路径的文件"); + throw new Error( + "请先打开一个文件夹作为工作区,这样我就能为您重命名文件了" + ); } const oldUri = vscode.Uri.file(absoluteOldPath); @@ -401,10 +422,13 @@ export async function renameFile( throw new Error(`目标文件已存在: ${absoluteNewPath}`); } catch (error: any) { // 如果文件不存在,继续重命名 - if (error.code !== 'FileNotFound' && !error.message.includes('目标文件已存在')) { + if ( + error.code !== "FileNotFound" && + !error.message.includes("目标文件已存在") + ) { throw error; } - if (error.message.includes('目标文件已存在')) { + if (error.message.includes("目标文件已存在")) { throw error; } } diff --git a/src/views/inputArea.ts b/src/views/inputArea.ts index a0ec703..fcef3bf 100644 --- a/src/views/inputArea.ts +++ b/src/views/inputArea.ts @@ -271,6 +271,10 @@ export function getInputAreaScript(): string { // 对话状态管理 let isConversationActive = false; + // 工作区检测状态 + let hasCheckedWorkspace = false; // 是否已经检测过工作区 + let hasWorkspace = true; // 工作区状态 + // 自动调整 textarea 高度 function autoResizeTextarea() { if (messageInput) { @@ -283,11 +287,16 @@ export function getInputAreaScript(): string { if (messageInput) { messageInput.addEventListener('input', autoResizeTextarea); + // 监听点击事件,检测工作区状态 + messageInput.addEventListener('focus', () => { + if (!hasCheckedWorkspace) { + hasCheckedWorkspace = true; + vscode.postMessage({ command: 'checkWorkspace' }); + } + }); + // 初始化时调整一次高度 autoResizeTextarea(); - - // 聚焦到输入框 - messageInput.focus(); } // 切换发送按钮状态 @@ -326,6 +335,14 @@ export function getInputAreaScript(): string { const text = messageInput.value.trim(); if (!text) return; + // 检查工作区状态 + if (!hasWorkspace) { + // 如果没有工作区,阻止发送并清空输入框 + messageInput.value = ''; + autoResizeTextarea(); + return; + } + const mode = getCurrentMode(); // 从模式选择器组件获取当前模式 const model = getCurrentModel(); // 从模型选择器组件获取当前模型 diff --git a/src/views/webviewContent.ts b/src/views/webviewContent.ts index c586f31..db19a9b 100644 --- a/src/views/webviewContent.ts +++ b/src/views/webviewContent.ts @@ -443,8 +443,6 @@ export function getWebviewContent(iconUri?: string): string { } } - messageInput.focus(); - // 监听来自插件的消息 window.addEventListener('message', event => { const message = event.data; @@ -516,6 +514,14 @@ export function getWebviewContent(iconUri?: string): string { hideLoadingIndicator(); break; + case 'workspaceStatus': + // 更新工作区状态 + if (typeof hasWorkspace !== 'undefined') { + hasWorkspace = message.hasWorkspace; + console.log('[WebView] 工作区状态:', hasWorkspace); + } + break; + case 'vcdInfo': // 渲染迷你波形预览信息 try {