0
0

1、将每个代码仓库进行了隔离。2、优化了每个页面的ui对齐。3、增加了飞行器页面的所属项目显示。4、切换页面时对项目进行扫描,实时更新项目的结构,避免复制导致ui不显示的bug

This commit is contained in:
xubing
2026-03-04 10:19:04 +08:00
parent 942dab0f96
commit 79f7a3a860
38 changed files with 255 additions and 400 deletions

View File

@@ -24,7 +24,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProjectService = void 0;
// src/panels/services/ProjectService.ts
const vscode = __importStar(require("vscode"));
const path = __importStar(require("path"));
const fs = __importStar(require("fs"));
@@ -53,17 +52,17 @@ class ProjectService {
*/
sanitizeFileName(name) {
let fileName = name.trim();
// 1. 替换所有空格为下划线
// 替换所有空格为下划线
fileName = fileName.replace(/\s+/g, '_');
// 2. 移除特殊字符
// 移除特殊字符
fileName = fileName.replace(/[^\u4e00-\u9fa5a-zA-Z0-9_\-\.]/g, '');
// 3. 确保不为空
// 确保不为空
if (fileName.length === 0) {
return 'config_file';
}
return fileName;
}
// =============== 查重工具方法 (新增) ===============
// =============== 查重工具方法 ===============
/** 检查项目名是否重复 */
isProjectNameExists(name) {
return this.projects.some(p => p.name === name);
@@ -218,7 +217,6 @@ class ProjectService {
};
this.containers.push(newContainer);
await this.createContainerDirectory(newContainer);
await this.createDefaultConfigs(newContainer);
return newId;
}
updateContainerName(containerId, newName) {
@@ -537,20 +535,6 @@ class ProjectService {
console.error(`确保容器目录存在失败: ${error}`);
}
}
async createDefaultConfigs(container) {
this.configs.push({
id: this.generateUniqueId('cfg', this.configs),
name: '配置1',
fileName: 'dockerfile',
containerId: container.id
});
this.configs.push({
id: this.generateUniqueId('cfg', this.configs),
name: '配置2',
fileName: 'docker-compose.yml',
containerId: container.id
});
}
// =============== 数据持久化 ===============
async saveCurrentProjectData(projectId) {
try {
@@ -688,12 +672,11 @@ class ProjectService {
return true;
}
/**
* [新方法] 仅在内存中注册模块文件夹(用于监测到磁盘文件夹创建时)
* 仅在内存中注册模块文件夹(用于监测到磁盘文件夹创建时)
*/
registerModuleFolderFromDisk(folderName, containerId, aircraftId, projectId, aircraftName, containerName, fullPath) {
const relativePath = `/${projectId}/${aircraftName}/${containerName}/${folderName}`;
// 查重:只要同一个容器下,有任何一个模块指向了相同的文件夹名,就视为已存在
// 这样即使旧数据的 localPath 路径字符串是过时的,也不会重复添加
// 只要同一个容器下,有任何一个模块指向了相同的文件夹名,就视为已存在
const existing = this.moduleFolders.find(f => {
if (f.containerId !== containerId)
return false;
@@ -703,7 +686,7 @@ class ProjectService {
});
if (existing)
return false;
// 智能检测:如果文件夹下有 .git则标记为 git 类型
// 如果文件夹下有 .git则标记为 git 类型
let type = 'local';
if (fullPath) {
const gitDir = path.join(fullPath, '.git');
@@ -723,11 +706,9 @@ class ProjectService {
return true;
}
/**
* [新方法] 处理磁盘删除事件:根据路径移除对应的 Config 或 ModuleFolder
* 处理磁盘删除事件:根据路径移除对应的 Config 或 ModuleFolder
*/
removeEntityByPath(filePath, projectId) {
// 这里的 filePath 是绝对路径,需要反解出是哪个 Config 或 Folder
// 这是一个比较繁琐的过程,简化逻辑如下:
let changed = false;
const projectPath = this.projectPaths.get(projectId);
if (!projectPath || !filePath.startsWith(projectPath))
@@ -760,7 +741,7 @@ class ProjectService {
if (!projectPath || !fs.existsSync(projectPath))
return false;
let changed = false;
// 1. 扫描磁盘,添加缺失的飞行器
// 扫描磁盘,添加缺失的飞行器
try {
const entries = await fs.promises.readdir(projectPath, { withFileTypes: true });
for (const entry of entries) {
@@ -780,7 +761,7 @@ class ProjectService {
catch (e) {
console.error('扫描项目目录失败:', e);
}
// 2. 检查内存,移除磁盘不存在的飞行器 (清理无效数据)
// 检查内存,移除磁盘不存在的飞行器 (清理无效数据)
const currentAircrafts = this.getAircraftsByProject(projectId);
for (const aircraft of currentAircrafts) {
const aircraftPath = path.join(projectPath, aircraft.name);
@@ -799,7 +780,7 @@ class ProjectService {
if (!dirPath || !fs.existsSync(dirPath))
return false;
let changed = false;
// 1. 扫描磁盘,添加缺失的容器
// 扫描磁盘,添加缺失的容器
try {
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
for (const entry of entries) {
@@ -817,7 +798,7 @@ class ProjectService {
catch (e) {
console.error('扫描飞行器目录失败:', e);
}
// 2. 检查内存,移除磁盘不存在的容器
// 检查内存,移除磁盘不存在的容器
const currentContainers = this.getContainersByAircraft(aircraftId);
for (const container of currentContainers) {
const containerPath = path.join(dirPath, container.name);
@@ -842,7 +823,7 @@ class ProjectService {
if (!aircraft)
return false;
let changed = false;
// 1. 扫描磁盘,添加缺失的配置和模块
// 扫描磁盘,添加缺失的配置和模块
try {
const entries = await fs.promises.readdir(dirPath, { withFileTypes: true });
for (const entry of entries) {
@@ -865,7 +846,7 @@ class ProjectService {
catch (e) {
console.error('扫描容器目录失败:', e);
}
// 2. 检查内存,移除磁盘不存在的 配置
// 检查内存,移除磁盘不存在的 配置
const currentConfigs = this.getConfigsByContainer(containerId);
for (const config of currentConfigs) {
const configPath = path.join(dirPath, config.fileName);
@@ -874,12 +855,9 @@ class ProjectService {
changed = true;
}
}
// 3. 检查内存,移除磁盘不存在的 模块文件夹
// 检查内存,移除磁盘不存在的 模块文件夹
const currentModules = this.getModuleFoldersByContainer(containerId);
for (const folder of currentModules) {
// 注意Git 类型的模块文件夹,其 localPath 也是指向这个目录的
// 这里我们简单拼接路径来检查
// folder.localPath 格式: /projectId/aircraft/container/folderName
const folderName = folder.localPath.split('/').pop();
if (folderName) {
const folderPath = path.join(dirPath, folderName);
@@ -892,7 +870,7 @@ class ProjectService {
return changed;
}
/**
* [新增] 递归清理目录下所有的嵌套 .git 文件夹
* 递归清理目录下所有的嵌套 .git 文件夹
* 作用:保留 rootDir 下的 .git但删除所有子目录中的 .git
* 解决父级上传时因包含子级仓库导致的冲突
*/
@@ -902,17 +880,17 @@ class ProjectService {
try {
const entries = await fs.promises.readdir(rootDir, { withFileTypes: true });
for (const entry of entries) {
// 1. 如果遍历到的是当前目录下的 .git直接跳过(这是我们要保留的主仓库)
// 如果遍历到的是当前目录下的 .git直接跳过
if (entry.name === '.git')
continue;
// 2. 只处理目录
// 只处理目录
if (entry.isDirectory()) {
const subDir = path.join(rootDir, entry.name);
const nestedGit = path.join(subDir, '.git');
// 检查子目录下是否有 .git
if (fs.existsSync(nestedGit)) {
console.log(`🧹 发现嵌套 Git 仓库,正在移除以支持父级上传: ${nestedGit}`);
// 使用您之前实现的强力删除方法(带权限处理)
// 使用强力删除方法(带权限处理)
await this.deleteDirectoryFromDisk(nestedGit);
}
// 继续递归,防止有多层嵌套
@@ -922,7 +900,6 @@ class ProjectService {
}
catch (error) {
console.error(`清理嵌套 Git 失败: ${error}`);
// 不抛出错误,尽力而为,以免打断上传流程
}
}
}