import { useCallback, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { BookOpen, Database, Loader2, X } from 'lucide-react'; import { AnimatePresence, motion } from 'motion/react'; import { fetchJson } from '../auth/api-client'; import type { MetricDefinition, MetricDomain } from '../shared/analytics/catalog'; interface MetricCatalogResponse { catalogVersion: number; domains: MetricDomain[]; metrics: MetricDefinition[]; } const AGGREGATION_LABEL: Record = { sum: '求和', count: '计数', derived: '派生计算', 'weighted-ratio': '加权比率', 'distinct-count': '去重计数', latest: '取最新值', }; const TIME_LABEL: Record = { flow: '区间流量', snapshot: '时点快照', freshness: '数据新鲜度', }; export default function MetricCatalogButton({ domain }: { domain: MetricDomain }) { const [open, setOpen] = useState(false); const [data, setData] = useState(null); const [error, setError] = useState(null); const triggerRef = useRef(null); const closeRef = useRef(null); const setCloseRef = useCallback((node: HTMLButtonElement | null) => { closeRef.current = node; node?.focus(); }, []); useEffect(() => { if (!open || data) return undefined; let cancelled = false; setError(null); fetchJson(`/api/analytics/metrics?domain=${domain}`) .then(result => { if (!cancelled) setData(result); }) .catch(e => { if (!cancelled) setError(e instanceof Error ? e.message : String(e)); }); return () => { cancelled = true; }; }, [open, data, domain]); useEffect(() => { if (!open) return undefined; const previousOverflow = document.body.style.overflow; document.body.style.overflow = 'hidden'; const handleKeyDown = (event: KeyboardEvent) => { if (event.key === 'Escape') setOpen(false); }; document.addEventListener('keydown', handleKeyDown); return () => { document.body.style.overflow = previousOverflow; document.removeEventListener('keydown', handleKeyDown); triggerRef.current?.focus(); }; }, [open]); return ( <> {createPortal( {open && (
setOpen(false)} className="absolute inset-0 h-full w-full bg-slate-950/35 backdrop-blur-[2px]" />

指标口径

{data ? `目录版本 v${data.catalogVersion} · ${data.metrics.length} 项指标` : '读取已发布指标目录'}

{error ? (
{error}
) : !data ? (
正在加载指标口径
) : ( data.metrics.map(metric => (

{metric.label}

{metric.id}
{AGGREGATION_LABEL[metric.aggregation]} {TIME_LABEL[metric.timeSemantics]} {metric.unit}

{metric.description}

{metric.formula}
{metric.sources.join(' · ')}
{metric.dimensions.map(dimension => ( {dimension} ))}
)) )}
)}
, document.body)} ); }