第一个版本

This commit is contained in:
2025-07-31 21:21:45 +08:00
commit 7792734fb0
31 changed files with 662 additions and 0 deletions

View File

@@ -0,0 +1,239 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>服务状态监控</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#165DFF',
operational: '#36D399',
degraded: '#FBBD23',
outage: '#F87272',
dark: '#1E293B',
light: '#F8FAFC'
},
fontFamily: {
inter: ['Inter', 'system-ui', 'sans-serif'],
},
}
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
.card-shadow {
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
}
.card-hover {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card-hover:hover {
transform: translateY(-5px);
box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
}
.gradient-bg {
background: linear-gradient(135deg, #165DFF 0%, #0A2463 100%);
}
}
</style>
</head>
<body class="bg-gray-50 font-inter min-h-screen">
<!-- 顶部导航 -->
<header class="gradient-bg text-white shadow-lg">
<div class="container mx-auto px-4 py-6">
<div class="flex flex-col md:flex-row justify-between items-center">
<div class="flex items-center mb-4 md:mb-0">
<i class="fa fa-server text-3xl mr-3"></i>
<h1 class="text-[clamp(1.5rem,3vw,2.5rem)] font-bold">服务状态监控</h1>
</div>
<div class="flex items-center space-x-2">
<i class="fa fa-refresh animate-spin mr-2"></i>
<span id="last-updated" class="text-sm md:text-base">最后更新: 加载中...</span>
</div>
</div>
<p class="mt-2 text-gray-200">实时监控系统服务运行状态与可靠性</p>
</div>
</header>
<!-- 主内容区 -->
<main class="container mx-auto px-4 py-8">
<!-- 状态概览 -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-10">
<div class="bg-white rounded-xl p-6 card-shadow card-hover border-l-4 border-operational">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">正常运行</p>
<h3 id="operational-count" class="text-3xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-operational/10 flex items-center justify-center text-operational">
<i class="fa fa-check-circle text-xl"></i>
</div>
</div>
</div>
<div class="bg-white rounded-xl p-6 card-shadow card-hover border-l-4 border-degraded">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">性能下降</p>
<h3 id="degraded-count" class="text-3xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-degraded/10 flex items-center justify-center text-degraded">
<i class="fa fa-exclamation-triangle text-xl"></i>
</div>
</div>
</div>
<div class="bg-white rounded-xl p-6 card-shadow card-hover border-l-4 border-outage">
<div class="flex items-center justify-between">
<div>
<p class="text-gray-500 text-sm">服务中断</p>
<h3 id="outage-count" class="text-3xl font-bold mt-1">0</h3>
</div>
<div class="w-12 h-12 rounded-full bg-outage/10 flex items-center justify-center text-outage">
<i class="fa fa-times-circle text-xl"></i>
</div>
</div>
</div>
</div>
<!-- 服务列表 -->
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" id="services-container">
<!-- 服务卡片将通过JavaScript动态生成 -->
<div class="col-span-full text-center py-12 text-gray-500">
<i class="fa fa-circle-o-notch fa-spin text-3xl mb-4"></i>
<p>加载服务数据中...</p>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-dark text-white py-6 mt-12">
<div class="container mx-auto px-4 text-center">
<p>© 2025 服务状态监控系统 | 数据每30秒自动更新</p>
</div>
</footer>
<script>
// 状态样式映射
const statusStyles = {
operational: {
class: 'bg-operational text-white',
icon: 'fa-check-circle',
text: '正常运行'
},
degraded: {
class: 'bg-degraded text-white',
icon: 'fa-exclamation-triangle',
text: '性能下降'
},
outage: {
class: 'bg-outage text-white',
icon: 'fa-times-circle',
text: '服务中断'
}
};
// 更新服务数据
function updateServices() {
fetch('/api/services/')
.then(response => response.json())
.then(data => {
// 更新最后更新时间
const now = new Date();
document.getElementById('last-updated').textContent = `最后更新: ${now.toLocaleString()}`;
// 统计各状态数量
const counts = {
operational: 0,
degraded: 0,
outage: 0
};
data.forEach(service => {
counts[service.status]++;
});
// 更新统计数字
document.getElementById('operational-count').textContent = counts.operational;
document.getElementById('degraded-count').textContent = counts.degraded;
document.getElementById('outage-count').textContent = counts.outage;
// 生成服务卡片
const container = document.getElementById('services-container');
container.innerHTML = '';
if (data.length === 0) {
container.innerHTML = `
<div class="col-span-full text-center py-12 text-gray-500">
<i class="fa fa-info-circle text-3xl mb-4"></i>
<p>暂无服务数据</p>
</div>
`;
return;
}
data.forEach(service => {
const style = statusStyles[service.status];
const card = document.createElement('div');
card.className = 'bg-white rounded-xl overflow-hidden card-shadow card-hover';
card.innerHTML = `
<div class="p-6">
<div class="flex justify-between items-start mb-4">
<h3 class="text-xl font-bold text-gray-800">${service.name}</h3>
<span class="px-3 py-1 rounded-full text-sm font-medium ${style.class}">
<i class="fa ${style.icon} mr-1"></i> ${style.text}
</span>
</div>
<p class="text-gray-600 mb-4">${service.description}</p>
<div class="grid grid-cols-2 gap-3 text-sm">
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-gray-500">IP地址</p>
<p class="font-medium">${service.ip_address}</p>
</div>
<div class="bg-gray-50 p-3 rounded-lg">
<p class="text-gray-500">端口</p>
<p class="font-medium">${service.port}</p>
</div>
<div class="bg-gray-50 p-3 rounded-lg col-span-2">
<p class="text-gray-500">可靠率</p>
<div class="w-full bg-gray-200 rounded-full h-2 mt-1">
<div class="${style.class} h-2 rounded-full" style="width: ${service.reliability}%"></div>
</div>
<p class="font-medium mt-1">${service.reliability}%</p>
</div>
</div>
<div class="mt-4 text-xs text-gray-500">
<p>最后更新: ${new Date(service.last_updated).toLocaleString()}</p>
</div>
</div>
`;
container.appendChild(card);
});
})
.catch(error => {
console.error('获取服务数据失败:', error);
const container = document.getElementById('services-container');
container.innerHTML = `
<div class="col-span-full text-center py-12 text-red-500">
<i class="fa fa-exclamation-circle text-3xl mb-4"></i>
<p>加载服务数据失败,请刷新页面重试</p>
</div>
`;
});
}
// 初始加载
updateServices();
// 定时更新 (30秒)
setInterval(updateServices, 30000);
</script>
</body>
</html>