Files
aiops/frontend/src/pages/monitor/snmp-monitor/SnmpMetricTrendChart.tsx
T
LoganandClaude 471353e3d7 feat: 监控告警体系统一重构 + 自动化任务调度引擎 + 监控大屏拆分
告警中心
- 新增统一告警(alert_unified)、监控告警规则(monitor_alert_rule)、指标目录(alert_metric_catalog)
- 通知策略与消息分发(alert_notify_policy/dispatch/message)、静默规则
- 告警引擎按阈值/SNMP 拆分(alert_engine_monitor/snmp)

监控采集
- SNMP 常量/模板与历史指标(snmp templates/constants、snmp_metrics_history、snmp_collect)
- 中间件监控 Redis 采集与种子(middleware_monitor_redis/seed)
- 站点探测 pkg(siteprobe) + 站点视图(site_view)

自动化任务
- cron 调度器(cronscheduler)、脚本运行器(scriptrunner)、系统任务(systask)及运行记录(cron_job_run、system_task)

审计与凭证
- 审计设置(audit_setting) + 历史清理(auditcleaner)

前端
- 监控页面(host/middleware/site/snmp)拆分为子模块并大屏化
- 告警中心多 Tab(规则/指标目录/通知策略/静默)、任务管理组件重构、Agent CLI Markdown 渲染
- 移除旧脚本卡片/详情/日志组件,统一为 ScriptTable/ScriptCodeEditor/TerminalOutput

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-01 23:44:45 +08:00

63 lines
2.8 KiB
TypeScript

// SNMP 指标趋势折线图 — 光标拖拽选区 // Logan.Li
import { useMemo } from 'react';
import {
AreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer,
ReferenceArea,
} from 'recharts';
import type { SnmpHistoryPoint } from './helpers';
import { fmtChartTime, fmtMetricValue } from './helpers';
import { MonitorChartTooltip, MONITOR_CHART_GRID, MONITOR_CHART_TICK } from '../shared/monitorChartTheme';
import { useChartRangeZoom } from '../shared/useChartRangeZoom';
import { ChartRangeHint } from '../shared/ChartRangeHint';
interface Props {
data: SnmpHistoryPoint[];
color: string;
unit?: string;
height?: number;
}
export function SnmpMetricTrendChart({ data, color, unit, height = 160 }: Props) {
const chartData = useMemo(
() => data.map((p) => ({ time: fmtChartTime(p.timestamp), value: p.value })),
[data],
);
const {
displayData, refLeft, refRight, selectionLabel, resetZoom, chartHandlers, zoomed,
} = useChartRangeZoom(chartData, 'time');
if (chartData.length === 0) {
return (
<div className="flex items-center justify-center text-xs text-[var(--dg-text-muted)]" style={{ height }}>
暂无趋势数据,等待后台采集
</div>
);
}
const gradId = `snmp-grad-${color.replace(/[^a-z]/gi, '')}`;
return (
<div>
<ResponsiveContainer width="100%" height={height}>
<AreaChart data={displayData} margin={{ top: 6, right: 8, left: 0, bottom: 4 }} {...chartHandlers}>
<defs>
<linearGradient id={gradId} x1="0" y1="0" x2="0" y2="1">
<stop offset="0%" stopColor={color} stopOpacity={0.3} />
<stop offset="100%" stopColor={color} stopOpacity={0.02} />
</linearGradient>
</defs>
<CartesianGrid strokeDasharray="3 3" stroke={MONITOR_CHART_GRID} vertical={false} />
<XAxis dataKey="time" tick={MONITOR_CHART_TICK} tickLine={false} axisLine={{ stroke: MONITOR_CHART_GRID }} interval="preserveStartEnd" minTickGap={36} />
<YAxis tick={MONITOR_CHART_TICK} tickLine={false} axisLine={false} width={40} domain={['auto', 'auto']} />
<Tooltip content={<MonitorChartTooltip valueFormatter={(v) => fmtMetricValue(v, unit)} />} />
{refLeft && refRight && refLeft !== refRight && (
<ReferenceArea x1={refLeft} x2={refRight} strokeOpacity={0.4} fill="var(--dg-blue)" fillOpacity={0.12} />
)}
<Area type="monotone" dataKey="value" stroke={color} strokeWidth={2} fill={`url(#${gradId})`} dot={false} activeDot={{ r: 3, fill: color, stroke: 'var(--dg-bg-primary)', strokeWidth: 2 }} isAnimationActive={false} />
</AreaChart>
</ResponsiveContainer>
<ChartRangeHint label={selectionLabel} zoomed={zoomed} onReset={resetZoom} />
</div>
);
}