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

342 lines
14 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>冲突检测WebSocket测试工具</title>
<style>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1920px;
margin: 0 auto;
background: white;
border-radius: 10px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
padding: 2px;
}
.test-section {
border: 1px solid #ddd;
border-radius: 8px;
margin: 2px 0;
padding: 10px;
background: #fafafa;
}
.control-group {
margin: 15px 0;
display: flex;
align-items: center;
gap: 10px;
flex-wrap: wrap;
}
.control-group label {
min-width: 120px;
font-weight: bold;
}
select, input, button {
padding: 8px 12px;
border: 1px solid #ccc;
border-radius: 4px;
font-size: 14px;
}
button {
background: #007bff;
color: white;
border: none;
cursor: pointer;
transition: background 0.3s;
}
button:hover {
background: #0056b3;
}
button:disabled {
background: #6c757d;
cursor: not-allowed;
}
.status {
padding: 10px;
border-radius: 5px;
margin: 10px 0;
font-weight: bold;
}
.status.connected {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status.disconnected {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
.log-container {
border: 1px solid #ddd;
border-radius: 4px;
height: 960px;
overflow-y: auto;
padding: 10px;
background: white;
font-family: 'Consolas', 'Monaco', monospace;
font-size: 12px;
}
.log-entry {
margin: 2px 0;
padding: 2px 5px;
border-radius: 3px;
}
.log-info { background: #f8f9fa; }
.log-success { background: #d4edda; color: #155724; }
.log-error { background: #f8d7da; color: #721c24; }
.log-warning { background: #fff3cd; color: #856404; }
</style>
</head>
<body>
<div class="container">
<!-- 冲突检测WebSocket测试 -->
<div class="test-section">
<h3>🚗 冲突检测WebSocket</h3>
<div class="control-group">
<label>服务器地址:</label>
<select id="collisionServerSelect">
<option value="ws://10.0.0.123:8080/collision"> 10.64.58.228:8080/collision</option>
</select>
</div>
<div class="control-group">
<button id="collisionConnectBtn" onclick="connectCollisionWebSocket()">连接</button>
<button id="collisionDisconnectBtn" onclick="disconnectCollisionWebSocket()" disabled>断开</button>
<button onclick="sendCollisionPing()">发送心跳</button>
<button onclick="sendCollisionSubscribe()">订阅消息</button>
</div>
<div class="status disconnected" id="collisionStatus">状态:未连接</div>
<div>
<h4>日志:</h4>
<div class="log-container" id="collisionLog"></div>
</div>
</div>
<!-- 控制面板 -->
<div class="test-section">
<h3>🎛️ 控制面板</h3>
<div class="control-group">
<button onclick="clearLogs()">清空日志</button>
<button onclick="showConnectionStatus()">显示连接状态</button>
<button onclick="performStressTest()">压力测试</button>
</div>
</div>
</div>
<script>
// 全局变量
let collisionWebSocket = null;
let reconnectAttempts = 0;
const maxReconnectAttempts = 5;
// 通用日志函数
function log(containerId, message, type = 'info') {
const container = document.getElementById(containerId);
const timestamp = new Date().toLocaleTimeString();
const entry = document.createElement('div');
entry.className = `log-entry log-${type}`;
entry.innerHTML = `[${timestamp}] ${message}`;
container.appendChild(entry);
container.scrollTop = container.scrollHeight;
}
// 更新连接状态
function updateStatus(statusId, connected, message = '') {
const statusDiv = document.getElementById(statusId);
statusDiv.className = `status ${connected ? 'connected' : 'disconnected'}`;
statusDiv.textContent = `状态:${connected ? '已连接' : '未连接'}${message ? ' - ' + message : ''}`;
}
// =================== 冲突检测WebSocket ===================
function connectCollisionWebSocket() {
if (collisionWebSocket && collisionWebSocket.readyState === WebSocket.OPEN) {
log('collisionLog', 'WebSocket已经连接', 'warning');
return;
}
const serverUrl = document.getElementById('collisionServerSelect').value;
log('collisionLog', `连接到: ${serverUrl}`, 'info');
try {
collisionWebSocket = new WebSocket(serverUrl);
collisionWebSocket.onopen = function(event) {
log('collisionLog', '冲突检测WebSocket连接成功!', 'success');
updateStatus('collisionStatus', true, '冲突检测');
document.getElementById('collisionConnectBtn').disabled = true;
document.getElementById('collisionDisconnectBtn').disabled = false;
reconnectAttempts = 0;
};
collisionWebSocket.onmessage = function(event) {
log('collisionLog', `收到消息: ${event.data}`, 'success');
try {
const message = JSON.parse(event.data);
handleCollisionMessage(message);
} catch (e) {
log('collisionLog', `非JSON消息: ${event.data}`, 'info');
}
};
collisionWebSocket.onerror = function(error) {
log('collisionLog', `连接错误: ${error}`, 'error');
updateStatus('collisionStatus', false);
};
collisionWebSocket.onclose = function(event) {
log('collisionLog', `连接关闭: ${event.code} - ${event.reason}`, 'warning');
updateStatus('collisionStatus', false);
document.getElementById('collisionConnectBtn').disabled = false;
document.getElementById('collisionDisconnectBtn').disabled = true;
// 自动重连
if (reconnectAttempts < maxReconnectAttempts) {
reconnectAttempts++;
log('collisionLog', `尝试重连 (${reconnectAttempts}/${maxReconnectAttempts})`, 'info');
setTimeout(connectCollisionWebSocket, 3000);
}
};
} catch (error) {
log('collisionLog', `连接失败: ${error.message}`, 'error');
updateStatus('collisionStatus', false);
}
}
function disconnectCollisionWebSocket() {
if (collisionWebSocket) {
collisionWebSocket.close();
collisionWebSocket = null;
log('collisionLog', '主动断开连接', 'info');
reconnectAttempts = maxReconnectAttempts;
}
}
function sendCollisionPing() {
if (collisionWebSocket && collisionWebSocket.readyState === WebSocket.OPEN) {
collisionWebSocket.send('ping');
log('collisionLog', '发送心跳: ping', 'info');
} else {
log('collisionLog', 'WebSocket未连接', 'error');
}
}
function sendCollisionSubscribe() {
if (collisionWebSocket && collisionWebSocket.readyState === WebSocket.OPEN) {
const message = JSON.stringify({
type: 'subscribe',
topics: ['position_update', 'collision_warning', 'rule_violation'],
timestamp: Date.now()
});
collisionWebSocket.send(message);
log('collisionLog', '发送订阅请求', 'info');
} else {
log('collisionLog', 'WebSocket未连接', 'error');
}
}
function handleCollisionMessage(message) {
switch (message.type) {
case 'connection':
log('collisionLog', `连接确认: ${message.message}`, 'success');
break;
case 'pong':
log('collisionLog', '心跳响应', 'success');
break;
case 'position_update':
// 修复:使用正确的字段名 object_id 而不是 vehicleId
const objectId = message.payload?.object_id || '未知';
const objectType = message.payload?.object_type || '';
log('collisionLog', `位置更新: ${objectId} (${objectType})`, 'info');
break;
case 'collision_warning':
log('collisionLog', `碰撞预警: ${message.payload?.message || JSON.stringify(message.payload)}`, 'error');
break;
case 'rule_violation':
const vehicleLicense = message.payload?.vehicleLicense || '未知车辆';
const ruleName = message.payload?.ruleName || '未知规则';
const violationType = message.payload?.violationType || '未知类型';
const alertLevel = message.payload?.alertLevel || '未知级别';
const description = message.payload?.description || '无描述';
log('collisionLog', `规则违规: ${vehicleLicense} - ${ruleName} (${violationType}/${alertLevel}): ${description}`, 'warning');
break;
case 'rule_execution_status':
log('collisionLog', `规则执行状态: ${message.payload?.status || '未知状态'}`, 'info');
break;
case 'rule_state_change':
log('collisionLog', `规则状态变更: ${message.payload?.newState || '未知状态'}`, 'info');
break;
case 'vehicle_command':
log('collisionLog', `车辆指令: ${message.payload?.commandType || '未知指令'}`, 'info');
break;
case 'traffic_light_status':
log('collisionLog', `红绿灯状态: ${message.payload?.intersection_id || '未知路口'}`, 'info');
break;
case 'aircraftRouteUpdate':
const flightNo = message.payload?.flightNo || '未知航班';
const routeType = message.payload?.routeType || '未知路由';
const routeStatus = message.payload?.status || '未知状态';
log('collisionLog', `航空器路由更新: ${flightNo} - ${routeType} (${routeStatus})`, 'info');
break;
case 'path_conflict_alert':
const object1 = message.payload?.object1Name || '未知对象1';
const object2 = message.payload?.object2Name || '未知对象2';
const conflictType = message.payload?.alertType || '未知类型';
const conflictLevel = message.payload?.alertLevel || '未知级别';
log('collisionLog', `路径冲突告警: ${object1} vs ${object2} (${conflictType}/${conflictLevel})`, 'error');
break;
default:
log('collisionLog', `未知消息类型: ${message.type}`, 'info');
}
}
// =================== 控制面板 ===================
function clearLogs() {
document.getElementById('collisionLog').innerHTML = '';
log('collisionLog', '日志已清空', 'info');
}
function showConnectionStatus() {
const collisionStatus = collisionWebSocket ?
(collisionWebSocket.readyState === WebSocket.OPEN ? '已连接' : '未连接') : '未初始化';
log('collisionLog', `冲突检测WebSocket: ${collisionStatus}`, 'info');
}
function performStressTest() {
log('collisionLog', '开始压力测试...', 'info');
for (let i = 0; i < 10; i++) {
setTimeout(() => {
if (collisionWebSocket && collisionWebSocket.readyState === WebSocket.OPEN) {
collisionWebSocket.send(`ping_${i}`);
}
}, i * 100);
}
}
// 页面加载完成
window.onload = function() {
log('collisionLog', '冲突检测WebSocket测试就绪', 'info');
};
// 页面关闭时清理连接
window.onbeforeunload = function() {
if (collisionWebSocket) collisionWebSocket.close();
};
</script>
</body>
</html>