|
|
let selectedCodeForContext = '';
|
|
|
let contextFilePath = ''; // 存储当前上下文文件路径
|
|
|
let streamingMessageElement = null; // 用于存储当前流式消息的DOM元素
|
|
|
let streamingMessageContent = ''; // 用于存储当前流式消息的内容
|
|
|
let currentReader = null; // 用于存储当前流的reader,以便可以取消
|
|
|
let isRequestInProgress = false; // 标记是否有请求正在进行
|
|
|
let currentSessionHistory = []; // 存储当前会话历史
|
|
|
const vscode = acquireVsCodeApi();
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
const chatForm = document.getElementById('chat-form');
|
|
|
const userInput = document.getElementById('user-input');
|
|
|
const chatBox = document.getElementById('chat-box');
|
|
|
const loading = document.getElementById('loading');
|
|
|
const sendBtn = document.getElementById('send-btn');
|
|
|
|
|
|
// 初始化显示工作区容器
|
|
|
const workspaceContainer = document.querySelector('.workspace-container');
|
|
|
if (workspaceContainer) {
|
|
|
workspaceContainer.style.display = 'none';
|
|
|
}
|
|
|
|
|
|
chatForm.addEventListener('submit', async (e) => {
|
|
|
e.preventDefault();
|
|
|
const text = userInput.value.trim();
|
|
|
|
|
|
// 如果输入为空,不执行任何操作
|
|
|
if (!text && !isRequestInProgress) return;
|
|
|
|
|
|
// 如果有请求正在进行,点击按钮将中断请求
|
|
|
if (isRequestInProgress) {
|
|
|
logToExtension("取消请求");
|
|
|
// 发送取消请求的消息到扩展
|
|
|
vscode.postMessage({
|
|
|
command: 'cancelRequest'
|
|
|
});
|
|
|
|
|
|
// 重置按钮状态
|
|
|
resetSendButton();
|
|
|
hideLoading();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 发送消息
|
|
|
vscode.postMessage({
|
|
|
command: 'ask',
|
|
|
text,
|
|
|
fileContent: selectedCodeForContext,
|
|
|
fileContentPath: contextFilePath // 添加文件路径
|
|
|
});
|
|
|
|
|
|
// 切换按钮为停止按钮
|
|
|
isRequestInProgress = true;
|
|
|
if (sendBtn) {
|
|
|
sendBtn.textContent = '停止';
|
|
|
sendBtn.classList.add('stop-button');
|
|
|
}
|
|
|
showLoading();
|
|
|
userInput.value = '';
|
|
|
});
|
|
|
|
|
|
// 重置发送按钮为初始状态
|
|
|
function resetSendButton() {
|
|
|
isRequestInProgress = false;
|
|
|
const sendBtn = document.getElementById('send-btn');
|
|
|
if (sendBtn) {
|
|
|
sendBtn.textContent = '发送';
|
|
|
sendBtn.classList.remove('stop-button');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 显示加载状态
|
|
|
function showLoading() {
|
|
|
loading.classList.remove('hidden');
|
|
|
chatBox.scrollTop = chatBox.scrollHeight;
|
|
|
}
|
|
|
|
|
|
// 隐藏加载状态
|
|
|
function hideLoading() {
|
|
|
loading.classList.add('hidden');
|
|
|
}
|
|
|
|
|
|
// 判断内容是否为 Markdown(简单判断)
|
|
|
function isMarkdown(content) {
|
|
|
if (!content || content.trim() === '') return false;
|
|
|
|
|
|
const markdownPatterns = [
|
|
|
/^#/m, // 标题 #
|
|
|
/\*\*[^*]+\*\*/g, // 加粗 **text**
|
|
|
/__[^_]+__/g, // 加粗 __text__
|
|
|
/^- /gm, // 无序列表
|
|
|
/^\* /gm, // 无序列表
|
|
|
/^\d+\. /gm, // 有序列表
|
|
|
/```/g // 代码块
|
|
|
];
|
|
|
|
|
|
return markdownPatterns.some(pattern => pattern.test(content));
|
|
|
}
|
|
|
|
|
|
// 处理添加消息
|
|
|
function addMessage(role, content, codeDiffs) {
|
|
|
const msgDiv = document.createElement('div');
|
|
|
msgDiv.className = `message ${role}`;
|
|
|
|
|
|
// 渲染内容
|
|
|
if (isMarkdown(content)) {
|
|
|
msgDiv.innerHTML = marked.parse(content);
|
|
|
} else {
|
|
|
const div = document.createElement('div');
|
|
|
div.textContent = content;
|
|
|
msgDiv.appendChild(div);
|
|
|
}
|
|
|
|
|
|
// 如果是AI消息且包含代码块,为每个代码块添加按钮
|
|
|
if (role === 'ai') {
|
|
|
const codeBlocks = msgDiv.querySelectorAll('pre code');
|
|
|
// 确保 codeDiffs 是数组
|
|
|
const diffs = Array.isArray(codeDiffs) ? codeDiffs : [];
|
|
|
|
|
|
codeBlocks.forEach((block, index) => {
|
|
|
// 为每个代码块添加"创建文件"按钮
|
|
|
const createFileButton = document.createElement('button');
|
|
|
createFileButton.className = 'create-file-button';
|
|
|
createFileButton.textContent = `生成代码文件`;
|
|
|
createFileButton.onclick = () => createNewFileFromCode(block.textContent, index);
|
|
|
|
|
|
// 将按钮插入到代码块后面
|
|
|
block.parentNode.after(createFileButton);
|
|
|
|
|
|
// 如果有代码差异,也为每个代码块添加查看差异按钮
|
|
|
if (diffs[index]) {
|
|
|
const diffButton = document.createElement('button');
|
|
|
diffButton.className = 'diff-button';
|
|
|
diffButton.textContent = `查看代码差异`;
|
|
|
diffButton.onclick = () => showCodeDiff(diffs[index]);
|
|
|
|
|
|
// 将差异按钮插入到创建文件按钮后面
|
|
|
createFileButton.after(diffButton);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
chatBox.appendChild(msgDiv);
|
|
|
|
|
|
// 高亮代码块
|
|
|
const codeBlocks = msgDiv.querySelectorAll('pre code');
|
|
|
codeBlocks.forEach(block => {
|
|
|
if (hljs) {
|
|
|
hljs.highlightElement(block);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 滚动到底部
|
|
|
chatBox.scrollTop = chatBox.scrollHeight;
|
|
|
|
|
|
return msgDiv; // 返回创建的消息元素
|
|
|
}
|
|
|
|
|
|
// 开始流式传输
|
|
|
function startStreaming() {
|
|
|
// 创建一个新的AI消息元素
|
|
|
streamingMessageElement = document.createElement('div');
|
|
|
streamingMessageElement.className = 'message ai streaming';
|
|
|
|
|
|
// 添加流式消息内容容器
|
|
|
const contentDiv = document.createElement('div');
|
|
|
contentDiv.className = 'streaming-content';
|
|
|
streamingMessageElement.appendChild(contentDiv);
|
|
|
|
|
|
// 添加光标元素
|
|
|
const cursor = document.createElement('span');
|
|
|
cursor.className = 'streaming-cursor';
|
|
|
cursor.textContent = '▋';
|
|
|
streamingMessageElement.appendChild(cursor);
|
|
|
|
|
|
chatBox.appendChild(streamingMessageElement);
|
|
|
streamingMessageContent = '';
|
|
|
|
|
|
// 滚动到底部
|
|
|
chatBox.scrollTop = chatBox.scrollHeight;
|
|
|
}
|
|
|
|
|
|
// 处理流式数据
|
|
|
function handleStreamData(data) {
|
|
|
if (!streamingMessageElement) return;
|
|
|
|
|
|
let processedData = data;
|
|
|
if (data.startsWith('data:')) {
|
|
|
// 移除data:前缀
|
|
|
processedData = data.replace(/^data:/, '');
|
|
|
// 逐个匹配换行符,当出现两个或更多连续换行符时删除多余的
|
|
|
processedData = processedData.replace(/^(\n{2,})/, (match) => {
|
|
|
// 删除所有连续的换行符
|
|
|
return '';
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 更新内容
|
|
|
streamingMessageContent += processedData;
|
|
|
|
|
|
// 更新显示
|
|
|
const contentDiv = streamingMessageElement.querySelector('.streaming-content');
|
|
|
if (contentDiv) {
|
|
|
// 如果是Markdown内容,我们需要特殊处理
|
|
|
if (isMarkdown(streamingMessageContent)) {
|
|
|
contentDiv.innerHTML = marked.parse(streamingMessageContent);
|
|
|
} else {
|
|
|
contentDiv.textContent = streamingMessageContent;
|
|
|
}
|
|
|
|
|
|
// 高亮代码块
|
|
|
const codeBlocks = contentDiv.querySelectorAll('pre code');
|
|
|
codeBlocks.forEach(block => {
|
|
|
if (hljs && !block.dataset.highlighted) {
|
|
|
hljs.highlightElement(block);
|
|
|
block.dataset.highlighted = 'true';
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 滚动到底部
|
|
|
chatBox.scrollTop = chatBox.scrollHeight;
|
|
|
}
|
|
|
|
|
|
// 结束流式传输
|
|
|
function endStreaming(content, codeDiffs = null) {
|
|
|
if (streamingMessageElement) {
|
|
|
// 移除流式传输类和光标
|
|
|
streamingMessageElement.classList.remove('streaming');
|
|
|
const cursor = streamingMessageElement.querySelector('.streaming-cursor');
|
|
|
if (cursor) {
|
|
|
cursor.remove();
|
|
|
}
|
|
|
|
|
|
// 如果是AI消息且包含代码块,为每个代码块添加按钮
|
|
|
if (streamingMessageElement.classList.contains('ai')) {
|
|
|
const codeBlocks = streamingMessageElement.querySelectorAll('pre code');
|
|
|
codeBlocks.forEach((block, index) => {
|
|
|
// 为每个代码块添加"创建文件"按钮
|
|
|
const createFileButton = document.createElement('button');
|
|
|
createFileButton.className = 'create-file-button';
|
|
|
createFileButton.textContent = `生成代码文件`;
|
|
|
createFileButton.onclick = () => createNewFileFromCode(block.textContent, index);
|
|
|
|
|
|
// 将按钮插入到代码块后面
|
|
|
block.parentNode.after(createFileButton);
|
|
|
|
|
|
// 如果有代码差异,也为每个代码块添加查看差异按钮
|
|
|
// codeDiffs是一个数组,每个元素对应一个代码块的差异信息
|
|
|
if (codeDiffs && codeDiffs[index]) {
|
|
|
const diffButton = document.createElement('button');
|
|
|
diffButton.className = 'diff-button';
|
|
|
diffButton.textContent = `查看代码差异`;
|
|
|
diffButton.onclick = () => showCodeDiff(codeDiffs[index]);
|
|
|
// 将差异按钮插入到创建文件按钮后面
|
|
|
createFileButton.after(diffButton);
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 高亮代码块
|
|
|
const codeBlocks = streamingMessageElement.querySelectorAll('pre code');
|
|
|
codeBlocks.forEach(block => {
|
|
|
if (hljs) {
|
|
|
hljs.highlightElement(block);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
streamingMessageElement = null;
|
|
|
streamingMessageContent = '';
|
|
|
}
|
|
|
|
|
|
// 重置发送按钮状态
|
|
|
resetSendButton();
|
|
|
|
|
|
// 保存消息到历史记录
|
|
|
currentSessionHistory.push({role: 'assistant', content: content});
|
|
|
|
|
|
hideLoading();
|
|
|
}
|
|
|
|
|
|
// 处理请求取消
|
|
|
function handleRequestCancelled() {
|
|
|
// 重置发送按钮
|
|
|
resetSendButton();
|
|
|
|
|
|
// 如果有正在流式传输的消息,结束它
|
|
|
if (streamingMessageElement) {
|
|
|
streamingMessageElement.classList.remove('streaming');
|
|
|
const cursor = streamingMessageElement.querySelector('.streaming-cursor');
|
|
|
if (cursor) {
|
|
|
cursor.remove();
|
|
|
}
|
|
|
streamingMessageElement = null;
|
|
|
streamingMessageContent = '';
|
|
|
}
|
|
|
|
|
|
hideLoading();
|
|
|
}
|
|
|
|
|
|
// 显示代码差异
|
|
|
function showCodeDiff(codeDiff) {
|
|
|
const diffModal = document.getElementById('diff-modal');
|
|
|
const diffContent = document.getElementById('diff-content');
|
|
|
|
|
|
diffContent.innerHTML = '';
|
|
|
|
|
|
// 显示添加的行
|
|
|
if (codeDiff.added && codeDiff.added.length > 0) {
|
|
|
codeDiff.added.forEach((line, index) => {
|
|
|
const diffRow = document.createElement('div');
|
|
|
diffRow.className = 'diff-row';
|
|
|
|
|
|
// 修复行号显示问题
|
|
|
const lineNumber = document.createElement('div');
|
|
|
lineNumber.className = 'diff-line-number';
|
|
|
lineNumber.textContent = index + 1; // 使用索引+1作为行号
|
|
|
|
|
|
const diffLine = document.createElement('div');
|
|
|
diffLine.className = 'diff-line diff-added';
|
|
|
diffLine.textContent = `+ ${line}`;
|
|
|
|
|
|
diffRow.appendChild(lineNumber);
|
|
|
diffRow.appendChild(diffLine);
|
|
|
diffContent.appendChild(diffRow);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 显示删除的行
|
|
|
if (codeDiff.removed && codeDiff.removed.length > 0) {
|
|
|
codeDiff.removed.forEach((line, index) => {
|
|
|
const diffRow = document.createElement('div');
|
|
|
diffRow.className = 'diff-row';
|
|
|
|
|
|
// 修复行号显示问题
|
|
|
const lineNumber = document.createElement('div');
|
|
|
lineNumber.className = 'diff-line-number';
|
|
|
lineNumber.textContent = index + 1; // 使用索引+1作为行号
|
|
|
|
|
|
const diffLine = document.createElement('div');
|
|
|
diffLine.className = 'diff-line diff-removed';
|
|
|
diffLine.textContent = `- ${line}`;
|
|
|
|
|
|
diffRow.appendChild(lineNumber);
|
|
|
diffRow.appendChild(diffLine);
|
|
|
diffContent.appendChild(diffRow);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
// 添加接受和拒绝按钮的事件监听
|
|
|
document.getElementById('accept-changes-btn').onclick = () => acceptChanges(codeDiff.modifiedCode);
|
|
|
document.getElementById('reject-changes-btn').onclick = () => rejectChanges();
|
|
|
|
|
|
diffModal.classList.remove('hidden');
|
|
|
}
|
|
|
|
|
|
// 接受代码变更
|
|
|
function acceptChanges(modifiedCode) {
|
|
|
if (contextFilePath) {
|
|
|
// 发送消息到插件以接受变更
|
|
|
vscode.postMessage({
|
|
|
command: 'acceptChanges',
|
|
|
filePath: contextFilePath,
|
|
|
modifiedContent: modifiedCode
|
|
|
});
|
|
|
|
|
|
// 关闭模态框
|
|
|
document.getElementById('diff-modal').classList.add('hidden');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 拒绝代码变更
|
|
|
function rejectChanges() {
|
|
|
if (contextFilePath) {
|
|
|
// 发送消息到插件以拒绝变更
|
|
|
vscode.postMessage({
|
|
|
command: 'rejectChanges',
|
|
|
filePath: contextFilePath
|
|
|
});
|
|
|
|
|
|
// 关闭模态框
|
|
|
document.getElementById('diff-modal').classList.add('hidden');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 更新工作区文件列表
|
|
|
function updateWorkspaceFiles(files) {
|
|
|
const workspaceContainer = document.querySelector('.workspace-container');
|
|
|
const workspaceFilesContainer = document.getElementById('workspace-files');
|
|
|
|
|
|
// 如果没有文件变更,则隐藏工作区
|
|
|
if (!files || Object.keys(files).length === 0) {
|
|
|
workspaceContainer.style.display = 'none';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 显示工作区
|
|
|
workspaceContainer.style.display = 'block';
|
|
|
workspaceFilesContainer.innerHTML = '';
|
|
|
|
|
|
Object.keys(files).forEach(filePath => {
|
|
|
const fileChange = files[filePath];
|
|
|
const fileItem = document.createElement('div');
|
|
|
fileItem.className = 'workspace-file-item';
|
|
|
|
|
|
// 获取文件名
|
|
|
const fileName = filePath.split(/[\/\\]/).pop();
|
|
|
|
|
|
// 根据状态设置不同的显示样式
|
|
|
let statusText = '';
|
|
|
let statusClass = '';
|
|
|
|
|
|
switch (fileChange.status) {
|
|
|
case 'accepted':
|
|
|
statusText = '✓ 已接受';
|
|
|
statusClass = 'status-accepted';
|
|
|
break;
|
|
|
case 'rejected':
|
|
|
statusText = '✗ 已拒绝';
|
|
|
statusClass = 'status-rejected';
|
|
|
break;
|
|
|
default:
|
|
|
statusText = '待处理';
|
|
|
statusClass = 'status-pending';
|
|
|
}
|
|
|
|
|
|
fileItem.innerHTML = `
|
|
|
<span class="file-icon">📄</span>
|
|
|
<span class="file-name" title="${filePath}">${fileName}</span>
|
|
|
<span class="file-status ${statusClass}">${statusText}</span>
|
|
|
`;
|
|
|
|
|
|
fileItem.addEventListener('click', () => {
|
|
|
// 发送消息到插件以打开文件
|
|
|
vscode.postMessage({
|
|
|
command: 'openWorkspaceFile',
|
|
|
filePath: filePath
|
|
|
});
|
|
|
});
|
|
|
|
|
|
workspaceFilesContainer.appendChild(fileItem);
|
|
|
});
|
|
|
}
|
|
|
|
|
|
window.addEventListener('message', (event) => {
|
|
|
const message = event.data;
|
|
|
if (message.command === 'addMessage') {
|
|
|
addMessage(message.role, message.content, message.codeDiff);
|
|
|
} else if (message.command === 'startStream') {
|
|
|
// 开始流式传输
|
|
|
startStreaming();
|
|
|
} else if (message.command === 'streamData') {
|
|
|
// 处理流式数据
|
|
|
handleStreamData(message.data);
|
|
|
} else if (message.command === 'endStream') {
|
|
|
// 结束流式传输
|
|
|
endStreaming(message.content, message.codeDiffs);
|
|
|
} else if (message.command === 'requestCancelled') {
|
|
|
// 请求被取消
|
|
|
handleRequestCancelled();
|
|
|
} else if (message.command === 'hideLoading') {
|
|
|
hideLoading();
|
|
|
} else if (message.command === 'addToInput') {
|
|
|
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 = `<div class="loading">错误: ${message.error}</div>`;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
if (!message.files || message.files.length === 0) {
|
|
|
fileListContainer.innerHTML = '<div class="loading">未找到文件</div>';
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
// 渲染文件列表
|
|
|
fileListContainer.innerHTML = '';
|
|
|
message.files.forEach(file => {
|
|
|
const fileItem = document.createElement('div');
|
|
|
fileItem.className = 'file-item';
|
|
|
fileItem.innerHTML = ` <span class="file-icon">${file.isDirectory ? '📁' : '📄'}</span>
|
|
|
<span class="file-name" title="${file.relativePath}">${file.relativePath}</span>
|
|
|
`;
|
|
|
|
|
|
fileItem.addEventListener('click', () => {
|
|
|
// 选择文件
|
|
|
vscode.postMessage({
|
|
|
command: 'selectFileByPath',
|
|
|
filePath: file.path
|
|
|
});
|
|
|
|
|
|
// 关闭模态框
|
|
|
document.getElementById('file-browser-modal').classList.add('hidden');
|
|
|
|
|
|
// 清空文件搜索输入框
|
|
|
document.getElementById('file-search-input').value = '';
|
|
|
|
|
|
// 保存当前上下文文件路径
|
|
|
contextFilePath = file.path;
|
|
|
});
|
|
|
|
|
|
fileListContainer.appendChild(fileItem);
|
|
|
});
|
|
|
} else if (message.command === 'setContextFile') {
|
|
|
const contextPlaceholder = document.getElementById('context-placeholder');
|
|
|
const contextTab = document.getElementById('context-tab');
|
|
|
const fileNameElement = document.getElementById('context-file-name');
|
|
|
const fullPath = message.fileName;
|
|
|
const fileName = fullPath.split(/[\/\\]/).pop();
|
|
|
|
|
|
fileNameElement.innerText = fileName;
|
|
|
fileNameElement.title = fullPath;
|
|
|
selectedCodeForContext = message.fileContent;
|
|
|
contextFilePath = fullPath; // 保存上下文文件路径
|
|
|
|
|
|
// 隐藏占位符,显示文件标签
|
|
|
contextPlaceholder.classList.add('hidden');
|
|
|
contextTab.classList.remove('hidden');
|
|
|
} else if (message.command === 'updateWorkspaceFiles') {
|
|
|
// 更新工作区文件列表
|
|
|
updateWorkspaceFiles(message.files);
|
|
|
} else if (message.command === 'restoreState') {
|
|
|
// 恢复面板状态
|
|
|
currentSessionHistory = message.history || [];
|
|
|
|
|
|
// 恢复显示历史消息
|
|
|
currentSessionHistory.forEach(msg => {
|
|
|
addMessage(msg.role, msg.content, null);
|
|
|
});
|
|
|
|
|
|
// 恢复工作区变更
|
|
|
if (message.workspaceChanges) {
|
|
|
updateWorkspaceFiles(message.workspaceChanges);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
// 打开文件浏览器
|
|
|
const selectContextBtn = document.getElementById('select-context-btn');
|
|
|
if (selectContextBtn) {
|
|
|
selectContextBtn.addEventListener('click', () => {
|
|
|
// 显示模态框
|
|
|
const fileBrowserModal = document.getElementById('file-browser-modal');
|
|
|
if (fileBrowserModal) {
|
|
|
fileBrowserModal.classList.remove('hidden');
|
|
|
}
|
|
|
|
|
|
// 请求文件列表
|
|
|
vscode.postMessage({
|
|
|
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';
|
|
|
}
|
|
|
});
|
|
|
});
|
|
|
// 添加关闭按钮事件监听
|
|
|
document.getElementById('close-context-btn').addEventListener('click', () => {
|
|
|
const contextPlaceholder = document.getElementById('context-placeholder');
|
|
|
const contextTab = document.getElementById('context-tab');
|
|
|
|
|
|
contextTab.classList.add('hidden');
|
|
|
contextPlaceholder.classList.remove('hidden');
|
|
|
selectedCodeForContext = '';
|
|
|
contextFilePath = '';
|
|
|
});
|
|
|
// 关闭差异模态框
|
|
|
document.getElementById('close-diff-modal').addEventListener('click', () => {
|
|
|
document.getElementById('diff-modal').classList.add('hidden');
|
|
|
});
|
|
|
// 点击模态框外部关闭
|
|
|
document.getElementById('diff-modal').addEventListener('click', (e) => {
|
|
|
if (e.target.id === 'diff-modal') {
|
|
|
document.getElementById('diff-modal').classList.add('hidden');
|
|
|
}
|
|
|
});
|
|
|
|
|
|
// 从代码创建新文件
|
|
|
function createNewFileFromCode(codeContent, index) {
|
|
|
// 简单的语言检测
|
|
|
const language = detectLanguage(codeContent);
|
|
|
|
|
|
// 请求创建文件
|
|
|
const fileName = `new_file_${index + 1}${getFileExtension(language)}`;
|
|
|
|
|
|
vscode.postMessage({
|
|
|
command: 'createNewFile',
|
|
|
fileName: fileName,
|
|
|
content: codeContent,
|
|
|
language: language
|
|
|
});
|
|
|
}
|
|
|
function logToExtension(...args) {
|
|
|
vscode.postMessage({
|
|
|
command: 'log',
|
|
|
data: args
|
|
|
});
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 简单的语言检测
|
|
|
function detectLanguage(code) {
|
|
|
// 可以根据代码特征进行简单判断
|
|
|
if (code.includes('import React') || code.includes('from react')) {
|
|
|
return 'javascript'; // React代码
|
|
|
} else if (code.includes('public class') || code.includes('private static')) {
|
|
|
return 'java';
|
|
|
} else if (code.includes('def ') && code.includes(':')) {
|
|
|
return 'python';
|
|
|
} else if (code.includes('function ') || code.includes('const ') || code.includes('let ')) {
|
|
|
return 'javascript';
|
|
|
} else if (code.includes('interface ') && code.includes('export ')) {
|
|
|
return 'typescript';
|
|
|
} else if (code.includes('<?php')) {
|
|
|
return 'php';
|
|
|
} else if (code.includes('using System')) {
|
|
|
return 'csharp';
|
|
|
}
|
|
|
return 'text'; // 默认
|
|
|
}
|
|
|
|
|
|
// 根据语言获取文件扩展名
|
|
|
function getFileExtension(language) {
|
|
|
const extensions = {
|
|
|
'javascript': '.js',
|
|
|
'typescript': '.ts',
|
|
|
'python': '.py',
|
|
|
'java': '.java',
|
|
|
'html': '.html',
|
|
|
'css': '.css',
|
|
|
'php': '.php',
|
|
|
'csharp': '.cs',
|
|
|
'text': '.txt'
|
|
|
};
|
|
|
return extensions[language] || '.txt';
|
|
|
}
|
|
|
}); |