// LogClusterPanel.tsx — 日志聚类面板 // Logan.Li import { useState } from 'react'; import { ChevronDown, ChevronRight, Copy, Check } from 'lucide-react'; import type { LogCluster } from './types-v3'; import { useTranslation } from 'react-i18next'; interface Props { clusters: LogCluster[]; } function PatternHighlight({ pattern }: { pattern: string }) { const { t } = useTranslation(); // 将 * 高亮显示 // Logan.Li const parts = pattern.split('*'); return ( {parts.map((part, i) => ( {part} {i < parts.length - 1 && *} ))} ); } export function LogClusterPanel({ clusters }: Props) { const { t } = useTranslation(); const [expanded, setExpanded] = useState>({}); const [copied, setCopied] = useState(null); const toggleExpand = (i: number) => setExpanded(prev => ({ ...prev, [i]: !prev[i] })); const copySample = (i: number, text: string) => { navigator.clipboard.writeText(text); setCopied(i); setTimeout(() => setCopied(null), 1500); }; const total = clusters.reduce((sum, c) => sum + c.count, 0); return ( {/* 头部 */} 共 {clusters.length} 个聚类模式,总计 {total.toLocaleString()} 条日志 {t('monitor.logclusterpanel.s381127')} {/* 聚类列表 */} {clusters.map((cluster, i) => ( toggleExpand(i)} > {expanded[i] ? : } {/* 模式 */} {/* 数量 */} {cluster.count.toLocaleString()} {/* 百分比 */} {cluster.percentage.toFixed(1)}% {/* 复制 */} { e.stopPropagation(); copySample(i, cluster.sample); }} className="flex-shrink-0 opacity-0 group-hover:opacity-100 transition-opacity" style={{ color: 'var(--dg-text-muted)' }} > {copied === i ? : } {/* 展开详情 */} {expanded[i] && ( {t('monitor.logclusterpanel.se909e4')} {cluster.sample} 数量:{cluster.count.toLocaleString()} 占比:{cluster.percentage.toFixed(2)}% )} ))} ); }
{t('monitor.logclusterpanel.se909e4')}