Download static/index.html from WACATW/AIsay: direct link, hf CLI and curl.
- Browser
- Download file 5.67 kB
-
https://huggingface.co/spaces/WACATW/AIsay/resolve/main/static/index.html
- Command line
-
hf download hf://spaces/WACATW/AIsay/static/index.html
-
curl -L -o index.html https://huggingface.co/spaces/WACATW/AIsay/resolve/main/static/index.html
5.67 kB
| <html lang="zh-CN"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>终端 - 虚拟电脑</title> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.css" /> | |
| <script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.js"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.js"></script> | |
| <style> | |
| * { margin: 0; padding: 0; box-sizing: border-box; } | |
| html, body { width: 100%; height: 100%; background: #1e1e1e; overflow: hidden; } | |
| #terminal-container { width: 100%; height: 100%; padding: 8px; } | |
| .xterm { height: 100%; } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="terminal-container"></div> | |
| <script> | |
| const term = new Terminal({ | |
| cursorBlink: true, | |
| cursorStyle: 'block', | |
| fontSize: 14, | |
| fontFamily: '"Cascadia Code", "Fira Code", "JetBrains Mono", "Consolas", monospace', | |
| theme: { | |
| background: '#1e1e1e', | |
| foreground: '#d4d4d4', | |
| cursor: '#ffffff', | |
| selectionBackground: '#264f78', | |
| black: '#000000', | |
| red: '#cd3131', | |
| green: '#0dbc79', | |
| yellow: '#e5e510', | |
| blue: '#2472c8', | |
| magenta: '#bc3fbc', | |
| cyan: '#11a8cd', | |
| white: '#e5e5e5', | |
| }, | |
| scrollback: 5000, | |
| convertEol: true, | |
| }); | |
| const fitAddon = new FitAddon.FitAddon(); | |
| term.loadAddon(fitAddon); | |
| term.open(document.getElementById('terminal-container')); | |
| fitAddon.fit(); | |
| window.addEventListener('resize', () => fitAddon.fit()); | |
| let ws = null; | |
| let currentLine = ''; | |
| let commandHistory = []; | |
| let historyIndex = -1; | |
| function connectWebSocket() { | |
| const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; | |
| const wsUrl = `${protocol}//${window.location.host}/terminal/ws/terminal`; | |
| ws = new WebSocket(wsUrl); | |
| ws.onopen = () => { | |
| term.writeln('\x1b[1;32m✓ 已连接到虚拟电脑终端\x1b[0m'); | |
| term.writeln('\x1b[90m输入 Shell 命令,按 Enter 执行。\x1b[0m'); | |
| term.writeln(''); | |
| showPrompt(); | |
| }; | |
| ws.onmessage = (event) => { | |
| const output = event.data; | |
| term.write(output); | |
| if (!output.endsWith('\n')) term.write('\r\n'); | |
| showPrompt(); | |
| }; | |
| ws.onclose = () => { | |
| term.writeln('\r\n\x1b[1;31m✗ 连接已断开。请刷新页面重连。\x1b[0m'); | |
| }; | |
| ws.onerror = () => { | |
| term.writeln('\r\n\x1b[1;31m✗ 连接错误\x1b[0m'); | |
| }; | |
| } | |
| function showPrompt() { | |
| term.write('\x1b[1;36m$\x1b[0m '); | |
| } | |
| term.onData((data) => { | |
| if (data === '\r') { | |
| term.write('\r\n'); | |
| if (currentLine.trim()) { | |
| commandHistory.push(currentLine); | |
| historyIndex = commandHistory.length; | |
| if (currentLine.trim() === 'clear') { | |
| term.clear(); | |
| showPrompt(); | |
| } else if (currentLine.trim() === 'exit') { | |
| term.writeln('\x1b[90m再见!\x1b[0m'); | |
| } else { | |
| if (ws && ws.readyState === WebSocket.OPEN) { | |
| ws.send(currentLine); | |
| } else { | |
| term.writeln('\x1b[1;31m✗ 未连接到后端\x1b[0m'); | |
| showPrompt(); | |
| } | |
| } | |
| } else { | |
| showPrompt(); | |
| } | |
| currentLine = ''; | |
| return; | |
| } | |
| if (data === '\x7f') { | |
| if (currentLine.length > 0) { | |
| currentLine = currentLine.slice(0, -1); | |
| term.write('\b \b'); | |
| } | |
| return; | |
| } | |
| if (data === '\x1b[A') { | |
| if (historyIndex > 0) { | |
| historyIndex--; | |
| term.write('\r\x1b[K'); | |
| showPrompt(); | |
| currentLine = commandHistory[historyIndex]; | |
| term.write(currentLine); | |
| } | |
| return; | |
| } | |
| if (data === '\x1b[B') { | |
| if (historyIndex < commandHistory.length - 1) { | |
| historyIndex++; | |
| term.write('\r\x1b[K'); | |
| showPrompt(); | |
| currentLine = commandHistory[historyIndex]; | |
| term.write(currentLine); | |
| } else { | |
| historyIndex = commandHistory.length; | |
| term.write('\r\x1b[K'); | |
| showPrompt(); | |
| currentLine = ''; | |
| } | |
| return; | |
| } | |
| if (data >= ' ' || data === '\t') { | |
| currentLine += data; | |
| term.write(data); | |
| } | |
| }); | |
| connectWebSocket(); | |
| setTimeout(() => term.focus(), 100); | |
| </script> | |
| </body> | |
| </html> |