增加websocket,数据实时显示
This commit is contained in:
@@ -58,6 +58,34 @@
|
||||
animation: glow-pulse 2s ease-in-out;
|
||||
}
|
||||
|
||||
/* 服务器状态组件光晕效果 */
|
||||
.glow-effect {
|
||||
animation: pulse 2s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes pulse {
|
||||
0% {
|
||||
box-shadow: 0 0 0 0 rgba(41, 128, 185, 0.4);
|
||||
}
|
||||
70% {
|
||||
box-shadow: 0 0 0 10px rgba(41, 128, 185, 0);
|
||||
}
|
||||
100% {
|
||||
box-shadow: 0 0 0 0 rgba(41, 128, 185, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* 服务器状态组件样式优化 */
|
||||
.server-status-widget {
|
||||
min-width: 170px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.server-status-widget:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
/* 蓝色光晕效果 */
|
||||
.number-glow-blue {
|
||||
animation: glow-blue 2s ease-in-out;
|
||||
@@ -211,6 +239,32 @@
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-4">
|
||||
<!-- 服务器状态组件 -->
|
||||
<div class="relative bg-white rounded-lg shadow-md px-3 py-2 flex items-center space-x-2 server-status-widget" id="server-status-widget">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs font-medium text-gray-500">CPU</span>
|
||||
<span id="server-cpu-value" class="ml-2 text-sm font-semibold">0%</span>
|
||||
</div>
|
||||
<div class="w-16 h-1 bg-gray-100 rounded-full mt-1">
|
||||
<div id="server-cpu-bar" class="h-full bg-warning rounded-full" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="w-1 h-8 bg-gray-200 rounded-full mx-1"></div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center">
|
||||
<span class="text-xs font-medium text-gray-500">查询</span>
|
||||
<span id="server-queries-value" class="ml-2 text-sm font-semibold">0</span>
|
||||
</div>
|
||||
<div class="w-16 h-1 bg-gray-100 rounded-full mt-1">
|
||||
<div id="server-queries-bar" class="h-full bg-primary rounded-full" style="width: 0%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="absolute top-1 right-1">
|
||||
<span id="server-status-indicator" class="inline-block w-2 h-2 bg-success rounded-full"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button class="p-2 text-gray-500 hover:text-gray-700 rounded-full hover:bg-gray-100">
|
||||
<i class="fa fa-bell text-lg"></i>
|
||||
</button>
|
||||
@@ -564,6 +618,7 @@
|
||||
<script src="js/main.js"></script>
|
||||
<script src="js/api.js"></script>
|
||||
<script src="js/dashboard.js"></script>
|
||||
<script src="js/server-status.js"></script>
|
||||
<script src="js/shield.js"></script>
|
||||
<script src="js/hosts.js"></script>
|
||||
<script src="js/query.js"></script>
|
||||
|
||||
216
static/js/server-status.js
Normal file
216
static/js/server-status.js
Normal file
@@ -0,0 +1,216 @@
|
||||
// server-status.js - 服务器状态组件功能实现
|
||||
|
||||
// 全局变量
|
||||
let serverStatusUpdateTimer = null;
|
||||
let previousServerData = {
|
||||
cpu: 0,
|
||||
queries: 0
|
||||
};
|
||||
|
||||
// 初始化服务器状态组件
|
||||
function initServerStatusWidget() {
|
||||
console.log('初始化服务器状态组件');
|
||||
|
||||
// 确保组件存在
|
||||
if (!document.getElementById('server-status-widget')) {
|
||||
console.warn('服务器状态组件不存在');
|
||||
return;
|
||||
}
|
||||
|
||||
// 监听页面切换事件
|
||||
handlePageSwitchEvents();
|
||||
|
||||
// 初始加载数据
|
||||
loadServerStatusData();
|
||||
|
||||
// 监听WebSocket连接事件
|
||||
monitorWebSocketConnection();
|
||||
}
|
||||
|
||||
// 处理页面切换事件
|
||||
function handlePageSwitchEvents() {
|
||||
// 监听导航点击事件
|
||||
document.querySelectorAll('.sidebar-link').forEach(link => {
|
||||
link.addEventListener('click', () => {
|
||||
// 页面切换后重新初始化组件
|
||||
setTimeout(() => {
|
||||
if (document.getElementById('server-status-widget')) {
|
||||
loadServerStatusData();
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// 监听WebSocket连接
|
||||
function monitorWebSocketConnection() {
|
||||
// 检查全局WebSocket连接
|
||||
if (window.wsConnection && window.wsConnection.readyState === WebSocket.OPEN) {
|
||||
setupWebSocketListeners();
|
||||
} else {
|
||||
// 如果WebSocket未连接,尝试监听其连接状态
|
||||
const originalOnOpen = window.wsConnection?.onopen;
|
||||
if (window.wsConnection) {
|
||||
window.wsConnection.onopen = function(event) {
|
||||
if (originalOnOpen) originalOnOpen(event);
|
||||
setupWebSocketListeners();
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 设置WebSocket监听器
|
||||
function setupWebSocketListeners() {
|
||||
// 保存原始的onmessage函数
|
||||
const originalOnMessage = window.wsConnection.onmessage;
|
||||
|
||||
// 重写onmessage函数
|
||||
window.wsConnection.onmessage = function(event) {
|
||||
// 调用原始函数
|
||||
if (originalOnMessage) originalOnMessage(event);
|
||||
|
||||
// 处理服务器状态数据
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
if (data.type === 'initial_data' || data.type === 'stats_update') {
|
||||
updateServerStatusWidget(data.data);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('处理服务器状态WebSocket消息失败:', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// 加载服务器状态数据
|
||||
async function loadServerStatusData() {
|
||||
try {
|
||||
// 使用现有的API获取系统状态
|
||||
const statusData = await window.api?.getStatus();
|
||||
if (statusData && !statusData.error) {
|
||||
updateServerStatusWidget(statusData);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('加载服务器状态数据失败:', error);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新服务器状态组件
|
||||
function updateServerStatusWidget(stats) {
|
||||
// 确保组件存在
|
||||
const widget = document.getElementById('server-status-widget');
|
||||
if (!widget) return;
|
||||
|
||||
// 提取CPU使用率
|
||||
let cpuUsage = 0;
|
||||
if (stats.system && stats.system.cpu) {
|
||||
cpuUsage = stats.system.cpu;
|
||||
} else if (stats.cpuUsage) {
|
||||
cpuUsage = stats.cpuUsage;
|
||||
}
|
||||
|
||||
// 提取查询量
|
||||
let queryCount = 0;
|
||||
if (stats.dns) {
|
||||
queryCount = (stats.dns.Allowed || 0) + (stats.dns.Blocked || 0) + (stats.dns.Errors || 0);
|
||||
} else if (stats.totalQueries) {
|
||||
queryCount = stats.totalQueries;
|
||||
}
|
||||
|
||||
// 更新CPU使用率
|
||||
if (document.getElementById('server-cpu-value')) {
|
||||
document.getElementById('server-cpu-value').textContent = cpuUsage.toFixed(1) + '%';
|
||||
}
|
||||
if (document.getElementById('server-cpu-bar')) {
|
||||
document.getElementById('server-cpu-bar').style.width = Math.min(cpuUsage, 100) + '%';
|
||||
|
||||
// 根据CPU使用率改变颜色
|
||||
const cpuBar = document.getElementById('server-cpu-bar');
|
||||
if (cpuUsage > 80) {
|
||||
cpuBar.className = 'h-full bg-danger rounded-full';
|
||||
} else if (cpuUsage > 50) {
|
||||
cpuBar.className = 'h-full bg-warning rounded-full';
|
||||
} else {
|
||||
cpuBar.className = 'h-full bg-success rounded-full';
|
||||
}
|
||||
}
|
||||
|
||||
// 更新查询量
|
||||
if (document.getElementById('server-queries-value')) {
|
||||
document.getElementById('server-queries-value').textContent = formatNumber(queryCount);
|
||||
}
|
||||
|
||||
// 计算查询量百分比(假设最大查询量为10000)
|
||||
const queryPercentage = Math.min((queryCount / 10000) * 100, 100);
|
||||
if (document.getElementById('server-queries-bar')) {
|
||||
document.getElementById('server-queries-bar').style.width = queryPercentage + '%';
|
||||
}
|
||||
|
||||
// 添加光晕提示效果
|
||||
if (previousServerData.cpu !== cpuUsage || previousServerData.queries !== queryCount) {
|
||||
addGlowEffect();
|
||||
}
|
||||
|
||||
// 更新服务器状态指示器
|
||||
if (document.getElementById('server-status-indicator')) {
|
||||
const indicator = document.getElementById('server-status-indicator');
|
||||
|
||||
// 检查系统状态
|
||||
if (stats.system && stats.system.status === 'error') {
|
||||
indicator.className = 'inline-block w-2 h-2 bg-danger rounded-full';
|
||||
} else {
|
||||
indicator.className = 'inline-block w-2 h-2 bg-success rounded-full';
|
||||
}
|
||||
}
|
||||
|
||||
// 保存当前数据用于下次比较
|
||||
previousServerData = {
|
||||
cpu: cpuUsage,
|
||||
queries: queryCount
|
||||
};
|
||||
}
|
||||
|
||||
// 添加光晕提示效果
|
||||
function addGlowEffect() {
|
||||
const widget = document.getElementById('server-status-widget');
|
||||
if (!widget) return;
|
||||
|
||||
// 添加光晕类
|
||||
widget.classList.add('glow-effect');
|
||||
|
||||
// 2秒后移除光晕
|
||||
setTimeout(() => {
|
||||
widget.classList.remove('glow-effect');
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
// 格式化数字(添加千位分隔符)
|
||||
function formatNumber(num) {
|
||||
if (num >= 1000000) {
|
||||
return (num / 1000000).toFixed(1) + 'M';
|
||||
} else if (num >= 1000) {
|
||||
return (num / 1000).toFixed(1) + 'K';
|
||||
}
|
||||
return num.toString();
|
||||
}
|
||||
|
||||
// 在DOM加载完成后初始化
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
// 延迟初始化,确保页面完全加载
|
||||
setTimeout(initServerStatusWidget, 500);
|
||||
|
||||
// 监听页面切换事件(已在handlePageSwitchEvents中处理)
|
||||
});
|
||||
|
||||
// 在页面卸载时清理资源
|
||||
window.addEventListener('beforeunload', () => {
|
||||
if (serverStatusUpdateTimer) {
|
||||
clearInterval(serverStatusUpdateTimer);
|
||||
serverStatusUpdateTimer = null;
|
||||
}
|
||||
});
|
||||
|
||||
// 导出函数供其他模块使用
|
||||
window.serverStatusWidget = {
|
||||
init: initServerStatusWidget,
|
||||
update: updateServerStatusWidget
|
||||
};
|
||||
Reference in New Issue
Block a user