diff --git a/out/panels/ConfigPanel.js b/out/panels/ConfigPanel.js index b7373d0..5510477 100644 --- a/out/panels/ConfigPanel.js +++ b/out/panels/ConfigPanel.js @@ -36,7 +36,13 @@ const ProjectView_1 = require("./views/ProjectView"); const AircraftView_1 = require("./views/AircraftView"); const ContainerView_1 = require("./views/ContainerView"); const ConfigView_1 = require("./views/ConfigView"); +// ============================================= +// 主面板类 +// ============================================= class ConfigPanel { + // ============================================= + // 公共方法 + // ============================================= static createOrShow(extensionUri) { const column = vscode.window.activeTextEditor?.viewColumn || vscode.ViewColumn.One; if (ConfigPanel.currentPanel) { @@ -51,6 +57,7 @@ class ConfigPanel { ConfigPanel.currentPanel = new ConfigPanel(panel, extensionUri); } constructor(panel, extensionUri) { + // 视图状态管理 this.currentView = 'projects'; this.currentProjectId = ''; this.currentAircraftId = ''; @@ -61,17 +68,15 @@ class ConfigPanel { this.aircrafts = []; this.containers = []; this.configs = []; - this.moduleFolders = []; // 统一的模块文件夹数据 - // Git 文件树 + this.moduleFolders = []; this.currentModuleFolderFileTree = []; - // 项目存储路径映射 this.projectPaths = new Map(); - // Webview 状态跟踪 + // 状态管理 this.isWebviewDisposed = false; this.panel = panel; this.extensionUri = extensionUri; - this.isWebviewDisposed = false; // 初始化状态 - // 初始化各个视图 + this.isWebviewDisposed = false; + // 初始化视图 this.projectView = new ProjectView_1.ProjectView(extensionUri); this.aircraftView = new AircraftView_1.AircraftView(extensionUri); this.containerView = new ContainerView_1.ContainerView(extensionUri); @@ -79,160 +84,41 @@ class ConfigPanel { this.updateWebview(); this.setupMessageListener(); this.panel.onDidDispose(() => { - this.isWebviewDisposed = true; // 标记为已销毁 + this.isWebviewDisposed = true; ConfigPanel.currentPanel = undefined; }); } + // ============================================= + // 工具方法 - 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}`; + } + // ============================================= + // Webview 消息处理 + // ============================================= setupMessageListener() { this.panel.webview.onDidReceiveMessage(async (data) => { console.log('📨 收到Webview消息:', data); - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,忽略消息'); return; } try { - switch (data.type) { - case 'openExistingProject': - await this.openExistingProject(); - break; - case 'configureProject': - const selectedPath = await this.selectProjectPath(data.projectId, data.projectName); - if (selectedPath) { - this.currentView = 'aircrafts'; - this.currentProjectId = data.projectId; - this.updateWebview(); - } - break; - case 'openProject': - // 已配置的项目直接打开 - this.currentView = 'aircrafts'; - this.currentProjectId = data.projectId; - this.updateWebview(); - break; - case 'openAircraftConfig': - this.currentView = 'containers'; - this.currentProjectId = data.projectId; - this.currentAircraftId = data.aircraftId; - this.updateWebview(); - break; - case 'openContainerConfig': - this.currentView = 'configs'; - this.currentContainerId = data.containerId; - this.updateWebview(); - break; - // 修复返回按钮的消息处理 - case 'goBackToProjects': - this.currentView = 'projects'; - // 清空当前选择的ID - this.currentProjectId = ''; - this.currentAircraftId = ''; - this.currentContainerId = ''; - this.currentModuleFolderId = ''; - this.updateWebview(); - break; - case 'goBackToAircrafts': - this.currentView = 'aircrafts'; - // 保持 currentProjectId,清空其他ID - this.currentAircraftId = ''; - this.currentContainerId = ''; - this.updateWebview(); - break; - case 'goBackToContainers': - this.currentView = 'containers'; - // 保持 currentProjectId 和 currentAircraftId,清空 currentContainerId - this.currentContainerId = ''; - this.updateWebview(); - break; - case 'updateProjectName': - await this.updateProjectName(data.projectId, data.name); - break; - case 'createProject': - await this.createProject(data.name); - break; - case 'updateAircraftName': - await this.updateAircraftName(data.aircraftId, data.name); - break; - case 'createAircraft': - await this.createAircraft(data.name); - break; - case 'updateContainerName': - await this.updateContainerName(data.containerId, data.name); - break; - case 'createContainer': - await this.createContainer(data.name); - break; - case 'updateConfigName': - await this.updateConfigName(data.configId, data.name); - break; - case 'createConfig': - await this.createConfig(data.name); - break; - case 'deleteProject': - await this.deleteProject(data.projectId); - break; - case 'deleteAircraft': - await this.deleteAircraft(data.aircraftId); - break; - case 'deleteContainer': - await this.deleteContainer(data.containerId); - break; - case 'deleteConfig': - await this.deleteConfig(data.configId); - break; - // Git 仓库管理功能 - case 'fetchBranches': - console.log('🌿 获取分支列表:', data.url); - await this.fetchBranches(data.url); - break; - case 'cloneBranches': - console.log('🚀 克隆选中的分支:', data); - await this.cloneBranches(data.url, data.branches); - break; - case 'cancelBranchSelection': - console.log('❌ 取消分支选择'); - this.updateWebview(); - break; - case 'loadModuleFolder': - await this.loadModuleFolder(data.folderId); - break; - case 'syncGitModuleFolder': - await this.syncGitModuleFolder(data.folderId); - break; - case 'deleteModuleFolder': - await this.deleteModuleFolder(data.folderId); - break; - case 'importGitFile': - await this.importGitFile(data.filePath); - break; - case 'openModuleFolderInVSCode': - await this.openTheModuleFolder(data.moduleType, data.folderId); - break; - case 'openConfigFileInVSCode': - await this.openConfigFileInVSCode(data.configId); - break; - case 'mergeConfigs': - await this.mergeConfigs(data.configIds, data.displayName, data.folderName); - break; - case 'deleteMergedFolder': - await this.deleteModuleFolder(data.folderId); - break; - case 'openMergedFolderInVSCode': - await this.openTheModuleFolder('local', data.folderId); - break; - case 'loadMergedFolder': - await this.openTheModuleFolder('local', data.folderId); - break; - case 'openTheModuleFolder': - await this.openTheModuleFolder(data.moduleType, data.id); - break; - case 'uploadGitModuleFolder': - await this.uploadGitModuleFolder(data.folderId, data.username, data.password); - break; - case 'uploadLocalModuleFolder': - await this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName); - break; - } + await this.handleWebviewMessage(data); } catch (error) { console.error('处理 Webview 消息时出错:', error); @@ -242,90 +128,454 @@ class ConfigPanel { } }); } - // === 目录创建方法 === - /** - * 创建飞行器目录 - */ - 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}`); + async handleWebviewMessage(data) { + const messageHandlers = { + // 导航相关 + 'openExistingProject': () => this.openExistingProject(), + 'configureProject': (data) => this.handleConfigureProject(data), + 'openProject': (data) => this.handleOpenProject(data), + 'openAircraftConfig': (data) => this.handleOpenAircraftConfig(data), + 'openContainerConfig': (data) => this.handleOpenContainerConfig(data), + 'goBackToProjects': () => this.handleGoBackToProjects(), + 'goBackToAircrafts': () => this.handleGoBackToAircrafts(), + 'goBackToContainers': () => this.handleGoBackToContainers(), + // 项目管理 + 'updateProjectName': (data) => this.updateProjectName(data.projectId, data.name), + 'createProject': (data) => this.createProject(data.name), + 'deleteProject': (data) => this.deleteProject(data.projectId), + // 飞行器管理 + 'updateAircraftName': (data) => this.updateAircraftName(data.aircraftId, data.name), + 'createAircraft': (data) => this.createAircraft(data.name), + 'deleteAircraft': (data) => this.deleteAircraft(data.aircraftId), + // 容器管理 + 'updateContainerName': (data) => this.updateContainerName(data.containerId, data.name), + 'createContainer': (data) => this.createContainer(data.name), + 'deleteContainer': (data) => this.deleteContainer(data.containerId), + // 配置管理 + 'updateConfigName': (data) => this.updateConfigName(data.configId, data.name), + 'createConfig': (data) => this.createConfig(data.name), + 'deleteConfig': (data) => this.deleteConfig(data.configId), + 'openConfigFileInVSCode': (data) => this.openConfigFileInVSCode(data.configId), + 'mergeConfigs': (data) => this.mergeConfigs(data.configIds, data.displayName, data.folderName), + // Git 仓库管理 + 'fetchBranches': (data) => this.fetchBranches(data.url), + 'cloneBranches': (data) => this.cloneBranches(data.url, data.branches), + 'cancelBranchSelection': () => this.handleCancelBranchSelection(), + // 模块文件夹管理 + 'loadModuleFolder': (data) => this.loadModuleFolder(data.folderId), + 'syncGitModuleFolder': (data) => this.syncGitModuleFolder(data.folderId), + 'deleteModuleFolder': (data) => this.deleteModuleFolder(data.folderId), + 'importGitFile': (data) => this.importGitFile(data.filePath), + 'openTheModuleFolder': (data) => this.openTheModuleFolder(data.moduleType, data.id), + // 上传功能 + 'uploadGitModuleFolder': (data) => this.uploadGitModuleFolder(data.folderId, data.username, data.password), + 'uploadLocalModuleFolder': (data) => this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName) + }; + const handler = messageHandlers[data.type]; + if (handler) { + await handler(data); } - catch (error) { - console.error(`创建飞行器目录失败: ${error}`); + else { + console.warn(`未知的消息类型: ${data.type}`); } } - /** - * 创建容器目录 - */ - async createContainerDirectory(container) { + // ============================================= + // 导航处理方法 + // ============================================= + async handleConfigureProject(data) { + const selectedPath = await this.selectProjectPath(data.projectId, data.projectName); + if (selectedPath) { + this.currentView = 'aircrafts'; + this.currentProjectId = data.projectId; + this.updateWebview(); + } + } + async handleOpenProject(data) { + this.currentView = 'aircrafts'; + this.currentProjectId = data.projectId; + this.updateWebview(); + } + async handleOpenAircraftConfig(data) { + this.currentView = 'containers'; + this.currentProjectId = data.projectId; + this.currentAircraftId = data.aircraftId; + this.updateWebview(); + } + async handleOpenContainerConfig(data) { + this.currentView = 'configs'; + this.currentContainerId = data.containerId; + this.updateWebview(); + } + async handleGoBackToProjects() { + this.currentView = 'projects'; + this.currentProjectId = ''; + this.currentAircraftId = ''; + this.currentContainerId = ''; + this.currentModuleFolderId = ''; + this.updateWebview(); + } + async handleGoBackToAircrafts() { + this.currentView = 'aircrafts'; + this.currentAircraftId = ''; + this.currentContainerId = ''; + this.updateWebview(); + } + async handleGoBackToContainers() { + this.currentView = 'containers'; + this.currentContainerId = ''; + this.updateWebview(); + } + async handleCancelBranchSelection() { + console.log('❌ 取消分支选择'); + this.updateWebview(); + } + // ============================================= + // 项目管理方法 + // ============================================= + async updateProjectName(projectId, newName) { + const project = this.projects.find(p => p.id === projectId); + if (project) { + project.name = newName; + vscode.window.showInformationMessage(`项目名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + async createProject(name) { + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('p', this.projects); + const newProject = { + id: newId, + name: name + }; + this.projects.push(newProject); + // 设置当前项目 + 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(); + } + // ============================================= + // 飞行器管理方法 + // ============================================= + async updateAircraftName(aircraftId, newName) { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (aircraft) { + aircraft.name = newName; + vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + async createAircraft(name) { + if (!this.currentProjectId) { + vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目'); + return; + } + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('a', this.aircrafts); + const newAircraft = { + id: newId, + name: name, + projectId: this.currentProjectId + }; + this.aircrafts.push(newAircraft); + await this.createAircraftDirectory(newAircraft); + 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(); + } + // ============================================= + // 容器管理方法 + // ============================================= + async updateContainerName(containerId, newName) { + const container = this.containers.find(c => c.id === containerId); + if (container) { + container.name = newName; + vscode.window.showInformationMessage(`容器名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + async createContainer(name) { + if (!this.currentAircraftId) { + vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器'); + return; + } + // 使用新的 ID 生成方法 + 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); + 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(); + } + // ============================================= + // 配置管理方法 + // ============================================= + async updateConfigName(configId, newName) { + const config = this.configs.find(c => c.id === configId); + if (config) { + config.name = newName; + vscode.window.showInformationMessage(`配置名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + async createConfig(name) { + // 使用新的 ID 生成方法 + 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); + vscode.window.showInformationMessage(`新建配置: ${name}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + async deleteConfig(configId) { + const config = this.configs.find(c => c.id === configId); + if (!config) + return; + const confirm = await vscode.window.showWarningMessage(`确定要删除配置文件 "${config.name}" 吗?这将同时删除磁盘上的文件。`, { modal: true }, '确定删除', '取消'); + if (confirm !== '确定删除') { + return; + } try { + this.configs = this.configs.filter(c => c.id !== configId); + await this.deleteConfigFileFromDisk(config); + vscode.window.showInformationMessage(`删除配置: ${config.name}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + catch (error) { + vscode.window.showErrorMessage(`删除配置文件失败: ${error}`); + } + } + async mergeConfigs(configIds, displayName, folderName) { + if (!this.currentContainerId) { + vscode.window.showErrorMessage('未找到当前容器'); + return; + } + if (configIds.length < 2) { + vscode.window.showErrorMessage('请至少选择两个配置文件进行合并'); + return; + } + try { + const container = this.containers.find(c => c.id === this.currentContainerId); 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('未找到项目路径,跳过创建容器目录'); + if (!container || !aircraft || !projectPath) { + vscode.window.showErrorMessage('未找到相关项目数据'); return; } - // 构建路径:项目路径/飞行器名/容器名 - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - // 确保飞行器目录存在 - try { - await vscode.workspace.fs.createDirectory(aircraftDir); + const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); + if (selectedConfigs.length !== configIds.length) { + vscode.window.showErrorMessage('部分配置文件未找到'); + return; } - catch (error) { - // 目录可能已存在,忽略错误 + // 创建合并文件夹并复制文件 + const mergeFolderPath = path.join(projectPath, aircraft.name, container.name, folderName); + await fs.promises.mkdir(mergeFolderPath, { recursive: true }); + for (const config of selectedConfigs) { + const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); + const targetPath = path.join(mergeFolderPath, config.fileName); + if (fs.existsSync(sourcePath)) { + await fs.promises.copyFile(sourcePath, targetPath); + } + else { + await fs.promises.writeFile(targetPath, config.content || ''); + } } - // 创建容器目录 - await vscode.workspace.fs.createDirectory(containerDir); - console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); + // 创建合并文件夹记录 + const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('local-', this.moduleFolders); + const newFolder = { + id: newId, + name: displayName, + type: 'local', + localPath: relativePath, + containerId: this.currentContainerId + }; + this.moduleFolders.push(newFolder); + // 删除原始配置文件 + for (const configId of configIds) { + await this.deleteConfigInternal(configId); + } + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`); + this.updateWebview(); } catch (error) { - console.error(`创建容器目录失败: ${error}`); + console.error('❌ 合并配置文件失败:', error); + vscode.window.showErrorMessage(`合并配置文件失败: ${error}`); } } - /** - * 确保容器目录存在 - */ - async ensureContainerDirectoryExists(containerId) { + // ============================================= + // Git 分支管理方法 + // ============================================= + async fetchBranches(url) { 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); + console.log('🌿 开始获取分支列表:', url); + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: '正在获取分支信息', + cancellable: false + }, async (progress) => { + progress.report({ increment: 0, message: '连接远程仓库...' }); + try { + progress.report({ increment: 30, message: '获取远程引用...' }); + const refs = await isomorphic_git_1.default.listServerRefs({ + http: node_1.default, + url: url + }); + 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 + }; + }); + if (branches.length === 0) { + throw new Error('未找到任何分支'); + } + progress.report({ increment: 80, message: '处理分支数据...' }); + // 构建分支树状结构 + const branchTree = this.buildBranchTree(branches); + // 发送分支数据到前端 + if (!this.isWebviewDisposed) { + this.panel.webview.postMessage({ + type: 'branchesFetched', + branches: branches, + branchTree: branchTree, + repoUrl: url + }); + } + progress.report({ increment: 100, message: '完成' }); + } + catch (error) { + console.error('❌ 使用 listServerRefs 获取分支失败:', error); + vscode.window.showErrorMessage(`获取分支失败: ${error}`); + } + }); } catch (error) { - console.error(`确保容器目录存在失败: ${error}`); + console.error('❌ 获取分支失败:', error); + vscode.window.showErrorMessage(`获取分支失败: ${error}`); } } - // === Git 仓库管理方法 === - /** - * 添加 Git 模块文件夹到容器目录 - */ + async cloneBranches(url, branches) { + try { + console.log('🚀 开始克隆分支:', { url, branches }); + let successCount = 0; + let failCount = 0; + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在克隆 ${branches.length} 个分支`, + cancellable: false + }, async (progress) => { + for (let i = 0; i < branches.length; i++) { + const branch = branches[i]; + const progressPercent = (i / branches.length) * 100; + progress.report({ + increment: progressPercent, + message: `克隆分支: ${branch} (${i + 1}/${branches.length})` + }); + console.log(`📥 开始克隆分支: ${branch}`); + try { + const folderNames = this.generateModuleFolderName(url, branch); + await this.addGitModuleFolder(url, folderNames.displayName, folderNames.folderName, branch); + successCount++; + console.log(`✅ 分支克隆成功: ${branch}`); + } + catch (error) { + failCount++; + console.error(`❌ 分支克隆失败: ${branch}`, error); + } + } + }); + // 显示最终结果 + if (failCount === 0) { + vscode.window.showInformationMessage(`成功克隆 ${successCount} 个分支`); + } + else { + vscode.window.showWarningMessage(`克隆完成: ${successCount} 个成功, ${failCount} 个失败`); + } + } + catch (error) { + console.error('❌ 克隆分支失败:', error); + vscode.window.showErrorMessage(`克隆分支失败: ${error}`); + } + } + // ============================================= + // 模块文件夹管理方法 + // ============================================= async addGitModuleFolder(url, displayName, folderName, branch) { try { - // 验证 URL if (!url || !url.startsWith('http')) { vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL'); return; @@ -334,30 +584,19 @@ class ConfigPanel { vscode.window.showErrorMessage('请先选择容器'); return; } - const folderId = 'git-' + Date.now(); - // 构建本地路径 const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - vscode.window.showErrorMessage('未找到项目路径'); + if (!container || !aircraft || !projectPath) { + vscode.window.showErrorMessage('未找到相关项目数据'); return; } - // 构建相对路径(从项目路径开始)- 使用 folderName 作为实际文件夹名 + // 使用新的 ID 生成方法 + const folderId = this.generateUniqueId('git-', this.moduleFolders); const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - // 完整路径用于实际操作 - 使用 folderName 作为实际文件夹名 const localPath = path.join(projectPath, aircraft.name, container.name, folderName); console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`); - console.log(`📁 相对路径: ${relativePath}`); - // 修复:检查是否已存在相同实际路径的模块文件夹,而不是显示名称 + // 检查是否已存在相同路径的模块文件夹 const existingFolder = this.moduleFolders.find(folder => folder.localPath === relativePath && folder.containerId === this.currentContainerId); if (existingFolder) { vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`); @@ -370,7 +609,6 @@ class ConfigPanel { localPath: relativePath, containerId: this.currentContainerId }; - // 显示进度 await vscode.window.withProgress({ location: vscode.ProgressLocation.Notification, title: `正在克隆仓库: ${displayName}`, @@ -398,7 +636,7 @@ class ConfigPanel { vscode.window.showInformationMessage('克隆操作已取消'); return; } - // 清空目录(除了 .git 文件夹,如果存在的话) + // 清空目录(除了 .git 文件夹) for (const item of dirContents) { const itemPath = path.join(localPath, item); if (item !== '.git') { @@ -443,17 +681,13 @@ class ConfigPanel { await this.saveCurrentProjectData(); console.log('✅ Git模块文件夹数据已保存到项目文件'); vscode.window.showInformationMessage(`Git 仓库克隆成功: ${displayName}`); - // 检查 Webview 状态后再加载文件树 + // 自动加载文件树 if (!this.isWebviewDisposed) { console.log('🌳 开始加载模块文件夹文件树...'); - // 自动加载文件树 this.currentModuleFolderId = folderId; await this.loadModuleFolderFileTree(folderId); console.log('✅ 模块文件夹文件树加载完成'); } - else { - console.log('⚠️ Webview 已被销毁,跳过文件树加载'); - } } catch (error) { console.error('❌ 在克隆过程中捕获错误:', error); @@ -468,7 +702,6 @@ class ConfigPanel { console.error('清理失败目录时出错:', cleanupError); } vscode.window.showErrorMessage(`克隆仓库失败: ${error}`); - // 重新抛出错误,让外部知道克隆失败 throw error; } }); @@ -478,9 +711,6 @@ class ConfigPanel { vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`); } } - /** - * 加载模块文件夹 - */ async loadModuleFolder(folderId) { this.currentModuleFolderId = folderId; const folder = this.moduleFolders.find(f => f.id === folderId); @@ -489,16 +719,12 @@ class ConfigPanel { } this.updateWebview(); } - /** - * 同步 Git 模块文件夹 - */ async syncGitModuleFolder(folderId) { const folder = this.moduleFolders.find(f => f.id === folderId); if (!folder || folder.type !== 'git') { vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); return; } - // 获取完整路径 const fullPath = this.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); @@ -511,7 +737,6 @@ class ConfigPanel { }, async (progress) => { try { progress.report({ increment: 0, message: '拉取最新更改...' }); - // 拉取最新更改 await isomorphic_git_1.default.pull({ fs: fs, http: node_1.default, @@ -519,7 +744,6 @@ class ConfigPanel { author: { name: 'DCSP User', email: 'user@dcsp.local' }, fastForward: true }); - // 重新加载文件树 await this.loadModuleFolderFileTree(folderId); vscode.window.showInformationMessage(`Git 仓库同步成功: ${folder.name}`); this.updateWebview(); @@ -529,9 +753,6 @@ class ConfigPanel { } }); } - /** - * 删除模块文件夹 - */ async deleteModuleFolder(folderId) { const folder = this.moduleFolders.find(f => f.id === folderId); if (!folder) @@ -539,15 +760,12 @@ class ConfigPanel { const confirm = await vscode.window.showWarningMessage(`确定要删除模块文件夹 "${folder.name}" 吗?这将删除本地文件。`, { modal: true }, '确定删除', '取消'); if (confirm === '确定删除') { try { - // 获取完整路径并删除文件夹 const fullPath = this.getModuleFolderFullPath(folder); if (fullPath) { await fs.promises.rm(fullPath, { recursive: true, force: true }); } - // 从列表中移除 this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); await this.saveCurrentProjectData(); - // 如果删除的是当前文件夹,清空状态 if (this.currentModuleFolderId === folderId) { this.currentModuleFolderId = ''; this.currentModuleFolderFileTree = []; @@ -560,11 +778,591 @@ class ConfigPanel { } } } - /** - * 加载模块文件夹文件树 - */ + async importGitFile(filePath) { + if (!this.currentModuleFolderId || !this.currentContainerId) { + vscode.window.showErrorMessage('请先选择模块文件夹和容器'); + return; + } + const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); + return; + } + const container = this.containers.find(c => c.id === this.currentContainerId); + if (!container) { + vscode.window.showErrorMessage('未找到当前容器'); + return; + } + try { + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹路径'); + return; + } + const fileFullPath = path.join(fullPath, filePath); + const content = await fs.promises.readFile(fileFullPath, 'utf8'); + const fileName = path.basename(filePath); + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('cfg', this.configs); + const newConfig = { + id: newId, + name: fileName, + fileName: fileName, + content: content, + containerId: this.currentContainerId + }; + this.configs.push(newConfig); + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); + this.updateWebview(); + } + catch (error) { + vscode.window.showErrorMessage(`导入文件失败: ${error}`); + } + } + // ============================================= + // 上传功能方法 + // ============================================= + async uploadGitModuleFolder(folderId, username, password) { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); + return; + } + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); + return; + } + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '检查更改...' }); + await this.commitAndPushUsingCommandLine(fullPath); + progress.report({ increment: 100, message: '完成' }); + folder.uploaded = true; + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); + this.updateWebview(); + } + catch (error) { + console.error('❌ Git 上传失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message}`); + } + }); + } + async uploadLocalModuleFolder(folderId, repoUrl, branchName) { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder || folder.type !== 'local') { + vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); + return; + } + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); + return; + } + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传本地文件夹到 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '检查目录...' }); + if (!fs.existsSync(fullPath)) { + throw new Error('本地文件夹不存在'); + } + progress.report({ increment: 10, message: '初始化 Git 仓库...' }); + await this.initGitRepository(fullPath, branchName); + progress.report({ increment: 20, message: '添加远程仓库...' }); + await this.addGitRemote(fullPath, repoUrl); + progress.report({ increment: 40, message: '提交初始文件...' }); + await this.commitInitialFiles(fullPath); + progress.report({ increment: 60, message: '推送到远程仓库...' }); + await this.pushToRemoteWithForce(fullPath, branchName); + progress.report({ increment: 100, message: '完成' }); + folder.type = 'git'; + folder.uploaded = true; + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`); + this.updateWebview(); + } + catch (error) { + console.error('❌ 本地文件夹上传失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message}`); + // 清理:删除可能创建的 .git 文件夹 + try { + const gitDir = path.join(fullPath, '.git'); + if (fs.existsSync(gitDir)) { + await fs.promises.rm(gitDir, { recursive: true, force: true }); + } + } + catch (cleanupError) { + console.error('清理 .git 文件夹失败:', cleanupError); + } + } + }); + } + // ============================================= + // 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) { + const configCount = this.configs.length; + // 第一个配置文件 + 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) + 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) { + 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}`); + } + } + // ============================================= + // 项目数据持久化方法 + // ============================================= + async saveCurrentProjectData() { + 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 = { + 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}`); + } + } + 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.updateWebview(); + return true; + } + catch (error) { + vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); + return false; + } + } + 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; + } + } + // ============================================= + // 项目路径选择方法 + // ============================================= + async openExistingProject() { + try { + const result = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: '选择项目文件夹', + title: '选择包含项目数据的文件夹' + }); + if (result && result.length > 0) { + const selectedPath = result[0].fsPath; + await this.loadProjectData(selectedPath); + } + } + catch (error) { + vscode.window.showErrorMessage(`打开项目时出错: ${error}`); + } + } + async selectProjectPath(projectId, projectName) { + try { + const choice = await vscode.window.showQuickPick([ + { + label: '$(folder) 选择现有文件夹', + description: '从文件系统中选择已存在的文件夹', + value: 'select' + }, + { + label: '$(new-folder) 创建新文件夹', + description: '输入新文件夹路径(将自动创建)', + value: 'create' + } + ], { + placeHolder: '选择项目存储方式' + }); + if (!choice) { + return null; + } + if (choice.value === 'select') { + return await this.selectExistingProjectPath(projectId, projectName); + } + else { + return await this.createNewProjectPath(projectId, projectName); + } + } + catch (error) { + vscode.window.showErrorMessage(`选择存储路径时出错: ${error}`); + return null; + } + } + async selectExistingProjectPath(projectId, projectName) { + const result = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: `选择 ${projectName} 的存储位置`, + title: `为项目 "${projectName}" 选择存储文件夹` + }); + if (result && result.length > 0) { + const selectedPath = result[0].fsPath; + const hasExistingData = await this.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} 加载`); + return selectedPath; + } + } + } + this.projectPaths.set(projectId, selectedPath); + vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); + await this.saveCurrentProjectData(); + return selectedPath; + } + return null; + } + async createNewProjectPath(projectId, projectName) { + const pathInput = await vscode.window.showInputBox({ + prompt: '请输入项目存储路径(绝对路径)', + placeHolder: `/path/to/your/project/${projectName}`, + validateInput: (value) => { + if (!value) { + return '路径不能为空'; + } + return null; + } + }); + if (pathInput) { + try { + const dirUri = vscode.Uri.file(pathInput); + await vscode.workspace.fs.createDirectory(dirUri); + this.projectPaths.set(projectId, pathInput); + vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); + await this.saveCurrentProjectData(); + return pathInput; + } + catch (error) { + vscode.window.showErrorMessage(`创建目录失败: ${error}`); + return null; + } + } + return null; + } + // ============================================= + // 文件树和模块文件夹方法 + // ============================================= async loadModuleFolderFileTree(folderId) { - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,跳过文件树加载'); return; @@ -611,9 +1409,6 @@ class ConfigPanel { console.log('⚠️ 无法发送完成消息,Webview 可能已被销毁'); } } - /** - * 构建文件树 - */ async buildFileTree(dir, relativePath = '') { try { const files = await fs.promises.readdir(dir); @@ -651,559 +1446,9 @@ class ConfigPanel { return []; } } - /** - * 导入 Git 文件到当前容器 - */ - async importGitFile(filePath) { - if (!this.currentModuleFolderId || !this.currentContainerId) { - vscode.window.showErrorMessage('请先选择模块文件夹和容器'); - return; - } - const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); - return; - } - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹路径'); - return; - } - const fileFullPath = path.join(fullPath, filePath); - const content = await fs.promises.readFile(fileFullPath, 'utf8'); - const fileName = path.basename(filePath); - // 创建新配置 - const newId = 'cfg' + (this.configs.length + 1); - const newConfig = { - id: newId, - name: fileName, - fileName: fileName, - content: content, - containerId: this.currentContainerId - }; - this.configs.push(newConfig); - await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); - this.updateWebview(); - } - catch (error) { - vscode.window.showErrorMessage(`导入文件失败: ${error}`); - } - } - // === 原有项目配置管理方法 === - // === 打开现有项目功能 === - async openExistingProject() { - try { - const result = await vscode.window.showOpenDialog({ - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - openLabel: '选择项目文件夹', - title: '选择包含项目数据的文件夹' - }); - if (result && result.length > 0) { - const selectedPath = result[0].fsPath; - await this.loadProjectData(selectedPath); - } - } - catch (error) { - vscode.window.showErrorMessage(`打开项目时出错: ${error}`); - } - } - // === 数据持久化方法 === - /** - * 保存当前项目数据到项目路径 - */ - async saveCurrentProjectData() { - 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 currentProjectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); - const currentAircraftIds = currentProjectAircrafts.map(a => a.id); - const currentProjectContainers = this.containers.filter(c => currentAircraftIds.includes(c.aircraftId)); - const currentContainerIds = currentProjectContainers.map(c => c.id); - const currentProjectConfigs = this.configs.filter(cfg => currentContainerIds.includes(cfg.containerId)); - // 只保存与当前项目容器相关的模块文件夹 - const currentProjectModuleFolders = this.moduleFolders.filter(folder => currentContainerIds.includes(folder.containerId)); - const data = { - projects: this.projects.filter(p => p.id === this.currentProjectId), - aircrafts: currentProjectAircrafts, - containers: currentProjectContainers, - configs: currentProjectConfigs, - moduleFolders: currentProjectModuleFolders // 保存模块文件夹数据 - }; - const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); - await vscode.workspace.fs.writeFile(dataUri, uint8Array); - console.log('✅ 当前项目数据已保存,包含', currentProjectModuleFolders.length, '个模块文件夹'); - } - catch (error) { - vscode.window.showErrorMessage(`保存项目数据失败: ${error}`); - } - } - /** - * 从项目路径加载数据 - */ - 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); - // 清空现有数据 - this.projects = []; - this.aircrafts = []; - this.containers = []; - this.configs = []; - this.moduleFolders = []; // 清空模块文件夹数据 - // 验证数据格式并加载 - if (data.projects && Array.isArray(data.projects)) { - this.projects = data.projects; - } - if (data.aircrafts && Array.isArray(data.aircrafts)) { - this.aircrafts = data.aircrafts; - } - if (data.containers && Array.isArray(data.containers)) { - this.containers = data.containers; - } - if (data.configs && Array.isArray(data.configs)) { - this.configs = data.configs; - } - if (data.moduleFolders && Array.isArray(data.moduleFolders)) { - this.moduleFolders = data.moduleFolders; // 加载模块文件夹数据 - } - // 设置当前项目为第一个项目(如果有的话) - if (this.projects.length > 0) { - this.currentProjectId = this.projects[0].id; - this.projectPaths.set(this.currentProjectId, projectPath); - this.currentView = 'aircrafts'; - } - vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${this.moduleFolders.length} 个模块文件夹`); - this.updateWebview(); - return true; - } - catch (error) { - vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); - return false; - } - } - /** - * 检查项目路径是否已存在数据 - */ - 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; - } - } - // === 项目路径选择 === - async selectProjectPath(projectId, projectName) { - try { - // 选择现有路径或输入新路径 - const choice = await vscode.window.showQuickPick([ - { - label: '$(folder) 选择现有文件夹', - description: '从文件系统中选择已存在的文件夹', - value: 'select' - }, - { - label: '$(new-folder) 创建新文件夹', - description: '输入新文件夹路径(将自动创建)', - value: 'create' - } - ], { - placeHolder: '选择项目存储方式' - }); - if (!choice) { - return null; - } - if (choice.value === 'select') { - // 选择现有路径 - const result = await vscode.window.showOpenDialog({ - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - openLabel: `选择 ${projectName} 的存储位置`, - title: `为项目 "${projectName}" 选择存储文件夹` - }); - if (result && result.length > 0) { - const selectedPath = result[0].fsPath; - // 检查是否已存在数据 - const hasExistingData = await this.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} 加载`); - return selectedPath; - } - } - // 如果选择不加载或加载失败,继续创建新项目 - } - this.projectPaths.set(projectId, selectedPath); - vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); - // 保存初始数据 - await this.saveCurrentProjectData(); - return selectedPath; - } - } - else { - // 创建新路径 - const pathInput = await vscode.window.showInputBox({ - prompt: '请输入项目存储路径(绝对路径)', - placeHolder: `/path/to/your/project/${projectName}`, - validateInput: (value) => { - if (!value) { - return '路径不能为空'; - } - return null; - } - }); - if (pathInput) { - try { - // 尝试创建目录 - const dirUri = vscode.Uri.file(pathInput); - await vscode.workspace.fs.createDirectory(dirUri); - this.projectPaths.set(projectId, pathInput); - vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); - // 保存初始数据 - await this.saveCurrentProjectData(); - return pathInput; - } - catch (error) { - vscode.window.showErrorMessage(`创建目录失败: ${error}`); - return null; - } - } - } - return null; - } - catch (error) { - vscode.window.showErrorMessage(`选择存储路径时出错: ${error}`); - return null; - } - } - // 更新项目名 - async updateProjectName(projectId, newName) { - const project = this.projects.find(p => p.id === projectId); - if (project) { - project.name = newName; - vscode.window.showInformationMessage(`项目名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - // 创建新项目 - async createProject(name) { - const newId = 'p' + (this.projects.length + 1); - const newProject = { - id: newId, - name: name - }; - this.projects.push(newProject); - 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(); - } - // 更新飞行器名 - async updateAircraftName(aircraftId, newName) { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (aircraft) { - aircraft.name = newName; - vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - // 创建新飞行器 - async createAircraft(name) { - if (!this.currentProjectId) { - vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目'); - return; - } - const newId = 'a' + (this.aircrafts.length + 1); - const newAircraft = { - id: newId, - name: name, - projectId: this.currentProjectId - }; - this.aircrafts.push(newAircraft); - // 创建飞行器目录 - await this.createAircraftDirectory(newAircraft); - 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(); - } - // 更新容器名 - async updateContainerName(containerId, newName) { - const container = this.containers.find(c => c.id === containerId); - if (container) { - container.name = newName; - vscode.window.showInformationMessage(`容器名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - // 创建新容器 - async createContainer(name) { - if (!this.currentAircraftId) { - vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器'); - return; - } - const newId = 'c' + (this.containers.length + 1); - const newContainer = { - id: newId, - name: name, - aircraftId: this.currentAircraftId - }; - this.containers.push(newContainer); - // 创建容器目录 - await this.createContainerDirectory(newContainer); - // 创建两个默认配置文件 - const configCount = this.configs.length; - // 第一个配置文件 - this.configs.push({ - id: 'cfg' + (configCount + 1), - name: '配置1', - fileName: 'dockerfile', - content: `# ${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: newId - }); - // 第二个配置文件 - this.configs.push({ - id: 'cfg' + (configCount + 2), - name: '配置2', - fileName: 'docker-compose.yml', - content: `# ${name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${name.toLowerCase().replace(/\\s+/g, '-')}:\n build: .\n container_name: ${name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, - containerId: newId - }); - 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(); - } - // 更新配置名 - async updateConfigName(configId, newName) { - const config = this.configs.find(c => c.id === configId); - if (config) { - config.name = newName; - vscode.window.showInformationMessage(`配置名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - // 创建新配置文件 - async createConfig(name) { - const newId = 'cfg' + (this.configs.length + 1); - 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); - vscode.window.showInformationMessage(`新建配置: ${name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - // 删除配置文件 - 修复版本,同时删除磁盘文件 - async deleteConfig(configId) { - const config = this.configs.find(c => c.id === configId); - if (!config) - return; - const confirm = await vscode.window.showWarningMessage(`确定要删除配置文件 "${config.name}" 吗?这将同时删除磁盘上的文件。`, { modal: true }, '确定删除', '取消'); - if (confirm !== '确定删除') { - return; - } - try { - // 从内存中删除配置 - this.configs = this.configs.filter(c => c.id !== configId); - // 删除磁盘上的配置文件 - const container = this.containers.find(c => c.id === config.containerId); - if (container) { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (aircraft) { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (projectPath) { - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - // 检查文件是否存在,如果存在则删除 - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); - } - } - } - } - vscode.window.showInformationMessage(`删除配置: ${config.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - catch (error) { - vscode.window.showErrorMessage(`删除配置文件失败: ${error}`); - } - } - // === Git 分支管理 === - async fetchBranches(url) { - try { - console.log('🌿 开始获取分支列表:', url); - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: '正在获取分支信息', - cancellable: false - }, async (progress) => { - progress.report({ increment: 0, message: '连接远程仓库...' }); - try { - // 使用 isomorphic-git 的 listServerRefs - progress.report({ increment: 30, message: '获取远程引用...' }); - console.log('🔍 使用 listServerRefs 获取分支信息...'); - const refs = await isomorphic_git_1.default.listServerRefs({ - http: node_1.default, - url: url - }); - console.log('📋 获取到的引用:', refs); - // 过滤出分支引用 (refs/heads/ 和 refs/remotes/origin/) - const branchRefs = refs.filter(ref => ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/')); - console.log('🌿 过滤后的分支引用:', branchRefs); - // 构建分支数据 - 修复分支名称显示 - const branches = branchRefs.map(ref => { - let branchName; - if (ref.ref.startsWith('refs/remotes/')) { - // 远程分支:移除 refs/remotes/origin/ 前缀 - branchName = ref.ref.replace('refs/remotes/origin/', ''); - } - else { - // 本地分支:移除 refs/heads/ 前缀 - branchName = ref.ref.replace('refs/heads/', ''); - } - return { - name: branchName, - isCurrent: branchName === 'main' || branchName === 'master', - selected: false // 所有分支默认不选中 - }; - }); - console.log('🎯 最终分支列表:', branches); - if (branches.length === 0) { - throw new Error('未找到任何分支'); - } - progress.report({ increment: 80, message: '处理分支数据...' }); - // === 新增:构建分支树状结构 === - const branchTree = this.buildBranchTree(branches); - console.log('🌳 构建的分支树结构:', branchTree); - // 发送分支数据到前端 - 同时包含扁平列表和树状结构 - if (!this.isWebviewDisposed) { - this.panel.webview.postMessage({ - type: 'branchesFetched', - branches: branches, - branchTree: branchTree, - repoUrl: url - }); - } - progress.report({ increment: 100, message: '完成' }); - } - catch (error) { - console.error('❌ 使用 listServerRefs 获取分支失败:', error); - // 只在右下角显示分支获取失败的通知,不模拟分支数据 - vscode.window.showErrorMessage(`获取分支失败: ${error}`); - } - }); - } - catch (error) { - console.error('❌ 获取分支失败:', error); - vscode.window.showErrorMessage(`获取分支失败: ${error}`); - } - } - /** - * 构建分支树状结构 - */ + // ============================================= + // 工具方法 + // ============================================= buildBranchTree(branches) { const root = []; branches.forEach(branch => { @@ -1221,12 +1466,11 @@ class ConfigPanel { isLeaf: isLeaf, children: [], level: i, - expanded: true // 默认展开 + expanded: true }; currentLevel.push(node); } if (isLeaf) { - // 叶子节点存储分支信息 node.branch = branch; } currentLevel = node.children; @@ -1239,57 +1483,87 @@ class ConfigPanel { const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); return { displayName: repoName, - folderName: branchSafeName // 实际文件夹名称(只显示分支名) + folderName: branchSafeName }; } - async cloneBranches(url, branches) { + 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('未找到配置文件'); + 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 { - console.log('🚀 开始克隆分支:', { url, branches }); - let successCount = 0; - let failCount = 0; - // 显示总进度 - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在克隆 ${branches.length} 个分支`, - cancellable: false - }, async (progress) => { - for (let i = 0; i < branches.length; i++) { - const branch = branches[i]; - const progressPercent = (i / branches.length) * 100; - progress.report({ - increment: progressPercent, - message: `克隆分支: ${branch} (${i + 1}/${branches.length})` - }); - console.log(`📥 开始克隆分支: ${branch}`); - try { - const folderNames = this.generateModuleFolderName(url, branch); - await this.addGitModuleFolder(url, folderNames.displayName, folderNames.folderName, branch); - successCount++; - console.log(`✅ 分支克隆成功: ${branch}`); - } - catch (error) { - failCount++; - console.error(`❌ 分支克隆失败: ${branch}`, error); - // 继续克隆其他分支,不中断整个流程 - } - } - }); - // 显示最终结果 - if (failCount === 0) { - vscode.window.showInformationMessage(`成功克隆 ${successCount} 个分支`); + 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 || ''); } - else { - vscode.window.showWarningMessage(`克隆完成: ${successCount} 个成功, ${failCount} 个失败`); + 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) { - console.error('❌ 克隆分支失败:', error); - vscode.window.showErrorMessage(`克隆分支失败: ${error}`); + vscode.window.showErrorMessage(`打开模块文件夹文件失败: ${error}`); } } - // 更新视图 + // ============================================= + // Webview 更新方法 + // ============================================= updateWebview() { - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,跳过更新'); return; @@ -1309,6 +1583,7 @@ class ConfigPanel { projectPaths: this.projectPaths }); case 'aircrafts': + // 只显示当前项目的飞行器 const projectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); return this.aircraftView.render({ aircrafts: projectAircrafts @@ -1316,6 +1591,7 @@ class ConfigPanel { 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); return this.containerView.render({ project: currentProject, @@ -1324,9 +1600,9 @@ class ConfigPanel { }); case 'configs': const currentContainer = this.containers.find(c => c.id === this.currentContainerId); + // 只显示当前容器的配置和模块文件夹 const containerConfigs = this.configs.filter(cfg => cfg.containerId === this.currentContainerId); const currentModuleFolder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - // 获取当前容器的模块文件夹 const containerModuleFolders = this.moduleFolders.filter(folder => folder.containerId === this.currentContainerId); return this.configView.render({ container: currentContainer, @@ -1343,629 +1619,6 @@ class ConfigPanel { }); } } - async openGitRepoInVSCode(folderId) { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - try { - // 检查文件夹是否存在 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹目录不存在'); - return; - } - // 使用 VSCode 的文件选择器让用户选择要打开的文件 - const fileUri = await vscode.window.showOpenDialog({ - defaultUri: vscode.Uri.file(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 openConfigFileInVSCode(configId) { - const config = this.configs.find(c => c.id === configId); - if (!config) { - vscode.window.showErrorMessage('未找到配置文件'); - return; - } - const container = this.containers.find(c => c.id === config.containerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!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 || ''); - } - // 在 VSCode 中打开文件 - const document = await vscode.workspace.openTextDocument(filePath); - await vscode.window.showTextDocument(document); - } - catch (error) { - vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); - } - } - async mergeConfigs(configIds, displayName, folderName) { - try { - if (!this.currentContainerId) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } - if (configIds.length < 2) { - vscode.window.showErrorMessage('请至少选择两个配置文件进行合并'); - return; - } - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - vscode.window.showErrorMessage('未设置项目存储路径'); - return; - } - // 获取选中的配置文件 - const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); - 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 copiedFiles = []; - for (const config of selectedConfigs) { - const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - const targetPath = path.join(mergeFolderPath, config.fileName); - if (fs.existsSync(sourcePath)) { - await fs.promises.copyFile(sourcePath, targetPath); - copiedFiles.push(config.fileName); - console.log(`✅ 已复制配置文件: ${config.fileName}`); - } - else { - // 如果源文件不存在,创建新文件 - await fs.promises.writeFile(targetPath, config.content || ''); - copiedFiles.push(config.fileName); - console.log(`✅ 已创建配置文件: ${config.fileName}`); - } - } - // 构建相对路径 - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - // 创建合并文件夹记录 - const newFolder = { - id: 'local-' + Date.now(), - name: displayName, - type: 'local', - localPath: relativePath, - containerId: this.currentContainerId - }; - // 添加到模块文件夹列表 - this.moduleFolders.push(newFolder); - // 删除原始配置文件 - for (const configId of configIds) { - await this.deleteConfigInternal(configId); - } - // 保存数据 - await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`); - // 更新UI - this.updateWebview(); - } - catch (error) { - console.error('❌ 合并配置文件失败:', error); - vscode.window.showErrorMessage(`合并配置文件失败: ${error}`); - } - } - /** - * 内部删除配置文件方法(不显示确认对话框) - */ - async deleteConfigInternal(configId) { - try { - const config = this.configs.find(c => c.id === configId); - if (!config) - return; - // 从内存中删除配置 - this.configs = this.configs.filter(c => c.id !== configId); - // 删除磁盘上的配置文件 - const container = this.containers.find(c => c.id === config.containerId); - if (container) { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (aircraft) { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (projectPath) { - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - // 检查文件是否存在,如果存在则删除 - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); - } - } - } - } - console.log(`✅ 内部删除配置: ${config.name}`); - } - catch (error) { - console.error(`删除配置文件失败: ${error}`); - } - } - /** - * 在 VSCode 中打开合并文件夹 - */ - async openMergedFolderInVSCode(folderId) { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - try { - // 检查文件夹是否存在 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹不存在'); - return; - } - // 使用 VSCode 打开文件夹 - const folderUri = vscode.Uri.file(fullPath); - vscode.commands.executeCommand('vscode.openFolder', folderUri, { forceNewWindow: false }); - } - catch (error) { - vscode.window.showErrorMessage(`打开模块文件夹失败: ${error}`); - } - } - /** - * 统一方法:在 VSCode 中打开模块文件夹中的文件 - * @param type 模块类型:'git' 或 'merged' - * @param id 模块 ID - */ - 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; - } - // 使用 VSCode 的文件选择器让用户选择要打开的文件 - 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}`); - } - } - /** - * 获取模块文件夹的完整路径 - */ - 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 uploadGitModuleFolder(folderId, username, password) { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); - return; - } - // 获取完整路径 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); - return; - } - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '检查更改...' }); - // 使用改进的 Git 提交并推送 - await this.commitAndPushUsingCommandLine(fullPath); - progress.report({ increment: 100, message: '完成' }); - // 添加上传成功标记 - folder.uploaded = true; - await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); - // 更新 Webview 显示 - this.updateWebview(); - } - catch (error) { - console.error('❌ Git 上传失败:', error); - // 如果是"没有更改"的错误,显示友好提示 - if (error.message.includes('没有需要提交的更改')) { - vscode.window.showWarningMessage(`没有检测到更改,无需上传: ${folder.name}`); - } - else { - vscode.window.showErrorMessage(`推送失败: ${error.message}`); - } - } - }); - } - async uploadLocalModuleFolder(folderId, repoUrl, branchName) { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder || folder.type !== 'local') { - vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); - return; - } - // 获取完整路径 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); - return; - } - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传本地文件夹到 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '检查目录...' }); - // 检查目录是否存在 - if (!fs.existsSync(fullPath)) { - throw new Error('本地文件夹不存在'); - } - progress.report({ increment: 10, message: '初始化 Git 仓库...' }); - // 使用命令行 Git 初始化仓库 - await this.initGitRepository(fullPath, branchName); - progress.report({ increment: 20, message: '添加远程仓库...' }); - // 使用命令行 Git 添加远程仓库 - await this.addGitRemote(fullPath, repoUrl); - progress.report({ increment: 40, message: '提交初始文件...' }); - // 使用命令行 Git 提交初始文件 - await this.commitInitialFiles(fullPath); - progress.report({ increment: 60, message: '推送到远程仓库...' }); - // 使用命令行 Git 推送到远程仓库 - await this.pushToRemoteWithForce(fullPath, branchName); - progress.report({ increment: 100, message: '完成' }); - // 更新文件夹类型为 git 并标记已上传 - folder.type = 'git'; - folder.uploaded = true; - await this.saveCurrentProjectData(); - vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`); - // 更新 Webview 显示 - this.updateWebview(); - } - catch (error) { - console.error('❌ 本地文件夹上传失败:', error); - vscode.window.showErrorMessage(`推送失败: ${error.message}`); - // 清理:删除可能创建的 .git 文件夹 - try { - const gitDir = path.join(fullPath, '.git'); - if (fs.existsSync(gitDir)) { - await fs.promises.rm(gitDir, { recursive: true, force: true }); - } - } - catch (cleanupError) { - console.error('清理 .git 文件夹失败:', cleanupError); - } - } - }); - } - /** - * 使用命令行 Git 初始化仓库(简化版本) - */ - 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(); - }); - }); - } - /** - * 使用命令行 Git 添加远程仓库(简化版本) - */ - 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(); - }); - }); - } - /** - * 使用命令行 Git 提交初始文件(简化版本) - */ - 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(); - }); - }); - } - /** - * 使用命令行 Git 强制推送到远程仓库(简化版本) - */ - 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 getCurrentBranch(dir) { - try { - const currentBranch = await isomorphic_git_1.default.currentBranch({ - fs: fs, - dir: dir, - fullname: false - }); - if (!currentBranch) { - // 如果没有当前分支,尝试从 HEAD 文件读取 - const headPath = path.join(dir, '.git', 'HEAD'); - if (fs.existsSync(headPath)) { - const headContent = await fs.promises.readFile(headPath, 'utf8'); - const match = headContent.match(/ref: refs\/heads\/(.+)/); - if (match) { - return match[1]; - } - } - throw new Error('无法确定当前分支'); - } - return currentBranch; - } - catch (error) { - console.error('获取当前分支失败:', error); - throw new Error(`获取当前分支失败: ${error}`); - } - } - /** - * 使用命令行 Git 进行推送(带详细调试) - */ - async pushUsingCommandLine(fullPath) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('🚀 使用命令行 Git 推送...'); - console.log(`📁 工作目录: ${fullPath}`); - // 先检查 Git 状态 - exec('git status', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError, statusStdout, statusStderr) => { - console.log('🔍 Git 状态:', statusStdout); - // 然后执行推送 - exec('git push', { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - if (error) { - console.error('❌ Git push 失败:', error); - reject(new Error(`Git 推送失败: ${stderr || error.message}`)); - return; - } - // 检查实际的推送结果 - if (stdout.includes('Everything up-to-date')) { - console.log('ℹ️ 没有需要推送的更改'); - resolve(); - } - else if (stdout.includes('To http') || stdout.includes('To https') || stdout.includes('To git@')) { - console.log('✅ Git 推送成功'); - resolve(); - } - else { - console.log('⚠️ 推送结果不明确,可能需要手动检查'); - reject(new Error('推送结果不明确,请检查远程仓库')); - } - }); - }); - }); - } - /** - * 检查 Git 远程配置 - */ - async checkGitRemote(fullPath) { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - console.log('🔍 检查 Git 远程配置...'); - exec('git remote -v', { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - if (error) { - console.error('检查远程配置失败:', error); - reject(error); - return; - } - console.log('📡 Git 远程配置:', stdout); - 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(); - }); - }); - }); - } - /** - * 简化的推送方法 - */ - simplePush(fullPath, resolve, reject) { - const { exec } = require('child_process'); - exec('git push', { - cwd: fullPath, - encoding: 'utf8' - }, (pushError, pushStdout, pushStderr) => { - console.log('📋 Git push 输出:', pushStdout); - console.log('📋 Git push 错误:', pushStderr); - if (pushError) { - console.error('❌ Git push 失败'); - // 直接使用 Git 的错误信息 - reject(new Error(pushStderr || pushError.message)); - return; - } - // 只要没有错误就认为是成功 - console.log('✅ Git 推送成功'); - resolve(); - }); - } } exports.ConfigPanel = ConfigPanel; //# sourceMappingURL=ConfigPanel.js.map \ No newline at end of file diff --git a/out/panels/ConfigPanel.js.map b/out/panels/ConfigPanel.js.map index ac1621e..812befd 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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,+CAAiC;AACjC,2CAA6B;AAC7B,uCAAyB;AACzB,oEAAiC;AACjC,oEAA4C;AAC5C,qDAAkD;AAClD,uDAAoD;AACpD,yDAAsD;AACtD,mDAAgD;AAoDhD,MAAa,WAAW;IAiCb,MAAM,CAAC,YAAY,CAAC,YAAwB;QAC/C,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,EAAE,UAAU,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAEnF,IAAI,WAAW,CAAC,YAAY,EAAE;YAC1B,WAAW,CAAC,YAAY,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAC9C,OAAO;SACV;QAED,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAC1C,MAAM,EACN,UAAU,EACV,MAAM,EACN;YACI,aAAa,EAAE,IAAI;YACnB,kBAAkB,EAAE,CAAC,YAAY,CAAC;YAClC,uBAAuB,EAAE,IAAI;SAChC,CACJ,CAAC;QAEF,WAAW,CAAC,YAAY,GAAG,IAAI,WAAW,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACpE,CAAC;IAED,YAAmB,KAA0B,EAAE,YAAwB;QAlD/D,gBAAW,GAAwD,UAAU,CAAC;QAC9E,qBAAgB,GAAW,EAAE,CAAC;QAC9B,sBAAiB,GAAW,EAAE,CAAC;QAC/B,uBAAkB,GAAW,EAAE,CAAC;QAChC,0BAAqB,GAAW,EAAE,CAAC;QAE3C,OAAO;QACC,aAAQ,GAAc,EAAE,CAAC;QACzB,cAAS,GAAe,EAAE,CAAC;QAC3B,eAAU,GAAgB,EAAE,CAAC;QAC7B,YAAO,GAAa,EAAE,CAAC;QACvB,kBAAa,GAAmB,EAAE,CAAC,CAAC,aAAa;QAEzD,UAAU;QACF,gCAA2B,GAAkB,EAAE,CAAC;QAExD,WAAW;QACH,iBAAY,GAAwB,IAAI,GAAG,EAAE,CAAC;QAEtD,eAAe;QACP,sBAAiB,GAAY,KAAK,CAAC;QA+BvC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,iBAAiB,GAAG,KAAK,CAAC,CAAC,QAAQ;QAExC,UAAU;QACV,IAAI,CAAC,WAAW,GAAG,IAAI,yBAAW,CAAC,YAAY,CAAC,CAAC;QACjD,IAAI,CAAC,YAAY,GAAG,IAAI,2BAAY,CAAC,YAAY,CAAC,CAAC;QACnD,IAAI,CAAC,aAAa,GAAG,IAAI,6BAAa,CAAC,YAAY,CAAC,CAAC;QACrD,IAAI,CAAC,UAAU,GAAG,IAAI,uBAAU,CAAC,YAAY,CAAC,CAAC;QAE/C,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,oBAAoB,EAAE,CAAC;QAE5B,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,EAAE;YACzB,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAAC,SAAS;YACxC,WAAW,CAAC,YAAY,GAAG,SAAS,CAAC;QACzC,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,oBAAoB;QACxB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;YAClD,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;YAErC,oBAAoB;YACpB,IAAI,IAAI,CAAC,iBAAiB,EAAE;gBACxB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;gBACpC,OAAO;aACV;YAED,IAAI;gBACA,QAAQ,IAAI,CAAC,IAAI,EAAE;oBACf,KAAK,qBAAqB;wBACtB,MAAM,IAAI,CAAC,mBAAmB,EAAE,CAAC;wBACjC,MAAM;oBAEV,KAAK,kBAAkB;wBACnB,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC;wBACpF,IAAI,YAAY,EAAE;4BACd,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;4BAC/B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC;4BACvC,IAAI,CAAC,aAAa,EAAE,CAAC;yBACxB;wBACD,MAAM;oBAEV,KAAK,aAAa;wBACd,aAAa;wBACb,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;wBAC/B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC;wBACvC,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,oBAAoB;wBACrB,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC;wBAChC,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC;wBACvC,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC;wBACzC,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,qBAAqB;wBACtB,IAAI,CAAC,WAAW,GAAG,SAAS,CAAC;wBAC7B,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,WAAW,CAAC;wBAC3C,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,cAAc;oBACd,KAAK,kBAAkB;wBACnB,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;wBAC9B,YAAY;wBACZ,IAAI,CAAC,gBAAgB,GAAG,EAAE,CAAC;wBAC3B,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;wBAC5B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;wBAC7B,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC;wBAChC,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,mBAAmB;wBACpB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;wBAC/B,6BAA6B;wBAC7B,IAAI,CAAC,iBAAiB,GAAG,EAAE,CAAC;wBAC5B,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;wBAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,oBAAoB;wBACrB,IAAI,CAAC,WAAW,GAAG,YAAY,CAAC;wBAChC,gEAAgE;wBAChE,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;wBAC7B,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,mBAAmB;wBACpB,MAAM,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;wBACxD,MAAM;oBAEV,KAAK,eAAe;wBAChB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACpC,MAAM;oBAEV,KAAK,oBAAoB;wBACrB,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;wBAC1D,MAAM;oBAEV,KAAK,gBAAgB;wBACjB,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACrC,MAAM;oBAEV,KAAK,qBAAqB;wBACtB,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;wBAC5D,MAAM;oBAEV,KAAK,iBAAiB;wBAClB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACtC,MAAM;oBAEV,KAAK,kBAAkB;wBACnB,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;wBACtD,MAAM;oBAEV,KAAK,cAAc;wBACf,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;wBACnC,MAAM;oBAEV,KAAK,eAAe;wBAChB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBACzC,MAAM;oBAEV,KAAK,gBAAgB;wBACjB,MAAM,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC3C,MAAM;oBAEV,KAAK,iBAAiB;wBAClB,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;wBAC7C,MAAM;oBAEV,KAAK,cAAc;wBACf,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACvC,MAAM;oBAEV,aAAa;oBACb,KAAK,eAAe;wBAChB,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;wBACpC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;wBACnC,MAAM;oBAEV,KAAK,eAAe;wBAChB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC;wBACjC,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAClD,MAAM;oBAEV,KAAK,uBAAuB;wBACxB,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;wBACxB,IAAI,CAAC,aAAa,EAAE,CAAC;wBACrB,MAAM;oBAEV,KAAK,kBAAkB;wBACnB,MAAM,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC3C,MAAM;oBAEV,KAAK,qBAAqB;wBACtB,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC9C,MAAM;oBAEV,KAAK,oBAAoB;wBACrB,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC7C,MAAM;oBAEV,KAAK,eAAe;wBAChB,MAAM,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACxC,MAAM;oBAEV,KAAK,0BAA0B;wBAC3B,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC/D,MAAM;oBAEV,KAAK,wBAAwB;wBACzB,MAAM,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACjD,MAAM;oBAEV,KAAK,cAAc;wBACf,MAAM,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,WAAW,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;wBAC3E,MAAM;oBAEV,KAAK,oBAAoB;wBACrB,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC7C,MAAM;oBAEV,KAAK,0BAA0B;wBAC3B,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACvD,MAAM;oBAEV,KAAK,kBAAkB;wBACnB,MAAM,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;wBACvD,MAAM;oBAEV,KAAK,qBAAqB;wBACtB,MAAM,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC;wBACzD,MAAM;oBAEV,KAAK,uBAAuB;wBACxB,MAAM,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;wBAC9E,MAAM;oBAEV,KAAK,yBAAyB;wBAC1B,MAAM,IAAI,CAAC,uBAAuB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC;wBACjF,MAAM;iBACb;aACJ;YAAC,OAAO,KAAK,EAAE;gBACZ,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;gBAC1C,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;oBACzB,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;iBACvD;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED,iBAAiB;IAEjB;;OAEG;IACK,KAAK,CAAC,uBAAuB,CAAC,QAAkB;QACpD,IAAI;YACA,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAClC,OAAO;aACV;YAED,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YAErF,UAAU;YACV,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;SAEnD;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;SACxC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,wBAAwB,CAAC,SAAoB;QACvD,IAAI;YACA,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,CAAC,QAAQ,EAAE;gBACX,OAAO,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;gBACnC,OAAO;aACV;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACjC,OAAO;aACV;YAED,qBAAqB;YACrB,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrF,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YAEtE,YAAY;YACZ,IAAI;gBACA,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;aAC1D;YAAC,OAAO,KAAK,EAAE;gBACZ,eAAe;aAClB;YAED,SAAS;YACT,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,aAAa,YAAY,CAAC,MAAM,EAAE,CAAC,CAAC;SAEnD;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACvC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,8BAA8B,CAAC,WAAmB;QAC5D,IAAI;YACA,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;YAClE,IAAI,CAAC,SAAS;gBAAE,OAAO;YAEvB,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAEtB,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW;gBAAE,OAAO;YAEzB,YAAY;YACZ,MAAM,WAAW,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;YACrF,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAC,IAAI,CAAC,CAAC;YAEtE,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;YACvD,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;SAE3D;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC;SACzC;IACL,CAAC;IAED,qBAAqB;IAErB;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,GAAW,EAAE,WAAmB,EAAE,UAAkB,EAAE,MAAe;QACtG,IAAI;YACA,SAAS;YACT,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;gBACjC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,CAAC,CAAC;gBACpD,OAAO;aACV;YAED,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;gBAC1B,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBACzC,OAAO;aACV;YAED,MAAM,QAAQ,GAAG,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;YAErC,SAAS;YACT,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC9E,IAAI,CAAC,SAAS,EAAE;gBACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBACxC,OAAO;aACV;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,CAAC,QAAQ,EAAE;gBACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBACzC,OAAO;aACV;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW,EAAE;gBACd,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBAC1C,OAAO;aACV;YAED,0CAA0C;YAC1C,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;YAE/F,sCAAsC;YACtC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAEpF,OAAO,CAAC,GAAG,CAAC,cAAc,WAAW,SAAS,MAAM,SAAS,SAAS,EAAE,CAAC,CAAC;YAC1E,OAAO,CAAC,GAAG,CAAC,YAAY,YAAY,EAAE,CAAC,CAAC;YAExC,iCAAiC;YACjC,MAAM,cAAc,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CACpD,MAAM,CAAC,SAAS,KAAK,YAAY,IAAI,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,kBAAkB,CACtF,CAAC;YACF,IAAI,cAAc,EAAE;gBAChB,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,UAAU,EAAE,CAAC,CAAC;gBAChE,OAAO;aACV;YAED,MAAM,SAAS,GAAiB;gBAC5B,EAAE,EAAE,QAAQ;gBACZ,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,KAAK;gBACX,SAAS,EAAE,YAAY;gBACvB,WAAW,EAAE,IAAI,CAAC,kBAAkB;aACvC,CAAC;YAEF,OAAO;YACP,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;gBAC9C,KAAK,EAAE,WAAW,WAAW,EAAE;gBAC/B,WAAW,EAAE,KAAK;aACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,CAAC,CAAC;gBAElC,IAAI;oBACA,UAAU;oBACV,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAC1C,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;oBAExD,cAAc;oBACd,IAAI,SAAS,GAAG,KAAK,CAAC;oBACtB,IAAI;wBACA,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;wBACpC,SAAS,GAAG,IAAI,CAAC;qBACpB;oBAAC,MAAM;wBACJ,SAAS,GAAG,KAAK,CAAC;qBACrB;oBAED,IAAI,SAAS,EAAE;wBACX,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;wBACzD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE;4BACxB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAClD,SAAS,UAAU,eAAe,EAClC,EAAE,KAAK,EAAE,IAAI,EAAE,EACf,MAAM,EACN,IAAI,CACP,CAAC;4BAEF,IAAI,OAAO,KAAK,MAAM,EAAE;gCACpB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,CAAC,CAAC;gCAChD,OAAO;6BACV;4BAED,2BAA2B;4BAC3B,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE;gCAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;gCAC5C,IAAI,IAAI,KAAK,MAAM,EAAE;oCACjB,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iCACpE;6BACJ;yBACJ;qBACJ;oBAED,OAAO,CAAC,GAAG,CAAC,YAAY,GAAG,OAAO,SAAS,SAAS,MAAM,EAAE,CAAC,CAAC;oBAE9D,OAAO;oBACP,MAAM,wBAAG,CAAC,KAAK,CAAC;wBACZ,EAAE,EAAE,EAAE;wBACN,IAAI,EAAE,cAAI;wBACV,GAAG,EAAE,SAAS;wBACd,GAAG,EAAE,GAAG;wBACR,YAAY,EAAE,IAAI;wBAClB,KAAK,EAAE,CAAC;wBACR,GAAG,EAAE,MAAM,IAAI,MAAM;wBACrB,UAAU,EAAE,CAAC,KAAU,EAAE,EAAE;4BACvB,OAAO,CAAC,GAAG,CAAC,YAAY,KAAK,CAAC,KAAK,MAAM,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;4BACxE,IAAI,KAAK,CAAC,KAAK,EAAE;gCACb,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC;gCACnD,QAAQ,CAAC,MAAM,CAAC;oCACZ,SAAS,EAAE,OAAO;oCAClB,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI;iCACzD,CAAC,CAAC;6BACN;iCAAM;gCACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,KAAK,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC;6BACrD;wBACL,CAAC;qBACJ,CAAC,CAAC;oBAEH,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;oBAE3B,aAAa;oBACb,MAAM,cAAc,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAC5D,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,cAAc,CAAC,CAAC;oBAE5C,IAAI,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE;wBAC7B,MAAM,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;qBACrC;oBAED,iBAAiB;oBACjB,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oBACnC,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;oBACpC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;oBAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,eAAe,WAAW,EAAE,CAAC,CAAC;oBAEnE,uBAAuB;oBACvB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;wBACzB,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;wBAClC,UAAU;wBACV,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC;wBACtC,MAAM,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;wBAC9C,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;qBACjC;yBAAM;wBACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;qBAC1C;iBAEJ;gBAAC,OAAO,KAAK,EAAE;oBACZ,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;oBAEtC,yBAAyB;oBACzB,IAAI;wBACA,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE;4BAC1B,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;4BAClE,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;yBAChC;qBACJ;oBAAC,OAAO,YAAY,EAAE;wBACnB,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;qBAC7C;oBAED,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;oBAEnD,mBAAmB;oBACnB,MAAM,KAAK,CAAC;iBACf;YACL,CAAC,CAAC,CAAC;SAEN;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;YACrD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,mBAAmB,KAAK,EAAE,CAAC,CAAC;SAC9D;IACL,CAAC;IAEG;;OAEG;IACK,KAAK,CAAC,gBAAgB,CAAC,QAAgB;QAC3C,IAAI,CAAC,qBAAqB,GAAG,QAAQ,CAAC;QACtC,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE;YACjC,MAAM,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;SACjD;QACD,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,mBAAmB,CAAC,QAAgB;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;YACnD,OAAO;SACV;QAED,SAAS;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;YACjD,OAAO;SACV;QAED,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;YAC9C,KAAK,EAAE,WAAW,MAAM,CAAC,IAAI,EAAE;YAC/B,WAAW,EAAE,KAAK;SACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,IAAI;gBACA,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;gBAExD,SAAS;gBACT,MAAM,wBAAG,CAAC,IAAI,CAAC;oBACX,EAAE,EAAE,EAAE;oBACN,IAAI,EAAE,cAAI;oBACV,GAAG,EAAE,QAAQ;oBACb,MAAM,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,iBAAiB,EAAE;oBACvD,WAAW,EAAE,IAAI;iBACpB,CAAC,CAAC;gBAEH,UAAU;gBACV,MAAM,IAAI,CAAC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;gBAE9C,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,eAAe,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACnE,IAAI,CAAC,aAAa,EAAE,CAAC;aAExB;YAAC,OAAO,KAAK,EAAE;gBACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;aAC3D;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC7C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAClD,eAAe,MAAM,CAAC,IAAI,eAAe,EACzC,EAAE,KAAK,EAAE,IAAI,EAAE,EACf,MAAM,EACN,IAAI,CACP,CAAC;QAEF,IAAI,OAAO,KAAK,MAAM,EAAE;YACpB,IAAI;gBACA,eAAe;gBACf,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;gBACtD,IAAI,QAAQ,EAAE;oBACV,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;iBACpE;gBAED,SAAS;gBACT,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;gBACvE,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAEpC,mBAAmB;gBACnB,IAAI,IAAI,CAAC,qBAAqB,KAAK,QAAQ,EAAE;oBACzC,IAAI,CAAC,qBAAqB,GAAG,EAAE,CAAC;oBAChC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC;iBACzC;gBAED,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBACjE,IAAI,CAAC,aAAa,EAAE,CAAC;aAExB;YAAC,OAAO,KAAK,EAAE;gBACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;aACzD;SACJ;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,wBAAwB,CAAC,QAAgB;QACnD,oBAAoB;QACpB,IAAI,IAAI,CAAC,iBAAiB,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC;YACvC,OAAO;SACV;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,WAAW;QACX,IAAI;YACA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC3B,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,IAAI;aAChB,CAAC,CAAC;SACN;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;YAC1C,OAAO;SACV;QAED,IAAI;YACA,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,QAAQ,EAAE;gBACV,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;gBACpD,IAAI,CAAC,2BAA2B,GAAG,QAAQ,CAAC;aAC/C;SAEJ;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,2BAA2B,GAAG,EAAE,CAAC;SACzC;QAED,kBAAkB;QAClB,IAAI,IAAI,CAAC,iBAAiB,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;YACtC,OAAO;SACV;QAED,WAAW;QACX,IAAI;YACA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;gBAC3B,IAAI,EAAE,qBAAqB;gBAC3B,OAAO,EAAE,KAAK;aACjB,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa,EAAE,CAAC;SACxB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;SAC7C;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,eAAuB,EAAE;QAC9D,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,+BAA+B;gBAC/B,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,IAAI,CAAC,aAAa,CAAC,QAAQ,EAAE,mBAAmB,CAAC,CAAC;oBACzE,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;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,QAAgB;QACxC,IAAI,CAAC,IAAI,CAAC,qBAAqB,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;YACzD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,CAAC,CAAC;YAC/C,OAAO;SACV;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,qBAAqB,CAAC,CAAC;QACjF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;YAClD,OAAO;SACV;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAC9E,IAAI,CAAC,SAAS,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC1C,OAAO;SACV;QAED,IAAI;YACA,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,EAAE;gBACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;gBAC9C,OAAO;aACV;YAED,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YACnD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YACjE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;YAEzC,QAAQ;YACR,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAChD,MAAM,SAAS,GAAW;gBACtB,EAAE,EAAE,KAAK;gBACT,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,QAAQ;gBAClB,OAAO,EAAE,OAAO;gBAChB,WAAW,EAAE,IAAI,CAAC,kBAAkB;aACvC,CAAC;YAEF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC7B,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,YAAY,SAAS,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC,CAAC;YAChF,IAAI,CAAC,aAAa,EAAE,CAAC;SAExB;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;SACtD;IACL,CAAC;IAED,qBAAqB;IAErB,mBAAmB;IACX,KAAK,CAAC,mBAAmB;QAC7B,IAAI;YACA,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;gBAC9C,cAAc,EAAE,KAAK;gBACrB,gBAAgB,EAAE,IAAI;gBACtB,aAAa,EAAE,KAAK;gBACpB,SAAS,EAAE,SAAS;gBACpB,KAAK,EAAE,cAAc;aACxB,CAAC,CAAC;YAEH,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC7B,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBACtC,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;aAC5C;SACJ;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,KAAK,EAAE,CAAC,CAAC;SACvD;IACL,CAAC;IAED,kBAAkB;IAElB;;OAEG;IACK,KAAK,CAAC,sBAAsB;QAChC,IAAI;YACA,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;gBACxB,OAAO,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAChC,OAAO;aACV;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACjE,IAAI,CAAC,WAAW,EAAE;gBACd,OAAO,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;gBAClC,OAAO;aACV;YAED,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAErF,gBAAgB;YAChB,MAAM,uBAAuB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,gBAAgB,CAAC,CAAC;YAClG,MAAM,kBAAkB,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAClE,MAAM,wBAAwB,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YACxG,MAAM,mBAAmB,GAAG,wBAAwB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACpE,MAAM,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;YAExG,qBAAqB;YACrB,MAAM,2BAA2B,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CACnE,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CACnD,CAAC;YAEF,MAAM,IAAI,GAAgB;gBACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC;gBACnE,SAAS,EAAE,uBAAuB;gBAClC,UAAU,EAAE,wBAAwB;gBACpC,OAAO,EAAE,qBAAqB;gBAC9B,aAAa,EAAE,2BAA2B,CAAC,YAAY;aAC1D,CAAC;YAEF,MAAM,UAAU,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;YAC3E,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YAEzD,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,2BAA2B,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;SAC/E;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACxD;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,eAAe,CAAC,WAAmB;QAC7C,IAAI;YACA,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC,CAAC;YAErF,aAAa;YACb,IAAI;gBACA,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;aAC3C;YAAC,MAAM;gBACJ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,qCAAqC,CAAC,CAAC;gBACtE,OAAO,KAAK,CAAC;aAChB;YAED,SAAS;YACT,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;YAC7D,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACnD,MAAM,IAAI,GAAgB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAE9C,SAAS;YACT,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAC;YACnB,IAAI,CAAC,SAAS,GAAG,EAAE,CAAC;YACpB,IAAI,CAAC,UAAU,GAAG,EAAE,CAAC;YACrB,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;YAClB,IAAI,CAAC,aAAa,GAAG,EAAE,CAAC,CAAC,YAAY;YAErC,YAAY;YACZ,IAAI,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAC/C,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;aACjC;YACD,IAAI,IAAI,CAAC,SAAS,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;gBACjD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;aACnC;YACD,IAAI,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;gBACnD,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC;aACrC;YACD,IAAI,IAAI,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE;gBAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC;aAC/B;YACD,IAAI,IAAI,CAAC,aAAa,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE;gBACzD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,YAAY;aACxD;YAED,sBAAsB;YACtB,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC1B,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5C,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;gBAC1D,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;aAClC;YAED,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,WAAW,UAAU,IAAI,CAAC,aAAa,CAAC,MAAM,SAAS,CAAC,CAAC;YACxG,IAAI,CAAC,aAAa,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC;SACf;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;YACrD,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,uBAAuB,CAAC,WAAmB;QACrD,IAAI;YACA,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,iBAAiB,CAAC,CAAC;YACrF,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO,IAAI,CAAC;SACf;QAAC,MAAM;YACJ,OAAO,KAAK,CAAC;SAChB;IACL,CAAC;IAED,iBAAiB;IACT,KAAK,CAAC,iBAAiB,CAAC,SAAiB,EAAE,WAAmB;QAClE,IAAI;YACA,eAAe;YACf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,aAAa,CAC5C;gBACI;oBACI,KAAK,EAAE,mBAAmB;oBAC1B,WAAW,EAAE,iBAAiB;oBAC9B,KAAK,EAAE,QAAQ;iBAClB;gBACD;oBACI,KAAK,EAAE,sBAAsB;oBAC7B,WAAW,EAAE,iBAAiB;oBAC9B,KAAK,EAAE,QAAQ;iBAClB;aACJ,EACD;gBACI,WAAW,EAAE,UAAU;aAC1B,CACJ,CAAC;YAEF,IAAI,CAAC,MAAM,EAAE;gBACT,OAAO,IAAI,CAAC;aACf;YAED,IAAI,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE;gBAC3B,SAAS;gBACT,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;oBAC9C,cAAc,EAAE,KAAK;oBACrB,gBAAgB,EAAE,IAAI;oBACtB,aAAa,EAAE,KAAK;oBACpB,SAAS,EAAE,MAAM,WAAW,QAAQ;oBACpC,KAAK,EAAE,QAAQ,WAAW,WAAW;iBACxC,CAAC,CAAC;gBAEH,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE;oBAC7B,MAAM,YAAY,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;oBAEtC,YAAY;oBACZ,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,YAAY,CAAC,CAAC;oBACzE,IAAI,eAAe,EAAE;wBACjB,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CACrD,OAAO,YAAY,mBAAmB,EACtC,EAAE,KAAK,EAAE,IAAI,EAAE,EACf,UAAU,EACV,SAAS,CACZ,CAAC;wBAEF,IAAI,UAAU,KAAK,UAAU,EAAE;4BAC3B,SAAS;4BACT,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC;4BACzD,IAAI,OAAO,EAAE;gCACT,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;gCAC/C,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;gCAC/B,IAAI,CAAC,gBAAgB,GAAG,SAAS,CAAC;gCAClC,IAAI,CAAC,aAAa,EAAE,CAAC;gCACrB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,YAAY,KAAK,CAAC,CAAC;gCAClE,OAAO,YAAY,CAAC;6BACvB;yBACJ;wBACD,uBAAuB;qBAC1B;oBAED,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;oBAC/C,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,YAAY,EAAE,CAAC,CAAC;oBAEnE,SAAS;oBACT,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;oBAEpC,OAAO,YAAY,CAAC;iBACvB;aACJ;iBAAM;gBACH,QAAQ;gBACR,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;oBAC/C,MAAM,EAAE,iBAAiB;oBACzB,WAAW,EAAE,yBAAyB,WAAW,EAAE;oBACnD,aAAa,EAAE,CAAC,KAAK,EAAE,EAAE;wBACrB,IAAI,CAAC,KAAK,EAAE;4BACR,OAAO,QAAQ,CAAC;yBACnB;wBACD,OAAO,IAAI,CAAC;oBAChB,CAAC;iBACJ,CAAC,CAAC;gBAEH,IAAI,SAAS,EAAE;oBACX,IAAI;wBACA,SAAS;wBACT,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;wBAC1C,MAAM,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;wBAElD,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;wBAC5C,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,cAAc,SAAS,EAAE,CAAC,CAAC;wBAEhE,SAAS;wBACT,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;wBAEpC,OAAO,SAAS,CAAC;qBACpB;oBAAC,OAAO,KAAK,EAAE;wBACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;wBACnD,OAAO,IAAI,CAAC;qBACf;iBACJ;aACJ;YAED,OAAO,IAAI,CAAC;SACf;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;YACtD,OAAO,IAAI,CAAC;SACf;IACL,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,iBAAiB,CAAC,SAAiB,EAAE,OAAe;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC5D,IAAI,OAAO,EAAE;YACT,OAAO,CAAC,IAAI,GAAG,OAAO,CAAC;YACvB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;YAC3D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;SACxB;IACL,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,aAAa,CAAC,IAAY;QACpC,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC/C,MAAM,UAAU,GAAY;YACxB,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;SACb,CAAC;QACF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,OAAO;IACC,KAAK,CAAC,aAAa,CAAC,SAAiB;QACzC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC5D,IAAI,CAAC,OAAO;YAAE,OAAO;QAErB,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QAC9D,WAAW;QACX,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QAC/E,MAAM,WAAW,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;QACvE,UAAU;QACV,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QACnF,UAAU;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACpG,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;QACnF,aAAa;QACb,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QACrG,WAAW;QACX,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,SAAS;IACD,KAAK,CAAC,kBAAkB,CAAC,UAAkB,EAAE,OAAe;QAChE,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;QAC/D,IAAI,QAAQ,EAAE;YACV,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC;YACxB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,YAAY,OAAO,EAAE,CAAC,CAAC;YAC5D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;SACxB;IACL,CAAC;IAED,SAAS;IACD,KAAK,CAAC,cAAc,CAAC,IAAY;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE;YACxB,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;YAClD,OAAO;SACV;QAED,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChD,MAAM,WAAW,GAAa;YAC1B,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;YACV,SAAS,EAAE,IAAI,CAAC,gBAAgB;SACnC,CAAC;QACF,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEjC,UAAU;QACV,MAAM,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,CAAC;QAEhD,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QACvD,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,cAAc,CAAC,UAAkB;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;QAC/D,IAAI,CAAC,QAAQ;YAAE,OAAO;QAEtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,CAAC;QACjE,UAAU;QACV,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;QAC3E,UAAU;QACV,MAAM,YAAY,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7F,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC;QACnF,aAAa;QACb,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC;QAErG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,mBAAmB,CAAC,WAAmB,EAAE,OAAe;QAClE,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QAClE,IAAI,SAAS,EAAE;YACX,SAAS,CAAC,IAAI,GAAG,OAAO,CAAC;YACzB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;YAC3D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;SACxB;IACL,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,eAAe,CAAC,IAAY;QACtC,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;YACzB,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;YAClD,OAAO;SACV;QAED,MAAM,KAAK,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjD,MAAM,YAAY,GAAc;YAC5B,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;YACV,UAAU,EAAE,IAAI,CAAC,iBAAiB;SACrC,CAAC;QACF,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAEnC,SAAS;QACT,MAAM,IAAI,CAAC,wBAAwB,CAAC,YAAY,CAAC,CAAC;QAElD,aAAa;QACb,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;QAExC,UAAU;QACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,EAAE,EAAE,KAAK,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;YAC7B,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,YAAY;YACtB,OAAO,EAAE,KAAK,IAAI,oOAAoO;YACtP,WAAW,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,UAAU;QACV,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC;YACd,EAAE,EAAE,KAAK,GAAG,CAAC,WAAW,GAAG,CAAC,CAAC;YAC7B,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,oBAAoB;YAC9B,OAAO,EAAE,KAAK,IAAI,wDAAwD,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,wCAAwC,IAAI,uJAAuJ;YACrT,WAAW,EAAE,KAAK;SACrB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,IAAI,eAAe,CAAC,CAAC;QACnE,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,OAAO;IACC,KAAK,CAAC,eAAe,CAAC,WAAmB;QAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QAClE,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,OAAO;QACP,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QAEpE,UAAU;QACV,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;QAE3E,aAAa;QACb,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,KAAK,WAAW,CAAC,CAAC;QAE7F,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,QAAQ;IACA,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,OAAe;QAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACzD,IAAI,MAAM,EAAE;YACR,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC;YACtB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;YAC3D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;SACxB;IACL,CAAC;IAED,UAAU;IACF,KAAK,CAAC,YAAY,CAAC,IAAY;QACnC,MAAM,KAAK,GAAG,KAAK,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAChD,MAAM,SAAS,GAAW;YACtB,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,IAAI;YACV,QAAQ,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;YACjD,OAAO,EAAE,KAAK,IAAI,kBAAkB,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,qBAAqB;YACpF,WAAW,EAAE,IAAI,CAAC,kBAAkB;SACvC,CAAC;QACF,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAE7B,WAAW;QACX,MAAM,IAAI,CAAC,8BAA8B,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;QAEnE,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;QACpC,IAAI,CAAC,aAAa,EAAE,CAAC;IACzB,CAAC;IAED,yBAAyB;IACjB,KAAK,CAAC,YAAY,CAAC,QAAgB;QACvC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM;YAAE,OAAO;QAEpB,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAClD,cAAc,MAAM,CAAC,IAAI,mBAAmB,EAC5C,EAAE,KAAK,EAAE,IAAI,EAAE,EACf,MAAM,EACN,IAAI,CACP,CAAC;QAEF,IAAI,OAAO,KAAK,MAAM,EAAE;YACpB,OAAO;SACV;QAED,IAAI;YACA,WAAW;YACX,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;YAE3D,aAAa;YACb,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC;YACzE,IAAI,SAAS,EAAE;gBACX,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;gBACzE,IAAI,QAAQ,EAAE;oBACV,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;oBAC9D,IAAI,WAAW,EAAE;wBACb,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;wBAExF,mBAAmB;wBACnB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;4BACzB,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;4BACnC,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;yBACzC;qBACJ;iBACJ;aACJ;YAED,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;YAC7D,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YACpC,IAAI,CAAC,aAAa,EAAE,CAAC;SAExB;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACxD;IACL,CAAC;IAED,mBAAmB;IAEX,KAAK,CAAC,aAAa,CAAC,GAAW;QACnC,IAAI;YACA,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,GAAG,CAAC,CAAC;YAEjC,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;gBAC9C,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,KAAK;aACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAClB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;gBAExD,IAAI;oBACA,qCAAqC;oBACrC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;oBAEzD,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;oBAE9C,MAAM,IAAI,GAAG,MAAM,wBAAG,CAAC,cAAc,CAAC;wBAClC,IAAI,EAAE,cAAI;wBACV,GAAG,EAAE,GAAG;qBACX,CAAC,CAAC;oBAEH,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;oBAEhC,+CAA+C;oBAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CACjC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,sBAAsB,CAAC,CAClF,CAAC;oBAEF,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;oBAExC,oBAAoB;oBACpB,MAAM,QAAQ,GAAgB,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE;wBAC/C,IAAI,UAAkB,CAAC;wBAEvB,IAAI,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE;4BACrC,kCAAkC;4BAClC,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC,CAAC;yBAC5D;6BAAM;4BACH,yBAAyB;4BACzB,UAAU,GAAG,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;yBACnD;wBAED,OAAO;4BACH,IAAI,EAAE,UAAU;4BAChB,SAAS,EAAE,UAAU,KAAK,MAAM,IAAI,UAAU,KAAK,QAAQ;4BAC3D,QAAQ,EAAE,KAAK,CAAC,YAAY;yBAC/B,CAAC;oBACN,CAAC,CAAC,CAAC;oBAEH,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;oBAEpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE;wBACvB,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;qBAC9B;oBAED,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;oBAEzD,sBAAsB;oBACtB,MAAM,UAAU,GAAG,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;oBAClD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;oBAExC,4BAA4B;oBAC5B,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE;wBACzB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;4BAC3B,IAAI,EAAE,iBAAiB;4BACvB,QAAQ,EAAE,QAAQ;4BAClB,UAAU,EAAE,UAAU;4BACtB,OAAO,EAAE,GAAG;yBACf,CAAC,CAAC;qBACN;oBAED,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;iBAEtD;gBAAC,OAAO,KAAK,EAAE;oBACZ,OAAO,CAAC,KAAK,CAAC,6BAA6B,EAAE,KAAK,CAAC,CAAC;oBAEpD,2BAA2B;oBAC3B,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;iBACtD;YACL,CAAC,CAAC,CAAC;SAEN;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;SACtD;IACL,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,QAAqB;QACzC,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,CAAC,OAAO;qBACzB,CAAC;oBACF,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;iBAC3B;gBAED,IAAI,MAAM,EAAE;oBACR,aAAa;oBACb,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;IAEO,wBAAwB,CAAC,GAAW,EAAE,MAAc;QAC5D,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,CAAC,kBAAkB;SAChD,CAAC;IACN,CAAC;IAEW,KAAK,CAAC,aAAa,CAAC,GAAW,EAAE,QAAkB;QAC3D,IAAI;YACA,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAC;YAE7C,IAAI,YAAY,GAAG,CAAC,CAAC;YACrB,IAAI,SAAS,GAAG,CAAC,CAAC;YAElB,QAAQ;YACR,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;gBAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;gBAC9C,KAAK,EAAE,QAAQ,QAAQ,CAAC,MAAM,MAAM;gBACpC,WAAW,EAAE,KAAK;aACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;gBAClB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;oBACtC,MAAM,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;oBAC3B,MAAM,eAAe,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;oBACpD,QAAQ,CAAC,MAAM,CAAC;wBACZ,SAAS,EAAE,eAAe;wBAC1B,OAAO,EAAE,SAAS,MAAM,KAAK,CAAC,GAAG,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG;qBAC3D,CAAC,CAAC;oBAEH,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,EAAE,CAAC,CAAC;oBACpC,IAAI;wBACA,MAAM,WAAW,GAAG,IAAI,CAAC,wBAAwB,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;wBAC/D,MAAM,IAAI,CAAC,kBAAkB,CAAC,GAAG,EAAE,WAAW,CAAC,WAAW,EAAE,WAAW,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;wBAC5F,YAAY,EAAE,CAAC;wBACf,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,EAAE,CAAC,CAAC;qBACtC;oBAAC,OAAO,KAAK,EAAE;wBACZ,SAAS,EAAE,CAAC;wBACZ,OAAO,CAAC,KAAK,CAAC,aAAa,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC;wBAC5C,mBAAmB;qBACtB;iBACJ;YACL,CAAC,CAAC,CAAC;YAEH,SAAS;YACT,IAAI,SAAS,KAAK,CAAC,EAAE;gBACjB,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,QAAQ,YAAY,MAAM,CAAC,CAAC;aACpE;iBAAM;gBACH,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,SAAS,YAAY,SAAS,SAAS,MAAM,CAAC,CAAC;aACnF;SAEJ;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,KAAK,EAAE,CAAC,CAAC;SACtD;IACL,CAAC;IAEG,OAAO;IACC,aAAa;QACjB,oBAAoB;QACpB,IAAI,IAAI,CAAC,iBAAiB,EAAE;YACxB,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;YACpC,OAAO;SACV;QAED,IAAI;YACA,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,iBAAiB,EAAE,CAAC;SACtD;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;SAC1C;IACL,CAAC;IAEO,iBAAiB;QACrB,QAAQ,IAAI,CAAC,WAAW,EAAE;YACtB,KAAK,UAAU;gBACX,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;oBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,YAAY,EAAE,IAAI,CAAC,YAAY;iBAClC,CAAC,CAAC;YACP,KAAK,WAAW;gBACZ,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC3F,OAAO,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC;oBAC5B,SAAS,EAAE,gBAAgB;iBAC9B,CAAC,CAAC;YACP,KAAK,YAAY;gBACb,MAAM,cAAc,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,gBAAgB,CAAC,CAAC;gBAC/E,MAAM,eAAe,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAClF,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,IAAI,CAAC,iBAAiB,CAAC,CAAC;gBAE/F,OAAO,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;oBAC7B,OAAO,EAAE,cAAc;oBACvB,QAAQ,EAAE,eAAe;oBACzB,UAAU,EAAE,iBAAiB;iBAChC,CAAC,CAAC;YACP,KAAK,SAAS;gBACV,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACrF,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBACjG,MAAM,mBAAmB,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,qBAAqB,CAAC,CAAC;gBAE9F,eAAe;gBACf,MAAM,sBAAsB,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;gBAEnH,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;oBAC1B,SAAS,EAAE,gBAAgB;oBAC3B,OAAO,EAAE,gBAAgB;oBACzB,aAAa,EAAE,sBAAsB;oBACrC,mBAAmB,EAAE,mBAAmB;oBACxC,oBAAoB,EAAE,IAAI,CAAC,2BAA2B;oBACtD,mBAAmB,EAAE,KAAK;iBAC7B,CAAC,CAAC;YACP;gBACI,OAAO,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;oBAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,YAAY,EAAE,IAAI,CAAC,YAAY;iBAClC,CAAC,CAAC;SACV;IACL,CAAC;IAEO,KAAK,CAAC,mBAAmB,CAAC,QAAgB;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,EAAE;YACT,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO;SACV;QAED,IAAI;YACA,YAAY;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;gBACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAC7C,OAAO;aACV;YAED,8BAA8B;YAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;gBAC/C,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACrC,cAAc,EAAE,IAAI;gBACpB,gBAAgB,EAAE,KAAK;gBACvB,aAAa,EAAE,KAAK;gBACpB,SAAS,EAAE,UAAU;gBACrB,KAAK,EAAE,KAAK,MAAM,CAAC,IAAI,QAAQ;aAClC,CAAC,CAAC;YAEH,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC/B,UAAU;gBACV,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC/C,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;aACtF;SAEJ;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;SAC3D;IACL,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAAC,QAAgB;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,EAAE;YACT,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;YAC1C,OAAO;SACV;QAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO;SACV;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACzC,OAAO;SACV;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW,EAAE;YACd,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;YAC5C,OAAO;SACV;QAED,SAAS;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAExF,IAAI;YACA,WAAW;YACX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;gBAC1B,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,CAAC;gBACnD,SAAS;gBACT,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;gBACvC,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;gBACtD,OAAO;gBACP,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;aAC/D;YAED,iBAAiB;YACjB,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;YACnE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;SAElD;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACxD;IACL,CAAC;IAEO,KAAK,CAAC,YAAY,CAAC,SAAmB,EAAE,WAAmB,EAAE,UAAkB;QACnF,IAAI;YACA,IAAI,CAAC,IAAI,CAAC,kBAAkB,EAAE;gBAC1B,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC;gBAC1C,OAAO;aACV;YAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE;gBACtB,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,iBAAiB,CAAC,CAAC;gBAClD,OAAO;aACV;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,kBAAkB,CAAC,CAAC;YAC9E,IAAI,CAAC,SAAS,EAAE;gBACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC;gBACxC,OAAO;aACV;YAED,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;YACzE,IAAI,CAAC,QAAQ,EAAE;gBACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBACzC,OAAO;aACV;YAED,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;YAC9D,IAAI,CAAC,WAAW,EAAE;gBACd,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBAC5C,OAAO;aACV;YAED,YAAY;YACZ,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;YACrF,IAAI,eAAe,CAAC,MAAM,KAAK,SAAS,CAAC,MAAM,EAAE;gBAC7C,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC;gBAC5C,OAAO;aACV;YAED,UAAU;YACV,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;YAC1F,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,eAAe,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;YAE9D,oBAAoB;YACpB,MAAM,WAAW,GAAa,EAAE,CAAC;YACjC,KAAK,MAAM,MAAM,IAAI,eAAe,EAAE;gBAClC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAC1F,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;gBAE/D,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE;oBAC3B,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;oBACnD,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAClC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;iBAChD;qBAAM;oBACH,iBAAiB;oBACjB,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;oBAC9D,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;oBAClC,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;iBAChD;aACJ;YAED,SAAS;YACT,MAAM,YAAY,GAAG,IAAI,QAAQ,CAAC,SAAS,IAAI,QAAQ,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,IAAI,UAAU,EAAE,CAAC;YAE/F,YAAY;YACZ,MAAM,SAAS,GAAiB;gBAC5B,EAAE,EAAE,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE;gBACzB,IAAI,EAAE,WAAW;gBACjB,IAAI,EAAE,OAAO;gBACb,SAAS,EAAE,YAAY;gBACvB,WAAW,EAAE,IAAI,CAAC,kBAAkB;aACvC,CAAC;YAEF,aAAa;YACb,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAEnC,WAAW;YACX,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE;gBAC9B,MAAM,IAAI,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC;aAC7C;YAED,OAAO;YACP,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,QAAQ,eAAe,CAAC,MAAM,eAAe,UAAU,EAAE,CAAC,CAAC;YAEhG,OAAO;YACP,IAAI,CAAC,aAAa,EAAE,CAAC;SAExB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;YACpC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACxD;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QAC/C,IAAI;YACA,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;YACzD,IAAI,CAAC,MAAM;gBAAE,OAAO;YAEpB,WAAW;YACX,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;YAE3D,aAAa;YACb,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC;YACzE,IAAI,SAAS,EAAE;gBACX,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;gBACzE,IAAI,QAAQ,EAAE;oBACV,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;oBAC9D,IAAI,WAAW,EAAE;wBACb,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;wBAExF,mBAAmB;wBACnB,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;4BACzB,MAAM,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;4BACnC,OAAO,CAAC,GAAG,CAAC,cAAc,QAAQ,EAAE,CAAC,CAAC;yBACzC;qBACJ;iBACJ;aACJ;YAED,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;SAE3C;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACvC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,wBAAwB,CAAC,QAAgB;QACnD,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,EAAE;YACT,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO;SACV;QAED,IAAI;YACA,YAAY;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;gBACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,CAAC;gBAC3C,OAAO;aACV;YAED,kBAAkB;YAClB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC5C,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,mBAAmB,EAAE,SAAS,EAAE,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAC;SAE7F;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;SACzD;IACL,CAAC;IAED;;;;OAIG;IACK,KAAK,CAAC,mBAAmB,CAAC,IAAqB,EAAE,EAAU;QAC/D,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,EAAE;YACT,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC;YAC9C,OAAO;SACV;QAED,IAAI;YACA,YAAY;YACZ,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;gBACvC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC;gBAC7C,OAAO;aACV;YAED,8BAA8B;YAC9B,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC;gBAC/C,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;gBACrC,cAAc,EAAE,IAAI;gBACpB,gBAAgB,EAAE,KAAK;gBACvB,aAAa,EAAE,KAAK;gBACpB,SAAS,EAAE,UAAU;gBACrB,KAAK,EAAE,KAAK,MAAM,CAAC,IAAI,QAAQ;aAClC,CAAC,CAAC;YAEH,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE;gBAC/B,UAAU;gBACV,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gBACrE,MAAM,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC;gBAC/C,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,UAAU,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;aACtF;SAEJ;QAAC,OAAO,KAAK,EAAE;YACZ,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,KAAK,EAAE,CAAC,CAAC;SAC3D;IACL,CAAC;IAED;;OAEG;IACK,uBAAuB,CAAC,MAAoB;QAChD,MAAM,SAAS,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC;QACzE,IAAI,CAAC,SAAS;YAAE,OAAO,IAAI,CAAC;QAE5B,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,MAAM,WAAW,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC9D,IAAI,CAAC,WAAW;YAAE,OAAO,IAAI,CAAC;QAE9B,gBAAgB;QAChB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;QACnE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;QAEtC,MAAM,UAAU,GAAG,SAAS,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC7E,CAAC;IAEG,KAAK,CAAC,qBAAqB,CAAC,QAAgB,EAAE,QAAgB,EAAE,QAAgB;QACpF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,KAAK,EAAE;YAClC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;YACnD,OAAO;SACV;QAED,SAAS;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;YACjD,OAAO;SACV;QAED,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;YAC9C,KAAK,EAAE,gBAAgB,MAAM,CAAC,IAAI,EAAE;YACpC,WAAW,EAAE,KAAK;SACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,IAAI;gBACA,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;gBAEtD,kBAAkB;gBAClB,MAAM,IAAI,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC;gBAEnD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAEnD,WAAW;gBACX,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACvB,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,iBAAiB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;gBAErE,gBAAgB;gBAChB,IAAI,CAAC,aAAa,EAAE,CAAC;aAExB;YAAC,OAAO,KAAK,EAAE;gBACZ,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;gBAEpC,sBAAsB;gBACtB,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;oBACrC,MAAM,CAAC,MAAM,CAAC,kBAAkB,CAAC,iBAAiB,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;iBACpE;qBAAM;oBACH,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;iBAC5D;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,KAAK,CAAC,uBAAuB,CAAC,QAAgB,EAAE,OAAe,EAAE,UAAkB;QACvF,MAAM,MAAM,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC;QAC/D,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE;YACpC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC;YAChD,OAAO;SACV;QAED,SAAS;QACT,MAAM,QAAQ,GAAG,IAAI,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,gBAAgB,CAAC,CAAC;YACjD,OAAO;SACV;QAED,MAAM,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YAC7B,QAAQ,EAAE,MAAM,CAAC,gBAAgB,CAAC,YAAY;YAC9C,KAAK,EAAE,sBAAsB,MAAM,CAAC,IAAI,EAAE;YAC1C,WAAW,EAAE,KAAK;SACrB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;YAClB,IAAI;gBACA,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;gBAEtD,WAAW;gBACX,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;oBAC1B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;iBAC/B;gBAED,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,CAAC,CAAC;gBAE7D,kBAAkB;gBAClB,MAAM,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAEnD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;gBAEzD,mBAAmB;gBACnB,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAE3C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;gBAEzD,mBAAmB;gBACnB,MAAM,IAAI,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC;gBAExC,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;gBAE1D,oBAAoB;gBACpB,MAAM,IAAI,CAAC,qBAAqB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;gBAEvD,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;gBAEnD,sBAAsB;gBACtB,MAAM,CAAC,IAAI,GAAG,KAAK,CAAC;gBACpB,MAAM,CAAC,QAAQ,GAAG,IAAI,CAAC;gBACvB,MAAM,IAAI,CAAC,sBAAsB,EAAE,CAAC;gBAEpC,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,sBAAsB,MAAM,CAAC,IAAI,OAAO,UAAU,EAAE,CAAC,CAAC;gBAE3F,gBAAgB;gBAChB,IAAI,CAAC,aAAa,EAAE,CAAC;aAExB;YAAC,OAAO,KAAK,EAAE;gBACZ,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;gBACrC,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,SAAS,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBAEzD,sBAAsB;gBACtB,IAAI;oBACA,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE;wBACvB,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;qBAClE;iBACJ;gBAAC,OAAO,YAAY,EAAE;oBACnB,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,YAAY,CAAC,CAAC;iBACjD;aACJ;QACL,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,QAAgB,EAAE,UAAkB;QAChE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAC;YAEhC,IAAI,CAAC,+BAA+B,UAAU,EAAE,EAAE;gBAC9C,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE;oBACP,OAAO,CAAC,KAAK,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;oBACrC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC3C,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;gBAC3B,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,OAAe;QACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAE5B,IAAI,CAAC,yBAAyB,OAAO,EAAE,EAAE;gBACrC,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE;oBACP,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;oBACpC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC3C,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QAC7C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAE5B,MAAM,QAAQ,GAAG;gBACb,WAAW;gBACX,6CAA6C,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,GAAG;aAC9E,CAAC;YAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;gBACxB,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE;oBACP,oBAAoB;oBACpB,IAAI,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAC,EAAE;wBAC9E,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;wBAC5B,OAAO,EAAE,CAAC;wBACV,OAAO;qBACV;oBAED,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;oBACpC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC3C,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,qBAAqB,CAAC,QAAgB,EAAE,UAAkB;QACpE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;YAE/B,IAAI,CAAC,sBAAsB,UAAU,UAAU,EAAE;gBAC7C,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACzB,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;gBAC3C,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;gBAE3C,IAAI,KAAK,EAAE;oBACP,OAAO,CAAC,KAAK,CAAC,aAAa,EAAE,KAAK,CAAC,CAAC;oBACpC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;oBAC3C,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;gBAC1B,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,GAAW;QACtC,IAAI;YACA,MAAM,aAAa,GAAG,MAAM,wBAAG,CAAC,aAAa,CAAC;gBAC1C,EAAE,EAAE,EAAE;gBACN,GAAG,EAAE,GAAG;gBACR,QAAQ,EAAE,KAAK;aAClB,CAAC,CAAC;YAEH,IAAI,CAAC,aAAa,EAAE;gBAChB,yBAAyB;gBACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;gBAChD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE;oBACzB,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;oBACjE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;oBAC1D,IAAI,KAAK,EAAE;wBACP,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC;qBACnB;iBACJ;gBACD,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,CAAC;aAC/B;YAED,OAAO,aAAa,CAAC;SACxB;QAAC,OAAO,KAAK,EAAE;YACZ,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,aAAa,KAAK,EAAE,CAAC,CAAC;SACzC;IACL,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,oBAAoB,CAAC,QAAgB;QAC/C,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;YAEpC,aAAa;YACb,IAAI,CAAC,YAAY,EAAE;gBACf,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE;gBAC3C,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;gBAExC,SAAS;gBACT,IAAI,CAAC,UAAU,EAAE;oBACb,GAAG,EAAE,QAAQ;oBACb,QAAQ,EAAE,MAAM;iBACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;oBACzB,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;oBAC3C,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;oBAE3C,IAAI,KAAK,EAAE;wBACP,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;wBACvC,MAAM,CAAC,IAAI,KAAK,CAAC,aAAa,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;wBAC1D,OAAO;qBACV;oBAED,YAAY;oBACZ,IAAI,MAAM,CAAC,QAAQ,CAAC,uBAAuB,CAAC,EAAE;wBAC1C,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;wBAC5B,OAAO,EAAE,CAAC;qBACb;yBAAM,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;wBAChG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;wBAC1B,OAAO,EAAE,CAAC;qBACb;yBAAM;wBACH,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;wBACnC,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC,CAAC;qBACxC;gBACL,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,cAAc,CAAC,QAAgB;QACzC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YAEjC,IAAI,CAAC,eAAe,EAAE;gBAClB,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;gBACzB,IAAI,KAAK,EAAE;oBACP,OAAO,CAAC,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;oBAClC,MAAM,CAAC,KAAK,CAAC,CAAC;oBACd,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;gBACpC,OAAO,EAAE,CAAC;YACd,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,6BAA6B,CAAC,QAAgB;QACxD,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnC,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;YAE1C,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,EAAE,CAAC,CAAC;YAEpC,WAAW;YACX,IAAI,CAAC,wBAAwB,EAAE;gBAC3B,GAAG,EAAE,QAAQ;gBACb,QAAQ,EAAE,MAAM;aACnB,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE;gBAC3C,IAAI,WAAW,EAAE;oBACb,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAC;oBAC7C,MAAM,CAAC,IAAI,KAAK,CAAC,gBAAgB,YAAY,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;oBACzE,OAAO;iBACV;gBAED,SAAS;gBACT,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE;oBACtB,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;oBAC5B,MAAM,CAAC,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC;oBAC/B,OAAO;iBACV;gBAED,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;gBAEvC,aAAa;gBACb,MAAM,QAAQ,GAAG;oBACb,WAAW;oBACX,0CAA0C,IAAI,IAAI,EAAE,CAAC,cAAc,EAAE,GAAG;oBACxE,UAAU;iBACb,CAAC;gBAEF,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;oBACxB,GAAG,EAAE,QAAQ;oBACb,QAAQ,EAAE,MAAM;iBACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;oBACzB,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;oBACpC,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;oBAEpC,IAAI,KAAK,EAAE;wBACP,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;wBACvC,MAAM,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;wBAC3C,OAAO;qBACV;oBAED,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBAC7B,OAAO,EAAE,CAAC;gBACd,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;QACP,CAAC,CAAC,CAAC;IACP,CAAC;IAED;;OAEG;IACK,UAAU,CAAC,QAAgB,EAAE,OAAY,EAAE,MAAW;QAC1D,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;QAE1C,IAAI,CAAC,UAAU,EAAE;YACb,GAAG,EAAE,QAAQ;YACb,QAAQ,EAAE,MAAM;SACnB,EAAE,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,EAAE;YACrC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YAC3C,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,UAAU,CAAC,CAAC;YAE3C,IAAI,SAAS,EAAE;gBACX,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBAC/B,iBAAiB;gBACjB,MAAM,CAAC,IAAI,KAAK,CAAC,UAAU,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;gBACnD,OAAO;aACV;YAED,eAAe;YACf,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC1B,OAAO,EAAE,CAAC;QACd,CAAC,CAAC,CAAC;IACP,CAAC;CAEA;AA7uED,kCA6uEC"} \ 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/src/panels/ConfigPanel.ts b/src/panels/ConfigPanel.ts index 199c89f..474ea45 100755 --- a/src/panels/ConfigPanel.ts +++ b/src/panels/ConfigPanel.ts @@ -9,7 +9,10 @@ import { ContainerView } from './views/ContainerView'; import { ConfigView } from './views/ConfigView'; import { ModuleFolder } from './types/CommonTypes'; +// ============================================= // 数据模型接口 +// ============================================= + interface Project { id: string; name: string; @@ -42,27 +45,30 @@ interface GitFileTree { children?: GitFileTree[]; } -// Git 分支接口 interface GitBranch { name: string; isCurrent: boolean; selected?: boolean; } -// 修改 ProjectData 接口,使用统一的 moduleFolders interface ProjectData { projects: Project[]; aircrafts: Aircraft[]; containers: Container[]; configs: Config[]; - moduleFolders: ModuleFolder[]; // 统一的模块文件夹数据 + moduleFolders: ModuleFolder[]; } +// ============================================= +// 主面板类 +// ============================================= + export class ConfigPanel { public static currentPanel: ConfigPanel | undefined; public readonly panel: vscode.WebviewPanel; private readonly extensionUri: vscode.Uri; + // 视图状态管理 private currentView: 'projects' | 'aircrafts' | 'containers' | 'configs' = 'projects'; private currentProjectId: string = ''; private currentAircraftId: string = ''; @@ -74,15 +80,11 @@ export class ConfigPanel { private aircrafts: Aircraft[] = []; private containers: Container[] = []; private configs: Config[] = []; - private moduleFolders: ModuleFolder[] = []; // 统一的模块文件夹数据 - - // Git 文件树 + private moduleFolders: ModuleFolder[] = []; private currentModuleFolderFileTree: GitFileTree[] = []; - - // 项目存储路径映射 private projectPaths: Map = new Map(); - // Webview 状态跟踪 + // 状态管理 private isWebviewDisposed: boolean = false; // 视图实例 @@ -91,6 +93,10 @@ export class ConfigPanel { private readonly containerView: ContainerView; private readonly configView: ConfigView; + // ============================================= + // 公共方法 + // ============================================= + public static createOrShow(extensionUri: vscode.Uri) { const column = vscode.window.activeTextEditor?.viewColumn || vscode.ViewColumn.One; @@ -116,9 +122,9 @@ export class ConfigPanel { public constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri) { this.panel = panel; this.extensionUri = extensionUri; - this.isWebviewDisposed = false; // 初始化状态 + this.isWebviewDisposed = false; - // 初始化各个视图 + // 初始化视图 this.projectView = new ProjectView(extensionUri); this.aircraftView = new AircraftView(extensionUri); this.containerView = new ContainerView(extensionUri); @@ -128,198 +134,50 @@ export class ConfigPanel { this.setupMessageListener(); this.panel.onDidDispose(() => { - this.isWebviewDisposed = true; // 标记为已销毁 + this.isWebviewDisposed = true; ConfigPanel.currentPanel = undefined; }); } + // ============================================= + // 工具方法 - 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}`; + } + + // ============================================= + // Webview 消息处理 + // ============================================= + private setupMessageListener() { this.panel.webview.onDidReceiveMessage(async (data) => { console.log('📨 收到Webview消息:', data); - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,忽略消息'); return; } try { - switch (data.type) { - case 'openExistingProject': - await this.openExistingProject(); - break; - - case 'configureProject': - const selectedPath = await this.selectProjectPath(data.projectId, data.projectName); - if (selectedPath) { - this.currentView = 'aircrafts'; - this.currentProjectId = data.projectId; - this.updateWebview(); - } - break; - - case 'openProject': - // 已配置的项目直接打开 - this.currentView = 'aircrafts'; - this.currentProjectId = data.projectId; - this.updateWebview(); - break; - - case 'openAircraftConfig': - this.currentView = 'containers'; - this.currentProjectId = data.projectId; - this.currentAircraftId = data.aircraftId; - this.updateWebview(); - break; - - case 'openContainerConfig': - this.currentView = 'configs'; - this.currentContainerId = data.containerId; - this.updateWebview(); - break; - - // 修复返回按钮的消息处理 - case 'goBackToProjects': - this.currentView = 'projects'; - // 清空当前选择的ID - this.currentProjectId = ''; - this.currentAircraftId = ''; - this.currentContainerId = ''; - this.currentModuleFolderId = ''; - this.updateWebview(); - break; - - case 'goBackToAircrafts': - this.currentView = 'aircrafts'; - // 保持 currentProjectId,清空其他ID - this.currentAircraftId = ''; - this.currentContainerId = ''; - this.updateWebview(); - break; - - case 'goBackToContainers': - this.currentView = 'containers'; - // 保持 currentProjectId 和 currentAircraftId,清空 currentContainerId - this.currentContainerId = ''; - this.updateWebview(); - break; - - case 'updateProjectName': - await this.updateProjectName(data.projectId, data.name); - break; - - case 'createProject': - await this.createProject(data.name); - break; - - case 'updateAircraftName': - await this.updateAircraftName(data.aircraftId, data.name); - break; - - case 'createAircraft': - await this.createAircraft(data.name); - break; - - case 'updateContainerName': - await this.updateContainerName(data.containerId, data.name); - break; - - case 'createContainer': - await this.createContainer(data.name); - break; - - case 'updateConfigName': - await this.updateConfigName(data.configId, data.name); - break; - - case 'createConfig': - await this.createConfig(data.name); - break; - - case 'deleteProject': - await this.deleteProject(data.projectId); - break; - - case 'deleteAircraft': - await this.deleteAircraft(data.aircraftId); - break; - - case 'deleteContainer': - await this.deleteContainer(data.containerId); - break; - - case 'deleteConfig': - await this.deleteConfig(data.configId); - break; - - // Git 仓库管理功能 - case 'fetchBranches': - console.log('🌿 获取分支列表:', data.url); - await this.fetchBranches(data.url); - break; - - case 'cloneBranches': - console.log('🚀 克隆选中的分支:', data); - await this.cloneBranches(data.url, data.branches); - break; - - case 'cancelBranchSelection': - console.log('❌ 取消分支选择'); - this.updateWebview(); - break; - - case 'loadModuleFolder': - await this.loadModuleFolder(data.folderId); - break; - - case 'syncGitModuleFolder': - await this.syncGitModuleFolder(data.folderId); - break; - - case 'deleteModuleFolder': - await this.deleteModuleFolder(data.folderId); - break; - - case 'importGitFile': - await this.importGitFile(data.filePath); - break; - - case 'openModuleFolderInVSCode': - await this.openTheModuleFolder(data.moduleType, data.folderId); - break; - - case 'openConfigFileInVSCode': - await this.openConfigFileInVSCode(data.configId); - break; - - case 'mergeConfigs': - await this.mergeConfigs(data.configIds, data.displayName, data.folderName); - break; - - case 'deleteMergedFolder': - await this.deleteModuleFolder(data.folderId); - break; - - case 'openMergedFolderInVSCode': - await this.openTheModuleFolder('local', data.folderId); - break; - - case 'loadMergedFolder': - await this.openTheModuleFolder('local', data.folderId); - break; - - case 'openTheModuleFolder': - await this.openTheModuleFolder(data.moduleType, data.id); - break; - - case 'uploadGitModuleFolder': - await this.uploadGitModuleFolder(data.folderId, data.username, data.password); - break; - - case 'uploadLocalModuleFolder': - await this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName); - break; - } + await this.handleWebviewMessage(data); } catch (error) { console.error('处理 Webview 消息时出错:', error); if (!this.isWebviewDisposed) { @@ -329,287 +187,705 @@ export class ConfigPanel { }); } - // === 目录创建方法 === + private async handleWebviewMessage(data: any): Promise { + const messageHandlers: { [key: string]: (data: any) => Promise } = { + // 导航相关 + 'openExistingProject': () => this.openExistingProject(), + 'configureProject': (data) => this.handleConfigureProject(data), + 'openProject': (data) => this.handleOpenProject(data), + 'openAircraftConfig': (data) => this.handleOpenAircraftConfig(data), + 'openContainerConfig': (data) => this.handleOpenContainerConfig(data), + 'goBackToProjects': () => this.handleGoBackToProjects(), + 'goBackToAircrafts': () => this.handleGoBackToAircrafts(), + 'goBackToContainers': () => this.handleGoBackToContainers(), - /** - * 创建飞行器目录 - */ - private async createAircraftDirectory(aircraft: Aircraft): Promise { - try { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建飞行器目录'); - return; - } + // 项目管理 + 'updateProjectName': (data) => this.updateProjectName(data.projectId, data.name), + 'createProject': (data) => this.createProject(data.name), + 'deleteProject': (data) => this.deleteProject(data.projectId), - 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}`); - } - } + // 飞行器管理 + 'updateAircraftName': (data) => this.updateAircraftName(data.aircraftId, data.name), + 'createAircraft': (data) => this.createAircraft(data.name), + 'deleteAircraft': (data) => this.deleteAircraft(data.aircraftId), - /** - * 创建容器目录 - */ - private async createContainerDirectory(container: Container): Promise { - try { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - console.warn('未找到对应的飞行器,跳过创建容器目录'); - return; - } + // 容器管理 + 'updateContainerName': (data) => this.updateContainerName(data.containerId, data.name), + 'createContainer': (data) => this.createContainer(data.name), + 'deleteContainer': (data) => this.deleteContainer(data.containerId), - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - console.warn('未找到项目路径,跳过创建容器目录'); - return; - } + // 配置管理 + 'updateConfigName': (data) => this.updateConfigName(data.configId, data.name), + 'createConfig': (data) => this.createConfig(data.name), + 'deleteConfig': (data) => this.deleteConfig(data.configId), + 'openConfigFileInVSCode': (data) => this.openConfigFileInVSCode(data.configId), + 'mergeConfigs': (data) => this.mergeConfigs(data.configIds, data.displayName, data.folderName), - // 构建路径:项目路径/飞行器名/容器名 - const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name); - const containerDir = vscode.Uri.joinPath(aircraftDir, container.name); - - // 确保飞行器目录存在 - try { - await vscode.workspace.fs.createDirectory(aircraftDir); - } catch (error) { - // 目录可能已存在,忽略错误 - } - - // 创建容器目录 - await vscode.workspace.fs.createDirectory(containerDir); - console.log(`✅ 创建容器目录: ${containerDir.fsPath}`); - - } catch (error) { - console.error(`创建容器目录失败: ${error}`); - } - } + // Git 仓库管理 + 'fetchBranches': (data) => this.fetchBranches(data.url), + 'cloneBranches': (data) => this.cloneBranches(data.url, data.branches), + 'cancelBranchSelection': () => this.handleCancelBranchSelection(), - /** - * 确保容器目录存在 - */ - private async ensureContainerDirectoryExists(containerId: string): Promise { - try { - const container = this.containers.find(c => c.id === containerId); - if (!container) return; + // 模块文件夹管理 + 'loadModuleFolder': (data) => this.loadModuleFolder(data.folderId), + 'syncGitModuleFolder': (data) => this.syncGitModuleFolder(data.folderId), + 'deleteModuleFolder': (data) => this.deleteModuleFolder(data.folderId), + 'importGitFile': (data) => this.importGitFile(data.filePath), + 'openTheModuleFolder': (data) => this.openTheModuleFolder(data.moduleType, data.id), - 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}`); - } - } - - // === Git 仓库管理方法 === - - /** - * 添加 Git 模块文件夹到容器目录 - */ - private async addGitModuleFolder(url: string, displayName: string, folderName: string, branch?: string): Promise { - try { - // 验证 URL - if (!url || !url.startsWith('http')) { - vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL'); - return; - } - - if (!this.currentContainerId) { - vscode.window.showErrorMessage('请先选择容器'); - return; - } - - const folderId = 'git-' + Date.now(); - - // 构建本地路径 - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } - - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } - - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - vscode.window.showErrorMessage('未找到项目路径'); - return; - } - - // 构建相对路径(从项目路径开始)- 使用 folderName 作为实际文件夹名 - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - - // 完整路径用于实际操作 - 使用 folderName 作为实际文件夹名 - const localPath = path.join(projectPath, aircraft.name, container.name, folderName); - - console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`); - console.log(`📁 相对路径: ${relativePath}`); - - // 修复:检查是否已存在相同实际路径的模块文件夹,而不是显示名称 - const existingFolder = this.moduleFolders.find(folder => - folder.localPath === relativePath && folder.containerId === this.currentContainerId - ); - if (existingFolder) { - vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`); - return; - } - - const newFolder: ModuleFolder = { - id: folderId, - name: displayName, // 使用显示名称 - type: 'git', - localPath: relativePath, // 存储相对路径 - containerId: this.currentContainerId + // 上传功能 + 'uploadGitModuleFolder': (data) => this.uploadGitModuleFolder(data.folderId, data.username, data.password), + 'uploadLocalModuleFolder': (data) => this.uploadLocalModuleFolder(data.folderId, data.repoUrl, data.branchName) }; - // 显示进度 - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在克隆仓库: ${displayName}`, - cancellable: false - }, async (progress) => { - progress.report({ increment: 0 }); + const handler = messageHandlers[data.type]; + if (handler) { + await handler(data); + } else { + console.warn(`未知的消息类型: ${data.type}`); + } + } - 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; + private async handleConfigureProject(data: any): Promise { + const selectedPath = await this.selectProjectPath(data.projectId, data.projectName); + if (selectedPath) { + this.currentView = 'aircrafts'; + this.currentProjectId = data.projectId; + this.updateWebview(); + } + } + + private async handleOpenProject(data: any): Promise { + this.currentView = 'aircrafts'; + this.currentProjectId = data.projectId; + this.updateWebview(); + } + + private async handleOpenAircraftConfig(data: any): Promise { + this.currentView = 'containers'; + this.currentProjectId = data.projectId; + this.currentAircraftId = data.aircraftId; + this.updateWebview(); + } + + private async handleOpenContainerConfig(data: any): Promise { + this.currentView = 'configs'; + this.currentContainerId = data.containerId; + this.updateWebview(); + } + + private async handleGoBackToProjects(): Promise { + this.currentView = 'projects'; + this.currentProjectId = ''; + this.currentAircraftId = ''; + this.currentContainerId = ''; + this.currentModuleFolderId = ''; + this.updateWebview(); + } + + private async handleGoBackToAircrafts(): Promise { + this.currentView = 'aircrafts'; + this.currentAircraftId = ''; + this.currentContainerId = ''; + this.updateWebview(); + } + + private async handleGoBackToContainers(): Promise { + this.currentView = 'containers'; + this.currentContainerId = ''; + this.updateWebview(); + } + + private async handleCancelBranchSelection(): Promise { + console.log('❌ 取消分支选择'); + this.updateWebview(); + } + + // ============================================= + // 项目管理方法 + // ============================================= + + private async updateProjectName(projectId: string, newName: string): Promise { + const project = this.projects.find(p => p.id === projectId); + if (project) { + project.name = newName; + vscode.window.showInformationMessage(`项目名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + + private async createProject(name: string): Promise { + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('p', this.projects); + const newProject: Project = { + id: newId, + name: name + }; + this.projects.push(newProject); + + // 设置当前项目 + this.currentProjectId = newId; + + vscode.window.showInformationMessage(`新建项目: ${name}`); + this.updateWebview(); + } + + 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(); + } + + // ============================================= + // 飞行器管理方法 + // ============================================= + + private async updateAircraftName(aircraftId: string, newName: string): Promise { + const aircraft = this.aircrafts.find(a => a.id === aircraftId); + if (aircraft) { + aircraft.name = newName; + vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + + private async createAircraft(name: string): Promise { + if (!this.currentProjectId) { + vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目'); + return; + } + + // 使用新的 ID 生成方法 + 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); + 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(); + } + + // ============================================= + // 容器管理方法 + // ============================================= + + private async updateContainerName(containerId: string, newName: string): Promise { + const container = this.containers.find(c => c.id === containerId); + if (container) { + container.name = newName; + vscode.window.showInformationMessage(`容器名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + + private async createContainer(name: string): Promise { + if (!this.currentAircraftId) { + vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器'); + return; + } + + // 使用新的 ID 生成方法 + 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); + + 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(); + } + + // ============================================= + // 配置管理方法 + // ============================================= + + private async updateConfigName(configId: string, newName: string): Promise { + const config = this.configs.find(c => c.id === configId); + if (config) { + config.name = newName; + vscode.window.showInformationMessage(`配置名称更新: ${newName}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + } + + private async createConfig(name: string): Promise { + // 使用新的 ID 生成方法 + 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); + vscode.window.showInformationMessage(`新建配置: ${name}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + } + + private async deleteConfig(configId: string): Promise { + const config = this.configs.find(c => c.id === configId); + if (!config) return; + + const confirm = await vscode.window.showWarningMessage( + `确定要删除配置文件 "${config.name}" 吗?这将同时删除磁盘上的文件。`, + { modal: true }, + '确定删除', + '取消' + ); + + if (confirm !== '确定删除') { + return; + } + + try { + this.configs = this.configs.filter(c => c.id !== configId); + await this.deleteConfigFileFromDisk(config); + + vscode.window.showInformationMessage(`删除配置: ${config.name}`); + await this.saveCurrentProjectData(); + this.updateWebview(); + + } catch (error) { + vscode.window.showErrorMessage(`删除配置文件失败: ${error}`); + } + } + + private async mergeConfigs(configIds: string[], displayName: string, folderName: string): Promise { + if (!this.currentContainerId) { + vscode.window.showErrorMessage('未找到当前容器'); + return; + } + + if (configIds.length < 2) { + vscode.window.showErrorMessage('请至少选择两个配置文件进行合并'); + 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('未找到相关项目数据'); + return; + } + + const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); + 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 }); + + for (const config of selectedConfigs) { + const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); + const targetPath = path.join(mergeFolderPath, config.fileName); + + if (fs.existsSync(sourcePath)) { + await fs.promises.copyFile(sourcePath, targetPath); + } else { + await fs.promises.writeFile(targetPath, config.content || ''); } + } - if (dirExists) { - const dirContents = await fs.promises.readdir(localPath); - if (dirContents.length > 0) { - const confirm = await vscode.window.showWarningMessage( - `目标目录 "${folderName}" 不为空,确定要覆盖吗?`, - { modal: true }, - '确定覆盖', - '取消' - ); + // 创建合并文件夹记录 + const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('local-', this.moduleFolders); + const newFolder: ModuleFolder = { + id: newId, + name: displayName, + type: 'local', + localPath: relativePath, + containerId: this.currentContainerId + }; - if (confirm !== '确定覆盖') { - vscode.window.showInformationMessage('克隆操作已取消'); - return; + this.moduleFolders.push(newFolder); + + // 删除原始配置文件 + for (const configId of configIds) { + await this.deleteConfigInternal(configId); + } + + await this.saveCurrentProjectData(); + vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`); + this.updateWebview(); + + } catch (error) { + console.error('❌ 合并配置文件失败:', error); + vscode.window.showErrorMessage(`合并配置文件失败: ${error}`); + } + } + + // ============================================= + // Git 分支管理方法 + // ============================================= + + private async fetchBranches(url: string): Promise { + try { + console.log('🌿 开始获取分支列表:', url); + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: '正在获取分支信息', + cancellable: false + }, async (progress) => { + progress.report({ increment: 0, message: '连接远程仓库...' }); + + try { + progress.report({ increment: 30, message: '获取远程引用...' }); + + const refs = await git.listServerRefs({ + http: http, + url: url + }); + + console.log('📋 获取到的引用:', refs); + + // 过滤出分支引用 + const branchRefs = refs.filter(ref => + ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/') + ); + + // 构建分支数据 + const branches: GitBranch[] = branchRefs.map(ref => { + 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 + }; + }); - // 清空目录(除了 .git 文件夹,如果存在的话) - for (const item of dirContents) { - const itemPath = path.join(localPath, item); - if (item !== '.git') { - await fs.promises.rm(itemPath, { recursive: true, force: true }); + if (branches.length === 0) { + throw new Error('未找到任何分支'); + } + + progress.report({ increment: 80, message: '处理分支数据...' }); + + // 构建分支树状结构 + const branchTree = this.buildBranchTree(branches); + + // 发送分支数据到前端 + if (!this.isWebviewDisposed) { + this.panel.webview.postMessage({ + type: 'branchesFetched', + branches: branches, + branchTree: branchTree, + repoUrl: url + }); + } + + progress.report({ increment: 100, message: '完成' }); + + } catch (error) { + console.error('❌ 使用 listServerRefs 获取分支失败:', error); + vscode.window.showErrorMessage(`获取分支失败: ${error}`); + } + }); + + } catch (error) { + console.error('❌ 获取分支失败:', error); + vscode.window.showErrorMessage(`获取分支失败: ${error}`); + } + } + + private async cloneBranches(url: string, branches: string[]): Promise { + try { + console.log('🚀 开始克隆分支:', { url, branches }); + + let successCount = 0; + let failCount = 0; + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在克隆 ${branches.length} 个分支`, + cancellable: false + }, async (progress) => { + for (let i = 0; i < branches.length; i++) { + const branch = branches[i]; + const progressPercent = (i / branches.length) * 100; + progress.report({ + increment: progressPercent, + message: `克隆分支: ${branch} (${i + 1}/${branches.length})` + }); + + console.log(`📥 开始克隆分支: ${branch}`); + try { + const folderNames = this.generateModuleFolderName(url, branch); + await this.addGitModuleFolder(url, folderNames.displayName, folderNames.folderName, branch); + successCount++; + console.log(`✅ 分支克隆成功: ${branch}`); + } catch (error) { + failCount++; + console.error(`❌ 分支克隆失败: ${branch}`, error); + } + } + }); + + // 显示最终结果 + if (failCount === 0) { + vscode.window.showInformationMessage(`成功克隆 ${successCount} 个分支`); + } else { + vscode.window.showWarningMessage(`克隆完成: ${successCount} 个成功, ${failCount} 个失败`); + } + + } catch (error) { + console.error('❌ 克隆分支失败:', error); + vscode.window.showErrorMessage(`克隆分支失败: ${error}`); + } + } + + // ============================================= + // 模块文件夹管理方法 + // ============================================= + + private async addGitModuleFolder(url: string, displayName: string, folderName: string, branch?: string): Promise { + try { + if (!url || !url.startsWith('http')) { + vscode.window.showErrorMessage('请输入有效的 Git 仓库 URL'); + return; + } + + if (!this.currentContainerId) { + 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) { + vscode.window.showErrorMessage('未找到相关项目数据'); + return; + } + + // 使用新的 ID 生成方法 + 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); + + console.log(`📁 准备克隆仓库: ${displayName}, 分支: ${branch}, 路径: ${localPath}`); + + // 检查是否已存在相同路径的模块文件夹 + const existingFolder = this.moduleFolders.find(folder => + folder.localPath === relativePath && folder.containerId === this.currentContainerId + ); + if (existingFolder) { + vscode.window.showWarningMessage(`该路径的模块文件夹已存在: ${folderName}`); + return; + } + + const newFolder: ModuleFolder = { + id: folderId, + name: displayName, + type: 'git', + localPath: relativePath, + containerId: this.currentContainerId + }; + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在克隆仓库: ${displayName}`, + cancellable: false + }, 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; + } + + // 清空目录(除了 .git 文件夹) + 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}`); + 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) => { - 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}...` }); + // 克隆仓库 + await git.clone({ + fs: fs, + http: http, + dir: localPath, + url: url, + singleBranch: true, + depth: 1, + ref: branch || 'main', + onProgress: (event: any) => { + 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}...` }); + } } + }); + + console.log('✅ Git克隆成功完成'); + + // 验证克隆是否真的成功 + const clonedContents = await fs.promises.readdir(localPath); + console.log(`📁 克隆后的目录内容:`, clonedContents); + + if (clonedContents.length === 0) { + throw new Error('克隆后目录为空,可能克隆失败'); } - }); - console.log('✅ Git克隆成功完成'); - - // 验证克隆是否真的成功 - const clonedContents = await fs.promises.readdir(localPath); - console.log(`📁 克隆后的目录内容:`, clonedContents); - - if (clonedContents.length === 0) { - throw new Error('克隆后目录为空,可能克隆失败'); - } + // 只有在克隆成功后才添加到列表 + this.moduleFolders.push(newFolder); + await this.saveCurrentProjectData(); + console.log('✅ Git模块文件夹数据已保存到项目文件'); - // 只有在克隆成功后才添加到列表 - this.moduleFolders.push(newFolder); - await this.saveCurrentProjectData(); - console.log('✅ Git模块文件夹数据已保存到项目文件'); - - vscode.window.showInformationMessage(`Git 仓库克隆成功: ${displayName}`); - - // 检查 Webview 状态后再加载文件树 - if (!this.isWebviewDisposed) { - console.log('🌳 开始加载模块文件夹文件树...'); + vscode.window.showInformationMessage(`Git 仓库克隆成功: ${displayName}`); + // 自动加载文件树 - this.currentModuleFolderId = folderId; - await this.loadModuleFolderFileTree(folderId); - console.log('✅ 模块文件夹文件树加载完成'); - } else { - console.log('⚠️ Webview 已被销毁,跳过文件树加载'); - } - - } catch (error) { - console.error('❌ 在克隆过程中捕获错误:', error); - - // 清理:如果克隆失败,删除可能创建的不完整目录 - try { - if (fs.existsSync(localPath)) { - await fs.promises.rm(localPath, { recursive: true, force: true }); - console.log('🧹 已清理克隆失败的目录'); + if (!this.isWebviewDisposed) { + console.log('🌳 开始加载模块文件夹文件树...'); + this.currentModuleFolderId = folderId; + await this.loadModuleFolderFileTree(folderId); + console.log('✅ 模块文件夹文件树加载完成'); } - } catch (cleanupError) { - console.error('清理失败目录时出错:', cleanupError); + + } catch (error) { + console.error('❌ 在克隆过程中捕获错误:', error); + + // 清理:如果克隆失败,删除可能创建的不完整目录 + try { + if (fs.existsSync(localPath)) { + await fs.promises.rm(localPath, { recursive: true, force: true }); + console.log('🧹 已清理克隆失败的目录'); + } + } catch (cleanupError) { + console.error('清理失败目录时出错:', cleanupError); + } + + vscode.window.showErrorMessage(`克隆仓库失败: ${error}`); + throw error; } - - vscode.window.showErrorMessage(`克隆仓库失败: ${error}`); - - // 重新抛出错误,让外部知道克隆失败 - throw error; - } - }); + }); - } catch (error) { - console.error('❌ 在addGitModuleFolder外部捕获错误:', error); - vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`); + } catch (error) { + console.error('❌ 在addGitModuleFolder外部捕获错误:', error); + vscode.window.showErrorMessage(`添加 Git 模块文件夹失败: ${error}`); + } } -} - /** - * 加载模块文件夹 - */ private async loadModuleFolder(folderId: string): Promise { this.currentModuleFolderId = folderId; const folder = this.moduleFolders.find(f => f.id === folderId); @@ -619,9 +895,6 @@ export class ConfigPanel { this.updateWebview(); } - /** - * 同步 Git 模块文件夹 - */ private async syncGitModuleFolder(folderId: string): Promise { const folder = this.moduleFolders.find(f => f.id === folderId); if (!folder || folder.type !== 'git') { @@ -629,7 +902,6 @@ export class ConfigPanel { return; } - // 获取完整路径 const fullPath = this.getModuleFolderFullPath(folder); if (!fullPath) { vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); @@ -644,7 +916,6 @@ export class ConfigPanel { try { progress.report({ increment: 0, message: '拉取最新更改...' }); - // 拉取最新更改 await git.pull({ fs: fs, http: http, @@ -653,9 +924,7 @@ export class ConfigPanel { fastForward: true }); - // 重新加载文件树 await this.loadModuleFolderFileTree(folderId); - vscode.window.showInformationMessage(`Git 仓库同步成功: ${folder.name}`); this.updateWebview(); @@ -665,9 +934,6 @@ export class ConfigPanel { }); } - /** - * 删除模块文件夹 - */ private async deleteModuleFolder(folderId: string): Promise { const folder = this.moduleFolders.find(f => f.id === folderId); if (!folder) return; @@ -681,17 +947,14 @@ export class ConfigPanel { if (confirm === '确定删除') { try { - // 获取完整路径并删除文件夹 const fullPath = this.getModuleFolderFullPath(folder); if (fullPath) { await fs.promises.rm(fullPath, { recursive: true, force: true }); } - // 从列表中移除 this.moduleFolders = this.moduleFolders.filter(f => f.id !== folderId); await this.saveCurrentProjectData(); - // 如果删除的是当前文件夹,清空状态 if (this.currentModuleFolderId === folderId) { this.currentModuleFolderId = ''; this.currentModuleFolderFileTree = []; @@ -706,11 +969,695 @@ export class ConfigPanel { } } - /** - * 加载模块文件夹文件树 - */ + private async importGitFile(filePath: string): Promise { + if (!this.currentModuleFolderId || !this.currentContainerId) { + vscode.window.showErrorMessage('请先选择模块文件夹和容器'); + return; + } + + const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); + return; + } + + const container = this.containers.find(c => c.id === this.currentContainerId); + if (!container) { + vscode.window.showErrorMessage('未找到当前容器'); + return; + } + + try { + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹路径'); + return; + } + + const fileFullPath = path.join(fullPath, filePath); + const content = await fs.promises.readFile(fileFullPath, 'utf8'); + const fileName = path.basename(filePath); + + // 使用新的 ID 生成方法 + const newId = this.generateUniqueId('cfg', this.configs); + const newConfig: Config = { + id: newId, + name: fileName, + fileName: fileName, + content: content, + containerId: this.currentContainerId + }; + + this.configs.push(newConfig); + await this.saveCurrentProjectData(); + + vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); + this.updateWebview(); + + } catch (error) { + vscode.window.showErrorMessage(`导入文件失败: ${error}`); + } + } + + // ============================================= + // 上传功能方法 + // ============================================= + + private async uploadGitModuleFolder(folderId: string, username: string, password: string): Promise { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder || folder.type !== 'git') { + vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); + return; + } + + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); + return; + } + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '检查更改...' }); + + await this.commitAndPushUsingCommandLine(fullPath); + + progress.report({ increment: 100, message: '完成' }); + + folder.uploaded = true; + await this.saveCurrentProjectData(); + + vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); + this.updateWebview(); + + } catch (error) { + console.error('❌ Git 上传失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message}`); + } + }); + } + + private async uploadLocalModuleFolder(folderId: string, repoUrl: string, branchName: string): Promise { + const folder = this.moduleFolders.find(f => f.id === folderId); + if (!folder || folder.type !== 'local') { + vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); + return; + } + + const fullPath = this.getModuleFolderFullPath(folder); + if (!fullPath) { + vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); + return; + } + + await vscode.window.withProgress({ + location: vscode.ProgressLocation.Notification, + title: `正在上传本地文件夹到 Git 仓库: ${folder.name}`, + cancellable: false + }, async (progress) => { + try { + progress.report({ increment: 0, message: '检查目录...' }); + + if (!fs.existsSync(fullPath)) { + throw new Error('本地文件夹不存在'); + } + + progress.report({ increment: 10, message: '初始化 Git 仓库...' }); + await this.initGitRepository(fullPath, branchName); + + progress.report({ increment: 20, message: '添加远程仓库...' }); + await this.addGitRemote(fullPath, repoUrl); + + progress.report({ increment: 40, message: '提交初始文件...' }); + await this.commitInitialFiles(fullPath); + + progress.report({ increment: 60, message: '推送到远程仓库...' }); + await this.pushToRemoteWithForce(fullPath, branchName); + + progress.report({ increment: 100, message: '完成' }); + + folder.type = 'git'; + folder.uploaded = true; + await this.saveCurrentProjectData(); + + vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`); + this.updateWebview(); + + } catch (error) { + console.error('❌ 本地文件夹上传失败:', error); + vscode.window.showErrorMessage(`推送失败: ${error.message}`); + + // 清理:删除可能创建的 .git 文件夹 + try { + const gitDir = path.join(fullPath, '.git'); + if (fs.existsSync(gitDir)) { + await fs.promises.rm(gitDir, { recursive: true, force: true }); + } + } catch (cleanupError) { + console.error('清理 .git 文件夹失败:', cleanupError); + } + } + }); + } + + // ============================================= + // 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, 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(); + }); + }); + }); + } + + 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, stdout, stderr) => { + if (error) { + console.error('❌ Git 初始化失败:', error); + reject(new Error(stderr || error.message)); + return; + } + + console.log('✅ Git 初始化成功'); + resolve(); + }); + }); + } + + 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, stdout, stderr) => { + 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, 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(); + }); + }); + } + + 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, 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(); + }); + }); + } + + // ============================================= + // 文件系统操作方法 + // ============================================= + + 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 { + const configCount = this.configs.length; + + // 第一个配置文件 + 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}`); + } + } + + // ============================================= + // 项目数据持久化方法 + // ============================================= + + 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}`); + } + } + + 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; + } + + // 读取数据文件 + 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; + } + } + + private 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; + } + } + + // ============================================= + // 项目路径选择方法 + // ============================================= + + private async openExistingProject(): Promise { + try { + const result = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: '选择项目文件夹', + title: '选择包含项目数据的文件夹' + }); + + if (result && result.length > 0) { + const selectedPath = result[0].fsPath; + await this.loadProjectData(selectedPath); + } + } catch (error) { + vscode.window.showErrorMessage(`打开项目时出错: ${error}`); + } + } + + private async selectProjectPath(projectId: string, projectName: string): Promise { + try { + const choice = await vscode.window.showQuickPick( + [ + { + label: '$(folder) 选择现有文件夹', + description: '从文件系统中选择已存在的文件夹', + value: 'select' + }, + { + label: '$(new-folder) 创建新文件夹', + description: '输入新文件夹路径(将自动创建)', + value: 'create' + } + ], + { + placeHolder: '选择项目存储方式' + } + ); + + if (!choice) { + return null; + } + + if (choice.value === 'select') { + return await this.selectExistingProjectPath(projectId, projectName); + } else { + return await this.createNewProjectPath(projectId, projectName); + } + + } catch (error) { + vscode.window.showErrorMessage(`选择存储路径时出错: ${error}`); + return null; + } + } + + private async selectExistingProjectPath(projectId: string, projectName: string): Promise { + const result = await vscode.window.showOpenDialog({ + canSelectFiles: false, + canSelectFolders: true, + canSelectMany: false, + openLabel: `选择 ${projectName} 的存储位置`, + title: `为项目 "${projectName}" 选择存储文件夹` + }); + + if (result && result.length > 0) { + const selectedPath = result[0].fsPath; + + const hasExistingData = await this.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} 加载`); + return selectedPath; + } + } + } + + this.projectPaths.set(projectId, selectedPath); + vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); + await this.saveCurrentProjectData(); + return selectedPath; + } + + return null; + } + + private async createNewProjectPath(projectId: string, projectName: string): Promise { + const pathInput = await vscode.window.showInputBox({ + prompt: '请输入项目存储路径(绝对路径)', + placeHolder: `/path/to/your/project/${projectName}`, + validateInput: (value) => { + if (!value) { + return '路径不能为空'; + } + return null; + } + }); + + if (pathInput) { + try { + const dirUri = vscode.Uri.file(pathInput); + await vscode.workspace.fs.createDirectory(dirUri); + + this.projectPaths.set(projectId, pathInput); + vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); + await this.saveCurrentProjectData(); + return pathInput; + } catch (error) { + vscode.window.showErrorMessage(`创建目录失败: ${error}`); + return null; + } + } + + return null; + } + + // ============================================= + // 文件树和模块文件夹方法 + // ============================================= + private async loadModuleFolderFileTree(folderId: string): Promise { - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,跳过文件树加载'); return; @@ -761,9 +1708,6 @@ export class ConfigPanel { } } - /** - * 构建文件树 - */ private async buildFileTree(dir: string, relativePath: string = ''): Promise { try { const files = await fs.promises.readdir(dir); @@ -802,663 +1746,10 @@ export class ConfigPanel { } } - /** - * 导入 Git 文件到当前容器 - */ - private async importGitFile(filePath: string): Promise { - if (!this.currentModuleFolderId || !this.currentContainerId) { - vscode.window.showErrorMessage('请先选择模块文件夹和容器'); - return; - } + // ============================================= + // 工具方法 + // ============================================= - const folder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage('未找到当前 Git 模块文件夹'); - return; - } - - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } - - try { - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹路径'); - return; - } - - const fileFullPath = path.join(fullPath, filePath); - const content = await fs.promises.readFile(fileFullPath, 'utf8'); - const fileName = path.basename(filePath); - - // 创建新配置 - const newId = 'cfg' + (this.configs.length + 1); - const newConfig: Config = { - id: newId, - name: fileName, - fileName: fileName, - content: content, - containerId: this.currentContainerId - }; - - this.configs.push(newConfig); - await this.saveCurrentProjectData(); - - vscode.window.showInformationMessage(`文件已导入到容器 ${container.name}: ${fileName}`); - this.updateWebview(); - - } catch (error) { - vscode.window.showErrorMessage(`导入文件失败: ${error}`); - } - } - - // === 原有项目配置管理方法 === - - // === 打开现有项目功能 === - private async openExistingProject(): Promise { - try { - const result = await vscode.window.showOpenDialog({ - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - openLabel: '选择项目文件夹', - title: '选择包含项目数据的文件夹' - }); - - if (result && result.length > 0) { - const selectedPath = result[0].fsPath; - await this.loadProjectData(selectedPath); - } - } catch (error) { - vscode.window.showErrorMessage(`打开项目时出错: ${error}`); - } - } - - // === 数据持久化方法 === - - /** - * 保存当前项目数据到项目路径 - */ - 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 currentProjectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); - const currentAircraftIds = currentProjectAircrafts.map(a => a.id); - const currentProjectContainers = this.containers.filter(c => currentAircraftIds.includes(c.aircraftId)); - const currentContainerIds = currentProjectContainers.map(c => c.id); - const currentProjectConfigs = this.configs.filter(cfg => currentContainerIds.includes(cfg.containerId)); - - // 只保存与当前项目容器相关的模块文件夹 - const currentProjectModuleFolders = this.moduleFolders.filter(folder => - currentContainerIds.includes(folder.containerId) - ); - - const data: ProjectData = { - projects: this.projects.filter(p => p.id === this.currentProjectId), - aircrafts: currentProjectAircrafts, - containers: currentProjectContainers, - configs: currentProjectConfigs, - moduleFolders: currentProjectModuleFolders // 保存模块文件夹数据 - }; - - const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2)); - await vscode.workspace.fs.writeFile(dataUri, uint8Array); - - console.log('✅ 当前项目数据已保存,包含', currentProjectModuleFolders.length, '个模块文件夹'); - } catch (error) { - vscode.window.showErrorMessage(`保存项目数据失败: ${error}`); - } - } - - /** - * 从项目路径加载数据 - */ - 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; - } - - // 读取数据文件 - const fileData = await vscode.workspace.fs.readFile(dataUri); - const dataStr = new TextDecoder().decode(fileData); - const data: ProjectData = JSON.parse(dataStr); - - // 清空现有数据 - this.projects = []; - this.aircrafts = []; - this.containers = []; - this.configs = []; - this.moduleFolders = []; // 清空模块文件夹数据 - - // 验证数据格式并加载 - if (data.projects && Array.isArray(data.projects)) { - this.projects = data.projects; - } - if (data.aircrafts && Array.isArray(data.aircrafts)) { - this.aircrafts = data.aircrafts; - } - if (data.containers && Array.isArray(data.containers)) { - this.containers = data.containers; - } - if (data.configs && Array.isArray(data.configs)) { - this.configs = data.configs; - } - if (data.moduleFolders && Array.isArray(data.moduleFolders)) { - this.moduleFolders = data.moduleFolders; // 加载模块文件夹数据 - } - - // 设置当前项目为第一个项目(如果有的话) - if (this.projects.length > 0) { - this.currentProjectId = this.projects[0].id; - this.projectPaths.set(this.currentProjectId, projectPath); - this.currentView = 'aircrafts'; - } - - vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载,包含 ${this.moduleFolders.length} 个模块文件夹`); - this.updateWebview(); - return true; - } catch (error) { - vscode.window.showErrorMessage(`加载项目数据失败: ${error}`); - return false; - } - } - - /** - * 检查项目路径是否已存在数据 - */ - private 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; - } - } - - // === 项目路径选择 === - private async selectProjectPath(projectId: string, projectName: string): Promise { - try { - // 选择现有路径或输入新路径 - const choice = await vscode.window.showQuickPick( - [ - { - label: '$(folder) 选择现有文件夹', - description: '从文件系统中选择已存在的文件夹', - value: 'select' - }, - { - label: '$(new-folder) 创建新文件夹', - description: '输入新文件夹路径(将自动创建)', - value: 'create' - } - ], - { - placeHolder: '选择项目存储方式' - } - ); - - if (!choice) { - return null; - } - - if (choice.value === 'select') { - // 选择现有路径 - const result = await vscode.window.showOpenDialog({ - canSelectFiles: false, - canSelectFolders: true, - canSelectMany: false, - openLabel: `选择 ${projectName} 的存储位置`, - title: `为项目 "${projectName}" 选择存储文件夹` - }); - - if (result && result.length > 0) { - const selectedPath = result[0].fsPath; - - // 检查是否已存在数据 - const hasExistingData = await this.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} 加载`); - return selectedPath; - } - } - // 如果选择不加载或加载失败,继续创建新项目 - } - - this.projectPaths.set(projectId, selectedPath); - vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`); - - // 保存初始数据 - await this.saveCurrentProjectData(); - - return selectedPath; - } - } else { - // 创建新路径 - const pathInput = await vscode.window.showInputBox({ - prompt: '请输入项目存储路径(绝对路径)', - placeHolder: `/path/to/your/project/${projectName}`, - validateInput: (value) => { - if (!value) { - return '路径不能为空'; - } - return null; - } - }); - - if (pathInput) { - try { - // 尝试创建目录 - const dirUri = vscode.Uri.file(pathInput); - await vscode.workspace.fs.createDirectory(dirUri); - - this.projectPaths.set(projectId, pathInput); - vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`); - - // 保存初始数据 - await this.saveCurrentProjectData(); - - return pathInput; - } catch (error) { - vscode.window.showErrorMessage(`创建目录失败: ${error}`); - return null; - } - } - } - - return null; - } catch (error) { - vscode.window.showErrorMessage(`选择存储路径时出错: ${error}`); - return null; - } - } - - // 更新项目名 - private async updateProjectName(projectId: string, newName: string) { - const project = this.projects.find(p => p.id === projectId); - if (project) { - project.name = newName; - vscode.window.showInformationMessage(`项目名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - - // 创建新项目 - private async createProject(name: string) { - const newId = 'p' + (this.projects.length + 1); - const newProject: Project = { - id: newId, - name: name - }; - this.projects.push(newProject); - - vscode.window.showInformationMessage(`新建项目: ${name}`); - this.updateWebview(); - } - - // 删除项目 - private async deleteProject(projectId: string) { - 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(); - } - - // 更新飞行器名 - private async updateAircraftName(aircraftId: string, newName: string) { - const aircraft = this.aircrafts.find(a => a.id === aircraftId); - if (aircraft) { - aircraft.name = newName; - vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - - // 创建新飞行器 - private async createAircraft(name: string) { - if (!this.currentProjectId) { - vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目'); - return; - } - - const newId = 'a' + (this.aircrafts.length + 1); - const newAircraft: Aircraft = { - id: newId, - name: name, - projectId: this.currentProjectId - }; - this.aircrafts.push(newAircraft); - - // 创建飞行器目录 - await this.createAircraftDirectory(newAircraft); - - vscode.window.showInformationMessage(`新建飞行器: ${name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - - // 删除飞行器 - private async deleteAircraft(aircraftId: string) { - 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(); - } - - // 更新容器名 - private async updateContainerName(containerId: string, newName: string) { - const container = this.containers.find(c => c.id === containerId); - if (container) { - container.name = newName; - vscode.window.showInformationMessage(`容器名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - - // 创建新容器 - private async createContainer(name: string) { - if (!this.currentAircraftId) { - vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器'); - return; - } - - const newId = 'c' + (this.containers.length + 1); - - const newContainer: Container = { - id: newId, - name: name, - aircraftId: this.currentAircraftId - }; - this.containers.push(newContainer); - - // 创建容器目录 - await this.createContainerDirectory(newContainer); - - // 创建两个默认配置文件 - const configCount = this.configs.length; - - // 第一个配置文件 - this.configs.push({ - id: 'cfg' + (configCount + 1), - name: '配置1', - fileName: 'dockerfile', - content: `# ${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: newId - }); - - // 第二个配置文件 - this.configs.push({ - id: 'cfg' + (configCount + 2), - name: '配置2', - fileName: 'docker-compose.yml', - content: `# ${name} 的 Docker Compose 配置\nversion: '3.8'\n\nservices:\n ${name.toLowerCase().replace(/\\s+/g, '-')}:\n build: .\n container_name: ${name}\n ports:\n - "8080:8080"\n environment:\n - NODE_ENV=production\n volumes:\n - ./data:/app/data\n restart: unless-stopped`, - containerId: newId - }); - - vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - - // 删除容器 - private async deleteContainer(containerId: string) { - 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(); - } - - // 更新配置名 - private async updateConfigName(configId: string, newName: string) { - const config = this.configs.find(c => c.id === configId); - if (config) { - config.name = newName; - vscode.window.showInformationMessage(`配置名称更新: ${newName}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - } - - // 创建新配置文件 - private async createConfig(name: string) { - const newId = 'cfg' + (this.configs.length + 1); - 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); - - vscode.window.showInformationMessage(`新建配置: ${name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - } - - // 删除配置文件 - 修复版本,同时删除磁盘文件 - private async deleteConfig(configId: string) { - const config = this.configs.find(c => c.id === configId); - if (!config) return; - - const confirm = await vscode.window.showWarningMessage( - `确定要删除配置文件 "${config.name}" 吗?这将同时删除磁盘上的文件。`, - { modal: true }, - '确定删除', - '取消' - ); - - if (confirm !== '确定删除') { - return; - } - - try { - // 从内存中删除配置 - this.configs = this.configs.filter(c => c.id !== configId); - - // 删除磁盘上的配置文件 - const container = this.containers.find(c => c.id === config.containerId); - if (container) { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (aircraft) { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (projectPath) { - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - - // 检查文件是否存在,如果存在则删除 - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); - } - } - } - } - - vscode.window.showInformationMessage(`删除配置: ${config.name}`); - await this.saveCurrentProjectData(); - this.updateWebview(); - - } catch (error) { - vscode.window.showErrorMessage(`删除配置文件失败: ${error}`); - } - } - - // === Git 分支管理 === - - private async fetchBranches(url: string): Promise { - try { - console.log('🌿 开始获取分支列表:', url); - - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: '正在获取分支信息', - cancellable: false - }, async (progress) => { - progress.report({ increment: 0, message: '连接远程仓库...' }); - - try { - // 使用 isomorphic-git 的 listServerRefs - progress.report({ increment: 30, message: '获取远程引用...' }); - - console.log('🔍 使用 listServerRefs 获取分支信息...'); - - const refs = await git.listServerRefs({ - http: http, - url: url - }); - - console.log('📋 获取到的引用:', refs); - - // 过滤出分支引用 (refs/heads/ 和 refs/remotes/origin/) - const branchRefs = refs.filter(ref => - ref.ref.startsWith('refs/heads/') || ref.ref.startsWith('refs/remotes/origin/') - ); - - console.log('🌿 过滤后的分支引用:', branchRefs); - - // 构建分支数据 - 修复分支名称显示 - const branches: GitBranch[] = branchRefs.map(ref => { - let branchName: string; - - if (ref.ref.startsWith('refs/remotes/')) { - // 远程分支:移除 refs/remotes/origin/ 前缀 - branchName = ref.ref.replace('refs/remotes/origin/', ''); - } else { - // 本地分支:移除 refs/heads/ 前缀 - branchName = ref.ref.replace('refs/heads/', ''); - } - - return { - name: branchName, - isCurrent: branchName === 'main' || branchName === 'master', - selected: false // 所有分支默认不选中 - }; - }); - - console.log('🎯 最终分支列表:', branches); - - if (branches.length === 0) { - throw new Error('未找到任何分支'); - } - - progress.report({ increment: 80, message: '处理分支数据...' }); - - // === 新增:构建分支树状结构 === - const branchTree = this.buildBranchTree(branches); - console.log('🌳 构建的分支树结构:', branchTree); - - // 发送分支数据到前端 - 同时包含扁平列表和树状结构 - if (!this.isWebviewDisposed) { - this.panel.webview.postMessage({ - type: 'branchesFetched', - branches: branches, - branchTree: branchTree, // 新增树状结构数据 - repoUrl: url - }); - } - - progress.report({ increment: 100, message: '完成' }); - - } catch (error) { - console.error('❌ 使用 listServerRefs 获取分支失败:', error); - - // 只在右下角显示分支获取失败的通知,不模拟分支数据 - vscode.window.showErrorMessage(`获取分支失败: ${error}`); - } - }); - - } catch (error) { - console.error('❌ 获取分支失败:', error); - vscode.window.showErrorMessage(`获取分支失败: ${error}`); - } - } - - /** - * 构建分支树状结构 - */ private buildBranchTree(branches: GitBranch[]): any[] { const root: any[] = []; @@ -1480,13 +1771,12 @@ export class ConfigPanel { isLeaf: isLeaf, children: [], level: i, - expanded: true // 默认展开 + expanded: true }; currentLevel.push(node); } if (isLeaf) { - // 叶子节点存储分支信息 node.branch = branch; } @@ -1498,66 +1788,105 @@ export class ConfigPanel { } 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 async cloneBranches(url: string, branches: string[]): Promise { - try { - console.log('🚀 开始克隆分支:', { url, branches }); + const repoName = url.split('/').pop()?.replace('.git', '') || 'unknown-repo'; + const branchSafeName = branch.replace(/[^a-zA-Z0-9-_]/g, '-'); - let successCount = 0; - let failCount = 0; - - // 显示总进度 - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在克隆 ${branches.length} 个分支`, - cancellable: false - }, async (progress) => { - for (let i = 0; i < branches.length; i++) { - const branch = branches[i]; - const progressPercent = (i / branches.length) * 100; - progress.report({ - increment: progressPercent, - message: `克隆分支: ${branch} (${i + 1}/${branches.length})` - }); - - console.log(`📥 开始克隆分支: ${branch}`); - try { - const folderNames = this.generateModuleFolderName(url, branch); - await this.addGitModuleFolder(url, folderNames.displayName, folderNames.folderName, branch); - successCount++; - console.log(`✅ 分支克隆成功: ${branch}`); - } catch (error) { - failCount++; - console.error(`❌ 分支克隆失败: ${branch}`, error); - // 继续克隆其他分支,不中断整个流程 - } - } - }); - - // 显示最终结果 - if (failCount === 0) { - vscode.window.showInformationMessage(`成功克隆 ${successCount} 个分支`); - } else { - vscode.window.showWarningMessage(`克隆完成: ${successCount} 个成功, ${failCount} 个失败`); - } - - } catch (error) { - console.error('❌ 克隆分支失败:', error); - vscode.window.showErrorMessage(`克隆分支失败: ${error}`); + 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('未找到配置文件'); + 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}`); + } + } + + // ============================================= + // Webview 更新方法 + // ============================================= + private updateWebview() { - // 检查 Webview 是否仍然有效 if (this.isWebviewDisposed) { console.log('⚠️ Webview 已被销毁,跳过更新'); return; @@ -1578,6 +1907,7 @@ export class ConfigPanel { projectPaths: this.projectPaths }); case 'aircrafts': + // 只显示当前项目的飞行器 const projectAircrafts = this.aircrafts.filter(a => a.projectId === this.currentProjectId); return this.aircraftView.render({ aircrafts: projectAircrafts @@ -1585,6 +1915,7 @@ export class ConfigPanel { 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); return this.containerView.render({ @@ -1594,10 +1925,9 @@ export class ConfigPanel { }); case 'configs': const currentContainer = this.containers.find(c => c.id === this.currentContainerId); + // 只显示当前容器的配置和模块文件夹 const containerConfigs = this.configs.filter(cfg => cfg.containerId === this.currentContainerId); const currentModuleFolder = this.moduleFolders.find(f => f.id === this.currentModuleFolderId); - - // 获取当前容器的模块文件夹 const containerModuleFolders = this.moduleFolders.filter(folder => folder.containerId === this.currentContainerId); return this.configView.render({ @@ -1615,732 +1945,4 @@ export class ConfigPanel { }); } } - - private async openGitRepoInVSCode(folderId: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - - try { - // 检查文件夹是否存在 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹目录不存在'); - return; - } - - // 使用 VSCode 的文件选择器让用户选择要打开的文件 - const fileUri = await vscode.window.showOpenDialog({ - defaultUri: vscode.Uri.file(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 openConfigFileInVSCode(configId: string): Promise { - const config = this.configs.find(c => c.id === configId); - if (!config) { - vscode.window.showErrorMessage('未找到配置文件'); - return; - } - - const container = this.containers.find(c => c.id === config.containerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } - - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } - - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!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 || ''); - } - - // 在 VSCode 中打开文件 - const document = await vscode.workspace.openTextDocument(filePath); - await vscode.window.showTextDocument(document); - - } catch (error) { - vscode.window.showErrorMessage(`打开配置文件失败: ${error}`); - } - } - - private async mergeConfigs(configIds: string[], displayName: string, folderName: string): Promise { - try { - if (!this.currentContainerId) { - vscode.window.showErrorMessage('未找到当前容器'); - return; - } - - if (configIds.length < 2) { - vscode.window.showErrorMessage('请至少选择两个配置文件进行合并'); - return; - } - - const container = this.containers.find(c => c.id === this.currentContainerId); - if (!container) { - vscode.window.showErrorMessage('未找到容器'); - return; - } - - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (!aircraft) { - vscode.window.showErrorMessage('未找到飞行器'); - return; - } - - const projectPath = this.projectPaths.get(aircraft.projectId); - if (!projectPath) { - vscode.window.showErrorMessage('未设置项目存储路径'); - return; - } - - // 获取选中的配置文件 - const selectedConfigs = this.configs.filter(config => configIds.includes(config.id)); - 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 copiedFiles: string[] = []; - for (const config of selectedConfigs) { - const sourcePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - const targetPath = path.join(mergeFolderPath, config.fileName); - - if (fs.existsSync(sourcePath)) { - await fs.promises.copyFile(sourcePath, targetPath); - copiedFiles.push(config.fileName); - console.log(`✅ 已复制配置文件: ${config.fileName}`); - } else { - // 如果源文件不存在,创建新文件 - await fs.promises.writeFile(targetPath, config.content || ''); - copiedFiles.push(config.fileName); - console.log(`✅ 已创建配置文件: ${config.fileName}`); - } - } - - // 构建相对路径 - const relativePath = `/${aircraft.projectId}/${aircraft.name}/${container.name}/${folderName}`; - - // 创建合并文件夹记录 - const newFolder: ModuleFolder = { - id: 'local-' + Date.now(), - name: displayName, - type: 'local', - localPath: relativePath, - containerId: this.currentContainerId - }; - - // 添加到模块文件夹列表 - this.moduleFolders.push(newFolder); - - // 删除原始配置文件 - for (const configId of configIds) { - await this.deleteConfigInternal(configId); - } - - // 保存数据 - await this.saveCurrentProjectData(); - - vscode.window.showInformationMessage(`成功合并 ${selectedConfigs.length} 个配置文件到文件夹: ${folderName}`); - - // 更新UI - this.updateWebview(); - - } catch (error) { - console.error('❌ 合并配置文件失败:', error); - vscode.window.showErrorMessage(`合并配置文件失败: ${error}`); - } - } - - /** - * 内部删除配置文件方法(不显示确认对话框) - */ - 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); - - // 删除磁盘上的配置文件 - const container = this.containers.find(c => c.id === config.containerId); - if (container) { - const aircraft = this.aircrafts.find(a => a.id === container.aircraftId); - if (aircraft) { - const projectPath = this.projectPaths.get(aircraft.projectId); - if (projectPath) { - const filePath = path.join(projectPath, aircraft.name, container.name, config.fileName); - - // 检查文件是否存在,如果存在则删除 - if (fs.existsSync(filePath)) { - await fs.promises.unlink(filePath); - console.log(`✅ 已删除配置文件: ${filePath}`); - } - } - } - } - - console.log(`✅ 内部删除配置: ${config.name}`); - - } catch (error) { - console.error(`删除配置文件失败: ${error}`); - } - } - - /** - * 在 VSCode 中打开合并文件夹 - */ - private async openMergedFolderInVSCode(folderId: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder) { - vscode.window.showErrorMessage('未找到指定的模块文件夹'); - return; - } - - try { - // 检查文件夹是否存在 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath || !fs.existsSync(fullPath)) { - vscode.window.showErrorMessage('模块文件夹不存在'); - return; - } - - // 使用 VSCode 打开文件夹 - const folderUri = vscode.Uri.file(fullPath); - vscode.commands.executeCommand('vscode.openFolder', folderUri, { forceNewWindow: false }); - - } catch (error) { - vscode.window.showErrorMessage(`打开模块文件夹失败: ${error}`); - } - } - - /** - * 统一方法:在 VSCode 中打开模块文件夹中的文件 - * @param type 模块类型:'git' 或 'merged' - * @param id 模块 ID - */ - 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; - } - - // 使用 VSCode 的文件选择器让用户选择要打开的文件 - 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 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 uploadGitModuleFolder(folderId: string, username: string, password: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder || folder.type !== 'git') { - vscode.window.showErrorMessage('未找到指定的 Git 模块文件夹'); - return; - } - - // 获取完整路径 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); - return; - } - - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '检查更改...' }); - - // 使用改进的 Git 提交并推送 - await this.commitAndPushUsingCommandLine(fullPath); - - progress.report({ increment: 100, message: '完成' }); - - // 添加上传成功标记 - folder.uploaded = true; - await this.saveCurrentProjectData(); - - vscode.window.showInformationMessage(`✅ Git 仓库上传成功: ${folder.name}`); - - // 更新 Webview 显示 - this.updateWebview(); - - } catch (error) { - console.error('❌ Git 上传失败:', error); - - // 如果是"没有更改"的错误,显示友好提示 - if (error.message.includes('没有需要提交的更改')) { - vscode.window.showWarningMessage(`没有检测到更改,无需上传: ${folder.name}`); - } else { - vscode.window.showErrorMessage(`推送失败: ${error.message}`); - } - } - }); -} - -private async uploadLocalModuleFolder(folderId: string, repoUrl: string, branchName: string): Promise { - const folder = this.moduleFolders.find(f => f.id === folderId); - if (!folder || folder.type !== 'local') { - vscode.window.showErrorMessage('未找到指定的本地模块文件夹'); - return; - } - - // 获取完整路径 - const fullPath = this.getModuleFolderFullPath(folder); - if (!fullPath) { - vscode.window.showErrorMessage('无法获取模块文件夹的完整路径'); - return; - } - - await vscode.window.withProgress({ - location: vscode.ProgressLocation.Notification, - title: `正在上传本地文件夹到 Git 仓库: ${folder.name}`, - cancellable: false - }, async (progress) => { - try { - progress.report({ increment: 0, message: '检查目录...' }); - - // 检查目录是否存在 - if (!fs.existsSync(fullPath)) { - throw new Error('本地文件夹不存在'); - } - - progress.report({ increment: 10, message: '初始化 Git 仓库...' }); - - // 使用命令行 Git 初始化仓库 - await this.initGitRepository(fullPath, branchName); - - progress.report({ increment: 20, message: '添加远程仓库...' }); - - // 使用命令行 Git 添加远程仓库 - await this.addGitRemote(fullPath, repoUrl); - - progress.report({ increment: 40, message: '提交初始文件...' }); - - // 使用命令行 Git 提交初始文件 - await this.commitInitialFiles(fullPath); - - progress.report({ increment: 60, message: '推送到远程仓库...' }); - - // 使用命令行 Git 推送到远程仓库 - await this.pushToRemoteWithForce(fullPath, branchName); - - progress.report({ increment: 100, message: '完成' }); - - // 更新文件夹类型为 git 并标记已上传 - folder.type = 'git'; - folder.uploaded = true; - await this.saveCurrentProjectData(); - - vscode.window.showInformationMessage(`本地文件夹成功上传到 Git 仓库: ${folder.name} -> ${branchName}`); - - // 更新 Webview 显示 - this.updateWebview(); - - } catch (error) { - console.error('❌ 本地文件夹上传失败:', error); - vscode.window.showErrorMessage(`推送失败: ${error.message}`); - - // 清理:删除可能创建的 .git 文件夹 - try { - const gitDir = path.join(fullPath, '.git'); - if (fs.existsSync(gitDir)) { - await fs.promises.rm(gitDir, { recursive: true, force: true }); - } - } catch (cleanupError) { - console.error('清理 .git 文件夹失败:', cleanupError); - } - } - }); -} - -/** - * 使用命令行 Git 初始化仓库(简化版本) - */ -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, stdout, stderr) => { - if (error) { - console.error('❌ Git 初始化失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ Git 初始化成功'); - resolve(); - }); - }); -} - -/** - * 使用命令行 Git 添加远程仓库(简化版本) - */ -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, stdout, stderr) => { - if (error) { - console.error('❌ 添加远程仓库失败:', error); - reject(new Error(stderr || error.message)); - return; - } - - console.log('✅ 远程仓库添加成功'); - resolve(); - }); - }); -} - -/** - * 使用命令行 Git 提交初始文件(简化版本) - */ -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, 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(); - }); - }); -} - -/** - * 使用命令行 Git 强制推送到远程仓库(简化版本) - */ -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, 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(); - }); - }); -} - -private async getCurrentBranch(dir: string): Promise { - try { - const currentBranch = await git.currentBranch({ - fs: fs, - dir: dir, - fullname: false - }); - - if (!currentBranch) { - // 如果没有当前分支,尝试从 HEAD 文件读取 - const headPath = path.join(dir, '.git', 'HEAD'); - if (fs.existsSync(headPath)) { - const headContent = await fs.promises.readFile(headPath, 'utf8'); - const match = headContent.match(/ref: refs\/heads\/(.+)/); - if (match) { - return match[1]; - } - } - throw new Error('无法确定当前分支'); - } - - return currentBranch; - } catch (error) { - console.error('获取当前分支失败:', error); - throw new Error(`获取当前分支失败: ${error}`); - } -} - -/** - * 使用命令行 Git 进行推送(带详细调试) - */ -private async pushUsingCommandLine(fullPath: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('🚀 使用命令行 Git 推送...'); - console.log(`📁 工作目录: ${fullPath}`); - - // 先检查 Git 状态 - exec('git status', { - cwd: fullPath, - encoding: 'utf8' - }, (statusError, statusStdout, statusStderr) => { - console.log('🔍 Git 状态:', statusStdout); - - // 然后执行推送 - exec('git push', { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - console.log('📋 Git push stdout:', stdout); - console.log('📋 Git push stderr:', stderr); - - if (error) { - console.error('❌ Git push 失败:', error); - reject(new Error(`Git 推送失败: ${stderr || error.message}`)); - return; - } - - // 检查实际的推送结果 - if (stdout.includes('Everything up-to-date')) { - console.log('ℹ️ 没有需要推送的更改'); - resolve(); - } else if (stdout.includes('To http') || stdout.includes('To https') || stdout.includes('To git@')) { - console.log('✅ Git 推送成功'); - resolve(); - } else { - console.log('⚠️ 推送结果不明确,可能需要手动检查'); - reject(new Error('推送结果不明确,请检查远程仓库')); - } - }); - }); - }); -} - -/** - * 检查 Git 远程配置 - */ -private async checkGitRemote(fullPath: string): Promise { - return new Promise((resolve, reject) => { - const { exec } = require('child_process'); - - console.log('🔍 检查 Git 远程配置...'); - - exec('git remote -v', { - cwd: fullPath, - encoding: 'utf8' - }, (error, stdout, stderr) => { - if (error) { - console.error('检查远程配置失败:', error); - reject(error); - return; - } - - console.log('📡 Git 远程配置:', stdout); - 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, 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(); - }); - }); - }); -} - -/** - * 简化的推送方法 - */ -private simplePush(fullPath: string, resolve: any, reject: any): void { - const { exec } = require('child_process'); - - exec('git push', { - cwd: fullPath, - encoding: 'utf8' - }, (pushError, pushStdout, pushStderr) => { - console.log('📋 Git push 输出:', pushStdout); - console.log('📋 Git push 错误:', pushStderr); - - if (pushError) { - console.error('❌ Git push 失败'); - // 直接使用 Git 的错误信息 - reject(new Error(pushStderr || pushError.message)); - return; - } - - // 只要没有错误就认为是成功 - console.log('✅ Git 推送成功'); - resolve(); - }); -} - -} +} \ No newline at end of file