mirror of
https://github.com/YspCoder/clawgo.git
synced 2026-04-13 05:37:29 +08:00
webui i18n: localize EKG panel labels and actions (zh/en)
This commit is contained in:
@@ -20,6 +20,14 @@ const resources = {
|
||||
sidebarOps: 'Operations',
|
||||
sidebarInsights: 'Insights',
|
||||
ekg: 'EKG',
|
||||
ekgEscalations: 'Escalations',
|
||||
ekgSourceStats: 'Source Stats',
|
||||
ekgChannelStats: 'Channel Stats',
|
||||
ekgTopProvidersWorkload: 'Top Providers (workload)',
|
||||
ekgTopProvidersAll: 'Top Providers (all)',
|
||||
ekgTopErrsigWorkload: 'Top Error Signatures (workload)',
|
||||
ekgTopErrsigHeartbeat: 'Top Error Signatures (heartbeat)',
|
||||
ekgTopErrsigAll: 'Top Error Signatures (all)',
|
||||
taskList: 'Task List',
|
||||
taskDetail: 'Task Detail',
|
||||
taskQueue: 'Task Queue',
|
||||
@@ -195,6 +203,14 @@ const resources = {
|
||||
sidebarOps: '运维',
|
||||
sidebarInsights: '洞察',
|
||||
ekg: 'EKG',
|
||||
ekgEscalations: '升级拦截次数',
|
||||
ekgSourceStats: '来源统计',
|
||||
ekgChannelStats: '通道统计',
|
||||
ekgTopProvidersWorkload: 'Top Providers(业务负载)',
|
||||
ekgTopProvidersAll: 'Top Providers(全量)',
|
||||
ekgTopErrsigWorkload: 'Top 错误签名(业务负载)',
|
||||
ekgTopErrsigHeartbeat: 'Top 错误签名(心跳)',
|
||||
ekgTopErrsigAll: 'Top 错误签名(全量)',
|
||||
taskList: '任务列表',
|
||||
taskDetail: '任务详情',
|
||||
taskQueue: '任务队列',
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useAppContext } from '../context/AppContext';
|
||||
|
||||
type EKGKV = { key?: string; score?: number; count?: number };
|
||||
|
||||
const EKG: React.FC = () => {
|
||||
const { t } = useTranslation();
|
||||
const { q } = useAppContext();
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [ekgWindow, setEkgWindow] = useState<'6h' | '24h' | '7d'>(() => {
|
||||
@@ -56,47 +58,47 @@ const EKG: React.FC = () => {
|
||||
<option value="24h">24h</option>
|
||||
<option value="7d">7d</option>
|
||||
</select>
|
||||
<button onClick={fetchData} className="px-3 py-1.5 rounded-lg bg-zinc-800 hover:bg-zinc-700 text-sm">{loading ? 'Loading...' : 'Refresh'}</button>
|
||||
<button onClick={fetchData} className="px-3 py-1.5 rounded-lg bg-zinc-800 hover:bg-zinc-700 text-sm">{loading ? t('loading') : t('refresh')}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-3 text-xs">
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3">
|
||||
<div className="text-zinc-500 mb-1">Escalations</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgEscalations')}</div>
|
||||
<div className="text-zinc-100 text-2xl font-semibold">{escalationCount}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3">
|
||||
<div className="text-zinc-500 mb-1">Source Stats</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgSourceStats')}</div>
|
||||
<div className="space-y-1">{Object.keys(sourceStats).length === 0 ? <div className="text-zinc-500">-</div> : Object.entries(sourceStats).map(([k,v]) => <div key={k} className="text-zinc-200">{k}: <span className="text-zinc-400">{v}</span></div>)}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3">
|
||||
<div className="text-zinc-500 mb-1">Channel Stats</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgChannelStats')}</div>
|
||||
<div className="space-y-1">{Object.keys(channelStats).length === 0 ? <div className="text-zinc-500">-</div> : Object.entries(channelStats).map(([k,v]) => <div key={k} className="text-zinc-200">{k}: <span className="text-zinc-400">{v}</span></div>)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 xl:grid-cols-2 gap-3 text-xs">
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3">
|
||||
<div className="text-zinc-500 mb-1">Top Providers (workload)</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgTopProvidersWorkload')}</div>
|
||||
<div className="space-y-1">{providerTopWorkload.length === 0 ? <div className="text-zinc-500">-</div> : providerTopWorkload.map((x,i)=><div key={i} className="text-zinc-200">{x.key} <span className="text-zinc-500">({Number(x.score||0).toFixed(2)})</span></div>)}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3">
|
||||
<div className="text-zinc-500 mb-1">Top Providers (all)</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgTopProvidersAll')}</div>
|
||||
<div className="space-y-1">{providerTop.length === 0 ? <div className="text-zinc-500">-</div> : providerTop.map((x,i)=><div key={i} className="text-zinc-200">{x.key} <span className="text-zinc-500">({Number(x.score||0).toFixed(2)})</span></div>)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 xl:grid-cols-3 gap-3 text-xs flex-1 min-h-0">
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3 overflow-y-auto">
|
||||
<div className="text-zinc-500 mb-1">Top Error Signatures (workload)</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgTopErrsigWorkload')}</div>
|
||||
<div className="space-y-1">{errsigTopWorkload.length === 0 ? <div className="text-zinc-500">-</div> : errsigTopWorkload.map((x,i)=><div key={i} className="text-zinc-200 truncate">{x.key} <span className="text-zinc-500">(x{x.count||0})</span></div>)}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3 overflow-y-auto">
|
||||
<div className="text-zinc-500 mb-1">Top Error Signatures (heartbeat)</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgTopErrsigHeartbeat')}</div>
|
||||
<div className="space-y-1">{errsigTopHeartbeat.length === 0 ? <div className="text-zinc-500">-</div> : errsigTopHeartbeat.map((x,i)=><div key={i} className="text-zinc-200 truncate">{x.key} <span className="text-zinc-500">(x{x.count||0})</span></div>)}</div>
|
||||
</div>
|
||||
<div className="rounded-xl border border-zinc-800 bg-zinc-900/40 p-3 overflow-y-auto">
|
||||
<div className="text-zinc-500 mb-1">Top Error Signatures (all)</div>
|
||||
<div className="text-zinc-500 mb-1">{t('ekgTopErrsigAll')}</div>
|
||||
<div className="space-y-1">{errsigTop.length === 0 ? <div className="text-zinc-500">-</div> : errsigTop.map((x,i)=><div key={i} className="text-zinc-200 truncate">{x.key} <span className="text-zinc-500">(x{x.count||0})</span></div>)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user