feat(admin): 添加系统健康检测功能
新增管理员健康检测面板,可检测以下配置项: - 安全配置:JWT密钥、CORS、HTTPS、管理员账号、登录防爆破 - 服务状态:SMTP邮件、数据库连接、存储目录 - 运行配置:反向代理支持、Node环境 修改文件: - backend/auth.js: 新增 isJwtSecretSecure() 函数 - backend/server.js: 新增 /api/admin/health-check API - frontend/app.js: 新增健康检测数据和方法 - frontend/app.html: 新增健康检测UI界面 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -654,6 +654,12 @@
|
||||
background: rgba(102, 126, 234, 0.05);
|
||||
border-radius: 12px;
|
||||
}
|
||||
|
||||
/* 健康检测状态颜色 */
|
||||
.text-green-600 { color: #16a34a; }
|
||||
.text-yellow-600 { color: #ca8a04; }
|
||||
.text-red-600 { color: #dc2626; }
|
||||
.text-blue-600 { color: #2563eb; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@@ -1747,6 +1753,127 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 健康检测 -->
|
||||
<div class="card" style="margin-bottom: 30px;">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 20px;">
|
||||
<h3 style="margin: 0;">
|
||||
<i class="fas fa-heartbeat"></i> 系统健康检测
|
||||
</h3>
|
||||
<button class="btn btn-primary" @click="loadHealthCheck" :disabled="healthCheck.loading">
|
||||
<i class="fas" :class="healthCheck.loading ? 'fa-spinner fa-spin' : 'fa-sync'"></i>
|
||||
{{ healthCheck.loading ? '检测中...' : '刷新检测' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 整体状态 -->
|
||||
<div v-if="healthCheck.overallStatus" style="margin-bottom: 20px;">
|
||||
<div style="display: flex; align-items: center; gap: 15px; flex-wrap: wrap;">
|
||||
<div style="font-size: 18px; font-weight: bold;" :class="getOverallStatusColor(healthCheck.overallStatus)">
|
||||
<i class="fas" :class="{
|
||||
'fa-check-circle': healthCheck.overallStatus === 'healthy',
|
||||
'fa-exclamation-triangle': healthCheck.overallStatus === 'warning',
|
||||
'fa-times-circle': healthCheck.overallStatus === 'critical'
|
||||
}"></i>
|
||||
{{ getOverallStatusText(healthCheck.overallStatus) }}
|
||||
</div>
|
||||
<div style="display: flex; gap: 12px; font-size: 13px;">
|
||||
<span style="color: #28a745;"><i class="fas fa-check"></i> 通过: {{ healthCheck.summary.pass }}</span>
|
||||
<span style="color: #ffc107;"><i class="fas fa-exclamation"></i> 警告: {{ healthCheck.summary.warning }}</span>
|
||||
<span style="color: #dc3545;"><i class="fas fa-times"></i> 失败: {{ healthCheck.summary.fail }}</span>
|
||||
<span style="color: #17a2b8;"><i class="fas fa-info"></i> 信息: {{ healthCheck.summary.info }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="healthCheck.lastCheck" style="font-size: 12px; color: #888; margin-top: 8px;">
|
||||
上次检测: {{ new Date(healthCheck.lastCheck).toLocaleString() }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 检测项列表 -->
|
||||
<div v-if="healthCheck.checks.length > 0">
|
||||
<!-- 按分类分组 -->
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h4 style="margin-bottom: 12px; color: #333;"><i class="fas fa-shield-alt"></i> 安全配置</h4>
|
||||
<div style="display: grid; gap: 10px;">
|
||||
<div v-for="check in healthCheck.checks.filter(c => c.category === 'security')" :key="check.name"
|
||||
style="display: flex; align-items: flex-start; gap: 12px; padding: 12px; background: #f8f9fa; border-radius: 8px;">
|
||||
<span style="font-size: 18px; width: 24px; text-align: center;"
|
||||
:class="{
|
||||
'text-green-600': check.status === 'pass',
|
||||
'text-yellow-600': check.status === 'warning',
|
||||
'text-red-600': check.status === 'fail',
|
||||
'text-blue-600': check.status === 'info'
|
||||
}">
|
||||
{{ getHealthStatusIcon(check.status) }}
|
||||
</span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 500; margin-bottom: 4px;">{{ check.name }}</div>
|
||||
<div style="font-size: 13px; color: #666;">{{ check.message }}</div>
|
||||
<div v-if="check.suggestion" style="font-size: 12px; color: #e67e22; margin-top: 4px;">
|
||||
<i class="fas fa-lightbulb"></i> {{ check.suggestion }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="margin-bottom: 20px;">
|
||||
<h4 style="margin-bottom: 12px; color: #333;"><i class="fas fa-server"></i> 服务状态</h4>
|
||||
<div style="display: grid; gap: 10px;">
|
||||
<div v-for="check in healthCheck.checks.filter(c => c.category === 'service')" :key="check.name"
|
||||
style="display: flex; align-items: flex-start; gap: 12px; padding: 12px; background: #f8f9fa; border-radius: 8px;">
|
||||
<span style="font-size: 18px; width: 24px; text-align: center;"
|
||||
:class="{
|
||||
'text-green-600': check.status === 'pass',
|
||||
'text-yellow-600': check.status === 'warning',
|
||||
'text-red-600': check.status === 'fail',
|
||||
'text-blue-600': check.status === 'info'
|
||||
}">
|
||||
{{ getHealthStatusIcon(check.status) }}
|
||||
</span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 500; margin-bottom: 4px;">{{ check.name }}</div>
|
||||
<div style="font-size: 13px; color: #666;">{{ check.message }}</div>
|
||||
<div v-if="check.suggestion" style="font-size: 12px; color: #e67e22; margin-top: 4px;">
|
||||
<i class="fas fa-lightbulb"></i> {{ check.suggestion }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 style="margin-bottom: 12px; color: #333;"><i class="fas fa-cog"></i> 运行配置</h4>
|
||||
<div style="display: grid; gap: 10px;">
|
||||
<div v-for="check in healthCheck.checks.filter(c => c.category === 'config')" :key="check.name"
|
||||
style="display: flex; align-items: flex-start; gap: 12px; padding: 12px; background: #f8f9fa; border-radius: 8px;">
|
||||
<span style="font-size: 18px; width: 24px; text-align: center;"
|
||||
:class="{
|
||||
'text-green-600': check.status === 'pass',
|
||||
'text-yellow-600': check.status === 'warning',
|
||||
'text-red-600': check.status === 'fail',
|
||||
'text-blue-600': check.status === 'info'
|
||||
}">
|
||||
{{ getHealthStatusIcon(check.status) }}
|
||||
</span>
|
||||
<div style="flex: 1;">
|
||||
<div style="font-weight: 500; margin-bottom: 4px;">{{ check.name }}</div>
|
||||
<div style="font-size: 13px; color: #666;">{{ check.message }}</div>
|
||||
<div v-if="check.suggestion" style="font-size: 12px; color: #e67e22; margin-top: 4px;">
|
||||
<i class="fas fa-lightbulb"></i> {{ check.suggestion }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 未检测提示 -->
|
||||
<div v-else style="text-align: center; padding: 40px; color: #888;">
|
||||
<i class="fas fa-stethoscope" style="font-size: 48px; margin-bottom: 15px;"></i>
|
||||
<p>点击"刷新检测"按钮开始系统健康检测</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 style="margin-bottom: 20px;">用户管理</h3>
|
||||
<div style="overflow-x: auto;">
|
||||
<table style="width: 100%; border-collapse: collapse; table-layout: fixed; min-width: 900px;">
|
||||
|
||||
Reference in New Issue
Block a user