import { useEffect } from 'react'; import { Shield, ShieldCheck, ShieldAlert, ShieldX, RefreshCw, Loader2, AlertCircle } from 'lucide-react'; import { useSecurityStore } from '../store/securityStore'; // ZCLAW 16-layer security architecture names (Chinese) const SECURITY_LAYER_NAMES: Record = { // Layer 1: Network 'network.firewall': '网络防火墙', 'network.tls': 'TLS 加密', 'network.rate_limit': '速率限制', // Layer 2: Authentication 'auth.device': '设备认证', 'auth.jwt': 'JWT 令牌', 'auth.session': '会话管理', // Layer 3: Authorization 'auth.rbac': '角色权限', 'auth.capabilities': '能力控制', // Layer 4: Input Validation 'input.sanitization': '输入净化', 'input.schema': '模式验证', // Layer 5: Execution 'exec.sandbox': '沙箱隔离', 'exec.timeout': '执行超时', 'exec.resource_limit': '资源限制', // Layer 6: Audit & Logging 'audit.logging': '审计日志', 'audit.tracing': '请求追踪', 'audit.alerting': '审计告警', }; // Default 16 layers for display when API returns minimal data const DEFAULT_LAYERS = [ { name: 'network.firewall', enabled: false }, { name: 'network.tls', enabled: false }, { name: 'network.rate_limit', enabled: false }, { name: 'auth.device', enabled: false }, { name: 'auth.jwt', enabled: false }, { name: 'auth.session', enabled: false }, { name: 'auth.rbac', enabled: false }, { name: 'auth.capabilities', enabled: false }, { name: 'input.sanitization', enabled: false }, { name: 'input.schema', enabled: false }, { name: 'exec.sandbox', enabled: false }, { name: 'exec.timeout', enabled: false }, { name: 'exec.resource_limit', enabled: false }, { name: 'audit.logging', enabled: false }, { name: 'audit.tracing', enabled: false }, { name: 'audit.alerting', enabled: false }, ]; function getSecurityIcon(level: 'critical' | 'high' | 'medium' | 'low') { switch (level) { case 'critical': return ; case 'high': return ; case 'medium': return ; case 'low': return ; } } function getSecurityLabel(level: 'critical' | 'high' | 'medium' | 'low') { switch (level) { case 'critical': return { text: '极高', color: 'text-green-600 bg-green-50 border-green-200' }; case 'high': return { text: '高', color: 'text-blue-600 bg-blue-50 border-blue-200' }; case 'medium': return { text: '中', color: 'text-yellow-600 bg-yellow-50 border-yellow-200' }; case 'low': return { text: '低', color: 'text-red-600 bg-red-50 border-red-200' }; } } export function SecurityStatus() { const securityStatus = useSecurityStore((s) => s.securityStatus); const securityStatusLoading = useSecurityStore((s) => s.securityStatusLoading); const securityStatusError = useSecurityStore((s) => s.securityStatusError); const loadSecurityStatus = useSecurityStore((s) => s.loadSecurityStatus); useEffect(() => { loadSecurityStatus(); }, [loadSecurityStatus]); // Loading state if (securityStatusLoading && !securityStatus) { return (
安全状态

加载中...

); } // API error state - show friendly message if (securityStatusError && !securityStatus) { return (
安全状态

安全状态检测失败

本地安全检测模块加载失败,请检查安全组件是否正确初始化

); } // Use default layers if no data, or merge with API data const displayLayers = securityStatus?.layers?.length ? DEFAULT_LAYERS.map((defaultLayer) => { const apiLayer = securityStatus.layers.find((l) => l.name === defaultLayer.name); return apiLayer || defaultLayer; }) : DEFAULT_LAYERS; const enabledCount = displayLayers.filter((l) => l.enabled).length; const totalCount = displayLayers.length; const securityLevel = securityStatus?.securityLevel || (enabledCount >= 14 ? 'critical' : enabledCount >= 10 ? 'high' : enabledCount >= 6 ? 'medium' : 'low'); const levelLabel = getSecurityLabel(securityLevel); return (
{/* Header */}
{getSecurityIcon(securityLevel)} 安全状态 {securityStatusLoading && ( )}
{levelLabel.text}
{/* Summary */}
已启用 {enabledCount} / {totalCount} 层防护
{/* Progress bar */}
{/* Layers Grid */}
{displayLayers.map((layer) => { const label = SECURITY_LAYER_NAMES[layer.name] || layer.name; return (
{label}
); })}
{/* Layer Categories */}
l.name.startsWith('network.'))} /> l.name.startsWith('auth.'))} /> l.name.startsWith('exec.'))} /> l.name.startsWith('input.'))} /> l.name.startsWith('audit.'))} />
); } function CategorySummary({ label, layers }: { label: string; layers: { enabled: boolean }[] }) { if (layers.length === 0) return null; const enabled = layers.filter((l) => l.enabled).length; const total = layers.length; const allEnabled = enabled === total; return (
{enabled}/{total} {label}
); }