From f0f9cc87a15faed9348a51d4949446eecdb7048e Mon Sep 17 00:00:00 2001 From: OG T Date: Thu, 2 Apr 2026 13:55:29 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20monitoring=20=E9=A0=81=20QA=20?= =?UTF-8?q?=E4=BF=AE=E5=BE=A9=20=E2=80=94=20NAN%=20+=20HostGrid=20+=20i18n?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - HostGrid 接 useHosts() SSE 數據(不再傳空陣列) - HealthSummary NAN% 修復:total_count=0 時顯示 0% 而非 NaN% - 8 處硬編碼中文改 i18n (正常/警告/異常/黃金指標/主機狀態/服務清單/表頭) - 新增 monitoring namespace i18n keys (11 keys × 2 langs) Co-Authored-By: Claude Opus 4.6 (1M context) --- apps/web/messages/en.json | 13 ++++++ apps/web/messages/zh-TW.json | 13 ++++++ apps/web/src/app/[locale]/monitoring/page.tsx | 44 ++++++++++--------- 3 files changed, 50 insertions(+), 20 deletions(-) diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json index b0a9baa2..b2affdec 100644 --- a/apps/web/messages/en.json +++ b/apps/web/messages/en.json @@ -708,5 +708,18 @@ "entries": "entries", "empty": "No knowledge entries yet", "emptyDescription": "Entries will be auto-extracted from incidents, or you can create them manually" + }, + "monitoring": { + "healthy": "Healthy", + "warning": "Warning", + "critical": "Critical", + "goldMetrics": "GOLD METRICS", + "hostStatus": "HOST STATUS (FOUR-HOST ARCHITECTURE)", + "serviceList": "SERVICE LIST", + "serviceName": "Service", + "status": "Status", + "latency": "Latency", + "uptime": "Uptime", + "lastCheck": "Last Check" } } \ No newline at end of file diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json index d6af0f7a..09d70909 100644 --- a/apps/web/messages/zh-TW.json +++ b/apps/web/messages/zh-TW.json @@ -709,5 +709,18 @@ "entries": "筆", "empty": "尚未建立任何知識條目", "emptyDescription": "知識庫將自動從 Incident 中萃取案例,你也可以手動新增" + }, + "monitoring": { + "healthy": "正常", + "warning": "警告", + "critical": "異常", + "goldMetrics": "黃金指標 (GOLD METRICS)", + "hostStatus": "主機狀態 (FOUR-HOST ARCHITECTURE)", + "serviceList": "服務清單", + "serviceName": "服務名稱", + "status": "狀態", + "latency": "延遲", + "uptime": "可用率", + "lastCheck": "最後檢查" } } \ No newline at end of file diff --git a/apps/web/src/app/[locale]/monitoring/page.tsx b/apps/web/src/app/[locale]/monitoring/page.tsx index cf2bdf38..51a83430 100644 --- a/apps/web/src/app/[locale]/monitoring/page.tsx +++ b/apps/web/src/app/[locale]/monitoring/page.tsx @@ -4,18 +4,16 @@ * Monitoring Page - 服務監控 * =========================== * 黃金指標 (Gold Metrics) + 四主機狀態 + 服務健康 - * 資料來源: - * GET /api/v1/metrics/gold - * GET /api/v1/dashboard/hosts - * GET /api/v1/dashboard (SSE 快照) * * @created 2026-04-01 ogt + * @updated 2026-04-02 Claude Code — QA 修復: i18n + useHosts + NaN */ import { useState, useEffect, useCallback, useRef } from 'react' import { useTranslations } from 'next-intl' import { AppLayout } from '@/components/layout' import { useGlobalPulseMetrics } from '@/hooks/useGlobalPulseMetrics' +import { useHosts } from '@/stores/dashboard.store' import { GlobalPulseChart } from '@/components/charts/global-pulse-chart' import { HostGrid } from '@/components/infra/host-grid' import { cn } from '@/lib/utils' @@ -74,21 +72,23 @@ const STATUS_BADGE = { // Sub-component: Health Summary // ============================================================================= -function HealthSummary({ data }: { data: DashboardResponse }) { - const total = data.total_count || 1 +function HealthSummary({ data, t }: { data: DashboardResponse; t: (key: string) => string }) { + const total = data.total_count || 0 + const pct = (count: number) => total > 0 ? `${Math.round(count / total * 100)}%` : '0%' + return (
{[ - { label: '正常', count: data.healthy_count, color: 'text-status-healthy', bg: 'bg-status-healthy/10' }, - { label: '警告', count: data.warning_count, color: 'text-status-warning', bg: 'bg-status-warning/10' }, - { label: '異常', count: data.critical_count, color: 'text-status-critical', bg: 'bg-status-critical/10' }, + { label: t('healthy'), count: data.healthy_count, color: 'text-status-healthy', bg: 'bg-status-healthy/10' }, + { label: t('warning'), count: data.warning_count, color: 'text-status-warning', bg: 'bg-status-warning/10' }, + { label: t('critical'), count: data.critical_count, color: 'text-status-critical', bg: 'bg-status-critical/10' }, ].map(item => (
{item.count}
- {item.label} · {Math.round(item.count / total * 100)}% + {item.label} · {pct(item.count)}
))} @@ -101,7 +101,11 @@ function HealthSummary({ data }: { data: DashboardResponse }) { // ============================================================================= export default function MonitoringPage({ params }: { params: { locale: string } }) { - const t = useTranslations() + const t = useTranslations('monitoring') + const tNav = useTranslations('nav') + const tCommon = useTranslations('common') + const tAlerts = useTranslations('alerts') + const hosts = useHosts() const { metrics, isLoading: metricsLoading } = useGlobalPulseMetrics({ pollInterval: 30000, @@ -153,10 +157,10 @@ export default function MonitoringPage({ params }: { params: { locale: string }

- {t('nav.monitoring')} + {tNav('monitoring')}

- {t('alerts.autoRefresh', { seconds: 30 })} + {tAlerts('autoRefresh', { seconds: 30 })}

@@ -183,12 +187,12 @@ export default function MonitoringPage({ params }: { params: { locale: string } )} {/* Health Summary */} - {dashboard && } + {dashboard && } {/* Gold Metrics */}

- 黃金指標 (Gold Metrics) + {t('goldMetrics')}

{metricsLoading && metrics.length === 0 ? (
@@ -202,22 +206,22 @@ export default function MonitoringPage({ params }: { params: { locale: string } {/* Host Grid */}

- 主機狀態 (Four-Host Architecture) + {t('hostStatus')}

- +
{/* Service Table */} {dashboard && dashboard.services && dashboard.services.length > 0 && (

- 服務清單 + {t('serviceList')}

- {['服務名稱', '狀態', '延遲', '可用率', '最後檢查'].map(h => ( + {[t('serviceName'), t('status'), t('latency'), t('uptime'), t('lastCheck')].map(h => (
{h}