Ver código fonte

feat(merge): merge xyh

Next xyh
Lind 3 anos atrás
pai
commit
eb81dc0835

+ 6 - 2
src/components/DashBoard/baseCard.tsx

@@ -4,11 +4,12 @@ import type { EchartsProps } from './echarts';
 import Echarts from './echarts';
 import Style from './index.less';
 import classNames from 'classnames';
-import { forwardRef } from 'react';
+import React, { forwardRef } from 'react';
 
 interface BaseCardProps extends HeaderProps, EchartsProps {
   height: number;
   className?: string;
+  echartsAfter?: React.ReactNode;
 }
 
 export default forwardRef((props: BaseCardProps, ref) => {
@@ -22,7 +23,10 @@ export default forwardRef((props: BaseCardProps, ref) => {
       }}
     >
       <Header ref={ref} {...formProps} />
-      <Echarts options={options} className={Style['echarts']} />
+      <div className={Style['echarts-content']}>
+        <Echarts options={options} className={Style['echarts']} />
+        {props.echartsAfter}
+      </div>
     </div>
   );
 });

+ 4 - 3
src/components/DashBoard/echarts.tsx

@@ -1,4 +1,4 @@
-import { useEffect, useRef } from 'react';
+import { useCallback, useEffect, useRef } from 'react';
 import * as echarts from 'echarts/core';
 import type { ECharts, EChartsOption } from 'echarts';
 import {
@@ -72,11 +72,12 @@ export default (props: EchartsProps) => {
     }
   };
 
-  const updateOptions = () => {
+  const updateOptions = useCallback(() => {
+    console.log(chartsRef.current, props.options);
     if (chartsRef.current && props.options) {
       chartsRef.current.setOption(props.options);
     }
-  };
+  }, [props.options]);
 
   useEffect(() => {
     (window as Window).addEventListener('resize', updateSize);

+ 7 - 1
src/components/DashBoard/index.less

@@ -26,8 +26,14 @@
   height: 100%;
 }
 
-.echarts {
+.echarts-content {
+  display: flex;
   flex-grow: 1;
   height: 0;
   margin-top: 12px;
 }
+
+.echarts {
+  flex: 1;
+  height: 100%;
+}

+ 30 - 0
src/pages/link/DashBoard/index.less

@@ -0,0 +1,30 @@
+.link-dash-board {
+  background-color: #fff;
+
+  .echarts-items {
+    position: relative;
+    display: flex;
+    gap: 12px;
+    margin: 12px 0;
+
+    .echarts-item {
+      display: flex;
+      flex-grow: 1;
+      align-items: center;
+      justify-content: center;
+      width: 0;
+      height: 160px;
+
+      .echarts-item-title {
+        margin-bottom: 8px;
+        color: rgba(#000, 0.6);
+        font-size: 16px;
+      }
+
+      .echarts-item-value {
+        font-weight: bold;
+        font-size: 18px;
+      }
+    }
+  }
+}

+ 351 - 38
src/pages/link/DashBoard/index.tsx

@@ -1,10 +1,14 @@
 import { PageContainer } from '@ant-design/pro-layout';
 import DashBoard from '@/components/DashBoard';
-import { Radio, Select } from 'antd';
+import { Radio, Select, Progress } from 'antd';
 import { useEffect, useRef, useState } from 'react';
 import type { EChartsOption } from 'echarts';
 import { useRequest } from 'umi';
 import Service from './service';
+import moment from 'moment';
+import './index.less';
+import useSendWebsocketMessage from '@/hooks/websocket/useSendWebsocketMessage';
+import { map } from 'rxjs/operators';
 
 type RefType = {
   getValues: Function;
@@ -13,23 +17,136 @@ type RefType = {
 const service = new Service('dashboard');
 
 export default () => {
-  const [networkOptions] = useState<EChartsOption | undefined>(undefined);
-  const [cpuOptions] = useState<EChartsOption | undefined>(undefined);
-  const [jvmOptions] = useState<EChartsOption | undefined>(undefined);
+  const [networkOptions, setNetworkOptions] = useState<EChartsOption | undefined>(undefined);
+  const [cpuOptions, setCpuOptions] = useState<EChartsOption | undefined>(undefined);
+  const [jvmOptions, setJvmOptions] = useState<EChartsOption | undefined>(undefined);
   const [serverId, setServerId] = useState(undefined);
 
+  const [topValues, setTopValues] = useState({
+    cpu: 0,
+    jvm: 0,
+    usage: 0,
+    systemUsage: 0,
+  });
+
   const NETWORKRef = useRef<RefType>(); // 网络流量
   const CPURef = useRef<RefType>(); // CPU使用率
   const JVMRef = useRef<RefType>(); // JVM内存使用率
 
+  const [subscribeTopic] = useSendWebsocketMessage();
+
   const { data: serverNode } = useRequest(service.serverNode, {
     formatResult: (res) => res.result.map((item: any) => ({ label: item.name, value: item.id })),
   });
 
-  const getNetworkEcharts = () => {
-    const data = NETWORKRef.current!.getValues();
-    if (data) {
-      service.queryMulti([
+  const handleNetworkOptions = (data: Record<string, any>) => {
+    setNetworkOptions({
+      xAxis: {
+        type: 'category',
+        data: Object.keys(data),
+      },
+      tooltip: {
+        trigger: 'axis',
+      },
+      yAxis: {
+        type: 'value',
+      },
+      grid: {
+        left: '3%',
+        right: '2%',
+      },
+      series: [
+        {
+          data: Object.values(data),
+          type: 'line',
+        },
+      ],
+    });
+  };
+
+  const handleJVMOptions = (data: Record<string, any>) => {
+    setJvmOptions({
+      xAxis: {
+        type: 'category',
+        data: Object.keys(data).map((item) => {
+          return moment(Number(item)).format('YYYY-MM-DD HH:mm:ss');
+        }),
+      },
+      tooltip: {
+        trigger: 'axis',
+      },
+      yAxis: {
+        type: 'value',
+      },
+      grid: {
+        left: '3%',
+        right: '2%',
+      },
+      dataZoom: [
+        {
+          type: 'inside',
+          start: 0,
+          end: 10,
+        },
+        {
+          start: 0,
+          end: 10,
+        },
+      ],
+      series: [
+        {
+          data: Object.values(data),
+          type: 'line',
+        },
+      ],
+    });
+  };
+
+  const handleCpuOptions = (data: Record<string, any>) => {
+    setCpuOptions({
+      xAxis: {
+        type: 'category',
+        data: Object.keys(data).map((item) => {
+          return moment(Number(item)).format('YYYY-MM-DD HH:mm:ss');
+        }),
+      },
+      tooltip: {
+        trigger: 'axis',
+      },
+      yAxis: {
+        type: 'value',
+      },
+      grid: {
+        left: '3%',
+        right: '2%',
+      },
+      dataZoom: [
+        {
+          type: 'inside',
+          start: 0,
+          end: 10,
+        },
+        {
+          start: 0,
+          end: 10,
+        },
+      ],
+      series: [
+        {
+          data: Object.values(data),
+          type: 'line',
+        },
+      ],
+    });
+  };
+
+  const getAllEcharts = () => {
+    const networkData = NETWORKRef.current!.getValues();
+    const cpuData = CPURef.current!.getValues();
+    const jvmData = JVMRef.current!.getValues();
+
+    service
+      .queryMulti([
         {
           dashboard: 'systemMonitor',
           object: 'network',
@@ -37,57 +154,195 @@ export default () => {
           dimension: 'agg',
           group: 'network',
           params: {
-            type: data.type,
-            from: data.time.start,
-            to: data.time.end,
+            type: networkData.type,
+            interval: networkData.time.type === 'today' ? '1h' : '1d',
+            from: networkData.time.start,
+            to: networkData.time.end,
           },
         },
-      ]);
-    }
-  };
-
-  const getCPUEcharts = () => {
-    const data = CPURef.current!.getValues();
-    if (data) {
-      service.queryMulti([
         {
           dashboard: 'systemMonitor',
           object: 'stats',
-          measurement: 'traffic',
-          dimension: 'agg',
+          measurement: 'info',
+          dimension: 'history',
           group: 'cpu',
           params: {
-            from: data.time.start,
-            to: data.time.end,
+            from: cpuData.time.start,
+            to: cpuData.time.end,
           },
         },
-      ]);
-    }
-  };
-
-  const getJVMEcharts = () => {
-    const data = CPURef.current!.getValues();
-    if (data) {
-      service.queryMulti([
         {
           dashboard: 'systemMonitor',
           object: 'stats',
-          measurement: 'traffic',
-          dimension: 'agg',
+          measurement: 'info',
+          dimension: 'history',
           group: 'jvm',
           params: {
-            from: data.time.start,
-            to: data.time.end,
+            from: jvmData.time.start,
+            to: jvmData.time.end,
           },
         },
-      ]);
+      ])
+      .then((res) => {
+        if (res.status === 200) {
+          const _networkOptions = {};
+          const _jvmOptions = {};
+          const _cpuOptions = {};
+
+          res.result.forEach((item: any) => {
+            const value = item.data.value;
+            if (item.group === 'network') {
+              value.forEach((networkItem: any) => {
+                _networkOptions[networkItem.timeString] = networkItem.value;
+              });
+            } else if (item.group === 'cpu') {
+              const memoryJvmHeapFree = value.memoryJvmHeapFree;
+              const memoryJvmHeapTotal = value.memoryJvmHeapTotal;
+              _jvmOptions[value.timestamp] = (
+                ((memoryJvmHeapTotal - memoryJvmHeapFree) / memoryJvmHeapTotal) *
+                100
+              ).toFixed(2);
+            } else {
+              _cpuOptions[value.timestamp] = value.cpuSystemUsage;
+            }
+          });
+          handleNetworkOptions(_networkOptions);
+          handleJVMOptions(_jvmOptions);
+          handleCpuOptions(_cpuOptions);
+        }
+      });
+  };
+
+  const getNetworkEcharts = () => {
+    const data = NETWORKRef.current!.getValues();
+    if (data) {
+      service
+        .queryMulti([
+          {
+            dashboard: 'systemMonitor',
+            object: 'network',
+            measurement: 'traffic',
+            dimension: 'agg',
+            group: 'network',
+            params: {
+              type: data.type,
+              interval: data.time.type === 'today' ? '1h' : '1d',
+              from: data.time.start,
+              to: data.time.end,
+            },
+          },
+        ])
+        .then((res) => {
+          if (res.status === 200) {
+            const _options = {};
+            res.result.forEach((item: any) => {
+              const value = item.data.value;
+              value.forEach((networkItem: any) => {
+                _options[networkItem.timeString] = networkItem.value;
+              });
+            });
+            handleNetworkOptions(_options);
+          }
+        });
+    }
+  };
+
+  const getCPUEcharts = () => {
+    const data = CPURef.current!.getValues();
+    if (data) {
+      service
+        .queryMulti([
+          {
+            dashboard: 'systemMonitor',
+            object: 'stats',
+            measurement: 'info',
+            dimension: 'history',
+            group: 'cpu',
+            params: {
+              from: data.time.start,
+              to: data.time.end,
+            },
+          },
+        ])
+        .then((res) => {
+          if (res.status === 200) {
+            const _options = {};
+            res.result.forEach((item: any) => {
+              const value = item.data.value;
+              _options[value.timestamp] = value.cpuSystemUsage;
+            });
+            handleCpuOptions(_options);
+          }
+        });
+    }
+  };
+
+  const getJVMEcharts = () => {
+    const data = JVMRef.current!.getValues();
+    if (data) {
+      service
+        .queryMulti([
+          {
+            dashboard: 'systemMonitor',
+            object: 'stats',
+            measurement: 'info',
+            dimension: 'history',
+            group: 'jvm',
+            params: {
+              from: data.time.start,
+              to: data.time.end,
+            },
+          },
+        ])
+        .then((res) => {
+          if (res.status === 200) {
+            const _options = {};
+            res.result.forEach((item: any) => {
+              const value = item.data.value;
+              const memoryJvmHeapFree = value.memoryJvmHeapFree;
+              const memoryJvmHeapTotal = value.memoryJvmHeapTotal;
+              _options[value.timestamp] = (
+                ((memoryJvmHeapTotal - memoryJvmHeapFree) / memoryJvmHeapTotal) *
+                100
+              ).toFixed(2);
+            });
+            handleJVMOptions(_options);
+          }
+        });
     }
   };
 
   useEffect(() => {
     if (serverId) {
-      getNetworkEcharts();
+      getAllEcharts();
     }
+
+    const id = 'operations-statistics-system-info-realTime';
+    const topic = '/dashboard/systemMonitor/stats/info/realTime';
+    const sub = subscribeTopic!(id, topic, {
+      type: 'all',
+      serverNodeId: serverId,
+      interval: '5s',
+      agg: 'avg',
+    })
+      ?.pipe(map((res) => res.payload))
+      .subscribe((plyload: any) => {
+        const value = plyload.value;
+        const cpu = value.cpu;
+        const memory = value.memory;
+        const disk = value.disk;
+
+        setTopValues({
+          cpu: cpu.systemUsage,
+          jvm: memory.jvmHeapUsage,
+          usage: disk.usage,
+          systemUsage: memory.systemUsage,
+        });
+      });
+
+    return () => {
+      sub?.unsubscribe();
+    };
   }, [serverId]);
 
   useEffect(() => {
@@ -98,7 +353,7 @@ export default () => {
 
   return (
     <PageContainer>
-      <div>
+      <div className={'link-dash-board'}>
         {serverNode && serverNode.length ? (
           <Select
             value={serverId}
@@ -109,6 +364,64 @@ export default () => {
             style={{ width: 300 }}
           />
         ) : null}
+        <div className={'echarts-items'}>
+          <div className={'echarts-item'}>
+            <Progress
+              type="circle"
+              strokeWidth={8}
+              width={160}
+              percent={topValues.cpu}
+              format={(percent) => (
+                <div>
+                  <div className={'echarts-item-title'}>CPU使用率</div>
+                  <div className={'echarts-item-value'}>{percent}%</div>
+                </div>
+              )}
+            />
+          </div>
+          <div className={'echarts-item'}>
+            <Progress
+              type="circle"
+              strokeWidth={8}
+              width={160}
+              percent={topValues.jvm}
+              format={(percent) => (
+                <div>
+                  <div className={'echarts-item-title'}>JVM内存</div>
+                  <div className={'echarts-item-value'}>{percent}%</div>
+                </div>
+              )}
+            />
+          </div>
+          <div className={'echarts-item'}>
+            <Progress
+              type="circle"
+              strokeWidth={8}
+              width={160}
+              percent={topValues.usage}
+              format={(percent) => (
+                <div>
+                  <div className={'echarts-item-title'}>磁盘占用率</div>
+                  <div className={'echarts-item-value'}>{percent}%</div>
+                </div>
+              )}
+            />
+          </div>
+          <div className={'echarts-item'}>
+            <Progress
+              type="circle"
+              strokeWidth={8}
+              width={160}
+              percent={topValues.systemUsage}
+              format={(percent) => (
+                <div>
+                  <div className={'echarts-item-title'}>系统内存</div>
+                  <div className={'echarts-item-value'}>{percent}%</div>
+                </div>
+              )}
+            />
+          </div>
+        </div>
         <div>
           <DashBoard
             title={'网络流量'}