diff --git a/media/webview/script.js b/media/webview/script.js
index a16e26d..82c929a 100644
--- a/media/webview/script.js
+++ b/media/webview/script.js
@@ -86,6 +86,41 @@ document.addEventListener('DOMContentLoaded', () => {
userInput.value = message.content; // 插入选中内容到输入框
selectedCodeForContext = message.content;
userInput.focus(); // 自动聚焦输入框
+ } else if (message.command === 'fileList') {
+ const fileListContainer = document.getElementById('file-list');
+
+ if (message.error) {
+ fileListContainer.innerHTML = `
错误: ${message.error}
`;
+ return;
+ }
+
+ if (!message.files || message.files.length === 0) {
+ fileListContainer.innerHTML = '未找到文件
';
+ return;
+ }
+
+ // 渲染文件列表
+ fileListContainer.innerHTML = '';
+ message.files.forEach(file => {
+ const fileItem = document.createElement('div');
+ fileItem.className = 'file-item';
+ fileItem.innerHTML = ` ${file.isDirectory ? '📁' : '📄'}
+ ${file.relativePath}
+ `;
+
+ fileItem.addEventListener('click', () => {
+ // 选择文件
+ vscode.postMessage({
+ command: 'selectFileByPath',
+ filePath: file.path
+ });
+
+ // 关闭模态框
+ document.getElementById('file-browser-modal').classList.add('hidden');
+ });
+
+ fileListContainer.appendChild(fileItem);
+ });
} else if (message.command === 'setContextFile') {
const contextPlaceholder = document.getElementById('context-placeholder');
const contextTab = document.getElementById('context-tab');
@@ -104,9 +139,38 @@ document.addEventListener('DOMContentLoaded', () => {
});
+ // 打开文件浏览器
document.getElementById('select-context-btn').addEventListener('click', () => {
+ // 显示模态框
+ document.getElementById('file-browser-modal').classList.remove('hidden');
+
+ // 请求文件列表
vscode.postMessage({
- command: 'selectContextFile'
+ command: 'getFileList'
+ });
+ });
+ // 关闭模态框
+ document.getElementById('close-modal').addEventListener('click', () => {
+ document.getElementById('file-browser-modal').classList.add('hidden');
+ });
+ // 点击模态框外部关闭
+ document.getElementById('file-browser-modal').addEventListener('click', (e) => {
+ if (e.target.id === 'file-browser-modal') {
+ document.getElementById('file-browser-modal').classList.add('hidden');
+ }
+ });
+ // 文件搜索功能
+ document.getElementById('file-search-input').addEventListener('input', (e) => {
+ const searchTerm = e.target.value.toLowerCase();
+ const fileItems = document.querySelectorAll('.file-item');
+
+ fileItems.forEach(item => {
+ const fileName = item.querySelector('.file-name').textContent.toLowerCase();
+ if (fileName.includes(searchTerm)) {
+ item.style.display = '';
+ } else {
+ item.style.display = 'none';
+ }
});
});
// 添加关闭按钮事件监听
diff --git a/media/webview/style.css b/media/webview/style.css
index def79d0..9f370cb 100644
--- a/media/webview/style.css
+++ b/media/webview/style.css
@@ -207,3 +207,118 @@ body {
.select-context-btn:hover {
background-color: #005a9e;
}
+
+/* 模态框样式 */
+.modal {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ background-color: rgba(0, 0, 0, 0.5);
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ z-index: 1000;
+}
+
+.modal.hidden {
+ display: none;
+}
+
+.modal-content {
+ background-color: #282c34;
+ border-radius: 8px;
+ width: 80%;
+ max-width: 600px;
+ max-height: 80vh;
+ display: flex;
+ flex-direction: column;
+}
+
+.modal-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 15px 20px;
+ border-bottom: 1px solid #444;
+}
+
+.modal-header h3 {
+ margin: 0;
+ color: white;
+}
+
+.close-modal {
+ font-size: 24px;
+ cursor: pointer;
+ color: #aaa;
+}
+
+.close-modal:hover {
+ color: white;
+}
+
+.modal-body {
+ flex: 1;
+ padding: 15px;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+}
+
+.file-search {
+ flex: 1;
+ margin-bottom: 15px;
+}
+
+.file-search input {
+ padding: 8px;
+ background-color: #3e4451;
+ border: 1px solid #444;
+ border-radius: 4px;
+ color: white;
+}
+
+.file-list {
+ flex: 1;
+ overflow-y: auto;
+ border: 1px solid #444;
+ border-radius: 4px;
+ background-color: #3e4451;
+}
+
+.file-item {
+ padding: 10px;
+ border-bottom: 1px solid #444;
+ cursor: pointer;
+ display: flex;
+ align-items: center;
+}
+
+.file-item:hover {
+ background-color: #4e5461;
+}
+
+.file-item:last-child {
+ border-bottom: none;
+}
+
+.file-icon {
+ margin-right: 10px;
+ width: 16px;
+ text-align: center;
+}
+
+.file-name {
+ flex: 1;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.loading {
+ text-align: center;
+ padding: 20px;
+ color: #abb2bf;
+}
diff --git a/src/extension.ts b/src/extension.ts
index 770ab1b..6e719b9 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -72,8 +72,54 @@ export function activate(context: vscode.ExtensionContext) {
}
});
+ // 注册获取工作区文件列表的命令
+ const getFileListCommand = vscode.commands.registerCommand('ai-chat.getFileList', async () => {
+ if (panel && panel.webview) {
+ try {
+ // 获取工作区根路径
+ const workspaceFolders = vscode.workspace.workspaceFolders;
+ if (!workspaceFolders || workspaceFolders.length === 0) {
+ panel.webview.postMessage({
+ command: 'fileList',
+ files: [],
+ error: '未找到工作区'
+ });
+ return;
+ }
+
+ const rootPath = workspaceFolders[0].uri;
+
+ // 查找所有文件
+ const fileUris = await vscode.workspace.findFiles('**/*', '**/node_modules/**');
+
+ // 转换为相对路径和基本信息
+ const files = fileUris.map(uri => {
+ const relativePath = vscode.workspace.asRelativePath(uri);
+ const isDirectory = uri.path.endsWith('/');
+ return {
+ path: uri.fsPath,
+ relativePath: relativePath,
+ name: path.basename(uri.fsPath),
+ isDirectory: isDirectory
+ };
+ });
+
+ panel.webview.postMessage({
+ command: 'fileList',
+ files: files
+ });
+ } catch (error) {
+ panel.webview.postMessage({
+ command: 'fileList',
+ files: [],
+ error: error.message
+ });
+ }
+ }
+ });
+
// 添加到 subscriptions
- context.subscriptions.push(statusBarItem, openWebviewCommand, addToChatCommand,selectFileCommand);
+ context.subscriptions.push(statusBarItem, openWebviewCommand, addToChatCommand,selectFileCommand,getFileListCommand);
}
function openWebview(
@@ -163,6 +209,45 @@ function openWebview(
});
}
break;
+ case 'getFileList':
+ // 执行获取文件列表逻辑
+ const workspaceFolders = vscode.workspace.workspaceFolders;
+ if (workspaceFolders && workspaceFolders.length > 0) {
+ const fileUris = await vscode.workspace.findFiles('**/*', '**/node_modules/**');
+
+ const files = fileUris.map(uri => {
+ const relativePath = vscode.workspace.asRelativePath(uri);
+ return {
+ path: uri.fsPath,
+ relativePath: relativePath,
+ name: path.basename(uri.fsPath),
+ isDirectory: false // 简化处理,实际可以根据扩展名判断
+ };
+ });
+
+ panel.webview.postMessage({
+ command: 'fileList',
+ files: files
+ });
+ }
+ break;
+
+ case 'selectFileByPath':
+ // 根据路径选择文件
+ try {
+ const fileUri = vscode.Uri.file(message.filePath);
+ const fileContent = await vscode.workspace.fs.readFile(fileUri);
+ const decodedContent = new TextDecoder("utf-8").decode(fileContent);
+
+ panel.webview.postMessage({
+ command: 'setContextFile',
+ fileName: fileUri.fsPath,
+ fileContent: decodedContent
+ });
+ } catch (error) {
+ vscode.window.showErrorMessage(`无法读取文件: ${error.message}`);
+ }
+ break;
}
},
undefined,
@@ -249,6 +334,25 @@ function getWebviewContent(styleUri: vscode.Uri, scriptUri: vscode.Uri,highlight
+
+
+
+