This commit is contained in:
dengqichen 2025-12-17 09:54:23 +08:00
parent 8f09e63ea1
commit 8117b61fb1
6 changed files with 232 additions and 366 deletions

View File

@ -101,7 +101,7 @@ export const ApplicationCard: React.FC<ApplicationCardProps> = ({
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="runtime" className="text-xs"> <TabsTrigger value="runtime" className="text-xs">
<Activity className="h-3 w-3 mr-1" /> <Activity className="h-3 w-3 mr-1" />
</TabsTrigger> </TabsTrigger>
</TabsList> </TabsList>

View File

@ -11,14 +11,6 @@ export const DockerRuntimeStatus: React.FC<DockerRuntimeStatusProps> = ({
dockerServerName, dockerServerName,
dockerContainerName, dockerContainerName,
}) => { }) => {
// MOCK数据 - 后续替换为真实API
const mockStatus = {
status: 'running',
uptime: '2h 15m',
cpu: { used: 0.5, total: 2, percentage: 25 },
memory: { used: 512, total: 1024, percentage: 50 },
};
return ( return (
<div className="space-y-3"> <div className="space-y-3">
{/* 运行时类型 */} {/* 运行时类型 */}
@ -27,70 +19,16 @@ export const DockerRuntimeStatus: React.FC<DockerRuntimeStatusProps> = ({
Docker Docker
</Badge> </Badge>
{/* 运行状态 */} {/* 运行状态 - 研发中 */}
<div className="p-3 rounded-lg border bg-muted/30"> <div className="p-6 rounded-lg border bg-muted/30">
<div className="flex items-center gap-2 mb-3"> <div className="text-center space-y-3">
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" /> <div className="text-sm font-medium text-muted-foreground"></div>
<span className="text-sm font-medium"></span> <div className="space-y-2">
</div> <div className="h-3 bg-muted rounded animate-pulse" />
<div className="h-3 bg-muted rounded animate-pulse w-3/4 mx-auto" />
<div className="space-y-2 text-xs"> <div className="h-3 bg-muted rounded animate-pulse w-1/2 mx-auto" />
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">Running</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{mockStatus.uptime}</span>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground">CPU</span>
<span className="font-medium">{mockStatus.cpu.percentage}%</span>
</div>
<div className="w-full bg-muted rounded-full h-1.5">
<div
className="bg-blue-500 h-1.5 rounded-full transition-all"
style={{ width: `${mockStatus.cpu.percentage}%` }}
/>
</div>
<div className="text-[10px] text-muted-foreground text-right">
{mockStatus.cpu.used}/{mockStatus.cpu.total} cores
</div>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{mockStatus.memory.percentage}%</span>
</div>
<div className="w-full bg-muted rounded-full h-1.5">
<div
className="bg-green-500 h-1.5 rounded-full transition-all"
style={{ width: `${mockStatus.memory.percentage}%` }}
/>
</div>
<div className="text-[10px] text-muted-foreground text-right">
{mockStatus.memory.used}MB/{mockStatus.memory.total}MB
</div>
</div>
</div>
</div>
{/* 配置详情 */}
<div className="p-3 rounded-lg border bg-muted/30">
<div className="text-xs font-medium text-muted-foreground mb-2"></div>
<div className="space-y-2 text-xs">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{dockerServerName || '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{dockerContainerName || '-'}</span>
</div> </div>
<div className="text-xs text-muted-foreground pt-2">...</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -13,14 +13,6 @@ export const K8sRuntimeStatus: React.FC<K8sRuntimeStatusProps> = ({
k8sNamespaceName, k8sNamespaceName,
k8sDeploymentName, k8sDeploymentName,
}) => { }) => {
// MOCK数据 - 后续替换为真实API
const mockStatus = {
status: 'running',
podCount: { ready: 3, total: 3 },
cpu: { used: 0.9, total: 2, percentage: 45 },
memory: { used: 1.2, total: 2, percentage: 60 },
};
return ( return (
<div className="space-y-3"> <div className="space-y-3">
{/* 运行时类型 */} {/* 运行时类型 */}
@ -29,71 +21,16 @@ export const K8sRuntimeStatus: React.FC<K8sRuntimeStatusProps> = ({
Kubernetes Kubernetes
</Badge> </Badge>
{/* 运行状态 */} {/* 运行状态 - 研发中 */}
<div className="p-3 rounded-lg border bg-muted/30"> <div className="p-6 rounded-lg border bg-muted/30">
<div className="flex items-center gap-2 mb-3"> <div className="text-center space-y-3">
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" /> <div className="text-sm font-medium text-muted-foreground"></div>
<span className="text-sm font-medium"></span> <div className="space-y-2">
</div> <div className="h-3 bg-muted rounded animate-pulse" />
<div className="h-3 bg-muted rounded animate-pulse w-3/4 mx-auto" />
<div className="space-y-2 text-xs"> <div className="h-3 bg-muted rounded animate-pulse w-1/2 mx-auto" />
<div className="flex items-center justify-between">
<span className="text-muted-foreground">Pod</span>
<span className="font-medium">
{mockStatus.podCount.ready}/{mockStatus.podCount.total} Running
</span>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground">CPU</span>
<span className="font-medium">{mockStatus.cpu.percentage}%</span>
</div>
<div className="w-full bg-muted rounded-full h-1.5">
<div
className="bg-blue-500 h-1.5 rounded-full transition-all"
style={{ width: `${mockStatus.cpu.percentage}%` }}
/>
</div>
<div className="text-[10px] text-muted-foreground text-right">
{mockStatus.cpu.used}/{mockStatus.cpu.total} cores
</div>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{mockStatus.memory.percentage}%</span>
</div>
<div className="w-full bg-muted rounded-full h-1.5">
<div
className="bg-green-500 h-1.5 rounded-full transition-all"
style={{ width: `${mockStatus.memory.percentage}%` }}
/>
</div>
<div className="text-[10px] text-muted-foreground text-right">
{mockStatus.memory.used}GB/{mockStatus.memory.total}GB
</div>
</div>
</div>
</div>
{/* 配置详情 */}
<div className="p-3 rounded-lg border bg-muted/30">
<div className="text-xs font-medium text-muted-foreground mb-2"></div>
<div className="space-y-2 text-xs">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{k8sSystemName || '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{k8sNamespaceName || '-'}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{k8sDeploymentName || '-'}</span>
</div> </div>
<div className="text-xs text-muted-foreground pt-2">...</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -98,7 +98,7 @@ export const LogStreamViewer: React.FC<LogStreamViewerProps> = ({
return ( return (
<div <div
ref={scrollRef} ref={scrollRef}
className="h-full overflow-x-auto overflow-y-auto font-mono text-xs bg-gray-950 text-gray-100 p-4 rounded-md" className="h-full w-full overflow-x-auto overflow-y-auto font-mono text-xs bg-gray-950 text-gray-100 p-3 [&::-webkit-scrollbar]:w-2 [&::-webkit-scrollbar]:h-2 [&::-webkit-scrollbar-track]:bg-gray-900 [&::-webkit-scrollbar-thumb]:bg-gray-700 [&::-webkit-scrollbar-thumb]:rounded-full [&::-webkit-scrollbar-thumb]:hover:bg-gray-600"
> >
{logs.map((log) => ( {logs.map((log) => (
<div key={log.id} className="mb-1 whitespace-pre-wrap break-words"> <div key={log.id} className="mb-1 whitespace-pre-wrap break-words">

View File

@ -24,6 +24,8 @@ import {
Loader2, Loader2,
ScrollText, ScrollText,
Circle, Circle,
ChevronUp,
ChevronDown,
} from "lucide-react"; } from "lucide-react";
import { LogStreamViewer } from './LogStreamViewer'; import { LogStreamViewer } from './LogStreamViewer';
import { useLogStream } from '../hooks/useLogStream'; import { useLogStream } from '../hooks/useLogStream';
@ -53,6 +55,7 @@ export const LogViewerWindow: React.FC<LogViewerWindowProps> = ({
const [podName, setPodName] = useState(''); const [podName, setPodName] = useState('');
const [podNames, setPodNames] = useState<string[]>([]); const [podNames, setPodNames] = useState<string[]>([]);
const [loadingPods, setLoadingPods] = useState(false); const [loadingPods, setLoadingPods] = useState(false);
const [isControlBarCollapsed, setIsControlBarCollapsed] = useState(false);
const closeAllRef = useRef<(() => void) | null>(null); const closeAllRef = useRef<(() => void) | null>(null);
const onCloseReadyRef = useRef(onCloseReady); const onCloseReadyRef = useRef(onCloseReady);
@ -190,34 +193,32 @@ export const LogViewerWindow: React.FC<LogViewerWindowProps> = ({
} }
}; };
const runtimeConfig = getRuntimeIcon();
const RuntimeIcon = runtimeConfig.icon;
const getStatusIndicator = () => {
switch (status) {
case LogStreamStatus.CONNECTING:
return { color: 'text-yellow-500', label: '连接中' };
case LogStreamStatus.CONNECTED:
return { color: 'text-blue-500', label: '已连接' };
case LogStreamStatus.STREAMING:
return { color: 'text-green-500', label: '流式传输中' };
case LogStreamStatus.PAUSED:
return { color: 'text-orange-500', label: '已暂停' };
case LogStreamStatus.STOPPED:
return { color: 'text-gray-500', label: '已停止' };
case LogStreamStatus.ERROR:
return { color: 'text-red-500', label: '错误' };
default:
return { color: 'text-gray-500', label: '未连接' };
}
};
const statusIndicator = getStatusIndicator();
// 构建动态标题 // 构建动态标题
const buildTitle = useCallback(() => { const buildTitle = useCallback(() => {
const runtimeConfig = getRuntimeIcon();
const RuntimeIcon = runtimeConfig.icon; const RuntimeIcon = runtimeConfig.icon;
const statusColor = statusIndicator.color;
let statusColor = 'text-gray-500';
switch (status) {
case LogStreamStatus.CONNECTING:
statusColor = 'text-yellow-500';
break;
case LogStreamStatus.CONNECTED:
statusColor = 'text-blue-500';
break;
case LogStreamStatus.STREAMING:
statusColor = 'text-green-500';
break;
case LogStreamStatus.PAUSED:
statusColor = 'text-orange-500';
break;
case LogStreamStatus.STOPPED:
statusColor = 'text-gray-500';
break;
case LogStreamStatus.ERROR:
statusColor = 'text-red-500';
break;
}
return ( return (
<div className="flex items-center gap-3"> <div className="flex items-center gap-3">
@ -238,14 +239,15 @@ export const LogViewerWindow: React.FC<LogViewerWindowProps> = ({
<span className="text-sm font-normal"></span> <span className="text-sm font-normal"></span>
</div> </div>
); );
}, [app.applicationName, runtimeConfig, statusIndicator.color]); }, [app.applicationName, app.runtimeType, status]);
// 状态变化时更新标题 // 状态变化时更新标题
useEffect(() => { useEffect(() => {
console.log('[LogViewerWindow] 更新标题, status:', status, 'updateWindowTitleRef:', !!updateWindowTitleRef.current);
if (updateWindowTitleRef.current) { if (updateWindowTitleRef.current) {
updateWindowTitleRef.current(buildTitle()); updateWindowTitleRef.current(buildTitle());
} }
}, [buildTitle]); }, [buildTitle, status]);
const handleRestart = () => { const handleRestart = () => {
clearLogs(); clearLogs();
@ -265,145 +267,192 @@ export const LogViewerWindow: React.FC<LogViewerWindowProps> = ({
return ( return (
<div className="flex flex-col h-full w-full"> <div className="flex flex-col h-full w-full">
{/* 紧凑控制栏 */} {/* 紧凑控制栏 - 收缩时完全隐藏 */}
<div className="px-3 py-1.5 border-b flex-shrink-0 bg-muted/20"> <div className={isControlBarCollapsed ? 'hidden' : 'flex-shrink-0 border-b bg-muted/30'}>
<div className="flex items-center justify-end gap-2"> <div className="px-3 py-1.5">
<Input <div className="flex items-center justify-between gap-2">
type="number" <TooltipProvider>
value={lines} {/* 折叠/展开按钮 */}
onChange={(e) => setLines(Number(e.target.value))}
min={10}
max={1000}
placeholder="行数"
className="h-7 w-16 text-xs"
/>
{app.runtimeType === 'K8S' && (
<>
{loadingPods ? (
<div className="h-7 w-40 flex items-center justify-center border rounded-md bg-background">
<Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
</div>
) : podNames.length > 0 ? (
<Select value={podName} onValueChange={setPodName}>
<SelectTrigger className="h-7 w-40 text-xs">
<SelectValue placeholder="选择Pod" />
</SelectTrigger>
<SelectContent>
{podNames.map((name) => (
<SelectItem key={name} value={name}>
{name}
</SelectItem>
))}
</SelectContent>
</Select>
) : (
<Input
value={podName}
onChange={(e) => setPodName(e.target.value)}
placeholder="无可用Pod"
className="h-7 w-40 text-xs"
disabled
/>
)}
</>
)}
<TooltipProvider>
<div className="flex gap-1">
{/* 启动/恢复/重试按钮 */}
{(status === LogStreamStatus.DISCONNECTED ||
status === LogStreamStatus.CONNECTED ||
status === LogStreamStatus.ERROR) && (
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="outline"
onClick={handleRestart}
className="h-7 w-7 p-0"
>
<Play className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent>
{status === LogStreamStatus.ERROR ? '重试' : '启动'}
</TooltipContent>
</Tooltip>
)}
{/* 连接中按钮 */}
{status === LogStreamStatus.CONNECTING && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" disabled className="h-7 w-7 p-0">
<Loader2 className="h-3 w-3 animate-spin" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 恢复按钮(暂停状态) */}
{status === LogStreamStatus.PAUSED && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={resume} className="h-7 w-7 p-0">
<Play className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 暂停按钮(流式传输中) */}
{status === LogStreamStatus.STREAMING && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={pause} className="h-7 w-7 p-0">
<Pause className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 停止按钮 */}
{(status === LogStreamStatus.CONNECTING ||
status === LogStreamStatus.STREAMING ||
status === LogStreamStatus.PAUSED) && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={stop} className="h-7 w-7 p-0">
<Square className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 清空按钮 */}
<Tooltip> <Tooltip>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
size="sm" size="sm"
variant="outline" variant="outline"
onClick={clearLogs} onClick={() => setIsControlBarCollapsed(!isControlBarCollapsed)}
disabled={status === LogStreamStatus.CONNECTING} className={`p-0 transition-all ${isControlBarCollapsed ? 'h-5 w-5' : 'h-7 w-7'}`}
className="h-7 w-7 p-0"
> >
<Trash2 className="h-3 w-3" /> {isControlBarCollapsed ? (
<ChevronDown className="h-3 w-3" />
) : (
<ChevronUp className="h-4 w-4" />
)}
</Button> </Button>
</TooltipTrigger> </TooltipTrigger>
<TooltipContent></TooltipContent> <TooltipContent>
{isControlBarCollapsed ? '展开控制栏' : '折叠控制栏'}
</TooltipContent>
</Tooltip> </Tooltip>
</div>
</TooltipProvider> {/* 控制按钮区域 - 折叠时隐藏 */}
{!isControlBarCollapsed && (
<div className="flex items-center gap-2">
<Input
type="number"
value={lines}
onChange={(e) => setLines(Number(e.target.value))}
min={10}
max={1000}
placeholder="行数"
className="h-7 w-16 text-xs"
/>
{app.runtimeType === 'K8S' && (
<>
{loadingPods ? (
<div className="h-7 w-40 flex items-center justify-center border rounded-md bg-background">
<Loader2 className="h-3 w-3 animate-spin text-muted-foreground" />
</div>
) : podNames.length > 0 ? (
<Select value={podName} onValueChange={setPodName}>
<SelectTrigger className="h-7 w-40 text-xs">
<SelectValue placeholder="选择Pod" />
</SelectTrigger>
<SelectContent>
{podNames.map((name) => (
<SelectItem key={name} value={name}>
{name}
</SelectItem>
))}
</SelectContent>
</Select>
) : (
<Input
value={podName}
onChange={(e) => setPodName(e.target.value)}
placeholder="无可用Pod"
className="h-7 w-40 text-xs"
disabled
/>
)}
</>
)}
<div className="flex gap-1">
{/* 启动/恢复/重试按钮 */}
{(status === LogStreamStatus.DISCONNECTED ||
status === LogStreamStatus.CONNECTED ||
status === LogStreamStatus.ERROR) && (
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="outline"
onClick={handleRestart}
className="h-7 w-7 p-0"
>
<Play className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent>
{status === LogStreamStatus.ERROR ? '重试' : '启动'}
</TooltipContent>
</Tooltip>
)}
{/* 连接中按钮 */}
{status === LogStreamStatus.CONNECTING && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" disabled className="h-7 w-7 p-0">
<Loader2 className="h-3 w-3 animate-spin" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 恢复按钮(暂停状态) */}
{status === LogStreamStatus.PAUSED && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={resume} className="h-7 w-7 p-0">
<Play className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 暂停按钮(流式传输中) */}
{status === LogStreamStatus.STREAMING && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={pause} className="h-7 w-7 p-0">
<Pause className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 停止按钮 */}
{(status === LogStreamStatus.CONNECTING ||
status === LogStreamStatus.STREAMING ||
status === LogStreamStatus.PAUSED) && (
<Tooltip>
<TooltipTrigger asChild>
<Button size="sm" variant="outline" onClick={stop} className="h-7 w-7 p-0">
<Square className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
)}
{/* 清空按钮 */}
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="outline"
onClick={clearLogs}
disabled={status === LogStreamStatus.CONNECTING}
className="h-7 w-7 p-0"
>
<Trash2 className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
</div>
</div>
)}
</TooltipProvider>
</div>
</div> </div>
</div> </div>
{/* 日志显示区域 */} {/* 日志显示区域 - 无padding直接填充 */}
<div className="flex-1 overflow-hidden"> <div className="flex-1 w-full overflow-hidden relative">
{/* 悬浮展开按钮 - 收缩时显示 */}
{isControlBarCollapsed && (
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="outline"
onClick={() => setIsControlBarCollapsed(false)}
className="absolute top-2 right-2 z-10 h-6 w-6 p-0 bg-background/80 backdrop-blur-sm hover:bg-background"
>
<ChevronDown className="h-3 w-3" />
</Button>
</TooltipTrigger>
<TooltipContent></TooltipContent>
</Tooltip>
</TooltipProvider>
)}
<LogStreamViewer <LogStreamViewer
logs={logs} logs={logs}
status={status} status={status}

View File

@ -11,15 +11,6 @@ export const ServerRuntimeStatus: React.FC<ServerRuntimeStatusProps> = ({
serverName, serverName,
logQueryCommand, logQueryCommand,
}) => { }) => {
// MOCK数据 - 后续替换为真实API
const mockStatus = {
status: 'running',
pid: 12345,
uptime: '2h 15m',
cpu: { percentage: 15 },
memory: { used: 256 },
};
return ( return (
<div className="space-y-3"> <div className="space-y-3">
{/* 运行时类型 */} {/* 运行时类型 */}
@ -28,65 +19,16 @@ export const ServerRuntimeStatus: React.FC<ServerRuntimeStatusProps> = ({
</Badge> </Badge>
{/* 运行状态 */} {/* 运行状态 - 研发中 */}
<div className="p-3 rounded-lg border bg-muted/30"> <div className="p-6 rounded-lg border bg-muted/30">
<div className="flex items-center gap-2 mb-3"> <div className="text-center space-y-3">
<div className="w-2 h-2 rounded-full bg-green-500 animate-pulse" /> <div className="text-sm font-medium text-muted-foreground"></div>
<span className="text-sm font-medium"></span> <div className="space-y-2">
</div> <div className="h-3 bg-muted rounded animate-pulse" />
<div className="h-3 bg-muted rounded animate-pulse w-3/4 mx-auto" />
<div className="space-y-2 text-xs"> <div className="h-3 bg-muted rounded animate-pulse w-1/2 mx-auto" />
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">Running</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground">PID</span>
<span className="font-medium font-mono">{mockStatus.pid}</span>
</div>
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{mockStatus.uptime}</span>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground">CPU</span>
<span className="font-medium">{mockStatus.cpu.percentage}%</span>
</div>
<div className="w-full bg-muted rounded-full h-1.5">
<div
className="bg-blue-500 h-1.5 rounded-full transition-all"
style={{ width: `${mockStatus.cpu.percentage}%` }}
/>
</div>
</div>
<div className="space-y-1">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{mockStatus.memory.used}MB</span>
</div>
</div>
</div>
</div>
{/* 配置详情 */}
<div className="p-3 rounded-lg border bg-muted/30">
<div className="text-xs font-medium text-muted-foreground mb-2"></div>
<div className="space-y-2 text-xs">
<div className="flex items-center justify-between">
<span className="text-muted-foreground"></span>
<span className="font-medium">{serverName || '-'}</span>
</div>
<div className="flex flex-col gap-1">
<span className="text-muted-foreground"></span>
<code className="font-mono text-[10px] bg-muted px-2 py-1 rounded break-all">
{logQueryCommand || '-'}
</code>
</div> </div>
<div className="text-xs text-muted-foreground pt-2">...</div>
</div> </div>
</div> </div>
</div> </div>