import { CHART_SECONDARY_COLOR, CLS_PREFIX, THEME_COLOR_LIST } from '../../../common/constants'; import { formatByDecimalPlaces, getFormattedValue, getMinMaxDate, groupByColumn, normalizeTrendData, } from '../../../utils/utils'; import type { ECharts } from 'echarts'; import * as echarts from 'echarts'; import React, { useEffect, useRef, useState } from 'react'; import moment from 'moment'; import { ColumnType } from '../../../common/type'; import NoPermissionChart from '../NoPermissionChart'; type Props = { domain?: string; dateColumnName: string; categoryColumnName: string; metricField: ColumnType; resultList: any[]; onApplyAuth?: (domain: string) => void; }; const MetricTrendChart: React.FC = ({ domain, dateColumnName, categoryColumnName, metricField, resultList, onApplyAuth, }) => { const chartRef = useRef(); const [instance, setInstance] = useState(); const renderChart = () => { let instanceObj: any; if (!instance) { instanceObj = echarts.init(chartRef.current); setInstance(instanceObj); } else { instanceObj = instance; } const valueColumnName = metricField.nameEn; const groupDataValue = groupByColumn(resultList, categoryColumnName); const [startDate, endDate] = getMinMaxDate(resultList, dateColumnName); const groupData = Object.keys(groupDataValue).reduce((result: any, key) => { result[key] = startDate && endDate && (dateColumnName.includes('date') || dateColumnName.includes('month')) ? normalizeTrendData( groupDataValue[key], dateColumnName, valueColumnName, startDate, endDate, dateColumnName.includes('month') ? 'months' : 'days' ) : groupDataValue[key].reverse(); return result; }, {}); const sortedGroupKeys = Object.keys(groupData).sort((a, b) => { return ( groupData[b][groupData[b].length - 1][valueColumnName] - groupData[a][groupData[a].length - 1][valueColumnName] ); }); const xData = groupData[sortedGroupKeys[0]]?.map((item: any) => { const date = `${item[dateColumnName]}`; return date.length === 10 ? moment(date).format('MM-DD') : date; }); instanceObj.setOption({ legend: categoryColumnName && { left: 0, top: 0, icon: 'rect', itemWidth: 15, itemHeight: 5, type: 'scroll', }, xAxis: { type: 'category', axisTick: { alignWithLabel: true, lineStyle: { color: CHART_SECONDARY_COLOR, }, }, axisLine: { lineStyle: { color: CHART_SECONDARY_COLOR, }, }, axisLabel: { showMaxLabel: true, color: '#999', }, data: xData, }, yAxis: { type: 'value', splitLine: { lineStyle: { opacity: 0.3, }, }, axisLabel: { formatter: function (value: any) { return value === 0 ? 0 : metricField.dataFormatType === 'percent' ? `${formatByDecimalPlaces(value, metricField.dataFormat?.decimalPlaces || 2)}%` : getFormattedValue(value); }, }, }, tooltip: { trigger: 'axis', formatter: function (params: any[]) { const param = params[0]; const valueLabels = params .sort((a, b) => b.value - a.value) .map( (item: any) => `
${ item.marker } ${ item.seriesName }${ item.value === '' ? '-' : metricField.dataFormatType === 'percent' ? `${formatByDecimalPlaces( item.value, metricField.dataFormat?.decimalPlaces || 2 )}%` : getFormattedValue(item.value) }
` ) .join(''); return `${param.name}
${valueLabels}`; }, }, grid: { left: '1%', right: '4%', bottom: '3%', top: categoryColumnName ? 45 : 20, containLabel: true, }, series: sortedGroupKeys.slice(0, 20).map((category, index) => { const data = groupData[category]; return { type: 'line', name: categoryColumnName ? category : metricField.name, symbol: 'circle', showSymbol: data.length === 1, smooth: true, data: data.map((item: any) => { const value = item[valueColumnName]; return metricField.dataFormatType === 'percent' && metricField.dataFormat?.needmultiply100 ? value * 100 : value; }), color: THEME_COLOR_LIST[index], }; }), }); instanceObj.resize(); }; useEffect(() => { if (metricField.authorized) { renderChart(); } }, [resultList, metricField]); const prefixCls = `${CLS_PREFIX}-metric-trend`; return (
{!metricField.authorized ? ( ) : (
)}
); }; export default MetricTrendChart;