Spaces:
Sleeping
Sleeping
Upload 5 files
Browse files
app.py
CHANGED
|
@@ -104,8 +104,12 @@ HTML_CONTENT = '''<!DOCTYPE html>
|
|
| 104 |
.client-status { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.8em; margin-top: 8px; }
|
| 105 |
.status-online { background: #00d9ff22; color: #00d9ff; }
|
| 106 |
.status-offline { background: #ff6b6b22; color: #ff6b6b; }
|
| 107 |
-
.panel { background: #16213e; border-radius: 10px; padding: 20px; border: 1px solid #0f3460; display: none; }
|
| 108 |
-
.panel.active { display:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 109 |
.tabs { display: flex; gap: 10px; margin-bottom: 20px; border-bottom: 1px solid #0f3460; padding-bottom: 10px; flex-wrap: wrap; }
|
| 110 |
.tab { padding: 8px 16px; border-radius: 5px; cursor: pointer; background: transparent; border: none; color: #888; transition: all 0.3s; }
|
| 111 |
.tab:hover { color: #00d9ff; }
|
|
@@ -164,7 +168,7 @@ HTML_CONTENT = '''<!DOCTYPE html>
|
|
| 164 |
</label>
|
| 165 |
</div>
|
| 166 |
</div>
|
| 167 |
-
<div class="screenshot-view" id="screenshotView" style="
|
| 168 |
</div>
|
| 169 |
<div class="tab-content" id="tab-control" style="display:none;">
|
| 170 |
<p style="color:#888;margin-bottom:15px;">远程控制</p>
|
|
@@ -279,40 +283,27 @@ HTML_CONTENT = '''<!DOCTYPE html>
|
|
| 279 |
}
|
| 280 |
|
| 281 |
let screenshotImgElement = null;
|
| 282 |
-
let originalWidth = 0;
|
| 283 |
-
let originalHeight = 0;
|
| 284 |
|
| 285 |
async function loadScreenshot() {
|
| 286 |
if (!selectedClient) return;
|
| 287 |
const t = Date.now();
|
| 288 |
const container = document.getElementById('screenshotView');
|
| 289 |
|
| 290 |
-
|
| 291 |
-
if (screenshotImgElement && originalWidth > 0) {
|
| 292 |
screenshotImgElement.src = `/api/screenshots/${selectedClient.id}?t=${t}`;
|
| 293 |
} else {
|
| 294 |
-
container.innerHTML = `<img id="screenshotImg" style="cursor:crosshair;">`;
|
| 295 |
screenshotImgElement = document.getElementById('screenshotImg');
|
| 296 |
screenshotImgElement.src = `/api/screenshots/${selectedClient.id}?t=${t}`;
|
| 297 |
|
| 298 |
-
screenshotImgElement.onload = function() {
|
| 299 |
-
// 记录原始尺寸,后续使用固定尺寸
|
| 300 |
-
originalWidth = this.naturalWidth;
|
| 301 |
-
originalHeight = this.naturalHeight;
|
| 302 |
-
this.style.width = originalWidth + 'px';
|
| 303 |
-
this.style.height = originalHeight + 'px';
|
| 304 |
-
};
|
| 305 |
-
|
| 306 |
screenshotImgElement.onclick = function(e) {
|
| 307 |
const rect = this.getBoundingClientRect();
|
| 308 |
const x = Math.round((e.clientX - rect.left) * (this.naturalWidth / rect.width));
|
| 309 |
const y = Math.round((e.clientY - rect.top) * (this.naturalHeight / rect.height));
|
| 310 |
|
| 311 |
-
// 获取选中的点击类型
|
| 312 |
const clickButton = document.querySelector('input[name="clickButton"]:checked').value;
|
| 313 |
sendMouseClickAt(x, y, clickButton);
|
| 314 |
|
| 315 |
-
// 点击后自动刷新
|
| 316 |
if (document.getElementById('clickAutoRefresh').checked) {
|
| 317 |
setTimeout(loadScreenshot, 500);
|
| 318 |
}
|
|
@@ -386,7 +377,7 @@ HTML_CONTENT = '''<!DOCTYPE html>
|
|
| 386 |
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
| 387 |
document.querySelectorAll('.tab-content').forEach(c => c.style.display = 'none');
|
| 388 |
tab.classList.add('active');
|
| 389 |
-
document.getElementById('tab-' + tab.dataset.tab).style.display = '
|
| 390 |
};
|
| 391 |
});
|
| 392 |
|
|
|
|
| 104 |
.client-status { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 0.8em; margin-top: 8px; }
|
| 105 |
.status-online { background: #00d9ff22; color: #00d9ff; }
|
| 106 |
.status-offline { background: #ff6b6b22; color: #ff6b6b; }
|
| 107 |
+
.panel { background: #16213e; border-radius: 10px; padding: 20px; border: 1px solid #0f3460; display: none; flex-direction: column; flex: 1; min-height: 600px; }
|
| 108 |
+
.panel.active { display: flex; }
|
| 109 |
+
.tab-content { display: none; flex-direction: column; flex: 1; min-height: 0; }
|
| 110 |
+
.tab-content.active { display: flex; flex: 1; }
|
| 111 |
+
.screenshot-view { flex: 1; display: flex; align-items: center; justify-content: center; background: #000; overflow: hidden; }
|
| 112 |
+
.screenshot-view img { max-width: 100%; max-height: 100%; object-fit: contain; }
|
| 113 |
.tabs { display: flex; gap: 10px; margin-bottom: 20px; border-bottom: 1px solid #0f3460; padding-bottom: 10px; flex-wrap: wrap; }
|
| 114 |
.tab { padding: 8px 16px; border-radius: 5px; cursor: pointer; background: transparent; border: none; color: #888; transition: all 0.3s; }
|
| 115 |
.tab:hover { color: #00d9ff; }
|
|
|
|
| 168 |
</label>
|
| 169 |
</div>
|
| 170 |
</div>
|
| 171 |
+
<div class="screenshot-view" id="screenshotView" style="flex:1;background:#000;display:flex;align-items:center;justify-content:center;overflow:hidden;"></div>
|
| 172 |
</div>
|
| 173 |
<div class="tab-content" id="tab-control" style="display:none;">
|
| 174 |
<p style="color:#888;margin-bottom:15px;">远程控制</p>
|
|
|
|
| 283 |
}
|
| 284 |
|
| 285 |
let screenshotImgElement = null;
|
|
|
|
|
|
|
| 286 |
|
| 287 |
async function loadScreenshot() {
|
| 288 |
if (!selectedClient) return;
|
| 289 |
const t = Date.now();
|
| 290 |
const container = document.getElementById('screenshotView');
|
| 291 |
|
| 292 |
+
if (screenshotImgElement) {
|
|
|
|
| 293 |
screenshotImgElement.src = `/api/screenshots/${selectedClient.id}?t=${t}`;
|
| 294 |
} else {
|
| 295 |
+
container.innerHTML = `<img id="screenshotImg" style="max-width:100%;max-height:100%;object-fit:contain;cursor:crosshair;">`;
|
| 296 |
screenshotImgElement = document.getElementById('screenshotImg');
|
| 297 |
screenshotImgElement.src = `/api/screenshots/${selectedClient.id}?t=${t}`;
|
| 298 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 299 |
screenshotImgElement.onclick = function(e) {
|
| 300 |
const rect = this.getBoundingClientRect();
|
| 301 |
const x = Math.round((e.clientX - rect.left) * (this.naturalWidth / rect.width));
|
| 302 |
const y = Math.round((e.clientY - rect.top) * (this.naturalHeight / rect.height));
|
| 303 |
|
|
|
|
| 304 |
const clickButton = document.querySelector('input[name="clickButton"]:checked').value;
|
| 305 |
sendMouseClickAt(x, y, clickButton);
|
| 306 |
|
|
|
|
| 307 |
if (document.getElementById('clickAutoRefresh').checked) {
|
| 308 |
setTimeout(loadScreenshot, 500);
|
| 309 |
}
|
|
|
|
| 377 |
document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
|
| 378 |
document.querySelectorAll('.tab-content').forEach(c => c.style.display = 'none');
|
| 379 |
tab.classList.add('active');
|
| 380 |
+
document.getElementById('tab-' + tab.dataset.tab).style.display = 'flex';
|
| 381 |
};
|
| 382 |
});
|
| 383 |
|