251 lines
9.9 KiB
HTML
251 lines
9.9 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="en">
|
||
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="stylesheet" href="/css/font.css">
|
||
<link rel="stylesheet" href="/css/xadmin.css">
|
||
<link rel="stylesheet" href="/css/win10ui.css">
|
||
<link rel="stylesheet" href="/css/theme.css">
|
||
<link rel="stylesheet" href="/lib/layui/css/layui.css">
|
||
<link rel="stylesheet" href="/T4/css/task.css">
|
||
<link rel="stylesheet" href="/T4/css/hardware.css">
|
||
<link rel="stylesheet" href="/T4/css/font.css">
|
||
<link rel="stylesheet" href="/T4/css/chart.css">
|
||
<link rel="stylesheet" href="/T4/css/cmd.css">
|
||
<style>
|
||
/* Custom styles for the sidebar and full-screen image */
|
||
body {
|
||
margin: 0;
|
||
padding: 0;
|
||
overflow: hidden;
|
||
background-color: #000;
|
||
}
|
||
|
||
#sidebar {
|
||
position: fixed;
|
||
top: 40px;
|
||
left: 0;
|
||
width: 100%;
|
||
height: auto;
|
||
background: #fff;
|
||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
|
||
z-index: 999;
|
||
transform: translateY(-100%);
|
||
transition: transform 0.3s ease;
|
||
padding: 15px;
|
||
box-sizing: border-box;
|
||
user-select: none;
|
||
}
|
||
|
||
#sidebar.show {
|
||
transform: translateY(0);
|
||
}
|
||
|
||
#sidebar-toggle {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 40px;
|
||
background: #393D49;
|
||
color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
cursor: pointer;
|
||
z-index: 1000;
|
||
}
|
||
|
||
#image-container {
|
||
position: fixed;
|
||
top: 40px;
|
||
left: 0;
|
||
width: 100%;
|
||
height: calc(100vh - 40px);
|
||
background: #000;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
overflow: hidden;
|
||
}
|
||
|
||
#bytesImageView {
|
||
position: absolute;
|
||
max-width: 100%;
|
||
max-height: 100%;
|
||
object-fit: contain;
|
||
display: none;
|
||
/* 确保至少有一侧接触边缘 */
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
width: auto;
|
||
height: auto;
|
||
}
|
||
|
||
/* 强制全屏显示,至少有一侧接触边缘 */
|
||
#bytesImageView.fullscreen {
|
||
width: 100%;
|
||
height: 100%;
|
||
object-fit: cover;
|
||
}
|
||
|
||
.image-meta {
|
||
position: absolute;
|
||
top: 10px;
|
||
left: 10px;
|
||
color: white;
|
||
background-color: rgba(0, 0, 0, 0.7);
|
||
padding: 4px 8px;
|
||
border-radius: 4px;
|
||
font-size: 12px;
|
||
line-height: 1.5;
|
||
z-index: 10;
|
||
pointer-events: none;
|
||
}
|
||
</style>
|
||
<script type="text/javascript" src="/lib/layui/layui.js" charset="utf-8"></script>
|
||
<script type="text/javascript" src="/js/xadmin.js"></script>
|
||
<script src="/assets/js/socket/Socket.IO.js"></script>
|
||
<script src="/assets/js/core/echarts.min.js"></script>
|
||
</head>
|
||
|
||
<body>
|
||
<div id="sidebar-toggle">▼ 显示控制面板 ▼</div>
|
||
|
||
<div id="sidebar">
|
||
<div class="layui-form">
|
||
<div class="layui-form-item">
|
||
<label class="layui-form-label" style="width: 200px">图片压缩等级(0-20)</label>
|
||
<div class="layui-input-inline">
|
||
<input type="text" name="firstInput" placeholder="0-20" class="layui-input" value="15">
|
||
</div>
|
||
<label class="layui-form-label" style="width: 200px">单帧尾等待时间</label>
|
||
<div class="layui-input-inline">
|
||
<input type="text" name="secondInput" placeholder="秒" class="layui-input" value="1">
|
||
</div>
|
||
<div class="layui-input-inline">
|
||
<button class="layui-btn" lay-submit lay-filter="formSubmit">运行实时屏幕任务</button>
|
||
<button class="layui-btn" onclick='socket.emit("T4CMDCommand", {"PCMachineGUID": PCMachineGUID, "work": "KillRealTimeScreen"});'>终止工作进程</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div id="image-container">
|
||
<img class="layui-upload-img" id="bytesImageView">
|
||
<p id="demoText"></p>
|
||
</div>
|
||
|
||
<script>
|
||
socket = io("/Termination4SocketIOSpace");
|
||
layui.use(['layer', 'upload', 'jquery', 'form'], function() {
|
||
var layer = layui.layer;
|
||
var $ = layui.jquery;
|
||
var upload = layui.upload;
|
||
var form = layui.form;
|
||
|
||
// Toggle sidebar
|
||
$('#sidebar-toggle').click(function() {
|
||
$('#sidebar').toggleClass('show');
|
||
$(this).text(function(i, text) {
|
||
return text === '▼ 显示控制面板 ▼' ? '▲ 隐藏控制面板 ▲' : '▼ 显示控制面板 ▼';
|
||
});
|
||
});
|
||
|
||
form.on('submit(formSubmit)', function(data){
|
||
var compressionLevel = data.field.firstInput;
|
||
var waitTime = data.field.secondInput;
|
||
if(!compressionLevel || !waitTime) {
|
||
Toast.error("实时屏幕", "填写完整信息", 3000);
|
||
return false;
|
||
}
|
||
console.log('压缩等级:', compressionLevel);
|
||
console.log('等待时间:', waitTime);
|
||
socket.emit("T4CMDCommand", {"PCMachineGUID": PCMachineGUID, "work": "RealTimeScreen", "Command": {"level": compressionLevel, "sleep": waitTime}});
|
||
return false;
|
||
});
|
||
|
||
// Function to display image from bytes
|
||
window.showImageFromBytes = function(message) {
|
||
try {
|
||
// Convert binary data to Blob URL
|
||
const blob = new Blob([new Uint8Array(message.ImageBytes)], {type: `image/${message.Format || 'jpeg'}`});
|
||
const imageUrl = URL.createObjectURL(blob);
|
||
|
||
// Get image container and element
|
||
const imgContainer = document.getElementById('image-container');
|
||
const imgElement = document.getElementById('bytesImageView');
|
||
|
||
// Create/update metadata div
|
||
let metaDiv = imgContainer.querySelector('.image-meta');
|
||
if (!metaDiv) {
|
||
metaDiv = document.createElement('div');
|
||
metaDiv.className = 'image-meta';
|
||
imgContainer.appendChild(metaDiv);
|
||
}
|
||
|
||
// Update metadata content
|
||
metaDiv.innerHTML = `
|
||
<div>格式: ${message.Format.toUpperCase()}</div>
|
||
<div>压缩: ${message.CompressionLevel}</div>
|
||
<div>耗时: ${message.TimeElapsed.toFixed(2)}s</div>
|
||
<div>网络耗时: ${(Date.now() / 1000 - Number(message.CreateTime)).toFixed(4)}s</div>
|
||
<div>大小: ${formatFileSize(message.FileSize)}</div>
|
||
`;
|
||
|
||
// Set image source
|
||
imgElement.onload = function() {
|
||
// 检查图片比例与容器比例
|
||
const containerRatio = imgContainer.clientWidth / imgContainer.clientHeight;
|
||
const imageRatio = this.naturalWidth / this.naturalHeight;
|
||
|
||
// 根据比例决定如何全屏显示
|
||
if (containerRatio > imageRatio) {
|
||
// 容器更宽,图片高度填满,宽度自动
|
||
this.style.width = 'auto';
|
||
this.style.height = '100%';
|
||
} else {
|
||
// 容器更高,图片宽度填满,高度自动
|
||
this.style.width = '100%';
|
||
this.style.height = 'auto';
|
||
}
|
||
|
||
// 确保图片居中
|
||
this.style.position = 'absolute';
|
||
this.style.top = '50%';
|
||
this.style.left = '50%';
|
||
this.style.transform = 'translate(-50%, -50%)';
|
||
|
||
URL.revokeObjectURL(imageUrl);
|
||
};
|
||
imgElement.src = imageUrl;
|
||
imgElement.style.display = 'block';
|
||
|
||
return true;
|
||
} catch (e) {
|
||
console.error('显示图片失败:', e);
|
||
layer.msg('显示图片失败: ' + e.message);
|
||
return false;
|
||
}
|
||
};
|
||
|
||
// Helper function to format file size
|
||
function formatFileSize(bytes) {
|
||
if (bytes === 0) return '0 B';
|
||
const k = 1024;
|
||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
||
}
|
||
|
||
// Socket event listener
|
||
socket.on(PCMachineGUID + 'CMDRRealTimeScreen', (message) => {
|
||
showImageFromBytes(message);
|
||
});
|
||
});
|
||
</script>
|
||
</body>
|
||
</html> |