import { Activity, AlertTriangle, Clock, Cpu, Layers, Settings2, Wifi } from "lucide-react"; import React, { useEffect, useState, useCallback } from "react"; import { Button } from "../ui/button"; import { Switch } from "../ui/switch"; import { Input } from "../ui/input"; import { Badge } from "../ui/badge"; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from "../ui/select"; import { Label } from "../ui/label"; import { inspectionDeviceApi, inspectionCatalogApi, inspectionExecApi, type DeviceCatalog, type DeviceExtension, type DeviceTierInfo, type DeviceTier, } from "../../infrastructure/inspection/inspectionApi"; import { toast } from "../ui/toast"; import { HostDetailsSection } from "../host-details"; interface HostInspectionSectionProps { hostId: string; hostLabel: string; host: any; keys: any[]; } export function HostInspectionSection({ hostId, hostLabel, host, keys }: HostInspectionSectionProps) { const [catalogs, setCatalogs] = useState([]); const [tiers, setTiers] = useState([]); const [extension, setExtension] = useState(null); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); // 本地编辑状态 const [enabled, setEnabled] = useState(false); const [catalogId, setCatalogId] = useState(""); const [tier, setTier] = useState(""); const [customInterval, setCustomInterval] = useState(""); const loadData = useCallback(async () => { setLoading(true); try { const [catalogList, tierList, ext] = await Promise.all([ inspectionCatalogApi.list(), inspectionCatalogApi.getTiers(), inspectionDeviceApi.get(hostId), ]); const safeCatalogs = Array.isArray(catalogList) ? catalogList : []; const safeTiers = Array.isArray(tierList) ? tierList : []; setCatalogs(safeCatalogs); setTiers(safeTiers); setExtension(ext || null); if (ext) { setEnabled(ext.inspection_enabled); setCatalogId(ext.catalog_id); setTier(ext.tier || ""); setCustomInterval(ext.inspection_interval?.toString() || ""); } else { // 默认值 setCatalogId(safeCatalogs[0]?.id || "linux"); setTier("access"); } } catch (e: any) { console.error("[Inspection] 加载失败:", e); } finally { setLoading(false); } }, [hostId]); useEffect(() => { loadData(); }, [loadData]); const handleSave = async () => { if (!catalogId) { toast.error("请选择设备类型"); return; } setSaving(true); try { const data: Partial = { inspection_enabled: enabled, catalog_id: catalogId, tier: (tier as DeviceTier) || null, inspection_interval: customInterval ? parseInt(customInterval, 10) : null, // 存 hostname,用于调度器匹配 vault SSH 配置 hostname: host?.hostname || null, }; const result = await inspectionDeviceApi.upsert(hostId, data); setExtension(result); toast.success(enabled ? "巡检已启用" : "巡检已停用"); } catch (e: any) { toast.error("保存失败: " + e.message); } finally { setSaving(false); } }; const handleScanNow = async () => { try { if (!host || !host.hostname) { toast.error("主机配置不完整,无法巡检"); return; } // 构造连接配置 const hostConfig: any = { id: host.id || hostId, label: hostLabel, hostname: host.hostname, port: host.port || 22, username: host.username, }; // 密码 if (host.password) { hostConfig.password = host.password; } // 私钥 if (host.identityFileId && keys && keys.length) { const key = keys.find((k) => k.id === host.identityFileId); if (key && key.privateKey) { hostConfig.privateKeyContent = key.privateKey; if (key.passphrase) { hostConfig.passphrase = key.passphrase; } } } toast.info(`正在对 ${hostLabel} 执行立即巡检...`); const result = await inspectionExecApi.runInspection(hostId, hostConfig, catalogId); if (result?.success) { toast.success(`巡检完成,耗时 ${(result.duration / 1000).toFixed(1)} 秒`); if (result.alerts && result.alerts.length > 0) { toast.warning(`触发 ${result.alerts.length} 条告警`); } } else { toast.error(`巡检失败: ${result?.error || "未知错误"}`); } // 刷新扩展信息(更新 last_run_at) loadData(); } catch (e: any) { toast.error("巡检触发失败: " + e.message); } }; // 计算有效周期 const selectedTier = tiers.find((t) => t.key === tier); const selectedCatalog = catalogs.find((c) => c.id === catalogId); const effectiveInterval = customInterval ? `${customInterval} 分钟` : selectedTier ? `${selectedTier.default_interval} 分钟(${selectedTier.label}默认)` : "5 分钟(系统默认)"; return ( } title="巡检配置" hint={`为 ${hostLabel} 配置自动巡检`} > {loading ? (
加载中...
) : (
{/* 启用开关 */}
启用自动巡检
开启后系统将按周期自动巡检该设备
{/* 设备类型 */}
{selectedCatalog && (

{selectedCatalog.description}

)}
{/* 设备分级 */}
{tiers.map((t) => ( ))}

分级决定默认巡检周期,也可单独设置

{/* 自定义周期 */}
setCustomInterval(e.target.value)} />

有效周期:{effectiveInterval}

{/* 上次巡检信息 */} {extension?.last_scan_at && (
上次巡检: {new Date(extension.last_scan_at).toLocaleString()} {extension.last_scan_status === "success" ? "成功" : extension.last_scan_status === "timeout" ? "超时" : "失败"}
)} {/* 操作按钮 */}
)}
); }