打开git代码功能完成
This commit is contained in:
@@ -165,18 +165,9 @@ class ConfigPanel {
|
||||
case 'updateConfigName':
|
||||
await this.updateConfigName(data.configId, data.name);
|
||||
break;
|
||||
case 'updateConfigFileName':
|
||||
await this.updateConfigFileName(data.configId, data.fileName);
|
||||
break;
|
||||
case 'createConfig':
|
||||
await this.createConfig(data.name);
|
||||
break;
|
||||
case 'saveConfigFile':
|
||||
await this.saveConfigFileToDisk(data.configId, data.content);
|
||||
break;
|
||||
case 'loadConfigFile':
|
||||
this.loadConfigFile(data.configId);
|
||||
break;
|
||||
case 'deleteProject':
|
||||
await this.deleteProject(data.projectId);
|
||||
break;
|
||||
@@ -217,6 +208,9 @@ class ConfigPanel {
|
||||
case 'openGitRepoInVSCode':
|
||||
await this.openGitRepoInVSCode(data.repoId);
|
||||
break;
|
||||
case 'openConfigFileInVSCode':
|
||||
await this.openConfigFileInVSCode(data.configId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
@@ -339,7 +333,7 @@ class ConfigPanel {
|
||||
// 为每个分支创建独立的子目录
|
||||
const branchName = branch || 'main';
|
||||
const branchSafeName = branchName.replace(/[^a-zA-Z0-9-_]/g, '-');
|
||||
const repoDirName = `${name}-${branchSafeName}`;
|
||||
const repoDirName = name;
|
||||
// 路径:项目路径/飞行器名/容器名/仓库名-分支名/
|
||||
const localPath = path.join(projectPath, aircraft.name, container.name, repoDirName);
|
||||
console.log(`📁 Git仓库将保存到: ${localPath}`);
|
||||
@@ -1015,16 +1009,6 @@ class ConfigPanel {
|
||||
this.updateWebview();
|
||||
}
|
||||
}
|
||||
// 更新文件名
|
||||
async updateConfigFileName(configId, fileName) {
|
||||
const config = this.configs.find(c => c.id === configId);
|
||||
if (config) {
|
||||
config.fileName = fileName;
|
||||
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
||||
await this.saveCurrentProjectData();
|
||||
this.updateWebview();
|
||||
}
|
||||
}
|
||||
// 创建新配置文件
|
||||
async createConfig(name) {
|
||||
const newId = 'cfg' + (this.configs.length + 1);
|
||||
@@ -1078,95 +1062,6 @@ class ConfigPanel {
|
||||
vscode.window.showErrorMessage(`删除配置文件失败: ${error}`);
|
||||
}
|
||||
}
|
||||
// 保存配置文件到磁盘
|
||||
async saveConfigFileToDisk(configId, content) {
|
||||
try {
|
||||
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 project = this.projects.find(p => p.id === aircraft.projectId);
|
||||
if (!project) {
|
||||
vscode.window.showErrorMessage('未找到项目');
|
||||
return;
|
||||
}
|
||||
const projectPath = this.projectPaths.get(aircraft.projectId);
|
||||
if (!projectPath) {
|
||||
vscode.window.showErrorMessage('未设置项目存储路径,请先配置项目');
|
||||
return;
|
||||
}
|
||||
// 构建文件路径:项目路径/飞行器名/容器名/文件名
|
||||
const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name);
|
||||
const containerDir = vscode.Uri.joinPath(aircraftDir, container.name);
|
||||
const fileUri = vscode.Uri.joinPath(containerDir, config.fileName);
|
||||
// 确保飞行器目录存在
|
||||
try {
|
||||
await vscode.workspace.fs.createDirectory(aircraftDir);
|
||||
}
|
||||
catch (error) {
|
||||
// 目录可能已存在,忽略错误
|
||||
}
|
||||
// 确保容器目录存在
|
||||
try {
|
||||
await vscode.workspace.fs.createDirectory(containerDir);
|
||||
}
|
||||
catch (error) {
|
||||
// 目录可能已存在,忽略错误
|
||||
}
|
||||
// 写入文件
|
||||
const uint8Array = new TextEncoder().encode(content);
|
||||
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
||||
// 更新配置内容
|
||||
config.content = content;
|
||||
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
||||
// 保存数据到JSON文件
|
||||
await this.saveCurrentProjectData();
|
||||
}
|
||||
catch (error) {
|
||||
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
||||
}
|
||||
}
|
||||
// 加载配置文件
|
||||
loadConfigFile(configId) {
|
||||
if (this.isWebviewDisposed) {
|
||||
console.log('⚠️ Webview 已被销毁,跳过加载配置文件');
|
||||
return;
|
||||
}
|
||||
const config = this.configs.find(c => c.id === configId);
|
||||
if (config) {
|
||||
try {
|
||||
this.panel.webview.postMessage({
|
||||
type: 'configFileLoaded',
|
||||
content: config.content || `# ${config.name} 的配置文件\n# 您可以在此编辑配置内容\n\n`
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log('⚠️ 无法发送配置文件内容,Webview 可能已被销毁');
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
this.panel.webview.postMessage({
|
||||
type: 'configFileLoaded',
|
||||
content: `# 这是 ${configId} 的配置文件\n# 您可以在此编辑配置内容\n\napp.name = "示例应用"\napp.port = 8080\napp.debug = true`
|
||||
});
|
||||
}
|
||||
catch (error) {
|
||||
console.log('⚠️ 无法发送默认配置文件内容,Webview 可能已被销毁');
|
||||
}
|
||||
}
|
||||
}
|
||||
// === Git 分支管理 ===
|
||||
async fetchBranches(url) {
|
||||
try {
|
||||
@@ -1196,8 +1091,6 @@ class ConfigPanel {
|
||||
if (isRemote) {
|
||||
// 远程分支:移除 refs/remotes/origin/ 前缀
|
||||
branchName = ref.ref.replace('refs/remotes/origin/', '');
|
||||
// 可以选择添加远程标识,或者不添加
|
||||
// branchName = `origin/${branchName}`; // 如果需要显示远程标识
|
||||
}
|
||||
else {
|
||||
// 本地分支:移除 refs/heads/ 前缀
|
||||
@@ -1371,6 +1264,47 @@ class ConfigPanel {
|
||||
vscode.window.showErrorMessage(`打开 Git 仓库文件失败: ${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}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.ConfigPanel = ConfigPanel;
|
||||
//# sourceMappingURL=ConfigPanel.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -19,7 +19,7 @@ class ConfigView extends BaseView_1.BaseView {
|
||||
<span class="editable" onclick="editConfigName('${config.id}', '${config.name}')">🔧 ${config.name}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="clickable" onclick="openConfigFile('${config.id}')">📄 ${config.fileName}</span>
|
||||
<span class="clickable" onclick="openConfigFileInVSCode('${config.id}')">📄 ${config.fileName}</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-delete" onclick="deleteConfig('${config.id}')">删除</button>
|
||||
@@ -153,16 +153,6 @@ class ConfigView extends BaseView_1.BaseView {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 配置文件编辑器 -->
|
||||
<div class="config-editor" id="configEditor" style="display: none;">
|
||||
<h3>📝 编辑配置文件</h3>
|
||||
<textarea id="configContent" placeholder="在此编辑配置文件内容..."></textarea>
|
||||
<div style="margin-top: 15px;">
|
||||
<button class="btn-primary" onclick="saveConfigFile()">💾 保存到文件系统</button>
|
||||
<button class="back-btn" onclick="closeEditor()">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
let currentConfigId = null;
|
||||
@@ -187,12 +177,11 @@ class ConfigView extends BaseView_1.BaseView {
|
||||
);
|
||||
}
|
||||
|
||||
function openConfigFile(configId) {
|
||||
currentConfigId = configId;
|
||||
document.getElementById('configEditor').style.display = 'block';
|
||||
|
||||
// 新功能:在 VSCode 中打开配置文件
|
||||
function openConfigFileInVSCode(configId) {
|
||||
console.log('📄 在 VSCode 中打开配置文件:', configId);
|
||||
vscode.postMessage({
|
||||
type: 'loadConfigFile',
|
||||
type: 'openConfigFileInVSCode',
|
||||
configId: configId
|
||||
});
|
||||
}
|
||||
@@ -261,21 +250,6 @@ class ConfigView extends BaseView_1.BaseView {
|
||||
});
|
||||
}
|
||||
|
||||
function saveConfigFile() {
|
||||
const content = document.getElementById('configContent').value;
|
||||
vscode.postMessage({
|
||||
type: 'saveConfigFile',
|
||||
configId: currentConfigId,
|
||||
content: content
|
||||
});
|
||||
closeEditor();
|
||||
}
|
||||
|
||||
function closeEditor() {
|
||||
document.getElementById('configEditor').style.display = 'none';
|
||||
currentConfigId = null;
|
||||
}
|
||||
|
||||
function goBackToContainers() {
|
||||
vscode.postMessage({ type: 'goBackToContainers' });
|
||||
}
|
||||
@@ -486,10 +460,6 @@ class ConfigView extends BaseView_1.BaseView {
|
||||
console.log('🌿 收到分支数据:', message.branches);
|
||||
renderBranchSelection(message.branches, message.repoUrl);
|
||||
}
|
||||
|
||||
if (message.type === 'configFileLoaded') {
|
||||
document.getElementById('configContent').value = message.content;
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"version":3,"file":"ConfigView.js","sourceRoot":"","sources":["../../../src/panels/views/ConfigView.ts"],"names":[],"mappings":"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"}
|
||||
{"version":3,"file":"ConfigView.js","sourceRoot":"","sources":["../../../src/panels/views/ConfigView.ts"],"names":[],"mappings":";;;AAAA,yCAAsC;AA8BtC,MAAa,UAAW,SAAQ,mBAAQ;IACpC,MAAM,CAAC,IAON;QACG,MAAM,SAAS,GAAG,IAAI,EAAE,SAAS,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,EAAE,OAAO,IAAI,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,IAAI,EAAE,QAAQ,IAAI,EAAE,CAAC;QACtC,MAAM,cAAc,GAAG,IAAI,EAAE,cAAc,CAAC;QAC5C,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,KAAK,CAAC;QAC7C,MAAM,WAAW,GAAG,IAAI,EAAE,WAAW,IAAI,EAAE,CAAC;QAC5C,MAAM,UAAU,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QAE1C,gCAAgC;QAChC,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,MAAsB,EAAE,EAAE,CAAC;;;sEAGE,MAAM,CAAC,EAAE,OAAO,MAAM,CAAC,IAAI,UAAU,MAAM,CAAC,IAAI;;;+EAGvC,MAAM,CAAC,EAAE,UAAU,MAAM,CAAC,QAAQ;;;wEAGzC,MAAM,CAAC,EAAE;;;SAGxE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,6BAA6B;QAC7B,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACrC,yBAAyB;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU;YACrD,QAAQ;YACR,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACnD,MAAM,UAAU,GAAG,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YAE9D,OAAO;;;gDAG6B,QAAQ;;;;;4EAKoB,IAAI,CAAC,EAAE,OAAO,UAAU;;;yEAG3B,IAAI,CAAC,EAAE;;;aAGnE,CAAC;QACN,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAEZ,eAAe;QACf,MAAM,YAAY,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAE1F,OAAO;;;;;;MAMT,IAAI,CAAC,SAAS,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gFAwC0D,SAAS,EAAE,IAAI,IAAI,MAAM;;;;;;;;;;;;;;;;kBAgBvF,WAAW;kBACX,YAAY;;;;;;;;;;;;;;;;;;;;gCAoBE,UAAU;;;;;kBAKxB,YAAY;;;;;cAKhB,cAAc,CAAC,CAAC,CAAC;;6CAEc,cAAc,CAAC,IAAI,KAAK,cAAc,CAAC,GAAG;qEAClB,cAAc,CAAC,EAAE;;aAEzE,CAAC,CAAC,CAAC,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA+TV,CAAC;IACL,CAAC;IAEO,oBAAoB,CAAC,QAAqB;QAC9C,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QAErC,IAAI,IAAI,GAAG,uIAAuI,CAAC;QACnJ,IAAI,IAAI,qBAAqB,GAAG,QAAQ,CAAC,MAAM,GAAG,UAAU,CAAC;QAC7D,IAAI,IAAI,oEAAoE,CAAC;QAE7E,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE;YACtB,MAAM,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,CAAC;YACvE,IAAI,IAAI,0IAA0I,CAAC;YACnJ,IAAI,IAAI,6BAA6B,GAAG,QAAQ,GAAG,IAAI,CAAC;YACxD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,4BAA4B,GAAG,MAAM,CAAC,IAAI,GAAG,mCAAmC,CAAC;YAC9H,IAAI,IAAI,cAAc,GAAG,QAAQ,GAAG,sCAAsC,CAAC;YAC3E,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC;YACrD,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAAC;QACnE,CAAC,CAAC,CAAC;QAEH,IAAI,IAAI,QAAQ,CAAC;QACjB,IAAI,IAAI,iCAAiC,CAAC;QAC1C,IAAI,IAAI,yGAAyG,CAAC;QAClH,IAAI,IAAI,wEAAwE,CAAC;QACjF,IAAI,IAAI,cAAc,CAAC;QAEvB,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ;AA1fD,gCA0fC"}
|
||||
@@ -242,22 +242,10 @@ export class ConfigPanel {
|
||||
await this.updateConfigName(data.configId, data.name);
|
||||
break;
|
||||
|
||||
case 'updateConfigFileName':
|
||||
await this.updateConfigFileName(data.configId, data.fileName);
|
||||
break;
|
||||
|
||||
case 'createConfig':
|
||||
await this.createConfig(data.name);
|
||||
break;
|
||||
|
||||
case 'saveConfigFile':
|
||||
await this.saveConfigFileToDisk(data.configId, data.content);
|
||||
break;
|
||||
|
||||
case 'loadConfigFile':
|
||||
this.loadConfigFile(data.configId);
|
||||
break;
|
||||
|
||||
case 'deleteProject':
|
||||
await this.deleteProject(data.projectId);
|
||||
break;
|
||||
@@ -309,6 +297,10 @@ export class ConfigPanel {
|
||||
case 'openGitRepoInVSCode':
|
||||
await this.openGitRepoInVSCode(data.repoId);
|
||||
break;
|
||||
|
||||
case 'openConfigFileInVSCode':
|
||||
await this.openConfigFileInVSCode(data.configId);
|
||||
break;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理 Webview 消息时出错:', error);
|
||||
@@ -448,7 +440,7 @@ export class ConfigPanel {
|
||||
// 为每个分支创建独立的子目录
|
||||
const branchName = branch || 'main';
|
||||
const branchSafeName = branchName.replace(/[^a-zA-Z0-9-_]/g, '-');
|
||||
const repoDirName = `${name}-${branchSafeName}`;
|
||||
const repoDirName = name;
|
||||
|
||||
// 路径:项目路径/飞行器名/容器名/仓库名-分支名/
|
||||
const localPath = path.join(projectPath, aircraft.name, container.name, repoDirName);
|
||||
@@ -1238,17 +1230,6 @@ private async deleteGitRepo(repoId: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// 更新文件名
|
||||
private async updateConfigFileName(configId: string, fileName: string): Promise<void> {
|
||||
const config = this.configs.find(c => c.id === configId);
|
||||
if (config) {
|
||||
config.fileName = fileName;
|
||||
vscode.window.showInformationMessage(`文件名更新: ${fileName}`);
|
||||
await this.saveCurrentProjectData();
|
||||
this.updateWebview();
|
||||
}
|
||||
}
|
||||
|
||||
// 创建新配置文件
|
||||
private async createConfig(name: string) {
|
||||
const newId = 'cfg' + (this.configs.length + 1);
|
||||
@@ -1316,103 +1297,6 @@ private async deleteGitRepo(repoId: string): Promise<void> {
|
||||
}
|
||||
}
|
||||
|
||||
// 保存配置文件到磁盘
|
||||
private async saveConfigFileToDisk(configId: string, content: string): Promise<void> {
|
||||
try {
|
||||
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 project = this.projects.find(p => p.id === aircraft.projectId);
|
||||
if (!project) {
|
||||
vscode.window.showErrorMessage('未找到项目');
|
||||
return;
|
||||
}
|
||||
|
||||
const projectPath = this.projectPaths.get(aircraft.projectId);
|
||||
if (!projectPath) {
|
||||
vscode.window.showErrorMessage('未设置项目存储路径,请先配置项目');
|
||||
return;
|
||||
}
|
||||
|
||||
// 构建文件路径:项目路径/飞行器名/容器名/文件名
|
||||
const aircraftDir = vscode.Uri.joinPath(vscode.Uri.file(projectPath), aircraft.name);
|
||||
const containerDir = vscode.Uri.joinPath(aircraftDir, container.name);
|
||||
const fileUri = vscode.Uri.joinPath(containerDir, config.fileName);
|
||||
|
||||
// 确保飞行器目录存在
|
||||
try {
|
||||
await vscode.workspace.fs.createDirectory(aircraftDir);
|
||||
} catch (error) {
|
||||
// 目录可能已存在,忽略错误
|
||||
}
|
||||
|
||||
// 确保容器目录存在
|
||||
try {
|
||||
await vscode.workspace.fs.createDirectory(containerDir);
|
||||
} catch (error) {
|
||||
// 目录可能已存在,忽略错误
|
||||
}
|
||||
|
||||
// 写入文件
|
||||
const uint8Array = new TextEncoder().encode(content);
|
||||
await vscode.workspace.fs.writeFile(fileUri, uint8Array);
|
||||
|
||||
// 更新配置内容
|
||||
config.content = content;
|
||||
|
||||
vscode.window.showInformationMessage(`配置文件已保存: ${fileUri.fsPath}`);
|
||||
|
||||
// 保存数据到JSON文件
|
||||
await this.saveCurrentProjectData();
|
||||
} catch (error) {
|
||||
vscode.window.showErrorMessage(`保存文件时出错: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
// 加载配置文件
|
||||
private loadConfigFile(configId: string) {
|
||||
if (this.isWebviewDisposed) {
|
||||
console.log('⚠️ Webview 已被销毁,跳过加载配置文件');
|
||||
return;
|
||||
}
|
||||
|
||||
const config = this.configs.find(c => c.id === configId);
|
||||
if (config) {
|
||||
try {
|
||||
this.panel.webview.postMessage({
|
||||
type: 'configFileLoaded',
|
||||
content: config.content || `# ${config.name} 的配置文件\n# 您可以在此编辑配置内容\n\n`
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('⚠️ 无法发送配置文件内容,Webview 可能已被销毁');
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
this.panel.webview.postMessage({
|
||||
type: 'configFileLoaded',
|
||||
content: `# 这是 ${configId} 的配置文件\n# 您可以在此编辑配置内容\n\napp.name = "示例应用"\napp.port = 8080\napp.debug = true`
|
||||
});
|
||||
} catch (error) {
|
||||
console.log('⚠️ 无法发送默认配置文件内容,Webview 可能已被销毁');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// === Git 分支管理 ===
|
||||
|
||||
private async fetchBranches(url: string): Promise<void> {
|
||||
@@ -1454,8 +1338,6 @@ private async deleteGitRepo(repoId: string): Promise<void> {
|
||||
if (isRemote) {
|
||||
// 远程分支:移除 refs/remotes/origin/ 前缀
|
||||
branchName = ref.ref.replace('refs/remotes/origin/', '');
|
||||
// 可以选择添加远程标识,或者不添加
|
||||
// branchName = `origin/${branchName}`; // 如果需要显示远程标识
|
||||
} else {
|
||||
// 本地分支:移除 refs/heads/ 前缀
|
||||
branchName = ref.ref.replace('refs/heads/', '');
|
||||
@@ -1615,6 +1497,7 @@ private async deleteGitRepo(repoId: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private async openGitRepoInVSCode(repoId: string): Promise<void> {
|
||||
const repo = this.gitRepos.find(r => r.id === repoId);
|
||||
if (!repo) {
|
||||
@@ -1650,4 +1533,52 @@ private async deleteGitRepo(repoId: string): Promise<void> {
|
||||
vscode.window.showErrorMessage(`打开 Git 仓库文件失败: ${error}`);
|
||||
}
|
||||
}
|
||||
|
||||
private async openConfigFileInVSCode(configId: string): Promise<void> {
|
||||
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}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -53,7 +53,7 @@ export class ConfigView extends BaseView {
|
||||
<span class="editable" onclick="editConfigName('${config.id}', '${config.name}')">🔧 ${config.name}</span>
|
||||
</td>
|
||||
<td>
|
||||
<span class="clickable" onclick="openConfigFile('${config.id}')">📄 ${config.fileName}</span>
|
||||
<span class="clickable" onclick="openConfigFileInVSCode('${config.id}')">📄 ${config.fileName}</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-delete" onclick="deleteConfig('${config.id}')">删除</button>
|
||||
@@ -191,16 +191,6 @@ export class ConfigView extends BaseView {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 配置文件编辑器 -->
|
||||
<div class="config-editor" id="configEditor" style="display: none;">
|
||||
<h3>📝 编辑配置文件</h3>
|
||||
<textarea id="configContent" placeholder="在此编辑配置文件内容..."></textarea>
|
||||
<div style="margin-top: 15px;">
|
||||
<button class="btn-primary" onclick="saveConfigFile()">💾 保存到文件系统</button>
|
||||
<button class="back-btn" onclick="closeEditor()">取消</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const vscode = acquireVsCodeApi();
|
||||
let currentConfigId = null;
|
||||
@@ -225,12 +215,11 @@ export class ConfigView extends BaseView {
|
||||
);
|
||||
}
|
||||
|
||||
function openConfigFile(configId) {
|
||||
currentConfigId = configId;
|
||||
document.getElementById('configEditor').style.display = 'block';
|
||||
|
||||
// 新功能:在 VSCode 中打开配置文件
|
||||
function openConfigFileInVSCode(configId) {
|
||||
console.log('📄 在 VSCode 中打开配置文件:', configId);
|
||||
vscode.postMessage({
|
||||
type: 'loadConfigFile',
|
||||
type: 'openConfigFileInVSCode',
|
||||
configId: configId
|
||||
});
|
||||
}
|
||||
@@ -299,21 +288,6 @@ export class ConfigView extends BaseView {
|
||||
});
|
||||
}
|
||||
|
||||
function saveConfigFile() {
|
||||
const content = document.getElementById('configContent').value;
|
||||
vscode.postMessage({
|
||||
type: 'saveConfigFile',
|
||||
configId: currentConfigId,
|
||||
content: content
|
||||
});
|
||||
closeEditor();
|
||||
}
|
||||
|
||||
function closeEditor() {
|
||||
document.getElementById('configEditor').style.display = 'none';
|
||||
currentConfigId = null;
|
||||
}
|
||||
|
||||
function goBackToContainers() {
|
||||
vscode.postMessage({ type: 'goBackToContainers' });
|
||||
}
|
||||
@@ -524,10 +498,6 @@ export class ConfigView extends BaseView {
|
||||
console.log('🌿 收到分支数据:', message.branches);
|
||||
renderBranchSelection(message.branches, message.repoUrl);
|
||||
}
|
||||
|
||||
if (message.type === 'configFileLoaded') {
|
||||
document.getElementById('configContent').value = message.content;
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化
|
||||
|
||||
@@ -1,490 +0,0 @@
|
||||
// src/panels/views/GitView.ts
|
||||
import { BaseView } from './BaseView';
|
||||
import { GitRepoData, GitFileTree } from '../types/ViewTypes';
|
||||
|
||||
// 新增分支接口
|
||||
interface GitBranch {
|
||||
name: string;
|
||||
isCurrent: boolean;
|
||||
isRemote: boolean;
|
||||
selected?: boolean;
|
||||
}
|
||||
|
||||
export class GitView extends BaseView {
|
||||
render(data?: {
|
||||
repos: GitRepoData[];
|
||||
currentRepo?: GitRepoData;
|
||||
fileTree?: GitFileTree[];
|
||||
loading?: boolean;
|
||||
branches?: GitBranch[];
|
||||
repoUrl?: string;
|
||||
}): string {
|
||||
const repos = data?.repos || [];
|
||||
const currentRepo = data?.currentRepo;
|
||||
const fileTree = data?.fileTree || [];
|
||||
const loading = data?.loading || false;
|
||||
const branches = data?.branches || [];
|
||||
const repoUrl = data?.repoUrl || '';
|
||||
|
||||
// 生成仓库列表的 HTML
|
||||
const reposHtml = repos.map(repo => `
|
||||
<tr>
|
||||
<td>
|
||||
<span class="repo-name" data-repo-id="${repo.id}">📁 ${repo.name}</span>
|
||||
<div style="font-size: 12px; color: var(--vscode-descriptionForeground); margin-top: 4px;">
|
||||
${repo.url}
|
||||
</div>
|
||||
<div style="font-size: 11px; color: var(--vscode-descriptionForeground);">
|
||||
分支: ${repo.branch} | 最后同步: ${repo.lastSync}
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="clickable" onclick="loadRepo('${repo.id}')">打开</span>
|
||||
<span class="clickable" onclick="syncRepo('${repo.id}')" style="margin-left: 10px;">同步</span>
|
||||
</td>
|
||||
<td>
|
||||
<button class="btn-delete" onclick="deleteRepo('${repo.id}')">删除</button>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
|
||||
// 生成分支选择的 HTML - 使用转义符处理嵌套
|
||||
const branchesHtml = branches.length > 0 ? this.generateBranchesHtml(branches) : '';
|
||||
|
||||
// 生成文件树的 HTML
|
||||
const fileTreeHtml = fileTree.length > 0 ? this.renderFileTree(fileTree) : '<div style="text-align: center; padding: 20px; color: var(--vscode-descriptionForeground);">选择仓库以浏览文件</div>';
|
||||
|
||||
return `<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Git 仓库管理</title>
|
||||
${this.getStyles()}
|
||||
<style>
|
||||
.git-container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
.repo-list {
|
||||
flex: 1;
|
||||
min-width: 300px;
|
||||
}
|
||||
.file-tree {
|
||||
flex: 2;
|
||||
min-width: 400px;
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 4px;
|
||||
padding: 15px;
|
||||
background: var(--vscode-panel-background);
|
||||
max-height: 600px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.tree-item {
|
||||
margin: 2px 0;
|
||||
}
|
||||
.tree-folder {
|
||||
cursor: pointer;
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
.tree-folder:hover {
|
||||
background: var(--vscode-list-hoverBackground);
|
||||
}
|
||||
.tree-file {
|
||||
padding: 2px 4px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
}
|
||||
.tree-file:hover {
|
||||
background: var(--vscode-list-hoverBackground);
|
||||
}
|
||||
.tree-children {
|
||||
margin-left: 10px;
|
||||
}
|
||||
.current-repo {
|
||||
background: var(--vscode-badge-background);
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.loading {
|
||||
text-align: center;
|
||||
padding: 20px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
.btn-sync {
|
||||
background: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.btn-sync:hover {
|
||||
background: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
.branch-selection {
|
||||
border: 1px solid var(--vscode-input-border);
|
||||
}
|
||||
.branch-item:hover {
|
||||
background: var(--vscode-list-hoverBackground);
|
||||
}
|
||||
.url-input-section {
|
||||
background: var(--vscode-panel-background);
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid var(--vscode-input-border);
|
||||
}
|
||||
.debug-panel {
|
||||
background: var(--vscode-inputValidation-infoBackground);
|
||||
padding: 10px;
|
||||
margin-bottom: 15px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--vscode-inputValidation-infoBorder);
|
||||
}
|
||||
.debug-info {
|
||||
font-size: 12px;
|
||||
color: var(--vscode-input-foreground);
|
||||
font-family: 'Courier New', monospace;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<h2>📚 Git 仓库管理</h2>
|
||||
<button class="back-btn" onclick="goBackToProjects()">← 返回项目</button>
|
||||
</div>
|
||||
|
||||
<!-- 调试信息面板 -->
|
||||
<div class="debug-panel">
|
||||
<div style="font-size: 12px; color: var(--vscode-input-foreground);">
|
||||
<strong>调试信息:</strong>
|
||||
<div id="debugInfo" class="debug-info">等待操作...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- URL 输入区域 -->
|
||||
<div class="url-input-section">
|
||||
<h3>🔗 添加 Git 仓库</h3>
|
||||
<div style="display: flex; gap: 10px; margin-top: 10px;">
|
||||
<input type="text" id="repoUrlInput"
|
||||
placeholder="请输入 Git 仓库 URL,例如: https://github.com/username/repo.git"
|
||||
value="${repoUrl}"
|
||||
style="flex: 1; padding: 8px; background: var(--vscode-input-background); color: var(--vscode-input-foreground); border: 1px solid var(--vscode-input-border); border-radius: 4px;">
|
||||
<button class="btn-new" onclick="fetchBranches()">获取分支</button>
|
||||
</div>
|
||||
<div id="branchSelectionContainer">
|
||||
${branchesHtml}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 20px;">
|
||||
${currentRepo ? `
|
||||
<div class="current-repo">
|
||||
<strong>当前仓库:</strong> ${currentRepo.name} (${currentRepo.url})
|
||||
<button class="btn-sync" onclick="syncRepo('${currentRepo.id}')">同步</button>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
|
||||
<div class="git-container">
|
||||
<div class="repo-list">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="60%">仓库</th>
|
||||
<th width="20%">操作</th>
|
||||
<th width="20%">管理</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${reposHtml}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="file-tree">
|
||||
<h3>📂 文件浏览器</h3>
|
||||
${loading ? '<div class="loading">🔄 加载中...</div>' : fileTreeHtml}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let vscode;
|
||||
let selectedBranches = new Set();
|
||||
let currentRepoUrl = '';
|
||||
|
||||
try {
|
||||
if (typeof window.vscodeInstance !== 'undefined') {
|
||||
vscode = window.vscodeInstance;
|
||||
} else if (typeof acquireVsCodeApi !== 'undefined') {
|
||||
vscode = acquireVsCodeApi();
|
||||
window.vscodeInstance = vscode;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('获取 vscode API 失败:', error);
|
||||
}
|
||||
|
||||
function updateDebugInfo(message) {
|
||||
const debugElement = document.getElementById('debugInfo');
|
||||
if (debugElement) {
|
||||
debugElement.innerHTML = message;
|
||||
console.log('🔍 调试信息:', message);
|
||||
}
|
||||
}
|
||||
|
||||
function fetchBranches() {
|
||||
const urlInput = document.getElementById('repoUrlInput');
|
||||
const repoUrl = urlInput.value.trim();
|
||||
|
||||
if (!repoUrl) {
|
||||
alert('请输入 Git 仓库 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!repoUrl.startsWith('http')) {
|
||||
alert('请输入有效的 Git 仓库 URL');
|
||||
return;
|
||||
}
|
||||
|
||||
currentRepoUrl = repoUrl;
|
||||
console.log('🌿 获取分支列表:', repoUrl);
|
||||
updateDebugInfo('🌿 正在获取分支列表...');
|
||||
|
||||
vscode.postMessage({
|
||||
type: 'fetchBranches',
|
||||
url: repoUrl
|
||||
});
|
||||
}
|
||||
|
||||
function toggleBranch(branchName) {
|
||||
const checkbox = document.getElementById('branch-' + branchName.replace(/[^a-zA-Z0-9]/g, '-'));
|
||||
if (checkbox.checked) {
|
||||
selectedBranches.add(branchName);
|
||||
} else {
|
||||
selectedBranches.delete(branchName);
|
||||
}
|
||||
console.log('选中的分支:', Array.from(selectedBranches));
|
||||
updateDebugInfo('选中的分支: ' + Array.from(selectedBranches).join(', '));
|
||||
}
|
||||
|
||||
function cloneSelectedBranches() {
|
||||
if (selectedBranches.size === 0) {
|
||||
alert('请至少选择一个分支');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('🚀 开始克隆选中的分支:', Array.from(selectedBranches));
|
||||
updateDebugInfo('🚀 开始克隆分支: ' + Array.from(selectedBranches).join(', '));
|
||||
|
||||
vscode.postMessage({
|
||||
type: 'cloneBranches',
|
||||
url: currentRepoUrl,
|
||||
branches: Array.from(selectedBranches)
|
||||
});
|
||||
|
||||
// 重置选择
|
||||
selectedBranches.clear();
|
||||
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
|
||||
checkboxes.forEach(checkbox => checkbox.checked = false);
|
||||
|
||||
// 隐藏分支选择区域
|
||||
document.getElementById('branchSelectionContainer').innerHTML = '';
|
||||
updateDebugInfo('✅ 分支克隆请求已发送');
|
||||
}
|
||||
|
||||
function cancelBranchSelection() {
|
||||
selectedBranches.clear();
|
||||
const checkboxes = document.querySelectorAll('input[type="checkbox"]');
|
||||
checkboxes.forEach(checkbox => checkbox.checked = false);
|
||||
|
||||
// 隐藏分支选择区域
|
||||
document.getElementById('branchSelectionContainer').innerHTML = '';
|
||||
|
||||
updateDebugInfo('❌ 已取消分支选择');
|
||||
|
||||
vscode.postMessage({
|
||||
type: 'cancelBranchSelection'
|
||||
});
|
||||
}
|
||||
|
||||
function loadRepo(repoId) {
|
||||
console.log('📂 加载仓库:', repoId);
|
||||
updateDebugInfo('📂 正在加载仓库...');
|
||||
vscode.postMessage({
|
||||
type: 'loadGitRepo',
|
||||
repoId: repoId
|
||||
});
|
||||
}
|
||||
|
||||
function syncRepo(repoId) {
|
||||
console.log('🔄 同步仓库:', repoId);
|
||||
updateDebugInfo('🔄 正在同步仓库...');
|
||||
vscode.postMessage({
|
||||
type: 'syncGitRepo',
|
||||
repoId: repoId
|
||||
});
|
||||
}
|
||||
|
||||
function deleteRepo(repoId) {
|
||||
if (confirm('确定删除这个 Git 仓库吗?')) {
|
||||
console.log('🗑️ 删除仓库:', repoId);
|
||||
updateDebugInfo('🗑️ 正在删除仓库...');
|
||||
vscode.postMessage({
|
||||
type: 'deleteGitRepo',
|
||||
repoId: repoId
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function importFile(filePath) {
|
||||
if (confirm('确定要将此文件导入到当前项目吗?')) {
|
||||
console.log('📥 导入文件:', filePath);
|
||||
updateDebugInfo('📥 正在导入文件...');
|
||||
vscode.postMessage({
|
||||
type: 'importGitFile',
|
||||
filePath: filePath
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function toggleFolder(folderPath) {
|
||||
const folderElement = document.getElementById('folder-' + folderPath.replace(/[^a-zA-Z0-9]/g, '-'));
|
||||
if (folderElement) {
|
||||
folderElement.style.display = folderElement.style.display === 'none' ? 'block' : 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function goBackToProjects() {
|
||||
console.log('↩️ 返回项目页面');
|
||||
updateDebugInfo('↩️ 正在返回项目页面...');
|
||||
vscode.postMessage({
|
||||
type: 'goBackToProjects'
|
||||
});
|
||||
}
|
||||
|
||||
// 动态渲染分支选择区域
|
||||
function renderBranchSelection(branches, repoUrl) {
|
||||
const container = document.getElementById('branchSelectionContainer');
|
||||
|
||||
if (branches.length === 0) {
|
||||
container.innerHTML = '<div style="text-align: center; padding: 10px; color: var(--vscode-descriptionForeground);">未找到分支</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
let branchesHtml = '<div class="branch-selection" style="margin: 15px 0; padding: 15px; background: var(--vscode-panel-background); border-radius: 4px;">';
|
||||
branchesHtml += '<h4>🌿 选择要克隆的分支 (共 ' + branches.length + ' 个)</h4>';
|
||||
branchesHtml += '<div style="max-height: 200px; overflow-y: auto; margin: 10px 0;">';
|
||||
|
||||
branches.forEach(branch => {
|
||||
branchesHtml += '<div class="branch-item" style="padding: 8px; border-bottom: 1px solid var(--vscode-panel-border); display: flex; align-items: center;">';
|
||||
branchesHtml += '<input type="checkbox" id="branch-' + branch.name.replace(/[^a-zA-Z0-9]/g, '-') + '" ';
|
||||
branchesHtml += (branch.selected ? 'checked' : '') + ' onchange="toggleBranch(\\'' + branch.name + '\\')" style="margin-right: 10px;">';
|
||||
branchesHtml += '<label for="branch-' + branch.name.replace(/[^a-zA-Z0-9]/g, '-') + '" style="flex: 1; cursor: pointer;">';
|
||||
branchesHtml += (branch.isCurrent ? '⭐ ' : '') + branch.name;
|
||||
branchesHtml += (branch.isRemote ? '(远程)' : '(本地)') + '</label></div>';
|
||||
});
|
||||
|
||||
branchesHtml += '</div>';
|
||||
branchesHtml += '<div style="margin-top: 15px;">';
|
||||
branchesHtml += '<button class="btn-new" onclick="cloneSelectedBranches()" style="margin-right: 10px;">✅ 克隆选中分支</button>';
|
||||
branchesHtml += '<button class="back-btn" onclick="cancelBranchSelection()">取消</button>';
|
||||
branchesHtml += '</div></div>';
|
||||
|
||||
container.innerHTML = branchesHtml;
|
||||
}
|
||||
|
||||
// 消息监听
|
||||
window.addEventListener('message', event => {
|
||||
const message = event.data;
|
||||
console.log('📨 前端收到后端消息:', message);
|
||||
updateDebugInfo('📨 收到后端消息: ' + message.type);
|
||||
|
||||
if (message.type === 'branchesFetched') {
|
||||
console.log('🌿 收到分支数据:', message.branches);
|
||||
updateDebugInfo('✅ 获取到 ' + message.branches.length + ' 个分支');
|
||||
renderBranchSelection(message.branches, message.repoUrl);
|
||||
}
|
||||
|
||||
if (message.type === 'gitRepoLoading') {
|
||||
updateDebugInfo(message.loading ? '🔄 后端正在加载仓库文件树...' : '✅ 后端文件树加载完成');
|
||||
}
|
||||
|
||||
if (message.type === 'testFromBackend') {
|
||||
updateDebugInfo('✅ 前后端通信正常!消息: ' + message.message);
|
||||
}
|
||||
});
|
||||
|
||||
// 初始化
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
console.log('📄 GitView 页面加载完成');
|
||||
updateDebugInfo('📄 页面加载完成 - 等待用户操作');
|
||||
|
||||
setTimeout(() => {
|
||||
document.querySelectorAll('.tree-children').forEach(el => {
|
||||
el.style.display = 'block';
|
||||
});
|
||||
}, 100);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>`;
|
||||
}
|
||||
|
||||
private generateBranchesHtml(branches: GitBranch[]): string {
|
||||
if (branches.length === 0) return '';
|
||||
|
||||
let html = '<div class="branch-selection" style="margin: 15px 0; padding: 15px; background: var(--vscode-panel-background); border-radius: 4px;">';
|
||||
html += '<h4>🌿 选择要克隆的分支 (共 ' + branches.length + ' 个)</h4>';
|
||||
html += '<div style="max-height: 200px; overflow-y: auto; margin: 10px 0;">';
|
||||
|
||||
branches.forEach(branch => {
|
||||
const branchId = 'branch-' + branch.name.replace(/[^a-zA-Z0-9]/g, '-');
|
||||
html += '<div class="branch-item" style="padding: 8px; border-bottom: 1px solid var(--vscode-panel-border); display: flex; align-items: center;">';
|
||||
html += '<input type="checkbox" id="' + branchId + '" ';
|
||||
html += (branch.selected ? 'checked' : '') + ' onchange="toggleBranch(\'' + branch.name + '\')" style="margin-right: 10px;">';
|
||||
html += '<label for="' + branchId + '" style="flex: 1; cursor: pointer;">';
|
||||
html += (branch.isCurrent ? '⭐ ' : '') + branch.name;
|
||||
html += (branch.isRemote ? '(远程)' : '(本地)') + '</label></div>';
|
||||
});
|
||||
|
||||
html += '</div>';
|
||||
html += '<div style="margin-top: 15px;">';
|
||||
html += '<button class="btn-new" onclick="cloneSelectedBranches()" style="margin-right: 10px;">✅ 克隆选中分支</button>';
|
||||
html += '<button class="back-btn" onclick="cancelBranchSelection()">取消</button>';
|
||||
html += '</div></div>';
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
private renderFileTree(nodes: GitFileTree[], level = 0): string {
|
||||
return nodes.map(node => {
|
||||
const paddingLeft = level * 20;
|
||||
if (node.type === 'folder') {
|
||||
return `
|
||||
<div class="tree-item" style="padding-left: ${paddingLeft}px;">
|
||||
<span class="tree-folder" onclick="toggleFolder('${node.path}')">
|
||||
📁 ${node.name}
|
||||
</span>
|
||||
<div id="folder-${node.path.replace(/[^a-zA-Z0-9]/g, '-')}" class="tree-children">
|
||||
${this.renderFileTree(node.children || [], level + 1)}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
return `
|
||||
<div class="tree-item" style="padding-left: ${paddingLeft}px;">
|
||||
<span class="tree-file clickable" onclick="importFile('${node.path}')">
|
||||
📄 ${node.name}
|
||||
</span>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}).join('');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user