@@ -1,8 +1,8 @@
import { App , Button , Progress , Skeleton , Switch } from "antd" ;
import { Activity , AlertTriangle , Cpu , Database , Gauge , HardDrive , MemoryStick , RefreshCw , Server , ShieldCheck , Trash2 , Wifi } from "lucide-react" ;
import { App , Button , InputNumber , Progress , Skeleton , Switch } from "antd" ;
import { Activity , AlertTriangle , Bot , Cpu , Database , Gauge , HardDrive , MemoryStick , RefreshCw , Server , ShieldCheck , Trash2 , Wifi } from "lucide-react" ;
import { useCallback , useEffect , useRef , useState , type ReactNode } from "react" ;
import { clearRuntimeCache , getSystemPerformance , type SystemPerformance } from "@/services/api/system-performance" ;
import { clearRuntimeCache , getSystemPerformance , updateAgentSessionLimit , type SystemPerformance } from "@/services/api/system-performance" ;
import { AdminPageFrame } from "../components/admin-shell" ;
import { AdminStatusBadge , SettingsSectionCard } from "../components/admin-ui" ;
@@ -61,6 +61,8 @@ export default function SystemPerformancePage() {
const [ loading , setLoading ] = useState ( true ) ;
const [ refreshing , setRefreshing ] = useState ( false ) ;
const [ clearing , setClearing ] = useState ( false ) ;
const [ savingAgentLimit , setSavingAgentLimit ] = useState ( false ) ;
const [ agentLimitDraft , setAgentLimitDraft ] = useState < number | null > ( null ) ;
const [ autoRefresh , setAutoRefresh ] = useState ( true ) ;
const [ loadError , setLoadError ] = useState ( "" ) ;
const mountedRef = useRef ( true ) ;
@@ -149,7 +151,7 @@ export default function SystemPerformancePage() {
return (
< AdminPageFrame
title = "系统性能"
description = "紧凑查看主机、数据库、Redis 和安全运行时缓存;敏感连接信息不会在此展示。"
description = "紧凑查看主机、数据库、Redis、画布 Agent 和安全运行时缓存;敏感连接信息不会在此展示。"
scroll
actions = { < > < label className = "admin-performance-auto" > < Switch size = "small" checked = { autoRefresh } onChange = { setAutoRefresh } / > < span > 15 秒 刷 新 < / span > < / label > < Button icon = { < RefreshCw className = "size-4" / > } loading = { refreshing } onClick = { ( ) = > void load ( false ) } > 刷 新 < / Button > < / > }
>
@@ -213,6 +215,30 @@ export default function SystemPerformancePage() {
< / div >
< / div >
{ ( data . agents || [ ] ) . map ( ( agent ) = > {
const draft = agentLimitDraft ? ? agent . configuredLimit ;
return < SettingsSectionCard key = { agent . id } layout = "stacked" icon = { < Bot className = "size-4" / > } title = "画布 Agent 服务" description = "同时进行中的对话占用一个名额。审批等待不占用。降低上限不会中断已经开始的对话,也不会在这台机器上再启动容器。" status = { { label : agent.healthy ? "服务可连接" : "服务不可达" , color : agent.healthy ? "success" : "error" } } footer = { < > < span className = "admin-performance-cache-note" > < Gauge className = "size-3.5" / > 新 安 装 默 认 30 , 一 般 不 用 再 改 < / span > < span style = { { display : "flex" , gap : 8 , alignItems : "center" } } > < InputNumber min = { 1 } max = { 64 } precision = { 0 } value = { draft } onChange = { ( value ) = > setAgentLimitDraft ( typeof value === "number" ? value : draft ) } / > < Button type = "primary" loading = { savingAgentLimit } disabled = { draft === agent . configuredLimit } onClick = { ( ) = > {
setSavingAgentLimit ( true ) ;
void updateAgentSessionLimit ( draft ) . then ( ( ) = > {
message . success ( "已应用 Agent 同时对话上限" ) ;
setAgentLimitDraft ( null ) ;
return load ( false ) ;
} ) . catch ( ( error : unknown ) = > {
message . error ( error instanceof Error ? error . message : "保存 Agent 上限失败" ) ;
} ) . finally ( ( ) = > setSavingAgentLimit ( false ) ) ;
} } > 保 存 上 限 < / Button > < / span > < / > } >
< FactGrid >
< Fact label = "服务" value = { agent . name } / >
< Fact label = "运行位置" value = { agent . mode === "remote" ? "独立服务" : "后端进程" } / >
< Fact label = "地址" value = { agent . endpoint } mono / >
< Fact label = "进行中 / 上限" value = { ` ${ formatNumber ( agent . active ) } / ${ formatNumber ( agent . limit ) } ` } / >
< Fact label = "排队" value = { formatNumber ( agent . queued ) } / >
< Fact label = "已保存上限" value = { formatNumber ( agent . configuredLimit ) } / >
< Fact label = "说明" value = { agent . statusMessage || "同一台机器提高上限即可,不需要再启动容器。" } / >
< / FactGrid >
< / SettingsSectionCard > ;
} ) }
< SettingsSectionCard layout = "stacked" icon = { < ShieldCheck className = "size-4" / > } title = "缓存维护" description = "只清理可安全重建的运行时状态,保留业务数据与活动并发租约。" status = { < AdminStatusBadge label = "白名单清理" tone = "success" / > } footer = { < > < span className = "admin-performance-cache-note" > < Gauge className = "size-3.5" / > 清 理 后 频 控 与 线 路 健 康 状 态 会 重 新 计 算 < / span > < Button danger icon = { < Trash2 className = "size-4" / > } loading = { clearing } onClick = { requestClear } > 清 理 运 行 时 缓 存 < / Button > < / > } >
< div className = "admin-performance-cache-groups" >
{ ( data ? . redis . cacheGroups || [ ] ) . map ( ( group ) = > < div key = { group . id } > < span > { group . label } < / span > < strong > { formatNumber ( group . keys ) } < / strong > < small > keys < / small > < / div > ) }