12 changed files with 462 additions and 4571 deletions
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
<template> |
||||
<div>Use G6 in Vue</div> |
||||
<div id="container" class="w-full h-full"></div> |
||||
</template> |
||||
|
||||
<script setup lang="ts"> |
||||
import { onMounted } from 'vue'; |
||||
import { ExtensionCategory, Graph, register } from '@antv/g6'; |
||||
import { MyLineEdge } from './utils/MyLineEdge'; |
||||
import DeviceData from './utils/data.ts'; |
||||
|
||||
import { flattenTree, GenerateGraphData } from "@/views/testG6/utils"; |
||||
|
||||
|
||||
onMounted(() => { |
||||
register(ExtensionCategory.EDGE, 'my-line-edge', MyLineEdge); |
||||
const device = flattenTree(DeviceData) |
||||
console.log(device) |
||||
const graphData = new GenerateGraphData(device) |
||||
|
||||
const graph = new Graph({ |
||||
container: document.getElementById('container')!, |
||||
|
||||
layout: { |
||||
type: 'dagre', |
||||
}, |
||||
edge: { |
||||
type: 'my-line-edge', |
||||
}, |
||||
data: { |
||||
nodes: graphData.getNodes(), |
||||
edges: graphData.getEdges() |
||||
}, |
||||
behaviors: ['drag-canvas', 'zoom-canvas', 'drag-element'], |
||||
}); |
||||
console.log(graphData.getEdges()) |
||||
graph.render(); |
||||
|
||||
}); |
||||
</script> |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
import { BaseEdge } from '@antv/g6'; |
||||
import type { PathArray } from "@antv/util"; |
||||
import { Circle } from '@antv/g'; |
||||
import { subStyleProps } from '@antv/g6'; |
||||
|
||||
|
||||
export class MyLineEdge extends BaseEdge { |
||||
|
||||
getMarkerStyle(attributes: object) { |
||||
return { |
||||
r: 5, |
||||
fill: '#c3d5f9', |
||||
offsetPath: this.shapeMap.key, ...subStyleProps(attributes, 'marker') |
||||
}; |
||||
} |
||||
|
||||
onCreate() { |
||||
const marker = this.upsert('marker', Circle, this.getMarkerStyle(this.attributes), this)!; |
||||
marker.animate([{ offsetDistance: 0 }, { offsetDistance: 1 }], { |
||||
duration: 3000, |
||||
iterations: Infinity, |
||||
}); |
||||
} |
||||
|
||||
// 这里保持你的路径逻辑
|
||||
protected getKeyPath(attrs: any): PathArray { |
||||
const { sourceNode, targetNode } = this; |
||||
|
||||
const [sx, sy] = sourceNode.getPosition(); |
||||
const [tx, ty] = targetNode.getPosition(); |
||||
const [x1, y1] = sourceNode.getPosition(); |
||||
const [x2, y2] = targetNode.getPosition(); |
||||
|
||||
// 固定的主干 X
|
||||
const busX = attrs.busX ?? tx; |
||||
|
||||
// return [
|
||||
// ['M', x1, y1],
|
||||
// ['L', x2, y2],
|
||||
// ];
|
||||
|
||||
return [ |
||||
['M', sx, sy], |
||||
['L', busX, sy], |
||||
['L', busX, ty], |
||||
['L', tx, ty], |
||||
]; |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,226 @@
@@ -0,0 +1,226 @@
|
||||
export default [{ |
||||
"id": 398, |
||||
"sn": "ems1", |
||||
"name": "安庆滨江夜市站", |
||||
"sort": 0, |
||||
"parentId": 0, |
||||
"deviceId": "t00510398", |
||||
"dictName": "device_one_entity_type", |
||||
"level": 0, |
||||
"type": 0, |
||||
"description": null, |
||||
"children": [ |
||||
{ |
||||
"id": 400, |
||||
"sn": "yiming-EMS1", |
||||
"name": "储能单元1", |
||||
"sort": 1, |
||||
"parentId": 398, |
||||
"deviceId": "t00510400", |
||||
"dictName": "device_two_entity_type", |
||||
"level": 1, |
||||
"type": 1, |
||||
"description": "", |
||||
"children": [ |
||||
{ |
||||
"id": 404, |
||||
"sn": "B48100B210TF36003E-bms", |
||||
"name": "BMS-1", |
||||
"sort": 1, |
||||
"parentId": 400, |
||||
"deviceId": "t00510404", |
||||
"dictName": "", |
||||
"level": 2, |
||||
"type": 2, |
||||
"description": "", |
||||
"children": null |
||||
}, |
||||
{ |
||||
"id": 408, |
||||
"sn": "B48100B210TF36003E-pcs", |
||||
"name": "PCS-1", |
||||
"sort": 1, |
||||
"parentId": 400, |
||||
"deviceId": "t00510408", |
||||
"dictName": "", |
||||
"level": 2, |
||||
"type": 3, |
||||
"description": "", |
||||
"children": null |
||||
} |
||||
] |
||||
}, |
||||
{ |
||||
"id": 401, |
||||
"sn": "yiming-EMS2", |
||||
"name": "储能单元2", |
||||
"sort": 1, |
||||
"parentId": 398, |
||||
"deviceId": "t00510401", |
||||
"dictName": "device_two_entity_type", |
||||
"level": 1, |
||||
"type": 1, |
||||
"description": "", |
||||
"children": [ |
||||
{ |
||||
"id": 405, |
||||
"sn": "B48100B210TF36003K-bms", |
||||
"name": "BMS-2", |
||||
"sort": 1, |
||||
"parentId": 401, |
||||
"deviceId": "t00510405", |
||||
"dictName": "", |
||||
"level": 2, |
||||
"type": 2, |
||||
"description": "", |
||||
"children": null |
||||
}, |
||||
{ |
||||
"id": 409, |
||||
"sn": "B48100B210TF36003K-pcs", |
||||
"name": "PCS-2", |
||||
"sort": 1, |
||||
"parentId": 401, |
||||
"deviceId": "t00510409", |
||||
"dictName": "", |
||||
"level": 2, |
||||
"type": 3, |
||||
"description": "", |
||||
"children": null |
||||
} |
||||
] |
||||
}, |
||||
// {
|
||||
// "id": 402,
|
||||
// "sn": "yiming-EMS3",
|
||||
// "name": "储能单元3",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510402",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 1,
|
||||
// "description": "",
|
||||
// "children": [
|
||||
// {
|
||||
// "id": 406,
|
||||
// "sn": "B48100B210TF36002V-bms",
|
||||
// "name": "BMS-3",
|
||||
// "sort": 1,
|
||||
// "parentId": 402,
|
||||
// "deviceId": "t00510406",
|
||||
// "dictName": "",
|
||||
// "level": 2,
|
||||
// "type": 2,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// },
|
||||
// {
|
||||
// "id": 410,
|
||||
// "sn": "B48100B210TF36002V-pcs",
|
||||
// "name": "PCS-3",
|
||||
// "sort": 1,
|
||||
// "parentId": 402,
|
||||
// "deviceId": "t00510410",
|
||||
// "dictName": "",
|
||||
// "level": 2,
|
||||
// "type": 3,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "id": 403,
|
||||
// "sn": "yiming-EMS4",
|
||||
// "name": "储能单元4",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510403",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 1,
|
||||
// "description": "",
|
||||
// "children": [
|
||||
// {
|
||||
// "id": 407,
|
||||
// "sn": "B48100B210TF360029-bms",
|
||||
// "name": "BMS-4",
|
||||
// "sort": 1,
|
||||
// "parentId": 403,
|
||||
// "deviceId": "t00510407",
|
||||
// "dictName": "",
|
||||
// "level": 2,
|
||||
// "type": 2,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// },
|
||||
// {
|
||||
// "id": 411,
|
||||
// "sn": "B48100B210TF360029-pcs",
|
||||
// "name": "PCS-4",
|
||||
// "sort": 1,
|
||||
// "parentId": 403,
|
||||
// "deviceId": "t00510411",
|
||||
// "dictName": "",
|
||||
// "level": 2,
|
||||
// "type": 3,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// }
|
||||
// ]
|
||||
// },
|
||||
// {
|
||||
// "id": 412,
|
||||
// "sn": "B48100B210TF36003E-em",
|
||||
// "name": "电量信息-1",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510412",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 4,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// },
|
||||
// {
|
||||
// "id": 413,
|
||||
// "sn": "B48100B210TF36003K-em",
|
||||
// "name": "电量信息-2",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510413",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 4,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// },
|
||||
// {
|
||||
// "id": 414,
|
||||
// "sn": "B48100B210TF36002V-em",
|
||||
// "name": "电量信息-3",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510414",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 4,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// },
|
||||
// {
|
||||
// "id": 415,
|
||||
// "sn": "B48100B210TF360029-em",
|
||||
// "name": "电量信息-4",
|
||||
// "sort": 1,
|
||||
// "parentId": 398,
|
||||
// "deviceId": "t00510415",
|
||||
// "dictName": "device_two_entity_type",
|
||||
// "level": 1,
|
||||
// "type": 4,
|
||||
// "description": "",
|
||||
// "children": null
|
||||
// }
|
||||
] |
||||
}] |
@ -0,0 +1,102 @@
@@ -0,0 +1,102 @@
|
||||
import { flatMap } from 'lodash-es' |
||||
import type { NodeData, EdgeData } from "@antv/g6"; |
||||
|
||||
type Device = any |
||||
|
||||
export enum DeviceType { |
||||
Ems, |
||||
Ecu, |
||||
Bms, |
||||
Pcs, |
||||
Em, |
||||
'Em-Measure', |
||||
Tms, |
||||
Ffs, |
||||
Wpp, |
||||
Mppt, |
||||
Dgs, |
||||
Cac, |
||||
} |
||||
|
||||
export function flattenTree(tree: Device[], dep = 0): Device[] { |
||||
return flatMap(tree, (node: Device,) => { |
||||
const { children, ...rest } = node |
||||
const current = { ...rest, dep } |
||||
return [current, ...(children ? flattenTree(children, dep + 1) : [])] |
||||
}) |
||||
} |
||||
|
||||
export class GenerateGraphData { |
||||
private readonly devices: Device[] = []; |
||||
private nodes: NodeData[] = []; |
||||
private edges: EdgeData[] = []; |
||||
|
||||
constructor(devices: Device[]) { |
||||
this.devices = devices; |
||||
this.generateNodeData() |
||||
this.generateEdgeData(); |
||||
} |
||||
|
||||
private generateNodeData() { |
||||
for (const device of this.devices) { |
||||
const deviceChild = this.devices.filter((item: Device) => device.id === item.parentId) |
||||
this.nodes.push({ |
||||
id: String(device.id), |
||||
label: device.name, |
||||
data: device |
||||
}) |
||||
if (!!deviceChild.length) { |
||||
// 在每个有子节点的设备下插入一个虚拟节点
|
||||
this.nodes.push({ |
||||
id: `${device.id}-virtual`, |
||||
label: '', |
||||
type: '', |
||||
style: { opacity: 0 }, |
||||
size: 1, |
||||
data: { |
||||
type: 'virtual-node', |
||||
parentId: String(device.id), |
||||
} |
||||
}) |
||||
|
||||
} |
||||
} |
||||
} |
||||
|
||||
private generateEdgeData() { |
||||
for (const node of this.nodes) { |
||||
|
||||
const customData: Device = node.data |
||||
const virtualId = `${customData.parentId}-virtual`; |
||||
const findParentNode: Device = this.nodes.find((n: NodeData) => n.id === customData.parentId); |
||||
if (!findParentNode) { |
||||
// 如果没有找到父节点,则可能是根节点或孤立节点
|
||||
if (customData.type == DeviceType.Ems) continue; |
||||
this.edges.push({ |
||||
source: virtualId, |
||||
target: node.id, |
||||
type: 'polyline', |
||||
data: customData |
||||
}) |
||||
|
||||
} else { |
||||
this.edges.push({ |
||||
source: customData.type === 'virtual-node' ? customData.parentId : virtualId, |
||||
target: String(node.id), |
||||
type: 'polyline', |
||||
data: customData |
||||
}) |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
getNodes(): NodeData[] { |
||||
return this.nodes; |
||||
} |
||||
|
||||
getEdges(): EdgeData[] { |
||||
return this.edges; |
||||
} |
||||
|
||||
} |
Loading…
Reference in new issue