aigems commited on
Commit
8801327
·
1 Parent(s): 246bcdf
Files changed (2) hide show
  1. public/index.html +41 -16
  2. public/js/main.js +44 -8
public/index.html CHANGED
@@ -7,45 +7,70 @@
7
  <title>Web 命令执行器</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/xss.min.js"></script>
10
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
 
11
  <style>
12
  body {
13
  font-family: 'Inter', sans-serif;
14
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  </style>
16
  </head>
17
 
18
  <body
19
- class="bg-gradient-to-br from-indigo-100 via-purple-100 to-pink-100 min-h-screen flex items-center justify-center p-4">
20
  <div
21
- class="max-w-2xl w-full mx-auto bg-white p-8 rounded-2xl shadow-2xl transition-all duration-300 ease-in-out hover:shadow-3xl">
22
- <h1 class="text-4xl font-bold mb-6 text-center text-indigo-600 tracking-tight">Web 命令执行器</h1>
23
 
24
- <div id="loginForm" class="space-y-4">
25
  <input type="text" id="username" placeholder="用户名"
26
- class="p-3 border rounded-lg w-full focus:ring-2 focus:ring-indigo-300 transition-all duration-200 ease-in-out">
27
  <input type="password" id="password" placeholder="密码"
28
- class="p-3 border rounded-lg w-full focus:ring-2 focus:ring-indigo-300 transition-all duration-200 ease-in-out">
29
  <button id="loginButton"
30
- class="w-full bg-indigo-500 text-white px-4 py-3 rounded-lg hover:bg-indigo-600 transition-all duration-200 ease-in-out transform hover:scale-105">登录</button>
31
  </div>
32
 
33
- <div id="commandInterface" style="display: none;" class="space-y-6">
34
- <p class="text-gray-600 text-center">在下方输入命令并点击"执行"或按回车键来在服务器上执行命令。</p>
35
  <div class="flex">
36
  <input type="text" id="command" placeholder="输入命令"
37
- class="flex-grow p-3 border rounded-l-lg focus:outline-none focus:ring-2 focus:ring-indigo-300 transition-all duration-200 ease-in-out">
38
  <button id="executeButton"
39
- class="bg-green-500 text-white px-6 py-3 rounded-r-lg hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-300 transition-all duration-200 ease-in-out transform hover:scale-105">执行</button>
40
  </div>
41
  <div id="loadingIndicator" class="text-center" style="display: none;">
42
- <div class="inline-block animate-spin rounded-full h-8 w-8 border-t-2 border-b-2 border-indigo-500">
43
  </div>
44
  </div>
45
- <div id="output" class="bg-gray-100 p-4 rounded-lg h-64 overflow-y-auto font-mono text-sm"></div>
 
 
46
  <div>
47
- <h2 class="text-2xl font-bold mb-3 text-indigo-600">命令历史</h2>
48
- <ul id="history" class="list-disc pl-5 space-y-2 text-gray-700"></ul>
49
  </div>
50
  </div>
51
  </div>
 
7
  <title>Web 命令执行器</title>
8
  <script src="https://cdn.tailwindcss.com"></script>
9
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/xss.min.js"></script>
10
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&family=Fira+Code&display=swap"
11
+ rel="stylesheet">
12
  <style>
13
  body {
14
  font-family: 'Inter', sans-serif;
15
  }
16
+
17
+ .terminal {
18
+ font-family: 'Fira Code', monospace;
19
+ }
20
+
21
+ @keyframes glow {
22
+ 0% {
23
+ box-shadow: 0 0 5px rgba(66, 153, 225, 0.5);
24
+ }
25
+
26
+ 50% {
27
+ box-shadow: 0 0 20px rgba(66, 153, 225, 0.8);
28
+ }
29
+
30
+ 100% {
31
+ box-shadow: 0 0 5px rgba(66, 153, 225, 0.5);
32
+ }
33
+ }
34
+
35
+ .glow-effect {
36
+ animation: glow 2s infinite;
37
+ }
38
  </style>
39
  </head>
40
 
41
  <body
42
+ class="bg-gradient-to-br from-gray-900 via-blue-900 to-blue-700 min-h-screen flex items-center justify-center p-4">
43
  <div
44
+ class="max-w-4xl w-full mx-auto bg-gray-800 p-8 rounded-3xl shadow-2xl transition-all duration-300 ease-in-out hover:shadow-3xl border border-blue-500">
45
+ <h1 class="text-5xl font-bold mb-8 text-center text-blue-400 tracking-tight glow-effect">Web 命令执行器</h1>
46
 
47
+ <div id="loginForm" class="space-y-6">
48
  <input type="text" id="username" placeholder="用户名"
49
+ class="p-4 border-2 border-blue-500 rounded-lg w-full bg-gray-700 text-white focus:ring-2 focus:ring-blue-300 transition-all duration-200 ease-in-out placeholder-gray-400">
50
  <input type="password" id="password" placeholder="密码"
51
+ class="p-4 border-2 border-blue-500 rounded-lg w-full bg-gray-700 text-white focus:ring-2 focus:ring-blue-300 transition-all duration-200 ease-in-out placeholder-gray-400">
52
  <button id="loginButton"
53
+ class="w-full bg-blue-600 text-white px-6 py-4 rounded-lg hover:bg-blue-700 transition-all duration-200 ease-in-out transform hover:scale-105 focus:outline-none focus:ring-2 focus:ring-blue-400 focus:ring-opacity-50">登录</button>
54
  </div>
55
 
56
+ <div id="commandInterface" style="display: none;" class="space-y-8">
57
+ <p class="text-blue-300 text-center text-lg">在下方输入命令并点击"执行"或按回车键来在服务器上执行命令。</p>
58
  <div class="flex">
59
  <input type="text" id="command" placeholder="输入命令"
60
+ class="flex-grow p-4 border-2 border-blue-500 rounded-l-lg bg-gray-700 text-white focus:outline-none focus:ring-2 focus:ring-blue-300 transition-all duration-200 ease-in-out placeholder-gray-400 terminal">
61
  <button id="executeButton"
62
+ class="bg-green-500 text-white px-8 py-4 rounded-r-lg hover:bg-green-600 focus:outline-none focus:ring-2 focus:ring-green-300 transition-all duration-200 ease-in-out transform hover:scale-105">执行</button>
63
  </div>
64
  <div id="loadingIndicator" class="text-center" style="display: none;">
65
+ <div class="inline-block animate-spin rounded-full h-12 w-12 border-t-4 border-b-4 border-blue-500">
66
  </div>
67
  </div>
68
+ <div id="output"
69
+ class="bg-gray-900 p-6 rounded-lg h-80 overflow-y-auto terminal text-green-400 text-sm leading-relaxed">
70
+ </div>
71
  <div>
72
+ <h2 class="text-3xl font-bold mb-4 text-blue-400">命令历史</h2>
73
+ <ul id="history" class="space-y-2 text-gray-300"></ul>
74
  </div>
75
  </div>
76
  </div>
public/js/main.js CHANGED
@@ -15,7 +15,8 @@ async function executeCommand() {
15
  if (!command.trim()) return;
16
 
17
  showLoading(true);
18
- output.textContent = '正在执行命令...';
 
19
 
20
  try {
21
  let response = await fetch('/api/execute', {
@@ -48,12 +49,12 @@ async function executeCommand() {
48
  }
49
 
50
  const data = await response.json();
51
- output.innerHTML = formatOutput(data.output || data.error || '命令执行成功,但没有输出。');
52
  commandInput.value = '';
53
  loadCommandHistory();
54
  } catch (error) {
55
  console.error('执行命令时出错:', error);
56
- output.innerHTML = formatOutput('错误: ' + (error.message || '未知错误'));
57
  if (error.message.includes('Token 刷新失败')) {
58
  showNotification('访问被拒绝。请重新登录。', 'error');
59
  localStorage.removeItem('token');
@@ -66,8 +67,15 @@ async function executeCommand() {
66
  }
67
  }
68
 
69
- function formatOutput(text) {
70
- return text.replace(/\n/g, '<br>').replace(/ /g, '&nbsp;');
 
 
 
 
 
 
 
71
  }
72
 
73
  async function loadCommandHistory() {
@@ -78,13 +86,21 @@ async function loadCommandHistory() {
78
  }
79
  });
80
  const data = await response.json();
 
81
  history.innerHTML = '';
82
  data.reverse().forEach(item => {
83
  const li = document.createElement('li');
84
- li.innerHTML = `<span class="font-semibold">${filterXSS(item.command)}</span> <span class="text-sm text-gray-500">(${new Date(item.timestamp).toLocaleString()})</span>`;
85
- li.className = 'cursor-pointer hover:text-indigo-500 transition-colors duration-200';
 
 
 
 
 
86
  li.onclick = () => {
 
87
  commandInput.value = item.command;
 
88
  };
89
  history.appendChild(li);
90
  });
@@ -176,4 +192,24 @@ function checkLoginStatus() {
176
  }
177
 
178
  window.addEventListener('load', checkLoginStatus);
179
- document.getElementById('executeButton').addEventListener('click', executeCommand);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  if (!command.trim()) return;
16
 
17
  showLoading(true);
18
+ appendToOutput('$ ' + command, 'text-blue-400');
19
+ appendToOutput('正在执行命令...', 'text-yellow-400');
20
 
21
  try {
22
  let response = await fetch('/api/execute', {
 
49
  }
50
 
51
  const data = await response.json();
52
+ appendToOutput(data.output || data.error || '命令执行成功,但没有输出。', 'text-green-400');
53
  commandInput.value = '';
54
  loadCommandHistory();
55
  } catch (error) {
56
  console.error('执行命令时出错:', error);
57
+ appendToOutput('错误: ' + (error.message || '未知错误'), 'text-red-500');
58
  if (error.message.includes('Token 刷新失败')) {
59
  showNotification('访问被拒绝。请重新登录。', 'error');
60
  localStorage.removeItem('token');
 
67
  }
68
  }
69
 
70
+ function appendToOutput(text, className = 'text-green-400') {
71
+ const lines = text.split('\n');
72
+ lines.forEach((line, index) => {
73
+ const p = document.createElement('p');
74
+ p.className = className;
75
+ p.textContent = line;
76
+ output.appendChild(p);
77
+ });
78
+ output.scrollTop = output.scrollHeight;
79
  }
80
 
81
  async function loadCommandHistory() {
 
86
  }
87
  });
88
  const data = await response.json();
89
+ console.log('命令历史数据:', data); // 添加调试信息
90
  history.innerHTML = '';
91
  data.reverse().forEach(item => {
92
  const li = document.createElement('li');
93
+ li.innerHTML = `
94
+ <div class="flex justify-between items-center p-2 hover:bg-gray-700 rounded transition-colors duration-200">
95
+ <span class="font-semibold text-blue-400">${filterXSS(item.command)}</span>
96
+ <span class="text-sm text-gray-500">${new Date(item.timestamp).toLocaleString()}</span>
97
+ </div>
98
+ `;
99
+ li.className = 'cursor-pointer';
100
  li.onclick = () => {
101
+ console.log(`Clicked on command: ${item.command}`); // 添加调试信息
102
  commandInput.value = item.command;
103
+ commandInput.focus();
104
  };
105
  history.appendChild(li);
106
  });
 
192
  }
193
 
194
  window.addEventListener('load', checkLoginStatus);
195
+ document.getElementById('executeButton').addEventListener('click', executeCommand);
196
+
197
+ // 添加打字机效果
198
+ function typeWriter(element, text, speed = 50) {
199
+ let i = 0;
200
+ function type() {
201
+ if (i < text.length) {
202
+ element.textContent += text.charAt(i);
203
+ i++;
204
+ setTimeout(type, speed);
205
+ }
206
+ }
207
+ type();
208
+ }
209
+
210
+ // 在页面加载时添加一些酷炫的效果
211
+ window.addEventListener('load', () => {
212
+ const title = document.querySelector('h1');
213
+ title.textContent = '';
214
+ typeWriter(title, 'Web 命令执行器', 100);
215
+ });