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/entityExplorer/entityList/entityListMixin.js
2024-03-25 14:16:41 +08:00

369 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import _ from 'lodash'
import axios from 'axios'
import { api } from '@/utils/api'
import * as echarts from 'echarts'
import { entityListLineOption } from '@/views/charts/charts/chart-options'
import { riskLevelMapping, unitTypes } from '@/utils/constants'
import { getSecond } from '@/utils/date-util'
import { valueToRangeValue } from '@/utils/unit-convert'
import { shallowRef } from 'vue'
import { computeScore } from '@/utils/tools'
import i18n from '@/i18n'
export default {
props: {
entity: Object,
timeFilter: Object,
listMode: String
},
data () {
return {
entityData: {},
trafficUrl: '',
chartOption: null,
unitTypes,
valueToRangeValue,
echartsArray: [],
loadingNetworkQuality: false,
score: '-', // 网络质量评分
scoreUrl: '', // 网络质量评分url
eventNum: 0, // 性能事件和安全事件数量之和
loadingEvent: false, // event的loading
performanceEventUrl: '', // 性能事件接口url
securityEventUrl: '', // 安全事件接口url
performanceScoreData: {},
scoreDataState: false
}
},
computed: {
iconClass () {
let className
switch (this.entityData.entityType) {
case ('ip'): {
className = 'cn-icon cn-icon-ip2'
break
}
case ('domain'): {
className = 'cn-icon cn-icon-domain2'
break
}
case ('app'): {
className = 'cn-icon cn-icon-app2'
break
}
case ('subscriber_id'): {
className = 'cn-icon cn-icon-pedestrian'
break
}
default: break
}
return className
},
entityType () {
return this.entity.entityValue
},
entityName () {
return this.entity.entityValue
},
appRisk () {
return function (level) {
const m = riskLevelMapping.find(mapping => {
return mapping.value == level
})
return (m && m.name) || level
}
},
queryParams () {
let params
const now = window.$dayJs.tz().valueOf()
// eslint-disable-next-line prefer-const
params = {
startTime: this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : Math.floor(now / 1000 - 3600),
endTime: this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : Math.floor(now / 1000),
resource: this.entityData.entityValue
}
return params
},
scoreBaseState () {
return this.$store.getters.scoreBaseReady
},
scoreDot () {
const dots = []
if (this.score === '-') {
for (let i = 0; i < 6; i++) {
dots.push({
class: 'score-dot'
})
}
} else {
for (let i = 0; i < 6; i++) {
if (i < this.score) {
dots.push({
class: `score-dot ${handleClass(this.score)}`
})
} else {
dots.push({
class: 'score-dot'
})
}
}
}
return dots
function handleClass (score) {
if (score <= 2) {
return 'score-dot--red'
} else if (score <= 4) {
return 'score-dot--yellow'
} else if (score <= 6) {
return 'score-dot--green'
}
return ''
}
}
},
methods: {
showDetail () {
const { href } = this.$router.resolve({
path: '/entity/detail',
query: {
entityType: this.entityData.entityType,
entityName: this.entityData.entityValue,
range: this.timeFilter.dateRangeValue
}
})
window.open(href, '_blank')
},
showGraph () {
const { href } = this.$router.resolve({
path: '/entity/graph',
query: {
entityType: this.entityData.entityType,
entityName: this.entityData.entityValue
}
})
window.open(href, '_blank')
},
getQueryParams (dateRangeValue) {
if (dateRangeValue) {
// range取 config.js 中配置的值
const endTime = window.$dayJs.tz().valueOf()
const startTime = endTime - dateRangeValue * 60 * 1000
return {
startTime: getSecond(startTime),
endTime: getSecond(endTime),
resource: this.entityType
}
} else {
return {
startTime: getSecond(this.timeFilter.startTime),
endTime: getSecond(this.timeFilter.endTime),
resource: this.entityType
}
}
},
queryEntityDetailTraffic () {
this.loading = true
axios.get(this.trafficUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => {
if (response.status === 200 && response.data.data.result && response.data.data.result.length > 0) {
let sentSeries
let receivedSeries
response.data.data.result.forEach(t => {
if (t.legend === 'rate') {
this.entityData.max = t.aggregation.max
this.entityData.avg = t.aggregation.avg
this.entityData.p50 = t.aggregation.p50
this.entityData.p90 = t.aggregation.p90
} else if (t.legend === 'sentRate') {
this.entityData.bytesSentRate = t.aggregation.avg
sentSeries = {
name: i18n.global.t('entities.sentThroughput'),
type: 'line',
legendHoverLink: false,
itemStyle: {
lineStyle: {
width: 1
}
},
color: '#69b072',
data: _.dropRight(t.values, 2).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.bps]),
showSymbol: false
}
} else if (t.legend === 'receivedRate') {
this.entityData.bytesReceivedRate = t.aggregation.avg
receivedSeries = {
name: i18n.global.t('entities.receivedThroughput'),
type: 'line',
legendHoverLink: false,
itemStyle: {
lineStyle: {
width: 1
}
},
color: '#7899c6',
data: t.values.map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.bps]),
showSymbol: false
}
}
})
if (this.listMode === 'block') {
const chart = echarts.init(document.getElementById(`entityListChart${this.entityName}${this.listMode}`))
this.echartsArray.push(shallowRef(chart))
chart.setOption({
...this.chartOption,
series: [sentSeries, receivedSeries]
})
} else if (this.listMode === 'list') {
const sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}${this.listMode}`))
const receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}${this.listMode}`))
this.echartsArray.push(shallowRef(sentChart), shallowRef(receivedChart))
sentChart.setOption({
...this.chartOption,
series: [sentSeries]
})
receivedChart.setOption({
...this.chartOption,
series: [receivedSeries]
})
}
this.loading = false
} else {
this.loading = false
}
}).finally(() => {
setTimeout(() => {
try {
this.$nextTick(() => {
this.sentChart && this.sentChart.resize()
this.receivedChart && this.receivedChart.resize()
})
} catch (e) {}
}, 250)
})
},
resize () {
this.echartsArray.forEach(item => { item.value.resize() })
},
initUrl () {
if (this.entity.entityType) {
switch (this.entity.entityType) {
case 'ip': {
this.scoreUrl = api.entity.entityList.ipPerformance
this.trafficUrl = api.entity.entityList.ipThroughput
this.securityEventUrl = api.entity.entityList.ipSecurity
this.performanceEventUrl = api.entity.entityList.ipEventPerformance
break
}
case 'domain': {
this.scoreUrl = api.entity.entityList.domainPerformance
this.trafficUrl = api.entity.entityList.domainThroughput
this.securityEventUrl = api.entity.entityList.domainSecurity
this.performanceEventUrl = api.entity.entityList.domainEventPerformance
break
}
case 'app': {
this.scoreUrl = api.entity.entityList.appPerformance
this.trafficUrl = api.entity.entityList.appThroughput
this.securityEventUrl = api.entity.entityList.appSecurity
this.performanceEventUrl = api.entity.entityList.appEventPerformance
break
}
case 'subscriber_id': {
this.trafficUrl = api.entity.entityList.subscriberThroughput
break
}
default:
break
}
}
},
/** 获取网络评分 */
queryNetworkQuantity () {
this.loadingNetworkQuality = true
this.performanceScoreData = {}
this.scoreDataState = false
axios.get(this.scoreUrl, { params: this.getQueryParams(DEFAULT_TIME_FILTER_RANGE.entity.trafficLine) }).then(response => {
if (response.status === 200) {
this.performanceScoreData = {
establishLatencyMs: _.get(response, 'data.data.result.establishLatencyMsAvg', null),
httpResponseLatency: _.get(response, 'data.data.result.httpResponseLatencyAvg', null),
sslConLatency: _.get(response, 'data.data.result.sslConLatencyAvg', null),
tcpLostlenPercent: _.get(response, 'data.data.result.tcpLostlenPercentAvg', null),
pktRetransPercent: _.get(response, 'data.data.result.pktRetransPercentAvg', null)
}
}
}).finally(() => {
this.loadingNetworkQuality = false
this.scoreDataState = true
})
},
/** 获取事件数量 */
queryEventNum () {
this.loadingEvent = true
// const performance = axios.get(this.performanceEventUrl, { params: this.getQueryParams() })
// const security = axios.get(this.securityEventUrl, { params: this.getQueryParams() })
// performance接口修改暂时不能访问故只调用security的后续加上
this.eventNum = 0
const param = {
params: {
...this.getQueryParams(),
pageSize: -1
}
}
axios.get(this.securityEventUrl, param).then(res => {
if (res.status === 200) {
this.eventNum = res.data.data.result.length
}
}).finally(() => {
this.loadingEvent = false
})
// Promise.all([performance, security]).then(response => {
// this.eventNum = response[0].data.data.result.length + response[1].data.data.result.length
// }).catch(e => {
// this.eventNum = 0
// }).finally(() => {
// this.loadingEvent = false
// })
},
handleScoreData () {
this.score = computeScore(this.performanceScoreData, this.$store.getters.getScoreBase)
}
},
watch: {
entityData: {
deep: true,
handler (n) {
this.initUrl()
}
},
scoreBaseState (n) {
if (n && this.scoreDataState) {
this.handleScoreData()
}
},
scoreDataState (n) {
if (n && this.scoreBaseState) {
this.handleScoreData()
}
}
},
mounted () {
this.debounceFunc = this.$_.debounce(this.resize, 200)
window.addEventListener('resize', this.debounceFunc)
this.chartOption = _.cloneDeep(entityListLineOption)
this.entityData = { ...this.entityData, ...this.entity }
this.initUrl()
setTimeout(() => {
this.queryEntityDetailTraffic()
if (this.entity.entityType !== 'subscriber_id') {
this.queryNetworkQuantity()
this.queryEventNum()
}
})
},
beforeUnmount () {
window.removeEventListener('resize', this.debounceFunc)
}
}