fix: 拓扑图基础
This commit is contained in:
513
src/components/ChartGraphG6/index.vue
Normal file
513
src/components/ChartGraphG6/index.vue
Normal file
@@ -0,0 +1,513 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div ref="g6Dom" :style="{ height: height, width: width }"></div>
|
||||||
|
<button @click="actions['Enable/Disable Node States'].Breathing()">
|
||||||
|
Breathing()
|
||||||
|
</button>
|
||||||
|
<button @click="actions['Enable/Disable Node States'].Scaling()">
|
||||||
|
Scaling()
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button @click="actions['Enable/Disable Edge States'].Growing()">
|
||||||
|
Growing()
|
||||||
|
</button>
|
||||||
|
<button @click="actions['Enable/Disable Edge States'].Running()">
|
||||||
|
Running()
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { nextTick, watch, onMounted, onBeforeUnmount, ref } from 'vue';
|
||||||
|
import { Graph, extend, Extensions } from '@antv/g6';
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
/**
|
||||||
|
* 图表主题
|
||||||
|
*
|
||||||
|
* 'dark' | 'light'
|
||||||
|
*/
|
||||||
|
theme: {
|
||||||
|
type: String,
|
||||||
|
default: 'light', // 'dark' | 'light'
|
||||||
|
},
|
||||||
|
/**宽度,默认100% */
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '100%',
|
||||||
|
},
|
||||||
|
/**高度 */
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '500px',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const g6Dom = ref<HTMLElement | undefined>(undefined);
|
||||||
|
|
||||||
|
const ExtGraph = extend(Graph, {
|
||||||
|
// layouts: {
|
||||||
|
// dagre: Extensions.DagreLayout,
|
||||||
|
// },
|
||||||
|
edges: {
|
||||||
|
'polyline-edge': Extensions.PolylineEdge,
|
||||||
|
'custom-edge': Extensions.CubicEdge,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
data: {
|
||||||
|
label: 'A0',
|
||||||
|
x: 110,
|
||||||
|
y: 110,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// B
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
data: {
|
||||||
|
label: 'B1',
|
||||||
|
parentId: 'B',
|
||||||
|
x: 110,
|
||||||
|
y: 350,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
data: {
|
||||||
|
label: 'B2',
|
||||||
|
parentId: 'B',
|
||||||
|
x: 220,
|
||||||
|
y: 350,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
data: {
|
||||||
|
label: 'B3',
|
||||||
|
parentId: 'A',
|
||||||
|
x: 360,
|
||||||
|
y: 350,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// C
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
data: {
|
||||||
|
label: 'C1',
|
||||||
|
parentId: 'C',
|
||||||
|
x: 360,
|
||||||
|
y: 150,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '5',
|
||||||
|
data: {
|
||||||
|
label: 'C2',
|
||||||
|
parentId: 'C',
|
||||||
|
x: 460,
|
||||||
|
y: 150,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
id: 'edge-102',
|
||||||
|
source: '0',
|
||||||
|
target: '1',
|
||||||
|
data: {
|
||||||
|
type: 'custom-edge',
|
||||||
|
animates: {
|
||||||
|
update: [
|
||||||
|
{
|
||||||
|
// 在 selected 和 active 状态变化导致的 haloShape opacity 变化时,使 opacity 带动画地更新
|
||||||
|
fields: ['opacity'],
|
||||||
|
shapeId: 'haloShape',
|
||||||
|
states: ['selected', 'active'],
|
||||||
|
duration: 500,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-161',
|
||||||
|
source: '0',
|
||||||
|
target: '2',
|
||||||
|
data: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-253',
|
||||||
|
source: '0',
|
||||||
|
target: 'A',
|
||||||
|
data: {
|
||||||
|
keyShape: {
|
||||||
|
endArrow: true,
|
||||||
|
},
|
||||||
|
labelShape: {
|
||||||
|
text: 'asdf-arrow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-237',
|
||||||
|
source: '1',
|
||||||
|
target: '4',
|
||||||
|
data: {
|
||||||
|
type: 'polyline-edge',
|
||||||
|
keyShape: {
|
||||||
|
endArrow: true,
|
||||||
|
routeCfg: {
|
||||||
|
/**
|
||||||
|
* 目前支持正交路由 'orth' 和地铁路由 'er'
|
||||||
|
*/
|
||||||
|
// name: 'er',
|
||||||
|
/**
|
||||||
|
* 是否开启自动避障,默认为 false
|
||||||
|
* Whether to enable automatic obstacle avoidance, default is false
|
||||||
|
*/
|
||||||
|
enableObstacleAvoidance: true,
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 拐弯处的圆角弧度,默认为直角,值为 0
|
||||||
|
* The radius of the corner rounding, defaults to a right angle
|
||||||
|
*/
|
||||||
|
// radius: 20,
|
||||||
|
/**
|
||||||
|
* 拐弯处距离节点最小距离, 默认为 2
|
||||||
|
* Minimum distance from the node at the corner, default is 5.
|
||||||
|
*/
|
||||||
|
// offset: 0,
|
||||||
|
/**
|
||||||
|
* 控制点数组,不指定时根据 A* 算法自动生成折线。若指定了,则按照 controlPoints 指定的位置进行弯折
|
||||||
|
* An array of control points that, when not specified, automatically generates the bends according to the A* algorithm. If specified, bends are made at the position specified by controlPoints.
|
||||||
|
*/
|
||||||
|
// controlPoints: [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-133',
|
||||||
|
source: '2',
|
||||||
|
target: '4',
|
||||||
|
data: {
|
||||||
|
type: 'polyline-edge',
|
||||||
|
keyShape: {
|
||||||
|
/**
|
||||||
|
* 拐弯处的圆角弧度,默认为直角
|
||||||
|
*/
|
||||||
|
radius: 20,
|
||||||
|
/**
|
||||||
|
* 拐弯处距离节点最小距离, 默认为 5
|
||||||
|
*/
|
||||||
|
// offset: 0,
|
||||||
|
/**
|
||||||
|
* 控制点数组,不指定时根据 A* 算法自动生成折线。若指定了,则按照 controlPoints 指定的位置进行弯折
|
||||||
|
*/
|
||||||
|
controlPoints: [
|
||||||
|
{ x: 220, y: 220 },
|
||||||
|
{ x: 300, y: 130 },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-320',
|
||||||
|
source: '2',
|
||||||
|
target: '5',
|
||||||
|
data: {
|
||||||
|
keyShape: {
|
||||||
|
endArrow: true,
|
||||||
|
},
|
||||||
|
labelShape: {
|
||||||
|
text: 'edge-arrow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'edge-355',
|
||||||
|
source: '3',
|
||||||
|
target: '4',
|
||||||
|
data: {
|
||||||
|
keyShape: {
|
||||||
|
endArrow: true,
|
||||||
|
},
|
||||||
|
labelShape: {
|
||||||
|
text: 'asdf-arrow',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
combos: [
|
||||||
|
{
|
||||||
|
id: 'A',
|
||||||
|
data: {
|
||||||
|
text: 'combo A',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'B',
|
||||||
|
data: {
|
||||||
|
label: 'combo B',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 'C',
|
||||||
|
data: {
|
||||||
|
label: 'combo C',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
let graph: any = null;
|
||||||
|
/**初始化渲染图表 */
|
||||||
|
function initChart() {
|
||||||
|
if (!g6Dom.value) return;
|
||||||
|
graph = new ExtGraph({
|
||||||
|
container: g6Dom.value,
|
||||||
|
height: 500,
|
||||||
|
plugins: [
|
||||||
|
{
|
||||||
|
// lod-controller will be automatically assigned to graph with `disableLod: false` to graph if it is not configured as following
|
||||||
|
type: 'lod-controller',
|
||||||
|
disableLod: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
modes: {
|
||||||
|
default: [
|
||||||
|
{
|
||||||
|
type: 'drag-node',
|
||||||
|
enableTransient: false,
|
||||||
|
updateComboStructure: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'click-select',
|
||||||
|
itemTypes: ['node', 'edge', 'combo'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'drag-combo',
|
||||||
|
enableTransient: true,
|
||||||
|
updateComboStructure: true,
|
||||||
|
},
|
||||||
|
// 'drag-combo',
|
||||||
|
'drag-canvas',
|
||||||
|
// 'click-select',
|
||||||
|
'zoom-canvas',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
theme: {
|
||||||
|
type: 'spec',
|
||||||
|
base: 'light',
|
||||||
|
specification: {
|
||||||
|
node: {
|
||||||
|
dataTypeField: 'parentId',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
node: model => {
|
||||||
|
const { id, data } = model;
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
data: {
|
||||||
|
...data,
|
||||||
|
type: 'rect-node',
|
||||||
|
keyShape: {
|
||||||
|
width: 60,
|
||||||
|
height: 30,
|
||||||
|
radius: 8,
|
||||||
|
},
|
||||||
|
labelShape: {
|
||||||
|
position: 'center',
|
||||||
|
text: data.label,
|
||||||
|
},
|
||||||
|
animates: {
|
||||||
|
update: [
|
||||||
|
{
|
||||||
|
fields: ['opacity'],
|
||||||
|
shapeId: 'haloShape',
|
||||||
|
states: ['breathing'],
|
||||||
|
iterations: Infinity,
|
||||||
|
direction: 'alternate',
|
||||||
|
duration: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: ['lineWidth'],
|
||||||
|
shapeId: 'keyShape',
|
||||||
|
states: ['breathing'],
|
||||||
|
iterations: Infinity,
|
||||||
|
direction: 'alternate',
|
||||||
|
duration: 500,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: ['height'],
|
||||||
|
shapeId: 'keyShape',
|
||||||
|
states: ['scaling'],
|
||||||
|
iterations: Infinity,
|
||||||
|
direction: 'alternate',
|
||||||
|
duration: 500,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
edge: {
|
||||||
|
type: 'custom-edge',
|
||||||
|
animates: {
|
||||||
|
update: [
|
||||||
|
{
|
||||||
|
fields: ['lineDash'],
|
||||||
|
shapeId: 'keyShape',
|
||||||
|
states: ['growing', 'running'],
|
||||||
|
iterations: Infinity,
|
||||||
|
duration: 2000,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fields: ['offsetDistance'],
|
||||||
|
shapeId: 'buShape',
|
||||||
|
states: ['circleRunning'],
|
||||||
|
iterations: Infinity,
|
||||||
|
duration: 2000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
combo: model => {
|
||||||
|
const { id, data } = model;
|
||||||
|
return {
|
||||||
|
id,
|
||||||
|
data: {
|
||||||
|
...data,
|
||||||
|
type: 'rect-combo',
|
||||||
|
keyShape: {
|
||||||
|
opacity: 0.8,
|
||||||
|
padding: [20, 20, 20, 20],
|
||||||
|
radius: 8,
|
||||||
|
},
|
||||||
|
labelShape: {
|
||||||
|
text: data.label,
|
||||||
|
offsetY: 8,
|
||||||
|
},
|
||||||
|
labelBackgroundShape: {},
|
||||||
|
animates: {
|
||||||
|
update: [
|
||||||
|
{
|
||||||
|
fields: ['width', 'height', 'x', 'y'],
|
||||||
|
shapeId: 'keyShape',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
nodeState: {
|
||||||
|
breathing: {
|
||||||
|
haloShape: {
|
||||||
|
opacity: 0.25,
|
||||||
|
lineWidth: 20,
|
||||||
|
visible: true,
|
||||||
|
},
|
||||||
|
keyShape: {
|
||||||
|
stroke: '#000',
|
||||||
|
lineWidth: 4,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
scaling: {
|
||||||
|
keyShape: {
|
||||||
|
r: 24,
|
||||||
|
width: 48,
|
||||||
|
height: 48,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
edgeState: {
|
||||||
|
growing: {
|
||||||
|
keyShape: {
|
||||||
|
lineWidth: 2,
|
||||||
|
lineDash: ['100%', 0],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
running: {
|
||||||
|
keyShape: {
|
||||||
|
lineWidth: 2,
|
||||||
|
lineDash: [2, 2],
|
||||||
|
// TODO: lineDashOffset
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const actions = {
|
||||||
|
'Enable/Disable Node States': {
|
||||||
|
Breathing: () => {
|
||||||
|
graph.getAllNodesData().forEach(node => {
|
||||||
|
if (graph.getItemState(node.id, 'breathing')) {
|
||||||
|
graph.setItemState(node.id, 'breathing', false);
|
||||||
|
} else {
|
||||||
|
graph.setItemState(node.id, 'scaling', false);
|
||||||
|
graph.setItemState(node.id, 'breathing', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Scaling: () => {
|
||||||
|
graph.getAllNodesData().forEach(node => {
|
||||||
|
if (graph.getItemState(node.id, 'scaling')) {
|
||||||
|
graph.setItemState(node.id, 'scaling', false);
|
||||||
|
} else {
|
||||||
|
graph.setItemState(node.id, 'breathing', false);
|
||||||
|
graph.setItemState(node.id, 'scaling', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
'Enable/Disable Edge States': {
|
||||||
|
Growing: () => {
|
||||||
|
graph.getAllEdgesData().forEach(edge => {
|
||||||
|
if (graph.getItemState(edge.id, 'growing')) {
|
||||||
|
graph.setItemState(edge.id, 'growing', false);
|
||||||
|
} else {
|
||||||
|
graph.setItemState(edge.id, 'running', false);
|
||||||
|
graph.setItemState(edge.id, 'growing', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
Running: () => {
|
||||||
|
graph.getAllEdgesData().forEach(edge => {
|
||||||
|
if (graph.getItemState(edge.id, 'running')) {
|
||||||
|
graph.setItemState(edge.id, 'running', false);
|
||||||
|
} else {
|
||||||
|
graph.setItemState(edge.id, 'growing', false);
|
||||||
|
graph.setItemState(edge.id, 'running', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(
|
||||||
|
() => props.option,
|
||||||
|
val => {
|
||||||
|
// if (val) {
|
||||||
|
// nextTick(() => {
|
||||||
|
// initChart();
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
nextTick(() => {
|
||||||
|
initChart();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
onBeforeUnmount(() => {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped></style>
|
||||||
68
src/views/monitor/topology/index.vue
Normal file
68
src/views/monitor/topology/index.vue
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { reactive, onMounted } from 'vue';
|
||||||
|
import { PageContainer } from 'antdv-pro-layout';
|
||||||
|
import ChartGraphG6 from '@/components/ChartGraphG6/index.vue';
|
||||||
|
import useI18n from '@/hooks/useI18n';
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
/**查询全部网元数据列表 */
|
||||||
|
function fnGetList() {}
|
||||||
|
|
||||||
|
onMounted(() => {});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<PageContainer>
|
||||||
|
<a-card
|
||||||
|
:bordered="false"
|
||||||
|
:body-style="{ marginBottom: '24px', paddingBottom: 0 }"
|
||||||
|
>
|
||||||
|
<!-- 表格搜索栏 -->
|
||||||
|
<a-form name="queryParams" layout="horizontal">
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="10" :md="10" :xs="24">
|
||||||
|
<a-form-item
|
||||||
|
:label="t('views.monitor.monitor.filter')"
|
||||||
|
name="neTypeSelect"
|
||||||
|
>
|
||||||
|
ssdf
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :lg="6" :md="12" :xs="24">
|
||||||
|
<a-form-item>
|
||||||
|
<a-space :size="8">
|
||||||
|
<a-button type="primary" @click.prevent="fnGetList()">
|
||||||
|
<template #icon><SearchOutlined /></template>
|
||||||
|
{{ t('common.search') }}
|
||||||
|
</a-button>
|
||||||
|
</a-space>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-form>
|
||||||
|
</a-card>
|
||||||
|
|
||||||
|
<a-row :gutter="16">
|
||||||
|
<a-col :lg="24" :md="24" :xs="24">
|
||||||
|
<a-card :bordered="false" :body-style="{ marginBottom: '24px' }">
|
||||||
|
<!-- 插槽-卡片左侧侧 -->
|
||||||
|
<template #title>asdf</template>
|
||||||
|
<!-- 插槽-卡片右侧 -->
|
||||||
|
<template #extra> adf </template>
|
||||||
|
|
||||||
|
<div class="chart">
|
||||||
|
<ChartGraphG6 :option="{}"></ChartGraphG6>
|
||||||
|
</div>
|
||||||
|
</a-card>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</PageContainer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
.chart {
|
||||||
|
width: 100%;
|
||||||
|
height: 500px;
|
||||||
|
background-color: rgb(238, 237, 237);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Reference in New Issue
Block a user