qa1145's picture
download
raw
12.5 kB
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>终端界面</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
min-height: 100vh;
background: #e8e4dc;
display: flex;
justify-content: center;
align-items: center;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
overflow: hidden;
position: relative;
}
/* 背景纹理 */
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-image:
repeating-linear-gradient(
0deg,
transparent,
transparent 2px,
rgba(0,0,0,0.03) 2px,
rgba(0,0,0,0.03) 4px
);
pointer-events: none;
}
/* 背景数字纹理 */
.bg-texture {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow: hidden;
opacity: 0.08;
font-size: 12px;
line-height: 1.6;
color: #5c5c5c;
white-space: pre-wrap;
word-break: break-all;
padding: 20px;
pointer-events: none;
z-index: 0;
}
.terminal-window {
width: 900px;
height: 600px;
min-width: 400px;
min-height: 300px;
background: #1a1a1a;
border-radius: 12px;
overflow: hidden;
box-shadow:
0 20px 60px rgba(0,0,0,0.3),
0 0 0 1px rgba(255,255,255,0.1) inset;
position: fixed;
z-index: 1;
resize: both;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
.terminal-window.dragging {
transform: translate(0, 0);
transition: none;
}
.terminal-header {
background: linear-gradient(180deg, #7a6f5b 0%, #5c5346 100%);
padding: 12px 16px;
display: flex;
align-items: center;
gap: 8px;
border-bottom: 1px solid rgba(0,0,0,0.2);
cursor: move;
user-select: none;
}
.window-btn {
width: 12px;
height: 12px;
border-radius: 50%;
border: 1px solid rgba(0,0,0,0.1);
box-shadow:
inset 0 1px 0 rgba(255,255,255,0.3),
0 1px 2px rgba(0,0,0,0.2);
}
.btn-close { background: #ff5f56; }
.btn-minimize { background: #ffbd2e; }
.btn-maximize { background: #27c93f; }
.terminal-body {
padding: 20px;
background: #0d0d0d;
height: calc(100% - 44px);
display: flex;
flex-direction: column;
overflow: hidden;
}
.output-area {
flex: 1;
overflow-y: auto;
margin-bottom: 15px;
}
.log-line {
display: flex;
align-items: center;
gap: 14px;
margin-bottom: 18px;
font-size: 14px;
line-height: 1.5;
}
.timestamp {
color: #6b6b6b;
font-weight: 500;
flex-shrink: 0;
}
.prompt {
color: #4ade80;
flex-shrink: 0;
}
.log-content {
color: #4ade80;
text-shadow: 0 0 10px rgba(74, 222, 128, 0.3);
word-break: break-all;
}
.input-area {
display: flex;
align-items: center;
gap: 8px;
border-top: 1px solid #2a2a2a;
padding-top: 15px;
}
.input-prompt {
color: #4ade80;
font-size: 14px;
flex-shrink: 0;
}
.terminal-input {
flex: 1;
background: transparent;
border: none;
outline: none;
color: #4ade80;
font-family: 'Menlo', 'Monaco', 'Courier New', monospace;
font-size: 14px;
caret-color: #4ade80;
}
.terminal-input::placeholder {
color: #4a4a4a;
}
/* 滚动条样式 */
.output-area::-webkit-scrollbar {
width: 8px;
}
.output-area::-webkit-scrollbar-track {
background: #1a1a1a;
}
.output-area::-webkit-scrollbar-thumb {
background: #3a3a3a;
border-radius: 4px;
}
.output-area::-webkit-scrollbar-thumb:hover {
background: #4a4a4a;
}
</style>
</head>
<body>
<!-- 背景纹理 -->
<div class="bg-texture" id="bgTexture"></div>
<div class="terminal-window">
<div class="terminal-header">
<div class="window-btn btn-close"></div>
<div class="window-btn btn-minimize"></div>
<div class="window-btn btn-maximize"></div>
</div>
<div class="terminal-body">
<div class="output-area" id="outputArea">
<div class="log-line">
<span class="timestamp">欢迎使用终端</span>
</div>
</div>
<div class="input-area">
<span class="input-prompt">$</span>
<input type="text" class="terminal-input" id="terminalInput" placeholder="输入命令..." autocomplete="off" autofocus>
</div>
</div>
</div>
<script>
// 拖动窗口功能
const terminalWindow = document.querySelector('.terminal-window');
const terminalHeader = document.querySelector('.terminal-header');
let isDragging = false;
let startX, startY;
let currentX = 0;
let currentY = 0;
let isFirstClick = true;
function updatePosition() {
const rect = terminalWindow.getBoundingClientRect();
currentX = rect.left;
currentY = rect.top;
terminalWindow.style.left = currentX + 'px';
terminalWindow.style.top = currentY + 'px';
terminalWindow.style.transform = 'none';
}
// 初始化位置
updatePosition();
terminalHeader.addEventListener('mousedown', function(e) {
if (isFirstClick) {
updatePosition();
isFirstClick = false;
}
isDragging = true;
startX = e.clientX;
startY = e.clientY;
terminalWindow.classList.add('dragging');
});
document.addEventListener('mousemove', function(e) {
if (!isDragging) return;
const deltaX = e.clientX - startX;
const deltaY = e.clientY - startY;
currentX += deltaX;
currentY += deltaY;
terminalWindow.style.left = currentX + 'px';
terminalWindow.style.top = currentY + 'px';
terminalWindow.style.transform = 'none';
startX = e.clientX;
startY = e.clientY;
});
document.addEventListener('mouseup', function() {
if (isDragging) {
isDragging = false;
terminalWindow.classList.remove('dragging');
}
});
// 生成背景纹理
const bgTexture = document.getElementById('bgTexture');
let textureContent = '';
const chars = '01アイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワヲン';
for (let i = 0; i < 2000; i++) {
textureContent += chars[Math.floor(Math.random() * chars.length)];
if (i % 80 === 0) textureContent += '\n';
}
bgTexture.textContent = textureContent;
// 终端输入逻辑
const terminalInput = document.getElementById('terminalInput');
const outputArea = document.getElementById('outputArea');
let commandBoxVisible = false;
function getTimestamp() {
const now = new Date();
const hours = String(now.getHours()).padStart(2, '0');
const minutes = String(now.getMinutes()).padStart(2, '0');
const seconds = String(now.getSeconds()).padStart(2, '0');
return `${hours}:${minutes}:${seconds}`;
}
function addOutput(text) {
const logLine = document.createElement('div');
logLine.className = 'log-line';
logLine.innerHTML = `
<span class="timestamp">[${getTimestamp()}]</span>
<span class="log-content">${escapeHtml(text)}</span>
`;
outputArea.appendChild(logLine);
outputArea.scrollTop = outputArea.scrollHeight;
}
function showCommandBox() {
const commandBox = document.createElement('div');
commandBox.className = 'log-line';
commandBox.id = 'commandBox';
commandBox.innerHTML = `
<span class="timestamp">可用命令:</span>
<span class="log-content">/help - 显示帮助<br>/clear - 清除屏幕<br>/time - 显示当前时间</span>
`;
outputArea.appendChild(commandBox);
outputArea.scrollTop = outputArea.scrollHeight;
commandBoxVisible = true;
}
function hideCommandBox() {
const commandBox = document.getElementById('commandBox');
if (commandBox) {
commandBox.remove();
commandBoxVisible = false;
}
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
terminalInput.addEventListener('input', function() {
if (this.value === '/') {
showCommandBox();
} else if (commandBoxVisible && !this.value.startsWith('/')) {
hideCommandBox();
}
});
terminalInput.addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
const input = this.value;
if (input.trim()) {
// 添加用户输入显示
const userLine = document.createElement('div');
userLine.className = 'log-line';
userLine.innerHTML = `
<span class="prompt">$</span>
<span class="log-content">${escapeHtml(input)}</span>
`;
outputArea.appendChild(userLine);
// 处理命令
if (input === '/help') {
addOutput('可用命令: /help, /clear, /time');
} else if (input === '/clear') {
outputArea.innerHTML = '';
} else if (input === '/time') {
addOutput('当前时间: ' + new Date().toLocaleString());
} else if (input.startsWith('/')) {
addOutput('未知命令,输入 /help 查看可用命令');
} else {
// 输出用户输入的内容
addOutput(input);
}
}
this.value = '';
hideCommandBox();
outputArea.scrollTop = outputArea.scrollHeight;
}
});
// 保持输入框焦点
document.addEventListener('click', function() {
terminalInput.focus();
});
</script>
</body>
</html>

Xet Storage Details

Size:
12.5 kB
·
Xet hash:
fdf7b5c2d28e8d29c793bb2f17864e7efa022ff2a8a4b895457da706427739fd

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.