668 lines
24 KiB
JavaScript
Executable File
668 lines
24 KiB
JavaScript
Executable File
// 解析URL参数
|
|
function getQueryParams() {
|
|
const urlParams = new URLSearchParams(window.location.search);
|
|
return {
|
|
serverUUID: urlParams.get('serverUUID'),
|
|
nodeUUID: urlParams.get('nodeUUID')
|
|
};
|
|
}
|
|
|
|
// 检查是否包含必要的URL参数
|
|
function checkParams() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
if (!serverUUID || !nodeUUID) {
|
|
alert('URL中缺少必要的参数: serverUUID 和 nodeUUID');
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
// 显示加载模态框
|
|
function showLoadingModal() {
|
|
document.getElementById('loadingModal').classList.remove('hidden');
|
|
}
|
|
|
|
// 隐藏加载模态框
|
|
function hideLoadingModal() {
|
|
document.getElementById('loadingModal').classList.add('hidden');
|
|
}
|
|
|
|
// 加载实例信息
|
|
function loadInstanceInfo() {
|
|
showLoadingModal();
|
|
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
fetch(`php/api.php?action=getInstanceInfo&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`获取实例信息失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
const instanceInfo = data.data;
|
|
let html = `
|
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
|
<div class="card">
|
|
<h3 class="text-xl mb-2">基础信息</h3>
|
|
<p><strong>实例名称:</strong> ${instanceInfo.name || '未命名'}</p>
|
|
<p><strong>实例ID:</strong> ${instanceInfo.id}</p>
|
|
<p><strong>实例UUID:</strong> ${serverUUID}</p>
|
|
<p><strong>节点UUID:</strong> ${nodeUUID}</p>
|
|
<p><strong>状态:</strong> <span class="${instanceInfo.running ? 'text-green-500' : 'text-red-500'}">${instanceInfo.running ? '运行中' : '已停止'}</span></p>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<h3 class="text-xl mb-2">运行状态</h3>
|
|
${instanceInfo.running ? `
|
|
<p><strong>CPU使用率:</strong> ${instanceInfo.cpuUsage}%</p>
|
|
<p><strong>内存使用:</strong> ${(instanceInfo.memoryUsage / 1024 / 1024).toFixed(2)} MB / ${(instanceInfo.totalMemory / 1024 / 1024).toFixed(2)} MB</p>
|
|
<p><strong>运行时间:</strong> ${formatUptime(instanceInfo.uptime)}</p>
|
|
` : `
|
|
<p class="text-center py-4">实例未运行</p>
|
|
`}
|
|
</div>
|
|
</div>
|
|
|
|
<div class="mt-6">
|
|
<button id="startInstance" class="btn btn-primary mr-2 ${instanceInfo.running ? 'hidden' : ''}">启动实例</button>
|
|
<button id="stopInstance" class="btn btn-danger ml-2 ${!instanceInfo.running ? 'hidden' : ''}">停止实例</button>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById('instanceInfo').innerHTML = html;
|
|
|
|
// 绑定按钮事件
|
|
document.getElementById('startInstance')?.addEventListener('click', startInstance);
|
|
document.getElementById('stopInstance')?.addEventListener('click', stopInstance);
|
|
|
|
// 显示模态框
|
|
document.getElementById('instanceModal').classList.remove('hidden');
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('获取实例信息失败:', error);
|
|
alert('获取实例信息失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 格式化运行时间
|
|
function formatUptime(uptime) {
|
|
const hours = Math.floor(uptime / 3600);
|
|
const minutes = Math.floor((uptime % 3600) / 60);
|
|
const seconds = uptime % 60;
|
|
|
|
return `${hours}小时 ${minutes}分钟 ${seconds}秒`;
|
|
}
|
|
|
|
// 启动实例
|
|
function startInstance() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
if (!confirm('确定要启动实例吗?')) return;
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=startInstance&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`启动实例失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert('实例启动成功');
|
|
// 刷新实例信息
|
|
loadInstanceInfo();
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('启动实例失败:', error);
|
|
alert('启动实例失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 停止实例
|
|
function stopInstance() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
if (!confirm('确定要停止实例吗?')) return;
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=stopInstance&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`停止实例失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert('实例停止成功');
|
|
// 刷新实例信息
|
|
loadInstanceInfo();
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('停止实例失败:', error);
|
|
alert('停止实例失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 加载控制台
|
|
function loadConsole() {
|
|
showLoadingModal();
|
|
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
fetch(`php/api.php?action=getConsole&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`获取控制台失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
// 清空控制台输出
|
|
document.getElementById('consoleOutput').innerHTML = '';
|
|
|
|
// 显示模态框
|
|
document.getElementById('consoleModal').classList.remove('hidden');
|
|
|
|
// 绑定发送命令事件
|
|
document.getElementById('sendConsoleCommand').addEventListener('click', sendConsoleCommand);
|
|
|
|
// 监听输入框回车事件
|
|
document.getElementById('consoleInput').addEventListener('keypress', function(e) {
|
|
if (e.key === 'Enter') {
|
|
sendConsoleCommand();
|
|
}
|
|
});
|
|
|
|
// 开始轮询控制台输出
|
|
startConsolePolling();
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('获取控制台失败:', error);
|
|
alert('获取控制台失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 发送控制台命令
|
|
function sendConsoleCommand() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
const command = document.getElementById('consoleInput').value.trim();
|
|
|
|
if (!command) return;
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=sendConsoleCommand&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}&command=${encodeURIComponent(command)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`发送命令失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
// 添加命令到输出
|
|
addConsoleOutput(`> ${command}\n`);
|
|
|
|
// 清空输入框
|
|
document.getElementById('consoleInput').value = '';
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('发送命令失败:', error);
|
|
alert('发送命令失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 添加控制台输出
|
|
function addConsoleOutput(text) {
|
|
const output = document.getElementById('consoleOutput');
|
|
output.innerHTML += text;
|
|
output.scrollTop = output.scrollHeight;
|
|
}
|
|
|
|
// 开始控制台轮询
|
|
function startConsolePolling() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
// 清除之前的轮询
|
|
if (window.consolePollingInterval) {
|
|
clearInterval(window.consolePollingInterval);
|
|
}
|
|
|
|
// 开始新的轮询
|
|
window.consolePollingInterval = setInterval(() => {
|
|
fetch(`php/api.php?action=getConsoleOutput&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.status === 200) {
|
|
addConsoleOutput(data.data);
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('轮询控制台输出失败:', error);
|
|
});
|
|
}, 1000); // 每秒轮询一次
|
|
}
|
|
|
|
// 停止控制台轮询
|
|
function stopConsolePolling() {
|
|
if (window.consolePollingInterval) {
|
|
clearInterval(window.consolePollingInterval);
|
|
window.consolePollingInterval = null;
|
|
}
|
|
}
|
|
|
|
// 加载文件管理
|
|
function loadFiles() {
|
|
showLoadingModal();
|
|
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
fetch(`php/api.php?action=getFiles&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`获取文件列表失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
const files = data.data;
|
|
|
|
let html = `
|
|
<div class="flex justify-between items-center mb-4">
|
|
<h3 class="text-xl">文件管理</h3>
|
|
<div class="flex">
|
|
<button id="refreshFiles" class="btn btn-primary mr-2">
|
|
<i class="fas fa-sync-alt"></i> 刷新
|
|
</button>
|
|
<button id="uploadFile" class="btn btn-primary">
|
|
<i class="fas fa-upload"></i> 上传文件
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="table-container overflow-x-auto">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>名称</th>
|
|
<th>类型</th>
|
|
<th>大小</th>
|
|
<th>修改时间</th>
|
|
<th>操作</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="fileList">
|
|
`;
|
|
|
|
files.forEach(file => {
|
|
html += `
|
|
<tr>
|
|
<td>${file.name}</td>
|
|
<td>${file.type}</td>
|
|
<td>${formatFileSize(file.size)}</td>
|
|
<td>${new Date(file.modifiedTime).toLocaleString()}</td>
|
|
<td>
|
|
<button class="btn btn-sm btn-primary mr-1 view-file" data-path="${file.path}">
|
|
查看
|
|
</button>
|
|
<button class="btn btn-sm btn-primary mr-1 download-file" data-path="${file.path}">
|
|
下载
|
|
</button>
|
|
${file.type === 'file' ? `
|
|
<button class="btn btn-sm btn-primary mr-1 edit-file" data-path="${file.path}">
|
|
编辑
|
|
</button>
|
|
` : ''}
|
|
<button class="btn btn-sm btn-danger delete-file" data-path="${file.path}">
|
|
删除
|
|
</button>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
|
|
html += `
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById('fileContent').innerHTML = html;
|
|
|
|
// 显示模态框
|
|
document.getElementById('filesModal').classList.remove('hidden');
|
|
|
|
// 绑定事件
|
|
document.getElementById('refreshFiles').addEventListener('click', loadFiles);
|
|
document.getElementById('uploadFile').addEventListener('click', showUploadFileDialog);
|
|
|
|
// 绑定文件操作事件
|
|
document.querySelectorAll('.view-file').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
viewFile(this.dataset.path);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.download-file').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
downloadFile(this.dataset.path);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.edit-file').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
editFile(this.dataset.path);
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll('.delete-file').forEach(button => {
|
|
button.addEventListener('click', function() {
|
|
deleteFile(this.dataset.path);
|
|
});
|
|
});
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('获取文件列表失败:', error);
|
|
alert('获取文件列表失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 格式化文件大小
|
|
function formatFileSize(size) {
|
|
if (size < 1024) {
|
|
return `${size} B`;
|
|
} else if (size < 1024 * 1024) {
|
|
return `${(size / 1024).toFixed(2)} KB`;
|
|
} else if (size < 1024 * 1024 * 1024) {
|
|
return `${(size / 1024 / 1024).toFixed(2)} MB`;
|
|
} else {
|
|
return `${(size / 1024 / 1024 / 1024).toFixed(2)} GB`;
|
|
}
|
|
}
|
|
|
|
// 显示上传文件对话框
|
|
function showUploadFileDialog() {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
const input = document.createElement('input');
|
|
input.type = 'file';
|
|
input.onchange = function() {
|
|
if (this.files && this.files[0]) {
|
|
uploadFile(this.files[0], serverUUID, nodeUUID);
|
|
}
|
|
};
|
|
input.click();
|
|
}
|
|
|
|
// 上传文件
|
|
function uploadFile(file, serverUUID, nodeUUID) {
|
|
const formData = new FormData();
|
|
formData.append('file', file);
|
|
formData.append('serverUUID', serverUUID);
|
|
formData.append('nodeUUID', nodeUUID);
|
|
formData.append('path', '/'); // 默认上传到根目录
|
|
|
|
showLoadingModal();
|
|
|
|
fetch('php/api.php?action=uploadFile', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`上传文件失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert('文件上传成功');
|
|
loadFiles(); // 刷新文件列表
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('上传文件失败:', error);
|
|
alert('上传文件失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 查看文件
|
|
function viewFile(path) {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=viewFile&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}&path=${encodeURIComponent(path)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`查看文件失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert(`文件内容:\n${data.data}`);
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('查看文件失败:', error);
|
|
alert('查看文件失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 下载文件
|
|
function downloadFile(path) {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
window.location.href = `php/api.php?action=downloadFile&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}&path=${encodeURIComponent(path)}`;
|
|
}
|
|
|
|
// 编辑文件
|
|
function editFile(path) {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=viewFile&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}&path=${encodeURIComponent(path)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`编辑文件失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
// 显示编辑模态框
|
|
const modalHtml = `
|
|
<div id="editFileModal" class="fixed top-0 left-0 w-full h-full bg-gray-900 bg-opacity-50 flex items-center justify-center">
|
|
<div class="bg-white p-6 rounded-lg w-11/12 max-w-3xl overflow-y-auto max-h-screen">
|
|
<h3 class="text-xl mb-4 text-center">编辑文件: ${path.split('/').pop()}</h3>
|
|
<textarea id="editFileContent" class="w-full h-96 p-2 border border-gray-300">${data.data}</textarea>
|
|
<div class="text-center mt-4">
|
|
<button id="saveEditFile" class="bg-blue-500 text-white px-4 py-1 rounded hover:bg-blue-600 mr-2">保存</button>
|
|
<button id="cancelEditFile" class="bg-gray-500 text-white px-4 py-1 rounded hover:bg-gray-600">取消</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
|
|
document.body.insertAdjacentHTML('beforeend', modalHtml);
|
|
|
|
// 绑定保存按钮事件
|
|
document.getElementById('saveEditFile').addEventListener('click', function() {
|
|
const content = document.getElementById('editFileContent').value;
|
|
saveEditFile(path, content);
|
|
});
|
|
|
|
// 绑定取消按钮事件
|
|
document.getElementById('cancelEditFile').addEventListener('click', function() {
|
|
document.getElementById('editFileModal').remove();
|
|
});
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('编辑文件失败:', error);
|
|
alert('编辑文件失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 保存编辑的文件
|
|
function saveEditFile(path, content) {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
const formData = new FormData();
|
|
formData.append('content', content);
|
|
formData.append('serverUUID', serverUUID);
|
|
formData.append('nodeUUID', nodeUUID);
|
|
formData.append('path', path);
|
|
|
|
showLoadingModal();
|
|
|
|
fetch('php/api.php?action=saveEditFile', {
|
|
method: 'POST',
|
|
body: formData
|
|
})
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`保存文件失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert('文件保存成功');
|
|
document.getElementById('editFileModal').remove();
|
|
loadFiles(); // 刷新文件列表
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('保存文件失败:', error);
|
|
alert('保存文件失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 删除文件
|
|
function deleteFile(path) {
|
|
const { serverUUID, nodeUUID } = getQueryParams();
|
|
|
|
if (!confirm('确定要删除此文件/文件夹吗?此操作不可撤销')) return;
|
|
|
|
showLoadingModal();
|
|
|
|
fetch(`php/api.php?action=deleteFile&serverUUID=${serverUUID}&nodeUUID=${nodeUUID}&path=${encodeURIComponent(path)}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
hideLoadingModal();
|
|
|
|
if (data.status !== 200) {
|
|
alert(`删除文件失败: ${data.message || '未知错误'}`);
|
|
return;
|
|
}
|
|
|
|
alert('文件删除成功');
|
|
loadFiles(); // 刷新文件列表
|
|
})
|
|
.catch(error => {
|
|
hideLoadingModal();
|
|
console.error('删除文件失败:', error);
|
|
alert('删除文件失败,请检查网络连接或参数是否正确');
|
|
});
|
|
}
|
|
|
|
// 初始化页面
|
|
function initPage() {
|
|
// 检查URL参数
|
|
if (!checkParams()) return;
|
|
|
|
// 绑定菜单点击事件
|
|
document.getElementById('dashboardLink').addEventListener('click', function() {
|
|
document.getElementById('contentArea').innerHTML = `
|
|
<h2 class="text-2xl mb-4">仪表盘</h2>
|
|
<p class="text-gray-600">
|
|
这里将显示实例的概览信息。
|
|
</p>
|
|
<button id="viewInstanceInfo" class="btn btn-primary mt-4">查看实例信息</button>
|
|
`;
|
|
|
|
// 绑定按钮事件
|
|
document.getElementById('viewInstanceInfo').addEventListener('click', loadInstanceInfo);
|
|
});
|
|
|
|
document.getElementById('instancesLink').addEventListener('click', function() {
|
|
document.getElementById('contentArea').innerHTML = `
|
|
<h2 class="text-2xl mb-4">实例信息</h2>
|
|
<button id="refreshInstanceInfo" class="btn btn-primary mb-4">刷新信息</button>
|
|
<div id="instanceInfoContainer"></div>
|
|
`;
|
|
|
|
// 加载实例信息
|
|
loadInstanceInfo();
|
|
|
|
// 绑定刷新按钮事件
|
|
document.getElementById('refreshInstanceInfo').addEventListener('click', loadInstanceInfo);
|
|
});
|
|
|
|
document.getElementById('filesLink').addEventListener('click', function() {
|
|
document.getElementById('contentArea').innerHTML = `
|
|
<h2 class="text-2xl mb-4">文件管理</h2>
|
|
<button id="openFilesModal" class="btn btn-primary">打开文件管理</button>
|
|
`;
|
|
|
|
// 绑定按钮事件
|
|
document.getElementById('openFilesModal').addEventListener('click', loadFiles);
|
|
});
|
|
|
|
document.getElementById('consoleLink').addEventListener('click', function() {
|
|
document.getElementById('contentArea').innerHTML = `
|
|
<h2 class="text-2xl mb-4">控制台</h2>
|
|
<button id="openConsoleModal" class="btn btn-primary">打开控制台</button>
|
|
`;
|
|
|
|
// 绑定按钮事件
|
|
document.getElementById('openConsoleModal').addEventListener('click', loadConsole);
|
|
});
|
|
|
|
// 绑定模态框关闭事件
|
|
document.getElementById('closeInstanceModal')?.addEventListener('click', function() {
|
|
document.getElementById('instanceModal').classList.add('hidden');
|
|
});
|
|
|
|
document.getElementById('closeConsoleModal')?.addEventListener('click', function() {
|
|
document.getElementById('consoleModal').classList.add('hidden');
|
|
stopConsolePolling(); // 停止轮询
|
|
});
|
|
|
|
document.getElementById('closeFilesModal')?.addEventListener('click', function() {
|
|
document.getElementById('filesModal').classList.add('hidden');
|
|
});
|
|
}
|
|
|
|
// 页面加载完成后初始化
|
|
document.addEventListener('DOMContentLoaded', initPage); |