前言
该组件基于 Vue.js 和 AntV G6 构建
项目特色功能
1. 丰富的节点图标支持
本拓扑图系统的最大特色是支持使用自定义图片作为节点图标
2. 智能的力导向布局
系统采用力导向布局算法,能够自动优化节点位置,避免重叠,形成美观的网络拓扑结构。用户无需手动调整节点位置,系统会自动计算出最佳的显示效果。
3. 丰富的交互功能
- 拖拽操作:支持节点拖拽,用户可以手动调整布局
- 缩放平移:支持画布缩放和平移,方便查看大型网络
- 悬停效果:鼠标悬停显示详细信息
- 点击复制:点击节点可将信息复制到剪贴板
4. 漏洞信息展示
边缘连接不仅表示网络连接关系,还能显示具体的漏洞信息,如:
- SQL注入漏洞
- XSS跨站脚本攻击
- 网络协议漏洞
- 配置错误等
第一步:安装依赖
首先确保项目中已安装必要的依赖包:
npm install @antv/g6 vue axios
第二步:准备图标资源
在项目的 `public/目录下放置设备图标文件:
public/defalut.png # 默认设备图标kylin_high.png # 麒麟系统高危linux_mid.png # Linux中危win_high.png # Windows高危win_low.png # Windows低危win_safety.png # Windows安全linux_high.png # Linux高危linux_low.png # Linux低危
第三步:创建拓扑图组件
创建主要的拓扑图组件文件:
<template><div class="topology-container"><div id="container" class="topology-canvas"></div><screen-component :objF="objF":currentEve="currentEve":questionList="questionList":list="list"@realType="handleRealType"/></div>
</template><script>
import { Graph, NodeEvent } from '@antv/g6'
import axios from 'axios'
import ScreenComponent from './screen.vue'export default {name: 'TopologyViewer',components: {ScreenComponent},data() {return {graphHH: null,objF: {},currentEve: [],questionList: [],list: []}}
}
</script>
第四步:实现数据获取逻辑
methods: {async fetchTopologyData(type) {try {const urlParams = new URLSearchParams(window.location.search);const taskId = urlParams.get('taskId');const response = await axios.get(`/api/topology?taskId=${taskId}&type=${type}`,{headers: {'platform-token': 'your-token-here'}});if (response.data.code === 200) {const topologyData = response.data.data;this.processTopologyData(topologyData);}} catch (error) {console.error('获取拓扑数据失败:', error);this.useDefaultData();}}
}
第五步:初始化拓扑图
initTopology(allData) {// 销毁现有实例if (this.graphHH) {this.graphHH.destroy();this.graphHH = null;}const graph = new Graph({container: document.getElementById("container"),width: 1520,height: 900,data: {nodes: allData.nodes.map((node) => ({id: node.id,type: node.type || "circle",style: {size: node.size || 60,labelText: `${node.name}\n${node.title}`,labelFill: '#fff',src: node.style?.src,fill: "rgba(255,255,255,.9)"}})),edges: allData.edges.map((edge) => ({id: edge.id,source: edge.source,target: edge.target,style: {labelText: edge.vulName,stroke: "#aaa",lineWidth: 1,labelFill: "rgba(255,255,255,.8)"}}))},layout: {type: "force"},behaviors: ['hover-activate','drag-canvas','zoom-canvas', 'drag-node','drag-element']});// 绑定事件this.bindEvents(graph);this.graphHH = graph;graph.render();
}
数据结构说明
节点数据结构
{id: 'firewall-001', // 唯一标识name: '外网防火墙', // 显示名称type: 'image', // 节点类型size: 80, // 节点大小title: '192.168.1.1', // 副标题(如IP地址)style: {src: '/img2/firewall.png' // 图标路径}
}
边缘数据结构
{id: 'edge-001', // 唯一标识source: 'firewall-001', // 源节点IDtarget: 'router-001', // 目标节点IDvulName: '防火墙策略配置漏洞' // 漏洞描述
}
高级功能实现
1. 节点状态管理
实现不同状态下节点的视觉效果:
// 设置节点状态
setNodeState(nodeId, state) {const graph = this.graphHH;switch(state) {case 'active':graph.updateNodeData([{id: nodeId,style: {stroke: '#ff4d4f',shadowBlur: 10,shadowColor: 'rgba(255, 77, 79, 0.5)'}}]);break;case 'normal':graph.updateNodeData([{id: nodeId,style: {stroke: '#d9d9d9',shadowBlur: 0}}]);break;}graph.draw();
}
2. 动态数据更新
支持实时更新拓扑数据:
updateTopologyData(newData) {const graph = this.graphHH;// 更新节点if (newData.nodes) {graph.updateData({nodes: newData.nodes.map(node => ({id: node.id,style: node.style}))});}// 更新边缘if (newData.edges) {graph.updateData({edges: newData.edges.map(edge => ({id: edge.id,style: edge.style}))});}
}
3. 搜索和筛选功能
实现节点搜索和类型筛选:
searchNodes(keyword) {const graph = this.graphHH;const allNodes = graph.getNodes();allNodes.forEach(node => {const nodeData = graph.getNodeData(node.id);const isMatch = nodeData.name.includes(keyword) || nodeData.title.includes(keyword);graph.updateNodeData([{id: node.id,style: {opacity: isMatch ? 1 : 0.3}}]);});graph.draw();
}filterByType(deviceType) {const graph = this.graphHH;const allNodes = graph.getNodes();allNodes.forEach(node => {const nodeData = graph.getNodeData(node.id);const isVisible = deviceType === 'all' || nodeData.deviceType === deviceType;graph.updateNodeData([{id: node.id,style: {display: isVisible ? 'block' : 'none'}}]);});graph.draw();
}
性能优化建议
1. 大数据量处理
当节点数量超过1000个时,建议采用以下优化策略:
// 启用性能模式
const graph = new Graph({// ... 其他配置modes: {default: ['drag-canvas', 'zoom-canvas']},// 禁用一些耗性能的功能animate: false,groupByTypes: false
});
2. 内存管理
正确的实例销毁:
beforeDestroy() {if (this.graphHH) {this.graphHH.destroy();this.graphHH = null;}// 清理定时器if (this.intervalId) {clearInterval(this.intervalId);}
}
3. 事件优化
避免频繁的事件触发:
// 使用防抖处理鼠标事件
const debouncedHover = debounce((e) => {// 悬停处理逻辑
}, 100);graph.on(NodeEvent.POINTER_ENTER, debouncedHover);
样式定制
CSS样式配置
.topology-container {width: 100%;height: 100vh;background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);position: relative;
}.topology-canvas {width: 100%;height: 100%;border-radius: 10px;box-shadow: 0 10px 30px rgba(0, 0, 0, 0.2);
}/* 节点标签样式 */
.g6-tooltip {background: rgba(0, 0, 0, 0.8);color: white;border-radius: 4px;padding: 8px 12px;font-size: 12px;
}
常见问题及解决方案
- 图标不显示:检查图片路径是否正确,确保图片文件存在
- 节点重叠:调整力导向布局参数或增加画布大小
- 性能问题:减少节点数量或禁用动画效果
- 事件不响应:检查事件绑定是否正确,确保DOM元素已渲染