style: 修复样式

This commit is contained in:
TsMask
2024-11-23 15:51:31 +08:00
parent cb510d9fdb
commit 729d5518e8
24 changed files with 3038 additions and 346 deletions

View File

@@ -0,0 +1,267 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listAllNeInfo } from '@/api/ne/neInfo';
import { message } from 'ant-design-vue/es';
import { getGraphData } from '@/api/monitor/topology';
import { Graph, GraphData, Tooltip } from '@antv/g6';
import { parseBasePath } from '@/plugins/file-static-url';
import { edgeLineAnimateState } from '@/views/monitor/topologyBuild/hooks/registerEdge';
import { nodeImageAnimateState } from '@/views/monitor/topologyBuild/hooks/registerNode';
import {
graphG6,
graphState,
graphNodeClickID,
notNeNodes,
} from '../../hooks/useTopology';
import useI18n from '@/hooks/useI18n';
const { t } = useI18n();
/**图DOM节点实例对象 */
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
/**图节点展示 */
const graphNodeTooltip = new Tooltip({
offsetX: 20,
offsetY: 20,
getContent(evt) {
if (!evt) return t('views.monitor.topologyBuild.graphNotInfo');
const { id, label, neState }: any = evt.item?.getModel();
if (notNeNodes.includes(id)) {
return `<div><span>${label || id}</span></div>`;
}
if (!neState) {
return `<div><span>${label || id}</span></div>`;
}
return `
<div
style="
display: flex;
flex-direction: column;
width: 200px;
"
>
<div><strong>${t('views.monitor.topology.state')}</strong><span>
${
neState.online
? t('views.monitor.topology.normalcy')
: t('views.monitor.topology.exceptions')
}
</span></div>
<div><strong>${t('views.monitor.topology.refreshTime')}</strong><span>
${neState.refreshTime ?? '--'}
</span></div>
<div>========================</div>
<div><strong>ID</strong><span>${neState.neId}</span></div>
<div><strong>${t('views.monitor.topology.name')}</strong><span>
${neState.neName ?? '--'}
</span></div>
<div><strong>IP</strong><span>${neState.neIP}</span></div>
<div><strong>${t('views.monitor.topology.version')}</strong><span>
${neState.version ?? '--'}
</span></div>
<div><strong>${t('views.monitor.topology.serialNum')}</strong><span>
${neState.sn ?? '--'}
</span></div>
<div><strong>${t('views.monitor.topology.expiryDate')}</strong><span>
${neState.expire ?? '--'}
</span></div>
</div>
`;
},
itemTypes: ['node'],
});
/**图绑定事件 */
function fnGraphEvent(graph: Graph) {
// 节点点击
graph.on('node:click', evt => {
// 获得鼠标当前目标节点
const node = evt.item?.getModel();
if (node && node.id && !notNeNodes.includes(node.id)) {
graphNodeClickID.value = node.id;
}
});
}
/**图数据渲染 */
function handleRanderGraph(
container: HTMLElement | undefined,
data: GraphData
) {
if (!container) return;
const { clientHeight, clientWidth } = container;
edgeLineAnimateState();
nodeImageAnimateState();
const graph = new Graph({
container: container,
width: clientWidth,
height: clientHeight - 36,
fitCenter: true,
fitView: true,
fitViewPadding: [20],
autoPaint: true,
modes: {
default: ['drag-canvas', 'zoom-canvas'],
},
groupByTypes: false,
nodeStateStyles: {
selected: {
fill: 'transparent',
},
},
plugins: [graphNodeTooltip],
animate: true, // 是否使用动画过度,默认为 false
animateCfg: {
duration: 500, // Number一次动画的时长
easing: 'linearEasing', // String动画函数
},
});
graph.data(data);
graph.render();
fnGraphEvent(graph);
graphG6.value = graph;
// 创建 ResizeObserver 实例
var observer = new ResizeObserver(function (entries) {
// 当元素大小发生变化时触发回调函数
entries.forEach(function (entry) {
if (!graphG6.value) {
return;
}
graphG6.value.changeSize(
entry.contentRect.width,
entry.contentRect.height - 30
);
graphG6.value.fitCenter();
});
});
// 监听元素大小变化
observer.observe(container);
return graph;
}
/**
* 获取图组数据渲染到画布
* @param reload 是否重载数据
*/
function fnGraphDataLoad(reload: boolean = false) {
Promise.all([
getGraphData(graphState.group),
listAllNeInfo({
bandStatus: false,
}),
])
.then(resArr => {
const graphRes = resArr[0];
const neRes = resArr[1];
if (
graphRes.code === RESULT_CODE_SUCCESS &&
Array.isArray(graphRes.data.nodes) &&
graphRes.data.nodes.length > 0 &&
neRes.code === RESULT_CODE_SUCCESS &&
Array.isArray(neRes.data) &&
neRes.data.length > 0
) {
return {
graphData: graphRes.data,
neList: neRes.data,
};
} else {
message.warning({
content: t('views.monitor.topology.noData'),
duration: 5,
});
}
})
.then(res => {
if (!res) return;
const { combos, edges, nodes } = res.graphData;
// 节点过滤
const nf: Record<string, any>[] = nodes.filter(
(node: Record<string, any>) => {
Reflect.set(node, 'neState', { online: false });
// 图片路径处理
if (node.img) node.img = parseBasePath(node.img);
if (node.icon.show && node.icon?.img) {
node.icon.img = parseBasePath(node.icon.img);
}
// 遍历是否有网元数据
const nodeID: string = node.id;
const hasNe = res.neList.some(ne => {
Reflect.set(node, 'neInfo', ne.neType === nodeID ? ne : {});
return ne.neType === nodeID;
});
if (hasNe) {
return true;
}
if (notNeNodes.includes(nodeID)) {
return true;
}
return false;
}
);
// 边过滤
const ef: Record<string, any>[] = edges.filter(
(edge: Record<string, any>) => {
const edgeSource: string = edge.source;
const edgeTarget: string = edge.target;
const hasNeS = nf.some(n => n.id === edgeSource);
const hasNeT = nf.some(n => n.id === edgeTarget);
// console.log(hasNeS, edgeSource, hasNeT, edgeTarget);
if (hasNeS && hasNeT) {
return true;
}
if (hasNeS && notNeNodes.includes(edgeTarget)) {
return true;
}
if (hasNeT && notNeNodes.includes(edgeSource)) {
return true;
}
return false;
}
);
// 分组过滤
combos.forEach((combo: Record<string, any>) => {
const comboChildren: Record<string, any>[] = combo.children;
combo.children = comboChildren.filter(c => nf.some(n => n.id === c.id));
return combo;
});
// 图数据
graphState.data = { combos, edges: ef, nodes: nf };
})
.finally(() => {
if (graphState.data.length < 0) return;
// 重载数据
if (reload) {
graphG6.value.read(graphState.data);
} else {
handleRanderGraph(graphG6Dom.value, graphState.data);
}
});
}
onMounted(() => {
fnGraphDataLoad(false);
});
</script>
<template>
<div ref="graphG6Dom" class="chart"></div>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: 100%;
}
</style>