npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

yhsz_cpts

v1.8.4

Published

![alt text](https://s3.bmp.ovh/imgs/2025/03/19/20d0760addfaff77.png)

Readme

一,LinkReview 自动布局拓扑组件

完整功能

alt text

  • html
<LinkReview
  graphTitle="链路图总览"
  :showToolBar="false"
  timeRange=" 2025-01-27 00:00:00 至 2025-01-27 24:00:00"
  :graphData="graphData"
  :playData="playData"
  :showTimeline="true"
  :statusMap="statusMap"
  :timelineData="timelineData"
  @singleSwitchChange="handleSingleSwitchChange"
  @nodeClick="handleNodeClick"
  warningStatus="important"
>
</LinkReview>
  • ts script
// 定义的statusMap的key需要和节点数据中的status一致,否则不会显示对应状态颜色
const statusMap = {
    normal: { label: "正常", color: "#02E53D" },
    important: { label: "重要", color: "#ED3939" },
    emergency: { label: "紧急", color: "#FF9D00" },
    minor: { label: "次要", color: "#FFE100" },
};

const graphData =
  ref <
  any >
  {
    nodes: [
      {
        id: "0",
        label: "node-0",
        status: "emergency",
        tooltip: [
          // 鼠标覆盖节点展示的tooltip数据
          {
            label: "平均时延(ms)",
            value: "23",
          },
          {
            label: "平均重连率(%)",
            value: "2",
            status: "emergency",
          },
          {
            label: "平均丢包率(%)",
            value: "1.5",
          },
          {
            label: "平均响应时间(ms)",
            value: "12ms",
          },
        ],
      },
      { id: "1", label: "node-1", status: "important" },
      { id: "2", label: "node-2", status: "normal" },
      { id: "3", label: "node-3", status: "minor" },
      { id: "4", label: "node-4", status: "info" },
      { id: "5", label: "node-5" },
      { id: "6", label: "node-6" },
      { id: "7", label: "node-7" },
      { id: "8", label: "node-8" },
      { id: "9", label: "node-9" },
    ],
    edges: [
      {
        id: "0-1",
        source: "0",
        target: "1",
      },
      { id: "1-4", source: "1", target: "4", desc: "238/22ms\n边数据" }, //desc为边的描述数据,可添加换行符
      {
        id: "0-3",
        source: "0",
        target: "3",
        status: "important",
        desc: "238/22ms",
      },
      { id: "3-4", source: "3", target: "4" },
      { id: "4-5", source: "4", target: "5" },
      { id: "6-4", source: "6", target: "4" },
      { id: "4-6", source: "4", target: "6" },
      { id: "5-7", source: "5", target: "7" },
      { id: "5-8", source: "5", target: "8" },
      { id: "8-9", source: "8", target: "9" },
      { id: "2-9", source: "2", target: "9" },
      { id: "4-9", source: "3", target: "9" },
    ],
  };

// 播放数据,播放时需要传入时间戳和对应时间戳的边数组
const playData = ref({
  1672531200123: [
    { id: "0-1", source: "0", target: "1" },
    { id: "1-4", source: "1", target: "4" },
  ],

  1672531200456: [
    { id: "6-4", source: "6", target: "4" },
    { id: "4-5", source: "4", target: "5" },
  ],
});

// 时间轴数据,要播放对应边需要timestamp字段与playData中的timestamp一致
const timelineData =
  ref <
  any >
  [
    { timestamp: 1672531200123, errorNumber: 10, label: "01:00" },
    { timestamp: 1672531200456, errorNumber: 0, label: "02:00" },
    { timestamp: 1672531200789, errorNumber: 300, label: "03:00" },
    { timestamp: 1672531201123, errorNumber: 0, label: "04:00" },
    { timestamp: 1672531201456, errorNumber: 400, label: "05:00" },
    { timestamp: 1672531201789, errorNumber: 0, label: "06:00" },
    { timestamp: 1672531202123, errorNumber: 0, label: "07:00" },
    { timestamp: 1672531202456, errorNumber: 0, label: "08:00" },
    { timestamp: 1672531202789, errorNumber: 0, label: "09:00" },
    { timestamp: 1672531203123, errorNumber: 900, label: "10:00" },
  ];

const handleNodeClick = (v: any) => {
  //do something 如点击节点弹出表格
};

const handleSingleSwitchChange = (v: boolean) => {
  // 更新graph数据 or do something
  console.log("孤立点switch change =", v);
  // 比如说去除node-2节点
  if (v == false) {
    graphData.value.nodes = graphData.value.nodes.filter(
      (node: any) => node.id !== "2"
    );
    graphData.value.edges = graphData.value.edges.filter(
      (edge: any) => edge.source !== "2" && edge.target !== "2"
    );
  } else {
    // 添加节点和连线最好对属性直接赋值。而不是分别修改nodes和edges,这样会导致渲染多次图表,还可能会导致节点位置渲染不正确
    graphData.value = {
      nodes: [
        {
          id: "0",
          label: "node-0",
          status: "emergency",
          tooltip: [
            {
              label: "平均时延(ms)",
              value: "23",
            },
            {
              label: "平均重连率(%)",
              value: "2",
              status: "emergency",
            },
            {
              label: "平均丢包率(%)",
              value: "1.5",
            },
            {
              label: "平均响应时间(ms)",
              value: "12ms",
            },
          ],
        },
        { id: "1", label: "node-1", status: "important" },
        { id: "2", label: "node-2", status: "normal" },
        { id: "3", label: "node-3", status: "minor" },
        { id: "4", label: "node-4", status: "info" },
        { id: "5", label: "node-5" },
        { id: "6", label: "node-6" },
        { id: "7", label: "node-7" },
        { id: "8", label: "node-8" },
        { id: "9", label: "node-9" },
      ],
      edges: [
        {
          id: "0-1",
          source: "0",
          target: "1",
        },
        { id: "1-4", source: "1", target: "4", desc: "238/22ms\n边数据" },
        {
          id: "0-3",
          source: "0",
          target: "3",
          status: "important",
          desc: "238/22ms",
        },
        { id: "3-4", source: "3", target: "4" },
        { id: "4-5", source: "4", target: "5" },
        { id: "6-4", source: "6", target: "4" },
        { id: "4-6", source: "4", target: "6" },
        { id: "5-7", source: "5", target: "7" },
        { id: "5-8", source: "5", target: "8" },
        { id: "8-9", source: "8", target: "9" },
        { id: "2-9", source: "2", target: "9" },
        { id: "4-9", source: "3", target: "9" },
      ],
    };
  }
};

LinkReview API

Attributes

| 名称 | 说明 | 类型 | 默认值 | 是否必须 | | --------------- | ------------------------------- | --------------- | ----------------------------------------------- | -------- | | graphTitle | 标题 | string | 链路图总览 | 否 | | showToolBar | 上方工具栏显隐 | boolean | true | 否 | | timeRange | 上方时间文本 | string | | 否 | | `graphData` | 拓扑图所需数据,edges、nodes 等 | `object` | `[10, 20, 30, 40, 50, 100, 200, 300, 400, 500]` | 是 | | `playData` | 播放数据 | `object` | `{}` | 否 | | `showTimeline` | 播放时间轴显隐 | `boolean` | `true` | 否 | | `timelineData` | 时间轴数据 | `Array<object>` | `[]` | 否 | | `statusMap` | 右下角 legend | `object` | `{}` | 否 | | `warningStatus` | 左上方的 warning 图标;与定义的statusMap的key对应才能展示对应颜色 | `string` | | 否 |

Events

| 名称 | 说明 | 类型 | | ----------------------- | ----------------------- | ---------- | | singleSwitchChange | 切换孤立点 switch 触发 | function | | startNodeSwitchChange | 切换开始节点 switch 触发 | function | | nodeClick | 点击节点触发 | function |


二,TopoDesigner 拓扑编辑器

设计器模式

alt text

<TopoDesigner ref="topoRef" :preview="previewMode"> </TopoDesigner>

锁定节点模式

  • 此模式下,节点位置、点击节点与边展示在右侧抽屉的属性均不能改变,只能拖动画布、查看属性等。

alt text

<TopoDesigner ref="topoRef" :lock="true" />

预览模式

  • 与锁定模式功能类似,只是为了和系统风格统一修改了部分样式

alt text

<TopoDesigner ref="topoRef" :preview="true" />
  • html
<TopoDesigner ref="topoRef" /> 
  • ts script
// 定义TopoDesigner的ref引用
const topoRef = ref();

// 获取数据
topoRef.value?.getData();

// 设置数据(具体数据的格式可以自己拖出来一个拓扑,然后调取getGraphData控制台打印一下);网络建模模块的数据存取我是放在了`DuKang`接口数据中的nodes数组中第一个元素的nodeStyle中了(nodes?.[0]?.nodeStyle),具体见itSystemModeling/networkModeling/detail.vue
topoRef.value?.setData(JSON.parse(data));

// 清空数据
topoRef.value?.setData([]);

// 获取当前antv x6的Graph实例;获取到了实例就可以参考官网API,做一些自定义的操作
topoRef.value?.getInstance();

三,LinkOverview 链路总览组件

  • 主要用于业务监控和业务总体分析模块使用;相当于由上文中的TopoDesigner与LinkReview拼接而成;由于业务需求,网络拓扑需要用户手动拖拉拽创建,所以左侧基于antv x6开发;右侧需要根据接口数据自动排布,所以基于antv g6开发。

  • 最开始的版本右侧是折线模式,后来由于节点与线数据可能会出现过于复杂的情况,会导致各节点之间连线有重合部分导致效果不好,之后根据产品意见改为了曲线形式

基本功能

alt text

  • html
  <LinkOverview
        :graphTitle="`链路图总览`"
        :timeRange="` 2025-01-27 00:00:00 至 2025-01-27 24:00:00`" 
    
        :networkProps="{
          graphData: testData,
        }"

        :appProps="{
          graphData: testData2,
          statusMap: statusMap,
          warningStatus:'important'
        }"
        @networkSingleSwitchChange="
          (val) => {
            console.log('networkSingleSwitchChange', val);
          }
        "
        @appSingleSwitchChange="
          (val) => {
            console.log('appSingleSwitchChange', val);
          }
        "
        @appStartNodeSwitchChange="
          (val) => {
            console.log('appStartNodeSwitchChange', val);
          }
        "
        @appNodeClick="handleAppNodeClick"
        @networkNodeClick="handleNetworkNodeClick"
        @networkEdgeClick="handleNetworkEdgeClick"
        @appContextClick="handleAppContextClick"
        ref="topoRef"
      ></LinkOverview>
  • ts script
// 由于拖拉拽生成的网络拓扑,所以数据中包含位置信息节点图标等信息较复杂,不用太关注具体的数据内容,拖拉拽保存的拓扑数据,从接口中取出直接再赋给组件即可渲染出对应拓扑;
const testData = ref(
  [{"position":{"x":207,"y":120},"size":{"width":60,"height":80},"view":"html-view","shape":"customNode","id":"0744cc09-efd2-4347-bf0a-381e37c68f1e","data":{"label":"交换机","img":"data:image/svg+xml,%3csvg%20width='34'%20height='34'%20viewBox='0%200%2034%2034'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20id='&%23230;&%23177;&%23135;&%23232;&%23129;&%23154;&%23228;&%23186;&%23164;&%23230;&%23141;&%23162;&%23230;&%23156;&%23186;'%3e%3cpath%20id='&%23230;&%23177;&%23135;&%23232;&%23129;&%23154;&%23228;&%23186;&%23164;&%23230;&%23141;&%23162;&%23230;&%23156;&%23186;_2'%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M17%2031.875C25.2152%2031.875%2031.875%2025.2152%2031.875%2017C31.875%208.78477%2025.2152%202.125%2017%202.125C8.78476%202.125%202.125%208.78477%202.125%2017C2.125%2025.2152%208.78476%2031.875%2017%2031.875ZM17%2034C26.3888%2034%2034%2026.3888%2034%2017C34%207.61116%2026.3888%200%2017%200C7.61117%200%200%207.61116%200%2017C0%2026.3888%207.61117%2034%2017%2034ZM9.91667%2014.875H15.9375C16.1331%2014.875%2016.2917%2015.0336%2016.2917%2015.2292V17.3542C16.2917%2017.5498%2016.1331%2017.7083%2015.9375%2017.7083H9.91667V18.867C9.91667%2019.0792%209.6559%2019.2004%209.47318%2019.073L5.77754%2016.4977C5.6297%2016.3947%205.6297%2016.1887%205.77754%2016.0856L9.47318%2013.5103C9.6559%2013.383%209.91667%2013.5041%209.91667%2013.7163V14.875ZM15.9375%2021.25H9.91667V20.0913C9.91667%2019.8791%209.6559%2019.758%209.47318%2019.8853L5.77754%2022.4606C5.6297%2022.5637%205.6297%2022.7697%205.77754%2022.8727L9.47318%2025.448C9.6559%2025.5754%209.91667%2025.4542%209.91667%2025.242V24.0833H15.9375C16.1331%2024.0833%2016.2917%2023.9248%2016.2917%2023.7292V21.6042C16.2917%2021.4086%2016.1331%2021.25%2015.9375%2021.25ZM24.0833%209.91667H18.0625C17.8669%209.91667%2017.7083%2010.0752%2017.7083%2010.2708V12.3958C17.7083%2012.5914%2017.8669%2012.75%2018.0625%2012.75H24.0833V13.9087C24.0833%2014.1209%2024.3441%2014.242%2024.5268%2014.1147L28.2225%2011.5394C28.3703%2011.4363%2028.3703%2011.2303%2028.2225%2011.1273L24.5268%208.55198C24.3441%208.42464%2024.0833%208.54578%2024.0833%208.75801V9.91667ZM18.0625%2016.2917H24.0833V15.133C24.0833%2014.9208%2024.3441%2014.7996%2024.5268%2014.927L28.2225%2017.5023C28.3703%2017.6053%2028.3703%2017.8113%2028.2225%2017.9144L24.5268%2020.4897C24.3441%2020.617%2024.0833%2020.4959%2024.0833%2020.2837V19.125H18.0625C17.8669%2019.125%2017.7083%2018.9664%2017.7083%2018.7708V16.6458C17.7083%2016.4502%2017.8669%2016.2917%2018.0625%2016.2917Z'%20fill='%230099FF'/%3e%3c/g%3e%3c/svg%3e","type":"exchanger"},"ports":{"groups":{"top":{"position":[30,2],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"right":{"position":[60,40],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"bottom":{"position":[30,80],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"left":{"position":[0,40],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}}},"items":[{"group":"top","id":"6109329e-414d-44c6-98fd-4f90f47024e6","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"right","id":"a8dea5bd-fb83-43d6-bd93-4e3cec26d5a4","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"bottom","id":"1665bbcf-ea4a-40e1-93ad-0d0145866931","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"left","id":"ca13963e-faf2-4de8-b19b-56d2e02c1f04","attrs":{"circle":{"style":{"visibility":"hidden"}}}}]},"zIndex":1},{"position":{"x":539,"y":271},"size":{"width":60,"height":80},"view":"html-view","shape":"customNode","id":"3fcaa3b0-4a4b-4372-a3eb-aceef4964c0f","data":{"label":"路由器","img":"data:image/svg+xml,%3csvg%20width='34'%20height='34'%20viewBox='0%200%2034%2034'%20fill='none'%20xmlns='http://www.w3.org/2000/svg'%3e%3cg%20id='&%23232;&%23183;&%23175;&%23231;&%23148;&%23177;&%23229;&%23153;&%23168;'%3e%3cpath%20id='&%23232;&%23183;&%23175;&%23231;&%23148;&%23177;&%23229;&%23153;&%23168;_2'%20fill-rule='evenodd'%20clip-rule='evenodd'%20d='M17%2031.875C25.2152%2031.875%2031.875%2025.2152%2031.875%2017C31.875%208.78477%2025.2152%202.125%2017%202.125C8.78478%202.125%202.125%208.78477%202.125%2017C2.125%2025.2152%208.78478%2031.875%2017%2031.875ZM17%2034C26.3888%2034%2034%2026.3888%2034%2017C34%207.61116%2026.3888%200%2017%200C7.61117%200%200%207.61116%200%2017C0%2026.3888%207.61117%2034%2017%2034ZM11.0909%2020.9043L13.8457%2018.1495C13.984%2018.0112%2014.2083%2018.0112%2014.3466%2018.1495L15.8492%2019.6521C15.9875%2019.7904%2015.9875%2020.0147%2015.8492%2020.153L13.0944%2022.9078L13.9137%2023.7271C14.0637%2023.8772%2013.965%2024.1472%2013.7458%2024.1864L9.31153%2024.9786C9.13414%2025.0103%208.98849%2024.8646%209.02014%2024.6872L9.81234%2020.253C9.85151%2020.0337%2010.1215%2019.935%2010.2716%2020.085L11.0909%2020.9043ZM22.9104%2013.0938L20.1556%2015.8486C20.0173%2015.9869%2019.793%2015.9869%2019.6547%2015.8486L18.1521%2014.346C18.0138%2014.2077%2018.0138%2013.9834%2018.1521%2013.8451L20.9069%2011.0903L20.0876%2010.271C19.9375%2010.1209%2020.0363%209.85087%2020.2555%209.81171L24.6898%209.01951C24.8671%208.98783%2025.0128%209.13351%2024.9811%209.31088L24.189%2013.7451C24.1498%2013.9644%2023.8797%2014.0631%2023.7297%2013.913L22.9104%2013.0938ZM22.9076%2020.9078L25.6624%2023.6625C25.8007%2023.8008%2025.8007%2024.0251%2025.6624%2024.1634L24.1598%2025.666C24.0215%2025.8043%2023.7972%2025.8043%2023.6589%2025.666L20.9041%2022.9112L20.0855%2023.7305C19.9354%2023.8806%2019.6654%2023.7819%2019.6262%2023.5626L18.834%2019.1284C18.8023%2018.951%2018.948%2018.8053%2019.1254%2018.837L23.5596%2019.6292C23.7789%2019.6684%2023.8776%2019.9384%2023.7276%2020.0885L22.9076%2020.9078ZM11.0903%2013.0938L8.3355%2010.339C8.19719%2010.2007%208.19719%209.97647%208.3355%209.83815L9.83811%208.33555C9.97641%208.19724%2010.2007%208.19724%2010.339%208.33555L13.0937%2011.0903L13.9131%2010.271C14.0631%2010.121%2014.3332%2010.2197%2014.3723%2010.4389L15.1645%2014.8732C15.1962%2015.0505%2015.0505%2015.1962%2014.8731%2015.1645L10.4389%2014.3724C10.2196%2014.3332%2010.1209%2014.0632%2010.271%2013.9131L11.0903%2013.0938Z'%20fill='%230099FF'/%3e%3c/g%3e%3c/svg%3e","type":"router"},"ports":{"groups":{"top":{"position":[30,2],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"right":{"position":[60,40],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"bottom":{"position":[30,80],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}},"left":{"position":[0,40],"attrs":{"circle":{"r":4,"magnet":true,"stroke":"#5F95FF","strokeWidth":1,"fill":"#fff","style":{"visibility":"hidden"}}}}},"items":[{"group":"top","id":"f3ead02f-8e1d-4b30-845d-1868f849a700","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"right","id":"c7affd20-5d4c-45cd-8b2f-2c530ccbf97a","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"bottom","id":"95f28829-f6b4-49e3-9524-fc473645409b","attrs":{"circle":{"style":{"visibility":"hidden"}}}},{"group":"left","id":"fd23e228-7bc8-4f7d-a26a-a3b05bac1e23","attrs":{"circle":{"style":{"visibility":"hidden"}}}}]},"zIndex":2},{"shape":"edge","connector":{"name":"jumpover","args":{"type":"gap"}},"router":{"name":"manhattan","args":{"padding":50}},"id":"bcda4b5d-6603-45ee-9568-5e881869a132","source":{"cell":"0744cc09-efd2-4347-bf0a-381e37c68f1e","port":"1665bbcf-ea4a-40e1-93ad-0d0145866931"},"target":{"cell":"3fcaa3b0-4a4b-4372-a3eb-aceef4964c0f","port":"95f28829-f6b4-49e3-9524-fc473645409b"},"zIndex":3}]
)
const testData2 = ref({
  nodes: [
    { id: "0", label: "开始", status: "normal", tooltip: [] },
    {
      nodeCode: "app-3",
      nodeName: "用户认证应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-3",
      label: "用户认证应用",
      status: "emergency",
      tooltip: [
        { label: "平均时延(ms)", value: 259 },
        { label: "错误数", value: 3 },
        { label: "请求数", value: 93 },
      ],
    },
    {
      nodeCode: "app-2",
      nodeName: "支付网关应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-2",
      label: "支付网关应用",
      status: "emergency",
      //新增了一个告警图标,在节点的右下侧一个三角形的warning,使用方法同status,展现形式见下图
      warningStatus:'important',
      tooltip: [
        { label: "平均时延(ms)", value: 502 },
        { label: "错误数", value: 6 },
        { label: "请求数", value: 148 },
      ],
    },
    {
      nodeCode: "app-4",
      nodeName: "订单处理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-4",
      label: "订单处理应用",
      status: "emergency",
      tooltip: [
        { label: "平均时延(ms)", value: 280 },
        { label: "错误数", value: 3 },
        { label: "请求数", value: 104 },
      ],
    },
    {
      nodeCode: "app-5",
      nodeName: "内容管理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-5",
      label: "内容管理应用",
      status: "emergency",
      tooltip: [
        { label: "平均时延(ms)", value: 282 },
        { label: "错误数", value: 5 },
        { label: "请求数", value: 83 },
      ],
    },
  ],
  edges: [
    {
      sourceCode: "app-4",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-3",
      source: "app-4",
      target: "app-3",
      desc: "请求数:31/平均响应时间:244",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-3",
      source: "app-2",
      target: "app-3",
      desc: "请求数:43/平均响应时间:278",
    },
    {
      sourceCode: "0",
      targetCode: "app-2",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-2",
      source: "0",
      target: "app-2",
      desc: "请求数:148/平均响应时间:502",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-4",
      source: "app-5",
      target: "app-4",
      desc: "请求数:30/平均响应时间:254",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-3",
      source: "app-5",
      target: "app-3",
      desc: "请求数:19/平均响应时间:239",
    },
    {
      sourceCode: "app-3",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-4",
      source: "app-3",
      target: "app-4",
      desc: "请求数:36/平均响应时间:310",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-5",
      source: "app-2",
      target: "app-5",
      desc: "请求数:30/平均响应时间:274",
    },
    {
      sourceCode: "app-4",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-5",
      source: "app-4",
      target: "app-5",
      desc: "请求数:27/平均响应时间:299",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-4",
      source: "app-2",
      target: "app-4",
      desc: "请求数:38/平均响应时间:273",
    },
    {
      sourceCode: "app-3",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-5",
      source: "app-3",
      target: "app-5",
      desc: "请求数:26/平均响应时间:275",
    },
  ],
})

const statusMap = {
    normal: { label: "正常", color: "#02E53D" },
    important: { label: "重要", color: "#ED3939" },
    emergency: { label: "紧急", color: "#FF9D00" },
    minor: { label: "次要", color: "#FFE100" },
};

const handleNetworkNodeClick = (node:any)=>{
  // 网络拓扑基于antv X6,所以与应用拓扑antv g6的数据格式不同
  // 节点的数据配置参数在node.store.data
  console.log(`output->node`,node)
}

const handleNetworkEdgeClick = (edge:any)=>{
  console.log(`output->edge`,edge)
}

const handleAppContextClick = (value:any)=>{
  console.log(`output->value`, value);
}

const handleAppNodeClick = (node:any)=>{
  console.log(`output->node`,node)
}

右侧应用拓扑新增了节点上的告警图标,在节点的右下侧一个三角形的warning,使用方法同status。展现形式见下图

alt text

  • ts script
  // 对应的节点数据:
  {
      nodeCode: "app-2",
      nodeName: "支付网关应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-2",
      label: "支付网关应用",
      status: "emergency",
      //新增了一个告警图标,在节点的右下侧一个三角形的warning,使用方法同status,展现形式见下图
      warningStatus:'important',
      tooltip: [
        { label: "平均时延(ms)", value: 502 },
        { label: "错误数", value: 6 },
        { label: "请求数", value: 148 },
      ],
    },

网络拓扑的节点鼠标覆盖展示tooltip、异常节点label左侧的红色圆点、线上的描述信息与边的状态展示。展现形式见下图

alt text

  • html
  <LinkOverview
  ...

        :networkProps="{
          graphData: testData,
          statusMap,
          nodeMetrics,
          edgeMetrics,
        }"

  ...  
      ></LinkOverview>
  • ts script
 const statusMap = ref<any>({
  normal: { label: "正常", color: "#02E53D" },
  important: { label: "重要", color: "#ED3939" },
  emergency: { label: "紧急", color: "#FF9D00" },
  minor: { label: "次要", color: "#FFE100" },
});

// 与接口(http://172.17.201.11:18340/doc.html#/link_analysis-1.0.0-HTTP/%E9%93%BE%E8%B7%AF%E6%8B%93%E6%89%91%E5%88%86%E6%9E%90%E6%8E%A5%E5%8F%A3/getNetworkTopologyMetricsUsingGET)中返回的字段相同,只在edgeMetrics中新增了两个自定义字段;
// 需要注意的是,要先获取grahphData之后再获取nodeMetrics和edgeMetrics
const nodeMetrics = ref<any>([
  {
    nodeCode: "5c50b7b5-8e7f-435c-a1d3-406cb357a578",
    avgDelay: "10", //	平均时延(ms)
    avgPacketLossRate: "30", //平均丢包率(%)
    avgResponseTime: "40", //	平均响应时间(ms)
    avgRetransmissionRate: "20", //平均重传率(%)
    hasAlarm: 1,
  },
]);

const edgeMetrics = ref<any>([
  {
    sourceCode: "361f2c00-9c51-42f0-a0cd-c3531a8c3bbe",
    targetCode: "b1263827-88ec-4094-b284-bb5eb17c770f",
    packetCount: "0",
    avgResponseTime: "0",
    alarmStatus: 1,
    // 只在接口返回数据的基础上加了以下两个字段:
    desc: "20ms", //边上的文字描述
    status: "important", //状态,以边上的圆点形式展示,与statusMap,同之前用法
  },
]);

⚠️250515新需求:应用拓扑新增筛选功能

  • 效果 alt text
  • html
  <LinkOverview
  ...

        :appProps="{
          linkOptions,
          warningStatus: 'important',
          warningText: '紧急警告!',
          defaultSelectedLinks:['1'] //下拉默认值
          ...
        }"
        @appLinkSelectChange = 'appLinkSelectChange'

  ...  
      ></LinkOverview>
  • ts script
const linkOptions = ref([
  {
    label: "test1",
    value: "1",
    status: "important",//与statusMap映射,同之前用法
  },
  { label: "test2", value: "2" },
  { label: "test3", value: "3" },
  { label: "test4", value: "4" },
  { label: "test5", value: "5" },
  { label: "test6", value: "6" },
  { label: "test7", value: "7" },
  { label: "test8", value: "8" },
  { label: "test9", value: "9" },
  { label: "test10", value: "10" },
  { label: "test11", value: "11" },
]);

const appLinkSelectChange = (selectIds: string[]) => {
  console.log("selectIds", selectIds);
  // 在此根据筛选结果对数据进行过滤or other operations,然后对拓扑重新赋值即可
};

⚠️250611新需求:

  • 1,网络拓扑-网络节点图标标红功能,线标红,线描述标红

  • 2,网络拓扑-主机告警列表contextMenu

  • 3,应用拓扑-节点标红功能、主机告警、应用告警功能

  • 4,应用拓扑-主机告警列表、应用告警列表contextMenu

  • 效果 alt text

网络拓扑 代码示例

  • html
  <LinkOverview
  ...

        :networkProps="{
          graphData: testData,
          statusMap,
          nodeMetrics,
          edgeMetrics,
        }"
        @netContextClick="handleNetContextClick" //右键点击事件

  ...  
      ></LinkOverview>
  • ts script
 const statusMap = ref<any>({
  normal: { label: "正常", color: "#02E53D" },
  important: { label: "重要", color: "#ED3939" },
  emergency: { label: "紧急", color: "#FF9D00" },
  minor: { label: "次要", color: "#FFE100" },
});

// 与接口(http://172.17.201.11:18340/doc.html#/link_analysis-1.0.0-HTTP/%E9%93%BE%E8%B7%AF%E6%8B%93%E6%89%91%E5%88%86%E6%9E%90%E6%8E%A5%E5%8F%A3/getNetworkTopologyMetricsUsingGET)中返回的字段相同,只在edgeMetrics中新增了两个自定义字段;
// 需要注意的是,要先获取grahphData之后再获取nodeMetrics和edgeMetrics
const nodeMetrics = ref<any>([
  {
    nodeCode: "5c50b7b5-8e7f-435c-a1d3-406cb357a578",
    avgDelay: "10", //	平均时延(ms)
    avgPacketLossRate: "30", //平均丢包率(%)
    avgResponseTime: "40", //	平均响应时间(ms)
    avgRetransmissionRate: "20", //平均重传率(%)
    hasAlarm: 1, //节点标红
    tooltip: [//节点鼠标覆盖展示tooltip
    { label: "主机ip: ", value: "241.00" },
    { label: "内存使用率(%): ", value: 6 },
    { label: "CPU使用率(%): ", value: 332 },
    { label: "磁盘使用率(%): ", value: "1.81" },

  ],
  },
]);

const edgeMetrics = ref<any>([
  {
    sourceCode: "361f2c00-9c51-42f0-a0cd-c3531a8c3bbe",
    targetCode: "b1263827-88ec-4094-b284-bb5eb17c770f",
    packetCount: "0",
    avgResponseTime: "0",
    alarmStatus: 1,
    // 只在接口返回数据的基础上加了以下两个字段:
    desc: "20ms", //边上的文字描述
    warning: 1, //1是0否 1时线、描述标红
  },
]);

应用拓扑 代码示例

  • 右键事件同之前用法

  • ts script


  // 对应的节点数据:
    {
      nodeCode: "app-5",
      nodeName: "内容管理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-5",
      label: "内容管理应用",
      nodeWarning: true, //节点标红 1/true
      hostWarning: true,//主机告警 1/true
      appWarning: true,//应用告警 1/true

      tooltip: [
        { label: "平均响应时间(ms): ", value: "241.00" },
        { label: "请求错误数: ", value: 6 },
        { label: "请求数: ", value: 332 },
        { label: "请求错误率(%): ", value: "1.81" },
        { label: "耗时(ms): ", value: "241.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },

LinkOverview API

Attributes

| 名称 | 说明 | 类型 | 默认值 | 是否必须 | | --------------- | ------------------------------- | --------------- | ----------------------------------------------- | -------- | | graphTitle | 标题 | string | 链路图总览 | 否 | | timeRange | 上方时间文本 | string | | 否 | | `networkProps.graphData` | 网络拓扑图所需数据 | `Array<object>` | `[]` | 是 | | `networkProps.statusMap` | 节点状态、边状态的枚举 | `object` | `{}` | 否 | | `networkProps.nodeMetrics` | 网络拓扑图节点指标 | `Array<object>` | `[]` | 否 | | `networkProps.edgeMetrics` | 网络拓扑图边指标 | `Array<object>` | `[]` | 否 | | `networkProps.hidden` | 是否隐藏网络拓扑图 | `boolean` | `false` | 否 | | `appProps.graphData` | 应用拓扑图所需数据 | `object` | `{}` | 是 | | `appProps.statusMap` | legend枚举,为了和warningStatus字段做映射 | `object` | `{}` | 否 | | `appProps.warningStatus` | 左上方的 warning 图标;与定义的statusMap的key对应才能展示对应颜色 | `string` | | 否 | | appProps.hidden | 是否隐藏应用拓扑图 | boolean | false | 否 | | appProps.linkOptions | 应用拓扑下拉搜索选项 | Array<object> | false | 否 | | appProps.warningText | 左上方的 warning 文本 | string | false | 否 | | appProps.defaultSelectedLinks | 链路筛选默认值 | string[] | false
| appProps.loading | 右侧拓扑loading | false | false | networkProps.loading | 左侧拓扑loading | false | false

Events

| 名称 | 说明 | 类型 | | ----------------------- | ----------------------- | ---------- | | networkSingleSwitchChange、appSingleSwitchChange | 切换孤立点 switch 触发 | function | | appStartNodeSwitchChange | 切换开始节点 switch 触发 | function | | appNodeClick、networkNodeClick | 点击节点触发 | function | | appContextClick | 应用拓扑右键节点触发 | function | | netContextClick | 网络拓扑右键节点触发 | function | | networkEdgeClick | 点击边触发 | function | | appLinkSelectChange | 应用拓扑搜索链路=》切换checkbox触发 | function |


四,GlobalLinkReview 全局链路组件

⚠️250619新需求:

  • 1,修复了网络拓扑线上指标重叠的问题

  • 2,新增组件 GlobalLinkReview

  • 2,新增线与线描述信息颜色控制color属性

  • 效果 alt text

  • 主要属性

    • nodeWarning 设置之后节点是红色
    • subLabel 节点下方的子名称
    • color属性控制线与线描述信息颜色
  • html
      <GlobalLinkOverview
        :loading="appLoading"
        :graphData="testData"
        graphTitle="全局链路图总览"
        @singleSwitchChange='()=>{}'
        @nodeClick='()=>{}'

      />
  • ts script
const testData = {
  nodes: [
    {
      id: "0",
      label: "开始",
      subLabel: "122/1234ms/12%",//子标题
      tooltip: [],
    },
    {
      nodeCode: "app-2",
      nodeName: "支付网关应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-2",
      label: "支付网关应用",
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "507.00" },
        { label: "请求错误数: ", value: 76 },
        { label: "请求数: ", value: 1607 },
        { label: "请求错误率(%): ", value: "4.73" },
        { label: "耗时(ms): ", value: "507.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-5",
      nodeName: "内容管理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-5",
      label: "内容管理应用",
      subLabel: "122/1234ms/12%",
      nodeWarning: true,//红色告警节点
      tooltip: [
        { label: "平均响应时间(ms): ", value: "241.00" },
        { label: "请求错误数: ", value: 6 },
        { label: "请求数: ", value: 332 },
        { label: "请求错误率(%): ", value: "1.81" },
        { label: "耗时(ms): ", value: "241.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-3",
      nodeName: "用户认证应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-3",
      label: "用户认证应用",
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "247.00" },
        { label: "请求错误数: ", value: 20 },
        { label: "请求数: ", value: 341 },
        { label: "请求错误率(%): ", value: "5.87" },
        { label: "耗时(ms): ", value: "247.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-4",
      nodeName: "订单处理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-4",
      label: "订单处理应用",
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "243.00" },
        { label: "请求错误数: ", value: 16 },
        { label: "请求数: ", value: 352 },
        { label: "请求错误率(%): ", value: "4.55" },
        { label: "耗时(ms): ", value: "243.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
  ],
  edges: [
    {
      sourceCode: "0",
      targetCode: "app-2",
      color:"red",//线颜色控制
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-2",
      source: "0",
      target: "app-2",
      desc: "1607/507.00ms",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-5",
      source: "app-2",
      target: "app-5",
      desc: "137/257.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-3",
      source: "0",
      target: "app-3",
      desc: "136/261.00ms",
    },
    {
      sourceCode: "app-3",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-5",
      source: "app-3",
      target: "app-5",
      desc: "27/216.00ms",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-4",
      source: "app-2",
      target: "app-4",
      desc: "148/248.00ms",
    },
    {
      sourceCode: "app-4",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-3",
      source: "app-4",
      target: "app-3",
      desc: "35/231.00ms",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-3",
      source: "app-2",
      target: "app-3",
      desc: "138/236.00ms",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-4",
      source: "app-5",
      target: "app-4",
      desc: "21/294.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-5",
      source: "0",
      target: "app-5",
      desc: "126/230.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-4",
      source: "0",
      target: "app-4",
      desc: "145/247.00ms",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-3",
      source: "app-5",
      target: "app-3",
      desc: "32/250.00ms",
    },
    {
      sourceCode: "app-4",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-5",
      source: "app-4",
      target: "app-5",
      desc: "42/241.00ms",
    },
    {
      sourceCode: "app-3",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-4",
      source: "app-3",
      target: "app-4",
      desc: "38/178.00ms",
    },
  ],
}

⚠️250704新需求:

节点
  1. 新增disabled属性,设置了此属性之后节点会变成浅灰色,并且鼠标覆盖不会有tooltip等交互
线
  1. 新增activated属性,设置了此属性之后线会变成与UI一致的蓝色加粗线条,相当于设置了线条加粗+color蓝色;之前的color属性仍然可用
  2. 新增lineWidth属性,可以设置edge宽度,加上上述的activated属性就已经加粗了,如果效果不满意想继续加粗可以设置lineWidth属性
  • 效果 alt text
  • html
      <GlobalLinkOverview
        :loading="appLoading"
        :graphData="testData"
        graphTitle="全局链路图总览"
        @singleSwitchChange='()=>{}'
        @nodeClick='()=>{}'

      />
  • ts script
const testData = {
  nodes: [
    {
      id: "0",
      label: "开始",
      subLabel: "122/1234ms/12%",
      tooltip: [],
    },
    {
      nodeCode: "app-2",
      nodeName: "支付网关应用",
      chainType: 1,
      nodeWarning: true,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-2",
      label: "支付网关应用",
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "507.00" },
        { label: "请求错误数: ", value: 76 },
        { label: "请求数: ", value: 1607 },
        { label: "请求错误率(%): ", value: "4.73" },
        { label: "耗时(ms): ", value: "507.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-5",
      nodeName: "内容管理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-5",
      label: "内容管理应用",
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "241.00" },
        { label: "请求错误数: ", value: 6 },
        { label: "请求数: ", value: 332 },
        { label: "请求错误率(%): ", value: "1.81" },
        { label: "耗时(ms): ", value: "241.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-3",
      nodeName: "用户认证应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-3",
      label: "用户认证应用",
      subLabel: "122/1234ms/12%",
      status: "emergency",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "247.00" },
        { label: "请求错误数: ", value: 20 },
        { label: "请求数: ", value: 341 },
        { label: "请求错误率(%): ", value: "5.87" },
        { label: "耗时(ms): ", value: "247.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
    {
      nodeCode: "app-4",
      nodeName: "订单处理应用",
      chainType: 1,
      nodeType: null,
      nodeConfig: null,
      nodeStyle: null,
      id: "app-4",
      label: "订单处理应用",
      disabled: true,
      subLabel: "122/1234ms/12%",
      tooltip: [
        { label: "平均响应时间(ms): ", value: "243.00" },
        { label: "请求错误数: ", value: 16 },
        { label: "请求数: ", value: 352 },
        { label: "请求错误率(%): ", value: "4.55" },
        { label: "耗时(ms): ", value: "243.00" },
        { label: "内存使用率(%): ", value: "0.00" },
        { label: "CPU使用率(%): ", value: "0.00" },
        { label: "磁盘使用率(%): ", value: "0.00" },
      ],
    },
  ],
  edges: [
    {
      activated: true,
      sourceCode: "0",
      targetCode: "app-2",
      edgeType: "ONE_WAY",
      color: "red",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-2",
      source: "0",
      target: "app-2",
      desc: "1607/507.00ms",
    },
    {
      activated: true,
      lineWidth: 2,
      sourceCode: "app-2",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-5",
      source: "app-2",
      target: "app-5",
      desc: "137/257.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-3",
      source: "0",
      target: "app-3",
      desc: "136/261.00ms",
    },
    {
      activated: true,
      sourceCode: "app-3",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-5",
      source: "app-3",
      target: "app-5",
      desc: "27/216.00ms",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-4",
      source: "app-2",
      target: "app-4",
      desc: "148/248.00ms",
    },
    {
      sourceCode: "app-4",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-3",
      source: "app-4",
      target: "app-3",
      desc: "35/231.00ms",
    },
    {
      sourceCode: "app-2",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-2-app-3",
      source: "app-2",
      target: "app-3",
      desc: "138/236.00ms",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-4",
      source: "app-5",
      target: "app-4",
      desc: "21/294.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      activated: true,
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-5",
      source: "0",
      target: "app-5",
      desc: "126/230.00ms",
    },
    {
      sourceCode: "0",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "0-app-4",
      source: "0",
      target: "app-4",
      desc: "145/247.00ms",
    },
    {
      sourceCode: "app-5",
      targetCode: "app-3",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-5-app-3",
      source: "app-5",
      target: "app-3",
      desc: "32/250.00ms",
    },
    {
      sourceCode: "app-4",
      targetCode: "app-5",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-4-app-5",
      source: "app-4",
      target: "app-5",
      desc: "42/241.00ms",
    },
    {
      sourceCode: "app-3",
      targetCode: "app-4",
      edgeType: "ONE_WAY",
      chainType: 1,
      edgeConfig: null,
      edgeStyle: null,
      id: "app-3-app-4",
      source: "app-3",
      target: "app-4",
      desc: "38/178.00ms",
    },
  ],
}

五,TopoPreview 组件

⚠️251015新需求:

  • 替换业务监控、业务总体分析模块的拓扑图
  • 效果 alt text
  • html
      <TopoPreview
        graphTitle="拓扑视图"
        :graphData="graphData"
        :nodeMetrics="nodeMetrics"
        :edgeMetrics="edgeMetrics"
        @ContextClick="handleContextClick"
      />  
  • ts script
const nodeMetrics = ref<any>([
  {
    nodeCode: "fc488edc-97d0-4f26-9ee6-695337907d2f",
    avgDelay: "10", //	平均时延(ms)
    avgPacketLossRate: "30", //平均丢包率(%)
    avgResponseTime: "40", //	平均响应时间(ms)
    avgRetransmissionRate: "20", //平均重传率(%)
    connectFailureRate: "50",
    hasAlarm: 1,
    nodeIp: "192.168.1.1",
    tooltip: [
      { label: "平均响应时间(ms): ", value: "247.00" },
      { label: "请求错误数: ", value: 20 },
      { label: "请求数: ", value: 341 },
      { label: "请求错误率(%): ", value: "5.87" },
      { label: "耗时(ms): ", value: "247.00" },
      { label: "内存使用率(%): ", value: "0.00" },
      { label: "CPU使用率(%): ", value: "0.00" },
      { label: "磁盘使用率(%): ", value: "0.00" },
    ],
  },
]);

const edgeMetrics = ref<any>([
  {
    sourceCode: "fc488edc-97d0-4f26-9ee6-695337907d2f",
    targetCode: "0e5d0518-f7bc-43e9-a9ef-0cfc291bedfb",
    packetCount: "0",
    avgResponseTime: "0",
    alarmStatus: 1,
    desc: "59/14.78ms", //边上的文字描述
    warning: 1,
  },
  {
    sourceCode: "app-2",
    targetCode: "app-5",
    packetCount: "0",
    avgResponseTime: "0",
    alarmStatus: 1,
    desc: "59/14.78ms", //边上的文字描述
    warning: 1,
  },
  {
    sourceCode: "19cb25b1-85ec-4fb8-92f1-c4349a6a1edf",
    targetCode: "6ed954a9-d18d-4346-8fcd-4f4835cbaf82",
    packetCount: "0",
    avgResponseTime: "0",
    alarmStatus: 1,
    desc: "66/88.78ms", //边上的文字描述
    warning: 1,
  },
]);

const graphData = {
  client: {
    nodes: [
      {
        nodeCode: "client-0",
        nodeName: "客户端",
        chainType: 1,
        nodeType: null,
        nodeConfig: null,
        nodeStyle: null,
        id: "client-0",
        label: "客户端",
        status: "emergency",
        tooltip: [
          { label: "平均时延(ms)", value: 510 },
          { label: "错误数", value: 10 },
          { label: "请求数", value: 130 },
        ],
      },
    ],
    edges: [
      // {
      //   sourceCode: "client-0",
      //   targetCode: "fc488edc-97d0-4f26-9ee6-695337907d2f",
      //   id: "client-0-fc488edc-97d0-4f26-9ee6-695337907d2f",
      //   source: "client-0",
      //   target: "fc488edc-97d0-4f26-9ee6-695337907d2f",
      // },
    ],
  },
  network: [
    {
      position: { x: 69, y: 77 },
      size: { width: 60, height: 80 },
      view: "html-view",
      shape: "customNode",
      id: "fc488edc-97d0-4f26-9ee6-695337907d2f",
      data: { label: "交换机", type: "exchanger" },
      ports: {
        groups: {
          top: {
            position: [30, 2],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          right: {
            position: [60, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          bottom: {
            position: [30, 80],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          left: {
            position: [0, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
        },
        items: [
          {
            group: "top",
            id: "9bab0b66-9913-4868-883a-3bcd6eeb8f96",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "right",
            id: "dd8cc04a-0471-423f-91d4-a08692246982",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "bottom",
            id: "bc246f9c-53b6-4949-9b2a-5d964a174f77",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "left",
            id: "e46ef986-ffbf-41f8-b434-8745b17e1ede",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
        ],
      },
      zIndex: 1,
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "9110cc0d-1af9-40cb-9a50-6c651c3ae831",
      source: {
        cell: "fc488edc-97d0-4f26-9ee6-695337907d2f",
        port: "dd8cc04a-0471-423f-91d4-a08692246982",
      },
      target: {
        cell: "0e5d0518-f7bc-43e9-a9ef-0cfc291bedfb",
        port: "9da1902e-1b25-4525-a2dd-88da4e211deb",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "b0617dad-7669-4631-8f77-84abbbd4d26b",
      source: {
        cell: "fc488edc-97d0-4f26-9ee6-695337907d2f",
        port: "dd8cc04a-0471-423f-91d4-a08692246982",
      },
      target: {
        cell: "113d9869-04f3-4588-aabb-27320c7a2abf",
        port: "403ad49e-5f1d-438b-a752-ec170febc0f7",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "26f3c496-b990-475f-8cda-bdd3565c07bf",
      source: {
        cell: "113d9869-04f3-4588-aabb-27320c7a2abf",
        port: "7818e36b-98d3-49ea-9a69-965b54847d0d",
      },
      target: {
        cell: "fd801254-5388-4951-a12c-6f9badf30b4a",
        port: "fbfaad3f-0eb1-4f3c-b2d1-4fc0a516705c",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "2b57d6d9-796b-4fc5-8ca9-a1a9fe35c75a",
      source: {
        cell: "0e5d0518-f7bc-43e9-a9ef-0cfc291bedfb",
        port: "fd92228d-ca99-4de6-93d1-32400f14bdf9",
      },
      target: {
        cell: "f5c83e15-0e35-4309-94c4-e5849d31a0f5",
        port: "d120dcc9-329c-44ba-886d-c5d224833561",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "433e97a4-8921-4ff3-b0a8-716d30694d18",
      source: {
        cell: "fd801254-5388-4951-a12c-6f9badf30b4a",
        port: "68931aee-0eb4-43f9-8c35-fbb0910b3efc",
      },
      target: {
        cell: "d7de6a14-064e-4ffb-95b2-5ea31f1d1347",
        port: "06f819f8-a28c-4157-b145-0862db8ddafa",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "7b3bab78-4353-4826-9308-15c1b9ae5149",
      source: {
        cell: "fd801254-5388-4951-a12c-6f9badf30b4a",
        port: "4be336b5-9150-4085-b7b4-15f3ba99dd38",
      },
      target: {
        cell: "f305a38d-7bc8-4c95-bbd8-0d5af8dda517",
        port: "7412021a-54e5-44c0-a16e-3d0a67a8482d",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "a4f89b13-ba4e-4fb5-918a-d62fe1332f4f",
      source: {
        cell: "f305a38d-7bc8-4c95-bbd8-0d5af8dda517",
        port: "3abdad95-dfe6-4a9a-90f8-7d272eebaf9b",
      },
      target: {
        cell: "a1ceada1-c2cc-4420-994e-5f65f669751c",
        port: "f27afc81-0049-407a-bcec-97c785782308",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "eac63ef8-e6d3-49b7-8b3f-22a89462092a",
      source: {
        cell: "d7de6a14-064e-4ffb-95b2-5ea31f1d1347",
        port: "c1c804a1-be8a-4424-bc67-381dcca9abbb",
      },
      target: {
        cell: "a1ceada1-c2cc-4420-994e-5f65f669751c",
        port: "97a7c587-8d38-4514-978f-4ba87ec33999",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "ce1e3741-a659-42c1-909f-b052629ad732",
      source: {
        cell: "f5c83e15-0e35-4309-94c4-e5849d31a0f5",
        port: "56de6d8e-c53c-4504-a7a1-4d8fe0c136a8",
      },
      target: {
        cell: "893f1d6a-090b-49f4-9fbd-41ff26ee2a8d",
        port: "dbef3881-b344-4e84-a425-85e9927f25c1",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "b2ab824c-706d-4619-898f-520479d629cc",
      source: {
        cell: "f5c83e15-0e35-4309-94c4-e5849d31a0f5",
        port: "56de6d8e-c53c-4504-a7a1-4d8fe0c136a8",
      },
      target: {
        cell: "d2fba48f-b4c4-4ede-b223-193145a01eb6",
        port: "886f4074-67e8-49e9-9f6e-9a262b282361",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "24a5b0e3-0f36-49d6-beda-ce2a7a50a2ec",
      source: {
        cell: "a1ceada1-c2cc-4420-994e-5f65f669751c",
        port: "bba7a87b-7693-4711-bae6-1bb28ff08a56",
      },
      target: {
        cell: "1ab0a099-52d1-4f61-83a8-3088acba1910",
        port: "6e405a01-0087-43ef-aae5-5ca6b428beb3",
      },
      vertices: [],
    },
    {
      shape: "edge",
      zIndex: 1,
      connector: { name: "smooth", args: { raw: false } },
      id: "11c144bb-ca88-45b3-a896-d91b1a104dca",
      source: {
        cell: "893f1d6a-090b-49f4-9fbd-41ff26ee2a8d",
        port: "62d1e64f-40d8-41e2-a342-523f07210826",
      },
      target: {
        cell: "1ab0a099-52d1-4f61-83a8-3088acba1910",
        port: "6e405a01-0087-43ef-aae5-5ca6b428beb3",
      },
    },
    {
      position: { x: 212, y: 32 },
      size: { width: 60, height: 80 },
      view: "html-view",
      shape: "customNode",
      id: "113d9869-04f3-4588-aabb-27320c7a2abf",
      data: { label: "路由器", type: "router" },
      ports: {
        groups: {
          top: {
            position: [30, 2],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          right: {
            position: [60, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          bottom: {
            position: [30, 80],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          left: {
            position: [0, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
        },
        items: [
          {
            group: "top",
            id: "7993fd26-855e-4827-bf43-db082ba305e1",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "right",
            id: "7818e36b-98d3-49ea-9a69-965b54847d0d",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "bottom",
            id: "0620321f-19e3-46de-8aff-4ac1d7a0f4d0",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "left",
            id: "403ad49e-5f1d-438b-a752-ec170febc0f7",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
        ],
      },
      zIndex: 2,
    },
    {
      position: { x: 212, y: 139 },
      size: { width: 60, height: 80 },
      view: "html-view",
      shape: "customNode",
      id: "0e5d0518-f7bc-43e9-a9ef-0cfc291bedfb",
      data: { label: "路由器", type: "router" },
      ports: {
        groups: {
          top: {
            position: [30, 2],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          right: {
            position: [60, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          bottom: {
            position: [30, 80],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          left: {
            position: [0, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
        },
        items: [
          {
            group: "top",
            id: "907c6461-2503-4bb9-83a5-151253585c63",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "right",
            id: "c65c3e2f-8a3e-4449-ab51-4e10ee134880",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "bottom",
            id: "fd92228d-ca99-4de6-93d1-32400f14bdf9",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "left",
            id: "9da1902e-1b25-4525-a2dd-88da4e211deb",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
        ],
      },
      zIndex: 3,
    },
    {
      position: { x: 449, y: 32 },
      size: { width: 60, height: 80 },
      view: "html-view",
      shape: "customNode",
      id: "fd801254-5388-4951-a12c-6f9badf30b4a",
      data: { label: "路由器", type: "router" },
      ports: {
        groups: {
          top: {
            position: [30, 2],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          right: {
            position: [60, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          bottom: {
            position: [30, 80],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
          left: {
            position: [0, 40],
            attrs: {
              circle: {
                r: 4,
                magnet: true,
                stroke: "#5F95FF",
                strokeWidth: 1,
                fill: "#fff",
                style: { visibility: "hidden" },
              },
            },
          },
        },
        items: [
          {
            group: "top",
            id: "8bee0659-d0cd-45bd-9fc6-9064a586e665",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "right",
            id: "68931aee-0eb4-43f9-8c35-fbb0910b3efc",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "bottom",
            id: "4be336b5-9150-4085-b7b4-15f3ba99dd38",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
          {
            group: "left",
            id: "fbfaad3f-0eb1-4f3c-b2d1-4fc0a516705c",
            attrs: { circle: { style: { visibility: "hidden" } } },
          },
        ],
      },
      zIndex: 4,
    },
    {
      position: { x: 225, y: 423 },
      size: { width: 60, height: 80 },
      view: "html-view",
      shape: "customNode",
      id: "f5c83e15-0e35-4309-94c4-e5849d31a0f5",
      data: { label: "负载均衡", type: "load_balancer" },
      ports: {
        groups: {
          top: {
            position: [30, 2],
            attrs: {
              circle: {
                r: 4,