vue-safe-force-graph
v2.0.85
Published
force_graph in security area
Downloads
707
Keywords
Readme
vue-safe-force-graph
vue-safe-force-graph 是一个使用 Vue3、d3.js 、 canvas 开发的可视化溯源关系图。
安装
npm install vue-safe-force-graph
使用方式
可以在组件中引入 或者可以在全局引入注册组件。
方式一:组件中引入
在vue组件中引入Graph组件和样式:
import { Graph } from 'vue-safe-force-graph'
import 'vue-safe-force-graph/lib/style.css'
完整index.vue示例如下:
<template>
<div class="graph-container">
<Graph
:graph-api="graphApi"
:module="module"
:start-node="startNode"
:enter-start-node="true"
:has-level="true"
:snapshot_id="snapshotId"
:vcode="vcode"
:handle-select-node-event="handleSelectNode"
:custom-context-menu-event="handleEvent"
:singles-node-max-num="500"
@handle-data-loaded="handleDataLoaded"
/>
</div>
</template>
<script setup>
import {
getGraphConfig, getGraphRequest, getNodesDetail, getSnapshotDetail,
} from 'src/api/graph'
import { ref, watch } from 'vue'
import { useRoute } from 'vue-router'
import request from '@/utils/request'
import { Graph } from 'vue-safe-force-graph'
import 'vue-safe-force-graph/lib/style.css'
const module = ref('graph')
const startNode = ref([])
const vcode = ref(null)
const snapshotId = ref(null)
const forceGraph = ref(null)
function addSnapshot(params) {
return request({
url: `/graph/v1/snapshot/add?module=${module.value}`,
method: 'post',
data: params
})
}
const graphApi = {
getGraphConfig: getGraphConfig,
getGraphRequest: getGraphRequest,
getNodesDetail: getNodesDetail,
addSnapshot1: addSnapshot,
getSnapshotDetail: getSnapshotDetail,
}
const route = useRoute()
snapshotId.value = route.query.snapshot_id
vcode.value = route.query.vcode
if (route.query.type && route.query.id) {
startNode.value = [
{
type: route.query.type,
id: route.query.id
}
]
}
const handleHighLight = (type, prop, value) => {
console.log('forceGraph', forceGraph.value)
forceGraph.value.handleCustomSelect(type, prop, value)
}
const handleEvent = (data) => {
console.log('监听菜单事件', data)
}
const handleSelectNode = (data) => {
console.log('handleSelectNode', data)
}
function handleDataLoaded(data) {
console.log('handleDataLoaded', data)
}
</script>
<style lang="scss">
.graph-container {
height: calc(100vh - 66px);
}
</style>
方式二:全局引入
在main.js中引入并注册。
// main.js
import { createApp } from 'vue'
import Graph from 'vue-safe-force-graph'
import 'vue-safe-force-graph/lib/style.css'
const app = createApp(App)
app.use(Graph)
在自己的业务组件中使用,全局注册的组件名为ForceGraphByCanvas
,示例如下 :
<template>
<ForceGraphByCanvas
:graph-api="graphApi"
module="md5graph"
:start-node="startNode"
:enter-start-node="true"
:has-level="true"
:snapshot_id="snapshotId"
:vcode="vcode"
:handle-select-node-event="handleSelectNode"
:custom-context-menu-event="handleEvent"
@handle-data-loaded="handleDataLoaded"
/>
</template>
<script setup>
// 此处js代码参考上面组件引入的实例
</script>
组件属性
| 属性名 | 说明 | 类型 | 默认值 | 是否必填 |
| ------------------------ | ------------------------------------------------------------ | -------------- | ------------------------------------------------------------ | -------- |
| graph-api | 图数据相关接口,包含config、节点数据、节点详情接口 | Object | 无 | 是 |
| module | 当前图模块 用于 获取config接口时的传参。 this.graphApi?.getGraphConfig({name: this.module}).then(() => {}) | String | 无 | 是 |
| start-node | 开始节点,如 startNode = [{type: "ip",id: "193.36.119.50"}] | Array | 无 | 是 |
| enter-start-node | 起始节点时是否出现查询添加接口 | Boolean | false | 否 |
| has-level | 是否有level等级概念 | Boolean | true | 否 |
| snapshot_id | 快照id | String | 无 | 否 |
| vcode | 快照密码 | String | 无 | 否 |
| dark-mode | 是否为深色模式 | Boolean | false | 否 |
| showPoint | 图左侧的legend图例部分,是否需要收藏 备注 标签
| Boolean | true | 否 |
| isShowRightMenu | 是否展示右侧详情 部分 | Boolean | true | 否 |
| hideButtonList | 需要隐藏的顶部按钮, 如 hideButtonList = ["新增节点"]。全部可选项为[ "新增节点", "删除", "保存快照", "保存图片", "数据导出", "数据导入", "撤销", "恢复", "自动布局", "全局固定", "全局解除固定", "树型布局", "斥力布局","展开折叠", "功能介绍", ]
| Array | 无 | 否 |
| isRenderStartNode | 是否渲染startNode。 | Boolean | true | 否 |
| isDefaultSelectStartNode | 是否默认选中开始节点startNode | Boolean | true | 否 |
| graphUrlPath | 用于生成快照后的图页面的地址路径。 例如当生成快照成功后,会生成一个链接,https://xxx.b.net/${graphUrlPath}?snapshot_id=xxx
| String | '/graph' | 否 |
| levelList | level危险级别 | Array | [ { level: '未知', // 级别。必传 levelName: '未知', // 必传。级别的名称 用于展示文案 className: 'unknown', // class样式名。必传 iconType: '', // 默认使用图标,传dot使用圆点样式 normalColor: '#666', // 颜色色值。必传 darkColor: '#c6cdd5', // 暗黑模式颜色色值,非必传。不传使用normalColor dangerNumber: 0, // 是否是 危险的局别。 用于统计危险数,对危险的节点增加样式等。和危险数的排序 }, { level: '危险', levelName: '危险', className: 'warn', iconType: '', // 默认使用图标,传dot使用圆点样式 normalColor: '#CF1322', darkColor: '#fb2400', dangerNumber: 1, }, { level: '普通', levelName: '普通', className: 'normal', iconType: '', // 默认使用图标,传dot使用圆点样式 normalColor: '#007EE2', darkColor: '#0094ff', dangerNumber: -1, }, { level: '安全', levelName: '安全', className: 'safe', iconType: '', // 默认使用图标,传dot使用圆点样式 normalColor: '#009A75', darkColor: '#00da90', dangerNumber: -2, }, ] | 否 |
| showLevelCount | 是否在左侧图例legend的leve图标l旁边展示相关节点的数量。 | Boolean | false | 否 |
| title | 在图的左上角设置标题,默认无 | String | Html | 无 | 否 |
| isShowNodeMessage | 是否展示 渲染多少个节点的 message提示 | Boolean | true | 否 |
| nodeTypeScale | 图中关系节点图标大小的缩放比例。如缩小0.5倍则传数字0.5 | Number | 1 | 否 |
| singlesNodeMaxNum | 单个关系类型下的最大节点数量。如果节点数量超过此值,默认聚合隐藏起来 | Number | 100 | 否 |
| handleSelectNodeEvent | 选择节点事件的props(兼容angular调用,vue可以使用事件方式) | Function | 无 | 否 |
| customContextMenuEvent | 自定义右键菜单的点击事件,相关配置参考下面的自定义右键菜单。会返回数据 { eventName: 'api.name', customConfig: 'api.customConfig', nodes: 'nodes', allNodes: 'this.history.dataNow.nodes', }
(兼容angular调用,vue可以使用事件方式) | Function | 无 | 否 |
| handleDataLoaded | 图加载数据完成后 的事件通知。会返回图中所有的节点数据。(兼容angular调用,vue可以使用事件方式) | Function | 无 | 否 |
| nodeWidth | 节点的宽度 | Number | 24 | 否 |
| startNodeWidth | 起始节点的宽度 | Number | 24 | 否 |
| linkDistance | 用于调整**d3.forceLink
的距离**:以确保link长度,值越大距离越长。d3文档 (当配置nodeWidth后可能会用到,比如nodewidth太大时,需要增加link距离) | Number | 120 | 否 |
| strength | d3js的manyBody.strength属性。调整 d3.forceManyBody
的强度:增加或减少节点之间的排斥力,值为负值,负数越大斥力越大,如0表示无斥力,-600中等斥力。d3文档(当配置nodeWidth后可能会用到,比如nodewidth太大时,需要增加节点之间的斥力) | Number | -600 | 否 |
| customTooltip | 自定义tooltip内容,传入一个函数,函数中能拿到节点数据,函数需返回html模板 | Function | | 否 |
| edgeLabelMaxLength | 边上文字的最大长度,超过则省略展示,鼠标悬浮展示全部 | Number | 10 | 否 |
自定义右键菜单
在config接口中配置节点的右键菜单项,图组件拿到数据后渲染到页面上, 并绑定点击事件。点击后emit出去相关的数据。使用者监听该事件,然后自行处理后续流程。
菜单项配置在下面详情接口中,data => records => info => extraNodeContextMenus字段,如
{
'code': '0',
'msg': 'ok',
'data': {
'records': [
{
'summary': '',
'tags': [],
'info': {
// 额外右键菜单项
'extraNodeContextMenus': [
{
name: 'dealwith1', // 菜单唯一标识,用于点击事件传出去
namec: '菜单1 无children', // 菜单展示的文案
icon: 'button_edit_label', // 右键菜单的图标,不传的话默认一个图标
customConfig: { // 透传自定义配置
input: 'xxxxx',
a: 'ceshi'
}
},
{
name: 'dealwith2',
namec: '菜单2 无children',
customConfig: {
input: 'xxxxx',
a: 'ceshi'
},
// children 二级菜单
children: [
{
name: 'xxx',
namec: 'xxx',
customConfig: {
input: '333',
a: 'ces3333hi'
}
}
]
},
{
name: 'dealwxxith3',
namec: 'xxx',
children: [
{
name: 'xxx',
namec: 'xxx',
children: [
{
name: 'threelevel',
namec: '三级菜单'
}
]
}
]
}
],
'id': '1234',
'name': '123',
'type': 'url',
'basic': {
'level': '未知',
'check_time': '',
'desc': ''
},
'extends': null
},
'brief': []
},
{
'summary': '',
'tags': [],
'info': {
'id': '234234',
'name': '234234',
'type': 'url',
'basic': {
'level': '未知',
'check_time': '',
'desc': ''
},
'extends': null
},
'brief': []
}
]
}
}
事件
| 事件名 | 说明 | 示例 |
| ------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ |
| handle-data-loaded | 图加载数据完成后 的事件通知。会返回图中所有的节点数据 | <ForceGraphByCanvas :graph-api="graphApi" :module="module" :start-node="startNode" @handle-data-loaded="handleDataLoaded" @custom-contextmenu-click="handleContextmenu" @handle-select-node="handleSelectNode" />
|
| custom-contextmenu-click | 自定义右键菜单的点击事件。返回 eventName 事件名 、customConfig、 当前点击的nodes 节点的整个数据, 所有节点allNodes | 如上 |
| handle-select-node | 选择节点事件 | 如上 |
| | | |
方法
| 方法名 | 说明 | 参数 | | ------------------ | ------------------------------------------------------------ | ---- | | controlOperation | 操作控制,传入node数据和对应api操作。如显示隐藏按钮,示例如下 | | | handleCustomSelect | 选择节点 | | | | | |
controlOperation示例
<ForceGraphByCanvas
ref="forceGraph"
graph-url-path="/hmGraphByCanvas"
:graph-api="graphApi"
:module="module"
:start-node="startNode"
@handle-data-loaded="handleDataLoaded"
/>
/*
* 参数格式 { nodes: [{ id: '8c5c0cda7d0f3ec28e818b441037cf2d' }], api: { name: 'show_node' }}
* */
function showNode() {
forceGraph.value.controlOperation({ nodes: [{ id: '8c5c0cda7d0f3ec28e818b441037cf2d' }], api: { name: 'show_node' }})
}
function hideNode() {
forceGraph.value.controlOperation({ nodes: [{ id: '8c5c0cda7d0f3ec28e818b441037cf2d' }], api: { name: 'hide_node' }})
}
// 全部展示数据节点边的label
function allShowEdgeLabel() {
forceGraph.value.controlOperation({ api: { name: 'all_show_edges_label' }})
}
// 全部隐藏数据节点边的label
function allHideEdgeLabel() {
forceGraph.value.controlOperation({ api: { name: 'all_hide_edges_label' }})
}
controlOperation其他api name
edit_label
修改labelsingle_edge_select
单边顶点选择hold_aggregation
单边顶点聚合release_aggregation
聚合顶点释放node_star
收藏un_node_star
取消收藏show_label
show_names
显示节点名称un_show_names
un_show_label
隐藏节点名称fix_nodes
固定节点un_fix_nodes
取消固定节点delete_node
删除节点
handleCustomSelect
const handleHighLight = () => {
forceGraph.value.handleCustomSelect('include', 'id', ['xxxs0'])
}
图标加载方式
图标icon图片有2中加载方式:1从cdn中加载,2打包为base64到npm包中加载。
图谱中的图标icon默认是从cdn链接中加载的。如果您存在私有化部署不能访问公网的场景,可以联系作者打包base64版本。
其他配置项
1.关系节点增加统计数字
在config配置中的的plugs对应的新增一个 show_total 字段,布尔值 true 或者 false。
2.icon自定义图标的图片
数据节点的图标。 节点详情detail接口的 info下 新增 icon_img字段 存在,则使用此 icon_img 图片。 可以是图片链接或者是base64。
关系节点的图标。 在config接口的plugs字段下对应的位置,加一个icon_img字段,用于关系节点的图标。
3.节点线上 增加描述文案
在获取节点和link的接口中,在links字段下面,新增一个字段 edge_label,字符串,如果有值则展示此文案,没有则不展示。
config配置
// config配置
{
"code": "0",
"msg": "ok",
"request_id": "QJDysikHdHqtwhMRQFek",
"data": {
"plugs": {
"md5": [
{
"show_total": true, // 是否展示增加统计数字
"icon_img": "https://files.codelife.cc/icons/google.svg", // 自定义关系节点图标的图片
"canloop": true,
"icon": "file",
"name": "xxx",
"namec": "释放文件",
"path": "xxxx",
"relay_name": "释放文件"
},
]
}
}
}
detail配置
{
"code": "0",
"msg": "ok",
"data": {
"records": [
{
"summary": "",
"tags": null,
"info": {
"id": "sfdsdfsf",
"name": "“xxx",
"type": "report",
"icon_img": "自定义节点图片", // 自定义图片
"basic": {
"title": "“黑球”行动再升级,SMBGhost漏洞攻击进入实战",
"url": "xxxx",
"update_time": "2021-04-29 05:11:53"
},
"extends": null
},
"brief": []
}
]
}
}
获取节点数据接口示例
{
"code": "0",
"msg": "ok",
"data": {
"nodes": [
{
"id": "a",
"name": "a",
"type": "md5",
"origin": [],
"feature": {}
},
{
"id": "b",
"name": "b",
"type": "md5",
"origin": [],
"feature": {}
}
],
"links": [
{
"source": "a",
"target": "b",
"type": "domain-md5",
"desc": "",
"feature": {},
"edge_label": "边的描述文案" // 新增:边的描述文案
}
]
}
}
开发相关
To run the development server
npm run dev
To build the library
npm run lib
To publish a new version
npm run patch
npm run lib
npm publish
开发人员手册
如有问题请联系 jiangzhenxiang