425 lines
13 KiB
JavaScript
425 lines
13 KiB
JavaScript
// 美团基站测试组件
|
|
Router.register('/test/meituan', async () => {
|
|
const currentUser = await API.me().catch(() => null);
|
|
if (!currentUser) {
|
|
window.location.href = './login.html';
|
|
return '';
|
|
}
|
|
|
|
return `
|
|
<div class="page-container meituan-test-page">
|
|
<div class="page-header">
|
|
<h2 class="page-title">美团基站测试</h2>
|
|
<div class="page-actions">
|
|
<button class="btn btn-primary" id="connect-server-btn">
|
|
连接服务器
|
|
</button>
|
|
<button class="btn btn-secondary" id="refresh-btn">
|
|
刷新
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="meituan-test-content">
|
|
<!-- 服务器状态 -->
|
|
<div class="card server-status-card compact">
|
|
<div class="card-header">
|
|
<h3>服务器状态</h3>
|
|
<span class="status-indicator" id="server-status">
|
|
<span class="status-dot offline"></span>
|
|
离线
|
|
</span>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="info-row">
|
|
<span class="info-label">服务器地址:</span>
|
|
<span class="info-value">180.163.74.83:8888</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 基站控制面板 -->
|
|
<div class="card control-panel-card">
|
|
<div class="card-header">
|
|
<h3>基站控制</h3>
|
|
<div class="card-actions">
|
|
<label class="checkbox-label">
|
|
<input type="checkbox" id="hide-offline" checked>
|
|
<span>隐藏离线基站</span>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="control-row">
|
|
<select class="form-control" id="station-select">
|
|
<option value="">请选择在线基站</option>
|
|
</select>
|
|
<button class="btn btn-primary" id="self-test-btn">
|
|
开始自检
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 自检结果 -->
|
|
<div class="card self-test-card" id="self-test-card" style="display: none;">
|
|
<div class="card-header">
|
|
<h3>自检结果</h3>
|
|
<div class="card-actions">
|
|
<span class="test-status" id="test-status">检测中...</span>
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="test-results">
|
|
<div class="test-module" id="test-g">
|
|
<div class="module-header">
|
|
<span class="module-name">G模块</span>
|
|
<span class="module-status" id="g-status">待检测</span>
|
|
</div>
|
|
<div class="module-result" id="g-result"></div>
|
|
</div>
|
|
<div class="test-module" id="test-d">
|
|
<div class="module-header">
|
|
<span class="module-name">D模块</span>
|
|
<span class="module-status" id="d-status">待检测</span>
|
|
</div>
|
|
<div class="module-result" id="d-result"></div>
|
|
</div>
|
|
<div class="test-module" id="test-h">
|
|
<div class="module-header">
|
|
<span class="module-name">H模块</span>
|
|
<span class="module-status" id="h-status">待检测</span>
|
|
</div>
|
|
<div class="module-result" id="h-result"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 基站列表 -->
|
|
<div class="card stations-card">
|
|
<div class="card-header">
|
|
<h3>在线基站列表</h3>
|
|
<div class="card-actions">
|
|
<input type="text" class="form-control" id="search-station" placeholder="搜索基站...">
|
|
</div>
|
|
</div>
|
|
<div class="card-body">
|
|
<div class="stations-table-container">
|
|
<table class="table stations-table">
|
|
<thead>
|
|
<tr>
|
|
<th>基站SN</th>
|
|
<th>连接时间</th>
|
|
<th>状态</th>
|
|
<th>最后心跳</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="stations-tbody">
|
|
<tr>
|
|
<td colspan="4" class="text-center">暂无基站连接</td>
|
|
</tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
|
|
// 美团基站测试逻辑
|
|
(() => {
|
|
let ws = null;
|
|
let connected = false;
|
|
let stations = new Map();
|
|
let isInitialized = false;
|
|
|
|
// 初始化
|
|
function initMeituanTest() {
|
|
if (isInitialized) return;
|
|
|
|
// 等待DOM渲染完成
|
|
const checkElements = () => {
|
|
const statusEl = document.getElementById('server-status');
|
|
if (statusEl) {
|
|
isInitialized = true;
|
|
setupEventListeners();
|
|
connectServer();
|
|
} else {
|
|
setTimeout(checkElements, 50);
|
|
}
|
|
};
|
|
|
|
checkElements();
|
|
}
|
|
|
|
function cleanup() {
|
|
isInitialized = false;
|
|
if (ws) {
|
|
ws.close();
|
|
ws = null;
|
|
}
|
|
connected = false;
|
|
}
|
|
|
|
// 监听路由变化
|
|
Router.onAfterEach(async (path) => {
|
|
if (path === '/test/meituan') {
|
|
initMeituanTest();
|
|
} else {
|
|
cleanup();
|
|
}
|
|
});
|
|
|
|
function setupEventListeners() {
|
|
// 连接服务器按钮
|
|
const connectBtn = document.getElementById('connect-server-btn');
|
|
if (connectBtn) {
|
|
connectBtn.addEventListener('click', connectServer);
|
|
}
|
|
|
|
// 刷新按钮
|
|
const refreshBtn = document.getElementById('refresh-btn');
|
|
if (refreshBtn) {
|
|
refreshBtn.addEventListener('click', () => {
|
|
if (ws) {
|
|
ws.close();
|
|
}
|
|
connectServer();
|
|
});
|
|
}
|
|
|
|
// 搜索基站
|
|
const searchInput = document.getElementById('search-station');
|
|
if (searchInput) {
|
|
searchInput.addEventListener('input', (e) => {
|
|
filterStations(e.target.value);
|
|
});
|
|
}
|
|
|
|
// 隐藏离线基站
|
|
const hideOfflineCheckbox = document.getElementById('hide-offline');
|
|
if (hideOfflineCheckbox) {
|
|
hideOfflineCheckbox.addEventListener('change', () => {
|
|
updateStationsList();
|
|
updateStationSelect();
|
|
});
|
|
}
|
|
|
|
// 自检按钮
|
|
const selfTestBtn = document.getElementById('self-test-btn');
|
|
if (selfTestBtn) {
|
|
selfTestBtn.addEventListener('click', startSelfTest);
|
|
}
|
|
}
|
|
|
|
function connectServer() {
|
|
const statusEl = document.getElementById('server-status');
|
|
|
|
// 更新状态为连接中
|
|
statusEl.innerHTML = '<span class="status-dot connecting"></span>连接中...';
|
|
|
|
// 获取服务器状态
|
|
fetch('/api/meituan/server-status')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
connected = true;
|
|
statusEl.innerHTML = `<span class="status-dot ${data.status}"></span>${data.status === 'online' ? '在线' : '离线'}`;
|
|
|
|
// 获取基站列表
|
|
loadStations();
|
|
|
|
// 定期刷新
|
|
setInterval(() => {
|
|
loadStations();
|
|
}, 5000);
|
|
} else {
|
|
statusEl.innerHTML = '<span class="status-dot offline"></span>连接失败';
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('连接失败:', error);
|
|
statusEl.innerHTML = '<span class="status-dot offline"></span>连接失败';
|
|
});
|
|
}
|
|
|
|
function startLogPolling() {
|
|
// 轮询获取服务器日志
|
|
setInterval(async () => {
|
|
try {
|
|
// 这里应该调用实际的API获取日志
|
|
// const logs = await API.getServerLogs();
|
|
// updateLogs(logs);
|
|
} catch (e) {
|
|
console.error('获取日志失败:', e);
|
|
}
|
|
}, 2000);
|
|
}
|
|
|
|
function loadStations() {
|
|
fetch('/api/meituan/stations')
|
|
.then(response => response.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
stations.clear();
|
|
data.stations.forEach(station => {
|
|
stations.set(station.id, station);
|
|
});
|
|
updateStationsList();
|
|
updateStationSelect();
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('获取基站列表失败:', error);
|
|
});
|
|
}
|
|
|
|
function updateStationsList() {
|
|
const tbody = document.getElementById('stations-tbody');
|
|
const hideOffline = document.getElementById('hide-offline')?.checked ?? true;
|
|
|
|
if (!tbody) return;
|
|
|
|
// 过滤基站
|
|
let filteredStations = Array.from(stations.values());
|
|
if (hideOffline) {
|
|
filteredStations = filteredStations.filter(s => s.status === 'online');
|
|
}
|
|
|
|
if (filteredStations.length === 0) {
|
|
tbody.innerHTML = `<tr><td colspan="4" class="text-center">${hideOffline ? '暂无在线基站' : '暂无基站连接'}</td></tr>`;
|
|
return;
|
|
}
|
|
|
|
tbody.innerHTML = filteredStations.map(station => {
|
|
// 处理可能缺失的字段,适配实际数据格式
|
|
const lastSeen = station.last_seen || station.lastHeartbeat || new Date();
|
|
const connectTime = station.connect_time || station.connectTime || station.last_seen || new Date();
|
|
const ip = station.ip || '10.8.0.x'; // 基站通常在内网
|
|
const status = station.status || 'offline';
|
|
|
|
// 转换为Date对象
|
|
const connectTimeDate = connectTime instanceof Date ? connectTime : new Date(connectTime);
|
|
const lastSeenDate = lastSeen instanceof Date ? lastSeen : new Date(lastSeen);
|
|
|
|
return `
|
|
<tr>
|
|
<td>${station.id || '未知'}</td>
|
|
<td>${connectTimeDate.toLocaleString()}</td>
|
|
<td><span class="status-badge ${status}">${status === 'online' ? '在线' : '离线'}</span></td>
|
|
<td>${lastSeenDate.toLocaleString()}</td>
|
|
</tr>
|
|
`;
|
|
}).join('');
|
|
}
|
|
|
|
function updateStationSelect() {
|
|
const select = document.getElementById('station-select');
|
|
const hideOffline = document.getElementById('hide-offline')?.checked ?? true;
|
|
|
|
if (!select) return;
|
|
|
|
// 保存当前选中的值
|
|
const currentValue = select.value;
|
|
|
|
// 过滤基站
|
|
let filteredStations = Array.from(stations.values());
|
|
if (hideOffline) {
|
|
filteredStations = filteredStations.filter(s => s.status === 'online');
|
|
}
|
|
|
|
select.innerHTML = '<option value="">请选择在线基站</option>' +
|
|
filteredStations.map(station => {
|
|
const ip = station.ip || '未知';
|
|
return `<option value="${station.id}">${station.id}</option>`;
|
|
}).join('');
|
|
|
|
// 恢复之前选中的值(如果仍然存在)
|
|
if (currentValue && filteredStations.some(s => s.id === currentValue)) {
|
|
select.value = currentValue;
|
|
}
|
|
}
|
|
|
|
function filterStations(keyword) {
|
|
const rows = document.querySelectorAll('#stations-tbody tr');
|
|
rows.forEach(row => {
|
|
const text = row.textContent.toLowerCase();
|
|
row.style.display = text.includes(keyword.toLowerCase()) ? '' : 'none';
|
|
});
|
|
}
|
|
|
|
function startSelfTest() {
|
|
const stationId = document.getElementById('station-select').value;
|
|
|
|
if (!stationId) {
|
|
API.toast('请先选择基站', 'warning');
|
|
return;
|
|
}
|
|
|
|
// 显示自检卡片
|
|
const selfTestCard = document.getElementById('self-test-card');
|
|
selfTestCard.style.display = 'block';
|
|
|
|
// 重置状态
|
|
resetTestStatus();
|
|
|
|
// 更新状态
|
|
document.getElementById('test-status').textContent = `正在检测基站 ${stationId}...`;
|
|
|
|
// 模拟自检过程
|
|
simulateSelfTest(stationId);
|
|
}
|
|
|
|
function resetTestStatus() {
|
|
// 重置所有模块状态
|
|
['g', 'd', 'h'].forEach(module => {
|
|
document.getElementById(`${module}-status`).textContent = '待检测';
|
|
document.getElementById(`${module}-status`).className = 'module-status';
|
|
document.getElementById(`${module}-result`).textContent = '';
|
|
document.getElementById(`${module}-result`).className = 'module-result';
|
|
});
|
|
}
|
|
|
|
function simulateSelfTest(stationId) {
|
|
// 模拟G模块检测
|
|
updateModuleStatus('g', 'testing', '检测中...');
|
|
setTimeout(() => {
|
|
const gResult = Math.random() > 0.2 ? '正常' : '异常';
|
|
updateModuleStatus('g', gResult === '正常' ? 'success' : 'error', gResult === '正常' ? '正常' : '异常');
|
|
|
|
// 模拟D模块检测
|
|
updateModuleStatus('d', 'testing', '检测中...');
|
|
setTimeout(() => {
|
|
const dResult = Math.random() > 0.2 ? '正常' : '异常';
|
|
updateModuleStatus('d', dResult === '正常' ? 'success' : 'error', dResult === '正常' ? '正常' : '异常');
|
|
|
|
// 模拟H模块检测
|
|
updateModuleStatus('h', 'testing', '检测中...');
|
|
setTimeout(() => {
|
|
const hResult = Math.random() > 0.2 ? '正常' : '异常';
|
|
updateModuleStatus('h', hResult === '正常' ? 'success' : 'error', hResult === '正常' ? '正常' : '异常');
|
|
|
|
// 更新总体状态
|
|
document.getElementById('test-status').textContent = '检测完成';
|
|
}, 2000);
|
|
}, 2000);
|
|
}, 2000);
|
|
}
|
|
|
|
function updateModuleStatus(module, status, result) {
|
|
const statusEl = document.getElementById(`${module}-status`);
|
|
const resultEl = document.getElementById(`${module}-result`);
|
|
|
|
statusEl.textContent = status === 'testing' ? '检测中' : (status === 'success' ? '正常' : '异常');
|
|
statusEl.className = `module-status ${status}`;
|
|
|
|
if (result) {
|
|
resultEl.textContent = result;
|
|
resultEl.className = `module-result ${status}`;
|
|
}
|
|
}
|
|
})();
|