import React, { useCallback, useMemo } from 'react'; import { Box, Flex, HStack, useTheme } from '@chakra-ui/react'; import { ResponsiveContainer, XAxis, YAxis, CartesianGrid, Tooltip, type TooltipProps, LineChart, Line, ReferenceLine } from 'recharts'; import { type NameType, type ValueType } from 'recharts/types/component/DefaultTooltipContent'; import { formatNumber } from '@fastgpt/global/common/math/tools'; import { useTranslation } from 'next-i18next'; import QuestionTip from '../MyTooltip/QuestionTip'; type LineConfig = { dataKey: string; name: string; color: string; gradient?: boolean; }; type TooltipItem = { label: string; dataKey: string; color: string; formatter?: (value: number) => string; customValue?: (data: Record) => number; }; type LineChartComponentProps = { data: Record[]; title: string; description?: string; HeaderRightChildren?: React.ReactNode; lines: LineConfig[]; tooltipItems?: TooltipItem[]; showAverage?: boolean; averageKey?: string; blur?: boolean; }; const CustomTooltip = ({ active, payload, tooltipItems }: TooltipProps & { tooltipItems?: TooltipItem[] }) => { const data = payload?.[0]?.payload; if (!active || !data || !tooltipItems) { return null; } return ( 8 ? { position: 'relative', top: '-30px' } : {})} > 5 ? 1 : 2}> {data.xLabel || data.x} {tooltipItems.map((item, index) => { const value = item.customValue ? item.customValue(data) : data[item.dataKey]; const displayValue = item.formatter ? item.formatter(value) : formatNumber(value); return ( 5 ? 0 : 1 }}> {item.label} {displayValue.toLocaleString()} ); })} ); }; const LineChartComponent = ({ data, title, description, HeaderRightChildren, lines, tooltipItems, showAverage = false, averageKey, blur = false }: LineChartComponentProps) => { const theme = useTheme(); // Y-axis number formatter function const formatYAxisNumber = useCallback((value: number): string => { if (value >= 1000000) { return value / 1000000 + 'M'; } else if (value >= 1000) { return value / 1000 + 'K'; } return value.toString(); }, []); // Calculate average value const averageValue = useMemo(() => { if (!showAverage || !averageKey || data.length === 0) return null; const sum = data.reduce((acc, item) => acc + (item[averageKey] || 0), 0); return sum / data.length; }, [showAverage, averageKey, data]); // Generate gradient definitions const gradientDefs = useMemo( () => ( {lines.map((line) => ( ))} ), [lines] ); return ( { const chartElement = e.currentTarget.querySelector('.recharts-wrapper'); if (chartElement && showAverage && averageValue !== null) { chartElement.classList.add('show-average'); } }} onMouseLeave={(e) => { const chartElement = e.currentTarget.querySelector('.recharts-wrapper'); if (chartElement) { chartElement.classList.remove('show-average'); } }} h="100%" > {title} {HeaderRightChildren} {gradientDefs} {tooltipItems && } />} {lines.map((line, index) => ( ))} {showAverage && averageValue !== null && ( )} ); }; export default LineChartComponent;