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/LinkBlock.vue

393 lines
14 KiB
Vue
Raw Normal View History

2022-09-10 23:13:42 +08:00
<template>
<div class="link-blocks">
<div class="block-list" style="position: relative">
2022-11-21 17:31:30 +08:00
<div class="block-list__title" v-if="!showError">{{ $t('linkMonitor.links') }}</div>
<!--无数据noData-->
<chart-no-data v-if="isNoData"></chart-no-data>
<div class="block-list__list" v-show="!isNoData">
2022-11-21 17:31:30 +08:00
<chart-error v-if="showError" :content="errorMsg1" />
<el-popover
2022-11-21 17:31:30 +08:00
v-else
placement="bottom"
trigger="hover"
popper-class="link-block__popper"
v-for="(item, index) in linkData"
:width="item.popoverWidth"
:key="index"
>
<template #reference>
2022-10-07 21:04:35 +08:00
<div class="block-list__block" :key="index" @click="drillLinkId(item)">
<span class="block-hex">
<span class="block-hex-in" :style="`background-color: ${item.color}`"></span>
</span>
</div>
</template>
<template #default>
<div class="popper-content">
2022-09-30 14:16:23 +08:00
<div class="popper-content__link-id">Link ID: {{ item.linkId }}</div>
<div class="popper-content__link-info">
2022-09-30 14:16:23 +08:00
<div class="info__label">{{ $t('linkMonitor.linkBlock.total') }}</div>
<div class="info__value" style="margin-left: 8px">
{{ unitConvert(item.totalBitsRate, unitTypes.bps).join(' ') }}
2022-09-30 14:16:23 +08:00
</div>
</div>
<div class="popper-content__link-info">
2022-09-30 14:16:23 +08:00
<div class="info__label">{{ $t('linkMonitor.linkBlock.bandwidthUsage') }}</div>
<div class="info__value" style="display: flex">
<div>
<svg class="icon item-popover-up" aria-hidden="true">
<use xlink:href="#cn-icon-egress"></use>
</svg>
{{ convertValue(item.egressUsage) }}
2022-09-30 14:16:23 +08:00
</div>
<div>
<svg class="icon item-popover-down" aria-hidden="true">
<use xlink:href="#cn-icon-ingress"></use>
</svg>
{{ convertValue(item.ingressUsage) }}
2022-09-30 14:16:23 +08:00
</div>
</div>
</div>
</div>
</template>
</el-popover>
</div>
</div>
2022-09-30 14:16:23 +08:00
2022-11-21 17:31:30 +08:00
<div class="block-list" >
<div class="block-list__title" v-if="!showError">{{ $t('linkMonitor.nextHopInternet') }}</div>
<chart-no-data v-if="isNoData"></chart-no-data>
<div class="block-list__list" v-show="!isNoData">
2022-11-21 17:31:30 +08:00
<chart-error v-if="showError" :content="errorMsg2" />
<el-popover
2022-11-21 17:31:30 +08:00
v-else
placement="bottom"
trigger="hover"
popper-class="link-block__popper"
2022-09-30 14:16:23 +08:00
v-for="(item, index) in nextHopData"
:width="item.popoverWidth"
:key="index"
>
<template #reference>
2022-10-07 21:04:35 +08:00
<div class="block-list__block" :key="index" @click="drillNextHop(item)">
<span class="block-hex">
<span class="block-hex-in" :style="`background-color: ${item.color}`"></span>
</span>
</div>
</template>
<template #default>
<div class="popper-content">
2022-10-11 20:10:04 +08:00
<div class="popper-content__link-id">Next-Hop Internet: {{ item.linkDirection }}</div>
<div class="popper-content__link-info">
2022-09-30 14:16:23 +08:00
<div class="info__label">{{ $t('linkMonitor.linkBlock.total') }}</div>
<div class="info__value" style="margin-left: 8px">
{{ unitConvert(item.totalBitsRate, unitTypes.bps).join(' ') }}
2022-09-30 14:16:23 +08:00
</div>
</div>
<div class="popper-content__link-info">
2022-09-30 14:16:23 +08:00
<div class="info__label">{{ $t('linkMonitor.linkBlock.bandwidthUsage') }}</div>
<div class="info__value" style="display: flex">
<div>
<svg class="icon item-popover-up" aria-hidden="true">
<use xlink:href="#cn-icon-egress"></use>
</svg>
{{ convertValue(item.egressUsage) }}
2022-09-30 14:16:23 +08:00
</div>
<div>
<svg class="icon item-popover-down" aria-hidden="true">
<use xlink:href="#cn-icon-ingress"></use>
</svg>
{{ convertValue(item.ingressUsage) }}
2022-09-30 14:16:23 +08:00
</div>
</div>
</div>
</div>
</template>
</el-popover>
</div>
</div>
2022-09-10 23:13:42 +08:00
</div>
</template>
<script>
import ChartNoData from '@/views/charts/charts/ChartNoData'
import chartMixin from '@/views/charts2/chart-mixin'
import { useRoute } from 'vue-router'
import { ref } from 'vue'
import { get } from '@/utils/http'
import { api } from '@/utils/api'
import { colorGradientCalculation } from '@/utils/tools'
import unitConvert from '@/utils/unit-convert'
import { drillDownPanelTypeMapping, storageKey, unitTypes } from '@/utils/constants'
2022-09-30 14:16:23 +08:00
import { getSecond } from '@/utils/date-util'
2022-11-21 17:31:30 +08:00
import ChartError from '@/components/common/Error'
2022-09-10 23:13:42 +08:00
export default {
name: 'LinkBlock',
mixins: [chartMixin],
components: {
2022-11-21 17:31:30 +08:00
ChartError,
2022-09-10 23:13:42 +08:00
ChartNoData
},
data () {
return {
isNoData: false,
2022-09-10 23:13:42 +08:00
unitTypes,
linkData: [],
2022-09-30 14:16:23 +08:00
nextHopData: [],
2022-11-21 17:31:30 +08:00
gradientColor: ['#FF005C', '#40537E'], // [start, end]
showError: false,
errorMsg1: '',
errorMsg2: ''
2022-09-10 23:13:42 +08:00
}
},
setup () {
const { query } = useRoute()
const tab = ref(query.blockTab || 0)
return {
tab
}
},
2022-09-30 14:16:23 +08:00
watch: {
timeFilter: {
2022-11-29 17:21:01 +08:00
handler () {
2022-09-30 14:16:23 +08:00
this.init()
}
}
},
2022-09-10 23:13:42 +08:00
mounted () {
this.init()
},
methods: {
unitConvert,
init () {
this.toggleLoading(true)
2022-09-30 14:16:23 +08:00
// 链路基本信息
2022-11-29 17:21:01 +08:00
let linkInfo = null
linkInfo = localStorage.getItem(storageKey.linkInfo)
2022-09-30 14:16:23 +08:00
linkInfo = JSON.parse(linkInfo)
const params = {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime)
}
2022-10-07 21:04:35 +08:00
const dataRequest = get(api.linkMonitor.analysis, params)
2022-10-11 20:10:04 +08:00
const nextHopRequest = get(api.linkMonitor.nextHopAnalysis, params)
2022-09-30 14:16:23 +08:00
Promise.all([dataRequest, nextHopRequest]).then(res => {
if (res[0].code === 200 && res[1].code === 200) {
2022-11-21 17:31:30 +08:00
this.showError = false
2022-10-07 21:04:35 +08:00
const linkData = res[0].data.result
2022-09-30 14:16:23 +08:00
const nextHopData = res[1].data.result
2022-10-07 21:04:35 +08:00
this.isNoData = linkData.length === 0 && nextHopData.length === 0
2022-09-10 23:13:42 +08:00
if (this.isNoData) {
return
}
2022-10-07 21:04:35 +08:00
const data = []
linkData.forEach(d => {
const info = linkInfo.find(i => i.originalLinkId === d.linkId)
2022-10-07 21:04:35 +08:00
if (info) {
const hit = data.find(d => d.linkId === info.linkId)
if (hit) {
hit.egressBitsRate += d.egressBitsRate
hit.ingressBitsRate += d.ingressBitsRate
2022-10-07 21:04:35 +08:00
if (info.direction === 'egress') {
hit.egressBandwidth = info.bandwidth
hit.egressLinkId = d.linkId
} else if (info.direction === 'ingress') {
hit.ingressBandwidth = info.bandwidth
hit.ingressLinkId = d.linkId
}
} else {
const hit = {
linkId: info.linkId,
egressBitsRate: d.egressBitsRate,
ingressBitsRate: d.ingressBitsRate
2022-10-07 21:04:35 +08:00
}
if (info.direction === 'egress') {
hit.egressBandwidth = info.bandwidth
hit.egressLinkId = d.linkId
} else if (info.direction === 'ingress') {
hit.ingressBandwidth = info.bandwidth
hit.ingressLinkId = d.linkId
}
data.push(hit)
}
}
})
2022-09-30 14:16:23 +08:00
data.forEach((item) => {
item.totalBitsRate = item.egressBitsRate + item.ingressBitsRate
2022-09-30 14:16:23 +08:00
})
const sorted = data.sort((a, b) => b.totalBitsRate - a.totalBitsRate)
2022-10-11 20:10:04 +08:00
const linkColors = colorGradientCalculation(this.gradientColor[0], this.gradientColor[1], sorted.map(s => s.totalBitsRate))
2022-09-10 23:13:42 +08:00
sorted.forEach((s, i) => {
2022-10-11 20:10:04 +08:00
s.color = linkColors[i]
s.egressUsage = this.computeUsage(s.egressBitsRate, s.egressBandwidth)
s.ingressUsage = this.computeUsage(s.ingressBitsRate, s.ingressBandwidth)
s.popoverWidth = this.computePopoverWidth(s.egressUsage, s.ingressUsage)
2022-09-10 23:13:42 +08:00
})
this.linkData = sorted
2022-09-30 14:16:23 +08:00
let directionArr = []
nextHopData.forEach((item) => {
if (item.egressLinkDirection !== '' && item.ingressLinkDirection !== '') {
directionArr.push(item.egressLinkDirection)
directionArr.push(item.ingressLinkDirection)
}
})
directionArr = [...new Set(directionArr)]
const newNextHopData = []
directionArr.forEach((item1) => {
const newObj = { egressBitsRate: 0, ingressBitsRate: 0, totalBitsRate: 0, linkDirection: item1 }
nextHopData.forEach((item2) => {
if (item1 === item2.egressLinkDirection) {
newObj.egressBitsRate += item2.egressBitsRate
newObj.totalBitsRate += item2.egressBitsRate
}
if (item1 === item2.ingressLinkDirection) {
newObj.ingressBitsRate += item2.ingressBitsRate
newObj.totalBitsRate += item2.ingressBitsRate
}
})
newNextHopData.push(newObj)
})
// 下一跳数据处理
const nextHopSorted = newNextHopData.sort((a, b) => b.totalBitsRate - a.totalBitsRate)
2022-10-11 20:10:04 +08:00
const nextHopColors = colorGradientCalculation(this.gradientColor[0], this.gradientColor[1], nextHopSorted.map(s => s.totalBitsRate))
2022-09-30 14:16:23 +08:00
nextHopSorted.forEach((s, i) => {
2022-10-11 20:10:04 +08:00
s.color = nextHopColors[i]
2022-09-30 14:16:23 +08:00
let sum = 0
linkInfo.forEach((item) => {
// todo 此处需注意不明确接口返回的方向字段名是拼音还是汉字后期可能会变动缓存中的nextHop
2022-09-30 14:16:23 +08:00
if (s.linkDirection === item.nextHop) {
sum += item.bandwidth
}
})
// 上行使用情况计算
const egressUsage = this.computeUsage(s.egressBitsRate, sum)
2022-09-30 14:16:23 +08:00
// 下行使用情况计算
const ingressUsage = this.computeUsage(s.ingressBitsRate, sum)
2022-09-30 14:16:23 +08:00
s.egressUsage = egressUsage
s.ingressUsage = ingressUsage
s.popoverWidth = this.computePopoverWidth(egressUsage, ingressUsage)
2022-09-30 14:16:23 +08:00
})
this.nextHopData = nextHopSorted
2022-09-10 23:13:42 +08:00
} else {
2022-11-21 17:31:30 +08:00
this.isNoData = false
this.showError = true
this.errorMsg1 = res[0].message
this.errorMsg2 = res[1].message
2022-09-10 23:13:42 +08:00
}
}).catch(e => {
console.error(e)
2022-11-21 17:31:30 +08:00
this.isNoData = false
this.showError = true
// todo 此处数据还待验证
this.errorMsg1 = e.message
this.errorMsg2 = e.message
2022-09-10 23:13:42 +08:00
}).finally(() => {
this.toggleLoading(false)
})
2022-09-30 14:16:23 +08:00
},
/**
* 计算上下行使用占比
*/
computeUsage (e, bandwidth) {
let usage = e / bandwidth
if (usage >= 1) {
usage = 1
}
return usage
2022-10-07 21:04:35 +08:00
},
/**
* 计算popover弹窗的宽度
* 最小宽度为252px百分比每大一位popover弹窗宽度增加7px
*/
computePopoverWidth (egress, ingress) {
let width = 252
let length = 0
// 将上下行乘100保留2位转换即10.00为5位100.00为6位popover弹窗宽度就增加7px
// 最小宽度为252px最少位数为上下行相加为8位
let egressUsage = ''
let ingressUsage = ''
if (egress < 0.0001 && egress !== 0) {
2022-10-17 09:56:56 +08:00
egressUsage = '< 0.01%'
} else {
egressUsage = JSON.stringify(parseFloat((egress * 100).toFixed(2)))
}
if (ingress < 0.0001 && ingress !== 0) {
2022-10-17 09:56:56 +08:00
ingressUsage = '< 0.01%'
} else {
ingressUsage = JSON.stringify(parseFloat((ingress * 100).toFixed(2)))
}
length = egressUsage.length + ingressUsage.length
if (length > 8) {
width = 252 + (length - 8) * 7
}
return width
},
2022-10-07 21:04:35 +08:00
drillLinkId (item) {
const queryCondition = `common_egress_link_id = ${item.egressLinkId} or common_ingress_link_id = ${item.ingressLinkId}`
2022-10-09 18:47:09 +08:00
this.$router.push({
query: {
...this.$route.query,
thirdPanel: drillDownPanelTypeMapping.linkMonitor,
thirdMenu: `Link ID: ${item.linkId}`,
panelName: `Link ID: ${item.linkId}`,
queryCondition,
t: +new Date()
}
2022-10-07 21:04:35 +08:00
})
},
drillNextHop (item) {
const queryCondition = `egress_link_direction = '${item.linkDirection}' or ingress_link_direction = '${item.linkDirection}'`
2022-10-09 18:47:09 +08:00
this.$router.push({
query: {
...this.$route.query,
thirdPanel: drillDownPanelTypeMapping.linkMonitor,
2022-10-11 20:10:04 +08:00
thirdMenu: `Next-Hop Internet: ${item.linkDirection}`,
panelName: `Next-Hop Internet: ${item.linkDirection}`,
2022-10-09 18:47:09 +08:00
queryCondition,
t: +new Date()
}
2022-10-07 21:04:35 +08:00
})
},
/**
* 对单位进行转换值小于0.0001的显示为<0.01%除此之外正常转换显示
* @param value
* @returns {string}
*/
convertValue (value) {
let newValue = null
if (value < 0.0001 && value !== 0) {
2022-10-17 09:56:56 +08:00
newValue = '< 0.01%'
} else {
newValue = unitConvert(value, unitTypes.percent).join('')
}
return newValue
2022-09-10 23:13:42 +08:00
}
2022-11-29 17:21:01 +08:00
},
beforeUnmount () {
this.unitConvert = null
2022-09-10 23:13:42 +08:00
}
}
</script>