feat: M4-03 — health check status section in Servers page
All checks were successful
Deploy Admin Frontend / build-and-deploy (push) Successful in 10s

- Add getServerHealth API function with types
- Add health check status tags below server cards

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
WangDL 2026-05-24 17:51:44 +08:00
parent 35a3f40ef8
commit 8145279626
2 changed files with 36 additions and 1 deletions

View File

@ -2,7 +2,7 @@ import { useState } from 'react'
import { useQuery, useQueryClient } from '@tanstack/react-query' import { useQuery, useQueryClient } from '@tanstack/react-query'
import { Card, Row, Col, Progress, Table, Tag, Typography, Button, Space, Tooltip, App } from 'antd' import { Card, Row, Col, Progress, Table, Tag, Typography, Button, Space, Tooltip, App } from 'antd'
import { CloudServerOutlined, ReloadOutlined, CopyOutlined, GlobalOutlined } from '@ant-design/icons' import { CloudServerOutlined, ReloadOutlined, CopyOutlined, GlobalOutlined } from '@ant-design/icons'
import { getServerMetrics, type ServerInfo, type ProcessInfo } from '@/services/server-api' import { getServerMetrics, getServerHealth, type ServerInfo, type ProcessInfo, type ServerHealth } from '@/services/server-api'
const { Text, Title } = Typography const { Text, Title } = Typography
@ -96,6 +96,12 @@ function ServersContent() {
staleTime: 30_000, staleTime: 30_000,
}) })
const { data: health } = useQuery({
queryKey: ['servers', 'health'],
queryFn: getServerHealth,
staleTime: 60_000,
})
const handleRefresh = async () => { const handleRefresh = async () => {
setRefreshing(true) setRefreshing(true)
await qc.invalidateQueries({ queryKey: ['servers', 'metrics'] }) await qc.invalidateQueries({ queryKey: ['servers', 'metrics'] })
@ -115,6 +121,24 @@ function ServersContent() {
</Col> </Col>
))} ))}
</Row> </Row>
{/* Health Check Section */}
{health?.length ? (
<div style={{ marginTop: 20 }}>
<Title level={5} style={{ marginBottom: 12 }}></Title>
{(health as ServerHealth[]).map(h => (
<Card key={h.serverName} title={h.serverName} size="small" style={{ marginBottom: 8 }}>
<Space wrap>
{h.services.map(s => (
<Tag key={s.serviceName} color={s.status === 'healthy' ? 'green' : 'red'}>
{s.serviceName} · {s.message}
</Tag>
))}
</Space>
</Card>
))}
</div>
) : null}
</div> </div>
) )
} }

View File

@ -12,6 +12,17 @@ export interface ServerInfo {
network: { publicIp: string; privateIp: string; domains: string[] }; network: { publicIp: string; privateIp: string; domains: string[] };
} }
export interface ServiceHealthItem {
serviceName: string; status: string; message: string;
}
export interface ServerHealth {
serverName: string; services: ServiceHealthItem[];
}
export function getServerMetrics(): Promise<{ servers: ServerInfo[] }> { export function getServerMetrics(): Promise<{ servers: ServerInfo[] }> {
return api.get('/admin-api/servers/metrics') return api.get('/admin-api/servers/metrics')
} }
export function getServerHealth(): Promise<ServerHealth[]> {
return api.get('/admin-api/servers/health')
}