import { useEffect, useMemo, useState } from 'react' import api from '@/services/api' interface ProviderRow { account_id: number provider: string label: string usage_pct: number | null status: string error?: string | null fetched_at?: string | null reset_at?: string | null window?: string | null used?: number | null limit?: number | null } interface ServerRow { server_id: number identifier: string display_name: string online: boolean openclaw_version?: string | null cpu_pct?: number | null mem_pct?: number | null disk_pct?: number | null swap_pct?: number | null agents: Array<{ id?: string; name?: string; status?: string }> last_seen_at?: string | null } interface OverviewData { issues: { total_issues: number new_issues_24h: number processed_issues_24h: number computed_at: string } providers: ProviderRow[] servers: ServerRow[] generated_at: string } interface AdminUser { id: number is_admin: boolean } interface ProviderAccountItem { id: number provider: string label: string is_enabled: boolean credential_masked: string } interface ServerItem { server_id: number identifier: string display_name: string online: boolean } export default function MonitorPage() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [isAdmin, setIsAdmin] = useState(false) const [providerAccounts, setProviderAccounts] = useState([]) const [servers, setServers] = useState([]) const [providerForm, setProviderForm] = useState({ provider: 'openai', label: '', credential: '' }) const [providerTestMsg, setProviderTestMsg] = useState('') const [serverForm, setServerForm] = useState({ identifier: '', display_name: '' }) const canAdmin = useMemo(() => !!localStorage.getItem('token') && isAdmin, [isAdmin]) const load = async () => { try { const res = await api.get('/monitor/public/overview') setData(res.data) const token = localStorage.getItem('token') if (token) { try { const me = await api.get('/auth/me') setIsAdmin(!!me.data.is_admin) } catch { setIsAdmin(false) } } else { setIsAdmin(false) } } finally { setLoading(false) } } const loadAdminData = async () => { if (!canAdmin) return const [p, s] = await Promise.all([ api.get('/monitor/admin/providers/accounts'), api.get('/monitor/admin/servers'), ]) setProviderAccounts(p.data) setServers(s.data) } useEffect(() => { load() const t = setInterval(load, 30000) return () => clearInterval(t) }, []) useEffect(() => { loadAdminData() }, [canAdmin]) const testProvider = async () => { const r = await api.post<{ ok: boolean; message: string }>('/monitor/admin/providers/test', { provider: providerForm.provider, credential: providerForm.credential, }) setProviderTestMsg((r.data.ok ? '✅ ' : '❌ ') + r.data.message) } const addProvider = async () => { await api.post('/monitor/admin/providers/accounts', providerForm) setProviderForm({ ...providerForm, label: '', credential: '' }) await loadAdminData() } const deleteProvider = async (id: number) => { await api.delete('/monitor/admin/providers/accounts/' + id) await loadAdminData() } const addServer = async () => { await api.post('/monitor/admin/servers', serverForm) setServerForm({ identifier: '', display_name: '' }) await loadAdminData() } const deleteServer = async (id: number) => { await api.delete('/monitor/admin/servers/' + id) await loadAdminData() } const createChallenge = async (id: number) => { const r = await api.post<{ identifier: string; challenge_uuid: string; expires_at: string }>('/monitor/admin/servers/' + id + '/challenge') alert('identifier=' + r.data.identifier + ' | challenge_uuid=' + r.data.challenge_uuid + ' | expires_at=' + r.data.expires_at) } if (loading) return
Monitor loading...
if (!data) return
Monitor load failed
return (

📡 Monitor

{data.issues.total_issues} 总 Issues
{data.issues.new_issues_24h} 24小时新增
{data.issues.processed_issues_24h} 24小时已处理

Provider Usage

更新于 {data.generated_at}
{data.providers.length === 0 ?

暂无 provider 账号

: ( {data.providers.map((p) => ( ))}
Provider Label Usage Window Reset Status Updated
{p.provider} {p.label} {p.usage_pct !== null ? p.usage_pct + '%' : '-'} {p.window || '-'} {p.reset_at || '-'} {p.status} {p.fetched_at || '-'}
)}

服务器监测

{data.servers.length === 0 ?

暂无监测服务器

: (
{data.servers.map((s) => (
{s.display_name}
{s.identifier}
{s.online ? 'online' : 'offline'}
CPU {s.cpu_pct ?? '-'}% · MEM {s.mem_pct ?? '-'}% · DISK {s.disk_pct ?? '-'}% · SWAP {s.swap_pct ?? '-'}%
OpenClaw: {s.openclaw_version || '-'}
Agents: {s.agents?.length || 0}
))}
)}
{canAdmin && (

Admin 管理

Provider 账号

setProviderForm({ ...providerForm, label: e.target.value })} /> setProviderForm({ ...providerForm, credential: e.target.value })} />
{providerTestMsg &&

{providerTestMsg}

}
    {providerAccounts.map((p) => (
  • {p.provider} / {p.label} / {p.credential_masked}
  • ))}

服务器

setServerForm({ ...serverForm, identifier: e.target.value })} /> setServerForm({ ...serverForm, display_name: e.target.value })} />
    {servers.map((s) => (
  • {s.display_name} ({s.identifier})
  • ))}
)}
) }