| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250 |
- <!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>
- body {
- font-family: Arial, sans-serif;
- margin: 20px;
- background-color: #f5f5f5;
- }
- .container {
- max-width: 1400px;
- margin: 0 auto;
- background-color: white;
- padding: 20px;
- border-radius: 8px;
- box-shadow: 0 2px 4px rgba(0,0,0,0.1);
- }
- .header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 20px;
- padding-bottom: 20px;
- border-bottom: 2px solid #007bff;
- }
- .status {
- display: inline-block;
- padding: 5px 15px;
- border-radius: 4px;
- font-weight: bold;
- }
- .status.connected {
- background-color: #28a745;
- color: white;
- }
- .status.disconnected {
- background-color: #dc3545;
- color: white;
- }
- .equipment-grid {
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
- gap: 15px;
- }
- .equipment-card {
- background-color: #f9f9f9;
- border: 2px solid #ddd;
- border-radius: 8px;
- padding: 15px;
- transition: all 0.3s ease;
- }
- .equipment-card.changed {
- background-color: #fff3cd;
- border-color: #ffc107;
- transform: scale(1.05);
- }
- .equipment-name {
- font-size: 14px;
- color: #666;
- margin-bottom: 10px;
- }
- .equipment-value {
- font-size: 24px;
- font-weight: bold;
- color: #007bff;
- margin-bottom: 5px;
- }
- .equipment-id {
- font-size: 12px;
- color: #999;
- }
- .info-bar {
- display: flex;
- gap: 30px;
- margin-bottom: 20px;
- padding: 10px;
- background-color: #e9ecef;
- border-radius: 4px;
- }
- .info-item {
- display: flex;
- flex-direction: column;
- }
- .info-label {
- font-size: 12px;
- color: #666;
- }
- .info-value {
- font-size: 18px;
- font-weight: bold;
- color: #007bff;
- }
- </style>
- </head>
- <body>
- <div class="container">
- <div class="header">
- <h1>实时设备监控系统</h1>
- <div id="status" class="status disconnected">未连接</div>
- </div>
- <div class="info-bar">
- <div class="info-item">
- <span class="info-label">设备数量</span>
- <span class="info-value" id="equipmentCount">0</span>
- </div>
- <div class="info-item">
- <span class="info-label">线路号</span>
- <span class="info-value" id="lineID">0</span>
- </div>
- <div class="info-item">
- <span class="info-label">最后更新</span>
- <span class="info-value" id="lastUpdate">-</span>
- </div>
- </div>
- <div id="equipmentGrid" class="equipment-grid"></div>
- </div>
- <script>
- let ws = null;
- let equipmentData = {};
- function connect() {
- const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
- const host = window.location.host;
- const url = `${protocol}//${host}/ws/equipment`;
- console.log('正在连接到WebSocket:', url);
- ws = new WebSocket(url);
- ws.onopen = function(event) {
- console.log('WebSocket连接成功');
- updateStatus(true);
- };
- ws.onmessage = function(event) {
- try {
- const message = JSON.parse(event.data);
- if (message.event === 'connected') {
- console.log('已连接,客户端ID:', message.data.clientID);
- document.getElementById('lineID').textContent = message.data.lineID || 0;
- } else if (Array.isArray(message)) {
- // 直接处理设备数组
- console.log('收到设备数据,数量:', message.length);
- updateEquipmentList(message);
- document.getElementById('equipmentCount').textContent = message.length;
- document.getElementById('lastUpdate').textContent = new Date().toLocaleTimeString();
- }
- } catch (e) {
- console.error('解析消息失败:', e);
- }
- };
- ws.onerror = function(error) {
- console.error('WebSocket错误:', error);
- };
- ws.onclose = function(event) {
- console.log('WebSocket连接已关闭');
- updateStatus(false);
- // 自动重连
- setTimeout(connect, 3000);
- };
- }
- function updateStatus(connected) {
- const statusDiv = document.getElementById('status');
- if (connected) {
- statusDiv.className = 'status connected';
- statusDiv.textContent = '已连接';
- } else {
- statusDiv.className = 'status disconnected';
- statusDiv.textContent = '未连接';
- }
- }
- function updateEquipmentList(equipments) {
- const container = document.getElementById('equipmentGrid');
- // 标记现有设备
- const existingElements = {};
- container.querySelectorAll('.equipment-card').forEach(element => {
- existingElements[element.dataset.id] = element;
- });
- // 更新或添加设备
- equipments.forEach(equip => {
- let element = existingElements[equip.id];
- const oldValue = equipmentData[equip.id];
- // 检查值是否变化
- const valueChanged = oldValue !== undefined && oldValue !== equip.value;
- if (element) {
- // 更新现有设备
- const valueElement = element.querySelector('.equipment-value');
- valueElement.textContent = equip.value;
- if (valueChanged) {
- element.classList.add('changed');
- setTimeout(() => {
- element.classList.remove('changed');
- }, 1000);
- }
- // 移除已处理标记
- delete existingElements[equip.id];
- } else {
- // 添加新设备
- element = document.createElement('div');
- element.className = 'equipment-card changed';
- element.dataset.id = equip.id;
- element.innerHTML = `
- <div class="equipment-name">${equip.dataName}</div>
- <div class="equipment-value">${equip.value}</div>
- <div class="equipment-id">ID: ${equip.dataId}</div>
- `;
- container.appendChild(element);
- setTimeout(() => {
- element.classList.remove('changed');
- }, 1000);
- }
- // 更新数据缓存
- equipmentData[equip.id] = equip.value;
- });
- // 移除不存在的设备
- Object.values(existingElements).forEach(element => {
- element.remove();
- const id = element.dataset.id;
- delete equipmentData[id];
- });
- }
- // 页面加载时自动连接
- window.onload = function() {
- connect();
- };
- </script>
- </body>
- </html>
|