diff --git a/dcsp-repos.json b/dcsp-repos.json index 0727d12..2612e57 100644 --- a/dcsp-repos.json +++ b/dcsp-repos.json @@ -4,13 +4,7 @@ "name": "卫星模型", "url": "http://117.72.162.127:3000/xb/test.git", "username": "xb", - "password": "1627031394xb" - }, - { - "name": "动力学仓库", - "url": "http://117.72.162.127:3000/xb/build.git", - "username": "xb", - "password": "1627031394xb" + "token": "582e19830c58bdbfa8962f881ec873cce208ead0" } ] } \ No newline at end of file diff --git a/dsc-platform-1.5.1.vsix b/dsc-platform-1.5.1.vsix new file mode 100644 index 0000000..44c4478 Binary files /dev/null and b/dsc-platform-1.5.1.vsix differ diff --git a/out/panels/ConfigPanel.js b/out/panels/ConfigPanel.js index b5a83c2..dcc97bf 100644 --- a/out/panels/ConfigPanel.js +++ b/out/panels/ConfigPanel.js @@ -22,23 +22,18 @@ var __importStar = (this && this.__importStar) || function (mod) { __setModuleDefault(result, mod); return result; }; -var __importDefault = (this && this.__importDefault) || function (mod) { - return (mod && mod.__esModule) ? mod : { "default": mod }; -}; Object.defineProperty(exports, "__esModule", { value: true }); exports.ConfigPanel = void 0; +// src/panels/ConfigPanel.ts const vscode = __importStar(require("vscode")); const path = __importStar(require("path")); -const fs = __importStar(require("fs")); -const isomorphic_git_1 = __importDefault(require("isomorphic-git")); -const node_1 = __importDefault(require("isomorphic-git/http/node")); const ProjectView_1 = require("./views/ProjectView"); const AircraftView_1 = require("./views/AircraftView"); const ContainerView_1 = require("./views/ContainerView"); const ConfigView_1 = require("./views/ConfigView"); -// ============================================= -// 主面板类 -// ============================================= +const ProjectService_1 = require("./services/ProjectService"); +const GitService_1 = require("./services/GitService"); +const StorageService_1 = require("./services/StorageService"); class ConfigPanel { // ============================================= // 公共方法 @@ -63,30 +58,25 @@ class ConfigPanel { this.currentAircraftId = ''; this.currentContainerId = ''; this.currentModuleFolderId = ''; - // 数据存储 - this.projects = []; - this.aircrafts = []; - this.containers = []; - this.configs = []; - this.moduleFolders = []; - this.currentModuleFolderFileTree = []; - this.projectPaths = new Map(); - // 上传相关:local 上传 / git 上传 - this.pendingUploadFolderId = null; // local -> git - this.pendingGitUploadFolderId = null; // git -> repo(更新或新分支) + // 上传相关 + this.pendingUploadFolderId = null; + this.pendingGitUploadFolderId = null; // 仓库配置 this.repoConfigs = []; // 状态管理 this.isWebviewDisposed = false; + this.currentModuleFolderFileTree = []; this.panel = panel; this.extensionUri = extensionUri; this.isWebviewDisposed = false; + // 初始化服务 + this.projectService = new ProjectService_1.ProjectService(); // 初始化视图 this.projectView = new ProjectView_1.ProjectView(extensionUri); this.aircraftView = new AircraftView_1.AircraftView(extensionUri); this.containerView = new ContainerView_1.ContainerView(extensionUri); this.configView = new ConfigView_1.ConfigView(extensionUri); - // 尝试加载仓库配置 + // 加载仓库配置 void this.loadRepoConfigs(); this.updateWebview(); this.setupMessageListener(); @@ -96,93 +86,23 @@ class ConfigPanel { }); } // ============================================= - // 工具方法 - ID 生成 - // ============================================= - generateUniqueId(prefix, existingItems) { - let idNumber = 1; - const existingIds = existingItems.map(item => item.id); - const numberPattern = /\d+$/; - for (const id of existingIds) { - const match = id.match(numberPattern); - if (match) { - const num = parseInt(match[0]); - if (num >= idNumber) { - idNumber = num + 1; - } - } - } - return `${prefix}${idNumber}`; - } - // ============================================= // 仓库配置相关 // ============================================= - getRepoConfigPath() { - return path.join(this.extensionUri.fsPath, 'dcsp-repos.json'); - } async loadRepoConfigs() { - try { - const configPath = this.getRepoConfigPath(); - if (!fs.existsSync(configPath)) { - this.repoConfigs = []; - return; - } - const content = await fs.promises.readFile(configPath, 'utf8'); - if (!content.trim()) { - this.repoConfigs = []; - return; - } - const parsed = JSON.parse(content); - if (Array.isArray(parsed)) { - this.repoConfigs = parsed; - } - else if (parsed && Array.isArray(parsed.repos)) { - this.repoConfigs = parsed.repos; - } - else { - this.repoConfigs = []; - } - } - catch (error) { - console.error('加载仓库配置失败:', error); - vscode.window.showErrorMessage('读取仓库配置文件失败(dcsp-repos.json),请检查文件格式。'); - this.repoConfigs = []; - } - } - async ensureRepoConfigFileExists() { - const configPath = this.getRepoConfigPath(); - if (!fs.existsSync(configPath)) { - const defaultContent = JSON.stringify({ - repos: [ - { - name: 'example-repo', - url: 'https://github.com/username/repo.git', - username: '', - password: '' - } - ] - }, null, 2); - await fs.promises.writeFile(configPath, defaultContent, 'utf8'); - } + this.repoConfigs = await StorageService_1.StorageService.loadRepoConfigs(this.extensionUri); } async openRepoConfig() { - try { - await this.ensureRepoConfigFileExists(); - const configPath = this.getRepoConfigPath(); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(configPath)); - await vscode.window.showTextDocument(doc); - await this.loadRepoConfigs(); - } - catch (error) { - vscode.window.showErrorMessage(`打开仓库配置文件失败: ${error}`); - } + await StorageService_1.StorageService.openRepoConfig(this.extensionUri); + await this.loadRepoConfigs(); } /** - * 通用:弹出仓库选择弹窗(不区分“获取分支 / 上传”,使用 pendingXXX 做上下文判断) + * 弹出仓库选择弹窗 */ async openRepoSelect() { await this.loadRepoConfigs(); - if (!this.repoConfigs || this.repoConfigs.length === 0) { - vscode.window.showWarningMessage('尚未配置任何仓库,请先点击右上角 “仓库配置” 按钮编辑 dcsp-repos.json。'); + if (this.repoConfigs.length === 0) { + vscode.window.showWarningMessage('尚未配置任何仓库,请先点击右上角 "仓库配置" 按钮编辑 dcsp-repos.json。'); + return; } if (this.isWebviewDisposed) return; @@ -193,104 +113,96 @@ class ConfigPanel { } /** * 仓库选择确认后的统一入口 - * - local 上传:pendingUploadFolderId 有值 - * - git 上传:pendingGitUploadFolderId 有值 - * - 其余:当作“获取分支”处理 */ async handleRepoSelectedForBranches(repoName) { await this.loadRepoConfigs(); const repo = this.repoConfigs.find(r => r.name === repoName); if (!repo) { - vscode.window.showErrorMessage(`在仓库配置中未找到名为 "${repoName}" 的仓库,请检查 dcsp-repos.json。`); + vscode.window.showErrorMessage(`在仓库配置中未找到名为 "${repoName}" 的仓库`); return; } // 1️⃣ Local 模块上传(local -> git) if (this.pendingUploadFolderId) { const localFolderId = this.pendingUploadFolderId; this.pendingUploadFolderId = null; - console.log("🚀 Local 上传流程:repo =", repoName, "folderId =", localFolderId); - const folder = this.moduleFolders.find(f => f.id === localFolderId); - if (!folder || folder.type !== 'local') { - vscode.window.showErrorMessage("未找到要上传的本地模块文件夹"); - return; - } - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage("无法确定本地模块文件夹路径"); - return; - } - const branchName = path.basename(fullPath); - console.log("🌿 Local 上传自动生成分支名:", branchName); - await this.uploadLocalModuleFolder(localFolderId, repo.url, branchName); + await this.processLocalUpload(localFolderId, repo); return; } // 2️⃣ Git 模块上传(git -> repo) if (this.pendingGitUploadFolderId) { const gitFolderId = this.pendingGitUploadFolderId; this.pendingGitUploadFolderId = null; - console.log("🚀 Git 上传流程:repo =", repoName, "folderId =", gitFolderId); - const folder = this.moduleFolders.find(f => f.id === gitFolderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage("未找到要上传的 Git 模块文件夹"); - return; - } - const newFolderName = folder.localPath.split('/').pop() ?? ''; - const oldFolderName = folder.originalFolderName ?? newFolderName; - const isRenamed = newFolderName !== oldFolderName; - const isSameRepo = !!folder.originalRepoUrl && folder.originalRepoUrl === repo.url; - console.log('🔍 Git 上传判断:'); - console.log(' oldFolderName:', oldFolderName); - console.log(' newFolderName:', newFolderName); - console.log(' isRenamed :', isRenamed); - console.log(' folderRepo :', folder.originalRepoUrl); - console.log(' selectedRepo :', repo.url); - console.log(' isSameRepo :', isSameRepo); - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage("无法确定 Git 模块文件夹路径"); - return; - } - // 2.1 未改名 + 还是原来的仓库 → 直接在原分支上 push(更新代码) - if (!isRenamed && isSameRepo) { - console.log('✅ 未改名 & 同仓库:执行原始 push 逻辑'); - await this.uploadGitModuleFolder(gitFolderId); - return; - } - // 2.2 改了名字 或 换了仓库 → 使用“当前文件夹名”作为分支,推送到选中仓库 - console.log('🆕 名称改变或仓库改变:以文件夹名作为新分支上传'); - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '准备上传...' }); - await this.pushGitModuleFolderToRepoWithBranch(fullPath, repo.url, newFolderName); - folder.uploaded = true; - folder.originalFolderName = newFolderName; - folder.originalRepoUrl = repo.url; - await this.saveCurrentProjectData(); - progress.report({ increment: 100, message: '完成' }); - vscode.window.showInformationMessage(`✅ Git 仓库已上传到 ${repo.name} 的分支 ${newFolderName}`); - this.updateWebview(); - } - catch (error) { - console.error('❌ Git 上传到新仓库/分支失败:', error); - vscode.window.showErrorMessage(`推送失败: ${error.message || error}`); - } - }); + await this.processGitUpload(gitFolderId, repo); return; } - // 3️⃣ 默认:获取分支(用于“获取仓库”-> 克隆) + // 3️⃣ 默认:获取分支(用于"获取仓库"-> 克隆) this.currentRepoForBranches = repo; await this.fetchBranchesForRepo(repo); } + async processLocalUpload(folderId, repo) { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder || folder.type !== 'local') { + vscode.window.showErrorMessage("未找到要上传的本地模块文件夹"); + return; + } + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage("无法确定本地模块文件夹路径"); + return; + } + const branchName = path.basename(fullPath); + await this.uploadLocalModuleFolder(folderId, repo.url, branchName, repo.username, repo.token); + } + async processGitUpload(folderId, repo) { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage("未找到要上传的 Git 模块文件夹"); + return; + } + const newFolderName = folder.localPath.split('/').pop() ?? ''; + const oldFolderName = folder.originalFolderName ?? newFolderName; + const isRenamed = newFolderName !== oldFolderName; + const isSameRepo = !!folder.originalRepoUrl && folder.originalRepoUrl === repo.url; + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage("无法确定 Git 模块文件夹路径"); + return; + } + // 2.1 未改名 + 还是原来的仓库 → 直接在原分支上 push(更新代码) + if (!isRenamed && isSameRepo) { + await this.uploadGitModuleFolder(folderId); + return; + } + // 2.2 改了名字 或 换了仓库 → 使用"当前文件夹名"作为分支,推送到选中仓库 + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '准备上传...' }); + await GitService_1.GitService.pushToRepoUrl(fullPath, repo.url, newFolderName, repo.username, repo.token); + this.projectService.updateModuleFolder(folderId, { + uploaded: true, + originalFolderName: newFolderName, + originalRepoUrl: repo.url + }); + await this.saveCurrentProjectData(); + progress.report({ increment: 100, message: '完成' }); + vscode.window.showInformationMessage(`✅ Git 仓库已上传到 ${repo.name} 的分支 ${newFolderName}`); + this.updateWebview(); + } + catch (error) { + console.error('❌ Git 上传到新仓库/分支失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message || error}`); + } + }); + } // ============================================= // Webview 消息处理 // ============================================= setupMessageListener() { this.panel.webview.onDidReceiveMessage(async (data) => { - console.log('📨 收到Webview消息:', data); if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,忽略消息'); return; @@ -335,11 +247,11 @@ class ConfigPanel { 'deleteConfig': (data) => this.deleteConfig(data.configId), 'openConfigFileInVSCode': (data) => this.openConfigFileInVSCode(data.configId), 'mergeConfigs': (data) => this.mergeConfigs(data.configIds, data.displayName, data.folderName), - // Git 仓库管理(新:基于配置) + // Git 仓库管理 'openRepoConfig': () => this.openRepoConfig(), 'openRepoSelect': () => this.openRepoSelect(), 'repoSelectedForBranches': (data) => this.handleRepoSelectedForBranches(data.repoName), - // Git 仓库管理(老接口:为了兼容,仍然保留) + // Git 分支管理 'fetchBranches': (data) => this.fetchBranches(data.url), 'cloneBranches': (data) => this.cloneBranches(data.branches), 'cancelBranchSelection': () => this.handleCancelBranchSelection(), @@ -415,53 +327,53 @@ class ConfigPanel { console.log('❌ 取消分支选择'); this.updateWebview(); } + async handleOpenRepoSelectForUpload(folderId) { + console.log("📌 Local 上传:收到 openRepoSelectForUpload,folderId =", folderId); + this.pendingUploadFolderId = folderId; + await this.openRepoSelect(); + } + async openRepoSelectForGitUpload(folderId) { + console.log('📌 Git 上传:收到 openRepoSelectForGitUpload,folderId =', folderId); + this.pendingGitUploadFolderId = folderId; + await this.openRepoSelect(); + } + async handleRepoSelectedForGitUpload(folderId, repoName) { + // 兼容:如果前端用的是 repoSelectedForGitUpload 事件,则这里转成统一逻辑 + this.pendingGitUploadFolderId = folderId; + await this.handleRepoSelectedForBranches(repoName); + } // ============================================= // 项目管理方法 // ============================================= async updateProjectName(projectId, newName) { - const project = this.projects.find(p => p.id === projectId); - if (project) { - project.name = newName; + if (this.projectService.updateProjectName(projectId, newName)) { vscode.window.showInformationMessage(`项目名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); } } async createProject(name) { - const newId = this.generateUniqueId('p', this.projects); - const newProject = { - id: newId, - name: name - }; - this.projects.push(newProject); + const newId = await this.projectService.createProject(name); this.currentProjectId = newId; vscode.window.showInformationMessage(`新建项目: ${name}`); this.updateWebview(); } async deleteProject(projectId) { - const project = this.projects.find(p => p.id === projectId); - if (!project) - return; - this.projects = this.projects.filter(p => p.id !== projectId); - const relatedAircrafts = this.aircrafts.filter(a => a.projectId === projectId); - const aircraftIds = relatedAircrafts.map(a => a.id); - this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); - this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); - const containerIds = this.containers.filter(c => aircraftIds.includes(c.aircraftId)).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - this.projectPaths.delete(projectId); - vscode.window.showInformationMessage(`删除项目: ${project.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteProject(projectId)) { + if (this.currentProjectId === projectId) { + this.currentProjectId = ''; + this.currentView = 'projects'; + } + vscode.window.showInformationMessage('项目已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= // 飞行器管理方法 // ============================================= async updateAircraftName(aircraftId, newName) { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (aircraft) { - aircraft.name = newName; + if (this.projectService.updateAircraftName(aircraftId, newName)) { vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -472,38 +384,23 @@ class ConfigPanel { vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目'); return; } - const newId = this.generateUniqueId('a', this.aircrafts); - const newAircraft = { - id: newId, - name: name, - projectId: this.currentProjectId - }; - this.aircrafts.push(newAircraft); - await this.createAircraftDirectory(newAircraft); + const aircraftId = await this.projectService.createAircraft(name, this.currentProjectId); vscode.window.showInformationMessage(`新建飞行器: ${name}`); await this.saveCurrentProjectData(); this.updateWebview(); } async deleteAircraft(aircraftId) { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (!aircraft) - return; - this.aircrafts = this.aircrafts.filter(a => a.id !== aircraftId); - this.containers = this.containers.filter(c => c.aircraftId !== aircraftId); - const containerIds = this.containers.filter(c => c.aircraftId === aircraftId).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteAircraft(aircraftId)) { + vscode.window.showInformationMessage('飞行器已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= // 容器管理方法 // ============================================= async updateContainerName(containerId, newName) { - const container = this.containers.find(c => c.id === containerId); - if (container) { - container.name = newName; + if (this.projectService.updateContainerName(containerId, newName)) { vscode.window.showInformationMessage(`容器名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -514,64 +411,36 @@ class ConfigPanel { vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器'); return; } - const newId = this.generateUniqueId('c', this.containers); - const newContainer = { - id: newId, - name: name, - aircraftId: this.currentAircraftId - }; - this.containers.push(newContainer); - await this.createContainerDirectory(newContainer); - await this.createDefaultConfigs(newContainer); + const containerId = await this.projectService.createContainer(name, this.currentAircraftId); vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`); await this.saveCurrentProjectData(); this.updateWebview(); } async deleteContainer(containerId) { - const container = this.containers.find(c => c.id === containerId); - if (!container) - return; - this.containers = this.containers.filter(c => c.id !== containerId); - this.configs = this.configs.filter(cfg => cfg.containerId !== containerId); - this.moduleFolders = this.moduleFolders.filter(folder => folder.containerId !== containerId); - vscode.window.showInformationMessage(`删除容器: ${container.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteContainer(containerId)) { + vscode.window.showInformationMessage('容器已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= // 配置管理方法 // ============================================= async updateConfigName(configId, newName) { - const config = this.configs.find(c => c.id === configId); - if (config) { - config.name = newName; + if (this.projectService.updateConfigName(configId, newName)) { vscode.window.showInformationMessage(`配置名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); } } async createConfig(name) { - const newId = this.generateUniqueId('cfg', this.configs); - const newConfig = { - id: newId, - name: name, - fileName: name.toLowerCase().replace(/\s+/g, '_'), - content: `# ${name} 配置文件\n# 创建时间: ${new Date().toLocaleString()}\n# 您可以在此编辑配置内容\n\n`, - containerId: this.currentContainerId - }; - this.configs.push(newConfig); - await this.ensureContainerDirectoryExists(this.currentContainerId); + const configId = await this.projectService.createConfig(name, this.currentContainerId); vscode.window.showInformationMessage(`新建配置: ${name}`); await this.saveCurrentProjectData(); this.updateWebview(); } - async handleOpenRepoSelectForUpload(folderId) { - console.log("📌 Local 上传:收到 openRepoSelectForUpload,folderId =", folderId); - this.pendingUploadFolderId = folderId; - await this.openRepoSelect(); - } async deleteConfig(configId) { - const config = this.configs.find(c => c.id === configId); + const config = this.projectService.getConfig(configId); if (!config) return; const confirm = await vscode.window.showWarningMessage(`确定要删除配置文件 "${config.name}" 吗?这将同时删除磁盘上的文件。`, { modal: true }, '确定删除', '取消'); @@ -579,8 +448,10 @@ class ConfigPanel { return; } try { - this.configs = this.configs.filter(c => c.id !== configId); - await this.deleteConfigFileFromDisk(config); + // 删除配置文件 + await this.projectService.deleteConfigFileFromDisk(configId); + // 从内存中删除 + this.projectService.deleteConfig(configId); vscode.window.showInformationMessage(`删除配置: ${config.name}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -599,42 +470,55 @@ class ConfigPanel { return; } try { - const container = this.containers.find(c => c.id === this.currentContainerId); - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!container || !aircraft || !projectPath) { - vscode.window.showErrorMessage('未找到相关项目数据'); + const container = this.projectService.getContainersByAircraft(this.currentAircraftId) + .find(c => c.id === this.currentContainerId); + if (!container) { + vscode.window.showErrorMessage('未找到容器数据'); return; } - const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); + const projectPath = this.projectService.getProjectPath(this.currentProjectId); + if (!projectPath) { + vscode.window.showErrorMessage('未找到项目路径'); + return; + } + // 获取选中的配置 + const selectedConfigs = configIds + .map(id => this.projectService.getConfig(id)) + .filter(Boolean); if (selectedConfigs.length !== configIds.length) { vscode.window.showErrorMessage('部分配置文件未找到'); return; } - const mergeFolderPath = path.join(projectPath, aircraft.name, container.name, folderName); - await fs.promises.mkdir(mergeFolderPath, { recursive: true }); + // 创建合并文件夹 + const mergeFolderPath = path.join(projectPath, this.getAircraftName(), container.name, folderName); + await vscode.workspace.fs.createDirectory(vscode.Uri.file(mergeFolderPath)); + // 复制文件到合并文件夹 for (const config of selectedConfigs) { - const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); + if (!config) + continue; + const sourcePath = this.projectService.getConfigFilePath(config.id); const targetPath = path.join(mergeFolderPath, config.fileName); - if (fs.existsSync(sourcePath)) { - await fs.promises.copyFile(sourcePath, targetPath); + if (sourcePath && require('fs').existsSync(sourcePath)) { + await require('fs').promises.copyFile(sourcePath, targetPath); } else { - await fs.promises.writeFile(targetPath, config.content || ''); + await require('fs').promises.writeFile(targetPath, config.content || ''); } } - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - const newId = this.generateUniqueId('local-', this.moduleFolders); + // 创建模块文件夹记录(使用 ProjectService 的统一 ID 生成) + const relativePath = `/${this.currentProjectId}/${this.getAircraftName()}/${container.name}/${folderName}`; const newFolder = { - id: newId, + id: this.projectService.generateUniqueId('local-'), name: displayName, type: 'local', localPath: relativePath, containerId: this.currentContainerId }; - this.moduleFolders.push(newFolder); + this.projectService.addModuleFolder(newFolder); + // 删除原配置 for (const configId of configIds) { - await this.deleteConfigInternal(configId); + this.projectService.deleteConfig(configId); + await this.projectService.deleteConfigFileFromDisk(configId); } await this.saveCurrentProjectData(); vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`); @@ -645,6 +529,16 @@ class ConfigPanel { vscode.window.showErrorMessage(`合并配置文件失败: ${error}`); } } + getAircraftName() { + const aircrafts = this.projectService.getAircraftsByProject(this.currentProjectId); + const aircraft = aircrafts.find(a => a.id === this.currentAircraftId); + return aircraft?.name || '未知飞行器'; + } + getContainerName() { + const containers = this.projectService.getContainersByAircraft(this.currentAircraftId); + const container = containers.find(c => c.id === this.currentContainerId); + return container?.name || '未知容器'; + } // ============================================= // Git 分支管理方法 // ============================================= @@ -653,7 +547,6 @@ class ConfigPanel { } async fetchBranches(url, repo) { try { - console.log('🌿 开始获取分支列表:', url); await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: '正在获取分支信息', @@ -662,38 +555,12 @@ class ConfigPanel { progress.report({ increment: 0, message: '连接远程仓库...' }); try { progress.report({ increment: 30, message: '获取远程引用...' }); - const options = { - http: node_1.default, - url: url - }; - if (repo && (repo.username || repo.password)) { - options.onAuth = () => ({ - username: repo.username || '', - password: repo.password || '' - }); - } - const refs = await isomorphic_git_1.default.listServerRefs(options); - console.log('📋 获取到的引用:', refs); - const branchRefs = refs.filter((ref) => ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/')); - const branches = branchRefs.map((ref) => { - let branchName; - if (ref.ref.startsWith('refs/remotes/')) { - branchName = ref.ref.replace('refs/remotes/origin/', ''); - } - else { - branchName = ref.ref.replace('refs/heads/', ''); - } - return { - name: branchName, - isCurrent: branchName === 'main' || branchName === 'master', - selected: false - }; - }); + const branches = await GitService_1.GitService.fetchBranches(url, repo?.username, repo?.token); if (branches.length === 0) { throw new Error('未找到任何分支'); } progress.report({ increment: 80, message: '处理分支数据...' }); - const branchTree = this.buildBranchTree(branches); + const branchTree = GitService_1.GitService.buildBranchTree(branches); if (!this.isWebviewDisposed) { this.panel.webview.postMessage({ type: 'branchesFetched', @@ -706,7 +573,7 @@ class ConfigPanel { progress.report({ increment: 100, message: '完成' }); } catch (error) { - console.error('❌ 使用 listServerRefs 获取分支失败:', error); + console.error('❌ 获取分支失败:', error); vscode.window.showErrorMessage(`获取分支失败: ${error}`); } }); @@ -718,7 +585,7 @@ class ConfigPanel { } async cloneBranches(branches) { if (!this.currentRepoForBranches) { - vscode.window.showErrorMessage('请先通过“获取仓库”选择一个仓库'); + vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库'); return; } const url = this.currentRepoForBranches.url; @@ -741,8 +608,8 @@ class ConfigPanel { }); console.log(`📥 开始克隆分支: ${branch}`); try { - const folderNames = this.generateModuleFolderName(url, branch); - await this.addGitModuleFolder(url, repoDisplayName, folderNames.folderName, branch); + const folderNames = GitService_1.GitService.generateModuleFolderName(url, branch); + await this.addGitModuleFolder(url, repoDisplayName, folderNames.folderName, branch, this.currentRepoForBranches?.username, this.currentRepoForBranches?.token); successCount++; console.log(`✅ 分支克隆成功: ${branch}`); } @@ -764,10 +631,7 @@ class ConfigPanel { vscode.window.showErrorMessage(`克隆分支失败: ${error}`); } } - // ============================================= - // 模块文件夹管理方法 - // ============================================= - async addGitModuleFolder(url, displayName, folderName, branch) { + async addGitModuleFolder(url, displayName, folderName, branch, username, token) { try { if (!url || !url.startsWith('http')) { vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL'); @@ -777,18 +641,18 @@ class ConfigPanel { vscode.window.showErrorMessage('请先选择容器'); return; } - const container = this.containers.find(c => c.id === this.currentContainerId); - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!container || !aircraft || !projectPath) { + const projectPath = this.projectService.getProjectPath(this.currentProjectId); + if (!projectPath) { vscode.window.showErrorMessage('未找到相关项目数据'); return; } - const folderId = this.generateUniqueId('git-', this.moduleFolders); - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - const localPath = path.join(projectPath, aircraft.name, container.name, folderName); + // 使用 ProjectService 的统一 ID 生成 + const folderId = this.projectService.generateUniqueId('git-'); + const relativePath = `/${this.currentProjectId}/${this.getAircraftName()}/${this.getContainerName()}/${folderName}`; + const localPath = path.join(projectPath, this.getAircraftName(), this.getContainerName(), folderName); console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`); - const existingFolder = this.moduleFolders.find(folder => folder.localPath === relativePath && folder.containerId === this.currentContainerId); + const existingFolder = this.projectService.getModuleFoldersByContainer(this.currentContainerId) + .find(folder => folder.localPath === relativePath); if (existingFolder) { vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`); return; @@ -809,62 +673,27 @@ class ConfigPanel { }, async (progress) => { progress.report({ increment: 0 }); try { - const parentDir = path.dirname(localPath); - await fs.promises.mkdir(parentDir, { recursive: true }); - let dirExists = false; - try { - await fs.promises.access(localPath); - dirExists = true; - } - catch { - dirExists = false; - } - if (dirExists) { - const dirContents = await fs.promises.readdir(localPath); - if (dirContents.length > 0) { - const confirm = await vscode.window.showWarningMessage(`目标目录 "${folderName}" 不为空,确定要覆盖吗?`, { modal: true }, '确定覆盖', '取消'); - if (confirm !== '确定覆盖') { - vscode.window.showInformationMessage('克隆操作已取消'); - return; - } - for (const item of dirContents) { - const itemPath = path.join(localPath, item); - if (item !== '.git') { - await fs.promises.rm(itemPath, { recursive: true, force: true }); - } - } + // 使用 GitService 克隆仓库 + await GitService_1.GitService.cloneRepository(url, localPath, branch, (event) => { + console.log(`📊 克隆进度: ${event.phase} - ${event.loaded}/${event.total}`); + if (event.total) { + const percent = (event.loaded / event.total) * 100; + progress.report({ + increment: percent, + message: `${event.phase}... (${Math.round(percent)}%)` + }); } - } - console.log(`🚀 开始克隆: ${url} -> ${localPath}, 分支: ${branch}`); - await isomorphic_git_1.default.clone({ - fs: fs, - http: node_1.default, - dir: localPath, - url: url, - singleBranch: true, - depth: 1, - ref: branch || 'main', - onProgress: (event) => { - console.log(`📊 克隆进度: ${event.phase} - ${event.loaded}/${event.total}`); - if (event.total) { - const percent = (event.loaded / event.total) * 100; - progress.report({ - increment: percent, - message: `${event.phase}... (${Math.round(percent)}%)` - }); - } - else { - progress.report({ message: `${event.phase}...` }); - } + else { + progress.report({ message: `${event.phase}...` }); } - }); + }, username, token); console.log('✅ Git克隆成功完成'); - const clonedContents = await fs.promises.readdir(localPath); + const clonedContents = await require('fs').promises.readdir(localPath); console.log(`📁 克隆后的目录内容:`, clonedContents); if (clonedContents.length === 0) { throw new Error('克隆后目录为空,可能克隆失败'); } - this.moduleFolders.push(newFolder); + this.projectService.addModuleFolder(newFolder); await this.saveCurrentProjectData(); console.log('✅ Git模块文件夹数据已保存到项目文件'); vscode.window.showInformationMessage(`Git 仓库克隆成功: ${displayName}`); @@ -878,8 +707,8 @@ class ConfigPanel { catch (error) { console.error('❌ 在克隆过程中捕获错误:', error); try { - if (fs.existsSync(localPath)) { - await fs.promises.rm(localPath, { recursive: true, force: true }); + if (require('fs').existsSync(localPath)) { + await require('fs').promises.rm(localPath, { recursive: true, force: true }); console.log('🧹 已清理克隆失败的目录'); } } @@ -896,21 +725,24 @@ class ConfigPanel { vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`); } } + // ============================================= + // 模块文件夹管理方法 + // ============================================= async loadModuleFolder(folderId) { this.currentModuleFolderId = folderId; - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (folder && folder.type === 'git') { await this.loadModuleFolderFileTree(folderId); } this.updateWebview(); } async syncGitModuleFolder(folderId) { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -922,13 +754,7 @@ class ConfigPanel { }, async (progress) => { try { progress.report({ increment: 0, message: '拉取最新更改...' }); - await isomorphic_git_1.default.pull({ - fs: fs, - http: node_1.default, - dir: fullPath, - author: { name: 'DCSP User', email: 'user@dcsp.local' }, - fastForward: true - }); + await GitService_1.GitService.pullChanges(fullPath); await this.loadModuleFolderFileTree(folderId); vscode.window.showInformationMessage(`Git 仓库同步成功: ${folder.name}`); this.updateWebview(); @@ -939,17 +765,17 @@ class ConfigPanel { }); } async deleteModuleFolder(folderId) { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder) return; const confirm = await vscode.window.showWarningMessage(`确定要删除模块文件夹 "${folder.name}" 吗?这将删除本地文件。`, { modal: true }, '确定删除', '取消'); if (confirm === '确定删除') { try { - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (fullPath) { - await fs.promises.rm(fullPath, { recursive: true, force: true }); + await require('fs').promises.rm(fullPath, { recursive: true, force: true }); } - this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); + this.projectService.deleteModuleFolder(folderId); await this.saveCurrentProjectData(); if (this.currentModuleFolderId === folderId) { this.currentModuleFolderId = ''; @@ -968,36 +794,27 @@ class ConfigPanel { vscode.window.showErrorMessage('请先选择模块文件夹和容器'); return; } - const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); + const folder = this.projectService.getModuleFolder(this.currentModuleFolderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); return; } - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } try { - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹路径'); return; } const fileFullPath = path.join(fullPath, filePath); - const content = await fs.promises.readFile(fileFullPath, 'utf8'); + const content = await require('fs').promises.readFile(fileFullPath, 'utf8'); const fileName = path.basename(filePath); - const newId = this.generateUniqueId('cfg', this.configs); - const newConfig = { - id: newId, - name: fileName, - fileName: fileName, - content: content, - containerId: this.currentContainerId - }; - this.configs.push(newConfig); + const configId = await this.projectService.createConfig(fileName, this.currentContainerId); + const config = this.projectService.getConfig(configId); + if (config) { + config.content = content; + } await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); + vscode.window.showInformationMessage(`文件已导入: ${fileName}`); this.updateWebview(); } catch (error) { @@ -1007,17 +824,13 @@ class ConfigPanel { // ============================================= // 上传功能方法 // ============================================= - /** - * 旧的 Git 模块上传逻辑:直接在当前远程 / 当前分支上 commit + push - * 现在只在“未改名 + 同仓库”的场景下被调用 - */ async uploadGitModuleFolder(folderId, username, password) { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -1029,9 +842,9 @@ class ConfigPanel { }, async (progress) => { try { progress.report({ increment: 0, message: '检查更改...' }); - await this.commitAndPushUsingCommandLine(fullPath); + await GitService_1.GitService.commitAndPush(fullPath); progress.report({ increment: 100, message: '完成' }); - folder.uploaded = true; + this.projectService.updateModuleFolder(folderId, { uploaded: true }); await this.saveCurrentProjectData(); vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); this.updateWebview(); @@ -1042,13 +855,13 @@ class ConfigPanel { } }); } - async uploadLocalModuleFolder(folderId, repoUrl, branchName) { - const folder = this.moduleFolders.find(f => f.id === folderId); + async uploadLocalModuleFolder(folderId, repoUrl, branchName, username, token) { + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'local') { vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -1060,22 +873,24 @@ class ConfigPanel { }, async (progress) => { try { progress.report({ increment: 0, message: '检查目录...' }); - if (!fs.existsSync(fullPath)) { + if (!require('fs').existsSync(fullPath)) { throw new Error('本地文件夹不存在'); } progress.report({ increment: 10, message: '初始化 Git 仓库...' }); - await this.initGitRepository(fullPath, branchName); + await GitService_1.GitService.initRepository(fullPath, branchName); progress.report({ increment: 20, message: '添加远程仓库...' }); - await this.addGitRemote(fullPath, repoUrl); + await GitService_1.GitService.addRemote(fullPath, repoUrl); progress.report({ increment: 40, message: '提交初始文件...' }); - await this.commitInitialFiles(fullPath); + await GitService_1.GitService.commitInitialFiles(fullPath); progress.report({ increment: 60, message: '推送到远程仓库...' }); - await this.pushToRemoteWithForce(fullPath, branchName); + await GitService_1.GitService.pushToRemote(fullPath, branchName); progress.report({ increment: 100, message: '完成' }); - folder.type = 'git'; - folder.uploaded = true; - folder.originalFolderName = branchName; - folder.originalRepoUrl = repoUrl; + this.projectService.updateModuleFolder(folderId, { + type: 'git', + uploaded: true, + originalFolderName: branchName, + originalRepoUrl: repoUrl + }); await this.saveCurrentProjectData(); vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`); this.updateWebview(); @@ -1085,8 +900,8 @@ class ConfigPanel { vscode.window.showErrorMessage(`推送失败: ${error.message || error}`); try { const gitDir = path.join(fullPath, '.git'); - if (fs.existsSync(gitDir)) { - await fs.promises.rm(gitDir, { recursive: true, force: true }); + if (require('fs').existsSync(gitDir)) { + await require('fs').promises.rm(gitDir, { recursive: true, force: true }); } } catch (cleanupError) { @@ -1095,382 +910,131 @@ class ConfigPanel { } }); } - /** - * Git 模块以“当前文件夹名”为分支,推送到任意仓库 URL - * 不修改现有 remote 配置,直接用 URL 形式 push - */ - async pushGitModuleFolderToRepoWithBranch(fullPath, repoUrl, branchName) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('🚀 准备以新分支推送到仓库:', { fullPath, repoUrl, branchName }); - // 先检查是否有未提交修改 - exec('git status --porcelain', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError, statusStdout, statusStderr) => { - if (statusError) { - console.error('❌ 检查 Git 状态失败:', statusError); - reject(new Error(`检查 Git 状态失败: ${statusStderr || statusError.message}`)); - return; - } - const hasChanges = !!statusStdout.trim(); - console.log('📋 有未提交更改?:', hasChanges, ', status =\n', statusStdout); - const commands = []; - // 获取完整的仓库历史 - commands.push('git fetch --unshallow'); - // 切换 / 创建分支 - commands.push(`git checkout -B "${branchName}"`); - // 有变更就先提交 - if (hasChanges) { - commands.push('git add .'); - commands.push(`git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`); - } - // 直接用 URL 形式推送,不依赖 remote 名称 - commands.push(`git push -u "${repoUrl}" "${branchName}" --force`); - console.log('🧰 即将执行命令链:', commands.join(' && ')); - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - if (error) { - console.error('❌ Git 推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ Git 推送到指定仓库/分支成功'); - resolve(); - }); - }); - }); - } // ============================================= - // Git 命令行工具方法 + // 文件树和模块文件夹方法 // ============================================= - async commitAndPushUsingCommandLine(fullPath) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('🚀 使用命令行 Git 提交并推送...'); - console.log(`📁 工作目录: ${fullPath}`); - exec('git status --porcelain', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError, statusStdout, statusStderr) => { - if (statusError) { - console.error('❌ 检查 Git 状态失败:', statusError); - reject(new Error(`检查 Git 状态失败: ${statusStderr || statusError.message}`)); - return; - } - if (!statusStdout.trim()) { - console.log('ℹ️ 没有需要提交的更改'); - reject(new Error('没有需要提交的更改')); - return; - } - console.log('📋 检测到更改:', statusStdout); - const commands = [ - 'git add .', - `git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`, - 'git push' - ]; - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - console.log('📋 Git 命令输出:', stdout); - console.log('📋 Git 命令错误:', stderr); - if (error) { - console.error('❌ Git 提交/推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ Git 提交并推送成功'); - resolve(); - }); - }); - }); - } - async initGitRepository(fullPath, branchName) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('📁 初始化 Git 仓库...'); - exec(`git init && git checkout -b "${branchName}"`, { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - if (error) { - console.error('❌ Git 初始化失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ Git 初始化成功'); - resolve(); - }); - }); - } - async addGitRemote(fullPath, repoUrl) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('📡 添加远程仓库...'); - exec(`git remote add origin "${repoUrl}"`, { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - if (error) { - console.error('❌ 添加远程仓库失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ 远程仓库添加成功'); - resolve(); - }); - }); - } - async commitInitialFiles(fullPath) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('💾 提交初始文件...'); - const commands = [ - 'git add .', - `git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"` - ]; - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - if (error) { - if (stderr.includes('nothing to commit') || stdout.includes('nothing to commit')) { - console.log('ℹ️ 没有需要提交的更改'); - resolve(); - return; - } - console.error('❌ Git 提交失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ 初始文件提交成功'); - resolve(); - }); - }); - } - async pushToRemoteWithForce(fullPath, branchName) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('🚀 强制推送到远程仓库...'); - exec(`git push -u origin "${branchName}" --force`, { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - if (error) { - console.error('❌ Git 推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - console.log('✅ Git 推送成功'); - resolve(); - }); - }); - } - // ============================================= - // 文件系统操作方法 - // ============================================= - async createAircraftDirectory(aircraft) { - try { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建飞行器目录'); - return; - } - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - await vscode.workspace.fs.createDirectory(aircraftDir); - console.log(`✅ 创建飞行器目录: ${aircraftDir.fsPath}`); - } - catch (error) { - console.error(`创建飞行器目录失败: ${error}`); - } - } - async createContainerDirectory(container) { - try { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - console.warn('未找到对应的飞行器,跳过创建容器目录'); - return; - } - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建容器目录'); - return; - } - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - await vscode.workspace.fs.createDirectory(aircraftDir); - await vscode.workspace.fs.createDirectory(containerDir); - console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); - } - catch (error) { - console.error(`创建容器目录失败: ${error}`); - } - } - async ensureContainerDirectoryExists(containerId) { - try { - const container = this.containers.find(c => c.id === containerId); - if (!container) - return; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) - return; - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) - return; - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - await vscode.workspace.fs.createDirectory(aircraftDir); - await vscode.workspace.fs.createDirectory(containerDir); - } - catch (error) { - console.error(`确保容器目录存在失败: ${error}`); - } - } - async createDefaultConfigs(container) { - this.configs.push({ - id: this.generateUniqueId('cfg', this.configs), - name: '配置1', - fileName: 'dockerfile', - content: `# ${container.name} 的 Dockerfile\nFROM ubuntu:20.04\n\n# 设置工作目录\nWORKDIR /app\n\n# 复制文件\nCOPY . .\n\n# 安装依赖\nRUN apt-get update && apt-get install -y \\\n python3 \\\n python3-pip\n\n# 暴露端口\nEXPOSE 8080\n\n# 启动命令\nCMD ["python3", "app.py"]`, - containerId: container.id - }); - this.configs.push({ - id: this.generateUniqueId('cfg', this.configs), - name: '配置2', - fileName: 'docker-compose.yml', - content: `# ${container.name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${container.name.toLowerCase().replace(/\s+/g, '-')}:\n build: .\n container_name: ${container.name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, - containerId: container.id - }); - } - async deleteConfigFileFromDisk(config) { - const container = this.containers.find(c => c.id === config.containerId); - if (!container) + async loadModuleFolderFileTree(folderId) { + if (this.isWebviewDisposed) { + console.log('⚠️ Webview 已被销毁,跳过文件树加载'); return; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) - return; - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) - return; - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); } - } - async deleteConfigInternal(configId) { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder) + return; try { - const config = this.configs.find(c => c.id === configId); - if (!config) - return; - this.configs = this.configs.filter(c => c.id !== configId); - await this.deleteConfigFileFromDisk(config); - console.log(`✅ 内部删除配置: ${config.name}`); + this.panel.webview.postMessage({ + type: 'moduleFolderLoading', + loading: true + }); } catch (error) { - console.error(`删除配置文件失败: ${error}`); + console.log('⚠️ 无法发送加载消息,Webview 可能已被销毁'); + return; } - } - // ============================================= - // 项目数据持久化方法 - // ============================================= - async saveCurrentProjectData() { try { - if (!this.currentProjectId) { - console.warn('未找到当前项目,数据将不会保存'); - return; + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (fullPath) { + const fileTree = await GitService_1.GitService.buildFileTree(fullPath); + this.currentModuleFolderFileTree = fileTree; } - const projectPath = this.projectPaths.get(this.currentProjectId); - if (!projectPath) { - console.warn('未找到项目存储路径,数据将不会保存'); - return; - } - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - const data = { - projects: [this.projects.find(p => p.id === this.currentProjectId)], - aircrafts: this.aircrafts.filter(a => a.projectId === this.currentProjectId), - containers: this.containers.filter(c => { - const aircraft = this.aircrafts.find(a => a.id === c.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }), - configs: this.configs.filter(cfg => { - const container = this.containers.find(c => c.id === cfg.containerId); - if (!container) - return false; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }), - moduleFolders: this.moduleFolders.filter(folder => { - const container = this.containers.find(c => c.id === folder.containerId); - if (!container) - return false; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }) - }; - const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); - await vscode.workspace.fs.writeFile(dataUri, uint8Array); - console.log('✅ 当前项目数据已保存,包含', data.moduleFolders.length, '个模块文件夹'); } catch (error) { - vscode.window.showErrorMessage(`保存项目数据失败: ${error}`); + console.error('加载模块文件夹文件树失败:', error); + this.currentModuleFolderFileTree = []; + } + if (this.isWebviewDisposed) { + console.log('⚠️ Webview 已被销毁,跳过完成通知'); + return; } - } - async loadProjectData(projectPath) { try { - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - try { - await vscode.workspace.fs.stat(dataUri); - } - catch { - vscode.window.showErrorMessage('选择的文件夹中没有找到项目数据文件 (.dcsp-data.json)'); - return false; - } - const fileData = await vscode.workspace.fs.readFile(dataUri); - const dataStr = new TextDecoder().decode(fileData); - const data = JSON.parse(dataStr); - const projectId = data.projects[0]?.id; - if (projectId) { - this.projects = this.projects.filter(p => p.id !== projectId); - this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); - const aircraftIds = this.aircrafts.filter(a => a.projectId === projectId).map(a => a.id); - this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); - const containerIds = this.containers.filter(c => aircraftIds.includes(c.aircraftId)).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - this.projects.push(...data.projects); - this.aircrafts.push(...data.aircrafts); - this.containers.push(...data.containers); - this.configs.push(...data.configs); - this.moduleFolders.push(...data.moduleFolders); - this.currentProjectId = projectId; - this.projectPaths.set(projectId, projectPath); - this.currentView = 'aircrafts'; - } - vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${data.moduleFolders.length} 个模块文件夹`); + this.panel.webview.postMessage({ + type: 'moduleFolderLoading', + loading: false + }); this.updateWebview(); - return true; } catch (error) { - vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); - return false; + console.log('⚠️ 无法发送完成消息,Webview 可能已被销毁'); } } - async checkProjectPathHasData(projectPath) { - try { - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - await vscode.workspace.fs.stat(dataUri); - return true; + async openConfigFileInVSCode(configId) { + const config = this.projectService.getConfig(configId); + if (!config) { + vscode.window.showErrorMessage('未找到配置文件'); + return; } - catch { - return false; + const filePath = this.projectService.getConfigFilePath(configId); + if (!filePath) { + vscode.window.showErrorMessage('未设置项目存储路径'); + return; + } + try { + const fs = require('fs'); + if (!fs.existsSync(filePath)) { + vscode.window.showWarningMessage('配置文件不存在,将创建新文件'); + const dirPath = path.dirname(filePath); + await fs.promises.mkdir(dirPath, { recursive: true }); + await fs.promises.writeFile(filePath, config.content || ''); + } + const document = await vscode.workspace.openTextDocument(filePath); + await vscode.window.showTextDocument(document); + } + catch (error) { + vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); + } + } + async openTheModuleFolder(type, id) { + const folder = this.projectService.getModuleFolder(id); + if (!folder) { + vscode.window.showErrorMessage('未找到指定的模块文件夹'); + return; + } + try { + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath || !require('fs').existsSync(fullPath)) { + vscode.window.showErrorMessage('模块文件夹目录不存在'); + return; + } + const fileUri = await vscode.window.showOpenDialog({ + defaultUri: vscode.Uri.file(fullPath), + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: false, + openLabel: '选择要打开的文件', + title: `在 ${folder.name} 中选择文件` + }); + if (fileUri && fileUri.length > 0) { + const document = await vscode.workspace.openTextDocument(fileUri[0]); + await vscode.window.showTextDocument(document); + vscode.window.showInformationMessage(`已打开文件: ${path.basename(fileUri[0].fsPath)}`); + } + } + catch (error) { + vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`); + } + } + async renameModuleFolder(folderId, newName) { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder) { + vscode.window.showErrorMessage('未找到模块文件夹'); + return; + } + const oldName = folder.localPath.split('/').pop(); + if (!oldName) + return; + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) + return; + const newFullPath = path.join(path.dirname(fullPath), newName); + try { + await require('fs').promises.rename(fullPath, newFullPath); + this.projectService.renameModuleFolder(folderId, newName); + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`已重命名文件夹: ${oldName} → ${newName}`); + this.updateWebview(); + } + catch (error) { + vscode.window.showErrorMessage('重命名失败: ' + error); } } // ============================================= @@ -1535,22 +1099,20 @@ class ConfigPanel { }); if (result && result.length > 0) { const selectedPath = result[0].fsPath; - const hasExistingData = await this.checkProjectPathHasData(selectedPath); + const hasExistingData = await StorageService_1.StorageService.checkProjectPathHasData(selectedPath); if (hasExistingData) { const loadChoice = await vscode.window.showWarningMessage(`在路径 ${selectedPath} 中检测到现有项目数据,是否加载?`, { modal: true }, '是,加载现有数据', '否,创建新项目'); if (loadChoice === '是,加载现有数据') { const success = await this.loadProjectData(selectedPath); if (success) { - this.projectPaths.set(projectId, selectedPath); - this.currentView = 'aircrafts'; - this.currentProjectId = projectId; - this.updateWebview(); - vscode.window.showInformationMessage(`项目数据已从 ${selectedPath} 加载`); + // loadProjectData 里已经设置好了 currentProjectId 和 projectPath return selectedPath; } } + // 如果选择“否,创建新项目”,就往下走,覆盖旧数据 } - this.projectPaths.set(projectId, selectedPath); + // 没有旧数据,或者选择了“创建新项目”,把当前 projectId 绑定到这个路径 + this.projectService.setProjectPath(projectId, selectedPath); vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); await this.saveCurrentProjectData(); return selectedPath; @@ -1572,7 +1134,7 @@ class ConfigPanel { try { const dirUri = vscode.Uri.file(pathInput); await vscode.workspace.fs.createDirectory(dirUri); - this.projectPaths.set(projectId, pathInput); + this.projectService.setProjectPath(projectId, pathInput); vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); await this.saveCurrentProjectData(); return pathInput; @@ -1584,232 +1146,32 @@ class ConfigPanel { } return null; } - // ============================================= - // 文件树和模块文件夹方法 - // ============================================= - async loadModuleFolderFileTree(folderId) { - if (this.isWebviewDisposed) { - console.log('⚠️ Webview 已被销毁,跳过文件树加载'); - return; - } - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) - return; + async loadProjectData(projectPath) { try { - this.panel.webview.postMessage({ - type: 'moduleFolderLoading', - loading: true - }); - } - catch (error) { - console.log('⚠️ 无法发送加载消息,Webview 可能已被销毁'); - return; - } - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (fullPath) { - const fileTree = await this.buildFileTree(fullPath); - this.currentModuleFolderFileTree = fileTree; + const projectId = await this.projectService.loadProjectData(projectPath); + if (projectId) { + this.currentProjectId = projectId; + this.currentView = 'aircrafts'; + vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载`); + this.updateWebview(); + return true; } + return false; } catch (error) { - console.error('加载模块文件夹文件树失败:', error); - this.currentModuleFolderFileTree = []; + vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); + return false; } - if (this.isWebviewDisposed) { - console.log('⚠️ Webview 已被销毁,跳过完成通知'); - return; - } - try { - this.panel.webview.postMessage({ - type: 'moduleFolderLoading', - loading: false - }); - this.updateWebview(); - } - catch (error) { - console.log('⚠️ 无法发送完成消息,Webview 可能已被销毁'); - } - } - async buildFileTree(dir, relativePath = '') { - try { - const files = await fs.promises.readdir(dir); - const tree = []; - for (const file of files) { - if (file.startsWith('.') && file !== '.git') - continue; - if (file === '.dcsp-data.json') - continue; - const filePath = path.join(dir, file); - const stats = await fs.promises.stat(filePath); - const currentRelativePath = path.join(relativePath, file); - if (stats.isDirectory()) { - const children = await this.buildFileTree(filePath, currentRelativePath); - tree.push({ - name: file, - type: 'folder', - path: currentRelativePath, - children: children - }); - } - else { - tree.push({ - name: file, - type: 'file', - path: currentRelativePath - }); - } - } - return tree; - } - catch (error) { - console.error('构建文件树失败:', error); - return []; - } - } - async handleRepoSelectedForGitUpload(folderId, repoName) { - // 兼容:如果前端用的是 repoSelectedForGitUpload 事件,则这里转成统一逻辑 - this.pendingGitUploadFolderId = folderId; - await this.handleRepoSelectedForBranches(repoName); } // ============================================= - // 工具方法 + // 数据持久化 // ============================================= - buildBranchTree(branches) { - const root = []; - branches.forEach(branch => { - const parts = branch.name.split('/'); - let currentLevel = root; - for (let i = 0; i < parts.length; i++) { - const part = parts[i]; - const isLeaf = i === parts.length - 1; - const fullName = parts.slice(0, i + 1).join('/'); - let node = currentLevel.find((n) => n.name === part); - if (!node) { - node = { - name: part, - fullName: fullName, - isLeaf: isLeaf, - children: [], - level: i, - expanded: true - }; - currentLevel.push(node); - } - if (isLeaf) { - node.branch = branch; - } - currentLevel = node.children; - } - }); - return root; - } - generateModuleFolderName(url, branch) { - const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo'; - const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); - return { - displayName: repoName, - folderName: branchSafeName - }; - } - 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); - } - async openConfigFileInVSCode(configId) { - const config = this.configs.find(c => c.id === configId); - if (!config) { - vscode.window.showErrorMessage('未找到配置文件'); + async saveCurrentProjectData() { + if (!this.currentProjectId) { + console.warn('未找到当前项目,数据将不会保存'); return; } - const container = this.containers.find(c => c.id === config.containerId); - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!container || !aircraft || !projectPath) { - vscode.window.showErrorMessage('未设置项目存储路径'); - return; - } - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - try { - if (!fs.existsSync(filePath)) { - vscode.window.showWarningMessage('配置文件不存在,将创建新文件'); - const dirPath = path.dirname(filePath); - await fs.promises.mkdir(dirPath, { recursive: true }); - await fs.promises.writeFile(filePath, config.content || ''); - } - const document = await vscode.workspace.openTextDocument(filePath); - await vscode.window.showTextDocument(document); - } - catch (error) { - vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); - } - } - async openTheModuleFolder(type, id) { - const folder = this.moduleFolders.find(f => f.id === id); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹目录不存在'); - return; - } - const fileUri = await vscode.window.showOpenDialog({ - defaultUri: vscode.Uri.file(fullPath), - canSelectFiles: true, - canSelectFolders: false, - canSelectMany: false, - openLabel: '选择要打开的文件', - title: `在 ${folder.name} 中选择文件` - }); - if (fileUri && fileUri.length > 0) { - const document = await vscode.workspace.openTextDocument(fileUri[0]); - await vscode.window.showTextDocument(document); - vscode.window.showInformationMessage(`已打开文件: ${path.basename(fileUri[0].fsPath)}`); - } - } - catch (error) { - vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`); - } - } - async renameModuleFolder(folderId, newName) { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到模块文件夹'); - return; - } - const oldName = folder.localPath.split('/').pop(); - if (!oldName) - return; - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) - return; - const newFullPath = path.join(path.dirname(fullPath), newName); - try { - await fs.promises.rename(fullPath, newFullPath); - // 更新 localPath(注意:originalFolderName 不更新,用于判断“是否改名过”) - folder.localPath = folder.localPath.replace(/\/[^/]+$/, '/' + newName); - await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`已重命名文件夹: ${oldName} → ${newName}`); - this.updateWebview(); - } - catch (error) { - vscode.window.showErrorMessage('重命名失败: ' + error); - } + await this.projectService.saveCurrentProjectData(this.currentProjectId); } // ============================================= // Webview 更新方法 @@ -1826,37 +1188,34 @@ class ConfigPanel { console.error('更新 Webview 失败:', error); } } - async openRepoSelectForGitUpload(folderId) { - console.log('📌 Git 上传:收到 openRepoSelectForGitUpload,folderId =', folderId); - this.pendingGitUploadFolderId = folderId; - await this.openRepoSelect(); - } getWebviewContent() { switch (this.currentView) { case 'projects': return this.projectView.render({ - projects: this.projects, - projectPaths: this.projectPaths + projects: this.projectService.getProjects(), + projectPaths: this.projectService.getProjectPaths() }); case 'aircrafts': - const projectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); + const projectAircrafts = this.projectService.getAircraftsByProject(this.currentProjectId); return this.aircraftView.render({ aircrafts: projectAircrafts }); case 'containers': - const currentProject = this.projects.find(p => p.id === this.currentProjectId); - const currentAircraft = this.aircrafts.find(a => a.id === this.currentAircraftId); - const projectContainers = this.containers.filter(c => c.aircraftId === this.currentAircraftId); + const project = this.projectService.getProjects().find(p => p.id === this.currentProjectId); + const currentAircraft = this.projectService.getAircraftsByProject(this.currentProjectId) + .find(a => a.id === this.currentAircraftId); + const projectContainers = this.projectService.getContainersByAircraft(this.currentAircraftId); return this.containerView.render({ - project: currentProject, + project: project, aircraft: currentAircraft, containers: projectContainers }); case 'configs': - const currentContainer = this.containers.find(c => c.id === this.currentContainerId); - const currentModuleFolder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - const containerConfigs = this.configs.filter(cfg => cfg.containerId === this.currentContainerId); - const containerModuleFolders = this.moduleFolders.filter(folder => folder.containerId === this.currentContainerId); + const currentContainer = this.projectService.getContainersByAircraft(this.currentAircraftId) + .find(c => c.id === this.currentContainerId); + const currentModuleFolder = this.projectService.getModuleFolder(this.currentModuleFolderId); + const containerConfigs = this.projectService.getConfigsByContainer(this.currentContainerId); + const containerModuleFolders = this.projectService.getModuleFoldersByContainer(this.currentContainerId); return this.configView.render({ container: currentContainer, configs: containerConfigs, @@ -1867,8 +1226,8 @@ class ConfigPanel { }); default: return this.projectView.render({ - projects: this.projects, - projectPaths: this.projectPaths + projects: this.projectService.getProjects(), + projectPaths: this.projectService.getProjectPaths() }); } } diff --git a/out/panels/ConfigPanel.js.map b/out/panels/ConfigPanel.js.map index 3cf4623..4b4b6ef 100644 --- a/out/panels/ConfigPanel.js.map +++ b/out/panels/ConfigPanel.js.map @@ -1 +1 @@ -{"version":3,"file":"ConfigPanel.js","sourceRoot":"","sources":["../../src/panels/ConfigPanel.ts"],"names":[],"mappings":"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"} \ No newline at end of file +{"version":3,"file":"ConfigPanel.js","sourceRoot":"","sources":["../../src/panels/ConfigPanel.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/out/panels/services/GitService.js b/out/panels/services/GitService.js new file mode 100644 index 0000000..315c662 --- /dev/null +++ b/out/panels/services/GitService.js @@ -0,0 +1,292 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.GitService = void 0; +const fs = __importStar(require("fs")); +const isomorphic_git_1 = __importDefault(require("isomorphic-git")); +const node_1 = __importDefault(require("isomorphic-git/http/node")); +const path = __importStar(require("path")); +const child_process_1 = require("child_process"); +const util_1 = require("util"); +const execAsync = (0, util_1.promisify)(child_process_1.exec); +/** + * Git操作服务 + */ +class GitService { + /** + * 获取远程分支列表 + */ + static async fetchBranches(url, username, token) { + try { + const options = { + http: node_1.default, + url: url + }; + if (username || token) { + options.onAuth = () => ({ + username: username || '', + password: token || '' + }); + } + const refs = await isomorphic_git_1.default.listServerRefs(options); + const branchRefs = refs.filter((ref) => ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/')); + const branches = branchRefs.map((ref) => { + let branchName; + if (ref.ref.startsWith('refs/remotes/')) { + branchName = ref.ref.replace('refs/remotes/origin/', ''); + } + else { + branchName = ref.ref.replace('refs/heads/', ''); + } + return { + name: branchName, + isCurrent: branchName === 'main' || branchName === 'master', + selected: false + }; + }); + return branches; + } + catch (error) { + console.error('获取分支失败:', error); + throw error; + } + } + /** + * 克隆仓库 + */ + static async cloneRepository(url, localPath, branch = 'main', onProgress, username, token) { + const parentDir = path.dirname(localPath); + await fs.promises.mkdir(parentDir, { recursive: true }); + // 检查目录是否已存在且非空(不变) + let dirExists = false; + try { + await fs.promises.access(localPath); + dirExists = true; + } + catch { + dirExists = false; + } + if (dirExists) { + const dirContents = await fs.promises.readdir(localPath); + if (dirContents.length > 0 && dirContents.some(item => item !== '.git')) { + throw new Error('目标目录不为空,请清空目录或选择其他路径'); + } + } + const options = { + fs, + http: node_1.default, + dir: localPath, + url, + singleBranch: true, + depth: 1, + ref: branch, + onProgress + }; + if (username || token) { + options.onAuth = () => ({ + username: username || '', + password: token || '' + }); + } + await isomorphic_git_1.default.clone(options); + } + /** + * 拉取最新更改 + */ + static async pullChanges(localPath) { + await isomorphic_git_1.default.pull({ + fs: fs, + http: node_1.default, + dir: localPath, + author: { name: 'DCSP User', email: 'user@dcsp.local' }, + fastForward: true + }); + } + /** + * 构建分支树结构 + */ + static buildBranchTree(branches) { + const root = []; + branches.forEach(branch => { + const parts = branch.name.split('/'); + let currentLevel = root; + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + const isLeaf = i === parts.length - 1; + const fullName = parts.slice(0, i + 1).join('/'); + let node = currentLevel.find((n) => n.name === part); + if (!node) { + node = { + name: part, + fullName: fullName, + isLeaf: isLeaf, + children: [], + level: i, + expanded: true + }; + currentLevel.push(node); + } + if (isLeaf) { + node.branch = branch; + } + currentLevel = node.children; + } + }); + return root; + } + /** + * 初始化Git仓库 + */ + static async initRepository(localPath, branchName) { + await execAsync(`git init && git checkout -b "${branchName}"`, { cwd: localPath }); + } + /** + * 添加远程仓库 + */ + static async addRemote(localPath, repoUrl, username, token) { + let finalUrl = repoUrl; + if (username && token) { + const u = encodeURIComponent(username); + const t = encodeURIComponent(token); + finalUrl = repoUrl.replace('://', `://${u}:${t}@`); + } + await execAsync(`git remote add origin "${finalUrl}"`, { cwd: localPath }); + } + /** + * 提交初始文件 + */ + static async commitInitialFiles(localPath) { + try { + await execAsync('git add .', { cwd: localPath }); + await execAsync(`git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"`, { cwd: localPath }); + } + catch (error) { + if (error.stderr?.includes('nothing to commit')) { + console.log('没有需要提交的更改'); + } + else { + throw error; + } + } + } + /** + * 推送到远程仓库 + */ + static async pushToRemote(localPath, branchName) { + await execAsync(`git push -u origin "${branchName}" --force`, { cwd: localPath }); + } + /** + * 使用Git命令提交并推送 + */ + static async commitAndPush(localPath) { + await execAsync('git add .', { cwd: localPath }); + await execAsync(`git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`, { cwd: localPath }); + await execAsync('git push', { cwd: localPath }); + } + /** + * 检查是否有未提交的更改 + */ + static async hasUncommittedChanges(localPath) { + try { + const { stdout } = await execAsync('git status --porcelain', { cwd: localPath }); + return !!stdout.trim(); + } + catch { + return false; + } + } + /** + * 推送到指定仓库URL + */ + static async pushToRepoUrl(localPath, repoUrl, branchName, username, token) { + let finalUrl = repoUrl; + if (username && token) { + const u = encodeURIComponent(username); + const t = encodeURIComponent(token); + finalUrl = repoUrl.replace('://', `://${u}:${t}@`); + } + const commands = [ + 'git fetch --unshallow || true', + `git checkout -B "${branchName}"`, + `git push -u "${finalUrl}" "${branchName}" --force` + ]; + await execAsync(commands.join(' && '), { cwd: localPath }); + } + /** + * 生成模块文件夹名称 + */ + static generateModuleFolderName(url, branch) { + const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo'; + const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); + return { + displayName: repoName, + folderName: branchSafeName + }; + } + /** + * 构建文件树 + */ + static async buildFileTree(dir, relativePath = '') { + try { + const files = await fs.promises.readdir(dir); + const tree = []; + for (const file of files) { + if (file.startsWith('.') && file !== '.git') + continue; + if (file === '.dcsp-data.json') + continue; + const filePath = path.join(dir, file); + const stats = await fs.promises.stat(filePath); + const currentRelativePath = path.join(relativePath, file); + if (stats.isDirectory()) { + const children = await GitService.buildFileTree(filePath, currentRelativePath); + tree.push({ + name: file, + type: 'folder', + path: currentRelativePath, + children: children + }); + } + else { + tree.push({ + name: file, + type: 'file', + path: currentRelativePath + }); + } + } + return tree; + } + catch (error) { + console.error('构建文件树失败:', error); + return []; + } + } +} +exports.GitService = GitService; +//# sourceMappingURL=GitService.js.map \ No newline at end of file diff --git a/out/panels/services/GitService.js.map b/out/panels/services/GitService.js.map new file mode 100644 index 0000000..a28dbdc --- /dev/null +++ b/out/panels/services/GitService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"GitService.js","sourceRoot":"","sources":["../../../src/panels/services/GitService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,uCAAyB;AACzB,oEAAiC;AACjC,oEAA4C;AAC5C,2CAA6B;AAC7B,iDAAqC;AACrC,+BAAiC;AAGjC,MAAM,SAAS,GAAG,IAAA,gBAAS,EAAC,oBAAI,CAAC,CAAC;AAElC;;GAEG;AACH,MAAa,UAAU;IACnB;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,CACtB,GAAW,EACX,QAAiB,EACjB,KAAc;QAEd,IAAI;YACA,MAAM,OAAO,GAAQ;gBACjB,IAAI,EAAE,cAAI;gBACV,GAAG,EAAE,GAAG;aACX,CAAC;YAEF,IAAI,QAAQ,IAAI,KAAK,EAAE;gBACnB,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;oBACpB,QAAQ,EAAE,QAAQ,IAAI,EAAE;oBACxB,QAAQ,EAAE,KAAK,IAAI,EAAE;iBACxB,CAAC,CAAC;aACN;YAED,MAAM,IAAI,GAAG,MAAM,wBAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;YAE/C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAQ,EAAE,EAAE,CACxC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAClF,CAAC;YAEF,MAAM,QAAQ,GAAgB,UAAU,CAAC,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE;gBACtD,IAAI,UAAkB,CAAC;gBAEvB,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;oBACrC,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;iBAC5D;qBAAM;oBACH,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;iBACnD;gBAED,OAAO;oBACH,IAAI,EAAE,UAAU;oBAChB,SAAS,EAAE,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,QAAQ;oBAC3D,QAAQ,EAAE,KAAK;iBAClB,CAAC;YACN,CAAC,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC;SACnB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAChC,MAAM,KAAK,CAAC;SACf;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,eAAe,CACxB,GAAW,EACX,SAAiB,EACjB,SAAiB,MAAM,EACvB,UAAiC,EACjC,QAAiB,EACjB,KAAc;QAEd,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAExD,mBAAmB;QACnB,IAAI,SAAS,GAAG,KAAK,CAAC;QACtB,IAAI;YACA,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YACpC,SAAS,GAAG,IAAI,CAAC;SACpB;QAAC,MAAM;YACJ,SAAS,GAAG,KAAK,CAAC;SACrB;QAED,IAAI,SAAS,EAAE;YACX,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;YACzD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE;gBACrE,MAAM,IAAI,KAAK,CAAC,sBAAsB,CAAC,CAAC;aAC3C;SACJ;QAED,MAAM,OAAO,GAAQ;YACjB,EAAE;YACF,IAAI,EAAJ,cAAI;YACJ,GAAG,EAAE,SAAS;YACd,GAAG;YACH,YAAY,EAAE,IAAI;YAClB,KAAK,EAAE,CAAC;YACR,GAAG,EAAE,MAAM;YACX,UAAU;SACb,CAAC;QAEF,IAAI,QAAQ,IAAI,KAAK,EAAE;YACnB,OAAO,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC;gBACpB,QAAQ,EAAE,QAAQ,IAAI,EAAE;gBACxB,QAAQ,EAAE,KAAK,IAAI,EAAE;aACxB,CAAC,CAAC;SACN;QAED,MAAM,wBAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,SAAiB;QACtC,MAAM,wBAAG,CAAC,IAAI,CAAC;YACX,EAAE,EAAE,EAAE;YACN,IAAI,EAAE,cAAI;YACV,GAAG,EAAE,SAAS;YACd,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,iBAAiB,EAAE;YACvD,WAAW,EAAE,IAAI;SACpB,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,eAAe,CAAC,QAAqB;QACxC,MAAM,IAAI,GAAU,EAAE,CAAC;QAEvB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACtB,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACrC,IAAI,YAAY,GAAG,IAAI,CAAC;YAExB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBACnC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,MAAM,GAAG,CAAC,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;gBACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAEjD,IAAI,IAAI,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;gBAE1D,IAAI,CAAC,IAAI,EAAE;oBACP,IAAI,GAAG;wBACH,IAAI,EAAE,IAAI;wBACV,QAAQ,EAAE,QAAQ;wBAClB,MAAM,EAAE,MAAM;wBACd,QAAQ,EAAE,EAAE;wBACZ,KAAK,EAAE,CAAC;wBACR,QAAQ,EAAE,IAAI;qBACjB,CAAC;oBACF,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;iBAC3B;gBAED,IAAI,MAAM,EAAE;oBACR,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;iBACxB;gBAED,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC;aAChC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC;IAChB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,SAAiB,EAAE,UAAkB;QAC7D,MAAM,SAAS,CAAC,gCAAgC,UAAU,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACvF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,SAAS,CAClB,SAAiB,EACjB,OAAe,EACf,QAAiB,EACjB,KAAc;QAEd,IAAI,QAAQ,GAAG,OAAO,CAAC;QAEvB,IAAI,QAAQ,IAAI,KAAK,EAAE;YACnB,MAAM,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACpC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACtD;QAED,MAAM,SAAS,CAAC,0BAA0B,QAAQ,GAAG,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,kBAAkB,CAAC,SAAiB;QAC7C,IAAI;YACA,MAAM,SAAS,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;YACjD,MAAM,SAAS,CACX,6CAA6C,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,GAAG,EAC3E,EAAE,GAAG,EAAE,SAAS,EAAE,CACrB,CAAC;SACL;QAAC,OAAO,KAAU,EAAE;YACjB,IAAI,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,mBAAmB,CAAC,EAAE;gBAC7C,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;aAC5B;iBAAM;gBACH,MAAM,KAAK,CAAC;aACf;SACJ;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,SAAiB,EAAE,UAAkB;QAC3D,MAAM,SAAS,CAAC,uBAAuB,UAAU,WAAW,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACtF,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,SAAiB;QACxC,MAAM,SAAS,CAAC,WAAW,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;QACjD,MAAM,SAAS,CACX,0CAA0C,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,GAAG,EACxE,EAAE,GAAG,EAAE,SAAS,EAAE,CACrB,CAAC;QACF,MAAM,SAAS,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QAChD,IAAI;YACA,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;YACjF,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;SAC1B;QAAC,MAAM;YACJ,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,CACtB,SAAiB,EACjB,OAAe,EACf,UAAkB,EAClB,QAAiB,EACjB,KAAc;QAEd,IAAI,QAAQ,GAAG,OAAO,CAAC;QAEvB,IAAI,QAAQ,IAAI,KAAK,EAAE;YACnB,MAAM,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;YACvC,MAAM,CAAC,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;YACpC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;SACtD;QAED,MAAM,QAAQ,GAAG;YACb,+BAA+B;YAC/B,oBAAoB,UAAU,GAAG;YACjC,gBAAgB,QAAQ,MAAM,UAAU,WAAW;SACtD,CAAC;QAEF,MAAM,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,wBAAwB,CAAC,GAAW,EAAE,MAAc;QACvD,MAAM,QAAQ,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,IAAI,cAAc,CAAC;QAC7E,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,CAAC;QAE9D,OAAO;YACH,WAAW,EAAE,QAAQ;YACrB,UAAU,EAAE,cAAc;SAC7B,CAAC;IACN,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,eAAuB,EAAE;QAC7D,IAAI;YACA,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,IAAI,GAAkB,EAAE,CAAC;YAE/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACtB,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,MAAM;oBAAE,SAAS;gBACtD,IAAI,IAAI,KAAK,iBAAiB;oBAAE,SAAS;gBAEzC,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;gBACtC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBAC/C,MAAM,mBAAmB,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;gBAE1D,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE;oBACrB,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;oBAC/E,IAAI,CAAC,IAAI,CAAC;wBACN,IAAI,EAAE,IAAI;wBACV,IAAI,EAAE,QAAQ;wBACd,IAAI,EAAE,mBAAmB;wBACzB,QAAQ,EAAE,QAAQ;qBACrB,CAAC,CAAC;iBACN;qBAAM;oBACH,IAAI,CAAC,IAAI,CAAC;wBACN,IAAI,EAAE,IAAI;wBACV,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,mBAAmB;qBAC5B,CAAC,CAAC;iBACN;aACJ;YAED,OAAO,IAAI,CAAC;SACf;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YACjC,OAAO,EAAE,CAAC;SACb;IACL,CAAC;CACJ;AAvTD,gCAuTC"} \ No newline at end of file diff --git a/out/panels/services/ProjectService.js b/out/panels/services/ProjectService.js new file mode 100644 index 0000000..1436ab3 --- /dev/null +++ b/out/panels/services/ProjectService.js @@ -0,0 +1,441 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +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")); +const StorageService_1 = require("./StorageService"); +/** + * 项目数据管理服务 + */ +class ProjectService { + constructor() { + this.projects = []; + this.aircrafts = []; + this.containers = []; + this.configs = []; + this.moduleFolders = []; + this.projectPaths = new Map(); + } + /** + * 生成唯一ID + */ + generateUniqueId(prefix, _existingItems = []) { + const randomPart = `${Date.now().toString(36)}${Math.random().toString(36).substring(2, 8)}`; + return `${prefix}${randomPart}`; + } + // =============== 项目相关方法 =============== + getProjects() { + return this.projects; + } + getProjectPaths() { + return this.projectPaths; + } + getProjectPath(projectId) { + return this.projectPaths.get(projectId); + } + setProjectPath(projectId, path) { + this.projectPaths.set(projectId, path); + } + async createProject(name) { + const newId = this.generateUniqueId('p', this.projects); + const newProject = { + id: newId, + name: name + }; + this.projects.push(newProject); + return newId; + } + updateProjectName(projectId, newName) { + const project = this.projects.find(p => p.id === projectId); + if (project) { + project.name = newName; + return true; + } + return false; + } + deleteProject(projectId) { + const project = this.projects.find(p => p.id === projectId); + if (!project) + return false; + // 先把要删的 id 都算出来,再统一过滤 + const relatedAircrafts = this.aircrafts.filter(a => a.projectId === projectId); + const aircraftIds = relatedAircrafts.map(a => a.id); + const relatedContainers = this.containers.filter(c => aircraftIds.includes(c.aircraftId)); + const containerIds = relatedContainers.map(c => c.id); + // 真正删除数据 + this.projects = this.projects.filter(p => p.id !== projectId); + this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); + this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + this.projectPaths.delete(projectId); + return true; + } + // =============== 飞行器相关方法 =============== + getAircraftsByProject(projectId) { + return this.aircrafts.filter(a => a.projectId === projectId); + } + async createAircraft(name, projectId) { + const newId = this.generateUniqueId('a', this.aircrafts); + const newAircraft = { + id: newId, + name: name, + projectId: projectId + }; + this.aircrafts.push(newAircraft); + // 创建飞行器目录 + await this.createAircraftDirectory(newAircraft); + return newId; + } + updateAircraftName(aircraftId, newName) { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (aircraft) { + aircraft.name = newName; + return true; + } + return false; + } + deleteAircraft(aircraftId) { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (!aircraft) + return false; + // ⚠️ 修正点:先在删除 containers 之前,算出要删的 containerIds + const relatedContainers = this.containers.filter(c => c.aircraftId === aircraftId); + const containerIds = relatedContainers.map(c => c.id); + // 删除飞机自身和容器 + this.aircrafts = this.aircrafts.filter(a => a.id !== aircraftId); + this.containers = this.containers.filter(c => c.aircraftId !== aircraftId); + // 再删关联的 config 和 moduleFolder + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + return true; + } + // =============== 容器相关方法 =============== + getContainersByAircraft(aircraftId) { + return this.containers.filter(c => c.aircraftId === aircraftId); + } + async createContainer(name, aircraftId) { + const newId = this.generateUniqueId('c', this.containers); + const newContainer = { + id: newId, + name: name, + aircraftId: aircraftId + }; + this.containers.push(newContainer); + await this.createContainerDirectory(newContainer); + await this.createDefaultConfigs(newContainer); + return newId; + } + updateContainerName(containerId, newName) { + const container = this.containers.find(c => c.id === containerId); + if (container) { + container.name = newName; + return true; + } + return false; + } + deleteContainer(containerId) { + const container = this.containers.find(c => c.id === containerId); + if (!container) + return false; + this.containers = this.containers.filter(c => c.id !== containerId); + this.configs = this.configs.filter(cfg => cfg.containerId !== containerId); + this.moduleFolders = this.moduleFolders.filter(folder => folder.containerId !== containerId); + return true; + } + // =============== 配置相关方法 =============== + getConfigsByContainer(containerId) { + return this.configs.filter(cfg => cfg.containerId === containerId); + } + getConfig(configId) { + return this.configs.find(c => c.id === configId); + } + async createConfig(name, containerId) { + const newId = this.generateUniqueId('cfg', this.configs); + const newConfig = { + id: newId, + name: name, + fileName: name.toLowerCase().replace(/\s+/g, '_'), + content: `# ${name} 配置文件\n# 创建时间: ${new Date().toLocaleString()}\n# 您可以在此编辑配置内容\n\n`, + containerId: containerId + }; + this.configs.push(newConfig); + await this.ensureContainerDirectoryExists(containerId); + return newId; + } + updateConfigName(configId, newName) { + const config = this.configs.find(c => c.id === configId); + if (config) { + config.name = newName; + return true; + } + return false; + } + deleteConfig(configId) { + const config = this.configs.find(c => c.id === configId); + if (!config) + return false; + this.configs = this.configs.filter(c => c.id !== configId); + return true; + } + // =============== 模块文件夹相关方法 =============== + getModuleFoldersByContainer(containerId) { + return this.moduleFolders.filter(folder => folder.containerId === containerId); + } + getModuleFolder(folderId) { + return this.moduleFolders.find(f => f.id === folderId); + } + addModuleFolder(folder) { + this.moduleFolders.push(folder); + } + updateModuleFolder(folderId, updates) { + const folderIndex = this.moduleFolders.findIndex(f => f.id === folderId); + if (folderIndex === -1) + return false; + this.moduleFolders[folderIndex] = { + ...this.moduleFolders[folderIndex], + ...updates + }; + return true; + } + deleteModuleFolder(folderId) { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder) + return false; + this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); + return true; + } + renameModuleFolder(folderId, newName) { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder) + return false; + const oldName = folder.localPath.split('/').pop() || ''; + folder.localPath = folder.localPath.replace(/\/[^/]+$/, '/' + newName); + return true; + } + // =============== 文件系统操作 =============== + async createAircraftDirectory(aircraft) { + try { + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) { + console.warn('未找到项目路径,跳过创建飞行器目录'); + return; + } + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + await vscode.workspace.fs.createDirectory(aircraftDir); + console.log(`✅ 创建飞行器目录: ${aircraftDir.fsPath}`); + } + catch (error) { + console.error(`创建飞行器目录失败: ${error}`); + } + } + async createContainerDirectory(container) { + try { + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + if (!aircraft) { + console.warn('未找到对应的飞行器,跳过创建容器目录'); + return; + } + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) { + console.warn('未找到项目路径,跳过创建容器目录'); + return; + } + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); + await vscode.workspace.fs.createDirectory(aircraftDir); + await vscode.workspace.fs.createDirectory(containerDir); + console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); + } + catch (error) { + console.error(`创建容器目录失败: ${error}`); + } + } + async ensureContainerDirectoryExists(containerId) { + try { + const container = this.containers.find(c => c.id === containerId); + if (!container) + return; + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + if (!aircraft) + return; + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) + return; + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); + await vscode.workspace.fs.createDirectory(aircraftDir); + await vscode.workspace.fs.createDirectory(containerDir); + } + catch (error) { + console.error(`确保容器目录存在失败: ${error}`); + } + } + async createDefaultConfigs(container) { + this.configs.push({ + id: this.generateUniqueId('cfg', this.configs), + name: '配置1', + fileName: 'dockerfile', + content: `# ${container.name} 的 Dockerfile\nFROM ubuntu:20.04\n\n# 设置工作目录\nWORKDIR /app\n\n# 复制文件\nCOPY . .\n\n# 安装依赖\nRUN apt-get update && apt-get install -y \\\n python3 \\\n python3-pip\n\n# 暴露端口\nEXPOSE 8080\n\n# 启动命令\nCMD ["python3", "app.py"]`, + containerId: container.id + }); + this.configs.push({ + id: this.generateUniqueId('cfg', this.configs), + name: '配置2', + fileName: 'docker-compose.yml', + content: `# ${container.name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${container.name.toLowerCase().replace(/\s+/g, '-')}:\n build: .\n container_name: ${container.name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, + containerId: container.id + }); + } + // =============== 数据持久化 =============== + async saveCurrentProjectData(projectId) { + try { + const projectPath = this.projectPaths.get(projectId); + if (!projectPath) { + console.warn('未找到项目存储路径,数据将不会保存'); + return false; + } + const data = this.getProjectData(projectId); + return await StorageService_1.StorageService.saveProjectData(projectPath, data); + } + catch (error) { + console.error('保存项目数据失败:', error); + return false; + } + } + async loadProjectData(projectPath) { + try { + const data = await StorageService_1.StorageService.loadProjectData(projectPath); + if (!data) { + return null; + } + const projectId = data.projects[0]?.id; + if (!projectId) { + return null; + } + // 先根据旧的 projectId 算出要清理的 aircraft / container / config / moduleFolder + const existingAircrafts = this.aircrafts.filter(a => a.projectId === projectId); + const aircraftIds = existingAircrafts.map(a => a.id); + const existingContainers = this.containers.filter(c => aircraftIds.includes(c.aircraftId)); + const containerIds = existingContainers.map(c => c.id); + // 清理旧数据(同一个 projectId 的) + this.projects = this.projects.filter(p => p.id !== projectId); + this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); + this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + // 加载新数据 + this.projects.push(...data.projects); + this.aircrafts.push(...data.aircrafts); + this.containers.push(...data.containers); + this.configs.push(...data.configs); + this.moduleFolders.push(...data.moduleFolders); + this.projectPaths.set(projectId, projectPath); + return projectId; + } + catch (error) { + console.error('加载项目数据失败:', error); + return null; + } + } + getProjectData(projectId) { + return { + projects: [this.projects.find(p => p.id === projectId)], + aircrafts: this.aircrafts.filter(a => a.projectId === projectId), + containers: this.containers.filter(c => { + const aircraft = this.aircrafts.find(a => a.id === c.aircraftId); + return aircraft && aircraft.projectId === projectId; + }), + configs: this.configs.filter(cfg => { + const container = this.containers.find(c => c.id === cfg.containerId); + if (!container) + return false; + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + return aircraft && aircraft.projectId === projectId; + }), + moduleFolders: this.moduleFolders.filter(folder => { + const container = this.containers.find(c => c.id === folder.containerId); + if (!container) + return false; + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + return aircraft && aircraft.projectId === projectId; + }) + }; + } + // =============== 工具方法 =============== + 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); + } + getConfigFilePath(configId) { + const config = this.configs.find(c => c.id === configId); + if (!config) + return null; + const container = this.containers.find(c => c.id === config.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; + return path.join(projectPath, aircraft.name, container.name, config.fileName); + } + async deleteConfigFileFromDisk(configId) { + const filePath = this.getConfigFilePath(configId); + if (!filePath) + return false; + try { + if (fs.existsSync(filePath)) { + await fs.promises.unlink(filePath); + console.log(`✅ 已删除配置文件: ${filePath}`); + return true; + } + return false; + } + catch (error) { + console.error(`删除配置文件失败: ${error}`); + return false; + } + } +} +exports.ProjectService = ProjectService; +//# sourceMappingURL=ProjectService.js.map \ No newline at end of file diff --git a/out/panels/services/ProjectService.js.map b/out/panels/services/ProjectService.js.map new file mode 100644 index 0000000..799b5ff --- /dev/null +++ b/out/panels/services/ProjectService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ProjectService.js","sourceRoot":"","sources":["../../../src/panels/services/ProjectService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/out/panels/services/StorageService.js b/out/panels/services/StorageService.js new file mode 100644 index 0000000..7ddd033 --- /dev/null +++ b/out/panels/services/StorageService.js @@ -0,0 +1,152 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { enumerable: true, get: function() { return m[k]; } }; + } + Object.defineProperty(o, k2, desc); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.StorageService = void 0; +// src/panels/services/StorageService.ts +const vscode = __importStar(require("vscode")); +const fs = __importStar(require("fs")); +const path = __importStar(require("path")); +/** + * 数据存储服务 + * 负责项目的持久化存储和加载 + */ +class StorageService { + /** + * 加载项目数据 + */ + static async loadProjectData(projectPath) { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + try { + await vscode.workspace.fs.stat(dataUri); + } + catch { + console.warn('未找到项目数据文件'); + return null; + } + const fileData = await vscode.workspace.fs.readFile(dataUri); + const dataStr = new TextDecoder().decode(fileData); + const data = JSON.parse(dataStr); + return data; + } + catch (error) { + console.error('加载项目数据失败:', error); + return null; + } + } + /** + * 保存项目数据 + */ + static async saveProjectData(projectPath, data) { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); + await vscode.workspace.fs.writeFile(dataUri, uint8Array); + console.log('✅ 项目数据已保存'); + return true; + } + catch (error) { + console.error('保存项目数据失败:', error); + return false; + } + } + /** + * 检查项目路径是否有数据 + */ + static async checkProjectPathHasData(projectPath) { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + await vscode.workspace.fs.stat(dataUri); + return true; + } + catch { + return false; + } + } + /** + * 加载仓库配置 + */ + static async loadRepoConfigs(extensionUri) { + try { + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + if (!fs.existsSync(configPath)) { + return []; + } + const content = await fs.promises.readFile(configPath, 'utf8'); + if (!content.trim()) { + return []; + } + const parsed = JSON.parse(content); + if (Array.isArray(parsed)) { + return parsed; + } + else if (parsed && Array.isArray(parsed.repos)) { + return parsed.repos; + } + else { + return []; + } + } + catch (error) { + console.error('加载仓库配置失败:', error); + return []; + } + } + /** + * 确保仓库配置文件存在 + */ + static async ensureRepoConfigFileExists(extensionUri) { + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + if (!fs.existsSync(configPath)) { + const defaultContent = JSON.stringify({ + repos: [ + { + name: 'example-repo', + url: 'https://github.com/username/repo.git', + username: '', + token: '' + } + ] + }, null, 2); + await fs.promises.writeFile(configPath, defaultContent, 'utf8'); + } + } + /** + * 打开仓库配置文件 + */ + static async openRepoConfig(extensionUri) { + try { + await StorageService.ensureRepoConfigFileExists(extensionUri); + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(configPath)); + await vscode.window.showTextDocument(doc); + } + catch (error) { + vscode.window.showErrorMessage(`打开仓库配置文件失败: ${error}`); + } + } +} +exports.StorageService = StorageService; +//# sourceMappingURL=StorageService.js.map \ No newline at end of file diff --git a/out/panels/services/StorageService.js.map b/out/panels/services/StorageService.js.map new file mode 100644 index 0000000..590a3ed --- /dev/null +++ b/out/panels/services/StorageService.js.map @@ -0,0 +1 @@ +{"version":3,"file":"StorageService.js","sourceRoot":"","sources":["../../../src/panels/services/StorageService.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/out/panels/views/AircraftView.js b/out/panels/views/AircraftView.js index c1db712..ddf358b 100644 --- a/out/panels/views/AircraftView.js +++ b/out/panels/views/AircraftView.js @@ -6,7 +6,6 @@ const BaseView_1 = require("./BaseView"); class AircraftView extends BaseView_1.BaseView { render(data) { const aircrafts = data?.aircrafts || []; - console.log('AircraftView 渲染数据:', aircrafts); const aircraftsHtml = aircrafts.map(aircraft => ` @@ -60,7 +59,7 @@ class AircraftView extends BaseView_1.BaseView { display: flex; align-items: center; gap: 6px; - margin: 0 auto; /* 确保按钮在容器内居中 */ + margin: 0 auto; } .btn-new:hover { background: var(--vscode-button-hoverBackground); @@ -74,7 +73,6 @@ class AircraftView extends BaseView_1.BaseView { .aircraft-name:hover { background: var(--vscode-input-background); } - /* 专门为新建按钮的容器添加样式 */ .new-button-container { text-align: center; padding: 20px; @@ -97,7 +95,6 @@ class AircraftView extends BaseView_1.BaseView { ${aircraftsHtml} - @@ -186,86 +183,6 @@ class AircraftView extends BaseView_1.BaseView { } ); } - - // 对话框函数 - function showConfirmDialog(title, message, onConfirm, onCancel) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'confirmModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - window.confirmCallback = function(result) { - if (result && onConfirm) { - onConfirm(); - } else if (!result && onCancel) { - onCancel(); - } - delete window.confirmCallback; - }; - } - - function closeConfirmDialog(result) { - const modal = document.getElementById('confirmModal'); - if (modal) { - modal.remove(); - } - if (window.confirmCallback) { - window.confirmCallback(result); - } - } - - function showPromptDialog(title, message, defaultValue, onConfirm) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'promptModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - setTimeout(() => { - const input = document.getElementById('promptInput'); - if (input) { - input.focus(); - input.select(); - } - }, 100); - - window.promptCallback = onConfirm; - } - - function closePromptDialog(result) { - const modal = document.getElementById('promptModal'); - if (modal) { - modal.remove(); - } - if (window.promptCallback) { - window.promptCallback(result); - } - delete window.promptCallback; - } `; diff --git a/out/panels/views/AircraftView.js.map b/out/panels/views/AircraftView.js.map index b6945da..f24f11b 100644 --- a/out/panels/views/AircraftView.js.map +++ b/out/panels/views/AircraftView.js.map @@ -1 +1 @@ -{"version":3,"file":"AircraftView.js","sourceRoot":"","sources":["../../../src/panels/views/AircraftView.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AACnC,yCAAsC;AAGtC,MAAa,YAAa,SAAQ,mBAAQ;IACtC,MAAM,CAAC,IAAwC;QAC3C,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;QAExC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;QAE7C,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;;;oEAGY,QAAQ,CAAC,EAAE,QAAQ,QAAQ,CAAC,IAAI;;;2EAGzB,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,SAAS;;;0EAGrC,QAAQ,CAAC,EAAE;;;SAG5E,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsER,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4KnB,CAAC;IACL,CAAC;CACJ;AA9QD,oCA8QC"} \ No newline at end of file +{"version":3,"file":"AircraftView.js","sourceRoot":"","sources":["../../../src/panels/views/AircraftView.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AACnC,yCAAsC;AAGtC,MAAa,YAAa,SAAQ,mBAAQ;IACtC,MAAM,CAAC,IAAwC;QAC3C,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;QAExC,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;;;oEAGY,QAAQ,CAAC,EAAE,QAAQ,QAAQ,CAAC,IAAI;;;2EAGzB,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,SAAS;;;0EAGrC,QAAQ,CAAC,EAAE;;;SAG5E,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAqER,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2FnB,CAAC;IACL,CAAC;CACJ;AA1LD,oCA0LC"} \ No newline at end of file diff --git a/out/panels/views/BaseView.js b/out/panels/views/BaseView.js index 2b76bef..0192b83 100644 --- a/out/panels/views/BaseView.js +++ b/out/panels/views/BaseView.js @@ -5,7 +5,10 @@ class BaseView { constructor(extensionUri) { this.extensionUri = extensionUri; } - getStyles() { + /** + * 获取通用的样式和脚本 + */ + getBaseStylesAndScripts() { return ` + `; + } + /** + * 获取仓库选择对话框的脚本(仅ConfigView需要) + */ + getRepoSelectScript() { + return ` + `; } + /** + * 获取样式(被子类覆盖) + */ + getStyles() { + return this.getBaseStylesAndScripts(); + } } exports.BaseView = BaseView; //# sourceMappingURL=BaseView.js.map \ No newline at end of file diff --git a/out/panels/views/BaseView.js.map b/out/panels/views/BaseView.js.map index 4ac49e4..6a4d887 100644 --- a/out/panels/views/BaseView.js.map +++ b/out/panels/views/BaseView.js.map @@ -1 +1 @@ -{"version":3,"file":"BaseView.js","sourceRoot":"","sources":["../../../src/panels/views/BaseView.ts"],"names":[],"mappings":";;;AAEA,MAAsB,QAAQ;IAG1B,YAAY,YAAwB;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAIS,SAAS;QACf,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAuQN,CAAC;IACN,CAAC;CACJ;AAnRD,4BAmRC"} \ No newline at end of file +{"version":3,"file":"BaseView.js","sourceRoot":"","sources":["../../../src/panels/views/BaseView.ts"],"names":[],"mappings":";;;AAGA,MAAsB,QAAQ;IAG1B,YAAY,YAAwB;QAChC,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;IACrC,CAAC;IAID;;OAEG;IACO,uBAAuB;QAC7B,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAmPN,CAAC;IACN,CAAC;IAED;;OAEG;IACO,mBAAmB;QACzB,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;SAqGN,CAAC;IACN,CAAC;IAED;;OAEG;IACO,SAAS;QACf,OAAO,IAAI,CAAC,uBAAuB,EAAE,CAAC;IAC1C,CAAC;CACJ;AArXD,4BAqXC"} \ No newline at end of file diff --git a/out/panels/views/ConfigView.js b/out/panels/views/ConfigView.js index bfeff1c..9f58297 100644 --- a/out/panels/views/ConfigView.js +++ b/out/panels/views/ConfigView.js @@ -11,7 +11,7 @@ class ConfigView extends BaseView_1.BaseView { const moduleFolderFileTree = data?.moduleFolderFileTree || []; const moduleFolderLoading = data?.moduleFolderLoading || false; const gitBranches = data?.gitBranches || []; - // 生成配置列表的 HTML - 包含配置文件和模块文件夹 + // 生成配置列表的 HTML const configsHtml = configs.map((config) => ` @@ -27,10 +27,9 @@ class ConfigView extends BaseView_1.BaseView { `).join(''); - // 生成模块文件夹的 HTML - 按类别分类显示 + // 生成模块文件夹的 HTML const moduleFoldersHtml = moduleFolders.map((folder) => { const icon = '📁'; - // 根据类型和上传状态确定类别显示 let category = folder.type === 'git' ? 'git' : 'local'; if (folder.uploaded) { category += '(已上传)'; @@ -39,14 +38,12 @@ class ConfigView extends BaseView_1.BaseView { return ` - ${icon} ${folder.name} ${category} - 📄 ${fileName} @@ -59,7 +56,7 @@ class ConfigView extends BaseView_1.BaseView { `; }).join(''); - // 生成分支选择的 HTML - 使用树状结构(首次渲染可以为空,后续通过 message 更新) + // 生成分支选择的 HTML const branchesHtml = gitBranches.length > 0 ? this.generateBranchesTreeHtml(gitBranches) : ''; return ` @@ -67,7 +64,8 @@ class ConfigView extends BaseView_1.BaseView { 配置管理 - ${this.getStyles()} + ${this.getBaseStylesAndScripts()} + ${this.getRepoSelectScript()} @@ -319,12 +307,11 @@ class ConfigView extends BaseView_1.BaseView { `; diff --git a/out/panels/views/ContainerView.js.map b/out/panels/views/ContainerView.js.map index 7beb853..26cd7e6 100644 --- a/out/panels/views/ContainerView.js.map +++ b/out/panels/views/ContainerView.js.map @@ -1 +1 @@ -{"version":3,"file":"ContainerView.js","sourceRoot":"","sources":["../../../src/panels/views/ContainerView.ts"],"names":[],"mappings":";;;AAAA,oCAAoC;AACpC,yCAAsC;AAGtC,MAAa,aAAc,SAAQ,mBAAQ;IACvC,MAAM,CAAC,IAAyB;QAC5B,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,aAAa;QAC9C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QAE1C,eAAe;QACf,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAA4B,EAAE,EAAE,CAAC;;;yEAGP,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC,IAAI,UAAU,SAAS,CAAC,IAAI;;;4EAGtD,SAAS,CAAC,EAAE;;;2EAGb,SAAS,CAAC,EAAE;;;SAG9E,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;gFAI0D,QAAQ,EAAE,IAAI,IAAI,OAAO;;;;;;;;;;;;;cAa3F,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyJpB,CAAC;IACL,CAAC;CACJ;AAvMD,sCAuMC"} \ No newline at end of file +{"version":3,"file":"ContainerView.js","sourceRoot":"","sources":["../../../src/panels/views/ContainerView.ts"],"names":[],"mappings":";;;AAAA,oCAAoC;AACpC,yCAAsC;AAGtC,MAAa,aAAc,SAAQ,mBAAQ;IACvC,MAAM,CAAC,IAAyB;QAC5B,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,CAAC;QAC9B,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,CAAC;QAChC,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QAE1C,MAAM,cAAc,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,SAA4B,EAAE,EAAE,CAAC;;;yEAGP,SAAS,CAAC,EAAE,OAAO,SAAS,CAAC,IAAI,UAAU,SAAS,CAAC,IAAI;;;4EAGtD,SAAS,CAAC,EAAE;;;2EAGb,SAAS,CAAC,EAAE;;;SAG9E,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;gFAI0D,QAAQ,EAAE,IAAI,IAAI,OAAO;;;;;;;;;;;;;cAa3F,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyEpB,CAAC;IACL,CAAC;CACJ;AAtHD,sCAsHC"} \ No newline at end of file diff --git a/out/panels/views/ProjectView.js b/out/panels/views/ProjectView.js index d8c7d46..8c24e5a 100644 --- a/out/panels/views/ProjectView.js +++ b/out/panels/views/ProjectView.js @@ -1,6 +1,7 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.ProjectView = void 0; +// src/panels/views/ProjectView.ts const BaseView_1 = require("./BaseView"); class ProjectView extends BaseView_1.BaseView { render(data) { @@ -135,13 +136,11 @@ class ProjectView extends BaseView_1.BaseView { function configureProject(projectId, projectName, isConfigured) { if (isConfigured) { - // 已配置的项目直接打开 vscode.postMessage({ type: 'openProject', projectId: projectId }); } else { - // 未配置的项目需要设置路径 vscode.postMessage({ type: 'configureProject', projectId: projectId, @@ -188,7 +187,7 @@ class ProjectView extends BaseView_1.BaseView { ); } - // 项目名称编辑功能 - 修复版本 + // 项目名称编辑功能 document.addEventListener('DOMContentLoaded', function() { document.addEventListener('click', function(event) { if (event.target.classList.contains('project-name')) { @@ -219,86 +218,6 @@ class ProjectView extends BaseView_1.BaseView { } ); } - - // 对话框函数 - 只保留一份 - function showConfirmDialog(title, message, onConfirm, onCancel) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'confirmModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - window.confirmCallback = function(result) { - if (result && onConfirm) { - onConfirm(); - } else if (!result && onCancel) { - onCancel(); - } - delete window.confirmCallback; - }; - } - - function closeConfirmDialog(result) { - const modal = document.getElementById('confirmModal'); - if (modal) { - modal.remove(); - } - if (window.confirmCallback) { - window.confirmCallback(result); - } - } - - function showPromptDialog(title, message, defaultValue, onConfirm) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'promptModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - setTimeout(() => { - const input = document.getElementById('promptInput'); - if (input) { - input.focus(); - input.select(); - } - }, 100); - - window.promptCallback = onConfirm; - } - - function closePromptDialog(result) { - const modal = document.getElementById('promptModal'); - if (modal) { - modal.remove(); - } - if (window.promptCallback) { - window.promptCallback(result); - } - delete window.promptCallback; - } `; diff --git a/out/panels/views/ProjectView.js.map b/out/panels/views/ProjectView.js.map index 93efeac..0c3fa0a 100644 --- a/out/panels/views/ProjectView.js.map +++ b/out/panels/views/ProjectView.js.map @@ -1 +1 @@ -{"version":3,"file":"ProjectView.js","sourceRoot":"","sources":["../../../src/panels/views/ProjectView.ts"],"names":[],"mappings":";;;AAAA,yCAAsC;AAGtC,MAAa,WAAY,SAAQ,mBAAQ;IACrC,MAAM,CAAC,IAA0E;QAC7E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,IAAI,GAAG,EAAE,CAAC;QAErD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAwB,EAAE,EAAE;YAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAEhD,OAAO;;;kEAG+C,OAAO,CAAC,EAAE,KAAK,UAAU,IAAI,OAAO,CAAC,IAAI;;0BAEjF,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;;;yEAItB,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,MAAM,YAAY;0BAC9F,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;yEAIqB,OAAO,CAAC,EAAE;;;SAG1E,CAAA;QAAA,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEb,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyER,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAiMlB,CAAC;IACL,CAAC;CACJ;AA/SD,kCA+SC"} \ No newline at end of file +{"version":3,"file":"ProjectView.js","sourceRoot":"","sources":["../../../src/panels/views/ProjectView.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AAClC,yCAAsC;AAGtC,MAAa,WAAY,SAAQ,mBAAQ;IACrC,MAAM,CAAC,IAA0E;QAC7E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,IAAI,GAAG,EAAE,CAAC;QAErD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAwB,EAAE,EAAE;YAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAEhD,OAAO;;;kEAG+C,OAAO,CAAC,EAAE,KAAK,UAAU,IAAI,OAAO,CAAC,IAAI;;0BAEjF,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;;;yEAItB,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,MAAM,YAAY;0BAC9F,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;yEAIqB,OAAO,CAAC,EAAE;;;SAG1E,CAAA;QAAA,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEb,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyER,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+GlB,CAAC;IACL,CAAC;CACJ;AA7ND,kCA6NC"} \ No newline at end of file diff --git a/package.json b/package.json index d5070f9..86784fb 100755 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "dsc-platform", "displayName": "数字卫星构建平台", - "version": "1.4.1", + "version": "1.5.1", "publisher": "njust-micro-nano-lab", "description": "一个用于快速构建数字卫星的平台", "repository": { diff --git a/src/panels/ConfigPanel.ts b/src/panels/ConfigPanel.ts index 4583172..d5e289e 100755 --- a/src/panels/ConfigPanel.ts +++ b/src/panels/ConfigPanel.ts @@ -1,43 +1,24 @@ +// src/panels/ConfigPanel.ts import * as vscode from 'vscode'; import * as path from 'path'; -import * as fs from 'fs'; -import git from 'isomorphic-git'; -import http from 'isomorphic-git/http/node'; import { ProjectView } from './views/ProjectView'; import { AircraftView } from './views/AircraftView'; import { ContainerView } from './views/ContainerView'; import { ConfigView } from './views/ConfigView'; +import { ProjectService } from './services/ProjectService'; +import { GitService } from './services/GitService'; +import { StorageService } from './services/StorageService'; import { ModuleFolder } from './types/CommonTypes'; -// ============================================= -// 数据模型接口 -// ============================================= - -interface Project { - id: string; +// 仓库配置项接口 +interface RepoConfigItem { name: string; + url: string; + username?: string; + token?: string; } -interface Aircraft { - id: string; - name: string; - projectId: string; -} - -interface Container { - id: string; - name: string; - aircraftId: string; -} - -interface Config { - id: string; - name: string; - fileName: string; - content: string; - containerId: string; -} - +// Git文件树接口 interface GitFileTree { name: string; type: 'file' | 'folder'; @@ -45,37 +26,14 @@ interface GitFileTree { children?: GitFileTree[]; } -interface GitBranch { - name: string; - isCurrent: boolean; - selected?: boolean; -} - -interface ProjectData { - projects: Project[]; - aircrafts: Aircraft[]; - containers: Container[]; - configs: Config[]; - moduleFolders: ModuleFolder[]; -} - -// 仓库配置项 -interface RepoConfigItem { - name: string; - url: string; - username?: string; - password?: string; -} - -// ============================================= -// 主面板类 -// ============================================= - export class ConfigPanel { public static currentPanel: ConfigPanel | undefined; public readonly panel: vscode.WebviewPanel; private readonly extensionUri: vscode.Uri; + // 服务实例 + private projectService: ProjectService; + // 视图状态管理 private currentView: 'projects' | 'aircrafts' | 'containers' | 'configs' = 'projects'; private currentProjectId: string = ''; @@ -83,18 +41,9 @@ export class ConfigPanel { private currentContainerId: string = ''; private currentModuleFolderId: string = ''; - // 数据存储 - private projects: Project[] = []; - private aircrafts: Aircraft[] = []; - private containers: Container[] = []; - private configs: Config[] = []; - private moduleFolders: ModuleFolder[] = []; - private currentModuleFolderFileTree: GitFileTree[] = []; - private projectPaths: Map = new Map(); - - // 上传相关:local 上传 / git 上传 - private pendingUploadFolderId: string | null = null; // local -> git - private pendingGitUploadFolderId: string | null = null; // git -> repo(更新或新分支) + // 上传相关 + private pendingUploadFolderId: string | null = null; + private pendingGitUploadFolderId: string | null = null; // 仓库配置 private repoConfigs: RepoConfigItem[] = []; @@ -102,6 +51,7 @@ export class ConfigPanel { // 状态管理 private isWebviewDisposed: boolean = false; + private currentModuleFolderFileTree: GitFileTree[] = []; // 视图实例 private readonly projectView: ProjectView; @@ -140,13 +90,16 @@ export class ConfigPanel { this.extensionUri = extensionUri; this.isWebviewDisposed = false; + // 初始化服务 + this.projectService = new ProjectService(); + // 初始化视图 this.projectView = new ProjectView(extensionUri); this.aircraftView = new AircraftView(extensionUri); this.containerView = new ContainerView(extensionUri); this.configView = new ConfigView(extensionUri); - // 尝试加载仓库配置 + // 加载仓库配置 void this.loadRepoConfigs(); this.updateWebview(); @@ -158,107 +111,28 @@ export class ConfigPanel { }); } - // ============================================= - // 工具方法 - ID 生成 - // ============================================= - - private generateUniqueId(prefix: string, existingItems: any[]): string { - let idNumber = 1; - - const existingIds = existingItems.map(item => item.id); - const numberPattern = /\d+$/; - - for (const id of existingIds) { - const match = id.match(numberPattern); - if (match) { - const num = parseInt(match[0]); - if (num >= idNumber) { - idNumber = num + 1; - } - } - } - - return `${prefix}${idNumber}`; - } - // ============================================= // 仓库配置相关 // ============================================= - private getRepoConfigPath(): string { - return path.join(this.extensionUri.fsPath, 'dcsp-repos.json'); - } - private async loadRepoConfigs(): Promise { - try { - const configPath = this.getRepoConfigPath(); - if (!fs.existsSync(configPath)) { - this.repoConfigs = []; - return; - } - - const content = await fs.promises.readFile(configPath, 'utf8'); - if (!content.trim()) { - this.repoConfigs = []; - return; - } - - const parsed = JSON.parse(content); - if (Array.isArray(parsed)) { - this.repoConfigs = parsed; - } else if (parsed && Array.isArray(parsed.repos)) { - this.repoConfigs = parsed.repos; - } else { - this.repoConfigs = []; - } - } catch (error) { - console.error('加载仓库配置失败:', error); - vscode.window.showErrorMessage('读取仓库配置文件失败(dcsp-repos.json),请检查文件格式。'); - this.repoConfigs = []; - } - } - - private async ensureRepoConfigFileExists(): Promise { - const configPath = this.getRepoConfigPath(); - if (!fs.existsSync(configPath)) { - const defaultContent = JSON.stringify( - { - repos: [ - { - name: 'example-repo', - url: 'https://github.com/username/repo.git', - username: '', - password: '' - } - ] - }, - null, - 2 - ); - await fs.promises.writeFile(configPath, defaultContent, 'utf8'); - } + this.repoConfigs = await StorageService.loadRepoConfigs(this.extensionUri); } private async openRepoConfig(): Promise { - try { - await this.ensureRepoConfigFileExists(); - const configPath = this.getRepoConfigPath(); - const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(configPath)); - await vscode.window.showTextDocument(doc); - await this.loadRepoConfigs(); - } catch (error) { - vscode.window.showErrorMessage(`打开仓库配置文件失败: ${error}`); - } + await StorageService.openRepoConfig(this.extensionUri); + await this.loadRepoConfigs(); } /** - * 通用:弹出仓库选择弹窗(不区分“获取分支 / 上传”,使用 pendingXXX 做上下文判断) + * 弹出仓库选择弹窗 */ private async openRepoSelect(): Promise { await this.loadRepoConfigs(); - if (!this.repoConfigs || this.repoConfigs.length === 0) { - vscode.window.showWarningMessage('尚未配置任何仓库,请先点击右上角 “仓库配置” 按钮编辑 dcsp-repos.json。'); + if (this.repoConfigs.length === 0) { + vscode.window.showWarningMessage('尚未配置任何仓库,请先点击右上角 "仓库配置" 按钮编辑 dcsp-repos.json。'); + return; } if (this.isWebviewDisposed) return; @@ -271,16 +145,13 @@ export class ConfigPanel { /** * 仓库选择确认后的统一入口 - * - local 上传:pendingUploadFolderId 有值 - * - git 上传:pendingGitUploadFolderId 有值 - * - 其余:当作“获取分支”处理 */ private async handleRepoSelectedForBranches(repoName: string): Promise { await this.loadRepoConfigs(); const repo = this.repoConfigs.find(r => r.name === repoName); if (!repo) { - vscode.window.showErrorMessage(`在仓库配置中未找到名为 "${repoName}" 的仓库,请检查 dcsp-repos.json。`); + vscode.window.showErrorMessage(`在仓库配置中未找到名为 "${repoName}" 的仓库`); return; } @@ -288,25 +159,7 @@ export class ConfigPanel { if (this.pendingUploadFolderId) { const localFolderId = this.pendingUploadFolderId; this.pendingUploadFolderId = null; - - console.log("🚀 Local 上传流程:repo =", repoName, "folderId =", localFolderId); - - const folder = this.moduleFolders.find(f => f.id === localFolderId); - if (!folder || folder.type !== 'local') { - vscode.window.showErrorMessage("未找到要上传的本地模块文件夹"); - return; - } - - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage("无法确定本地模块文件夹路径"); - return; - } - - const branchName = path.basename(fullPath); - console.log("🌿 Local 上传自动生成分支名:", branchName); - - await this.uploadLocalModuleFolder(localFolderId, repo.url, branchName); + await this.processLocalUpload(localFolderId, repo); return; } @@ -314,86 +167,105 @@ export class ConfigPanel { if (this.pendingGitUploadFolderId) { const gitFolderId = this.pendingGitUploadFolderId; this.pendingGitUploadFolderId = null; - - console.log("🚀 Git 上传流程:repo =", repoName, "folderId =", gitFolderId); - - const folder = this.moduleFolders.find(f => f.id === gitFolderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage("未找到要上传的 Git 模块文件夹"); - return; - } - - const newFolderName = folder.localPath.split('/').pop() ?? ''; - const oldFolderName = folder.originalFolderName ?? newFolderName; - - const isRenamed = newFolderName !== oldFolderName; - const isSameRepo = !!folder.originalRepoUrl && folder.originalRepoUrl === repo.url; - - console.log('🔍 Git 上传判断:'); - console.log(' oldFolderName:', oldFolderName); - console.log(' newFolderName:', newFolderName); - console.log(' isRenamed :', isRenamed); - console.log(' folderRepo :', folder.originalRepoUrl); - console.log(' selectedRepo :', repo.url); - console.log(' isSameRepo :', isSameRepo); - - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage("无法确定 Git 模块文件夹路径"); - return; - } - - // 2.1 未改名 + 还是原来的仓库 → 直接在原分支上 push(更新代码) - if (!isRenamed && isSameRepo) { - console.log('✅ 未改名 & 同仓库:执行原始 push 逻辑'); - await this.uploadGitModuleFolder(gitFolderId); - return; - } - - // 2.2 改了名字 或 换了仓库 → 使用“当前文件夹名”作为分支,推送到选中仓库 - console.log('🆕 名称改变或仓库改变:以文件夹名作为新分支上传'); - - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '准备上传...' }); - - await this.pushGitModuleFolderToRepoWithBranch(fullPath, repo.url, newFolderName); - - folder.uploaded = true; - folder.originalFolderName = newFolderName; - folder.originalRepoUrl = repo.url; - - await this.saveCurrentProjectData(); - - progress.report({ increment: 100, message: '完成' }); - vscode.window.showInformationMessage(`✅ Git 仓库已上传到 ${repo.name} 的分支 ${newFolderName}`); - this.updateWebview(); - } catch (error: any) { - console.error('❌ Git 上传到新仓库/分支失败:', error); - vscode.window.showErrorMessage(`推送失败: ${error.message || error}`); - } - }); - + await this.processGitUpload(gitFolderId, repo); return; } - // 3️⃣ 默认:获取分支(用于“获取仓库”-> 克隆) + // 3️⃣ 默认:获取分支(用于"获取仓库"-> 克隆) this.currentRepoForBranches = repo; await this.fetchBranchesForRepo(repo); } + private async processLocalUpload(folderId: string, repo: RepoConfigItem): Promise { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder || folder.type !== 'local') { + vscode.window.showErrorMessage("未找到要上传的本地模块文件夹"); + return; + } + + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage("无法确定本地模块文件夹路径"); + return; + } + + const branchName = path.basename(fullPath); + await this.uploadLocalModuleFolder( + folderId, + repo.url, + branchName, + repo.username, + repo.token + ); + } + + private async processGitUpload(folderId: string, repo: RepoConfigItem): Promise { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage("未找到要上传的 Git 模块文件夹"); + return; + } + + const newFolderName = folder.localPath.split('/').pop() ?? ''; + const oldFolderName = folder.originalFolderName ?? newFolderName; + + const isRenamed = newFolderName !== oldFolderName; + const isSameRepo = !!folder.originalRepoUrl && folder.originalRepoUrl === repo.url; + + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage("无法确定 Git 模块文件夹路径"); + return; + } + + // 2.1 未改名 + 还是原来的仓库 → 直接在原分支上 push(更新代码) + if (!isRenamed && isSameRepo) { + await this.uploadGitModuleFolder(folderId); + return; + } + + // 2.2 改了名字 或 换了仓库 → 使用"当前文件夹名"作为分支,推送到选中仓库 + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '准备上传...' }); + + await GitService.pushToRepoUrl( + fullPath, + repo.url, + newFolderName, + repo.username, + repo.token + ); + + + this.projectService.updateModuleFolder(folderId, { + uploaded: true, + originalFolderName: newFolderName, + originalRepoUrl: repo.url + }); + + await this.saveCurrentProjectData(); + + progress.report({ increment: 100, message: '完成' }); + vscode.window.showInformationMessage(`✅ Git 仓库已上传到 ${repo.name} 的分支 ${newFolderName}`); + this.updateWebview(); + } catch (error: any) { + console.error('❌ Git 上传到新仓库/分支失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message || error}`); + } + }); + } + // ============================================= // Webview 消息处理 // ============================================= private setupMessageListener() { this.panel.webview.onDidReceiveMessage(async (data) => { - console.log('📨 收到Webview消息:', data); - if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,忽略消息'); return; @@ -444,12 +316,12 @@ export class ConfigPanel { 'openConfigFileInVSCode': (data) => this.openConfigFileInVSCode(data.configId), 'mergeConfigs': (data) => this.mergeConfigs(data.configIds, data.displayName, data.folderName), - // Git 仓库管理(新:基于配置) + // Git 仓库管理 'openRepoConfig': () => this.openRepoConfig(), 'openRepoSelect': () => this.openRepoSelect(), 'repoSelectedForBranches': (data) => this.handleRepoSelectedForBranches(data.repoName), - // Git 仓库管理(老接口:为了兼容,仍然保留) + // Git 分支管理 'fetchBranches': (data) => this.fetchBranches(data.url), 'cloneBranches': (data) => this.cloneBranches(data.branches), 'cancelBranchSelection': () => this.handleCancelBranchSelection(), @@ -537,14 +409,30 @@ export class ConfigPanel { this.updateWebview(); } + private async handleOpenRepoSelectForUpload(folderId: string): Promise { + console.log("📌 Local 上传:收到 openRepoSelectForUpload,folderId =", folderId); + this.pendingUploadFolderId = folderId; + await this.openRepoSelect(); + } + + private async openRepoSelectForGitUpload(folderId: string): Promise { + console.log('📌 Git 上传:收到 openRepoSelectForGitUpload,folderId =', folderId); + this.pendingGitUploadFolderId = folderId; + await this.openRepoSelect(); + } + + private async handleRepoSelectedForGitUpload(folderId: string, repoName: string): Promise { + // 兼容:如果前端用的是 repoSelectedForGitUpload 事件,则这里转成统一逻辑 + this.pendingGitUploadFolderId = folderId; + await this.handleRepoSelectedForBranches(repoName); + } + // ============================================= // 项目管理方法 // ============================================= private async updateProjectName(projectId: string, newName: string): Promise { - const project = this.projects.find(p => p.id === projectId); - if (project) { - project.name = newName; + if (this.projectService.updateProjectName(projectId, newName)) { vscode.window.showInformationMessage(`项目名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -552,13 +440,7 @@ export class ConfigPanel { } private async createProject(name: string): Promise { - const newId = this.generateUniqueId('p', this.projects); - const newProject: Project = { - id: newId, - name: name - }; - this.projects.push(newProject); - + const newId = await this.projectService.createProject(name); this.currentProjectId = newId; vscode.window.showInformationMessage(`新建项目: ${name}`); @@ -566,26 +448,15 @@ export class ConfigPanel { } private async deleteProject(projectId: string): Promise { - const project = this.projects.find(p => p.id === projectId); - if (!project) return; - - this.projects = this.projects.filter(p => p.id !== projectId); - - const relatedAircrafts = this.aircrafts.filter(a => a.projectId === projectId); - const aircraftIds = relatedAircrafts.map(a => a.id); - - this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); - this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); - - const containerIds = this.containers.filter(c => aircraftIds.includes(c.aircraftId)).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - - this.projectPaths.delete(projectId); - - vscode.window.showInformationMessage(`删除项目: ${project.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteProject(projectId)) { + if (this.currentProjectId === projectId) { + this.currentProjectId = ''; + this.currentView = 'projects'; + } + vscode.window.showInformationMessage('项目已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= @@ -593,9 +464,7 @@ export class ConfigPanel { // ============================================= private async updateAircraftName(aircraftId: string, newName: string): Promise { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (aircraft) { - aircraft.name = newName; + if (this.projectService.updateAircraftName(aircraftId, newName)) { vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -608,34 +477,18 @@ export class ConfigPanel { return; } - const newId = this.generateUniqueId('a', this.aircrafts); - const newAircraft: Aircraft = { - id: newId, - name: name, - projectId: this.currentProjectId - }; - this.aircrafts.push(newAircraft); - - await this.createAircraftDirectory(newAircraft); + const aircraftId = await this.projectService.createAircraft(name, this.currentProjectId); vscode.window.showInformationMessage(`新建飞行器: ${name}`); await this.saveCurrentProjectData(); this.updateWebview(); } private async deleteAircraft(aircraftId: string): Promise { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (!aircraft) return; - - this.aircrafts = this.aircrafts.filter(a => a.id !== aircraftId); - this.containers = this.containers.filter(c => c.aircraftId !== aircraftId); - - const containerIds = this.containers.filter(c => c.aircraftId === aircraftId).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - - vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteAircraft(aircraftId)) { + vscode.window.showInformationMessage('飞行器已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= @@ -643,9 +496,7 @@ export class ConfigPanel { // ============================================= private async updateContainerName(containerId: string, newName: string): Promise { - const container = this.containers.find(c => c.id === containerId); - if (container) { - container.name = newName; + if (this.projectService.updateContainerName(containerId, newName)) { vscode.window.showInformationMessage(`容器名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -658,33 +509,18 @@ export class ConfigPanel { return; } - const newId = this.generateUniqueId('c', this.containers); - const newContainer: Container = { - id: newId, - name: name, - aircraftId: this.currentAircraftId - }; - this.containers.push(newContainer); - - await this.createContainerDirectory(newContainer); - await this.createDefaultConfigs(newContainer); - + const containerId = await this.projectService.createContainer(name, this.currentAircraftId); vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`); await this.saveCurrentProjectData(); this.updateWebview(); } private async deleteContainer(containerId: string): Promise { - const container = this.containers.find(c => c.id === containerId); - if (!container) return; - - this.containers = this.containers.filter(c => c.id !== containerId); - this.configs = this.configs.filter(cfg => cfg.containerId !== containerId); - this.moduleFolders = this.moduleFolders.filter(folder => folder.containerId !== containerId); - - vscode.window.showInformationMessage(`删除容器: ${container.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); + if (this.projectService.deleteContainer(containerId)) { + vscode.window.showInformationMessage('容器已删除'); + await this.saveCurrentProjectData(); + this.updateWebview(); + } } // ============================================= @@ -692,9 +528,7 @@ export class ConfigPanel { // ============================================= private async updateConfigName(configId: string, newName: string): Promise { - const config = this.configs.find(c => c.id === configId); - if (config) { - config.name = newName; + if (this.projectService.updateConfigName(configId, newName)) { vscode.window.showInformationMessage(`配置名称更新: ${newName}`); await this.saveCurrentProjectData(); this.updateWebview(); @@ -702,30 +536,14 @@ export class ConfigPanel { } private async createConfig(name: string): Promise { - const newId = this.generateUniqueId('cfg', this.configs); - const newConfig: Config = { - id: newId, - name: name, - fileName: name.toLowerCase().replace(/\s+/g, '_'), - content: `# ${name} 配置文件\n# 创建时间: ${new Date().toLocaleString()}\n# 您可以在此编辑配置内容\n\n`, - containerId: this.currentContainerId - }; - this.configs.push(newConfig); - - await this.ensureContainerDirectoryExists(this.currentContainerId); + const configId = await this.projectService.createConfig(name, this.currentContainerId); vscode.window.showInformationMessage(`新建配置: ${name}`); await this.saveCurrentProjectData(); this.updateWebview(); } - private async handleOpenRepoSelectForUpload(folderId: string): Promise { - console.log("📌 Local 上传:收到 openRepoSelectForUpload,folderId =", folderId); - this.pendingUploadFolderId = folderId; - await this.openRepoSelect(); - } - private async deleteConfig(configId: string): Promise { - const config = this.configs.find(c => c.id === configId); + const config = this.projectService.getConfig(configId); if (!config) return; const confirm = await vscode.window.showWarningMessage( @@ -740,8 +558,11 @@ export class ConfigPanel { } try { - this.configs = this.configs.filter(c => c.id !== configId); - await this.deleteConfigFileFromDisk(config); + // 删除配置文件 + await this.projectService.deleteConfigFileFromDisk(configId); + + // 从内存中删除 + this.projectService.deleteConfig(configId); vscode.window.showInformationMessage(`删除配置: ${config.name}`); await this.saveCurrentProjectData(); @@ -764,49 +585,63 @@ export class ConfigPanel { } try { - const container = this.containers.find(c => c.id === this.currentContainerId); - const aircraft = this.aircrafts.find(a => a.id === container!.aircraftId); - const projectPath = this.projectPaths.get(aircraft!.projectId); - - if (!container || !aircraft || !projectPath) { - vscode.window.showErrorMessage('未找到相关项目数据'); + const container = this.projectService.getContainersByAircraft(this.currentAircraftId) + .find(c => c.id === this.currentContainerId); + if (!container) { + vscode.window.showErrorMessage('未找到容器数据'); return; } - const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); + const projectPath = this.projectService.getProjectPath(this.currentProjectId); + if (!projectPath) { + vscode.window.showErrorMessage('未找到项目路径'); + return; + } + + // 获取选中的配置 + const selectedConfigs = configIds + .map(id => this.projectService.getConfig(id)) + .filter(Boolean); + if (selectedConfigs.length !== configIds.length) { vscode.window.showErrorMessage('部分配置文件未找到'); return; } - const mergeFolderPath = path.join(projectPath, aircraft.name, container.name, folderName); - await fs.promises.mkdir(mergeFolderPath, { recursive: true }); + // 创建合并文件夹 + const mergeFolderPath = path.join(projectPath, this.getAircraftName(), container.name, folderName); + await vscode.workspace.fs.createDirectory(vscode.Uri.file(mergeFolderPath)); + // 复制文件到合并文件夹 for (const config of selectedConfigs) { - const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); + if (!config) continue; + + const sourcePath = this.projectService.getConfigFilePath(config.id); const targetPath = path.join(mergeFolderPath, config.fileName); - if (fs.existsSync(sourcePath)) { - await fs.promises.copyFile(sourcePath, targetPath); + if (sourcePath && require('fs').existsSync(sourcePath)) { + await require('fs').promises.copyFile(sourcePath, targetPath); } else { - await fs.promises.writeFile(targetPath, config.content || ''); + await require('fs').promises.writeFile(targetPath, config.content || ''); } } - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - const newId = this.generateUniqueId('local-', this.moduleFolders); + // 创建模块文件夹记录(使用 ProjectService 的统一 ID 生成) + const relativePath = `/${this.currentProjectId}/${this.getAircraftName()}/${container.name}/${folderName}`; const newFolder: ModuleFolder = { - id: newId, + id: this.projectService.generateUniqueId('local-'), name: displayName, type: 'local', localPath: relativePath, containerId: this.currentContainerId }; - this.moduleFolders.push(newFolder); + this.projectService.addModuleFolder(newFolder); + // 删除原配置 for (const configId of configIds) { - await this.deleteConfigInternal(configId); + this.projectService.deleteConfig(configId); + await this.projectService.deleteConfigFileFromDisk(configId); } await this.saveCurrentProjectData(); @@ -819,6 +654,18 @@ export class ConfigPanel { } } + private getAircraftName(): string { + const aircrafts = this.projectService.getAircraftsByProject(this.currentProjectId); + const aircraft = aircrafts.find(a => a.id === this.currentAircraftId); + return aircraft?.name || '未知飞行器'; + } + + private getContainerName(): string { + const containers = this.projectService.getContainersByAircraft(this.currentAircraftId); + const container = containers.find(c => c.id === this.currentContainerId); + return container?.name || '未知容器'; + } + // ============================================= // Git 分支管理方法 // ============================================= @@ -829,8 +676,6 @@ export class ConfigPanel { private async fetchBranches(url: string, repo?: RepoConfigItem): Promise { try { - console.log('🌿 开始获取分支列表:', url); - await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: '正在获取分支信息', @@ -841,49 +686,19 @@ export class ConfigPanel { try { progress.report({ increment: 30, message: '获取远程引用...' }); - const options: any = { - http: http, - url: url - }; - - if (repo && (repo.username || repo.password)) { - options.onAuth = () => ({ - username: repo.username || '', - password: repo.password || '' - }); - } - - const refs = await git.listServerRefs(options); - - console.log('📋 获取到的引用:', refs); - - const branchRefs = refs.filter((ref: any) => - ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/') + const branches = await GitService.fetchBranches( + url, + repo?.username, + repo?.token ); - const branches: GitBranch[] = branchRefs.map((ref: any) => { - let branchName: string; - - if (ref.ref.startsWith('refs/remotes/')) { - branchName = ref.ref.replace('refs/remotes/origin/', ''); - } else { - branchName = ref.ref.replace('refs/heads/', ''); - } - - return { - name: branchName, - isCurrent: branchName === 'main' || branchName === 'master', - selected: false - }; - }); - if (branches.length === 0) { throw new Error('未找到任何分支'); } progress.report({ increment: 80, message: '处理分支数据...' }); - const branchTree = this.buildBranchTree(branches); + const branchTree = GitService.buildBranchTree(branches); if (!this.isWebviewDisposed) { this.panel.webview.postMessage({ @@ -898,7 +713,7 @@ export class ConfigPanel { progress.report({ increment: 100, message: '完成' }); } catch (error) { - console.error('❌ 使用 listServerRefs 获取分支失败:', error); + console.error('❌ 获取分支失败:', error); vscode.window.showErrorMessage(`获取分支失败: ${error}`); } }); @@ -911,7 +726,7 @@ export class ConfigPanel { private async cloneBranches(branches: string[]): Promise { if (!this.currentRepoForBranches) { - vscode.window.showErrorMessage('请先通过“获取仓库”选择一个仓库'); + vscode.window.showErrorMessage('请先通过"获取仓库"选择一个仓库'); return; } @@ -939,8 +754,9 @@ export class ConfigPanel { console.log(`📥 开始克隆分支: ${branch}`); try { - const folderNames = this.generateModuleFolderName(url, branch); - await this.addGitModuleFolder(url, repoDisplayName, folderNames.folderName, branch); + const folderNames = GitService.generateModuleFolderName(url, branch); + await this.addGitModuleFolder(url,repoDisplayName,folderNames.folderName,branch,this.currentRepoForBranches?.username,this.currentRepoForBranches?.token); + successCount++; console.log(`✅ 分支克隆成功: ${branch}`); } catch (error) { @@ -962,11 +778,14 @@ export class ConfigPanel { } } - // ============================================= - // 模块文件夹管理方法 - // ============================================= - - private async addGitModuleFolder(url: string, displayName: string, folderName: string, branch?: string): Promise { + private async addGitModuleFolder( + url: string, + displayName: string, + folderName: string, + branch?: string, + username?: string, + token?: string +): Promise { try { if (!url || !url.startsWith('http')) { vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL'); @@ -978,24 +797,22 @@ export class ConfigPanel { return; } - const container = this.containers.find(c => c.id === this.currentContainerId); - const aircraft = this.aircrafts.find(a => a.id === container!.aircraftId); - const projectPath = this.projectPaths.get(aircraft!.projectId); - - if (!container || !aircraft || !projectPath) { + const projectPath = this.projectService.getProjectPath(this.currentProjectId); + if (!projectPath) { vscode.window.showErrorMessage('未找到相关项目数据'); return; } - const folderId = this.generateUniqueId('git-', this.moduleFolders); - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - const localPath = path.join(projectPath, aircraft.name, container.name, folderName); + // 使用 ProjectService 的统一 ID 生成 + const folderId = this.projectService.generateUniqueId('git-'); + const relativePath = `/${this.currentProjectId}/${this.getAircraftName()}/${this.getContainerName()}/${folderName}`; + const localPath = path.join(projectPath, this.getAircraftName(), this.getContainerName(), folderName); console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`); - const existingFolder = this.moduleFolders.find(folder => - folder.localPath === relativePath && folder.containerId === this.currentContainerId - ); + const existingFolder = this.projectService.getModuleFoldersByContainer(this.currentContainerId) + .find(folder => folder.localPath === relativePath); + if (existingFolder) { vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`); return; @@ -1019,52 +836,12 @@ export class ConfigPanel { progress.report({ increment: 0 }); try { - const parentDir = path.dirname(localPath); - await fs.promises.mkdir(parentDir, { recursive: true }); - - let dirExists = false; - try { - await fs.promises.access(localPath); - dirExists = true; - } catch { - dirExists = false; - } - - if (dirExists) { - const dirContents = await fs.promises.readdir(localPath); - if (dirContents.length > 0) { - const confirm = await vscode.window.showWarningMessage( - `目标目录 "${folderName}" 不为空,确定要覆盖吗?`, - { modal: true }, - '确定覆盖', - '取消' - ); - - if (confirm !== '确定覆盖') { - vscode.window.showInformationMessage('克隆操作已取消'); - return; - } - - for (const item of dirContents) { - const itemPath = path.join(localPath, item); - if (item !== '.git') { - await fs.promises.rm(itemPath, { recursive: true, force: true }); - } - } - } - } - - console.log(`🚀 开始克隆: ${url} -> ${localPath}, 分支: ${branch}`); - - await git.clone({ - fs: fs, - http: http, - dir: localPath, - url: url, - singleBranch: true, - depth: 1, - ref: branch || 'main', - onProgress: (event: any) => { + // 使用 GitService 克隆仓库 + await GitService.cloneRepository( + url, + localPath, + branch, + (event: any) => { console.log(`📊 克隆进度: ${event.phase} - ${event.loaded}/${event.total}`); if (event.total) { const percent = (event.loaded / event.total) * 100; @@ -1075,19 +852,21 @@ export class ConfigPanel { } else { progress.report({ message: `${event.phase}...` }); } - } - }); + }, + username, + token + ); console.log('✅ Git克隆成功完成'); - const clonedContents = await fs.promises.readdir(localPath); + const clonedContents = await require('fs').promises.readdir(localPath); console.log(`📁 克隆后的目录内容:`, clonedContents); if (clonedContents.length === 0) { throw new Error('克隆后目录为空,可能克隆失败'); } - this.moduleFolders.push(newFolder); + this.projectService.addModuleFolder(newFolder); await this.saveCurrentProjectData(); console.log('✅ Git模块文件夹数据已保存到项目文件'); @@ -1104,8 +883,8 @@ export class ConfigPanel { console.error('❌ 在克隆过程中捕获错误:', error); try { - if (fs.existsSync(localPath)) { - await fs.promises.rm(localPath, { recursive: true, force: true }); + if (require('fs').existsSync(localPath)) { + await require('fs').promises.rm(localPath, { recursive: true, force: true }); console.log('🧹 已清理克隆失败的目录'); } } catch (cleanupError) { @@ -1123,9 +902,13 @@ export class ConfigPanel { } } + // ============================================= + // 模块文件夹管理方法 + // ============================================= + private async loadModuleFolder(folderId: string): Promise { this.currentModuleFolderId = folderId; - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (folder && folder.type === 'git') { await this.loadModuleFolderFileTree(folderId); } @@ -1133,13 +916,13 @@ export class ConfigPanel { } private async syncGitModuleFolder(folderId: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -1153,13 +936,7 @@ export class ConfigPanel { try { progress.report({ increment: 0, message: '拉取最新更改...' }); - await git.pull({ - fs: fs, - http: http, - dir: fullPath, - author: { name: 'DCSP User', email: 'user@dcsp.local' }, - fastForward: true - }); + await GitService.pullChanges(fullPath); await this.loadModuleFolderFileTree(folderId); vscode.window.showInformationMessage(`Git 仓库同步成功: ${folder.name}`); @@ -1172,7 +949,7 @@ export class ConfigPanel { } private async deleteModuleFolder(folderId: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder) return; const confirm = await vscode.window.showWarningMessage( @@ -1184,12 +961,12 @@ export class ConfigPanel { if (confirm === '确定删除') { try { - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (fullPath) { - await fs.promises.rm(fullPath, { recursive: true, force: true }); + await require('fs').promises.rm(fullPath, { recursive: true, force: true }); } - this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); + this.projectService.deleteModuleFolder(folderId); await this.saveCurrentProjectData(); if (this.currentModuleFolderId === folderId) { @@ -1212,42 +989,33 @@ export class ConfigPanel { return; } - const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); + const folder = this.projectService.getModuleFolder(this.currentModuleFolderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); return; } - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } - try { - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹路径'); return; } const fileFullPath = path.join(fullPath, filePath); - const content = await fs.promises.readFile(fileFullPath, 'utf8'); + const content = await require('fs').promises.readFile(fileFullPath, 'utf8'); const fileName = path.basename(filePath); - const newId = this.generateUniqueId('cfg', this.configs); - const newConfig: Config = { - id: newId, - name: fileName, - fileName: fileName, - content: content, - containerId: this.currentContainerId - }; + const configId = await this.projectService.createConfig(fileName, this.currentContainerId); + const config = this.projectService.getConfig(configId); + + if (config) { + config.content = content; + } - this.configs.push(newConfig); await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); + vscode.window.showInformationMessage(`文件已导入: ${fileName}`); this.updateWebview(); } catch (error) { @@ -1259,18 +1027,14 @@ export class ConfigPanel { // 上传功能方法 // ============================================= - /** - * 旧的 Git 模块上传逻辑:直接在当前远程 / 当前分支上 commit + push - * 现在只在“未改名 + 同仓库”的场景下被调用 - */ private async uploadGitModuleFolder(folderId: string, username?: string, password?: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -1284,11 +1048,11 @@ export class ConfigPanel { try { progress.report({ increment: 0, message: '检查更改...' }); - await this.commitAndPushUsingCommandLine(fullPath); + await GitService.commitAndPush(fullPath); progress.report({ increment: 100, message: '完成' }); - folder.uploaded = true; + this.projectService.updateModuleFolder(folderId, { uploaded: true }); await this.saveCurrentProjectData(); vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); @@ -1301,14 +1065,20 @@ export class ConfigPanel { }); } - private async uploadLocalModuleFolder(folderId: string, repoUrl: string, branchName: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); + private async uploadLocalModuleFolder( + folderId: string, + repoUrl: string, + branchName: string, + username?: string, + token?: string + ): Promise { + const folder = this.projectService.getModuleFolder(folderId); if (!folder || folder.type !== 'local') { vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); return; } - const fullPath = this.getModuleFolderFullPath(folder); + const fullPath = this.projectService.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); return; @@ -1322,28 +1092,30 @@ export class ConfigPanel { try { progress.report({ increment: 0, message: '检查目录...' }); - if (!fs.existsSync(fullPath)) { + if (!require('fs').existsSync(fullPath)) { throw new Error('本地文件夹不存在'); } progress.report({ increment: 10, message: '初始化 Git 仓库...' }); - await this.initGitRepository(fullPath, branchName); + await GitService.initRepository(fullPath, branchName); progress.report({ increment: 20, message: '添加远程仓库...' }); - await this.addGitRemote(fullPath, repoUrl); + await GitService.addRemote(fullPath, repoUrl); progress.report({ increment: 40, message: '提交初始文件...' }); - await this.commitInitialFiles(fullPath); + await GitService.commitInitialFiles(fullPath); progress.report({ increment: 60, message: '推送到远程仓库...' }); - await this.pushToRemoteWithForce(fullPath, branchName); + await GitService.pushToRemote(fullPath, branchName); progress.report({ increment: 100, message: '完成' }); - folder.type = 'git'; - folder.uploaded = true; - folder.originalFolderName = branchName; - folder.originalRepoUrl = repoUrl; + this.projectService.updateModuleFolder(folderId, { + type: 'git', + uploaded: true, + originalFolderName: branchName, + originalRepoUrl: repoUrl + }); await this.saveCurrentProjectData(); @@ -1356,8 +1128,8 @@ export class ConfigPanel { try { const gitDir = path.join(fullPath, '.git'); - if (fs.existsSync(gitDir)) { - await fs.promises.rm(gitDir, { recursive: true, force: true }); + if (require('fs').existsSync(gitDir)) { + await require('fs').promises.rm(gitDir, { recursive: true, force: true }); } } catch (cleanupError) { console.error('清理 .git 文件夹失败:', cleanupError); @@ -1366,449 +1138,147 @@ export class ConfigPanel { }); } - /** - * Git 模块以“当前文件夹名”为分支,推送到任意仓库 URL - * 不修改现有 remote 配置,直接用 URL 形式 push - */ - private async pushGitModuleFolderToRepoWithBranch(fullPath: string, repoUrl: string, branchName: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('🚀 准备以新分支推送到仓库:', { fullPath, repoUrl, branchName }); - - // 先检查是否有未提交修改 - exec('git status --porcelain', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError: any, statusStdout: string, statusStderr: string) => { - if (statusError) { - console.error('❌ 检查 Git 状态失败:', statusError); - reject(new Error(`检查 Git 状态失败: ${statusStderr || statusError.message}`)); - return; - } - - const hasChanges = !!statusStdout.trim(); - console.log('📋 有未提交更改?:', hasChanges, ', status =\n', statusStdout); - - const commands: string[] = []; - - // 获取完整的仓库历史 - commands.push('git fetch --unshallow'); - - // 切换 / 创建分支 - commands.push(`git checkout -B "${branchName}"`); - - // 有变更就先提交 - if (hasChanges) { - commands.push('git add .'); - commands.push(`git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`); - } - - // 直接用 URL 形式推送,不依赖 remote 名称 - commands.push(`git push -u "${repoUrl}" "${branchName}" --force`); - - console.log('🧰 即将执行命令链:', commands.join(' && ')); - - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - - if (error) { - console.error('❌ Git 推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ Git 推送到指定仓库/分支成功'); - resolve(); - }); - }); - }); -} - - // ============================================= - // Git 命令行工具方法 + // 文件树和模块文件夹方法 // ============================================= - private async commitAndPushUsingCommandLine(fullPath: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('🚀 使用命令行 Git 提交并推送...'); - console.log(`📁 工作目录: ${fullPath}`); - - exec('git status --porcelain', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError: any, statusStdout: string, statusStderr: string) => { - if (statusError) { - console.error('❌ 检查 Git 状态失败:', statusError); - reject(new Error(`检查 Git 状态失败: ${statusStderr || statusError.message}`)); - return; - } - - if (!statusStdout.trim()) { - console.log('ℹ️ 没有需要提交的更改'); - reject(new Error('没有需要提交的更改')); - return; - } - - console.log('📋 检测到更改:', statusStdout); - - const commands = [ - 'git add .', - `git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`, - 'git push' - ]; - - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - console.log('📋 Git 命令输出:', stdout); - console.log('📋 Git 命令错误:', stderr); - - if (error) { - console.error('❌ Git 提交/推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ Git 提交并推送成功'); - resolve(); - }); - }); - }); - } + private async loadModuleFolderFileTree(folderId: string): Promise { + if (this.isWebviewDisposed) { + console.log('⚠️ Webview 已被销毁,跳过文件树加载'); + return; + } - private async initGitRepository(fullPath: string, branchName: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('📁 初始化 Git 仓库...'); - - exec(`git init && git checkout -b "${branchName}"`, { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - if (error) { - console.error('❌ Git 初始化失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ Git 初始化成功'); - resolve(); - }); - }); - } + const folder = this.projectService.getModuleFolder(folderId); + if (!folder) return; - private async addGitRemote(fullPath: string, repoUrl: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('📡 添加远程仓库...'); - - exec(`git remote add origin "${repoUrl}"`, { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - if (error) { - console.error('❌ 添加远程仓库失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ 远程仓库添加成功'); - resolve(); - }); - }); - } - - private async commitInitialFiles(fullPath: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('💾 提交初始文件...'); - - const commands = [ - 'git add .', - `git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"` - ]; - - exec(commands.join(' && '), { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - if (error) { - if (stderr.includes('nothing to commit') || stdout.includes('nothing to commit')) { - console.log('ℹ️ 没有需要提交的更改'); - resolve(); - return; - } - - console.error('❌ Git 提交失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ 初始文件提交成功'); - resolve(); - }); - }); - } - - private async pushToRemoteWithForce(fullPath: string, branchName: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('🚀 强制推送到远程仓库...'); - - exec(`git push -u origin "${branchName}" --force`, { - cwd: fullPath, - encoding: 'utf8' - }, (error: any, stdout: string, stderr: string) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - - if (error) { - console.error('❌ Git 推送失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ Git 推送成功'); - resolve(); - }); - }); - } - - // ============================================= - // 文件系统操作方法 - // ============================================= - - private async createAircraftDirectory(aircraft: Aircraft): Promise { try { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建飞行器目录'); - return; - } - - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - await vscode.workspace.fs.createDirectory(aircraftDir); - console.log(`✅ 创建飞行器目录: ${aircraftDir.fsPath}`); - + this.panel.webview.postMessage({ + type: 'moduleFolderLoading', + loading: true + }); } catch (error) { - console.error(`创建飞行器目录失败: ${error}`); + console.log('⚠️ 无法发送加载消息,Webview 可能已被销毁'); + return; } - } - private async createContainerDirectory(container: Container): Promise { try { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - console.warn('未找到对应的飞行器,跳过创建容器目录'); - return; + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (fullPath) { + const fileTree = await GitService.buildFileTree(fullPath); + this.currentModuleFolderFileTree = fileTree; } - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建容器目录'); - return; - } - - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - - await vscode.workspace.fs.createDirectory(aircraftDir); - await vscode.workspace.fs.createDirectory(containerDir); - console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); - - } catch (error) { - console.error(`创建容器目录失败: ${error}`); - } - } - - private async ensureContainerDirectoryExists(containerId: string): Promise { - try { - const container = this.containers.find(c => c.id === containerId); - if (!container) return; - - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) return; - - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) return; - - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - - await vscode.workspace.fs.createDirectory(aircraftDir); - await vscode.workspace.fs.createDirectory(containerDir); - - } catch (error) { - console.error(`确保容器目录存在失败: ${error}`); - } - } - - private async createDefaultConfigs(container: Container): Promise { - this.configs.push({ - id: this.generateUniqueId('cfg', this.configs), - name: '配置1', - fileName: 'dockerfile', - content: `# ${container.name} 的 Dockerfile\nFROM ubuntu:20.04\n\n# 设置工作目录\nWORKDIR /app\n\n# 复制文件\nCOPY . .\n\n# 安装依赖\nRUN apt-get update && apt-get install -y \\\n python3 \\\n python3-pip\n\n# 暴露端口\nEXPOSE 8080\n\n# 启动命令\nCMD ["python3", "app.py"]`, - containerId: container.id - }); - - this.configs.push({ - id: this.generateUniqueId('cfg', this.configs), - name: '配置2', - fileName: 'docker-compose.yml', - content: `# ${container.name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${container.name.toLowerCase().replace(/\s+/g, '-')}:\n build: .\n container_name: ${container.name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, - containerId: container.id - }); - } - - private async deleteConfigFileFromDisk(config: Config): Promise { - const container = this.containers.find(c => c.id === config.containerId); - if (!container) return; - - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) return; - - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) return; - - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); - } - } - - private async deleteConfigInternal(configId: string): Promise { - try { - const config = this.configs.find(c => c.id === configId); - if (!config) return; - - this.configs = this.configs.filter(c => c.id !== configId); - await this.deleteConfigFileFromDisk(config); - console.log(`✅ 内部删除配置: ${config.name}`); - } catch (error) { - console.error(`删除配置文件失败: ${error}`); + console.error('加载模块文件夹文件树失败:', error); + this.currentModuleFolderFileTree = []; } - } - // ============================================= - // 项目数据持久化方法 - // ============================================= - - private async saveCurrentProjectData(): Promise { - try { - if (!this.currentProjectId) { - console.warn('未找到当前项目,数据将不会保存'); - return; - } - - const projectPath = this.projectPaths.get(this.currentProjectId); - if (!projectPath) { - console.warn('未找到项目存储路径,数据将不会保存'); - return; - } - - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - - const data: ProjectData = { - projects: [this.projects.find(p => p.id === this.currentProjectId)!], - aircrafts: this.aircrafts.filter(a => a.projectId === this.currentProjectId), - containers: this.containers.filter(c => { - const aircraft = this.aircrafts.find(a => a.id === c.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }), - configs: this.configs.filter(cfg => { - const container = this.containers.find(c => c.id === cfg.containerId); - if (!container) return false; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }), - moduleFolders: this.moduleFolders.filter(folder => { - const container = this.containers.find(c => c.id === folder.containerId); - if (!container) return false; - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - return aircraft && aircraft.projectId === this.currentProjectId; - }) - }; - - const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); - await vscode.workspace.fs.writeFile(dataUri, uint8Array); - - console.log('✅ 当前项目数据已保存,包含', data.moduleFolders.length, '个模块文件夹'); - } catch (error) { - vscode.window.showErrorMessage(`保存项目数据失败: ${error}`); + if (this.isWebviewDisposed) { + console.log('⚠️ Webview 已被销毁,跳过完成通知'); + return; } - } - private async loadProjectData(projectPath: string): Promise { try { - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - - try { - await vscode.workspace.fs.stat(dataUri); - } catch { - vscode.window.showErrorMessage('选择的文件夹中没有找到项目数据文件 (.dcsp-data.json)'); - return false; - } + this.panel.webview.postMessage({ + type: 'moduleFolderLoading', + loading: false + }); - const fileData = await vscode.workspace.fs.readFile(dataUri); - const dataStr = new TextDecoder().decode(fileData); - const data: ProjectData = JSON.parse(dataStr); - - const projectId = data.projects[0]?.id; - if (projectId) { - this.projects = this.projects.filter(p => p.id !== projectId); - this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); - - const aircraftIds = this.aircrafts.filter(a => a.projectId === projectId).map(a => a.id); - this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); - - const containerIds = this.containers.filter(c => aircraftIds.includes(c.aircraftId)).map(c => c.id); - this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); - this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); - - this.projects.push(...data.projects); - this.aircrafts.push(...data.aircrafts); - this.containers.push(...data.containers); - this.configs.push(...data.configs); - this.moduleFolders.push(...data.moduleFolders); - - this.currentProjectId = projectId; - this.projectPaths.set(projectId, projectPath); - this.currentView = 'aircrafts'; - } - - vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${data.moduleFolders.length} 个模块文件夹`); this.updateWebview(); - return true; } catch (error) { - vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); - return false; + console.log('⚠️ 无法发送完成消息,Webview 可能已被销毁'); } } - private async checkProjectPathHasData(projectPath: string): Promise { + private async openConfigFileInVSCode(configId: string): Promise { + const config = this.projectService.getConfig(configId); + if (!config) { + vscode.window.showErrorMessage('未找到配置文件'); + return; + } + + const filePath = this.projectService.getConfigFilePath(configId); + if (!filePath) { + vscode.window.showErrorMessage('未设置项目存储路径'); + return; + } + try { - const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); - await vscode.workspace.fs.stat(dataUri); - return true; - } catch { - return false; + const fs = require('fs'); + if (!fs.existsSync(filePath)) { + vscode.window.showWarningMessage('配置文件不存在,将创建新文件'); + const dirPath = path.dirname(filePath); + await fs.promises.mkdir(dirPath, { recursive: true }); + await fs.promises.writeFile(filePath, config.content || ''); + } + + const document = await vscode.workspace.openTextDocument(filePath); + await vscode.window.showTextDocument(document); + + } catch (error) { + vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); + } + } + + private async openTheModuleFolder(type: 'git' | 'local', id: string): Promise { + const folder = this.projectService.getModuleFolder(id); + if (!folder) { + vscode.window.showErrorMessage('未找到指定的模块文件夹'); + return; + } + + try { + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath || !require('fs').existsSync(fullPath)) { + vscode.window.showErrorMessage('模块文件夹目录不存在'); + return; + } + + const fileUri = await vscode.window.showOpenDialog({ + defaultUri: vscode.Uri.file(fullPath), + canSelectFiles: true, + canSelectFolders: false, + canSelectMany: false, + openLabel: '选择要打开的文件', + title: `在 ${folder.name} 中选择文件` + }); + + if (fileUri && fileUri.length > 0) { + const document = await vscode.workspace.openTextDocument(fileUri[0]); + await vscode.window.showTextDocument(document); + vscode.window.showInformationMessage(`已打开文件: ${path.basename(fileUri[0].fsPath)}`); + } + + } catch (error) { + vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`); + } + } + + private async renameModuleFolder(folderId: string, newName: string): Promise { + const folder = this.projectService.getModuleFolder(folderId); + if (!folder) { + vscode.window.showErrorMessage('未找到模块文件夹'); + return; + } + + const oldName = folder.localPath.split('/').pop(); + if (!oldName) return; + + const fullPath = this.projectService.getModuleFolderFullPath(folder); + if (!fullPath) return; + + const newFullPath = path.join(path.dirname(fullPath), newName); + + try { + await require('fs').promises.rename(fullPath, newFullPath); + + this.projectService.renameModuleFolder(folderId, newName); + await this.saveCurrentProjectData(); + + vscode.window.showInformationMessage(`已重命名文件夹: ${oldName} → ${newName}`); + this.updateWebview(); + } catch (error) { + vscode.window.showErrorMessage('重命名失败: ' + error); } } @@ -1882,8 +1352,8 @@ export class ConfigPanel { if (result && result.length > 0) { const selectedPath = result[0].fsPath; - - const hasExistingData = await this.checkProjectPathHasData(selectedPath); + + const hasExistingData = await StorageService.checkProjectPathHasData(selectedPath); if (hasExistingData) { const loadChoice = await vscode.window.showWarningMessage( `在路径 ${selectedPath} 中检测到现有项目数据,是否加载?`, @@ -1895,22 +1365,20 @@ export class ConfigPanel { if (loadChoice === '是,加载现有数据') { const success = await this.loadProjectData(selectedPath); if (success) { - this.projectPaths.set(projectId, selectedPath); - this.currentView = 'aircrafts'; - this.currentProjectId = projectId; - this.updateWebview(); - vscode.window.showInformationMessage(`项目数据已从 ${selectedPath} 加载`); + // loadProjectData 里已经设置好了 currentProjectId 和 projectPath return selectedPath; } } + // 如果选择“否,创建新项目”,就往下走,覆盖旧数据 } - this.projectPaths.set(projectId, selectedPath); + // 没有旧数据,或者选择了“创建新项目”,把当前 projectId 绑定到这个路径 + this.projectService.setProjectPath(projectId, selectedPath); vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); await this.saveCurrentProjectData(); return selectedPath; } - + return null; } @@ -1931,7 +1399,7 @@ export class ConfigPanel { const dirUri = vscode.Uri.file(pathInput); await vscode.workspace.fs.createDirectory(dirUri); - this.projectPaths.set(projectId, pathInput); + this.projectService.setProjectPath(projectId, pathInput); vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); await this.saveCurrentProjectData(); return pathInput; @@ -1944,266 +1412,35 @@ export class ConfigPanel { return null; } - // ============================================= - // 文件树和模块文件夹方法 - // ============================================= - - private async loadModuleFolderFileTree(folderId: string): Promise { - if (this.isWebviewDisposed) { - console.log('⚠️ Webview 已被销毁,跳过文件树加载'); - return; - } - - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) return; - + private async loadProjectData(projectPath: string): Promise { try { - this.panel.webview.postMessage({ - type: 'moduleFolderLoading', - loading: true - }); - } catch (error) { - console.log('⚠️ 无法发送加载消息,Webview 可能已被销毁'); - return; - } + const projectId = await this.projectService.loadProjectData(projectPath); + if (projectId) { + this.currentProjectId = projectId; + this.currentView = 'aircrafts'; - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (fullPath) { - const fileTree = await this.buildFileTree(fullPath); - this.currentModuleFolderFileTree = fileTree; + vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载`); + this.updateWebview(); + return true; } - + return false; } catch (error) { - console.error('加载模块文件夹文件树失败:', error); - this.currentModuleFolderFileTree = []; + vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); + return false; } - - if (this.isWebviewDisposed) { - console.log('⚠️ Webview 已被销毁,跳过完成通知'); - return; - } - - try { - this.panel.webview.postMessage({ - type: 'moduleFolderLoading', - loading: false - }); - - this.updateWebview(); - } catch (error) { - console.log('⚠️ 无法发送完成消息,Webview 可能已被销毁'); - } - } - - private async buildFileTree(dir: string, relativePath: string = ''): Promise { - try { - const files = await fs.promises.readdir(dir); - const tree: GitFileTree[] = []; - - for (const file of files) { - if (file.startsWith('.') && file !== '.git') continue; - if (file === '.dcsp-data.json') continue; - - const filePath = path.join(dir, file); - const stats = await fs.promises.stat(filePath); - const currentRelativePath = path.join(relativePath, file); - - if (stats.isDirectory()) { - const children = await this.buildFileTree(filePath, currentRelativePath); - tree.push({ - name: file, - type: 'folder', - path: currentRelativePath, - children: children - }); - } else { - tree.push({ - name: file, - type: 'file', - path: currentRelativePath - }); - } - } - - return tree; - } catch (error) { - console.error('构建文件树失败:', error); - return []; - } - } - - private async handleRepoSelectedForGitUpload(folderId: string, repoName: string): Promise { - // 兼容:如果前端用的是 repoSelectedForGitUpload 事件,则这里转成统一逻辑 - this.pendingGitUploadFolderId = folderId; - await this.handleRepoSelectedForBranches(repoName); } // ============================================= - // 工具方法 + // 数据持久化 // ============================================= - private buildBranchTree(branches: GitBranch[]): any[] { - const root: any[] = []; - - branches.forEach(branch => { - const parts = branch.name.split('/'); - let currentLevel = root; - - for (let i = 0; i < parts.length; i++) { - const part = parts[i]; - const isLeaf = i === parts.length - 1; - const fullName = parts.slice(0, i + 1).join('/'); - - let node = currentLevel.find((n: any) => n.name === part); - - if (!node) { - node = { - name: part, - fullName: fullName, - isLeaf: isLeaf, - children: [], - level: i, - expanded: true - }; - currentLevel.push(node); - } - - if (isLeaf) { - node.branch = branch; - } - - currentLevel = node.children; - } - }); - - return root; - } - - private generateModuleFolderName(url: string, branch: string): { displayName: string; folderName: string } { - const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo'; - const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); - - return { - displayName: repoName, - folderName: branchSafeName - }; - } - - private getModuleFolderFullPath(folder: ModuleFolder): string | null { - 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); - } - - private async openConfigFileInVSCode(configId: string): Promise { - const config = this.configs.find(c => c.id === configId); - if (!config) { - vscode.window.showErrorMessage('未找到配置文件'); + private async saveCurrentProjectData(): Promise { + if (!this.currentProjectId) { + console.warn('未找到当前项目,数据将不会保存'); return; } - const container = this.containers.find(c => c.id === config.containerId); - const aircraft = this.aircrafts.find(a => a.id === container!.aircraftId); - const projectPath = this.projectPaths.get(aircraft!.projectId); - - if (!container || !aircraft || !projectPath) { - vscode.window.showErrorMessage('未设置项目存储路径'); - return; - } - - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - - try { - if (!fs.existsSync(filePath)) { - vscode.window.showWarningMessage('配置文件不存在,将创建新文件'); - const dirPath = path.dirname(filePath); - await fs.promises.mkdir(dirPath, { recursive: true }); - await fs.promises.writeFile(filePath, config.content || ''); - } - - const document = await vscode.workspace.openTextDocument(filePath); - await vscode.window.showTextDocument(document); - - } catch (error) { - vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); - } - } - - private async openTheModuleFolder(type: 'git' | 'local', id: string): Promise { - const folder = this.moduleFolders.find(f => f.id === id); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹目录不存在'); - return; - } - - const fileUri = await vscode.window.showOpenDialog({ - defaultUri: vscode.Uri.file(fullPath), - canSelectFiles: true, - canSelectFolders: false, - canSelectMany: false, - openLabel: '选择要打开的文件', - title: `在 ${folder.name} 中选择文件` - }); - - if (fileUri && fileUri.length > 0) { - const document = await vscode.workspace.openTextDocument(fileUri[0]); - await vscode.window.showTextDocument(document); - vscode.window.showInformationMessage(`已打开文件: ${path.basename(fileUri[0].fsPath)}`); - } - - } catch (error) { - vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`); - } - } - - private async renameModuleFolder(folderId: string, newName: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到模块文件夹'); - return; - } - - const oldName = folder.localPath.split('/').pop(); - if (!oldName) return; - - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) return; - - const newFullPath = path.join(path.dirname(fullPath), newName); - - try { - await fs.promises.rename(fullPath, newFullPath); - - // 更新 localPath(注意:originalFolderName 不更新,用于判断“是否改名过”) - folder.localPath = folder.localPath.replace(/\/[^/]+$/, '/' + newName); - - await this.saveCurrentProjectData(); - - vscode.window.showInformationMessage(`已重命名文件夹: ${oldName} → ${newName}`); - - this.updateWebview(); - } catch (error) { - vscode.window.showErrorMessage('重命名失败: ' + error); - } + await this.projectService.saveCurrentProjectData(this.currentProjectId); } // ============================================= @@ -2223,39 +1460,35 @@ export class ConfigPanel { } } - private async openRepoSelectForGitUpload(folderId: string): Promise { - console.log('📌 Git 上传:收到 openRepoSelectForGitUpload,folderId =', folderId); - this.pendingGitUploadFolderId = folderId; - await this.openRepoSelect(); - } - private getWebviewContent(): string { switch (this.currentView) { case 'projects': return this.projectView.render({ - projects: this.projects, - projectPaths: this.projectPaths + projects: this.projectService.getProjects(), + projectPaths: this.projectService.getProjectPaths() }); case 'aircrafts': - const projectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); + const projectAircrafts = this.projectService.getAircraftsByProject(this.currentProjectId); return this.aircraftView.render({ aircrafts: projectAircrafts }); case 'containers': - const currentProject = this.projects.find(p => p.id === this.currentProjectId); - const currentAircraft = this.aircrafts.find(a => a.id === this.currentAircraftId); - const projectContainers = this.containers.filter(c => c.aircraftId === this.currentAircraftId); + const project = this.projectService.getProjects().find(p => p.id === this.currentProjectId); + const currentAircraft = this.projectService.getAircraftsByProject(this.currentProjectId) + .find(a => a.id === this.currentAircraftId); + const projectContainers = this.projectService.getContainersByAircraft(this.currentAircraftId); return this.containerView.render({ - project: currentProject, + project: project, aircraft: currentAircraft, containers: projectContainers }); case 'configs': - const currentContainer = this.containers.find(c => c.id === this.currentContainerId); - const currentModuleFolder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - const containerConfigs = this.configs.filter(cfg => cfg.containerId === this.currentContainerId); - const containerModuleFolders = this.moduleFolders.filter(folder => folder.containerId === this.currentContainerId); + const currentContainer = this.projectService.getContainersByAircraft(this.currentAircraftId) + .find(c => c.id === this.currentContainerId); + const currentModuleFolder = this.projectService.getModuleFolder(this.currentModuleFolderId); + const containerConfigs = this.projectService.getConfigsByContainer(this.currentContainerId); + const containerModuleFolders = this.projectService.getModuleFoldersByContainer(this.currentContainerId); return this.configView.render({ container: currentContainer, @@ -2267,9 +1500,9 @@ export class ConfigPanel { }); default: return this.projectView.render({ - projects: this.projects, - projectPaths: this.projectPaths + projects: this.projectService.getProjects(), + projectPaths: this.projectService.getProjectPaths() }); } } -} +} \ No newline at end of file diff --git a/src/panels/services/GitService.ts b/src/panels/services/GitService.ts new file mode 100644 index 0000000..ee39c16 --- /dev/null +++ b/src/panels/services/GitService.ts @@ -0,0 +1,325 @@ +import * as fs from 'fs'; +import git from 'isomorphic-git'; +import http from 'isomorphic-git/http/node'; +import * as path from 'path'; +import { exec } from 'child_process'; +import { promisify } from 'util'; +import { GitBranch, GitFileTree } from '../types/CommonTypes'; + +const execAsync = promisify(exec); + +/** + * Git操作服务 + */ +export class GitService { + /** + * 获取远程分支列表 + */ + static async fetchBranches( + url: string, + username?: string, + token?: string + ): Promise { + try { + const options: any = { + http: http, + url: url + }; + + if (username || token) { + options.onAuth = () => ({ + username: username || '', + password: token || '' + }); + } + + const refs = await git.listServerRefs(options); + + const branchRefs = refs.filter((ref: any) => + ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/') + ); + + const branches: GitBranch[] = branchRefs.map((ref: any) => { + let branchName: string; + + if (ref.ref.startsWith('refs/remotes/')) { + branchName = ref.ref.replace('refs/remotes/origin/', ''); + } else { + branchName = ref.ref.replace('refs/heads/', ''); + } + + return { + name: branchName, + isCurrent: branchName === 'main' || branchName === 'master', + selected: false + }; + }); + + return branches; + } catch (error) { + console.error('获取分支失败:', error); + throw error; + } + } + + /** + * 克隆仓库 + */ + static async cloneRepository( + url: string, + localPath: string, + branch: string = 'main', + onProgress?: (event: any) => void, + username?: string, + token?: string + ): Promise { + const parentDir = path.dirname(localPath); + await fs.promises.mkdir(parentDir, { recursive: true }); + + // 检查目录是否已存在且非空(不变) + let dirExists = false; + try { + await fs.promises.access(localPath); + dirExists = true; + } catch { + dirExists = false; + } + + if (dirExists) { + const dirContents = await fs.promises.readdir(localPath); + if (dirContents.length > 0 && dirContents.some(item => item !== '.git')) { + throw new Error('目标目录不为空,请清空目录或选择其他路径'); + } + } + + const options: any = { + fs, + http, + dir: localPath, + url, + singleBranch: true, + depth: 1, + ref: branch, + onProgress + }; + + if (username || token) { + options.onAuth = () => ({ + username: username || '', + password: token || '' + }); + } + + await git.clone(options); + } + + /** + * 拉取最新更改 + */ + static async pullChanges(localPath: string): Promise { + await git.pull({ + fs: fs, + http: http, + dir: localPath, + author: { name: 'DCSP User', email: 'user@dcsp.local' }, + fastForward: true + }); + } + + /** + * 构建分支树结构 + */ + static buildBranchTree(branches: GitBranch[]): any[] { + const root: any[] = []; + + branches.forEach(branch => { + const parts = branch.name.split('/'); + let currentLevel = root; + + for (let i = 0; i < parts.length; i++) { + const part = parts[i]; + const isLeaf = i === parts.length - 1; + const fullName = parts.slice(0, i + 1).join('/'); + + let node = currentLevel.find((n: any) => n.name === part); + + if (!node) { + node = { + name: part, + fullName: fullName, + isLeaf: isLeaf, + children: [], + level: i, + expanded: true + }; + currentLevel.push(node); + } + + if (isLeaf) { + node.branch = branch; + } + + currentLevel = node.children; + } + }); + + return root; + } + + /** + * 初始化Git仓库 + */ + static async initRepository(localPath: string, branchName: string): Promise { + await execAsync(`git init && git checkout -b "${branchName}"`, { cwd: localPath }); + } + + /** + * 添加远程仓库 + */ + static async addRemote( + localPath: string, + repoUrl: string, + username?: string, + token?: string + ): Promise { + let finalUrl = repoUrl; + + if (username && token) { + const u = encodeURIComponent(username); + const t = encodeURIComponent(token); + finalUrl = repoUrl.replace('://', `://${u}:${t}@`); + } + + await execAsync(`git remote add origin "${finalUrl}"`, { cwd: localPath }); + } + + /** + * 提交初始文件 + */ + static async commitInitialFiles(localPath: string): Promise { + try { + await execAsync('git add .', { cwd: localPath }); + await execAsync( + `git commit -m "Initial commit from DCSP - ${new Date().toLocaleString()}"`, + { cwd: localPath } + ); + } catch (error: any) { + if (error.stderr?.includes('nothing to commit')) { + console.log('没有需要提交的更改'); + } else { + throw error; + } + } + } + + /** + * 推送到远程仓库 + */ + static async pushToRemote(localPath: string, branchName: string): Promise { + await execAsync(`git push -u origin "${branchName}" --force`, { cwd: localPath }); + } + + /** + * 使用Git命令提交并推送 + */ + static async commitAndPush(localPath: string): Promise { + await execAsync('git add .', { cwd: localPath }); + await execAsync( + `git commit -m "Auto commit from DCSP - ${new Date().toLocaleString()}"`, + { cwd: localPath } + ); + await execAsync('git push', { cwd: localPath }); + } + + /** + * 检查是否有未提交的更改 + */ + static async hasUncommittedChanges(localPath: string): Promise { + try { + const { stdout } = await execAsync('git status --porcelain', { cwd: localPath }); + return !!stdout.trim(); + } catch { + return false; + } + } + + /** + * 推送到指定仓库URL + */ + static async pushToRepoUrl( + localPath: string, + repoUrl: string, + branchName: string, + username?: string, + token?: string + ): Promise { + let finalUrl = repoUrl; + + if (username && token) { + const u = encodeURIComponent(username); + const t = encodeURIComponent(token); + finalUrl = repoUrl.replace('://', `://${u}:${t}@`); + } + + const commands = [ + 'git fetch --unshallow || true', // 防止没有 shallow 时直接失败 + `git checkout -B "${branchName}"`, + `git push -u "${finalUrl}" "${branchName}" --force` + ]; + + await execAsync(commands.join(' && '), { cwd: localPath }); + } + + /** + * 生成模块文件夹名称 + */ + static generateModuleFolderName(url: string, branch: string): { displayName: string; folderName: string } { + const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo'; + const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); + + return { + displayName: repoName, + folderName: branchSafeName + }; + } + + /** + * 构建文件树 + */ + static async buildFileTree(dir: string, relativePath: string = ''): Promise { + try { + const files = await fs.promises.readdir(dir); + const tree: GitFileTree[] = []; + + for (const file of files) { + if (file.startsWith('.') && file !== '.git') continue; + if (file === '.dcsp-data.json') continue; + + const filePath = path.join(dir, file); + const stats = await fs.promises.stat(filePath); + const currentRelativePath = path.join(relativePath, file); + + if (stats.isDirectory()) { + const children = await GitService.buildFileTree(filePath, currentRelativePath); + tree.push({ + name: file, + type: 'folder', + path: currentRelativePath, + children: children + }); + } else { + tree.push({ + name: file, + type: 'file', + path: currentRelativePath + }); + } + } + + return tree; + } catch (error) { + console.error('构建文件树失败:', error); + return []; + } + } +} diff --git a/src/panels/services/ProjectService.ts b/src/panels/services/ProjectService.ts new file mode 100644 index 0000000..4cb3cea --- /dev/null +++ b/src/panels/services/ProjectService.ts @@ -0,0 +1,484 @@ +// src/panels/services/ProjectService.ts +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; +import { + Project, + Aircraft, + Container, + Config, + ModuleFolder +} from '../types/CommonTypes'; +import { StorageService } from './StorageService'; + +/** + * 项目数据管理服务 + */ +export class ProjectService { + private projects: Project[] = []; + private aircrafts: Aircraft[] = []; + private containers: Container[] = []; + private configs: Config[] = []; + private moduleFolders: ModuleFolder[] = []; + private projectPaths: Map = new Map(); + + /** + * 生成唯一ID + */ + generateUniqueId(prefix: string, _existingItems: any[] = []): string { + const randomPart = `${Date.now().toString(36)}${Math.random().toString(36).substring(2, 8)}`; + return `${prefix}${randomPart}`; + } + + // =============== 项目相关方法 =============== + + getProjects(): Project[] { + return this.projects; + } + + getProjectPaths(): Map { + return this.projectPaths; + } + + getProjectPath(projectId: string): string | undefined { + return this.projectPaths.get(projectId); + } + + setProjectPath(projectId: string, path: string): void { + this.projectPaths.set(projectId, path); + } + + async createProject(name: string): Promise { + const newId = this.generateUniqueId('p', this.projects); + const newProject: Project = { + id: newId, + name: name + }; + this.projects.push(newProject); + return newId; + } + + updateProjectName(projectId: string, newName: string): boolean { + const project = this.projects.find(p => p.id === projectId); + if (project) { + project.name = newName; + return true; + } + return false; + } + + deleteProject(projectId: string): boolean { + const project = this.projects.find(p => p.id === projectId); + if (!project) return false; + + // 先把要删的 id 都算出来,再统一过滤 + const relatedAircrafts = this.aircrafts.filter(a => a.projectId === projectId); + const aircraftIds = relatedAircrafts.map(a => a.id); + + const relatedContainers = this.containers.filter(c => aircraftIds.includes(c.aircraftId)); + const containerIds = relatedContainers.map(c => c.id); + + // 真正删除数据 + this.projects = this.projects.filter(p => p.id !== projectId); + this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); + this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + + this.projectPaths.delete(projectId); + + return true; + } + + // =============== 飞行器相关方法 =============== + + getAircraftsByProject(projectId: string): Aircraft[] { + return this.aircrafts.filter(a => a.projectId === projectId); + } + + async createAircraft(name: string, projectId: string): Promise { + const newId = this.generateUniqueId('a', this.aircrafts); + const newAircraft: Aircraft = { + id: newId, + name: name, + projectId: projectId + }; + this.aircrafts.push(newAircraft); + + // 创建飞行器目录 + await this.createAircraftDirectory(newAircraft); + return newId; + } + + updateAircraftName(aircraftId: string, newName: string): boolean { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (aircraft) { + aircraft.name = newName; + return true; + } + return false; + } + + deleteAircraft(aircraftId: string): boolean { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (!aircraft) return false; + + // ⚠️ 修正点:先在删除 containers 之前,算出要删的 containerIds + const relatedContainers = this.containers.filter(c => c.aircraftId === aircraftId); + const containerIds = relatedContainers.map(c => c.id); + + // 删除飞机自身和容器 + this.aircrafts = this.aircrafts.filter(a => a.id !== aircraftId); + this.containers = this.containers.filter(c => c.aircraftId !== aircraftId); + + // 再删关联的 config 和 moduleFolder + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + + return true; + } + + // =============== 容器相关方法 =============== + + getContainersByAircraft(aircraftId: string): Container[] { + return this.containers.filter(c => c.aircraftId === aircraftId); + } + + async createContainer(name: string, aircraftId: string): Promise { + const newId = this.generateUniqueId('c', this.containers); + const newContainer: Container = { + id: newId, + name: name, + aircraftId: aircraftId + }; + this.containers.push(newContainer); + + await this.createContainerDirectory(newContainer); + await this.createDefaultConfigs(newContainer); + + return newId; + } + + updateContainerName(containerId: string, newName: string): boolean { + const container = this.containers.find(c => c.id === containerId); + if (container) { + container.name = newName; + return true; + } + return false; + } + + deleteContainer(containerId: string): boolean { + const container = this.containers.find(c => c.id === containerId); + if (!container) return false; + + this.containers = this.containers.filter(c => c.id !== containerId); + this.configs = this.configs.filter(cfg => cfg.containerId !== containerId); + this.moduleFolders = this.moduleFolders.filter(folder => folder.containerId !== containerId); + + return true; + } + + // =============== 配置相关方法 =============== + + getConfigsByContainer(containerId: string): Config[] { + return this.configs.filter(cfg => cfg.containerId === containerId); + } + + getConfig(configId: string): Config | undefined { + return this.configs.find(c => c.id === configId); + } + + async createConfig(name: string, containerId: string): Promise { + const newId = this.generateUniqueId('cfg', this.configs); + const newConfig: Config = { + id: newId, + name: name, + fileName: name.toLowerCase().replace(/\s+/g, '_'), + content: `# ${name} 配置文件\n# 创建时间: ${new Date().toLocaleString()}\n# 您可以在此编辑配置内容\n\n`, + containerId: containerId + }; + this.configs.push(newConfig); + + await this.ensureContainerDirectoryExists(containerId); + return newId; + } + + updateConfigName(configId: string, newName: string): boolean { + const config = this.configs.find(c => c.id === configId); + if (config) { + config.name = newName; + return true; + } + return false; + } + + deleteConfig(configId: string): boolean { + const config = this.configs.find(c => c.id === configId); + if (!config) return false; + + this.configs = this.configs.filter(c => c.id !== configId); + return true; + } + + // =============== 模块文件夹相关方法 =============== + + getModuleFoldersByContainer(containerId: string): ModuleFolder[] { + return this.moduleFolders.filter(folder => folder.containerId === containerId); + } + + getModuleFolder(folderId: string): ModuleFolder | undefined { + return this.moduleFolders.find(f => f.id === folderId); + } + + addModuleFolder(folder: ModuleFolder): void { + this.moduleFolders.push(folder); + } + + updateModuleFolder(folderId: string, updates: Partial): boolean { + const folderIndex = this.moduleFolders.findIndex(f => f.id === folderId); + if (folderIndex === -1) return false; + + this.moduleFolders[folderIndex] = { + ...this.moduleFolders[folderIndex], + ...updates + }; + return true; + } + + deleteModuleFolder(folderId: string): boolean { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder) return false; + + this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); + return true; + } + + renameModuleFolder(folderId: string, newName: string): boolean { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder) return false; + + const oldName = folder.localPath.split('/').pop() || ''; + folder.localPath = folder.localPath.replace(/\/[^/]+$/, '/' + newName); + return true; + } + + // =============== 文件系统操作 =============== + + private async createAircraftDirectory(aircraft: Aircraft): Promise { + try { + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) { + console.warn('未找到项目路径,跳过创建飞行器目录'); + return; + } + + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + await vscode.workspace.fs.createDirectory(aircraftDir); + console.log(`✅ 创建飞行器目录: ${aircraftDir.fsPath}`); + + } catch (error) { + console.error(`创建飞行器目录失败: ${error}`); + } + } + + private async createContainerDirectory(container: Container): Promise { + try { + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + if (!aircraft) { + console.warn('未找到对应的飞行器,跳过创建容器目录'); + return; + } + + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) { + console.warn('未找到项目路径,跳过创建容器目录'); + return; + } + + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); + + await vscode.workspace.fs.createDirectory(aircraftDir); + await vscode.workspace.fs.createDirectory(containerDir); + console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); + + } catch (error) { + console.error(`创建容器目录失败: ${error}`); + } + } + + private async ensureContainerDirectoryExists(containerId: string): Promise { + try { + const container = this.containers.find(c => c.id === containerId); + if (!container) return; + + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + if (!aircraft) return; + + const projectPath = this.projectPaths.get(aircraft.projectId); + if (!projectPath) return; + + const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); + const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); + + await vscode.workspace.fs.createDirectory(aircraftDir); + await vscode.workspace.fs.createDirectory(containerDir); + + } catch (error) { + console.error(`确保容器目录存在失败: ${error}`); + } + } + + private async createDefaultConfigs(container: Container): Promise { + this.configs.push({ + id: this.generateUniqueId('cfg', this.configs), + name: '配置1', + fileName: 'dockerfile', + content: `# ${container.name} 的 Dockerfile\nFROM ubuntu:20.04\n\n# 设置工作目录\nWORKDIR /app\n\n# 复制文件\nCOPY . .\n\n# 安装依赖\nRUN apt-get update && apt-get install -y \\\n python3 \\\n python3-pip\n\n# 暴露端口\nEXPOSE 8080\n\n# 启动命令\nCMD ["python3", "app.py"]`, + containerId: container.id + }); + + this.configs.push({ + id: this.generateUniqueId('cfg', this.configs), + name: '配置2', + fileName: 'docker-compose.yml', + content: `# ${container.name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${container.name.toLowerCase().replace(/\s+/g, '-')}:\n build: .\n container_name: ${container.name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, + containerId: container.id + }); + } + + // =============== 数据持久化 =============== + + async saveCurrentProjectData(projectId: string): Promise { + try { + const projectPath = this.projectPaths.get(projectId); + if (!projectPath) { + console.warn('未找到项目存储路径,数据将不会保存'); + return false; + } + + const data = this.getProjectData(projectId); + return await StorageService.saveProjectData(projectPath, data); + } catch (error) { + console.error('保存项目数据失败:', error); + return false; + } + } + + async loadProjectData(projectPath: string): Promise { + try { + const data = await StorageService.loadProjectData(projectPath); + if (!data) { + return null; + } + + const projectId = data.projects[0]?.id; + if (!projectId) { + return null; + } + + // 先根据旧的 projectId 算出要清理的 aircraft / container / config / moduleFolder + const existingAircrafts = this.aircrafts.filter(a => a.projectId === projectId); + const aircraftIds = existingAircrafts.map(a => a.id); + + const existingContainers = this.containers.filter(c => aircraftIds.includes(c.aircraftId)); + const containerIds = existingContainers.map(c => c.id); + + // 清理旧数据(同一个 projectId 的) + this.projects = this.projects.filter(p => p.id !== projectId); + this.aircrafts = this.aircrafts.filter(a => a.projectId !== projectId); + this.containers = this.containers.filter(c => !aircraftIds.includes(c.aircraftId)); + this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId)); + this.moduleFolders = this.moduleFolders.filter(folder => !containerIds.includes(folder.containerId)); + + // 加载新数据 + this.projects.push(...data.projects); + this.aircrafts.push(...data.aircrafts); + this.containers.push(...data.containers); + this.configs.push(...data.configs); + this.moduleFolders.push(...data.moduleFolders); + + this.projectPaths.set(projectId, projectPath); + return projectId; + } catch (error) { + console.error('加载项目数据失败:', error); + return null; + } + } + + private getProjectData(projectId: string): any { + return { + projects: [this.projects.find(p => p.id === projectId)!], + aircrafts: this.aircrafts.filter(a => a.projectId === projectId), + containers: this.containers.filter(c => { + const aircraft = this.aircrafts.find(a => a.id === c.aircraftId); + return aircraft && aircraft.projectId === projectId; + }), + configs: this.configs.filter(cfg => { + const container = this.containers.find(c => c.id === cfg.containerId); + if (!container) return false; + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + return aircraft && aircraft.projectId === projectId; + }), + moduleFolders: this.moduleFolders.filter(folder => { + const container = this.containers.find(c => c.id === folder.containerId); + if (!container) return false; + const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); + return aircraft && aircraft.projectId === projectId; + }) + }; + } + + // =============== 工具方法 =============== + + getModuleFolderFullPath(folder: ModuleFolder): string | null { + 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); + } + + getConfigFilePath(configId: string): string | null { + const config = this.configs.find(c => c.id === configId); + if (!config) return null; + + const container = this.containers.find(c => c.id === config.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; + + return path.join(projectPath, aircraft.name, container.name, config.fileName); + } + + async deleteConfigFileFromDisk(configId: string): Promise { + const filePath = this.getConfigFilePath(configId); + if (!filePath) return false; + + try { + if (fs.existsSync(filePath)) { + await fs.promises.unlink(filePath); + console.log(`✅ 已删除配置文件: ${filePath}`); + return true; + } + return false; + } catch (error) { + console.error(`删除配置文件失败: ${error}`); + return false; + } + } +} diff --git a/src/panels/services/StorageService.ts b/src/panels/services/StorageService.ts new file mode 100644 index 0000000..02a8040 --- /dev/null +++ b/src/panels/services/StorageService.ts @@ -0,0 +1,135 @@ +// src/panels/services/StorageService.ts +import * as vscode from 'vscode'; +import * as fs from 'fs'; +import * as path from 'path'; +import { ProjectData } from '../types/CommonTypes'; + +/** + * 数据存储服务 + * 负责项目的持久化存储和加载 + */ +export class StorageService { + /** + * 加载项目数据 + */ + static async loadProjectData(projectPath: string): Promise { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + + try { + await vscode.workspace.fs.stat(dataUri); + } catch { + console.warn('未找到项目数据文件'); + return null; + } + + const fileData = await vscode.workspace.fs.readFile(dataUri); + const dataStr = new TextDecoder().decode(fileData); + const data: ProjectData = JSON.parse(dataStr); + + return data; + } catch (error) { + console.error('加载项目数据失败:', error); + return null; + } + } + + /** + * 保存项目数据 + */ + static async saveProjectData(projectPath: string, data: ProjectData): Promise { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + + const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); + await vscode.workspace.fs.writeFile(dataUri, uint8Array); + + console.log('✅ 项目数据已保存'); + return true; + } catch (error) { + console.error('保存项目数据失败:', error); + return false; + } + } + + /** + * 检查项目路径是否有数据 + */ + static async checkProjectPathHasData(projectPath: string): Promise { + try { + const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json'); + await vscode.workspace.fs.stat(dataUri); + return true; + } catch { + return false; + } + } + + /** + * 加载仓库配置 + */ + static async loadRepoConfigs(extensionUri: vscode.Uri): Promise { + try { + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + + if (!fs.existsSync(configPath)) { + return []; + } + + const content = await fs.promises.readFile(configPath, 'utf8'); + if (!content.trim()) { + return []; + } + + const parsed = JSON.parse(content); + if (Array.isArray(parsed)) { + return parsed; + } else if (parsed && Array.isArray(parsed.repos)) { + return parsed.repos; + } else { + return []; + } + } catch (error) { + console.error('加载仓库配置失败:', error); + return []; + } + } + + /** + * 确保仓库配置文件存在 + */ + static async ensureRepoConfigFileExists(extensionUri: vscode.Uri): Promise { + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + if (!fs.existsSync(configPath)) { + const defaultContent = JSON.stringify( + { + repos: [ + { + name: 'example-repo', + url: 'https://github.com/username/repo.git', + username: '', + token: '' + } + ] + }, + null, + 2 + ); + await fs.promises.writeFile(configPath, defaultContent, 'utf8'); + } + } + + /** + * 打开仓库配置文件 + */ + static async openRepoConfig(extensionUri: vscode.Uri): Promise { + try { + await StorageService.ensureRepoConfigFileExists(extensionUri); + const configPath = path.join(extensionUri.fsPath, 'dcsp-repos.json'); + const doc = await vscode.workspace.openTextDocument(vscode.Uri.file(configPath)); + await vscode.window.showTextDocument(doc); + } catch (error) { + vscode.window.showErrorMessage(`打开仓库配置文件失败: ${error}`); + } + } +} \ No newline at end of file diff --git a/src/panels/types/CommonTypes.ts b/src/panels/types/CommonTypes.ts index aebb9ed..9d0a126 100755 --- a/src/panels/types/CommonTypes.ts +++ b/src/panels/types/CommonTypes.ts @@ -1,7 +1,10 @@ // src/panels/types/CommonTypes.ts // 统一的核心类型定义 +// ============================================= // 基础实体接口 +// ============================================= + export interface Project { id: string; name: string; @@ -27,22 +30,27 @@ export interface Config { containerId: string; } -// 统一的模块文件夹接口 +export type ModuleFolderType = 'git' | 'local'; + +// 模块文件夹接口 export interface ModuleFolder { id: string; name: string; - type: 'git' | 'local'; + type: ModuleFolderType; localPath: string; containerId: string; uploaded?: boolean; - /** 🟦 记录原始文件夹名(用于判断用户是否重命名) */ + /** 记录原始文件夹名(用于判断用户是否重命名) */ originalFolderName?: string; - /** 🟦 记录创建时使用的仓库 URL(用于判断是否同仓库) */ + /** 记录创建时使用的仓库 URL(用于判断是否同仓库) */ originalRepoUrl?: string; } +// ============================================= +// 数据模型接口 +// ============================================= // 完整数据模型接口 export interface ProjectData { @@ -53,10 +61,115 @@ export interface ProjectData { moduleFolders: ModuleFolder[]; } -// Git文件树结构 +// ============================================= +// Git 相关类型 +// ============================================= + export interface GitFileTree { name: string; type: 'file' | 'folder'; path: string; children?: GitFileTree[]; } + +export interface GitBranch { + name: string; + isCurrent: boolean; + selected?: boolean; +} + +// ============================================= +// 服务配置类型 +// ============================================= + +// 仓库配置项 +export interface RepoConfigItem { + name: string; + url: string; + username?: string; + token?: string; +} + +// ============================================= +// 树状结构类型 +// ============================================= + +// 树状分支节点接口 +export interface BranchTreeNode { + name: string; + fullName: string; + isLeaf: boolean; + children: BranchTreeNode[]; + level: number; + expanded?: boolean; + branch?: GitBranch; +} + +// ============================================= +// 状态类型 +// ============================================= + +// 视图状态类型 +export type ViewType = 'projects' | 'aircrafts' | 'containers' | 'configs'; + +// ============================================= +// 工具类型 +// ============================================= + +// 可选属性类型 +export type PartialBy = Omit & Partial>; + +// 可空类型 +export type Nullable = T | null; +export type Optional = T | undefined; + +// ============================================= +// 事件消息类型基础 +// ============================================= + +export interface BaseMessage { + type: string; + [key: string]: any; +} + +// ID参数类型 +export interface WithId { + id: string; +} + +export interface WithProjectId { + projectId: string; +} + +export interface WithAircraftId { + aircraftId: string; +} + +export interface WithContainerId { + containerId: string; +} + +export interface WithConfigId { + configId: string; +} + +export interface WithModuleFolderId { + folderId: string; +} + +// ============================================= +// 文件操作类型 +// ============================================= + +export interface FileOperationResult { + success: boolean; + message?: string; + error?: any; +} + +export interface DirectoryInfo { + path: string; + exists: boolean; + isEmpty: boolean; + files: string[]; +} \ No newline at end of file diff --git a/src/panels/views/AircraftView.ts b/src/panels/views/AircraftView.ts old mode 100644 new mode 100755 index 31c07a4..f6cb493 --- a/src/panels/views/AircraftView.ts +++ b/src/panels/views/AircraftView.ts @@ -6,8 +6,6 @@ export class AircraftView extends BaseView { render(data?: { aircrafts: AircraftViewData[] }): string { const aircrafts = data?.aircrafts || []; - console.log('AircraftView 渲染数据:', aircrafts); - const aircraftsHtml = aircrafts.map(aircraft => ` @@ -62,7 +60,7 @@ export class AircraftView extends BaseView { display: flex; align-items: center; gap: 6px; - margin: 0 auto; /* 确保按钮在容器内居中 */ + margin: 0 auto; } .btn-new:hover { background: var(--vscode-button-hoverBackground); @@ -76,7 +74,6 @@ export class AircraftView extends BaseView { .aircraft-name:hover { background: var(--vscode-input-background); } - /* 专门为新建按钮的容器添加样式 */ .new-button-container { text-align: center; padding: 20px; @@ -99,7 +96,6 @@ export class AircraftView extends BaseView { ${aircraftsHtml} - @@ -188,88 +184,8 @@ export class AircraftView extends BaseView { } ); } - - // 对话框函数 - function showConfirmDialog(title, message, onConfirm, onCancel) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'confirmModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - window.confirmCallback = function(result) { - if (result && onConfirm) { - onConfirm(); - } else if (!result && onCancel) { - onCancel(); - } - delete window.confirmCallback; - }; - } - - function closeConfirmDialog(result) { - const modal = document.getElementById('confirmModal'); - if (modal) { - modal.remove(); - } - if (window.confirmCallback) { - window.confirmCallback(result); - } - } - - function showPromptDialog(title, message, defaultValue, onConfirm) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'promptModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - setTimeout(() => { - const input = document.getElementById('promptInput'); - if (input) { - input.focus(); - input.select(); - } - }, 100); - - window.promptCallback = onConfirm; - } - - function closePromptDialog(result) { - const modal = document.getElementById('promptModal'); - if (modal) { - modal.remove(); - } - if (window.promptCallback) { - window.promptCallback(result); - } - delete window.promptCallback; - } `; } -} +} \ No newline at end of file diff --git a/src/panels/views/BaseView.ts b/src/panels/views/BaseView.ts index cbd17be..704bb25 100755 --- a/src/panels/views/BaseView.ts +++ b/src/panels/views/BaseView.ts @@ -1,3 +1,4 @@ +// src/panels/views/BaseView.ts import * as vscode from 'vscode'; export abstract class BaseView { @@ -9,7 +10,10 @@ export abstract class BaseView { abstract render(data?: any): string; - protected getStyles(): string { + /** + * 获取通用的样式和脚本 + */ + protected getBaseStylesAndScripts(): string { return ` + `; + } + + /** + * 获取仓库选择对话框的脚本(仅ConfigView需要) + */ + protected getRepoSelectScript(): string { + return ` + `; } -} + + /** + * 获取样式(被子类覆盖) + */ + protected getStyles(): string { + return this.getBaseStylesAndScripts(); + } +} \ No newline at end of file diff --git a/src/panels/views/ConfigView.ts b/src/panels/views/ConfigView.ts index ee90f98..e8f0b75 100755 --- a/src/panels/views/ConfigView.ts +++ b/src/panels/views/ConfigView.ts @@ -2,22 +2,12 @@ import { BaseView } from './BaseView'; import { ContainerConfigData, ConfigViewData } from '../types/ViewTypes'; import { ModuleFolder } from '../types/CommonTypes'; -// Git 分支接口 interface GitBranch { name: string; isCurrent: boolean; selected?: boolean; } -// Git 文件树接口 -interface GitFileTree { - name: string; - type: 'file' | 'folder'; - path: string; - children?: GitFileTree[]; -} - -// 树状分支节点接口 interface BranchTreeNode { name: string; fullName: string; @@ -32,7 +22,7 @@ export class ConfigView extends BaseView { render(data?: ContainerConfigData & { moduleFolders?: ModuleFolder[]; currentModuleFolder?: ModuleFolder; - moduleFolderFileTree?: GitFileTree[]; + moduleFolderFileTree?: any[]; moduleFolderLoading?: boolean; gitBranches?: GitBranch[]; }): string { @@ -44,7 +34,7 @@ export class ConfigView extends BaseView { const moduleFolderLoading = data?.moduleFolderLoading || false; const gitBranches = data?.gitBranches || []; - // 生成配置列表的 HTML - 包含配置文件和模块文件夹 + // 生成配置列表的 HTML const configsHtml = configs.map((config: ConfigViewData) => ` @@ -61,10 +51,9 @@ export class ConfigView extends BaseView { `).join(''); - // 生成模块文件夹的 HTML - 按类别分类显示 + // 生成模块文件夹的 HTML const moduleFoldersHtml = moduleFolders.map((folder: ModuleFolder) => { const icon = '📁'; - // 根据类型和上传状态确定类别显示 let category = folder.type === 'git' ? 'git' : 'local'; if (folder.uploaded) { category += '(已上传)'; @@ -75,14 +64,12 @@ export class ConfigView extends BaseView { return ` - ${icon} ${folder.name} ${category} - 📄 ${fileName} @@ -96,7 +83,7 @@ export class ConfigView extends BaseView { `; }).join(''); - // 生成分支选择的 HTML - 使用树状结构(首次渲染可以为空,后续通过 message 更新) + // 生成分支选择的 HTML const branchesHtml = gitBranches.length > 0 ? this.generateBranchesTreeHtml(gitBranches) : ''; return ` @@ -105,7 +92,8 @@ export class ConfigView extends BaseView { 配置管理 - ${this.getStyles()} + ${this.getBaseStylesAndScripts()} + ${this.getRepoSelectScript()} @@ -357,12 +335,11 @@ export class ConfigView extends BaseView { `; diff --git a/src/panels/views/ProjectView.ts b/src/panels/views/ProjectView.ts index 9aee099..61378a6 100755 --- a/src/panels/views/ProjectView.ts +++ b/src/panels/views/ProjectView.ts @@ -1,3 +1,4 @@ +// src/panels/views/ProjectView.ts import { BaseView } from './BaseView'; import { ProjectViewData } from '../types/ViewTypes'; @@ -136,13 +137,11 @@ export class ProjectView extends BaseView { function configureProject(projectId, projectName, isConfigured) { if (isConfigured) { - // 已配置的项目直接打开 vscode.postMessage({ type: 'openProject', projectId: projectId }); } else { - // 未配置的项目需要设置路径 vscode.postMessage({ type: 'configureProject', projectId: projectId, @@ -189,7 +188,7 @@ export class ProjectView extends BaseView { ); } - // 项目名称编辑功能 - 修复版本 + // 项目名称编辑功能 document.addEventListener('DOMContentLoaded', function() { document.addEventListener('click', function(event) { if (event.target.classList.contains('project-name')) { @@ -220,88 +219,8 @@ export class ProjectView extends BaseView { } ); } - - // 对话框函数 - 只保留一份 - function showConfirmDialog(title, message, onConfirm, onCancel) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'confirmModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - window.confirmCallback = function(result) { - if (result && onConfirm) { - onConfirm(); - } else if (!result && onCancel) { - onCancel(); - } - delete window.confirmCallback; - }; - } - - function closeConfirmDialog(result) { - const modal = document.getElementById('confirmModal'); - if (modal) { - modal.remove(); - } - if (window.confirmCallback) { - window.confirmCallback(result); - } - } - - function showPromptDialog(title, message, defaultValue, onConfirm) { - const overlay = document.createElement('div'); - overlay.className = 'modal-overlay'; - overlay.id = 'promptModal'; - - overlay.innerHTML = \` - - \`; - - document.body.appendChild(overlay); - - setTimeout(() => { - const input = document.getElementById('promptInput'); - if (input) { - input.focus(); - input.select(); - } - }, 100); - - window.promptCallback = onConfirm; - } - - function closePromptDialog(result) { - const modal = document.getElementById('promptModal'); - if (modal) { - modal.remove(); - } - if (window.promptCallback) { - window.promptCallback(result); - } - delete window.promptCallback; - } `; } -} +} \ No newline at end of file