Parcourir la source

六统一监控可视化统一接入

hm il y a 2 mois
Parent
commit
5bf9b45fe3

+ 1 - 1
package.json

@@ -36,7 +36,7 @@
     "url": "https://gitee.com/y_project/RuoYi-Vue.git"
   },
   "dependencies": {
-    "@antv/g6": "^5.0.42",
+    "@antv/x6": "^2.18.1",
     "@riophae/vue-treeselect": "0.4.0",
     "axios": "0.24.0",
     "clipboard": "2.0.8",

+ 21 - 0
src/api/unified-resources/link-monitor/visualMonitor.js

@@ -0,0 +1,21 @@
+import request from "@/utils/request";
+
+// 统一接入
+export function getLookMonitor(query) {
+  return request({
+    url: "/web/lookMonitor/getLookMonitor",
+    method: "get",
+    params: query,
+  });
+}
+
+
+// 统一接口监控状态监听
+export function getLookMonitorByUrlAndStatus(query) {
+    return request({
+      url: "/web/lookMonitor/getLookMonitorByUrlAndStatus",
+      method: "get",
+      params: query,
+    });
+  }
+  

Fichier diff supprimé car celui-ci est trop grand
+ 1405 - 0
src/views/unified-resources/link-monitor/link-monitor-center/components/VisualMonitor copy 2.vue


Fichier diff supprimé car celui-ci est trop grand
+ 1501 - 0
src/views/unified-resources/link-monitor/link-monitor-center/components/VisualMonitor copy.vue


+ 521 - 42
src/views/unified-resources/link-monitor/link-monitor-center/components/VisualMonitor.vue

@@ -88,7 +88,7 @@
             :data="userTableData"
             stripe
             style="width: 100%"
-            max-height="200"
+            max-height="120"
           >
             <el-table-column prop="date" label></el-table-column>
             <el-table-column
@@ -100,6 +100,7 @@
         </div>
         <div class="left_bottom">
           <div class="title">接入</div>
+          <div ref="graphChartRef" class="graph_content"></div>
         </div>
       </div>
 
@@ -112,46 +113,64 @@
               <div class="grid-content2_top_item1_title">今日API接入总量</div>
               <div class="grid-content2_top_item1_count">
                 <div>接口数量</div>
-                <div class="grid-content2_top_item1_num">169</div>
+                <div class="grid-content2_top_item1_num">
+                  {{ this.unifiedAccessObj.api.num }}
+                </div>
               </div>
               <div class="grid-content2_top_item1_count">
-                <div>转发数量</div>
+                <div>业务量</div>
                 <div class="grid-content2_top_item1_num">
-                  <span>55</span>/23
+                  <span>
+                    {{ this.unifiedAccessObj.api.business }}
+                  </span>
                 </div>
               </div>
             </div>
             <div class="grid-content2_top_item1">
               <div class="grid-content2_top_item1_title">库表接入总量</div>
               <div class="grid-content2_top_item1_count">
-                <div>接口数量</div>
-                <div class="grid-content2_top_item1_num">169</div>
+                <div>MIDDB</div>
+                <div class="grid-content2_top_item1_num">
+                  {{ this.unifiedAccessObj.kb.num }}
+                </div>
               </div>
               <div class="grid-content2_top_item1_count">
-                <div>转发数量</div>
-                <div class="grid-content2_top_item1_num">55/23</div>
+                <div>JKCLOUD</div>
+                <div class="grid-content2_top_item1_num">
+                  <span>
+                    {{ this.unifiedAccessObj.kb.business }}
+                  </span>
+                </div>
               </div>
             </div>
             <div class="grid-content2_top_item1">
               <div class="grid-content2_top_item1_title">Kafka topic总量</div>
               <div class="grid-content2_top_item1_count">
-                <div>接口数量</div>
-                <div class="grid-content2_top_item1_num">169</div>
+                <div>topic数量</div>
+                <div class="grid-content2_top_item1_num">
+                  {{ this.unifiedAccessObj.kafka.num }}
+                </div>
               </div>
               <div class="grid-content2_top_item1_count">
-                <div>转发数量</div>
-                <div class="grid-content2_top_item1_num">55/23</div>
+                <div>入湖</div>
+                <div class="grid-content2_top_item1_num">
+                  <span>
+                    {{ this.unifiedAccessObj.kafka.business }}
+                  </span>
+                </div>
               </div>
             </div>
             <div class="grid-content2_top_item1">
               <div class="grid-content2_top_item1_title">文件</div>
               <div class="grid-content2_top_item1_count">
-                <div>接口数量</div>
-                <div class="grid-content2_top_item1_num">169</div>
+                <div>数据源</div>
+                <div class="grid-content2_top_item1_num">100</div>
               </div>
               <div class="grid-content2_top_item1_count">
-                <div>转发数量</div>
-                <div class="grid-content2_top_item1_num">55/23</div>
+                <div>数据接收</div>
+                <div class="grid-content2_top_item1_num">
+                  <span>100</span>
+                </div>
               </div>
             </div>
           </div>
@@ -164,7 +183,9 @@
                 />
                 <div>
                   <div class="grid-content2_top_item2_status_title">异常</div>
-                  <div class="grid-content2_top_item2_num_danger">16</div>
+                  <div class="grid-content2_top_item2_num_danger">
+                    {{ this.unifiedAccessObj.four.error }}
+                  </div>
                 </div>
               </div>
               <div class="grid-content2_top_item2_status_danger"></div>
@@ -179,7 +200,8 @@
                 <div>
                   <div class="grid-content2_top_item2_status_title">最高</div>
                   <div class="grid-content2_top_item2_num_success">
-                    1209<span>ms</span>
+                    {{ this.unifiedAccessObj.four.big }}
+                    <span>ms</span>
                   </div>
                 </div>
               </div>
@@ -194,7 +216,7 @@
                 <div>
                   <div class="grid-content2_top_item2_status_title">平均</div>
                   <div class="grid-content2_top_item2_num_primary">
-                    1012.8<span>ms</span>
+                    {{ this.unifiedAccessObj.four.average }}
                   </div>
                 </div>
               </div>
@@ -209,7 +231,7 @@
                 <div>
                   <div class="grid-content2_top_item2_status_title">最低</div>
                   <div class="grid-content2_top_item2_num_warning">
-                    803<span>ms</span>
+                    {{ this.unifiedAccessObj.four.small }}
                   </div>
                 </div>
               </div>
@@ -337,24 +359,39 @@
                 <span>统一接口监控状态监听</span>
               </div>
               <div class="tab_table">
-                <div class="tab_img" :class="{ tab_active: true }">
-                  存储空间
+                <div
+                  class="tab_img"
+                  :class="{ tab_active: tabActive === 1 }"
+                  @click="InterfaceChange(1)"
+                >
+                  API状态
+                </div>
+                <div
+                  class="tab_img"
+                  :class="{ tab_active: tabActive === 2 }"
+                  @click="InterfaceChange(2)"
+                >
+                  监控预警
                 </div>
-                <div class="tab_img" :class="{ tab_active: '' }">监控预警</div>
               </div>
               <el-table
-                :data="userTableData"
+                :data="unifiedInterfaceStatusData"
                 stripe
                 style="width: 100%"
                 max-height="200"
               >
                 <el-table-column type="index" width="50"></el-table-column>
-                <el-table-column prop="name" label="接口"></el-table-column>
-                <el-table-column
-                  prop="name"
-                  label="状态"
-                  width="80"
-                ></el-table-column>
+                <el-table-column prop="url" label="接口"></el-table-column>
+                <el-table-column prop="status" label="状态" width="80">
+                  <template slot-scope="scope">
+                    <el-tag type="success" v-if="+scope.row.status === 1"
+                      >正常</el-tag
+                    >
+                    <el-tag type="danger" v-if="+scope.row.status === 0"
+                      >不正常</el-tag
+                    >
+                  </template>
+                </el-table-column>
               </el-table>
             </div>
           </div>
@@ -366,9 +403,45 @@
 
 <script>
 import * as echarts from "echarts";
+import {
+  getLookMonitor,
+  getLookMonitorByUrlAndStatus,
+} from "@/api/unified-resources/link-monitor/visualMonitor.js";
+// 动态改变节点的大小来模拟呼吸动画
+let scaleFactor = 1;
+let increasing = true;
 export default {
   data() {
     return {
+      tabActive: 1,
+      unifiedInterfaceStatusData: [],
+      unifiedAccessObj: {
+        four: {
+          big: 32,
+          average: 16,
+          small: 1,
+          error: 1,
+        },
+        kb: {
+          num: 1,
+          business: 1,
+          url: null,
+          status: null,
+        },
+        kafka: {
+          num: 1,
+          business: 123,
+          url: null,
+          status: null,
+        },
+        api: {
+          num: 2,
+          business: 2,
+          url: null,
+          status: null,
+        },
+      },
+      userTableData: [],
       hotUse: [3, 5],
       // 热点应用
       hotChartData: [
@@ -422,16 +495,65 @@ export default {
         { title: "数据目录" },
       ],
       tabData: [{ title: "存储空间" }, { title: "监控预警" }],
+
+      chart: null,
+      nodes: [
+        {
+          id: "center",
+          name: "市疫情控",
+          x: 400,
+          y: 300,
+          symbolSize: 50,
+          children: [
+            { id: "node1", name: "长三角(昆山)", x: 200, y: 150 },
+            { id: "node2", name: "大数据中心", x: 600, y: 150 },
+            { id: "node3", name: "卫建委", x: 200, y: 450 },
+            { id: "node4", name: "长三角(嘉善)", x: 600, y: 450 },
+            { id: "node5", name: "各卫生医疗机构", x: 600, y: 450 },
+          ],
+        },
+      ],
+      colorPool: [
+        "#ff4d4f",
+        "#52c41a",
+        "#1890ff",
+        "#fadb14",
+        "#13c2c2",
+        "#722ed1",
+        "#fa8c16",
+      ], // 预定义的颜色池
     };
   },
   mounted() {
+    this.getUnifiedAccess();
+    this.getUnifiedInterfaceStatusMonitor();
+
     this.initHotChart();
     this.initBrowserChart();
 
     this.drawShape();
-    // this.initBarChart()
+    this.initGraphChart();
   },
   methods: {
+    //统一接入
+    getUnifiedAccess() {
+      getLookMonitor().then((res) => {
+        if (+res.code === 200) {
+          this.unifiedAccessObj = res.data;
+        }
+      });
+    },
+    // 统一接口监控状态监听
+    getUnifiedInterfaceStatusMonitor() {
+      getLookMonitorByUrlAndStatus().then((res) => {
+        if (+res.code === 200) {
+          this.unifiedInterfaceStatusData = res.data;
+        }
+      });
+    },
+    InterfaceChange(type) {
+      this.tabActive = type;
+    },
     initHotChart() {
       const chart = echarts.init(this.$refs.hot_chart);
       const data = this.hotChartData;
@@ -679,7 +801,7 @@ export default {
 
       chart.setOption(option);
     },
- initBarChart() {
+    initBarChart() {
       const chart = echarts.init(this.$refs.bar_chart);
       const data = this.chartData;
 
@@ -699,9 +821,8 @@ export default {
           data: data.map((item) => item.name),
           axisLabel: { color: "#333" },
           axisTick: {
-        show: false, // 隐藏 X 轴刻度线
-      },
-
+            show: false, // 隐藏 X 轴刻度线
+          },
         },
 
         yAxis: {
@@ -711,7 +832,7 @@ export default {
             color: "#333",
           },
           splitLine: {
-            lineStyle: { type: "dashed", color: "#e5f0fc" }
+            lineStyle: { type: "dashed", color: "#e5f0fc" },
           },
         },
         tooltip: {
@@ -894,6 +1015,297 @@ export default {
       echarts.graphic.registerShape("topShape", topShape);
       this.initBarChart();
     },
+
+    // initGraphChart() {
+    //   const container = this.$refs.graphChartRef;
+    //   if (!container) return;
+
+    //   // 初始化 ECharts 实例
+    //   const myChart = echarts.init(container);
+
+    //    // 设置图表配置项
+    //    const option = {
+    //     tooltip: {
+    //       trigger: 'item',
+    //     },
+    //     animation: true,
+    //     series: [
+    //       {
+    //         type: 'graph',
+    //         layout: 'none',  // 设置布局为无布局
+    //         symbolSize: 40,  // 节点大小
+    //         roam: true,
+    //         edgeSymbol: ['none', 'arrow'],
+    //         edgeSymbolSize: [4, 10],
+    //         lineStyle: {
+    //           type: 'solid', // 设置边为实线
+    //           width: 2, // 设置边宽
+    //           color: '#000', // 设置边颜色
+    //         },
+    //         // 设置边为平滑曲线
+    //         edgeShape: 'curve',  // 使用曲线
+    //         smooth: 0.9,  // 控制曲线的平滑程度,值在 0 到 1 之间
+    //         data: [
+    //           {
+    //             id: 'parent',
+    //             name: '中心节点',
+    //             x: 300,
+    //             y: 300,
+    //             symbol: 'circle', // 圆形节点
+    //             symbolSize: 60,
+    //             itemStyle: {
+    //               color: 'blue',
+    //               borderColor: 'blue',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //           {
+    //             id: 'node1',
+    //             name: '子节点1',
+    //             symbol: 'circle', // 圆形节点
+    //             itemStyle: {
+    //               color: 'orange',
+    //               borderColor: 'orange',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //           {
+    //             id: 'node2',
+    //             name: '子节点2',
+    //             symbol: 'circle', // 圆形节点
+    //             itemStyle: {
+    //               color: 'green',
+    //               borderColor: 'green',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //           {
+    //             id: 'node3',
+    //             name: '子节点3',
+    //             symbol: 'circle', // 圆形节点
+    //             itemStyle: {
+    //               color: 'red',
+    //               borderColor: 'red',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //           {
+    //             id: 'node4',
+    //             name: '子节点4',
+    //             symbol: 'circle', // 圆形节点
+    //             itemStyle: {
+    //               color: 'purple',
+    //               borderColor: 'purple',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //           {
+    //             id: 'node5',
+    //             name: '子节点5',
+    //             symbol: 'circle', // 圆形节点
+    //             itemStyle: {
+    //               color: 'purple',
+    //               borderColor: 'purple',
+    //               borderWidth: 5,
+    //             },
+    //             label: {
+    //               show: true,
+    //               position: 'top',  // 标签在节点下方
+    //               color: '#000',
+    //             },
+    //           },
+    //         ],
+    //         edges: [
+    //           { source: 'parent', target: 'node1' },
+    //           { source: 'parent', target: 'node2' },
+    //           { source: 'parent', target: 'node3' },
+    //           { source: 'parent', target: 'node4' },
+    //           { source: 'parent', target: 'node5' },
+    //         ],
+    //       },
+    //     ],
+    //   };
+
+    //   // 在这里手动计算节点的 `x` 和 `y` 坐标来实现辐射效果
+    //   const radius = 200; // 调整半径,拉长连线
+    //   const centerX = 300; // 中心点的 X 坐标
+    //   const centerY = 300; // 中心点的 Y 坐标
+    //   const nodes = option.series[0].data;
+
+    //   nodes.slice(1).forEach((node, index) => {
+    //     const angle = (index / (nodes.length - 1)) * Math.PI * 2;
+    //     node.x = centerX + Math.cos(angle) * radius;
+    //     node.y = centerY + Math.sin(angle) * radius;
+    //   });
+
+    //   // 设置配置项
+    //   myChart.setOption(option);
+
+    //   // 监听窗口变化,调整图表大小
+    //   window.addEventListener('resize', () => {
+    //     myChart.resize();
+    //   });
+    // },
+
+    // ============================================
+
+    initGraphChart() {
+      this.chart = echarts.init(this.$refs.graphChartRef);
+      const option = {
+        series: [
+          {
+            type: "graph",
+            layout: "force",
+            force: {
+              repulsion: 500, // 增加排斥力,增大节点间的距离
+              edgeLength: [60, 200], // 增加连线的距离
+              layoutAnimation: true,
+            },
+            symbolSize: 50, // 默认节点大小
+            roam: true,
+            label: {
+              show: true,
+              position: "top", // 标签放在节点上方
+              color: "#000", // 文字颜色为黑色
+            },
+            data: this.createNodes(),
+            links: this.createLinks(),
+            lineStyle: {
+              curveness: 0.3, // 适度的曲线连接线
+              color: "source", // 连接线颜色
+              width: 2,
+            },
+            itemStyle: {
+              borderWidth: 3, // 边框宽度
+              opacity: 0.9, // 保持不透明
+              shadowColor: "rgba(0, 0, 0, 0.3)",
+              shadowBlur: 10,
+            },
+          },
+        ],
+      };
+      this.chart.setOption(option);
+
+    },
+
+
+
+
+
+
+    // 动态生成节点,父节点比子节点大
+    createNodes() {
+      const nodes = [];
+      let colorIndex = 0; // 颜色池索引
+      this.nodes.forEach((node) => {
+        nodes.push({
+          id: node.id,
+          name: node.name,
+          x: node.x,
+          y: node.y,
+          symbolSize: node.symbolSize, // 父节点大于子节点
+          itemStyle: {
+            color: this.colorPool[colorIndex % this.colorPool.length],
+            borderColor: this.colorPool[colorIndex % this.colorPool.length],
+            borderWidth: 3,
+            opacity: 0.9,
+            shadowColor: "rgba(0, 0, 0, 0.3)",
+            shadowBlur: 10,
+            borderType: "solid",
+            // 增加渐变色的效果
+            borderColor: new echarts.graphic.LinearGradient(0, 0, 1, 1, [
+              { offset: 0, color: "#ff4d4f" }, // 渐变起始颜色
+              { offset: 1, color: "#fa8c16" }, // 渐变结束颜色
+            ]),
+          },
+          label: {
+            show: true,
+            position: "top",
+            color: "#000", // 文字为黑色
+            fontWeight: "bold",
+          },
+          animation: {
+            duration: 2000, // 设置动画时长为2秒
+            easing: "easeInOutSine",
+            loop: true, // 无限循环
+            scale: [1, 1.5], // 节点从 1x 到 1.5x 放大
+          },
+        });
+        colorIndex++; // 增加颜色池索引
+        if (node.children) {
+          node.children.forEach((child) => {
+            nodes.push({
+              id: child.id,
+              name: child.name,
+              x: child.x,
+              y: child.y,
+              symbolSize: 40, // 子节点小于父节点
+              itemStyle: {
+                color: this.colorPool[colorIndex % this.colorPool.length],
+                borderColor: this.colorPool[colorIndex % this.colorPool.length],
+                borderWidth: 3,
+                opacity: 0.8,
+              },
+              animation: {
+                duration: 2000, // 设置动画时长为2秒
+                easing: "easeInOutSine",
+                loop: true, // 无限循环
+                scale: [1, 1.5], // 节点从 1x 到 1.5x 放大
+              },
+              label: {
+                show: true,
+                position: "top",
+                color: "#000",
+              },
+            });
+            colorIndex++;
+          });
+        }
+      });
+      return nodes;
+    },
+    // 创建连线,连接父节点和子节点
+    createLinks() {
+      const links = [];
+      this.nodes.forEach((node) => {
+        if (node.children) {
+          node.children.forEach((child) => {
+            links.push({
+              source: node.id,
+              target: child.id,
+            });
+          });
+        }
+      });
+      return links;
+    },
+
+    
   },
 };
 </script>
@@ -923,7 +1335,6 @@ export default {
     no-repeat;
   background-size: 100% 100%;
   color: #ffffff;
-
 }
 
 .small_title {
@@ -959,6 +1370,8 @@ export default {
 }
 
 .grid-content1 {
+  display: flex;
+  flex-direction: column;
   width: 574px;
   //   height: 500px;
   // height: calc(100vh - 80px);
@@ -968,10 +1381,10 @@ export default {
   .left_top {
     box-sizing: border-box;
     width: 574px;
-    height: 400px;
+    height: 370px;
     background: rgba(255, 255, 255, 0.7);
     box-shadow: 0px 2px 15px 1px rgba(0, 26, 52, 0.08);
-    padding: 20px;
+    padding: 15px;
 
     .use_content {
       //   height: 200px;
@@ -1021,17 +1434,23 @@ export default {
     }
   }
   .left_center {
+    height: 200px;
     background: rgba(255, 255, 255, 0.7);
     box-shadow: 0px 2px 15px 1px rgba(0, 26, 52, 0.08);
-    padding: 20px;
+    padding: 15px;
     box-sizing: border-box;
-    margin: 20px 0;
+    margin: 10px 0;
   }
   .left_bottom {
+    flex: 1;
     background: rgba(255, 255, 255, 0.7);
     box-shadow: 0px 2px 15px 1px rgba(0, 26, 52, 0.08);
     padding: 20px;
     box-sizing: border-box;
+    .graph_content {
+      height: calc(100% - 30px);
+      width: 100%;
+    }
   }
 }
 
@@ -1048,7 +1467,7 @@ export default {
     box-shadow: 0px 2px 15px 1px rgba(0, 26, 52, 0.08);
     padding: 20px;
     box-sizing: border-box;
-    margin-bottom: 20px;
+    margin-bottom: 10px;
     .grid-content2_top_box1 {
       display: flex;
       justify-content: space-between;
@@ -1342,4 +1761,64 @@ export default {
   text-align: center;
   line-height: 31px;
 }
+
+/* 呼吸动画效果,每次初始化时播放 */
+// @keyframes breathing {
+//   0% {
+//     transform: scale(1);
+//   }
+//   50% {
+//     transform: scale(1.2); /* 放大效果 */
+//   }
+//   100% {
+//     transform: scale(1);
+//   }
+// }
+
+// /* 添加持续的呼吸动画 */
+// .node {
+//   animation: breathing 2s ease-in-out infinite; /* 无限循环动画 */
+// }
+
+// =======================
+/* 自定义呼吸动画 */
+@keyframes breathe {
+  0% {
+    transform: scale(1);
+    opacity: 0.9;
+  }
+  50% {
+    transform: scale(1.2);
+    opacity: 1;
+  }
+  100% {
+    transform: scale(1);
+    opacity: 0.9;
+  }
+}
+
+/* 呼吸动画效果,适用于节点 */
+.node {
+  animation: breathe 3s infinite ease-in-out;
+}
+
+/* 使用渐变颜色边框 */
+.node-item {
+  border-color: transparent;
+  border-style: solid;
+  border-width: 20px;
+  animation: gradient-border 3s infinite;
+}
+
+@keyframes gradient-border {
+  0% {
+    border-color: #ff4d4f;
+  }
+  50% {
+    border-color: #13c2c2;
+  }
+  100% {
+    border-color: #ff4d4f;
+  }
+}
 </style>