import React, { useState, useEffect, useRef } from 'react'; import { Utils, AppContainer } from 'knowdesign'; import api, { MetricType } from '@src/api'; import DBreadcrumb from 'knowdesign/es/extend/d-breadcrumb'; import ConnectCard from '@src/components/CardBar/ConnectCard'; import { useParams } from 'react-router-dom'; import { FormattedMetricData, formatChartData, MetricInfo } from '@src/constants/chartConfig'; import ChartOperateBar, { KsHeaderOptions } from '@src/components/ChartOperateBar'; import ChartDetail from '@src/components/DraggableCharts/Detail'; import ChartList from '@src/components/DraggableCharts/ChartList'; import MetricsFilter from './MetricsFilter'; import SelectContent, { Connector } from './SelectContent'; import './index.less'; import { ConnectCluster } from '../Connect/AddConnector'; import HasConnector from '../Connect/HasConnector'; type ChartFilterOptions = Omit; const { EventBus } = Utils; const busInstance = new EventBus(); const DraggableCharts = (): JSX.Element => { const [global] = AppContainer.useGlobalValue(); const { clusterId } = useParams<{ clusterId: string; }>(); const [loading, setLoading] = useState(true); // const [scopeList, setScopeList] = useState([]); // 节点范围列表 const [curHeaderOptions, setCurHeaderOptions] = useState(); const [metricList, setMetricList] = useState<{ [key: string]: (string | number)[] }>({}); const [metricChartData, setMetricChartData] = useState([]); // 指标图表数据列表 const [gridNum, setGridNum] = useState(12); // 图表列布局 const [scopeList, setScopeList] = useState<{ connectClusters: ConnectCluster[]; connectors: Connector[]; }>({ connectClusters: [], connectors: [], }); const [screenType, setScreenType] = useState('all'); const curFetchingTimestamp = useRef(0); const metricRankList = useRef([]); const metricFilterRef = useRef(null); const chartDetailRef = useRef(null); // 根据筛选项获取图表信息 const getMetricChartData = () => { !curHeaderOptions.isAutoReload && setLoading(true); const curTimestamp = Date.now(); curFetchingTimestamp.current = curTimestamp; const [startTime, endTime] = curHeaderOptions.rangeTime; const { connectClusters, connectors } = curHeaderOptions.scopeData.data; const isTop = curHeaderOptions?.scopeData?.isTop; const reqBasicBody = { startTime, endTime, topNu: isTop ? curHeaderOptions.scopeData.data : null, }; const getConnectClusterMetrics = metricList[MetricType.Connect] && (isTop || connectClusters?.length) ? Utils.post( api.getConnectClusterMetrics(clusterId), Object.assign( { ...reqBasicBody, metricsNames: metricList[MetricType.Connect], }, isTop ? {} : { connectClusterIdList: connectClusters, } ) ) : Promise.resolve([]); const getConnectorMetrics = metricList[MetricType.Connectors] && (isTop || connectors?.length) ? Utils.post( api.getConnectorMetrics(clusterId), Object.assign( { ...reqBasicBody, metricsNames: metricList[MetricType.Connectors], }, isTop ? {} : { connectorNameList: connectors } ) ) : Promise.resolve([]); Promise.all([getConnectClusterMetrics, getConnectorMetrics]).then( (res: any) => { // 如果当前请求不是最新请求,则不做任何操作 if (curFetchingTimestamp.current !== curTimestamp) { return; } // 为保证指标排序结果正确,当指标全部返回后才展示图表 if (res.length === 1 || (res.length === 2 && res[0] && res[1])) { const connectClusterData = formatChartData( res[0], global.getMetricDefine || {}, MetricType.Connect, curHeaderOptions.rangeTime ) as FormattedMetricData[]; // todo 将指标筛选选中但是没有返回的指标插入chartData中 const newConnectClusterData: any = []; metricList[MetricType.Connect]?.forEach((item) => { if (connectClusterData && connectClusterData.some((key) => item === key.metricName)) { newConnectClusterData.push(null); } else { const chartData: any = { metricName: item, metricType: MetricType.Connect, metricUnit: global.getMetricDefine(MetricType.Connect, item)?.unit || '', metricLines: [], showLegend: false, targetUnit: undefined, }; newConnectClusterData.push(chartData); } }); const connectorData = formatChartData( res[1], global.getMetricDefine || {}, MetricType.Connectors, curHeaderOptions.rangeTime ) as FormattedMetricData[]; // todo 将指标筛选选中但是没有返回的指标插入chartData中 const newConnectorData: any = []; metricList[MetricType.Connectors]?.forEach((item) => { if (connectorData && connectorData.some((key) => item === key.metricName)) { newConnectorData.push(null); } else { const chartData: any = { metricName: item, metricType: MetricType.Connectors, metricUnit: global.getMetricDefine(MetricType.Connectors, item)?.unit || '', metricLines: [], showLegend: false, targetUnit: undefined, }; newConnectorData.push(chartData); } }); // 指标排序 const formattedMetricData = [...connectClusterData, ...connectorData]; const nullDataMetricData = [...newConnectClusterData, ...newConnectorData].filter((item) => item !== null); formattedMetricData.sort((a, b) => metricRankList.current.indexOf(a.metricName) - metricRankList.current.indexOf(b.metricName)); nullDataMetricData.sort((a, b) => metricRankList.current.indexOf(a.metricName) - metricRankList.current.indexOf(b.metricName)); const filterMetricData = [...formattedMetricData, ...nullDataMetricData]; setMetricChartData( screenType === 'Connect' ? filterMetricData.filter((item) => item.metricType === MetricType.Connect) : screenType === 'Connector' ? filterMetricData.filter((item) => item.metricType === MetricType.Connectors) : filterMetricData ); } else { setMetricChartData([]); } setLoading(false); }, () => curFetchingTimestamp.current === curTimestamp && setLoading(false) ); }; const getScopeList = () => { const getConnectClusters = Utils.request(api.getConnectClusters(clusterId)); const getConnectors = Utils.request(api.getConnectors(clusterId)); Promise.all([getConnectClusters, getConnectors]).then(([connectClusters, connectors]: [ConnectCluster[], Connector[]]) => { setScopeList({ connectClusters, connectors, }); }); }; // 筛选项变化或者点击刷新按钮 const ksHeaderChange = (ksOptions: KsHeaderOptions) => { const { isAutoReload, gridNum: newGridNum, isRelativeRangeTime, rangeTime, scopeData } = ksOptions; let newRangeTime = rangeTime; // 重新渲染图表 if (newGridNum !== gridNum) { setGridNum(newGridNum || 12); busInstance.emit('chartResize'); } else { // 如果为相对时间,则当前时间减去 1 分钟,避免最近一分钟的数据还没采集到时前端多补一个点 if (isRelativeRangeTime) { newRangeTime = rangeTime.map((timestamp) => timestamp - 60 * 1000) as [number, number]; } setCurHeaderOptions({ isRelativeRangeTime: isRelativeRangeTime, isAutoReload: isAutoReload, rangeTime: newRangeTime, scopeData: scopeData, }); } }; // 图表拖拽 const dragCallback = (oldIndex: number, newIndex: number) => { const originFrom = metricRankList.current.indexOf(metricChartData[oldIndex].metricName); const originTarget = metricRankList.current.indexOf(metricChartData[newIndex].metricName); metricFilterRef.current?.rankChange(originFrom, originTarget); }; // 展开图表详情 const onExpand = (metricName: string, metricType: MetricType) => { const linesName = metricType === MetricType.Connect ? scopeList.connectClusters.map((cluster) => cluster.id) : scopeList.connectors.map((connector) => ({ connectClusterId: connector.connectClusterId, connectorName: connector.connectorName, })); chartDetailRef.current.onOpen(metricType, metricName, linesName); }; // 获取图表指标 useEffect(() => { if (Object.values(metricList).some((list) => list.length) && curHeaderOptions) { getMetricChartData(); } }, [curHeaderOptions, screenType]); useEffect(() => { if (Object.values(metricList).some((list) => list.length) && curHeaderOptions) { setLoading(true); getMetricChartData(); } else { setMetricChartData([]); setLoading(false); } }, [metricList]); useEffect(() => { getScopeList(); }, []); return (
metricFilterRef.current?.open()} nodeSelect={{ name: 'Connect', customContent: , }} setScreenType={setScreenType} /> { const res: { [key: string]: (string | number)[] } = {}; list.forEach(({ type, name, set }) => { set && (res[type] ? res[type].push(name) : (res[type] = [name])); }); setMetricList(res); }} onRankChange={(rankList) => { metricRankList.current = rankList; }} /> {/* 图表详情 */}
); }; const ConnectDashboard = (): JSX.Element => { const [global] = AppContainer.useGlobalValue(); return ( <>
<> ); }; export default ConnectDashboard;