Files
YG_FT_Platform/request/static/status.html
DESKTOP-72TV0V4\caoxiaozhu bda8f13446 1. 增加了请求框架
2. 增加了删除虚拟环境的脚本
2026-01-12 14:20:44 +08:00

475 lines
22 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>系统状态 - X-Request</title>
<!-- 引入Tailwind CSS (离线版本) -->
<script src="vendor/tailwind.min.js"></script>
<!-- 引入内联 SVG 图标系统 (完全离线) -->
<script src="vendor/icons.js"></script>
<style>
.inline-icon, .inline-emoji {
display: inline-block;
vertical-align: middle;
}
.inline-icon svg {
width: 1em;
height: 1em;
fill: currentColor;
}
.inline-emoji {
font-size: 1em;
line-height: 1;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.inline-icon[data-spin="true"], .inline-emoji[data-spin="true"] {
animation: spin 1s linear infinite;
}
</style>
<!-- 配置Tailwind -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3b82f6',
secondary: '#8b5cf6',
success: '#10b981',
warning: '#f59e0b',
danger: '#ef4444',
},
},
}
}
</script>
<style type="text/tailwindcss">
@layer utilities {
.content-auto {
content-visibility: auto;
}
}
/* 全屏样式 */
html, body {
height: 100vh;
margin: 0;
padding: 0;
}
body {
display: flex;
flex-direction: column;
}
main {
flex: 1;
padding: 1rem;
}
.status-card {
transition: all 0.3s ease;
}
.status-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.pulse-animation {
animation: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes pulse {
0%, 100% {
opacity: 1;
}
50% {
opacity: .5;
}
}
</style>
</head>
<body class="bg-gray-50 min-h-screen">
<!-- 顶部导航栏 -->
<nav class="bg-white shadow-md h-16">
<div class="w-full mx-auto px-4 sm:px-6 lg:px-8">
<div class="flex justify-between h-16 items-center">
<div class="flex items-center">
<div class="flex-shrink-0 flex items-center">
<span class="text-3xl font-bold text-primary">X</span>
<span class="ml-2 text-xl font-semibold text-gray-800">X-Request 管理系统</span>
</div>
<div class="ml-6 flex items-center space-x-4">
<a href="/" class="px-3 py-2 rounded-md text-sm font-medium text-gray-500 hover:text-primary hover:bg-primary/10 hover:border-b-2 hover:border-primary transition-colors">
<i class="fa fa-home mr-1"></i> 首页
</a>
<a href="/log.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-500 hover:text-primary hover:bg-primary/10 hover:border-b-2 hover:border-primary transition-colors">
<i class="fa fa-file-text mr-1"></i> 日志管理
</a>
<a href="/doc.html" class="px-3 py-2 rounded-md text-sm font-medium text-gray-500 hover:text-primary hover:bg-primary/10 hover:border-b-2 hover:border-primary transition-colors">
<i class="fa fa-book mr-1"></i> 接口文档
</a>
<a href="/status.html" class="px-3 py-2 rounded-md text-sm font-medium text-primary bg-primary/10 border-b-2 border-primary">
<i class="fa fa-heartbeat mr-1"></i> 系统状态
</a>
</div>
</div>
<div class="flex items-center space-x-4">
<button id="refresh-btn" class="px-4 py-2 bg-primary text-white rounded-md hover:bg-primary/90 transition-colors flex items-center">
<i class="fa fa-refresh mr-2"></i>
<span>刷新</span>
</button>
<a href="index.html" class="px-4 py-2 bg-gray-200 text-gray-700 rounded-md hover:bg-gray-300 transition-colors flex items-center">
<i class="fa fa-home mr-2"></i>
<span>返回首页</span>
</a>
</div>
</div>
</div>
</nav>
<!-- 主要内容 -->
<main class="w-full px-4 sm:px-6 lg:px-8 py-4">
<div class="max-w-6xl mx-auto">
<!-- 健康检查卡片 -->
<div class="bg-white rounded-lg shadow-md p-6 mb-6 status-card">
<div class="flex items-center justify-between mb-4">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i class="fa fa-heartbeat text-primary mr-3"></i>
健康检查
</h2>
<div id="health-status" class="flex items-center">
<span class="px-3 py-1 rounded-full text-sm font-medium bg-gray-200 text-gray-700">
<i class="fa fa-spinner fa-spin mr-2"></i>
检查中...
</span>
</div>
</div>
<div id="health-content" class="space-y-3">
<div class="flex items-center justify-center py-8">
<i class="fa fa-spinner fa-spin text-3xl text-primary"></i>
<span class="ml-3 text-gray-600">正在加载健康检查信息...</span>
</div>
</div>
</div>
<!-- 应用信息卡片 -->
<div class="bg-white rounded-lg shadow-md p-6 mb-6 status-card">
<div class="flex items-center justify-between mb-4">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i class="fa fa-info-circle text-primary mr-3"></i>
应用信息
</h2>
<div class="text-sm text-gray-500">
<i class="fa fa-clock-o mr-1"></i>
<span id="last-updated">--</span>
</div>
</div>
<div id="info-content" class="space-y-3">
<div class="flex items-center justify-center py-8">
<i class="fa fa-spinner fa-spin text-3xl text-primary"></i>
<span class="ml-3 text-gray-600">正在加载应用信息...</span>
</div>
</div>
</div>
<!-- 系统状态卡片 -->
<div class="bg-white rounded-lg shadow-md p-6 status-card">
<div class="flex items-center justify-between mb-4">
<h2 class="text-2xl font-bold text-gray-800 flex items-center">
<i class="fa fa-server text-primary mr-3"></i>
系统状态
</h2>
</div>
<div id="system-content" class="space-y-3">
<div class="flex items-center justify-center py-8">
<i class="fa fa-spinner fa-spin text-3xl text-primary"></i>
<span class="ml-3 text-gray-600">正在加载系统状态...</span>
</div>
</div>
</div>
</div>
</main>
<!-- 页脚 -->
<footer class="bg-white border-t border-gray-200 py-4 mt-6">
<div class="w-full mx-auto px-4 sm:px-6 lg:px-8 text-center text-sm text-gray-500">
<p>X-Request © 2025</p>
</div>
</footer>
<script>
// 工具函数
function formatTimestamp(timestamp) {
if (!timestamp) return '--';
const date = new Date(timestamp * 1000);
return date.toLocaleString('zh-CN');
}
function formatDateTime(date) {
return date.toLocaleString('zh-CN');
}
// 获取健康检查信息
async function fetchHealth() {
try {
const response = await fetch('/health');
const data = await response.json();
const healthStatus = document.getElementById('health-status');
const healthContent = document.getElementById('health-content');
if (data.status === 1 && data.response) {
// 健康状态
healthStatus.innerHTML = `
<span class="px-3 py-1 rounded-full text-sm font-medium bg-success/20 text-success border border-success/30">
<i class="fa fa-check-circle mr-2"></i>
健康
</span>
`;
// 健康信息内容
healthContent.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-success/5 border border-success/20 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-check-circle text-success text-xl mr-2"></i>
<span class="font-semibold text-gray-800">服务状态</span>
</div>
<p class="text-2xl font-bold text-success">${data.response.status || 'healthy'}</p>
</div>
<div class="bg-primary/5 border border-primary/20 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-cog text-primary text-xl mr-2"></i>
<span class="font-semibold text-gray-800">服务名称</span>
</div>
<p class="text-lg font-semibold text-gray-700">${data.response.service || 'Unknown'}</p>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-200">
<div class="text-sm text-gray-500">
<i class="fa fa-clock-o mr-1"></i>
检查时间: ${data.time || '--'}
</div>
</div>
`;
} else {
// 不健康状态
healthStatus.innerHTML = `
<span class="px-3 py-1 rounded-full text-sm font-medium bg-danger/20 text-danger border border-danger/30">
<i class="fa fa-exclamation-circle mr-2"></i>
异常
</span>
`;
healthContent.innerHTML = `
<div class="bg-danger/5 border border-danger/20 rounded-lg p-4">
<p class="text-danger font-semibold">健康检查失败</p>
<p class="text-sm text-gray-600 mt-2">${data.response?.error || '未知错误'}</p>
</div>
`;
}
} catch (error) {
const healthStatus = document.getElementById('health-status');
const healthContent = document.getElementById('health-content');
healthStatus.innerHTML = `
<span class="px-3 py-1 rounded-full text-sm font-medium bg-danger/20 text-danger border border-danger/30">
<i class="fa fa-times-circle mr-2"></i>
错误
</span>
`;
healthContent.innerHTML = `
<div class="bg-danger/5 border border-danger/20 rounded-lg p-4">
<p class="text-danger font-semibold">无法获取健康检查信息</p>
<p class="text-sm text-gray-600 mt-2">${error.message}</p>
</div>
`;
}
}
// 获取应用信息
async function fetchInfo() {
try {
const response = await fetch('/info');
const data = await response.json();
const infoContent = document.getElementById('info-content');
if (data.status === 1 && data.response) {
const info = data.response;
infoContent.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div class="bg-primary/5 border border-primary/20 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-tag text-primary text-xl mr-2"></i>
<span class="font-semibold text-gray-800">应用名称</span>
</div>
<p class="text-lg font-semibold text-gray-700">${info.app_name || 'Unknown'}</p>
</div>
<div class="bg-secondary/5 border border-secondary/20 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-code-fork text-secondary text-xl mr-2"></i>
<span class="font-semibold text-gray-800">版本号</span>
</div>
<p class="text-lg font-semibold text-gray-700">${info.version || 'Unknown'}</p>
</div>
<div class="bg-${info.debug ? 'warning' : 'success'}/5 border border-${info.debug ? 'warning' : 'success'}/20 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-${info.debug ? 'bug' : 'shield'} text-${info.debug ? 'warning' : 'success'} text-xl mr-2"></i>
<span class="font-semibold text-gray-800">调试模式</span>
</div>
<p class="text-lg font-semibold text-${info.debug ? 'warning' : 'success'}">${info.debug ? '已启用' : '已禁用'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-server text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">主机地址</span>
</div>
<p class="text-lg font-semibold text-gray-700">${info.host || 'Unknown'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-plug text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">端口号</span>
</div>
<p class="text-lg font-semibold text-gray-700">${info.port || 'Unknown'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-link text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">访问地址</span>
</div>
<p class="text-lg font-semibold text-gray-700">http://${info.host === '0.0.0.0' ? 'localhost' : info.host}:${info.port || 'Unknown'}</p>
</div>
</div>
<div class="mt-4 pt-4 border-t border-gray-200">
<div class="text-sm text-gray-500">
<i class="fa fa-clock-o mr-1"></i>
更新时间: ${data.time || '--'}
</div>
</div>
`;
} else {
infoContent.innerHTML = `
<div class="bg-danger/5 border border-danger/20 rounded-lg p-4">
<p class="text-danger font-semibold">无法获取应用信息</p>
<p class="text-sm text-gray-600 mt-2">${data.response?.error || '未知错误'}</p>
</div>
`;
}
} catch (error) {
const infoContent = document.getElementById('info-content');
infoContent.innerHTML = `
<div class="bg-danger/5 border border-danger/20 rounded-lg p-4">
<p class="text-danger font-semibold">无法获取应用信息</p>
<p class="text-sm text-gray-600 mt-2">${error.message}</p>
</div>
`;
}
}
// 获取系统状态
async function fetchSystemStatus() {
try {
const response = await fetch('/monitoring/status');
const data = await response.json();
const systemContent = document.getElementById('system-content');
if (data.success && data.data && data.data.system) {
const system = data.data.system;
systemContent.innerHTML = `
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-desktop text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">主机名</span>
</div>
<p class="text-lg font-semibold text-gray-700">${system.hostname || 'Unknown'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-linux text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">系统类型</span>
</div>
<p class="text-lg font-semibold text-gray-700">${system.system_type || 'Unknown'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-python text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">Python 版本</span>
</div>
<p class="text-lg font-semibold text-gray-700">${system.python_version || 'Unknown'}</p>
</div>
<div class="bg-gray-50 border border-gray-200 rounded-lg p-4">
<div class="flex items-center mb-2">
<i class="fa fa-clock-o text-gray-600 text-xl mr-2"></i>
<span class="font-semibold text-gray-800">时间戳</span>
</div>
<p class="text-lg font-semibold text-gray-700">${formatTimestamp(system.timestamp)}</p>
</div>
</div>
`;
} else {
systemContent.innerHTML = `
<div class="bg-warning/5 border border-warning/20 rounded-lg p-4">
<p class="text-warning font-semibold">系统状态信息不可用</p>
</div>
`;
}
} catch (error) {
const systemContent = document.getElementById('system-content');
systemContent.innerHTML = `
<div class="bg-warning/5 border border-warning/20 rounded-lg p-4">
<p class="text-warning font-semibold">无法获取系统状态</p>
<p class="text-sm text-gray-600 mt-2">${error.message}</p>
</div>
`;
}
}
// 刷新所有信息
async function refreshAll() {
const lastUpdated = document.getElementById('last-updated');
lastUpdated.textContent = formatDateTime(new Date());
await Promise.all([
fetchHealth(),
fetchInfo(),
fetchSystemStatus()
]);
}
// 初始化
async function init() {
// 初始加载数据
await refreshAll();
// 刷新按钮事件
document.getElementById('refresh-btn').addEventListener('click', async () => {
const btn = document.getElementById('refresh-btn');
const icon = btn.querySelector('i');
icon.classList.add('fa-spin');
btn.disabled = true;
await refreshAll();
icon.classList.remove('fa-spin');
btn.disabled = false;
});
// 自动刷新每30秒
setInterval(refreshAll, 30000);
}
// 页面加载完成后初始化
document.addEventListener('DOMContentLoaded', init);
</script>
</body>
</html>