0
0

修复了保存的绝对路径问题

This commit is contained in:
xubing
2025-11-27 22:04:32 +08:00
parent 2970f64587
commit 17e9dc1451
13 changed files with 911 additions and 984 deletions

View File

@@ -55,16 +55,15 @@ class ConfigPanel {
this.currentProjectId = '';
this.currentAircraftId = '';
this.currentContainerId = '';
this.currentRepoId = '';
this.currentModuleFolderId = '';
// 数据存储
this.projects = [];
this.aircrafts = [];
this.containers = [];
this.configs = [];
this.gitRepos = []; // Git 仓库数据
this.mergedFolders = [];
this.moduleFolders = []; // 统一的模块文件夹数据
// Git 文件树
this.currentRepoFileTree = [];
this.currentModuleFolderFileTree = [];
// 项目存储路径映射
this.projectPaths = new Map();
// Webview 状态跟踪
@@ -129,7 +128,7 @@ class ConfigPanel {
this.currentProjectId = '';
this.currentAircraftId = '';
this.currentContainerId = '';
this.currentRepoId = '';
this.currentModuleFolderId = '';
this.updateWebview();
break;
case 'goBackToAircrafts':
@@ -194,20 +193,20 @@ class ConfigPanel {
console.log('❌ 取消分支选择');
this.updateWebview();
break;
case 'loadGitRepo':
await this.loadGitRepo(data.repoId);
case 'loadModuleFolder':
await this.loadModuleFolder(data.folderId);
break;
case 'syncGitRepo':
await this.syncGitRepo(data.repoId);
case 'syncGitModuleFolder':
await this.syncGitModuleFolder(data.folderId);
break;
case 'deleteGitRepo':
await this.deleteGitRepo(data.repoId);
case 'deleteModuleFolder':
await this.deleteModuleFolder(data.folderId);
break;
case 'importGitFile':
await this.importGitFile(data.filePath);
break;
case 'openGitRepoInVSCode':
await this.openTheModuleFolder('git', data.repoId);
case 'openModuleFolderInVSCode':
await this.openTheModuleFolder(data.moduleType, data.folderId);
break;
case 'openConfigFileInVSCode':
await this.openConfigFileInVSCode(data.configId);
@@ -216,7 +215,7 @@ class ConfigPanel {
await this.mergeConfigs(data.configIds, data.displayName, data.folderName);
break;
case 'deleteMergedFolder':
await this.deleteMergedFolder(data.folderId);
await this.deleteModuleFolder(data.folderId);
break;
case 'openMergedFolderInVSCode':
await this.openTheModuleFolder('merged', data.folderId);
@@ -316,9 +315,9 @@ class ConfigPanel {
}
// === Git 仓库管理方法 ===
/**
* 添加 Git 仓库到容器目录
* 添加 Git 模块文件夹到容器目录
*/
async addGitRepo(url, name, branch) {
async addGitModuleFolder(url, name, branch) {
try {
// 验证 URL
if (!url || !url.startsWith('http')) {
@@ -329,8 +328,8 @@ class ConfigPanel {
vscode.window.showErrorMessage('请先选择容器');
return;
}
const repoId = 'git-' + Date.now();
// 构建本地路径 - 在容器目录下创建分支子目录
const folderId = 'git-' + Date.now();
// 构建本地路径
const container = this.containers.find(c => c.id === this.currentContainerId);
if (!container) {
vscode.window.showErrorMessage('未找到容器');
@@ -346,33 +345,30 @@ class ConfigPanel {
vscode.window.showErrorMessage('未找到项目路径');
return;
}
// 为每个分支创建独立的子目录
const branchName = branch || 'main';
const branchSafeName = branchName.replace(/[^a-zA-Z0-9-_]/g, '-');
const repoDirName = name;
// 路径:项目路径/飞行器名/容器名/仓库名-分支名/
const localPath = path.join(projectPath, aircraft.name, container.name, repoDirName);
console.log(`📁 Git仓库将保存到: ${localPath}`);
// 检查是否已存在相同 URL 和分支的仓库
const existingRepo = this.gitRepos.find(repo => repo.url === url && repo.branch === branchName && repo.containerId === this.currentContainerId);
if (existingRepo) {
vscode.window.showWarningMessage('该 Git 仓库和分支组合已存在');
// 构建相对路径(从项目路径开始)
const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${name}`;
// 完整路径用于实际操作
const localPath = path.join(projectPath, aircraft.name, container.name, name);
console.log(`📁 Git模块文件夹将保存到: ${localPath}`);
console.log(`📁 相对路径: ${relativePath}`);
// 检查是否已存在相同名称的模块文件夹
const existingFolder = this.moduleFolders.find(folder => folder.name === name && folder.containerId === this.currentContainerId);
if (existingFolder) {
vscode.window.showWarningMessage('该名称的模块文件夹已存在');
return;
}
const newRepo = {
id: repoId,
name: `${name} (${branchName})`,
url: url,
localPath: localPath,
branch: branchName,
lastSync: new Date().toLocaleString(),
const newFolder = {
id: folderId,
name: name,
type: 'git',
localPath: relativePath,
containerId: this.currentContainerId
};
console.log(`📁 准备克隆仓库: ${name}, 分支: ${newRepo.branch}, 路径: ${localPath}`);
console.log(`📁 准备克隆仓库: ${name}, 分支: ${branch}, 路径: ${localPath}`);
// 显示进度
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在克隆仓库: ${name} (${newRepo.branch})`,
title: `正在克隆仓库: ${name}`,
cancellable: false
}, async (progress) => {
progress.report({ increment: 0 });
@@ -403,7 +399,7 @@ class ConfigPanel {
url: url,
singleBranch: true,
depth: 1,
ref: branchName,
ref: branch || 'main',
onProgress: (event) => {
if (event.total) {
const percent = (event.loaded / event.total) * 100;
@@ -412,17 +408,17 @@ class ConfigPanel {
}
});
console.log('✅ Git克隆成功完成');
this.gitRepos.push(newRepo);
this.moduleFolders.push(newFolder);
await this.saveCurrentProjectData();
console.log('✅ Git仓库数据已保存到项目文件');
vscode.window.showInformationMessage(`Git 仓库克隆成功: ${name} (${newRepo.branch})`);
console.log('✅ Git模块文件夹数据已保存到项目文件');
vscode.window.showInformationMessage(`Git 仓库克隆成功: ${name}`);
// 检查 Webview 状态后再加载文件树
if (!this.isWebviewDisposed) {
console.log('🌳 开始加载仓库文件树...');
// 自动加载仓库文件树
this.currentRepoId = repoId;
await this.loadGitRepoFileTree(repoId);
console.log('✅ 仓库文件树加载完成');
console.log('🌳 开始加载模块文件夹文件树...');
// 自动加载文件树
this.currentModuleFolderId = folderId;
await this.loadModuleFolderFileTree(folderId);
console.log('✅ 模块文件夹文件树加载完成');
}
else {
console.log('⚠️ Webview 已被销毁,跳过文件树加载');
@@ -435,30 +431,39 @@ class ConfigPanel {
});
}
catch (error) {
console.error('❌ 在addGitRepo外部捕获错误:', error);
vscode.window.showErrorMessage(`添加 Git 仓库失败: ${error}`);
console.error('❌ 在addGitModuleFolder外部捕获错误:', error);
vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`);
}
}
/**
* 加载 Git 仓库文件
* 加载模块文件
*/
async loadGitRepo(repoId) {
this.currentRepoId = repoId;
await this.loadGitRepoFileTree(repoId);
async loadModuleFolder(folderId) {
this.currentModuleFolderId = folderId;
const folder = this.moduleFolders.find(f => f.id === folderId);
if (folder && folder.type === 'git') {
await this.loadModuleFolderFileTree(folderId);
}
this.updateWebview();
}
/**
* 同步 Git 仓库
* 同步 Git 模块文件夹
*/
async syncGitRepo(repoId) {
const repo = this.gitRepos.find(r => r.id === repoId);
if (!repo) {
vscode.window.showErrorMessage('未找到指定的 Git 仓库');
async syncGitModuleFolder(folderId) {
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder || folder.type !== 'git') {
vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹');
return;
}
// 获取完整路径
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath) {
vscode.window.showErrorMessage('无法获取模块文件夹的完整路径');
return;
}
await vscode.window.withProgress({
location: vscode.ProgressLocation.Notification,
title: `正在同步仓库: ${repo.name}`,
title: `正在同步仓库: ${folder.name}`,
cancellable: false
}, async (progress) => {
try {
@@ -467,16 +472,13 @@ class ConfigPanel {
await isomorphic_git_1.default.pull({
fs: fs,
http: node_1.default,
dir: repo.localPath,
dir: fullPath,
author: { name: 'DCSP User', email: 'user@dcsp.local' },
fastForward: true
});
// 更新最后同步时间
repo.lastSync = new Date().toLocaleString();
await this.saveCurrentProjectData();
// 重新加载文件树
await this.loadGitRepoFileTree(repoId);
vscode.window.showInformationMessage(`Git 仓库同步成功: ${repo.name}`);
await this.loadModuleFolderFileTree(folderId);
vscode.window.showInformationMessage(`Git 仓库同步成功: ${folder.name}`);
this.updateWebview();
}
catch (error) {
@@ -485,49 +487,52 @@ class ConfigPanel {
});
}
/**
* 删除 Git 仓库
* 删除模块文件夹
*/
async deleteGitRepo(repoId) {
const repo = this.gitRepos.find(r => r.id === repoId);
if (!repo)
async deleteModuleFolder(folderId) {
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder)
return;
const confirm = await vscode.window.showWarningMessage(`确定要删除 Git 仓库 "${repo.name}" 吗?这将删除本地文件。`, { modal: true }, '确定删除', '取消');
const confirm = await vscode.window.showWarningMessage(`确定要删除模块文件夹 "${folder.name}" 吗?这将删除本地文件。`, { modal: true }, '确定删除', '取消');
if (confirm === '确定删除') {
try {
// 删除整个仓库目录(因为是独立目录)
await fs.promises.rm(repo.localPath, { recursive: true, force: true });
// 从列表中移除
this.gitRepos = this.gitRepos.filter(r => r.id !== repoId);
await this.saveCurrentProjectData();
// 如果删除的是当前仓库,清空状态
if (this.currentRepoId === repoId) {
this.currentRepoId = '';
this.currentRepoFileTree = [];
// 获取完整路径并删除文件夹
const fullPath = this.getModuleFolderFullPath(folder);
if (fullPath) {
await fs.promises.rm(fullPath, { recursive: true, force: true });
}
vscode.window.showInformationMessage(`Git 仓库已删除: ${repo.name}`);
// 从列表中移除
this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId);
await this.saveCurrentProjectData();
// 如果删除的是当前文件夹,清空状态
if (this.currentModuleFolderId === folderId) {
this.currentModuleFolderId = '';
this.currentModuleFolderFileTree = [];
}
vscode.window.showInformationMessage(`模块文件夹已删除: ${folder.name}`);
this.updateWebview();
}
catch (error) {
vscode.window.showErrorMessage(`删除 Git 仓库失败: ${error}`);
vscode.window.showErrorMessage(`删除模块文件夹失败: ${error}`);
}
}
}
/**
* 加载 Git 仓库文件树
* 加载模块文件夹文件树
*/
async loadGitRepoFileTree(repoId) {
async loadModuleFolderFileTree(folderId) {
// 检查 Webview 是否仍然有效
if (this.isWebviewDisposed) {
console.log('⚠️ Webview 已被销毁,跳过文件树加载');
return;
}
const repo = this.gitRepos.find(r => r.id === repoId);
if (!repo)
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder)
return;
// 通知前端开始加载
try {
this.panel.webview.postMessage({
type: 'gitRepoLoading',
type: 'moduleFolderLoading',
loading: true
});
}
@@ -536,15 +541,15 @@ class ConfigPanel {
return;
}
try {
const fileTree = await this.buildFileTree(repo.localPath);
this.currentRepoFileTree = fileTree;
// 更新最后访问时间
repo.lastSync = new Date().toLocaleString();
await this.saveCurrentProjectData();
const fullPath = this.getModuleFolderFullPath(folder);
if (fullPath) {
const fileTree = await this.buildFileTree(fullPath);
this.currentModuleFolderFileTree = fileTree;
}
}
catch (error) {
console.error('加载仓库文件树失败:', error);
this.currentRepoFileTree = [];
console.error('加载模块文件夹文件树失败:', error);
this.currentModuleFolderFileTree = [];
}
// 再次检查 Webview 状态
if (this.isWebviewDisposed) {
@@ -554,7 +559,7 @@ class ConfigPanel {
// 通知前端加载完成
try {
this.panel.webview.postMessage({
type: 'gitRepoLoading',
type: 'moduleFolderLoading',
loading: false
});
this.updateWebview();
@@ -607,13 +612,13 @@ class ConfigPanel {
* 导入 Git 文件到当前容器
*/
async importGitFile(filePath) {
if (!this.currentRepoId || !this.currentContainerId) {
vscode.window.showErrorMessage('请先选择 Git 仓库和容器');
if (!this.currentModuleFolderId || !this.currentContainerId) {
vscode.window.showErrorMessage('请先选择模块文件夹和容器');
return;
}
const repo = this.gitRepos.find(r => r.id === this.currentRepoId);
if (!repo) {
vscode.window.showErrorMessage('未找到当前 Git 仓库');
const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId);
if (!folder || folder.type !== 'git') {
vscode.window.showErrorMessage('未找到当前 Git 模块文件夹');
return;
}
const container = this.containers.find(c => c.id === this.currentContainerId);
@@ -622,8 +627,13 @@ class ConfigPanel {
return;
}
try {
const fullPath = path.join(repo.localPath, filePath);
const content = await fs.promises.readFile(fullPath, 'utf8');
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath) {
vscode.window.showErrorMessage('无法获取模块文件夹路径');
return;
}
const fileFullPath = path.join(fullPath, filePath);
const content = await fs.promises.readFile(fileFullPath, 'utf8');
const fileName = path.basename(filePath);
// 创建新配置
const newId = 'cfg' + (this.configs.length + 1);
@@ -685,20 +695,18 @@ class ConfigPanel {
const currentProjectContainers = this.containers.filter(c => currentAircraftIds.includes(c.aircraftId));
const currentContainerIds = currentProjectContainers.map(c => c.id);
const currentProjectConfigs = this.configs.filter(cfg => currentContainerIds.includes(cfg.containerId));
// 只保存与当前项目容器相关的 Git 仓库和合并文件夹
const currentProjectGitRepos = this.gitRepos.filter(repo => currentContainerIds.includes(repo.containerId));
const currentProjectMergedFolders = this.mergedFolders.filter(folder => currentContainerIds.includes(folder.containerId));
// 只保存与当前项目容器相关的模块文件夹
const currentProjectModuleFolders = this.moduleFolders.filter(folder => currentContainerIds.includes(folder.containerId));
const data = {
projects: this.projects.filter(p => p.id === this.currentProjectId),
aircrafts: currentProjectAircrafts,
containers: currentProjectContainers,
configs: currentProjectConfigs,
gitRepos: currentProjectGitRepos,
mergedFolders: currentProjectMergedFolders // 保存合并文件夹数据
moduleFolders: currentProjectModuleFolders // 保存模块文件夹数据
};
const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2));
await vscode.workspace.fs.writeFile(dataUri, uint8Array);
console.log('✅ 当前项目数据已保存,包含', currentProjectGitRepos.length, '个 Git 仓库和', currentProjectMergedFolders.length, '个合并文件夹');
console.log('✅ 当前项目数据已保存,包含', currentProjectModuleFolders.length, '个模块文件夹');
}
catch (error) {
vscode.window.showErrorMessage(`保存项目数据失败: ${error}`);
@@ -727,8 +735,7 @@ class ConfigPanel {
this.aircrafts = [];
this.containers = [];
this.configs = [];
this.gitRepos = [];
this.mergedFolders = []; // 清空合并文件夹数据
this.moduleFolders = []; // 清空模块文件夹数据
// 验证数据格式并加载
if (data.projects && Array.isArray(data.projects)) {
this.projects = data.projects;
@@ -742,11 +749,8 @@ class ConfigPanel {
if (data.configs && Array.isArray(data.configs)) {
this.configs = data.configs;
}
if (data.gitRepos && Array.isArray(data.gitRepos)) {
this.gitRepos = data.gitRepos;
}
if (data.mergedFolders && Array.isArray(data.mergedFolders)) {
this.mergedFolders = data.mergedFolders; // 加载合并文件夹数据
if (data.moduleFolders && Array.isArray(data.moduleFolders)) {
this.moduleFolders = data.moduleFolders; // 加载模块文件夹数据
}
// 设置当前项目为第一个项目(如果有的话)
if (this.projects.length > 0) {
@@ -754,7 +758,7 @@ class ConfigPanel {
this.projectPaths.set(this.currentProjectId, projectPath);
this.currentView = 'aircrafts';
}
vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${this.gitRepos.length} 个 Git 仓库和 ${this.mergedFolders.length}合并文件夹`);
vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${this.moduleFolders.length}模块文件夹`);
this.updateWebview();
return true;
}
@@ -905,8 +909,8 @@ class ConfigPanel {
// 删除相关的配置
const containerIds = this.containers.filter(c => aircraftIds.includes(c.aircraftId)).map(c => c.id);
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
// 删除相关的 Git 仓库
this.gitRepos = this.gitRepos.filter(repo => !containerIds.includes(repo.containerId));
// 删除相关的模块文件夹
this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId));
// 删除项目路径映射
this.projectPaths.delete(projectId);
vscode.window.showInformationMessage(`删除项目: ${project.name}`);
@@ -953,8 +957,8 @@ class ConfigPanel {
// 删除相关的配置
const containerIds = this.containers.filter(c => c.aircraftId === aircraftId).map(c => c.id);
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
// 删除相关的 Git 仓库
this.gitRepos = this.gitRepos.filter(repo => !containerIds.includes(repo.containerId));
// 删除相关的模块文件夹
this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId));
vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`);
await this.saveCurrentProjectData();
this.updateWebview();
@@ -1015,8 +1019,8 @@ class ConfigPanel {
this.containers = this.containers.filter(c => c.id !== containerId);
// 删除相关的配置
this.configs = this.configs.filter(cfg => cfg.containerId !== containerId);
// 删除相关的 Git 仓库
this.gitRepos = this.gitRepos.filter(repo => repo.containerId !== containerId);
// 删除相关的模块文件夹
this.moduleFolders = this.moduleFolders.filter(folder => folder.containerId !== containerId);
vscode.window.showInformationMessage(`删除容器: ${container.name}`);
await this.saveCurrentProjectData();
this.updateWebview();
@@ -1204,7 +1208,7 @@ class ConfigPanel {
message: `克隆分支: ${branch} (${i + 1}/${branches.length})`
});
console.log(`📥 克隆分支: ${branch}`);
await this.addGitRepo(url, this.generateRepoName(url, branch), branch);
await this.addGitModuleFolder(url, this.generateModuleFolderName(url, branch), branch);
}
});
vscode.window.showInformationMessage(`成功克隆 ${branches.length} 个分支`);
@@ -1214,7 +1218,7 @@ class ConfigPanel {
vscode.window.showErrorMessage(`克隆分支失败: ${error}`);
}
}
generateRepoName(url, branch) {
generateModuleFolderName(url, branch) {
const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo';
const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-');
return `${repoName}-${branchSafeName}`;
@@ -1257,18 +1261,16 @@ class ConfigPanel {
case 'configs':
const currentContainer = this.containers.find(c => c.id === this.currentContainerId);
const containerConfigs = this.configs.filter(cfg => cfg.containerId === this.currentContainerId);
const currentRepo = this.gitRepos.find(r => r.id === this.currentRepoId);
// 获取当前容器的 Git 仓库和合并文件夹
const containerGitRepos = this.gitRepos.filter(repo => repo.containerId === this.currentContainerId);
const containerMergedFolders = this.mergedFolders.filter(folder => folder.containerId === this.currentContainerId);
const currentModuleFolder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId);
// 获取当前容器的模块文件夹
const containerModuleFolders = this.moduleFolders.filter(folder => folder.containerId === this.currentContainerId);
return this.configView.render({
container: currentContainer,
configs: containerConfigs,
gitRepos: containerGitRepos,
currentGitRepo: currentRepo,
gitFileTree: this.currentRepoFileTree,
gitLoading: false,
mergedFolders: containerMergedFolders // 传递合并文件夹数据
moduleFolders: containerModuleFolders,
currentModuleFolder: currentModuleFolder,
moduleFolderFileTree: this.currentModuleFolderFileTree,
moduleFolderLoading: false
});
default:
return this.projectView.render({
@@ -1277,26 +1279,27 @@ class ConfigPanel {
});
}
}
async openGitRepoInVSCode(repoId) {
const repo = this.gitRepos.find(r => r.id === repoId);
if (!repo) {
vscode.window.showErrorMessage('未找到指定的 Git 仓库');
async openGitRepoInVSCode(folderId) {
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder) {
vscode.window.showErrorMessage('未找到指定的模块文件夹');
return;
}
try {
// 检查仓库目录是否存在
if (!fs.existsSync(repo.localPath)) {
vscode.window.showErrorMessage('Git 仓库目录不存在,请重新克隆');
// 检查文件夹是否存在
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath || !fs.existsSync(fullPath)) {
vscode.window.showErrorMessage('模块文件夹目录不存在');
return;
}
// 使用 VSCode 的文件选择器让用户选择要打开的文件
const fileUri = await vscode.window.showOpenDialog({
defaultUri: vscode.Uri.file(repo.localPath),
defaultUri: vscode.Uri.file(fullPath),
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
openLabel: '选择要打开的文件',
title: `${repo.name} 中选择文件`
title: `${folder.name} 中选择文件`
});
if (fileUri && fileUri.length > 0) {
// 打开选中的文件
@@ -1306,7 +1309,7 @@ class ConfigPanel {
}
}
catch (error) {
vscode.window.showErrorMessage(`打开 Git 仓库文件失败: ${error}`);
vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`);
}
}
async openConfigFileInVSCode(configId) {
@@ -1401,19 +1404,18 @@ class ConfigPanel {
console.log(`✅ 已创建配置文件: ${config.fileName}`);
}
}
// 构建相对路径
const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`;
// 创建合并文件夹记录
const newFolder = {
id: 'merged-' + Date.now(),
displayName: displayName,
folderName: folderName,
path: mergeFolderPath,
fileCount: copiedFiles.length,
containerId: this.currentContainerId,
originalConfigIds: configIds,
createdAt: new Date().toLocaleString()
name: displayName,
type: 'merged',
localPath: relativePath,
containerId: this.currentContainerId
};
// 添加到合并文件夹列表
this.mergedFolders.push(newFolder);
// 添加到模块文件夹列表
this.moduleFolders.push(newFolder);
// 删除原始配置文件
for (const configId of configIds) {
await this.deleteConfigInternal(configId);
@@ -1421,7 +1423,7 @@ class ConfigPanel {
// 保存数据
await this.saveCurrentProjectData();
vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`);
// 更新UI(不自动打开文件夹)
// 更新UI
this.updateWebview();
}
catch (error) {
@@ -1461,50 +1463,28 @@ class ConfigPanel {
console.error(`删除配置文件失败: ${error}`);
}
}
/**
* 删除合并文件夹
*/
async deleteMergedFolder(folderId) {
const folder = this.mergedFolders.find(f => f.id === folderId);
if (!folder)
return;
const confirm = await vscode.window.showWarningMessage(`确定要删除合并文件夹 "${folder.displayName}" 吗?这将删除文件夹及其所有内容。`, { modal: true }, '确定删除', '取消');
if (confirm === '确定删除') {
try {
// 删除文件夹及其所有内容
await fs.promises.rm(folder.path, { recursive: true, force: true });
// 从列表中移除
this.mergedFolders = this.mergedFolders.filter(f => f.id !== folderId);
await this.saveCurrentProjectData();
vscode.window.showInformationMessage(`合并文件夹已删除: ${folder.displayName}`);
this.updateWebview();
}
catch (error) {
vscode.window.showErrorMessage(`删除合并文件夹失败: ${error}`);
}
}
}
/**
* 在 VSCode 中打开合并文件夹
*/
async openMergedFolderInVSCode(folderId) {
const folder = this.mergedFolders.find(f => f.id === folderId);
const folder = this.moduleFolders.find(f => f.id === folderId);
if (!folder) {
vscode.window.showErrorMessage('未找到指定的合并文件夹');
vscode.window.showErrorMessage('未找到指定的模块文件夹');
return;
}
try {
// 检查文件夹是否存在
if (!fs.existsSync(folder.path)) {
vscode.window.showErrorMessage('合并文件夹不存在');
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath || !fs.existsSync(fullPath)) {
vscode.window.showErrorMessage('模块文件夹不存在');
return;
}
// 使用 VSCode 打开文件夹
const folderUri = vscode.Uri.file(folder.path);
const folderUri = vscode.Uri.file(fullPath);
vscode.commands.executeCommand('vscode.openFolder', folderUri, { forceNewWindow: false });
}
catch (error) {
vscode.window.showErrorMessage(`打开合并文件夹失败: ${error}`);
vscode.window.showErrorMessage(`打开模块文件夹失败: ${error}`);
}
}
/**
@@ -1513,44 +1493,26 @@ class ConfigPanel {
* @param id 模块 ID
*/
async openTheModuleFolder(type, id) {
let folderPath;
let folderName;
if (type === 'git') {
const repo = this.gitRepos.find(r => r.id === id);
if (!repo) {
vscode.window.showErrorMessage('未找到指定的 Git 仓库');
return;
}
folderPath = repo.localPath;
folderName = repo.name;
}
else if (type === 'merged') {
const folder = this.mergedFolders.find(f => f.id === id);
if (!folder) {
vscode.window.showErrorMessage('未找到指定的合并文件夹');
return;
}
folderPath = folder.path;
folderName = folder.displayName;
}
if (!folderPath) {
vscode.window.showErrorMessage('未找到文件夹路径');
const folder = this.moduleFolders.find(f => f.id === id);
if (!folder) {
vscode.window.showErrorMessage('未找到指定的模块文件夹');
return;
}
try {
// 检查文件夹是否存在
if (!fs.existsSync(folderPath)) {
vscode.window.showErrorMessage(`${type === 'git' ? 'Git 仓库' : '合并文件夹'}目录不存在`);
const fullPath = this.getModuleFolderFullPath(folder);
if (!fullPath || !fs.existsSync(fullPath)) {
vscode.window.showErrorMessage('模块文件夹目录不存在');
return;
}
// 使用 VSCode 的文件选择器让用户选择要打开的文件
const fileUri = await vscode.window.showOpenDialog({
defaultUri: vscode.Uri.file(folderPath),
defaultUri: vscode.Uri.file(fullPath),
canSelectFiles: true,
canSelectFolders: false,
canSelectMany: false,
openLabel: '选择要打开的文件',
title: `${folderName} 中选择文件`
title: `${folder.name} 中选择文件`
});
if (fileUri && fileUri.length > 0) {
// 打开选中的文件
@@ -1560,9 +1522,29 @@ class ConfigPanel {
}
}
catch (error) {
vscode.window.showErrorMessage(`打开${type === 'git' ? 'Git 仓库' : '合并文件夹'}文件失败: ${error}`);
vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`);
}
}
/**
* 获取模块文件夹的完整路径
*/
getModuleFolderFullPath(folder) {
const container = this.containers.find(c => c.id === folder.containerId);
if (!container)
return null;
const aircraft = this.aircrafts.find(a => a.id === container.aircraftId);
if (!aircraft)
return null;
const projectPath = this.projectPaths.get(aircraft.projectId);
if (!projectPath)
return null;
// 从相对路径解析出文件夹名称
const pathParts = folder.localPath.split('/').filter(part => part);
if (pathParts.length < 4)
return null;
const folderName = pathParts[pathParts.length - 1];
return path.join(projectPath, aircraft.name, container.name, folderName);
}
}
exports.ConfigPanel = ConfigPanel;
//# sourceMappingURL=ConfigPanel.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,4 @@
"use strict";
// src/types/DataTypes.ts
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=DataTypes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DataTypes.js","sourceRoot":"","sources":["../../../src/panels/types/DataTypes.ts"],"names":[],"mappings":";AAAA,yBAAyB"}

View File

@@ -6,14 +6,13 @@ class ConfigView extends BaseView_1.BaseView {
render(data) {
const container = data?.container;
const configs = data?.configs || [];
const gitRepos = data?.gitRepos || [];
const currentGitRepo = data?.currentGitRepo;
const gitFileTree = data?.gitFileTree || [];
const gitLoading = data?.gitLoading || false;
const moduleFolders = data?.moduleFolders || [];
const currentModuleFolder = data?.currentModuleFolder;
const moduleFolderFileTree = data?.moduleFolderFileTree || [];
const moduleFolderLoading = data?.moduleFolderLoading || false;
const gitBranches = data?.gitBranches || [];
const gitRepoUrl = data?.gitRepoUrl || '';
const mergedFolders = data?.mergedFolders || [];
// 生成配置列表的 HTML - 包含配置文件和 Git 仓库
// 生成配置列表的 HTML - 包含配置文件和模块文件夹
const configsHtml = configs.map((config) => `
<tr>
<td>
@@ -28,39 +27,22 @@ class ConfigView extends BaseView_1.BaseView {
</td>
</tr>
`).join('');
// 生成合并文件夹的 HTML - 显示在配置列表中
const mergedFoldersHtml = mergedFolders.map((folder) => `
<tr>
<td>
<span class="editable">📁 ${folder.displayName}</span>
</td>
<td>
<span class="clickable" onclick="openTheModuleFolder('${folder.id}', 'merged')">${folder.folderName}</span>
</td>
<td>
<button class="btn-delete" onclick="deleteMergedFolder('${folder.id}')">删除</button>
</td>
</tr>
`).join('');
// 生成 Git 仓库列表的 HTML - 修改显示方式Git 仓库不可勾选
const gitReposHtml = gitRepos.map(repo => {
// 提取仓库名称从URL中获取或使用name
const repoName = repo.name.split(' (')[0]; // 移除分支名部分
// 提取分支名
const branchMatch = repo.name.match(/\(([^)]+)\)/);
const branchName = branchMatch ? branchMatch[1] : repo.branch;
// 生成模块文件夹的 HTML - 统一显示 Git 和合并文件夹
const moduleFoldersHtml = moduleFolders.map((folder) => {
const icon = folder.type === 'git' ? '📁' : '📁';
return `
<tr>
<td>
<span class="editable">📁 ${repoName}</span>
<div style="font-size: 12px; color: var(--vscode-descriptionForeground); margin-top: 4px;">
</div>
<span class="editable">${icon} ${folder.name}</span>
</td>
<td>
<span class="clickable" onclick="openTheModuleFolder('${repo.id}', 'git')">${branchName}</span>
<span class="clickable" onclick="openTheModuleFolder('${folder.id}', '${folder.type}')">${folder.localPath.split('/').pop()}</span>
</td>
<td>
<button class="btn-delete" onclick="deleteGitRepo('${repo.id}')">删除</button>
${folder.type === 'git' ? `
<button class="btn-sync" onclick="syncModuleFolder('${folder.id}')" style="margin-right: 5px;">同步</button>
` : ''}
<button class="btn-delete" onclick="deleteModuleFolder('${folder.id}')">删除</button>
</td>
</tr>
`;
@@ -110,6 +92,19 @@ class ConfigView extends BaseView_1.BaseView {
opacity: 0.8;
}
.btn-sync {
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
padding: 4px 8px;
border: none;
border-radius: 2px;
cursor: pointer;
}
.btn-sync:hover {
background: var(--vscode-button-hoverBackground);
}
/* 树状分支样式 */
.branch-tree {
font-family: 'Courier New', monospace;
@@ -251,21 +246,20 @@ class ConfigView extends BaseView_1.BaseView {
<thead>
<tr>
<th width="30%">配置</th>
<th width="40%">文件</th>
<th width="40%">文件/文件夹</th>
<th width="30%">操作</th>
</tr>
</thead>
<tbody>
${configsHtml}
${mergedFoldersHtml}
${gitReposHtml}
${moduleFoldersHtml}
</tbody>
</table>
</div>
<!-- Git 仓库管理部分 -->
<!-- 模块文件夹管理部分 -->
<div class="config-section">
<h3 class="section-title">📚 Git 仓库管理</h3>
<h3 class="section-title">📚 模块云仓库</h3>
<!-- URL 输入区域 -->
<div class="url-input-section">
@@ -319,8 +313,7 @@ class ConfigView extends BaseView_1.BaseView {
});
}
// 统一功能:打开模块文件夹(合并 Git 仓库和合并文件夹功能)
// 统一功能:打开模块文件夹
function openTheModuleFolder(id, type) {
console.log('📂 打开模块文件夹:', { id, type });
vscode.postMessage({
@@ -364,46 +357,34 @@ class ConfigView extends BaseView_1.BaseView {
);
}
// 删除合并文件夹功能
function deleteMergedFolder(folderId) {
console.log('🗑️ 尝试删除合并文件夹:', folderId);
// 删除模块文件夹功能
function deleteModuleFolder(folderId) {
console.log('🗑️ 尝试删除模块文件夹:', folderId);
showConfirmDialog(
'确认删除合并文件夹',
'确定删除这个合并文件夹吗?这将删除文件夹及其所有内容。',
'确认删除模块文件夹',
'确定删除这个模块文件夹吗?这将删除文件夹及其所有内容。',
function() {
console.log('✅ 用户确认删除合并文件夹:', folderId);
console.log('✅ 用户确认删除模块文件夹:', folderId);
vscode.postMessage({
type: 'deleteMergedFolder',
type: 'deleteModuleFolder',
folderId: folderId
});
},
function() {
// 用户取消删除
console.log('❌ 用户取消删除合并文件夹');
console.log('❌ 用户取消删除模块文件夹');
}
);
}
// Git 仓库删除功能
function deleteGitRepo(repoId) {
console.log('🗑️ 尝试删除 Git 仓库:', repoId);
showConfirmDialog(
'确认删除 Git 仓库',
'确定删除这个 Git 仓库吗?这将删除本地克隆的代码文件夹。',
function() {
console.log('✅ 用户确认删除 Git 仓库:', repoId);
vscode.postMessage({
type: 'deleteGitRepo',
repoId: repoId
});
},
function() {
// 用户取消删除
console.log('❌ 用户取消删除 Git 仓库');
}
);
// 同步 Git 模块文件夹
function syncModuleFolder(folderId) {
console.log('🔄 同步模块文件夹:', folderId);
vscode.postMessage({
type: 'syncGitModuleFolder',
folderId: folderId
});
}
function goBackToContainers() {
@@ -480,14 +461,6 @@ class ConfigView extends BaseView_1.BaseView {
});
}
function syncGitRepo(repoId) {
console.log('🔄 同步仓库:', repoId);
vscode.postMessage({
type: 'syncGitRepo',
repoId: repoId
});
}
// 配置文件合并功能
function toggleConfigSelection(configId) {
const checkbox = document.querySelector('.config-checkbox[data-id="' + configId + '"]');

File diff suppressed because one or more lines are too long

4
out/types/DataTypes.js Normal file
View File

@@ -0,0 +1,4 @@
"use strict";
// src/types/DataTypes.ts
Object.defineProperty(exports, "__esModule", { value: true });
//# sourceMappingURL=DataTypes.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DataTypes.js","sourceRoot":"","sources":["../../src/types/DataTypes.ts"],"names":[],"mappings":";AAAA,yBAAyB"}

File diff suppressed because it is too large Load Diff

View File

@@ -16,6 +16,7 @@ export interface Container {
name: string;
aircraftId: string;
configs: Config[];
moduleFolders: ModuleFolder[]; // 新增:模块文件夹列表
}
export interface Config {
@@ -24,4 +25,13 @@ export interface Config {
fileName: string;
content: string;
containerId: string;
}
// 新增:统一的模块文件夹接口
export interface ModuleFolder {
id: string;
name: string;
type: 'git' | 'merged'; // 类型标识
localPath: string; // 相对路径,如 "/项目1/飞行器1/容器1/test-code"
containerId: string;
}

View File

@@ -0,0 +1,45 @@
// src/types/DataTypes.ts
// 统一的模块文件夹接口
export interface ModuleFolder {
id: string;
name: string;
type: 'git' | 'merged'; // 类型标识
localPath: string; // 相对路径,如 "/项目1/飞行器1/容器1/test-code"
containerId: string;
}
// 项目数据接口
export interface ProjectData {
projects: Project[];
aircrafts: Aircraft[];
containers: Container[];
configs: Config[];
moduleFolders: ModuleFolder[]; // 统一的模块文件夹数据
}
// 基础数据接口
export interface Project {
id: string;
name: string;
}
export interface Aircraft {
id: string;
name: string;
projectId: string;
}
export interface Container {
id: string;
name: string;
aircraftId: string;
}
export interface Config {
id: string;
name: string;
fileName: string;
content: string;
containerId: string;
}

9
src/panels/types/ViewTypes.ts Normal file → Executable file
View File

@@ -39,14 +39,13 @@ export interface ContainerConfigData {
configs: ConfigViewData[];
}
// 新增 Git 相关类型
export interface GitRepoData {
// 新增模块文件夹相关类型
export interface ModuleFolderData {
id: string;
name: string;
url: string;
type: 'git' | 'merged';
localPath: string;
branch: string;
lastSync: string;
containerId: string;
}
export interface GitFileTree {

View File

@@ -1,5 +1,6 @@
import { BaseView } from './BaseView';
import { ContainerConfigData, ConfigViewData } from '../types/ViewTypes';
import { ModuleFolder } from '../types/DataTypes';
// Git 分支接口
interface GitBranch {
@@ -26,29 +27,6 @@ interface GitFileTree {
children?: GitFileTree[];
}
// Git 仓库接口
interface GitRepo {
id: string;
name: string;
url: string;
localPath: string;
branch: string;
lastSync: string;
containerId: string;
}
// 合并文件夹接口
interface MergedFolder {
id: string;
displayName: string; // 配置栏显示的名称
folderName: string; // 实际文件夹名称
path: string;
fileCount: number;
containerId: string;
originalConfigIds: string[];
createdAt: string;
}
// 树状分支节点接口
interface BranchTreeNode {
name: string;
@@ -62,25 +40,23 @@ interface BranchTreeNode {
export class ConfigView extends BaseView {
render(data?: ContainerConfigData & {
gitRepos?: GitRepo[];
currentGitRepo?: GitRepo;
gitFileTree?: GitFileTree[];
gitLoading?: boolean;
moduleFolders?: ModuleFolder[];
currentModuleFolder?: ModuleFolder;
moduleFolderFileTree?: GitFileTree[];
moduleFolderLoading?: boolean;
gitBranches?: GitBranch[];
gitRepoUrl?: string;
mergedFolders?: MergedFolder[];
}): string {
const container = data?.container;
const configs = data?.configs || [];
const gitRepos = data?.gitRepos || [];
const currentGitRepo = data?.currentGitRepo;
const gitFileTree = data?.gitFileTree || [];
const gitLoading = data?.gitLoading || false;
const moduleFolders = data?.moduleFolders || [];
const currentModuleFolder = data?.currentModuleFolder;
const moduleFolderFileTree = data?.moduleFolderFileTree || [];
const moduleFolderLoading = data?.moduleFolderLoading || false;
const gitBranches = data?.gitBranches || [];
const gitRepoUrl = data?.gitRepoUrl || '';
const mergedFolders = data?.mergedFolders || [];
// 生成配置列表的 HTML - 包含配置文件和 Git 仓库
// 生成配置列表的 HTML - 包含配置文件和模块文件夹
const configsHtml = configs.map((config: ConfigViewData) => `
<tr>
<td>
@@ -96,41 +72,23 @@ export class ConfigView extends BaseView {
</tr>
`).join('');
// 生成合并文件夹的 HTML - 显示在配置列表中
const mergedFoldersHtml = mergedFolders.map((folder: MergedFolder) => `
<tr>
<td>
<span class="editable">📁 ${folder.displayName}</span>
</td>
<td>
<span class="clickable" onclick="openTheModuleFolder('${folder.id}', 'merged')">${folder.folderName}</span>
</td>
<td>
<button class="btn-delete" onclick="deleteMergedFolder('${folder.id}')">删除</button>
</td>
</tr>
`).join('');
// 生成 Git 仓库列表的 HTML - 修改显示方式Git 仓库不可勾选
const gitReposHtml = gitRepos.map(repo => {
// 提取仓库名称从URL中获取或使用name
const repoName = repo.name.split(' (')[0]; // 移除分支名部分
// 提取分支名
const branchMatch = repo.name.match(/\(([^)]+)\)/);
const branchName = branchMatch ? branchMatch[1] : repo.branch;
// 生成模块文件夹的 HTML - 统一显示 Git 和合并文件夹
const moduleFoldersHtml = moduleFolders.map((folder: ModuleFolder) => {
const icon = folder.type === 'git' ? '📁' : '📁';
return `
<tr>
<td>
<span class="editable">📁 ${repoName}</span>
<div style="font-size: 12px; color: var(--vscode-descriptionForeground); margin-top: 4px;">
</div>
<span class="editable">${icon} ${folder.name}</span>
</td>
<td>
<span class="clickable" onclick="openTheModuleFolder('${repo.id}', 'git')">${branchName}</span>
<span class="clickable" onclick="openTheModuleFolder('${folder.id}', '${folder.type}')">${folder.localPath.split('/').pop()}</span>
</td>
<td>
<button class="btn-delete" onclick="deleteGitRepo('${repo.id}')">删除</button>
${folder.type === 'git' ? `
<button class="btn-sync" onclick="syncModuleFolder('${folder.id}')" style="margin-right: 5px;">同步</button>
` : ''}
<button class="btn-delete" onclick="deleteModuleFolder('${folder.id}')">删除</button>
</td>
</tr>
`;
@@ -182,6 +140,19 @@ export class ConfigView extends BaseView {
opacity: 0.8;
}
.btn-sync {
background: var(--vscode-button-background);
color: var(--vscode-button-foreground);
padding: 4px 8px;
border: none;
border-radius: 2px;
cursor: pointer;
}
.btn-sync:hover {
background: var(--vscode-button-hoverBackground);
}
/* 树状分支样式 */
.branch-tree {
font-family: 'Courier New', monospace;
@@ -323,21 +294,20 @@ export class ConfigView extends BaseView {
<thead>
<tr>
<th width="30%">配置</th>
<th width="40%">文件</th>
<th width="40%">文件/文件夹</th>
<th width="30%">操作</th>
</tr>
</thead>
<tbody>
${configsHtml}
${mergedFoldersHtml}
${gitReposHtml}
${moduleFoldersHtml}
</tbody>
</table>
</div>
<!-- Git 仓库管理部分 -->
<!-- 模块文件夹管理部分 -->
<div class="config-section">
<h3 class="section-title">📚 Git 仓库管理</h3>
<h3 class="section-title">📚 模块云仓库</h3>
<!-- URL 输入区域 -->
<div class="url-input-section">
@@ -391,8 +361,7 @@ export class ConfigView extends BaseView {
});
}
// 统一功能:打开模块文件夹(合并 Git 仓库和合并文件夹功能)
// 统一功能:打开模块文件夹
function openTheModuleFolder(id, type) {
console.log('📂 打开模块文件夹:', { id, type });
vscode.postMessage({
@@ -436,46 +405,34 @@ export class ConfigView extends BaseView {
);
}
// 删除合并文件夹功能
function deleteMergedFolder(folderId) {
console.log('🗑️ 尝试删除合并文件夹:', folderId);
// 删除模块文件夹功能
function deleteModuleFolder(folderId) {
console.log('🗑️ 尝试删除模块文件夹:', folderId);
showConfirmDialog(
'确认删除合并文件夹',
'确定删除这个合并文件夹吗?这将删除文件夹及其所有内容。',
'确认删除模块文件夹',
'确定删除这个模块文件夹吗?这将删除文件夹及其所有内容。',
function() {
console.log('✅ 用户确认删除合并文件夹:', folderId);
console.log('✅ 用户确认删除模块文件夹:', folderId);
vscode.postMessage({
type: 'deleteMergedFolder',
type: 'deleteModuleFolder',
folderId: folderId
});
},
function() {
// 用户取消删除
console.log('❌ 用户取消删除合并文件夹');
console.log('❌ 用户取消删除模块文件夹');
}
);
}
// Git 仓库删除功能
function deleteGitRepo(repoId) {
console.log('🗑️ 尝试删除 Git 仓库:', repoId);
showConfirmDialog(
'确认删除 Git 仓库',
'确定删除这个 Git 仓库吗?这将删除本地克隆的代码文件夹。',
function() {
console.log('✅ 用户确认删除 Git 仓库:', repoId);
vscode.postMessage({
type: 'deleteGitRepo',
repoId: repoId
});
},
function() {
// 用户取消删除
console.log('❌ 用户取消删除 Git 仓库');
}
);
// 同步 Git 模块文件夹
function syncModuleFolder(folderId) {
console.log('🔄 同步模块文件夹:', folderId);
vscode.postMessage({
type: 'syncGitModuleFolder',
folderId: folderId
});
}
function goBackToContainers() {
@@ -552,14 +509,6 @@ export class ConfigView extends BaseView {
});
}
function syncGitRepo(repoId) {
console.log('🔄 同步仓库:', repoId);
vscode.postMessage({
type: 'syncGitRepo',
repoId: repoId
});
}
// 配置文件合并功能
function toggleConfigSelection(configId) {
const checkbox = document.querySelector('.config-checkbox[data-id="' + configId + '"]');