airport-qingdao-vue3/src/utils/test_websocket.html

389 lines
14 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>WebSocket 测试客户端 - STOMP + SockJS</title>
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background: white;
padding: 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h2 {
color: #333;
border-bottom: 2px solid #007bff;
padding-bottom: 10px;
}
#messages {
width: 100%;
height: 600px;
overflow-y: auto;
border: 1px solid #ddd;
margin: 20px 0;
padding: 15px;
font-family: 'Courier New', monospace;
font-size: 12px;
background-color: #1e1e1e;
color: #fff;
border-radius: 4px;
}
.controls {
margin: 20px 0;
text-align: center;
}
button {
padding: 10px 20px;
margin: 0 10px;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.connect-btn {
background-color: #28a745;
color: white;
}
.disconnect-btn {
background-color: #dc3545;
color: white;
}
.clear-btn {
background-color: #6c757d;
color: white;
}
button:hover {
opacity: 0.8;
}
button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.status {
padding: 10px;
margin: 10px 0;
border-radius: 4px;
text-align: center;
font-weight: bold;
}
.status.connected {
background-color: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.disconnected {
background-color: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.message-stats {
display: flex;
justify-content: space-around;
margin: 20px 0;
padding: 15px;
background-color: #f8f9fa;
border-radius: 4px;
}
.stat-item {
text-align: center;
}
.stat-number {
font-size: 24px;
font-weight: bold;
color: #007bff;
}
.stat-label {
font-size: 12px;
color: #6c757d;
}
/* 消息类型样式 */
.error { color: #ff6b6b; }
.success { color: #51cf66; }
.info { color: #74c0fc; }
.position { color: #ffd43b; }
.warning { color: #ff8c42; }
.command { color: #da77f2; }
.traffic-light { color: #69db7c; }
.collision { color: #ff6b6b; font-weight: bold; }
.system { color: #91a7ff; }
</style>
<!-- 引入SockJS和STOMP客户端库 -->
<script src="https://cdn.jsdelivr.net/npm/sockjs-client@1.6.1/dist/sockjs.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@stomp/stompjs@7.0.0/bundles/stomp.umd.min.js"></script>
</head>
<body>
<div class="container">
<h2>WebSocket 实时消息测试客户端</h2>
<p><strong>连接地址:</strong> http://10.0.0.124:8082/ws</p>
<p><strong>订阅主题:</strong> /topic/realtime</p>
<div id="status" class="status disconnected">未连接</div>
<div class="controls">
<button id="connectBtn" class="connect-btn" onclick="connect()">连接</button>
<button id="disconnectBtn" class="disconnect-btn" onclick="disconnect()" disabled>断开</button>
<button class="clear-btn" onclick="clearMessages()">清空日志</button>
</div>
<div class="message-stats">
<div class="stat-item">
<div id="totalMessages" class="stat-number">0</div>
<div class="stat-label">总消息数</div>
</div>
<div class="stat-item">
<div id="positionMessages" class="stat-number">0</div>
<div class="stat-label">位置更新</div>
</div>
<div class="stat-item">
<div id="warningMessages" class="stat-number">0</div>
<div class="stat-label">预警消息</div>
</div>
<div class="stat-item">
<div id="commandMessages" class="stat-number">0</div>
<div class="stat-label">控制指令</div>
</div>
</div>
<div id="messages"></div>
</div>
<script>
let stompClient = null;
const messagesDiv = document.getElementById('messages');
const statusDiv = document.getElementById('status');
const connectBtn = document.getElementById('connectBtn');
const disconnectBtn = document.getElementById('disconnectBtn');
// 消息计数器
let messageStats = {
total: 0,
position_update: 0,
collision_warning: 0,
vehicle_command: 0,
traffic_light_status: 0,
system_alert: 0
};
function updateStats() {
document.getElementById('totalMessages').textContent = messageStats.total;
document.getElementById('positionMessages').textContent = messageStats.position_update;
document.getElementById('warningMessages').textContent = messageStats.collision_warning;
document.getElementById('commandMessages').textContent = messageStats.vehicle_command;
}
function log(message, type = 'info') {
const div = document.createElement('div');
div.className = type;
div.innerHTML = `<span style="color: #888;">[${new Date().toLocaleTimeString()}]</span> ${message}`;
messagesDiv.appendChild(div);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
function clearMessages() {
messagesDiv.innerHTML = '';
messageStats = {
total: 0,
position_update: 0,
collision_warning: 0,
vehicle_command: 0,
traffic_light_status: 0,
system_alert: 0
};
updateStats();
}
function updateConnectionStatus(connected) {
if (connected) {
statusDiv.textContent = '已连接';
statusDiv.className = 'status connected';
connectBtn.disabled = true;
disconnectBtn.disabled = false;
} else {
statusDiv.textContent = '未连接';
statusDiv.className = 'status disconnected';
connectBtn.disabled = false;
disconnectBtn.disabled = true;
}
}
function connect() {
if (stompClient && stompClient.connected) {
log('已经连接,请先断开', 'error');
return;
}
try {
// 创建SockJS连接
const socket = new SockJS('http://10.0.0.124:8081/ws');
stompClient = new StompJs.Client({
webSocketFactory: () => socket,
connectHeaders: {},
debug: function (str) {
console.log('STOMP Debug: ' + str);
},
reconnectDelay: 5000,
heartbeatIncoming: 4000,
heartbeatOutgoing: 4000,
});
stompClient.onConnect = function (frame) {
log('WebSocket连接成功!', 'success');
log('Frame: ' + frame, 'info');
updateConnectionStatus(true);
// 订阅实时消息主题
stompClient.subscribe('/topic/realtime', function (message) {
handleMessage(message);
});
log('已订阅主题: /topic/realtime', 'success');
};
stompClient.onStompError = function (frame) {
log('STOMP错误: ' + frame.headers['message'], 'error');
log('详细信息: ' + frame.body, 'error');
updateConnectionStatus(false);
};
stompClient.onWebSocketClose = function (event) {
log('WebSocket连接关闭', 'info');
updateConnectionStatus(false);
};
stompClient.onWebSocketError = function (error) {
log('WebSocket错误: ' + error, 'error');
updateConnectionStatus(false);
};
// 激活连接
stompClient.activate();
log('正在连接到 ws://10.0.0.124:8082/ws ...', 'info');
} catch (error) {
log('连接失败: ' + error.message, 'error');
updateConnectionStatus(false);
}
}
function disconnect() {
if (!stompClient) {
log('未连接', 'error');
return;
}
stompClient.deactivate();
stompClient = null;
log('连接已断开', 'info');
updateConnectionStatus(false);
}
function handleMessage(message) {
try {
const data = JSON.parse(message.body);
messageStats.total++;
if (messageStats[data.type]) {
messageStats[data.type]++;
}
updateStats();
// 根据消息类型进行不同的处理和显示
switch (data.type) {
case 'position_update':
handlePositionUpdate(data);
break;
case 'collision_warning':
handleCollisionWarning(data);
break;
case 'vehicle_command':
handleVehicleCommand(data);
break;
case 'intersection_traffic_light_status':
handleTrafficLightStatus(data);
break;
case 'system_alert':
handleSystemAlert(data);
break;
default:
log('收到未知类型消息: ' + JSON.stringify(data, null, 2), 'info');
}
} catch (e) {
log('消息解析错误: ' + e.message + ', 原始消息: ' + message.body, 'error');
}
}
function handlePositionUpdate(data) {
const payload = data.payload;
log(`<strong>位置更新</strong> | 对象: ${payload.object_id} (${payload.object_type}) | ` +
`位置: (${payload.position?.latitude?.toFixed(6)}, ${payload.position?.longitude?.toFixed(6)}) | ` +
`航向: ${payload.heading}° | 速度: ${payload.speed} km/h`, 'position');
}
function handleCollisionWarning(data) {
const payload = data.payload;
log(`<strong>🚨 碰撞预警!</strong> | 对象1: ${payload.object1_id} (${payload.object1_type}) | ` +
`对象2: ${payload.object2_id} (${payload.object2_type}) | ` +
`风险等级: <strong>${payload.risk_level}</strong> | 距离: ${payload.distance}m | ` +
`预计时间: ${payload.estimated_time}s`, 'collision');
}
function handleVehicleCommand(data) {
const payload = data.payload;
const commandTypes = {
'SIGNAL': '🚥 信号灯',
'ALERT': '⚠️ 告警',
'WARNING': '⚠️ 预警',
'RESUME': '✅ 恢复',
'PARKING': '🅿️ 停车'
};
const reasons = {
'TRAFFIC_LIGHT': '红绿灯控制',
'AIRCRAFT_CROSSING': '航空器交叉',
'COLLISION_WARNING': '碰撞预警',
'SPECIAL_VEHICLE': '特勤车辆',
'AIRCRAFT_PUSH': '航空器推出',
'RESUME_TRAFFIC': '恢复通行',
'PARKING_SIDE': '安全停车'
};
log(`<strong>车辆控制指令</strong> | 车辆: ${payload.vehicleId} | ` +
`指令: ${commandTypes[payload.commandType] || payload.commandType} | ` +
`原因: ${reasons[payload.reason] || payload.reason} | ` +
`描述: ${payload.description || '无'}`, 'command');
}
function handleTrafficLightStatus(data) {
const payload = data.payload;
log(`<strong>🚦 红绿灯状态</strong> | 路口: ${payload.intersection_id} | ` +
`南北: ${payload.ns_status} | 东西: ${payload.ew_status}`, 'traffic-light');
}
function handleSystemAlert(data) {
const payload = data.payload;
log(`<strong>⚠️ 系统告警</strong> | ${payload.alert_level} | ${payload.title} | ` +
`组件: ${payload.component} | 描述: ${payload.description}`, 'system');
}
// 页面加载完成后的初始化
window.onload = function() {
log('WebSocket测试客户端已就绪', 'success');
log('请点击"连接"按钮开始测试', 'info');
};
// 页面关闭时自动断开连接
window.onbeforeunload = function() {
if (stompClient && stompClient.connected) {
disconnect();
}
};
</script>
</body>
</html>