Files
fe.ems.vue3/src/views/monitor/topology/index.vue
2024-01-05 15:49:42 +08:00

194 lines
5.2 KiB
Vue

<script setup lang="ts">
import { reactive, onMounted, ref, onBeforeUnmount } from 'vue';
import { PageContainer } from 'antdv-pro-layout';
import useI18n from '@/hooks/useI18n';
import { RESULT_CODE_SUCCESS } from '@/constants/result-constants';
import { listNe, stateNe } from '@/api/ne/ne';
import message from 'ant-design-vue/lib/message';
import { randerGroph, switchLayout } from './graph';
import { parseDateToStr } from '@/utils/date-utils';
const { t } = useI18n();
/**图DOM节点实例对象 */
const graphG6Dom = ref<HTMLElement | undefined>(undefined);
/**图实例对象 */
const graphG6 = ref<any>(null);
/**图数据 */
const graphG6Data = reactive<Record<string, any>>({
nodes: [],
edges: [],
});
/**查询全部网元数据列表 */
function fnRanderData() {
if (!graphG6Dom.value) return;
graphG6.value = randerGroph(t, graphG6Dom.value, graphG6Data);
}
/**网元状态定时器 */
const stateTimeout = ref<any>(null);
/**查询网元状态 */
async function fnGetState() {
clearTimeout(stateTimeout.value);
for (const node of graphG6Data.nodes) {
const ne = node.info;
// if (ne.neType === 'OMC') continue;
const result = await stateNe(ne.neType, ne.neId);
if (result.code === RESULT_CODE_SUCCESS) {
ne.serverState = result.data;
ne.serverState.refreshTime = parseDateToStr(
ne.serverState.refreshTime,
'HH:mm:ss'
);
// 修改网元状态颜色
const neShape = graphG6.value.findById(ne.neName);
graphG6.value.setItemState(neShape, 'neState', ne.serverState.online);
}
}
stateTimeout.value = setTimeout(() => fnGetState(), 30_000);
}
/**查询全部网元数据列表 */
function fnGetList(refresh: boolean = false) {
listNe({
bandStatus: false,
})
.then(res => {
if (
res.code === RESULT_CODE_SUCCESS &&
Array.isArray(res.data) &&
res.data.length > 0
) {
// 根网管
let rootNodeInfo = { neName: undefined };
const nodes = [];
const edges = [];
for (const item of res.data) {
item.serverState = {};
// 节点
const nodeIndex = nodes.findIndex(v => v.id === item.neName);
if (nodeIndex === -1) {
if (item.neType === 'OMC') {
nodes.push({
id: item.neName,
label: item.neName,
info: item,
labelCfg: {
position: 'bottom',
offset: 8,
style: {
fill: '#fff',
fontSize: 14,
},
},
size: 60,
icon: {
x: -30,
y: -30,
// 可更换为其他图片地址
img: '/svg/service_db.svg',
width: 60,
height: 60,
},
});
!rootNodeInfo.neName && (rootNodeInfo = item);
} else {
nodes.push({
id: item.neName,
label: item.neName,
info: item,
size: 48,
icon: {
x: -24,
y: -24,
img: '/svg/service.svg',
width: 48,
height: 48,
},
});
}
}
// 边
if (item.neType !== 'OMC') {
const edgeIndex = edges.findIndex(v => v.source === item.neName);
if (edgeIndex === -1) {
edges.push({
source: item.neName,
target: rootNodeInfo.neName,
label: `${item.neName}-${rootNodeInfo.neName}`,
});
}
} else {
edges.push({
source: item.neName,
target: rootNodeInfo.neName,
label: `${item.neName}-${rootNodeInfo.neName}`,
});
}
}
graphG6Data.nodes = nodes;
graphG6Data.edges = edges;
return true;
} else {
message.warning({
content: t('common.noData'),
duration: 2,
});
return false;
}
})
.then(hasNeList => {
if (!hasNeList) return;
if (refresh) {
// graphG6.value.get('canvas').set('localRefresh', true);
graphG6.value.destroy();
// graphG6.value.clear();
}
fnRanderData();
fnGetState();
});
}
onMounted(() => {
// 获取网元列表G
fnGetList();
});
onBeforeUnmount(() => {
clearTimeout(stateTimeout.value);
});
</script>
<template>
<PageContainer>
<a-card
:bordered="false"
:body-style="{ marginBottom: '24px' }"
size="small"
>
<!-- 插槽-卡片左侧侧 -->
<template #title> </template>
<!-- 插槽-卡片右侧 -->
<template #extra>
<a-button type="default" @click.prevent="switchLayout()">
<template #icon><RetweetOutlined /></template>
{{ t('views.monitor.topology.switchLayout') }}
</a-button>
</template>
<div ref="graphG6Dom" class="chart"></div>
</a-card>
</PageContainer>
</template>
<style lang="less" scoped>
.chart {
width: 100%;
height: calc(100vh - 300px);
background-color: rgb(43, 47, 51);
}
</style>