This repository has been archived on 2025-09-14. You can view files and clone it, but cannot push or open issues or pull requests.
Files
cyber-narrator-cn-ui/src/views/charts2/charts/linkMonitor/LinkDirectionGrid.vue

368 lines
13 KiB
Vue
Raw Normal View History

2022-09-10 23:13:42 +08:00
<template>
2022-09-15 15:51:00 +08:00
<div class="link-direction-grid">
<!--左侧链路出入口-->
<popover-content :title="$t('linkMonitor.egressLink') + ' & ' + $t('linkMonitor.ingressLink')" :isNoData="isLinkNoData" :gridData="linkGridData" :showError="isLinkShowError" :content="linkErrorMsg" style="width: 900px;"/>
<!--右侧链路下一跳-->
2023-03-16 19:07:37 +08:00
<popover-content :title="$t('linkMonitor.nextHopInternetOfGrid')" :isNoData="isNextNoData" :gridData="nextGridData" :showError="isNextShowError" :content="nextErrorMsg" />
2022-09-15 15:51:00 +08:00
</div>
2022-09-10 23:13:42 +08:00
</template>
<script>
import chartMixin from '@/views/charts2/chart-mixin'
2022-09-15 15:51:00 +08:00
import { getSecond } from '@/utils/date-util'
import { api } from '@/utils/api'
import { storageKey } from '@/utils/constants'
import PopoverContent from './LinkDirectionGrid/PopoverContent'
import { computeScore } from '@/utils/tools'
import axios from 'axios'
import _ from 'lodash'
2022-09-10 23:13:42 +08:00
export default {
name: 'LinkDirectionGrid',
2022-09-15 15:51:00 +08:00
mixins: [chartMixin],
data () {
return {
2022-11-21 17:31:30 +08:00
linkGridData: [],
nextGridData: [],
isLinkNoData: false,
isNextNoData: false,
isLinkShowError: false, // 显示左侧链路报错标识
linkErrorMsg: '', // 左侧链路的报错信息
isNextShowError: false, // 显示右侧下一跳报错标识
nextErrorMsg: '' // 右侧下一跳的报错信息
2022-09-15 15:51:00 +08:00
}
},
components: {
PopoverContent
},
watch: {
timeFilter: {
2022-11-21 17:31:30 +08:00
handler () {
this.init()
}
}
},
mounted () {
this.init()
},
2022-09-15 15:51:00 +08:00
methods: {
init () {
// 链路基本信息
let linkInfo = localStorage.getItem(storageKey.linkInfo)
linkInfo = JSON.parse(linkInfo)
2022-09-15 15:51:00 +08:00
const params = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime)
}
2023-03-16 19:07:37 +08:00
const dataRequest = axios.get(api.linkMonitor.bigramAnalysis, { params: params }).catch(e => {
this.isLinkShowError = true
this.isLinkNoData = false
this.linkErrorMsg = this.errorMsgHandler(e)
})
const nextHopRequest = axios.get(api.linkMonitor.bigramNextHopAnalysis, { params: params }).catch(e => {
this.isNextShowError = true
this.isNextNoData = false
this.nextErrorMsg = this.errorMsgHandler(e)
})
this.toggleLoading(true)
Promise.all([dataRequest, nextHopRequest]).then(response => {
2023-08-25 16:23:18 +08:00
if (response[0].status === 200 && response[1].status === 200) {
2023-03-16 19:07:37 +08:00
const res = []
res[0] = response[0].data
res[1] = response[1].data
2023-08-25 16:23:18 +08:00
if (response[0].status === 200) {
2023-03-16 19:07:37 +08:00
this.isLinkShowError = false
// 链路流量数据
2023-03-16 19:07:37 +08:00
const linkData = res[0].data.result
2023-08-29 16:24:02 +08:00
// 接口数据乱序根据入链路idinLinkId大小排序之后
// 再根据同inLinkId下的outLinkId进行排序
2023-03-16 19:07:37 +08:00
linkData.sort((a, b) => {
2023-08-29 16:24:02 +08:00
if (a.inLinkId !== b.inLinkId) {
return a.inLinkId - b.inLinkId
2023-03-16 19:07:37 +08:00
}
2023-08-29 16:24:02 +08:00
return a.outLinkId - b.outLinkId
2023-03-16 19:07:37 +08:00
})
2023-03-16 19:07:37 +08:00
this.isLinkNoData = linkData.length === 0
if (!this.isLinkNoData) {
// 链路流量数据
const linkGridData = []
// 默认构造10*10矩阵根据行列键值进行填充最后再删除空行空列
linkInfo.forEach(link => {
if (link.direction === 'in') {
const outList = []
linkInfo.forEach(link1 => {
if (link1.direction === 'out') {
outList.push({ linkId: link1.linkId, noData: true })
}
})
linkGridData.push({ linkId: link.linkId, out: outList })
}
})
2023-03-16 19:07:37 +08:00
linkData.forEach(d => {
2023-08-29 16:24:02 +08:00
const inLink = linkInfo.find(l => l.originalLinkId === d.inLinkId)
const outLink = linkInfo.find(l => l.originalLinkId === d.outLinkId)
if (inLink && outLink) {
2023-03-16 19:07:37 +08:00
// 上行使用情况计算
2023-08-29 16:24:02 +08:00
const outUsage = this.computeUsage(d.outBitsRate, outLink.bandwidth)
2023-03-16 19:07:37 +08:00
// 下行使用情况计算
2023-08-29 16:24:02 +08:00
const inUsage = this.computeUsage(d.inBitsRate, inLink.bandwidth)
2023-03-16 19:07:37 +08:00
// 宽带使用超过90%,赋红点
2022-11-21 17:31:30 +08:00
2023-08-29 16:24:02 +08:00
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
2023-03-16 19:07:37 +08:00
// 计算npm分数
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
2023-03-16 19:07:37 +08:00
d.scoreLow3 = d.score < 3 || d.score === '-'
const xAxis = inLink.linkId.split('Hundredgige').pop() - 1
const yAxis = outLink.linkId.split('Hundredgige').pop() - 1
linkGridData[xAxis].out[yAxis] = {
noData: false,
linkId: outLink.linkId,
outUsage: outUsage,
inUsage: inUsage,
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
totalBitsRate: d.totalBitsRate,
...d
}
2022-09-15 15:51:00 +08:00
}
2023-03-16 19:07:37 +08:00
})
// 一行如果无数据则删除该行默认10*10矩阵
const rowIndex1 = 0
this.handleXRowNoData(linkGridData, rowIndex1)
// 一列如果无数据则删除该列默认10*10矩阵
const rowIndex = 0
this.handleYRowNoData(linkGridData, rowIndex)
this.isLinkNoData = linkGridData.length === 0
2023-03-16 19:07:37 +08:00
this.linkGridData = linkGridData
}
} else {
this.isLinkNoData = true
2023-03-16 19:07:37 +08:00
this.isLinkShowError = true
2023-03-22 10:20:22 +08:00
this.linkErrorMsg = this.errorMsgHandler(res[0])
}
2022-11-21 17:31:30 +08:00
2023-08-25 16:23:18 +08:00
if (response[1].status === 200) {
2023-03-16 19:07:37 +08:00
this.isNextShowError = false
2022-11-21 17:31:30 +08:00
2023-03-16 19:07:37 +08:00
// 链路下一跳信息
const nextLinkData = res[1].data.result
// 接口数据乱序,根据入方向排序,再根据同个入方向下的出方向进行排序
nextLinkData.sort((a, b) => {
2023-08-29 16:24:02 +08:00
if (a.inLinkDirection !== b.inLinkDirection) {
return a.inLinkDirection.localeCompare(b.inLinkDirection, 'zh')
2023-03-16 19:07:37 +08:00
}
2023-08-29 16:24:02 +08:00
return a.outLinkDirection.localeCompare(b.outLinkDirection, 'zh')
2023-03-16 19:07:37 +08:00
})
2022-11-21 17:31:30 +08:00
2023-03-16 19:07:37 +08:00
this.isNextNoData = nextLinkData.length === 0
if (!this.isNextNoData) {
// 链路下一跳数据
let nextGridData = []
const nextGridTemplate = [
{ linkId: 'Hundredgige2', nextHop: '太原', out: [] },
{ linkId: 'Hundredgige1', nextHop: '西安', out: [] },
{ linkId: 'Hundredgige4', nextHop: '西宁', out: [] }
]
nextGridData = JSON.parse(JSON.stringify(nextGridTemplate))
nextGridData.forEach(link => {
link.out = JSON.parse(JSON.stringify(nextGridTemplate))
link.out.forEach(link1 => {
link1.noData = true
link1.coordinate = `${link.linkId}-${link1.linkId}`
delete link1.out
})
})
2023-03-16 19:07:37 +08:00
nextLinkData.forEach(d => {
2023-08-29 16:24:02 +08:00
const inLink = linkInfo.find(l => l.nextHop === d.inLinkDirection && l.direction === 'in')
const outLink = linkInfo.find(l => l.nextHop === d.outLinkDirection && l.direction === 'out')
2023-08-29 16:24:02 +08:00
if (inLink && outLink) {
// const data = nextGridData.find(g => g.linkId === inLink.linkId)
2023-08-29 16:24:02 +08:00
let outBandwidth = 0
let inBandwidth = 0
2023-03-16 19:07:37 +08:00
linkInfo.forEach((item) => {
2023-08-29 16:24:02 +08:00
if (item.nextHop === d.outLinkDirection && item.direction === 'out') {
outBandwidth += item.bandwidth
2023-03-16 19:07:37 +08:00
}
2023-08-29 16:24:02 +08:00
if (item.nextHop === d.inLinkDirection && item.direction === 'in') {
inBandwidth += item.bandwidth
2023-03-16 19:07:37 +08:00
}
})
2023-03-16 19:07:37 +08:00
// 上行使用情况计算
2023-08-29 16:24:02 +08:00
const outUsage = this.computeUsage(d.outBitsRate, outBandwidth)
2023-03-16 19:07:37 +08:00
// 下行使用情况计算
2023-08-29 16:24:02 +08:00
const inUsage = this.computeUsage(d.inBitsRate, inBandwidth)
2023-03-16 19:07:37 +08:00
// 宽带使用超过90%,赋红点
2022-11-21 17:31:30 +08:00
2023-08-29 16:24:02 +08:00
d.usageMore90 = outUsage >= 0.9 || inUsage >= 0.9
2023-03-16 19:07:37 +08:00
// 计算npm分数
// 分数低于3分赋红点
d.score = this.localComputeScore(d)
2022-11-21 17:31:30 +08:00
2023-03-16 19:07:37 +08:00
d.scoreLow3 = d.score < 3 || d.score === '-'
const xAxis = inLink.linkId
const yAxis = outLink.linkId
nextGridData.forEach((link, index) => {
link.out.forEach((link1, index1) => {
if (link1.coordinate === (xAxis + '-' + yAxis)) {
nextGridData[index].out[index1] = {
coordinate: link1.coordinate,
noData: false,
linkId: outLink.linkId,
nextHop: outLink.nextHop,
outUsage: outUsage,
inUsage: inUsage,
popoverWidth: this.computeWidth(outUsage, inUsage, 'popover'),
valueWidth: this.computeWidth(outUsage, inUsage, 'value'),
totalBitsRate: d.totalBitsRate,
...d
}
}
})
})
}
})
// 一行如果无数据则删除该行默认3*3矩阵
const rowIndex1 = 0
this.handleXRowNoData(nextGridData, rowIndex1)
// 一列如果无数据则删除该列默认3*3矩阵
const rowIndex = 0
this.handleYRowNoData(nextGridData, rowIndex)
this.isNextNoData = nextGridData.length === 0
2023-03-16 19:07:37 +08:00
this.nextGridData = nextGridData
}
} else {
this.isNextNoData = true
2023-03-16 19:07:37 +08:00
this.isNextShowError = true
2023-03-22 10:20:22 +08:00
this.nextErrorMsg = this.errorMsgHandler(res[1])
}
2022-09-15 15:51:00 +08:00
}
}).finally(() => {
this.toggleLoading(false)
2022-09-15 15:51:00 +08:00
})
},
/**
* 计算上下行使用占比
*/
computeUsage (e, bandwidth) {
let usage = e / bandwidth
if (usage >= 1) {
usage = 1
}
return usage
},
/**
* 本地计算npm分数
*/
2022-11-21 17:31:30 +08:00
localComputeScore (data) {
let score = 0
2022-11-01 14:13:47 +08:00
const dataScore = {
establishLatencyMs: _.get(data, 'establishLatencyMs', null),
httpResponseLatency: _.get(data, 'httpResponseLatency', null),
sslConLatency: _.get(data, 'sslConLatency', null),
tcpLostlenPercent: _.get(data, 'tcpLostlenPercent', null),
pktRetransPercent: _.get(data, 'pktRetransPercent', null)
}
2022-11-01 14:13:47 +08:00
score = computeScore(dataScore)
return score
},
/**
* 计算popover弹窗和右侧数据模块的宽度
* 弹窗最小宽度为360px右侧数据最小宽度为75px右侧数据每大一位popover弹窗宽度增加7px
*/
2023-08-29 16:24:02 +08:00
computeWidth (out, _in, flag) {
let width = 0
let length = 0
2023-08-29 16:24:02 +08:00
let outUsage = ''
let inUsage = ''
2023-08-29 16:24:02 +08:00
if (out < 0.0001 && out !== 0) {
outUsage = '<0.01%'
} else {
2023-08-29 16:24:02 +08:00
outUsage = JSON.stringify(parseFloat((out * 100).toFixed(2)))
}
2023-08-29 16:24:02 +08:00
if (_in < 0.0001 && _in !== 0) {
inUsage = '<0.01%'
} else {
2023-08-29 16:24:02 +08:00
inUsage = JSON.stringify(parseFloat((_in * 100).toFixed(2)))
}
2023-08-29 16:24:02 +08:00
length = outUsage.length + inUsage.length - 1
if (flag === 'popover') {
width = 360 + length * 7
} else {
width = 75 + length * 7
}
return width
},
/**
* 删除重复行
* @param data
* @param index
*/
handleXRowNoData (data, index) {
if (data) {
const item = data[index]
let tempList = []
if (item) {
tempList = item.out.filter(l => l.noData)
// 如果该行数据都为空,则删除该行
if (tempList.length === item.out.length) {
data.splice(index, 1)
this.handleXRowNoData(data, index)
} else if (index < (data.length - 2)) {
index = index + 1
this.handleXRowNoData(data, index)
}
}
}
},
/**
* 删除重复列
* @param data
* @param index
*/
handleYRowNoData (data, index) {
const rowList = []
if (data) {
data.forEach(item => {
if (item.out[index]) {
if (item.out[index].noData) {
rowList.push(item.out[index].noData)
}
}
})
if (rowList.length === data.length) {
data.forEach(item => {
item.out.splice(index, 1)
})
this.handleYRowNoData(data, index)
} else if (index < (data[0].out.length - 1)) {
this.handleYRowNoData(data, index + 1)
}
}
2022-09-15 15:51:00 +08:00
}
}
2022-09-10 23:13:42 +08:00
}
</script>