增加了项目回读的功能
This commit is contained in:
@@ -49,6 +49,9 @@ class ConfigPanel {
|
|||||||
setupMessageListener() {
|
setupMessageListener() {
|
||||||
this.panel.webview.onDidReceiveMessage(async (data) => {
|
this.panel.webview.onDidReceiveMessage(async (data) => {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
case 'openExistingProject':
|
||||||
|
await this.openExistingProject();
|
||||||
|
break;
|
||||||
case 'configureProject':
|
case 'configureProject':
|
||||||
const selectedPath = await this.selectProjectPath(data.projectId, data.projectName);
|
const selectedPath = await this.selectProjectPath(data.projectId, data.projectName);
|
||||||
if (selectedPath) {
|
if (selectedPath) {
|
||||||
@@ -77,42 +80,51 @@ class ConfigPanel {
|
|||||||
// 修复返回按钮的消息处理
|
// 修复返回按钮的消息处理
|
||||||
case 'goBackToProjects':
|
case 'goBackToProjects':
|
||||||
this.currentView = 'projects';
|
this.currentView = 'projects';
|
||||||
|
// 清空当前选择的ID
|
||||||
|
this.currentProjectId = '';
|
||||||
|
this.currentAircraftId = '';
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
case 'goBackToAircrafts':
|
case 'goBackToAircrafts':
|
||||||
this.currentView = 'aircrafts';
|
this.currentView = 'aircrafts';
|
||||||
|
// 保持 currentProjectId,清空其他ID
|
||||||
|
this.currentAircraftId = '';
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
case 'goBackToContainers':
|
case 'goBackToContainers':
|
||||||
this.currentView = 'containers';
|
this.currentView = 'containers';
|
||||||
|
// 保持 currentProjectId 和 currentAircraftId,清空 currentContainerId
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
case 'updateProjectName':
|
case 'updateProjectName':
|
||||||
this.updateProjectName(data.projectId, data.name);
|
await this.updateProjectName(data.projectId, data.name);
|
||||||
break;
|
break;
|
||||||
case 'createProject':
|
case 'createProject':
|
||||||
this.createProject(data.name);
|
await this.createProject(data.name);
|
||||||
break;
|
break;
|
||||||
case 'updateAircraftName':
|
case 'updateAircraftName':
|
||||||
this.updateAircraftName(data.aircraftId, data.name);
|
await this.updateAircraftName(data.aircraftId, data.name);
|
||||||
break;
|
break;
|
||||||
case 'createAircraft':
|
case 'createAircraft':
|
||||||
this.createAircraft(data.name);
|
await this.createAircraft(data.name);
|
||||||
break;
|
break;
|
||||||
case 'updateContainerName':
|
case 'updateContainerName':
|
||||||
this.updateContainerName(data.containerId, data.name);
|
await this.updateContainerName(data.containerId, data.name);
|
||||||
break;
|
break;
|
||||||
case 'createContainer':
|
case 'createContainer':
|
||||||
this.createContainer(data.name);
|
await this.createContainer(data.name);
|
||||||
break;
|
break;
|
||||||
case 'updateConfigName':
|
case 'updateConfigName':
|
||||||
this.updateConfigName(data.configId, data.name);
|
await this.updateConfigName(data.configId, data.name);
|
||||||
break;
|
break;
|
||||||
case 'updateConfigFileName':
|
case 'updateConfigFileName':
|
||||||
await this.updateConfigFileName(data.configId, data.fileName);
|
await this.updateConfigFileName(data.configId, data.fileName);
|
||||||
break;
|
break;
|
||||||
case 'createConfig':
|
case 'createConfig':
|
||||||
this.createConfig(data.name);
|
await this.createConfig(data.name);
|
||||||
break;
|
break;
|
||||||
case 'saveConfigFile':
|
case 'saveConfigFile':
|
||||||
await this.saveConfigFileToDisk(data.configId, data.content);
|
await this.saveConfigFileToDisk(data.configId, data.content);
|
||||||
@@ -121,21 +133,164 @@ class ConfigPanel {
|
|||||||
this.loadConfigFile(data.configId);
|
this.loadConfigFile(data.configId);
|
||||||
break;
|
break;
|
||||||
case 'deleteProject':
|
case 'deleteProject':
|
||||||
this.deleteProject(data.projectId);
|
await this.deleteProject(data.projectId);
|
||||||
break;
|
break;
|
||||||
case 'deleteAircraft':
|
case 'deleteAircraft':
|
||||||
this.deleteAircraft(data.aircraftId);
|
await this.deleteAircraft(data.aircraftId);
|
||||||
break;
|
break;
|
||||||
case 'deleteContainer':
|
case 'deleteContainer':
|
||||||
this.deleteContainer(data.containerId);
|
await this.deleteContainer(data.containerId);
|
||||||
break;
|
break;
|
||||||
case 'deleteConfig':
|
case 'deleteConfig':
|
||||||
this.deleteConfig(data.configId);
|
await this.deleteConfig(data.configId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// ... 其余方法保持不变(selectProjectPath, updateProjectName, createProject等)
|
// === 打开现有项目功能 ===
|
||||||
|
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 saveAllData() {
|
||||||
|
try {
|
||||||
|
console.log('开始保存数据...');
|
||||||
|
console.log('当前项目ID:', this.currentProjectId);
|
||||||
|
console.log('项目路径映射:', Array.from(this.projectPaths.entries()));
|
||||||
|
// 找到当前项目的路径
|
||||||
|
let projectPath;
|
||||||
|
// 首先尝试使用当前项目ID
|
||||||
|
if (this.currentProjectId) {
|
||||||
|
projectPath = this.projectPaths.get(this.currentProjectId);
|
||||||
|
}
|
||||||
|
// 如果没有找到,尝试使用第一个项目
|
||||||
|
if (!projectPath && this.projects.length > 0) {
|
||||||
|
projectPath = this.projectPaths.get(this.projects[0].id);
|
||||||
|
}
|
||||||
|
if (!projectPath) {
|
||||||
|
console.log('未找到项目路径,跳过保存数据');
|
||||||
|
vscode.window.showWarningMessage('未找到项目存储路径,数据将不会保存');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json');
|
||||||
|
const data = {
|
||||||
|
projects: this.projects,
|
||||||
|
aircrafts: this.aircrafts,
|
||||||
|
containers: this.containers,
|
||||||
|
configs: this.configs,
|
||||||
|
projectPaths: Object.fromEntries(this.projectPaths)
|
||||||
|
};
|
||||||
|
console.log('要保存的数据:', {
|
||||||
|
projects: this.projects.length,
|
||||||
|
aircrafts: this.aircrafts.length,
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length,
|
||||||
|
projectPaths: this.projectPaths.size
|
||||||
|
});
|
||||||
|
const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2));
|
||||||
|
await vscode.workspace.fs.writeFile(dataUri, uint8Array);
|
||||||
|
console.log('项目数据已保存到:', dataUri.fsPath);
|
||||||
|
vscode.window.showInformationMessage('项目数据已保存');
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('保存项目数据时出错:', 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);
|
||||||
|
console.log('从文件加载的数据:', data);
|
||||||
|
// 清空现有数据
|
||||||
|
this.projects = [];
|
||||||
|
this.aircrafts = [];
|
||||||
|
this.containers = [];
|
||||||
|
this.configs = [];
|
||||||
|
this.projectPaths = new Map();
|
||||||
|
// 验证数据格式并加载
|
||||||
|
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.projectPaths && typeof data.projectPaths === 'object') {
|
||||||
|
this.projectPaths = new Map(Object.entries(data.projectPaths));
|
||||||
|
}
|
||||||
|
console.log('加载后的数据状态:', {
|
||||||
|
projects: this.projects.length,
|
||||||
|
aircrafts: this.aircrafts.length,
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length,
|
||||||
|
projectPaths: this.projectPaths.size
|
||||||
|
});
|
||||||
|
// 设置当前项目为第一个项目(如果有的话)
|
||||||
|
if (this.projects.length > 0) {
|
||||||
|
this.currentProjectId = this.projects[0].id;
|
||||||
|
this.currentView = 'aircrafts';
|
||||||
|
}
|
||||||
|
vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载`);
|
||||||
|
this.updateWebview();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('加载项目数据时出错:', 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) {
|
async selectProjectPath(projectId, projectName) {
|
||||||
try {
|
try {
|
||||||
@@ -168,8 +323,28 @@ class ConfigPanel {
|
|||||||
});
|
});
|
||||||
if (result && result.length > 0) {
|
if (result && result.length > 0) {
|
||||||
const selectedPath = result[0].fsPath;
|
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);
|
this.projectPaths.set(projectId, selectedPath);
|
||||||
vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`);
|
vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`);
|
||||||
|
// 保存初始数据
|
||||||
|
await this.saveAllData();
|
||||||
return selectedPath;
|
return selectedPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -192,6 +367,8 @@ class ConfigPanel {
|
|||||||
await vscode.workspace.fs.createDirectory(dirUri);
|
await vscode.workspace.fs.createDirectory(dirUri);
|
||||||
this.projectPaths.set(projectId, pathInput);
|
this.projectPaths.set(projectId, pathInput);
|
||||||
vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`);
|
vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`);
|
||||||
|
// 保存初始数据
|
||||||
|
await this.saveAllData();
|
||||||
return pathInput;
|
return pathInput;
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
@@ -208,16 +385,17 @@ class ConfigPanel {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 更新项目名
|
// 更新项目名
|
||||||
updateProjectName(projectId, newName) {
|
async updateProjectName(projectId, newName) {
|
||||||
const project = this.projects.find(p => p.id === projectId);
|
const project = this.projects.find(p => p.id === projectId);
|
||||||
if (project) {
|
if (project) {
|
||||||
project.name = newName;
|
project.name = newName;
|
||||||
vscode.window.showInformationMessage(`项目名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`项目名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建新项目
|
// 创建新项目
|
||||||
createProject(name) {
|
async createProject(name) {
|
||||||
const newId = 'p' + (this.projects.length + 1);
|
const newId = 'p' + (this.projects.length + 1);
|
||||||
const newProject = {
|
const newProject = {
|
||||||
id: newId,
|
id: newId,
|
||||||
@@ -225,10 +403,11 @@ class ConfigPanel {
|
|||||||
};
|
};
|
||||||
this.projects.push(newProject);
|
this.projects.push(newProject);
|
||||||
vscode.window.showInformationMessage(`新建项目: ${name}`);
|
vscode.window.showInformationMessage(`新建项目: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 删除项目
|
// 删除项目
|
||||||
deleteProject(projectId) {
|
async deleteProject(projectId) {
|
||||||
const project = this.projects.find(p => p.id === projectId);
|
const project = this.projects.find(p => p.id === projectId);
|
||||||
if (!project)
|
if (!project)
|
||||||
return;
|
return;
|
||||||
@@ -245,19 +424,21 @@ class ConfigPanel {
|
|||||||
// 删除项目路径映射
|
// 删除项目路径映射
|
||||||
this.projectPaths.delete(projectId);
|
this.projectPaths.delete(projectId);
|
||||||
vscode.window.showInformationMessage(`删除项目: ${project.name}`);
|
vscode.window.showInformationMessage(`删除项目: ${project.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 更新飞行器名
|
// 更新飞行器名
|
||||||
updateAircraftName(aircraftId, newName) {
|
async updateAircraftName(aircraftId, newName) {
|
||||||
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
||||||
if (aircraft) {
|
if (aircraft) {
|
||||||
aircraft.name = newName;
|
aircraft.name = newName;
|
||||||
vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建新飞行器
|
// 创建新飞行器
|
||||||
createAircraft(name) {
|
async createAircraft(name) {
|
||||||
if (!this.currentProjectId) {
|
if (!this.currentProjectId) {
|
||||||
vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目');
|
vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目');
|
||||||
return;
|
return;
|
||||||
@@ -270,10 +451,11 @@ class ConfigPanel {
|
|||||||
};
|
};
|
||||||
this.aircrafts.push(newAircraft);
|
this.aircrafts.push(newAircraft);
|
||||||
vscode.window.showInformationMessage(`新建飞行器: ${name}`);
|
vscode.window.showInformationMessage(`新建飞行器: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 删除飞行器
|
// 删除飞行器
|
||||||
deleteAircraft(aircraftId) {
|
async deleteAircraft(aircraftId) {
|
||||||
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
||||||
if (!aircraft)
|
if (!aircraft)
|
||||||
return;
|
return;
|
||||||
@@ -284,19 +466,21 @@ class ConfigPanel {
|
|||||||
const containerIds = this.containers.filter(c => c.aircraftId === aircraftId).map(c => c.id);
|
const containerIds = this.containers.filter(c => c.aircraftId === aircraftId).map(c => c.id);
|
||||||
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
|
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
|
||||||
vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`);
|
vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 更新容器名
|
// 更新容器名
|
||||||
updateContainerName(containerId, newName) {
|
async updateContainerName(containerId, newName) {
|
||||||
const container = this.containers.find(c => c.id === containerId);
|
const container = this.containers.find(c => c.id === containerId);
|
||||||
if (container) {
|
if (container) {
|
||||||
container.name = newName;
|
container.name = newName;
|
||||||
vscode.window.showInformationMessage(`容器名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`容器名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建新容器
|
// 创建新容器 - 修复版本
|
||||||
createContainer(name) {
|
async createContainer(name) {
|
||||||
console.log('创建容器,当前飞行器ID:', this.currentAircraftId);
|
console.log('创建容器,当前飞行器ID:', this.currentAircraftId);
|
||||||
if (!this.currentAircraftId) {
|
if (!this.currentAircraftId) {
|
||||||
vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器');
|
vscode.window.showErrorMessage('无法创建容器:未找到当前飞行器');
|
||||||
@@ -315,7 +499,7 @@ class ConfigPanel {
|
|||||||
this.configs.push({
|
this.configs.push({
|
||||||
id: 'cfg' + (configCount + 1),
|
id: 'cfg' + (configCount + 1),
|
||||||
name: '配置1',
|
name: '配置1',
|
||||||
fileName: 'config.sh',
|
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"]`,
|
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
|
containerId: newId
|
||||||
});
|
});
|
||||||
@@ -323,15 +507,20 @@ class ConfigPanel {
|
|||||||
this.configs.push({
|
this.configs.push({
|
||||||
id: 'cfg' + (configCount + 2),
|
id: 'cfg' + (configCount + 2),
|
||||||
name: '配置2',
|
name: '配置2',
|
||||||
fileName: 'config.sh',
|
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`,
|
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
|
containerId: newId
|
||||||
});
|
});
|
||||||
|
console.log('创建容器后的数据状态:', {
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length
|
||||||
|
});
|
||||||
vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`);
|
vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 删除容器
|
// 删除容器
|
||||||
deleteContainer(containerId) {
|
async deleteContainer(containerId) {
|
||||||
const container = this.containers.find(c => c.id === containerId);
|
const container = this.containers.find(c => c.id === containerId);
|
||||||
if (!container)
|
if (!container)
|
||||||
return;
|
return;
|
||||||
@@ -340,14 +529,16 @@ class ConfigPanel {
|
|||||||
// 删除相关的配置
|
// 删除相关的配置
|
||||||
this.configs = this.configs.filter(cfg => cfg.containerId !== containerId);
|
this.configs = this.configs.filter(cfg => cfg.containerId !== containerId);
|
||||||
vscode.window.showInformationMessage(`删除容器: ${container.name}`);
|
vscode.window.showInformationMessage(`删除容器: ${container.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 更新配置名
|
// 更新配置名
|
||||||
updateConfigName(configId, newName) {
|
async updateConfigName(configId, newName) {
|
||||||
const config = this.configs.find(c => c.id === configId);
|
const config = this.configs.find(c => c.id === configId);
|
||||||
if (config) {
|
if (config) {
|
||||||
config.name = newName;
|
config.name = newName;
|
||||||
vscode.window.showInformationMessage(`配置名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`配置名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -357,11 +548,12 @@ class ConfigPanel {
|
|||||||
if (config) {
|
if (config) {
|
||||||
config.fileName = fileName;
|
config.fileName = fileName;
|
||||||
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 创建新配置文件
|
// 创建新配置文件
|
||||||
createConfig(name) {
|
async createConfig(name) {
|
||||||
const newId = 'cfg' + (this.configs.length + 1);
|
const newId = 'cfg' + (this.configs.length + 1);
|
||||||
const newConfig = {
|
const newConfig = {
|
||||||
id: newId,
|
id: newId,
|
||||||
@@ -372,14 +564,16 @@ class ConfigPanel {
|
|||||||
};
|
};
|
||||||
this.configs.push(newConfig);
|
this.configs.push(newConfig);
|
||||||
vscode.window.showInformationMessage(`新建配置: ${name}`);
|
vscode.window.showInformationMessage(`新建配置: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
// 删除配置文件
|
// 删除配置文件
|
||||||
deleteConfig(configId) {
|
async deleteConfig(configId) {
|
||||||
const config = this.configs.find(c => c.id === configId);
|
const config = this.configs.find(c => c.id === configId);
|
||||||
if (config) {
|
if (config) {
|
||||||
this.configs = this.configs.filter(c => c.id !== configId);
|
this.configs = this.configs.filter(c => c.id !== configId);
|
||||||
vscode.window.showInformationMessage(`删除配置: ${config.name}`);
|
vscode.window.showInformationMessage(`删除配置: ${config.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -432,7 +626,11 @@ class ConfigPanel {
|
|||||||
// 写入文件
|
// 写入文件
|
||||||
const uint8Array = new TextEncoder().encode(content);
|
const uint8Array = new TextEncoder().encode(content);
|
||||||
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
||||||
|
// 更新配置内容
|
||||||
|
config.content = content;
|
||||||
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
||||||
|
// 保存数据到JSON文件
|
||||||
|
await this.saveAllData();
|
||||||
}
|
}
|
||||||
catch (error) {
|
catch (error) {
|
||||||
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,35 +6,87 @@ const BaseView_1 = require("./BaseView");
|
|||||||
class AircraftView extends BaseView_1.BaseView {
|
class AircraftView extends BaseView_1.BaseView {
|
||||||
render(data) {
|
render(data) {
|
||||||
const aircrafts = data?.aircrafts || [];
|
const aircrafts = data?.aircrafts || [];
|
||||||
// 生成飞行器列表的 HTML
|
console.log('AircraftView 渲染数据:', aircrafts);
|
||||||
const aircraftsHtml = aircrafts.map((aircraft) => {
|
const aircraftsHtml = aircrafts.map(aircraft => `
|
||||||
return `
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span class="editable" onclick="editAircraftName('${aircraft.id}', '${aircraft.name}')">🛸 ${aircraft.name}</span>
|
<span class="aircraft-name" data-aircraft-id="${aircraft.id}">✈️ ${aircraft.name}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="clickable" onclick="openAircraftConfig('${aircraft.id}')">配置</span>
|
<span class="clickable" onclick="openAircraftConfig('${aircraft.id}', '${aircraft.projectId}')">配置容器</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn-delete" onclick="deleteAircraft('${aircraft.id}')">删除</button>
|
<button class="btn-delete" onclick="deleteAircraft('${aircraft.id}')">删除</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`).join('');
|
||||||
}).join('');
|
|
||||||
return `<!DOCTYPE html>
|
return `<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>飞行器管理</title>
|
<title>飞行器配置</title>
|
||||||
${this.getStyles()}
|
${this.getStyles()}
|
||||||
|
<style>
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.back-btn {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
color: var(--vscode-input-foreground);
|
||||||
|
border: 1px solid var(--vscode-input-border);
|
||||||
|
padding: 5px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.back-btn:hover {
|
||||||
|
background: var(--vscode-inputOption-hoverBackground);
|
||||||
|
}
|
||||||
|
.btn-new {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
margin: 0 auto; /* 确保按钮在容器内居中 */
|
||||||
|
}
|
||||||
|
.btn-new:hover {
|
||||||
|
background: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
.aircraft-name {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
.aircraft-name:hover {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
}
|
||||||
|
/* 专门为新建按钮的容器添加样式 */
|
||||||
|
.new-button-container {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h2>🚀 飞行器管理</h2>
|
<h2>飞行器配置</h2>
|
||||||
<button class="back-btn" onclick="goBackToProjects()">← 返回项目管理</button>
|
<button class="back-btn" onclick="goBackToProjects()">← 返回项目</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -45,8 +97,9 @@ class AircraftView extends BaseView_1.BaseView {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
${aircraftsHtml}
|
${aircraftsHtml}
|
||||||
|
<!-- 修复:使用专门的容器类确保居中 -->
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" style="text-align: center; padding: 20px;">
|
<td colspan="3" class="new-button-container">
|
||||||
<button class="btn-new" onclick="createNewAircraft()">+ 新建飞行器</button>
|
<button class="btn-new" onclick="createNewAircraft()">+ 新建飞行器</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -56,27 +109,17 @@ class AircraftView extends BaseView_1.BaseView {
|
|||||||
<script>
|
<script>
|
||||||
const vscode = acquireVsCodeApi();
|
const vscode = acquireVsCodeApi();
|
||||||
|
|
||||||
function editAircraftName(aircraftId, currentName) {
|
function openAircraftConfig(aircraftId, projectId) {
|
||||||
showPromptDialog(
|
|
||||||
'修改飞行器名称',
|
|
||||||
'请输入新的飞行器名称:',
|
|
||||||
currentName,
|
|
||||||
function(newName) {
|
|
||||||
if (newName && newName !== currentName) {
|
|
||||||
vscode.postMessage({
|
|
||||||
type: 'updateAircraftName',
|
|
||||||
aircraftId: aircraftId,
|
|
||||||
name: newName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openAircraftConfig(aircraftId) {
|
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
type: 'openAircraftConfig',
|
type: 'openAircraftConfig',
|
||||||
aircraftId: aircraftId
|
aircraftId: aircraftId,
|
||||||
|
projectId: projectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function goBackToProjects() {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'goBackToProjects'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +155,36 @@ class AircraftView extends BaseView_1.BaseView {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBackToProjects() {
|
// 飞行器名称编辑功能
|
||||||
vscode.postMessage({ type: 'goBackToProjects' });
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
if (event.target.classList.contains('aircraft-name')) {
|
||||||
|
const aircraftNameElement = event.target;
|
||||||
|
const aircraftId = aircraftNameElement.getAttribute('data-aircraft-id');
|
||||||
|
const currentName = aircraftNameElement.textContent.trim().split(' ').slice(1).join(' ');
|
||||||
|
|
||||||
|
if (aircraftId) {
|
||||||
|
editAircraftName(aircraftId, currentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function editAircraftName(aircraftId, currentName) {
|
||||||
|
showPromptDialog(
|
||||||
|
'修改飞行器名称',
|
||||||
|
'请输入新的飞行器名称:',
|
||||||
|
currentName,
|
||||||
|
function(newName) {
|
||||||
|
if (newName && newName !== currentName) {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'updateAircraftName',
|
||||||
|
aircraftId: aircraftId,
|
||||||
|
name: newName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对话框函数
|
// 对话框函数
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"AircraftView.js","sourceRoot":"","sources":["../../../src/panels/views/AircraftView.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AACnC,yCAAsC;AAEtC,MAAa,YAAa,SAAQ,mBAAQ;IACtC,MAAM,CAAC,IAA2B;QAC9B,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;QAExC,gBAAgB;QAChB,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,QAAa,EAAE,EAAE;YAClD,OAAO;;;wEAGqD,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,IAAI,UAAU,QAAQ,CAAC,IAAI;;;2EAGnD,QAAQ,CAAC,EAAE;;;0EAGZ,QAAQ,CAAC,EAAE;;;aAGxE,CAAC;QACN,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;cAgBR,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAyJnB,CAAC;IACL,CAAC;CACJ;AAtMD,oCAsMC"}
|
{"version":3,"file":"AircraftView.js","sourceRoot":"","sources":["../../../src/panels/views/AircraftView.ts"],"names":[],"mappings":";;;AAAA,mCAAmC;AACnC,yCAAsC;AAQtC,MAAa,YAAa,SAAQ,mBAAQ;IACtC,MAAM,CAAC,IAAwC;QAC3C,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,IAAI,EAAE,CAAC;QAExC,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,SAAS,CAAC,CAAC;QAE7C,MAAM,aAAa,GAAG,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;;;oEAGY,QAAQ,CAAC,EAAE,QAAQ,QAAQ,CAAC,IAAI;;;2EAGzB,QAAQ,CAAC,EAAE,OAAO,QAAQ,CAAC,SAAS;;;0EAGrC,QAAQ,CAAC,EAAE;;;SAG5E,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsER,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA4KnB,CAAC;IACL,CAAC;CACJ;AA9QD,oCA8QC"}
|
||||||
@@ -62,10 +62,41 @@ class ProjectView extends BaseView_1.BaseView {
|
|||||||
.project-name:hover {
|
.project-name:hover {
|
||||||
background: var(--vscode-input-background);
|
background: var(--vscode-input-background);
|
||||||
}
|
}
|
||||||
|
.table-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.btn-action {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.btn-action:hover {
|
||||||
|
background: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
.btn-new {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
}
|
||||||
|
.btn-open {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
color: var(--vscode-input-foreground);
|
||||||
|
border: 1px solid var(--vscode-input-border);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2><span class="satellite-icon">🛰️</span>数字卫星构建平台</h2>
|
<h2><span class="satellite-icon">🛰️</span>数字卫星构建平台</h2>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -77,8 +108,15 @@ class ProjectView extends BaseView_1.BaseView {
|
|||||||
<tbody>
|
<tbody>
|
||||||
${projectsHtml}
|
${projectsHtml}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" style="text-align: center; padding: 20px;">
|
<td colspan="3" style="padding: 20px;">
|
||||||
<button class="btn-new" onclick="createNewProject()">+ 新建项目</button>
|
<div class="table-actions">
|
||||||
|
<button class="btn-action btn-open" onclick="openExistingProject()">
|
||||||
|
<span style="font-size: 14px;">📂</span> 打开项目
|
||||||
|
</button>
|
||||||
|
<button class="btn-action btn-new" onclick="createNewProject()">
|
||||||
|
<span style="font-size: 14px;">+</span> 新建项目
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -104,6 +142,12 @@ class ProjectView extends BaseView_1.BaseView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openExistingProject() {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'openExistingProject'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createNewProject() {
|
function createNewProject() {
|
||||||
showPromptDialog(
|
showPromptDialog(
|
||||||
'新建项目',
|
'新建项目',
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"version":3,"file":"ProjectView.js","sourceRoot":"","sources":["../../../src/panels/views/ProjectView.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AAClC,yCAAsC;AAGtC,MAAa,WAAY,SAAQ,mBAAQ;IACrC,MAAM,CAAC,IAA0E;QAC7E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,IAAI,GAAG,EAAE,CAAC;QAErD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAwB,EAAE,EAAE;YAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAEhD,OAAO;;;kEAG+C,OAAO,CAAC,EAAE,KAAK,UAAU,IAAI,OAAO,CAAC,IAAI;;0BAEjF,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;;;yEAItB,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,MAAM,YAAY;0BAC9F,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;yEAIqB,OAAO,CAAC,EAAE;;;SAG1E,CAAA;QAAA,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEb,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAuCR,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA8KlB,CAAC;IACL,CAAC;CACJ;AA1PD,kCA0PC"}
|
{"version":3,"file":"ProjectView.js","sourceRoot":"","sources":["../../../src/panels/views/ProjectView.ts"],"names":[],"mappings":";;;AAAA,kCAAkC;AAClC,yCAAsC;AAGtC,MAAa,WAAY,SAAQ,mBAAQ;IACrC,MAAM,CAAC,IAA0E;QAC7E,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,YAAY,GAAG,IAAI,EAAE,YAAY,IAAI,IAAI,GAAG,EAAE,CAAC;QAErD,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAwB,EAAE,EAAE;YAC3D,MAAM,YAAY,GAAG,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClD,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;YAC7C,MAAM,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAEhD,OAAO;;;kEAG+C,OAAO,CAAC,EAAE,KAAK,UAAU,IAAI,OAAO,CAAC,IAAI;;0BAEjF,UAAU,GAAG,YAAY,CAAC,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;;;;yEAItB,OAAO,CAAC,EAAE,OAAO,OAAO,CAAC,IAAI,MAAM,YAAY;0BAC9F,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;;;;yEAIqB,OAAO,CAAC,EAAE;;;SAG1E,CAAA;QAAA,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEb,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAsER,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA2LlB,CAAC;IACL,CAAC;CACJ;AAtSD,kCAsSC"}
|
||||||
@@ -31,6 +31,14 @@ interface Config {
|
|||||||
containerId: string;
|
containerId: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ProjectData {
|
||||||
|
projects: Project[];
|
||||||
|
aircrafts: Aircraft[];
|
||||||
|
containers: Container[];
|
||||||
|
configs: Config[];
|
||||||
|
projectPaths: { [key: string]: string };
|
||||||
|
}
|
||||||
|
|
||||||
export class ConfigPanel {
|
export class ConfigPanel {
|
||||||
private static currentPanel: ConfigPanel | undefined;
|
private static currentPanel: ConfigPanel | undefined;
|
||||||
private readonly panel: vscode.WebviewPanel;
|
private readonly panel: vscode.WebviewPanel;
|
||||||
@@ -99,6 +107,10 @@ export class ConfigPanel {
|
|||||||
private setupMessageListener() {
|
private setupMessageListener() {
|
||||||
this.panel.webview.onDidReceiveMessage(async (data) => {
|
this.panel.webview.onDidReceiveMessage(async (data) => {
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
|
case 'openExistingProject':
|
||||||
|
await this.openExistingProject();
|
||||||
|
break;
|
||||||
|
|
||||||
case 'configureProject':
|
case 'configureProject':
|
||||||
const selectedPath = await this.selectProjectPath(data.projectId, data.projectName);
|
const selectedPath = await this.selectProjectPath(data.projectId, data.projectName);
|
||||||
if (selectedPath) {
|
if (selectedPath) {
|
||||||
@@ -131,45 +143,54 @@ export class ConfigPanel {
|
|||||||
// 修复返回按钮的消息处理
|
// 修复返回按钮的消息处理
|
||||||
case 'goBackToProjects':
|
case 'goBackToProjects':
|
||||||
this.currentView = 'projects';
|
this.currentView = 'projects';
|
||||||
|
// 清空当前选择的ID
|
||||||
|
this.currentProjectId = '';
|
||||||
|
this.currentAircraftId = '';
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'goBackToAircrafts':
|
case 'goBackToAircrafts':
|
||||||
this.currentView = 'aircrafts';
|
this.currentView = 'aircrafts';
|
||||||
|
// 保持 currentProjectId,清空其他ID
|
||||||
|
this.currentAircraftId = '';
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'goBackToContainers':
|
case 'goBackToContainers':
|
||||||
this.currentView = 'containers';
|
this.currentView = 'containers';
|
||||||
|
// 保持 currentProjectId 和 currentAircraftId,清空 currentContainerId
|
||||||
|
this.currentContainerId = '';
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'updateProjectName':
|
case 'updateProjectName':
|
||||||
this.updateProjectName(data.projectId, data.name);
|
await this.updateProjectName(data.projectId, data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'createProject':
|
case 'createProject':
|
||||||
this.createProject(data.name);
|
await this.createProject(data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'updateAircraftName':
|
case 'updateAircraftName':
|
||||||
this.updateAircraftName(data.aircraftId, data.name);
|
await this.updateAircraftName(data.aircraftId, data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'createAircraft':
|
case 'createAircraft':
|
||||||
this.createAircraft(data.name);
|
await this.createAircraft(data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'updateContainerName':
|
case 'updateContainerName':
|
||||||
this.updateContainerName(data.containerId, data.name);
|
await this.updateContainerName(data.containerId, data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'createContainer':
|
case 'createContainer':
|
||||||
this.createContainer(data.name);
|
await this.createContainer(data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'updateConfigName':
|
case 'updateConfigName':
|
||||||
this.updateConfigName(data.configId, data.name);
|
await this.updateConfigName(data.configId, data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'updateConfigFileName':
|
case 'updateConfigFileName':
|
||||||
@@ -177,7 +198,7 @@ export class ConfigPanel {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'createConfig':
|
case 'createConfig':
|
||||||
this.createConfig(data.name);
|
await this.createConfig(data.name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'saveConfigFile':
|
case 'saveConfigFile':
|
||||||
@@ -189,25 +210,186 @@ export class ConfigPanel {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 'deleteProject':
|
case 'deleteProject':
|
||||||
this.deleteProject(data.projectId);
|
await this.deleteProject(data.projectId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'deleteAircraft':
|
case 'deleteAircraft':
|
||||||
this.deleteAircraft(data.aircraftId);
|
await this.deleteAircraft(data.aircraftId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'deleteContainer':
|
case 'deleteContainer':
|
||||||
this.deleteContainer(data.containerId);
|
await this.deleteContainer(data.containerId);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'deleteConfig':
|
case 'deleteConfig':
|
||||||
this.deleteConfig(data.configId);
|
await this.deleteConfig(data.configId);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... 其余方法保持不变(selectProjectPath, updateProjectName, createProject等)
|
// === 打开现有项目功能 ===
|
||||||
|
private async openExistingProject(): Promise<void> {
|
||||||
|
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 saveAllData(): Promise<void> {
|
||||||
|
try {
|
||||||
|
console.log('开始保存数据...');
|
||||||
|
console.log('当前项目ID:', this.currentProjectId);
|
||||||
|
console.log('项目路径映射:', Array.from(this.projectPaths.entries()));
|
||||||
|
|
||||||
|
// 找到当前项目的路径
|
||||||
|
let projectPath: string | undefined;
|
||||||
|
|
||||||
|
// 首先尝试使用当前项目ID
|
||||||
|
if (this.currentProjectId) {
|
||||||
|
projectPath = this.projectPaths.get(this.currentProjectId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有找到,尝试使用第一个项目
|
||||||
|
if (!projectPath && this.projects.length > 0) {
|
||||||
|
projectPath = this.projectPaths.get(this.projects[0].id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!projectPath) {
|
||||||
|
console.log('未找到项目路径,跳过保存数据');
|
||||||
|
vscode.window.showWarningMessage('未找到项目存储路径,数据将不会保存');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dataUri = vscode.Uri.joinPath(vscode.Uri.file(projectPath), '.dcsp-data.json');
|
||||||
|
|
||||||
|
const data: ProjectData = {
|
||||||
|
projects: this.projects,
|
||||||
|
aircrafts: this.aircrafts,
|
||||||
|
containers: this.containers,
|
||||||
|
configs: this.configs,
|
||||||
|
projectPaths: Object.fromEntries(this.projectPaths)
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log('要保存的数据:', {
|
||||||
|
projects: this.projects.length,
|
||||||
|
aircrafts: this.aircrafts.length,
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length,
|
||||||
|
projectPaths: this.projectPaths.size
|
||||||
|
});
|
||||||
|
|
||||||
|
const uint8Array = new TextEncoder().encode(JSON.stringify(data, null, 2));
|
||||||
|
await vscode.workspace.fs.writeFile(dataUri, uint8Array);
|
||||||
|
|
||||||
|
console.log('项目数据已保存到:', dataUri.fsPath);
|
||||||
|
vscode.window.showInformationMessage('项目数据已保存');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('保存项目数据时出错:', error);
|
||||||
|
vscode.window.showErrorMessage(`保存项目数据失败: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从项目路径加载数据
|
||||||
|
*/
|
||||||
|
private async loadProjectData(projectPath: string): Promise<boolean> {
|
||||||
|
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);
|
||||||
|
|
||||||
|
console.log('从文件加载的数据:', data);
|
||||||
|
|
||||||
|
// 清空现有数据
|
||||||
|
this.projects = [];
|
||||||
|
this.aircrafts = [];
|
||||||
|
this.containers = [];
|
||||||
|
this.configs = [];
|
||||||
|
this.projectPaths = new Map();
|
||||||
|
|
||||||
|
// 验证数据格式并加载
|
||||||
|
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.projectPaths && typeof data.projectPaths === 'object') {
|
||||||
|
this.projectPaths = new Map(Object.entries(data.projectPaths));
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('加载后的数据状态:', {
|
||||||
|
projects: this.projects.length,
|
||||||
|
aircrafts: this.aircrafts.length,
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length,
|
||||||
|
projectPaths: this.projectPaths.size
|
||||||
|
});
|
||||||
|
|
||||||
|
// 设置当前项目为第一个项目(如果有的话)
|
||||||
|
if (this.projects.length > 0) {
|
||||||
|
this.currentProjectId = this.projects[0].id;
|
||||||
|
this.currentView = 'aircrafts';
|
||||||
|
}
|
||||||
|
|
||||||
|
vscode.window.showInformationMessage(`项目数据已从 ${projectPath} 加载`);
|
||||||
|
this.updateWebview();
|
||||||
|
return true;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载项目数据时出错:', error);
|
||||||
|
vscode.window.showErrorMessage(`加载项目数据失败: ${error}`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查项目路径是否已存在数据
|
||||||
|
*/
|
||||||
|
private async checkProjectPathHasData(projectPath: string): Promise<boolean> {
|
||||||
|
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<string | null> {
|
private async selectProjectPath(projectId: string, projectName: string): Promise<string | null> {
|
||||||
try {
|
try {
|
||||||
@@ -246,8 +428,38 @@ export class ConfigPanel {
|
|||||||
|
|
||||||
if (result && result.length > 0) {
|
if (result && result.length > 0) {
|
||||||
const selectedPath = result[0].fsPath;
|
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);
|
this.projectPaths.set(projectId, selectedPath);
|
||||||
vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`);
|
vscode.window.showInformationMessage(`项目存储位置已设置: ${selectedPath}`);
|
||||||
|
|
||||||
|
// 保存初始数据
|
||||||
|
await this.saveAllData();
|
||||||
|
|
||||||
return selectedPath;
|
return selectedPath;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -271,6 +483,10 @@ export class ConfigPanel {
|
|||||||
|
|
||||||
this.projectPaths.set(projectId, pathInput);
|
this.projectPaths.set(projectId, pathInput);
|
||||||
vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`);
|
vscode.window.showInformationMessage(`项目存储位置已创建: ${pathInput}`);
|
||||||
|
|
||||||
|
// 保存初始数据
|
||||||
|
await this.saveAllData();
|
||||||
|
|
||||||
return pathInput;
|
return pathInput;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(`创建目录失败: ${error}`);
|
vscode.window.showErrorMessage(`创建目录失败: ${error}`);
|
||||||
@@ -287,17 +503,18 @@ export class ConfigPanel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 更新项目名
|
// 更新项目名
|
||||||
private updateProjectName(projectId: string, newName: string) {
|
private async updateProjectName(projectId: string, newName: string) {
|
||||||
const project = this.projects.find(p => p.id === projectId);
|
const project = this.projects.find(p => p.id === projectId);
|
||||||
if (project) {
|
if (project) {
|
||||||
project.name = newName;
|
project.name = newName;
|
||||||
vscode.window.showInformationMessage(`项目名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`项目名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新项目
|
// 创建新项目
|
||||||
private createProject(name: string) {
|
private async createProject(name: string) {
|
||||||
const newId = 'p' + (this.projects.length + 1);
|
const newId = 'p' + (this.projects.length + 1);
|
||||||
const newProject: Project = {
|
const newProject: Project = {
|
||||||
id: newId,
|
id: newId,
|
||||||
@@ -306,11 +523,12 @@ export class ConfigPanel {
|
|||||||
this.projects.push(newProject);
|
this.projects.push(newProject);
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`新建项目: ${name}`);
|
vscode.window.showInformationMessage(`新建项目: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除项目
|
// 删除项目
|
||||||
private deleteProject(projectId: string) {
|
private async deleteProject(projectId: string) {
|
||||||
const project = this.projects.find(p => p.id === projectId);
|
const project = this.projects.find(p => p.id === projectId);
|
||||||
if (!project) return;
|
if (!project) return;
|
||||||
|
|
||||||
@@ -328,21 +546,23 @@ export class ConfigPanel {
|
|||||||
this.projectPaths.delete(projectId);
|
this.projectPaths.delete(projectId);
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`删除项目: ${project.name}`);
|
vscode.window.showInformationMessage(`删除项目: ${project.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新飞行器名
|
// 更新飞行器名
|
||||||
private updateAircraftName(aircraftId: string, newName: string) {
|
private async updateAircraftName(aircraftId: string, newName: string) {
|
||||||
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
||||||
if (aircraft) {
|
if (aircraft) {
|
||||||
aircraft.name = newName;
|
aircraft.name = newName;
|
||||||
vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`飞行器名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新飞行器
|
// 创建新飞行器
|
||||||
private createAircraft(name: string) {
|
private async createAircraft(name: string) {
|
||||||
if (!this.currentProjectId) {
|
if (!this.currentProjectId) {
|
||||||
vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目');
|
vscode.window.showErrorMessage('无法创建飞行器:未找到当前项目');
|
||||||
return;
|
return;
|
||||||
@@ -357,11 +577,12 @@ export class ConfigPanel {
|
|||||||
this.aircrafts.push(newAircraft);
|
this.aircrafts.push(newAircraft);
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`新建飞行器: ${name}`);
|
vscode.window.showInformationMessage(`新建飞行器: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除飞行器
|
// 删除飞行器
|
||||||
private deleteAircraft(aircraftId: string) {
|
private async deleteAircraft(aircraftId: string) {
|
||||||
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
const aircraft = this.aircrafts.find(a => a.id === aircraftId);
|
||||||
if (!aircraft) return;
|
if (!aircraft) return;
|
||||||
|
|
||||||
@@ -373,21 +594,23 @@ export class ConfigPanel {
|
|||||||
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
|
this.configs = this.configs.filter(cfg => !containerIds.includes(cfg.containerId));
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`);
|
vscode.window.showInformationMessage(`删除飞行器: ${aircraft.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新容器名
|
// 更新容器名
|
||||||
private updateContainerName(containerId: string, newName: string) {
|
private async updateContainerName(containerId: string, newName: string) {
|
||||||
const container = this.containers.find(c => c.id === containerId);
|
const container = this.containers.find(c => c.id === containerId);
|
||||||
if (container) {
|
if (container) {
|
||||||
container.name = newName;
|
container.name = newName;
|
||||||
vscode.window.showInformationMessage(`容器名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`容器名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新容器
|
// 创建新容器 - 修复版本
|
||||||
private createContainer(name: string) {
|
private async createContainer(name: string) {
|
||||||
console.log('创建容器,当前飞行器ID:', this.currentAircraftId);
|
console.log('创建容器,当前飞行器ID:', this.currentAircraftId);
|
||||||
|
|
||||||
if (!this.currentAircraftId) {
|
if (!this.currentAircraftId) {
|
||||||
@@ -411,7 +634,7 @@ export class ConfigPanel {
|
|||||||
this.configs.push({
|
this.configs.push({
|
||||||
id: 'cfg' + (configCount + 1),
|
id: 'cfg' + (configCount + 1),
|
||||||
name: '配置1',
|
name: '配置1',
|
||||||
fileName: 'config.sh',
|
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"]`,
|
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
|
containerId: newId
|
||||||
});
|
});
|
||||||
@@ -420,17 +643,23 @@ export class ConfigPanel {
|
|||||||
this.configs.push({
|
this.configs.push({
|
||||||
id: 'cfg' + (configCount + 2),
|
id: 'cfg' + (configCount + 2),
|
||||||
name: '配置2',
|
name: '配置2',
|
||||||
fileName: 'config.sh',
|
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`,
|
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
|
containerId: newId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log('创建容器后的数据状态:', {
|
||||||
|
containers: this.containers.length,
|
||||||
|
configs: this.configs.length
|
||||||
|
});
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`);
|
vscode.window.showInformationMessage(`新建容器: ${name} (包含2个默认配置文件)`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除容器
|
// 删除容器
|
||||||
private deleteContainer(containerId: string) {
|
private async deleteContainer(containerId: string) {
|
||||||
const container = this.containers.find(c => c.id === containerId);
|
const container = this.containers.find(c => c.id === containerId);
|
||||||
if (!container) return;
|
if (!container) return;
|
||||||
|
|
||||||
@@ -441,15 +670,17 @@ export class ConfigPanel {
|
|||||||
this.configs = this.configs.filter(cfg => cfg.containerId !== containerId);
|
this.configs = this.configs.filter(cfg => cfg.containerId !== containerId);
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`删除容器: ${container.name}`);
|
vscode.window.showInformationMessage(`删除容器: ${container.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 更新配置名
|
// 更新配置名
|
||||||
private updateConfigName(configId: string, newName: string) {
|
private async updateConfigName(configId: string, newName: string) {
|
||||||
const config = this.configs.find(c => c.id === configId);
|
const config = this.configs.find(c => c.id === configId);
|
||||||
if (config) {
|
if (config) {
|
||||||
config.name = newName;
|
config.name = newName;
|
||||||
vscode.window.showInformationMessage(`配置名称更新: ${newName}`);
|
vscode.window.showInformationMessage(`配置名称更新: ${newName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -460,12 +691,13 @@ export class ConfigPanel {
|
|||||||
if (config) {
|
if (config) {
|
||||||
config.fileName = fileName;
|
config.fileName = fileName;
|
||||||
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 创建新配置文件
|
// 创建新配置文件
|
||||||
private createConfig(name: string) {
|
private async createConfig(name: string) {
|
||||||
const newId = 'cfg' + (this.configs.length + 1);
|
const newId = 'cfg' + (this.configs.length + 1);
|
||||||
const newConfig: Config = {
|
const newConfig: Config = {
|
||||||
id: newId,
|
id: newId,
|
||||||
@@ -477,15 +709,17 @@ export class ConfigPanel {
|
|||||||
this.configs.push(newConfig);
|
this.configs.push(newConfig);
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`新建配置: ${name}`);
|
vscode.window.showInformationMessage(`新建配置: ${name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除配置文件
|
// 删除配置文件
|
||||||
private deleteConfig(configId: string) {
|
private async deleteConfig(configId: string) {
|
||||||
const config = this.configs.find(c => c.id === configId);
|
const config = this.configs.find(c => c.id === configId);
|
||||||
if (config) {
|
if (config) {
|
||||||
this.configs = this.configs.filter(c => c.id !== configId);
|
this.configs = this.configs.filter(c => c.id !== configId);
|
||||||
vscode.window.showInformationMessage(`删除配置: ${config.name}`);
|
vscode.window.showInformationMessage(`删除配置: ${config.name}`);
|
||||||
|
await this.saveAllData();
|
||||||
this.updateWebview();
|
this.updateWebview();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -546,7 +780,13 @@ export class ConfigPanel {
|
|||||||
const uint8Array = new TextEncoder().encode(content);
|
const uint8Array = new TextEncoder().encode(content);
|
||||||
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
||||||
|
|
||||||
|
// 更新配置内容
|
||||||
|
config.content = content;
|
||||||
|
|
||||||
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
||||||
|
|
||||||
|
// 保存数据到JSON文件
|
||||||
|
await this.saveAllData();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,40 +1,99 @@
|
|||||||
// src/panels/views/AircraftView.ts
|
// src/panels/views/AircraftView.ts
|
||||||
import { BaseView } from './BaseView';
|
import { BaseView } from './BaseView';
|
||||||
|
|
||||||
|
interface AircraftViewData {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
projectId: string;
|
||||||
|
}
|
||||||
|
|
||||||
export class AircraftView extends BaseView {
|
export class AircraftView extends BaseView {
|
||||||
render(data?: { aircrafts: any[] }): string {
|
render(data?: { aircrafts: AircraftViewData[] }): string {
|
||||||
const aircrafts = data?.aircrafts || [];
|
const aircrafts = data?.aircrafts || [];
|
||||||
|
|
||||||
// 生成飞行器列表的 HTML
|
console.log('AircraftView 渲染数据:', aircrafts);
|
||||||
const aircraftsHtml = aircrafts.map((aircraft: any) => {
|
|
||||||
return `
|
const aircraftsHtml = aircrafts.map(aircraft => `
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<span class="editable" onclick="editAircraftName('${aircraft.id}', '${aircraft.name}')">🛸 ${aircraft.name}</span>
|
<span class="aircraft-name" data-aircraft-id="${aircraft.id}">✈️ ${aircraft.name}</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<span class="clickable" onclick="openAircraftConfig('${aircraft.id}')">配置</span>
|
<span class="clickable" onclick="openAircraftConfig('${aircraft.id}', '${aircraft.projectId}')">配置容器</span>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<button class="btn-delete" onclick="deleteAircraft('${aircraft.id}')">删除</button>
|
<button class="btn-delete" onclick="deleteAircraft('${aircraft.id}')">删除</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
`;
|
`).join('');
|
||||||
}).join('');
|
|
||||||
|
|
||||||
return `<!DOCTYPE html>
|
return `<!DOCTYPE html>
|
||||||
<html lang="zh-CN">
|
<html lang="zh-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>飞行器管理</title>
|
<title>飞行器配置</title>
|
||||||
${this.getStyles()}
|
${this.getStyles()}
|
||||||
|
<style>
|
||||||
|
.header {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
.back-btn {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
color: var(--vscode-input-foreground);
|
||||||
|
border: 1px solid var(--vscode-input-border);
|
||||||
|
padding: 5px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.back-btn:hover {
|
||||||
|
background: var(--vscode-inputOption-hoverBackground);
|
||||||
|
}
|
||||||
|
.btn-new {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
margin: 0 auto; /* 确保按钮在容器内居中 */
|
||||||
|
}
|
||||||
|
.btn-new:hover {
|
||||||
|
background: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
.aircraft-name {
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 4px 8px;
|
||||||
|
border-radius: 4px;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
.aircraft-name:hover {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
}
|
||||||
|
/* 专门为新建按钮的容器添加样式 */
|
||||||
|
.new-button-container {
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<h2>🚀 飞行器管理</h2>
|
<h2>飞行器配置</h2>
|
||||||
<button class="back-btn" onclick="goBackToProjects()">← 返回项目管理</button>
|
<button class="back-btn" onclick="goBackToProjects()">← 返回项目</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -45,8 +104,9 @@ export class AircraftView extends BaseView {
|
|||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
${aircraftsHtml}
|
${aircraftsHtml}
|
||||||
|
<!-- 修复:使用专门的容器类确保居中 -->
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" style="text-align: center; padding: 20px;">
|
<td colspan="3" class="new-button-container">
|
||||||
<button class="btn-new" onclick="createNewAircraft()">+ 新建飞行器</button>
|
<button class="btn-new" onclick="createNewAircraft()">+ 新建飞行器</button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -56,27 +116,17 @@ export class AircraftView extends BaseView {
|
|||||||
<script>
|
<script>
|
||||||
const vscode = acquireVsCodeApi();
|
const vscode = acquireVsCodeApi();
|
||||||
|
|
||||||
function editAircraftName(aircraftId, currentName) {
|
function openAircraftConfig(aircraftId, projectId) {
|
||||||
showPromptDialog(
|
|
||||||
'修改飞行器名称',
|
|
||||||
'请输入新的飞行器名称:',
|
|
||||||
currentName,
|
|
||||||
function(newName) {
|
|
||||||
if (newName && newName !== currentName) {
|
|
||||||
vscode.postMessage({
|
|
||||||
type: 'updateAircraftName',
|
|
||||||
aircraftId: aircraftId,
|
|
||||||
name: newName
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openAircraftConfig(aircraftId) {
|
|
||||||
vscode.postMessage({
|
vscode.postMessage({
|
||||||
type: 'openAircraftConfig',
|
type: 'openAircraftConfig',
|
||||||
aircraftId: aircraftId
|
aircraftId: aircraftId,
|
||||||
|
projectId: projectId
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function goBackToProjects() {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'goBackToProjects'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,8 +162,36 @@ export class AircraftView extends BaseView {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
function goBackToProjects() {
|
// 飞行器名称编辑功能
|
||||||
vscode.postMessage({ type: 'goBackToProjects' });
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
document.addEventListener('click', function(event) {
|
||||||
|
if (event.target.classList.contains('aircraft-name')) {
|
||||||
|
const aircraftNameElement = event.target;
|
||||||
|
const aircraftId = aircraftNameElement.getAttribute('data-aircraft-id');
|
||||||
|
const currentName = aircraftNameElement.textContent.trim().split(' ').slice(1).join(' ');
|
||||||
|
|
||||||
|
if (aircraftId) {
|
||||||
|
editAircraftName(aircraftId, currentName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function editAircraftName(aircraftId, currentName) {
|
||||||
|
showPromptDialog(
|
||||||
|
'修改飞行器名称',
|
||||||
|
'请输入新的飞行器名称:',
|
||||||
|
currentName,
|
||||||
|
function(newName) {
|
||||||
|
if (newName && newName !== currentName) {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'updateAircraftName',
|
||||||
|
aircraftId: aircraftId,
|
||||||
|
name: newName
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 对话框函数
|
// 对话框函数
|
||||||
|
|||||||
@@ -63,10 +63,41 @@ export class ProjectView extends BaseView {
|
|||||||
.project-name:hover {
|
.project-name:hover {
|
||||||
background: var(--vscode-input-background);
|
background: var(--vscode-input-background);
|
||||||
}
|
}
|
||||||
|
.table-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
.btn-action {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
border: none;
|
||||||
|
padding: 8px 16px;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 13px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
.btn-action:hover {
|
||||||
|
background: var(--vscode-button-hoverBackground);
|
||||||
|
}
|
||||||
|
.btn-new {
|
||||||
|
background: var(--vscode-button-background);
|
||||||
|
color: var(--vscode-button-foreground);
|
||||||
|
}
|
||||||
|
.btn-open {
|
||||||
|
background: var(--vscode-input-background);
|
||||||
|
color: var(--vscode-input-foreground);
|
||||||
|
border: 1px solid var(--vscode-input-border);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h2><span class="satellite-icon">🛰️</span>数字卫星构建平台</h2>
|
<h2><span class="satellite-icon">🛰️</span>数字卫星构建平台</h2>
|
||||||
|
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
@@ -78,8 +109,15 @@ export class ProjectView extends BaseView {
|
|||||||
<tbody>
|
<tbody>
|
||||||
${projectsHtml}
|
${projectsHtml}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="3" style="text-align: center; padding: 20px;">
|
<td colspan="3" style="padding: 20px;">
|
||||||
<button class="btn-new" onclick="createNewProject()">+ 新建项目</button>
|
<div class="table-actions">
|
||||||
|
<button class="btn-action btn-open" onclick="openExistingProject()">
|
||||||
|
<span style="font-size: 14px;">📂</span> 打开项目
|
||||||
|
</button>
|
||||||
|
<button class="btn-action btn-new" onclick="createNewProject()">
|
||||||
|
<span style="font-size: 14px;">+</span> 新建项目
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
@@ -105,6 +143,12 @@ export class ProjectView extends BaseView {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openExistingProject() {
|
||||||
|
vscode.postMessage({
|
||||||
|
type: 'openExistingProject'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function createNewProject() {
|
function createNewProject() {
|
||||||
showPromptDialog(
|
showPromptDialog(
|
||||||
'新建项目',
|
'新建项目',
|
||||||
|
|||||||
Reference in New Issue
Block a user