0
0
Files
vs-p/out/panels/views/GitView.js
2025-11-24 17:53:48 +08:00

470 lines
18 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.GitView = void 0;
// src/panels/views/GitView.ts
const BaseView_1 = require("./BaseView");
class GitView extends BaseView_1.BaseView {
render(data) {
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>`;
}
generateBranchesHtml(branches) {
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;
}
renderFileTree(nodes, level = 0) {
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('');
}
}
exports.GitView = GitView;
//# sourceMappingURL=GitView.js.map