fix(charts): единый стиль AreaChart с градиентом
Общий AreaTrendChart для мониторинга и daily-графиков, StatisticSparklineCard на дашборде. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
AreaChart,
|
||||
Area,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
|
||||
export interface AreaTrendSeries {
|
||||
key: string;
|
||||
color: string;
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
data: Record<string, unknown>[];
|
||||
xKey: string;
|
||||
series: AreaTrendSeries[];
|
||||
height?: number;
|
||||
xMinTickGap?: number;
|
||||
yAllowDecimals?: boolean;
|
||||
}
|
||||
|
||||
const AreaTrendChart: React.FC<Props> = ({
|
||||
data,
|
||||
xKey,
|
||||
series,
|
||||
height = 280,
|
||||
xMinTickGap = 30,
|
||||
yAllowDecimals = true,
|
||||
}) => (
|
||||
<ResponsiveContainer width="100%" height={height}>
|
||||
<AreaChart data={data}>
|
||||
<defs>
|
||||
{series.map((s) => (
|
||||
<linearGradient key={s.key} id={`grad-${s.key}`} x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor={s.color} stopOpacity={0.4} />
|
||||
<stop offset="95%" stopColor={s.color} stopOpacity={0.05} />
|
||||
</linearGradient>
|
||||
))}
|
||||
</defs>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey={xKey} minTickGap={xMinTickGap} />
|
||||
<YAxis allowDecimals={yAllowDecimals} />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
{series.map((s) => (
|
||||
<Area
|
||||
key={s.key}
|
||||
type="monotone"
|
||||
dataKey={s.key}
|
||||
stroke={s.color}
|
||||
fill={`url(#grad-${s.key})`}
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
activeDot={{ r: 3, strokeWidth: 0 }}
|
||||
name={s.name}
|
||||
/>
|
||||
))}
|
||||
</AreaChart>
|
||||
</ResponsiveContainer>
|
||||
);
|
||||
|
||||
export default AreaTrendChart;
|
||||
@@ -1,16 +1,7 @@
|
||||
import React from 'react';
|
||||
import { Card, Col } from 'antd';
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import { DayCount } from '../types/api';
|
||||
import AreaTrendChart from './AreaTrendChart';
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
@@ -32,16 +23,13 @@ const DailyLineChartCard: React.FC<Props> = ({ title, data, color, lg = 12 }) =>
|
||||
return (
|
||||
<Col xs={24} lg={lg}>
|
||||
<Card title={title}>
|
||||
<ResponsiveContainer width="100%" height={300}>
|
||||
<LineChart data={chartData}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="date" />
|
||||
<YAxis allowDecimals={false} />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
<Line type="monotone" dataKey="count" stroke={color} name={title} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
<AreaTrendChart
|
||||
data={chartData}
|
||||
xKey="date"
|
||||
series={[{ key: 'count', color, name: title }]}
|
||||
height={300}
|
||||
yAllowDecimals={false}
|
||||
/>
|
||||
</Card>
|
||||
</Col>
|
||||
);
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import React from 'react';
|
||||
import { Card, Statistic } from 'antd';
|
||||
import { AreaChart, Area, XAxis, Tooltip } from 'recharts';
|
||||
|
||||
interface SparklinePoint {
|
||||
date: string;
|
||||
value: number;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
title: string;
|
||||
value: number;
|
||||
prefix?: React.ReactNode;
|
||||
data?: SparklinePoint[];
|
||||
color?: string;
|
||||
gradientId: string;
|
||||
}
|
||||
|
||||
const StatisticSparklineCard: React.FC<Props> = ({
|
||||
title,
|
||||
value,
|
||||
prefix,
|
||||
data,
|
||||
color = '#1890ff',
|
||||
gradientId,
|
||||
}) => (
|
||||
<Card variant="outlined">
|
||||
<div style={{ display: 'flex', alignItems: 'center' }}>
|
||||
<Statistic
|
||||
title={title}
|
||||
value={value}
|
||||
prefix={prefix}
|
||||
style={{ flex: '0 0 auto', marginRight: 16 }}
|
||||
/>
|
||||
{data && data.length > 0 && (
|
||||
<AreaChart
|
||||
width={150}
|
||||
height={50}
|
||||
data={data}
|
||||
margin={{ top: 5, right: 0, left: 0, bottom: 0 }}
|
||||
>
|
||||
<defs>
|
||||
<linearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="5%" stopColor={color} stopOpacity={0.4} />
|
||||
<stop offset="95%" stopColor={color} stopOpacity={0.05} />
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<XAxis dataKey="date" hide />
|
||||
<Tooltip labelFormatter={(label) => `Дата: ${label}`} />
|
||||
<Area
|
||||
type="monotone"
|
||||
dataKey="value"
|
||||
stroke={color}
|
||||
fill={`url(#${gradientId})`}
|
||||
strokeWidth={2}
|
||||
dot={false}
|
||||
activeDot={{ r: 3, strokeWidth: 0 }}
|
||||
/>
|
||||
</AreaChart>
|
||||
)}
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
|
||||
export default StatisticSparklineCard;
|
||||
@@ -1,18 +1,9 @@
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { Card, Col, Row, Select, Table, Tabs } from 'antd';
|
||||
import {
|
||||
LineChart,
|
||||
Line,
|
||||
XAxis,
|
||||
YAxis,
|
||||
CartesianGrid,
|
||||
Tooltip,
|
||||
Legend,
|
||||
ResponsiveContainer,
|
||||
} from 'recharts';
|
||||
import dayjs from 'dayjs';
|
||||
import { useMetricsStore, NodeMetric } from '../../store/metricsStore';
|
||||
import { monitoringApi } from '../../api/monitoringApi';
|
||||
import AreaTrendChart from '../../components/AreaTrendChart';
|
||||
|
||||
const NODE_COLORS = ['#1677ff', '#52c41a', '#fa8c16', '#eb2f96', '#722ed1', '#13c2c2'];
|
||||
const TIME_RANGES = [
|
||||
@@ -51,18 +42,7 @@ const MetricChart: React.FC<{
|
||||
data: ReturnType<typeof buildChartData>;
|
||||
lines: Array<{ key: string; color: string; name: string }>;
|
||||
}> = ({ data, lines }) => (
|
||||
<ResponsiveContainer width="100%" height={280}>
|
||||
<LineChart data={data}>
|
||||
<CartesianGrid strokeDasharray="3 3" />
|
||||
<XAxis dataKey="time" minTickGap={30} />
|
||||
<YAxis />
|
||||
<Tooltip />
|
||||
<Legend />
|
||||
{lines.map((line) => (
|
||||
<Line key={line.key} type="monotone" dataKey={line.key} stroke={line.color} name={line.name} dot={false} />
|
||||
))}
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
<AreaTrendChart data={data} xKey="time" series={lines} />
|
||||
);
|
||||
|
||||
const MonitoringPage: React.FC = () => {
|
||||
|
||||
Reference in New Issue
Block a user