148 lines
6.4 KiB
HTML
148 lines
6.4 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>Cloud IDE</title>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/editor/editor.main.css">
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.5.1/socket.io.min.js"></script>
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.15.0/dist/xterm.css">
|
|
|
|
|
|
<link rel="stylesheet" href="/vsc-like/static/css/index.css">
|
|
</head>
|
|
<body>
|
|
<div id="container">
|
|
<div id="fileTree" onclick="selectEmpty(this)">
|
|
<div id="topbar">
|
|
<button id="newFileBtn"><i class="fas fa-file"></i></button>
|
|
<button id="newFolderBtn"><i class="fas fa-folder"></i></button>
|
|
<button id="toggleSearchBtn"><i class="fas fa-search"></i></button>
|
|
<button id="refreshBtn"><i class="fas fa-sync-alt"></i></button>
|
|
<button id="saveBtn"><i class="fas fa-save"></i></button>
|
|
<button id="openTerminalBtn"><i class="fas fa-terminal"></i></button>
|
|
</div>
|
|
<div id="fileTreeContent"></div>
|
|
<div id="searchSidebar">
|
|
<h3>Global Search</h3>
|
|
<input type="text" id="searchInput" placeholder="Search..." oninput="searchFiles()">
|
|
<ul id="searchResults"></ul>
|
|
</div>
|
|
</div>
|
|
<!-- 右键菜单 -->
|
|
<div id="contextMenu" class="context-menu" style="display: none;">
|
|
<ul>
|
|
<li id="renameOption">Rename</li>
|
|
<li id="copyOption">Copy</li>
|
|
<li id="pasteOption">Paste</li>
|
|
<li id="deleteOption">Delete</li>
|
|
</ul>
|
|
</div>
|
|
|
|
<div id="contentArea">
|
|
<!-- 编辑器部分 -->
|
|
<div id="editorContainer">
|
|
<h3>Editor</h3>
|
|
<textarea style="width: 100%; height: 100%;"></textarea>
|
|
</div>
|
|
|
|
<!-- 终端部分 -->
|
|
<div id="terminal">
|
|
<h3>Terminal</h3>
|
|
<div id="terminalContent"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs/loader.js"></script>
|
|
<script src="/vsc-like/static/js/file.js"></script>
|
|
<script src="/vsc-like/static/js/terminal.js"></script>
|
|
<script>
|
|
require.config({ paths: { vs: 'https://cdnjs.cloudflare.com/ajax/libs/monaco-editor/0.34.0/min/vs' } });
|
|
|
|
require(['vs/editor/editor.main'], function() {
|
|
editor = monaco.editor.create(document.getElementById('editorContainer'), {
|
|
value: '',
|
|
language: 'javascript'
|
|
});
|
|
|
|
const fileTreeDiv = document.getElementById('fileTreeContent');
|
|
const searchSidebar = document.getElementById('searchSidebar');
|
|
const searchInput = document.getElementById('searchInput');
|
|
const searchResults = document.getElementById('searchResults');
|
|
const saveBtn = document.getElementById('saveBtn');
|
|
const openTerminalBtn = document.getElementById('openTerminalBtn');
|
|
|
|
|
|
// 切换全局搜索侧栏
|
|
function toggleSearchSidebar(event) {
|
|
event.stopPropagation();
|
|
searchSidebar.style.display = (searchSidebar.style.display === 'none' || searchSidebar.style.display === '') ? 'block' : 'none';
|
|
if (searchSidebar.style.display === 'block') {
|
|
fileTreeDiv.style.display = 'none';
|
|
}
|
|
else{
|
|
fileTreeDiv.style.display = 'block';
|
|
}
|
|
}
|
|
|
|
// 刷新文件树
|
|
function refreshFileTree(event) {
|
|
event.stopPropagation();
|
|
loadFileTree();
|
|
}
|
|
|
|
// 搜索文件
|
|
function searchFiles() {
|
|
const query = searchInput.value;
|
|
fetch(`/vsc-like/search-files?query=${query}`)
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
searchResults.innerHTML = '';
|
|
data.forEach(result => {
|
|
const li = document.createElement('li');
|
|
li.textContent = result.name;
|
|
li.onclick = () => loadFileContent(result);
|
|
searchResults.appendChild(li);
|
|
});
|
|
});
|
|
}
|
|
let socket = null;
|
|
function openTerminal(event) {
|
|
event.stopPropagation();
|
|
const terminalDiv = document.getElementById('terminal');
|
|
terminalDiv.style.display = (terminalDiv.style.display === 'none' || terminalDiv.style.display === '') ? 'block' : 'none';
|
|
if (socket == null) {
|
|
socket = io.connect('http://' + document.domain + ':5200/vsc-like/terminal');
|
|
}
|
|
socket.on('connected', function(data) {
|
|
console.log('Terminal connected');
|
|
});
|
|
socket.on('terminal_output', function(data) {
|
|
const terminalDiv = document.getElementById('terminal');
|
|
terminalDiv.textContent += data.data;
|
|
});
|
|
|
|
function sendTerminalInput(input) {
|
|
socket.emit('send_input', { input: input });
|
|
}
|
|
}
|
|
|
|
// 按钮绑定事件
|
|
document.getElementById('newFileBtn').addEventListener('click', (event) => createNewFile(event));
|
|
document.getElementById('newFolderBtn').addEventListener('click', (event) => createNewFolder(event));
|
|
document.getElementById('toggleSearchBtn').addEventListener('click', (event) => toggleSearchSidebar(event));
|
|
document.getElementById('refreshBtn').addEventListener('click', (event) => refreshFileTree(event));
|
|
document.getElementById('saveBtn').addEventListener('click', (event) => saveFile(event));
|
|
document.getElementById('openTerminalBtn').addEventListener('click', (event) => openTerminal(event));
|
|
|
|
loadFileTree();
|
|
});
|
|
|
|
</script>
|
|
</body>
|
|
</html>
|