import * as vscode from "vscode"; import { readFileContent } from "./readFiles"; import { createFile, createOrOverwriteFile, deleteFile, updateFile, renameFile, replaceFile, } from "./createFiles"; /** * 处理用户消息 */ export async function handleUserMessage( panel: vscode.WebviewPanel, text: string ) { console.log("收到用户消息:", text); // 检查是否是文件操作命令 const fileOperation = parseFileOperation(text); console.log("解析结果:", fileOperation); if (fileOperation) { console.log("执行文件操作:", fileOperation.type, fileOperation.filePath); await handleFileOperation(panel, fileOperation); return; } // 普通消息处理 console.log("作为普通消息处理"); const reply = getMockReply(text); setTimeout(() => { panel.webview.postMessage({ command: "receiveMessage", text: reply, }); }, 500); } /** * 解析文件操作命令 */ function parseFileOperation(text: string): { type: "create" | "delete" | "read" | "update" | "rename" | "replace"; filePath: string; content?: string; newPath?: string; searchText?: string; replaceText?: string; } | null { const lowerText = text.toLowerCase().trim(); // 匹配创建文件:创建一个 xxx.ts 文件 const createMatch = lowerText.match(/创建(?:一个)?(.+?\.\w+)(?:文件)?/); if (createMatch) { const filePath = createMatch[1].trim(); return { type: "create", filePath: filePath, content: getDefaultContent(filePath), }; } // 匹配删除文件:删除 xxx.ts 文件 const deleteMatch = lowerText.match(/删除(.+?\.\w+)(?:文件)?/); if (deleteMatch) { const filePath = deleteMatch[1].trim(); return { type: "delete", filePath: filePath, }; } // 匹配重命名文件:将 xxx.ts 重命名为 yyy.ts 或 把 xxx.ts 改名为 yyy.ts(优先匹配,避免被修改匹配) const renameMatch = lowerText.match(/(?:将|把)\s*(.+?\.\w+)\s*(?:重命名|改名)\s*(?:为|成)\s*(.+?\.\w+)/); if (renameMatch) { const oldPath = renameMatch[1].trim(); const newPath = renameMatch[2].trim(); return { type: "rename", filePath: oldPath, newPath: newPath, }; } // 匹配替换内容:支持多种格式 // 格式1: 在 xxx.ts 中将 "aaa" 替换为 "bbb" // 格式2: 将 xxx.ts 文件 "aaa" 替换为 "bbb" // 格式3: 将 xxx.ts 文件 'aaa' 替换为 'bbb' const replaceMatch1 = lowerText.match(/在\s*(.+?\.\w+)\s*(?:文件)?中?\s*(?:将|把)\s*["'](.+?)["']\s*替换\s*(?:为|成)\s*["'](.+?)["']/); if (replaceMatch1) { const filePath = replaceMatch1[1].trim(); const searchText = replaceMatch1[2].trim(); const replaceText = replaceMatch1[3].trim(); return { type: "replace", filePath: filePath, searchText: searchText, replaceText: replaceText, }; } // 格式2: 将 xxx.ts 文件 "aaa" 替换为 "bbb" const replaceMatch2 = lowerText.match(/(?:将|把)\s*(.+?\.\w+)\s*(?:文件)?\s*["'](.+?)["']\s*替换\s*(?:为|成)\s*["'](.+?)["']/); if (replaceMatch2) { const filePath = replaceMatch2[1].trim(); const searchText = replaceMatch2[2].trim(); const replaceText = replaceMatch2[3].trim(); return { type: "replace", filePath: filePath, searchText: searchText, replaceText: replaceText, }; } // 匹配读取文件:读取 xxx.ts 文件 或 打开 xxx.ts const readMatch = lowerText.match(/(?:读取|打开)\s*(.+?\.\w+)\s*(?:文件)?/); if (readMatch) { const filePath = readMatch[1].trim(); return { type: "read", filePath: filePath, }; } // 匹配修改文件:修改 xxx.ts 文件(放在最后,避免误匹配) const updateMatch = lowerText.match(/修改\s*(.+?\.\w+)\s*(?:文件)?/); if (updateMatch) { const filePath = updateMatch[1].trim(); return { type: "update", filePath: filePath, }; } return null; } /** * 处理文件操作 */ async function handleFileOperation( panel: vscode.WebviewPanel, operation: { type: "create" | "delete" | "read" | "update" | "rename" | "replace"; filePath: string; content?: string; newPath?: string; searchText?: string; replaceText?: string; } ) { try { switch (operation.type) { case "create": await createFile(operation.filePath, operation.content || ""); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件创建成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件创建成功: ${operation.filePath}` ); break; case "delete": await deleteFile(operation.filePath); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件删除成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件删除成功: ${operation.filePath}` ); break; case "read": const content = await readFileContent(operation.filePath); panel.webview.postMessage({ command: "fileContent", content: content, filePath: operation.filePath, }); break; case "update": const currentContent = await readFileContent(operation.filePath); panel.webview.postMessage({ command: "editFile", content: currentContent, filePath: operation.filePath, }); break; case "rename": if (!operation.newPath) { throw new Error("缺少新文件名"); } await renameFile(operation.filePath, operation.newPath); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件重命名成功: ${operation.filePath} → ${operation.newPath}`, }); vscode.window.showInformationMessage( `文件重命名成功: ${operation.filePath} → ${operation.newPath}` ); break; case "replace": if (!operation.searchText || !operation.replaceText) { throw new Error("缺少替换内容"); } await replaceFile( operation.filePath, operation.searchText, operation.replaceText ); panel.webview.postMessage({ command: "receiveMessage", text: `✅ 文件内容替换成功: ${operation.filePath}`, }); vscode.window.showInformationMessage( `文件内容替换成功: ${operation.filePath}` ); break; } } catch (error) { const errorMsg = error instanceof Error ? error.message : "操作失败"; panel.webview.postMessage({ command: "receiveMessage", text: `❌ ${errorMsg}`, }); vscode.window.showErrorMessage(errorMsg); } } /** * 根据文件扩展名生成默认内容 */ function getDefaultContent(filePath: string): string { const ext = filePath.split(".").pop()?.toLowerCase(); switch (ext) { case "ts": return `// ${filePath}\n\nexport {};\n`; case "js": return `// ${filePath}\n\n`; case "json": return "{\n \n}\n"; case "md": return `# ${filePath}\n\n`; case "html": return `