CN-197 perf: 调整地图的tooltip

This commit is contained in:
chenjinsong
2021-10-11 19:12:52 +08:00
parent 747a7ecd7c
commit 14a8365e20
6 changed files with 87 additions and 80 deletions

View File

@@ -10,8 +10,8 @@
<div v-for="(item, index) in data" :key="index" class="table-below-box" :class="{'table-below-box--inactivated': !item.active}" @click="toggleLegend(index)"> <div v-for="(item, index) in data" :key="index" class="table-below-box" :class="{'table-below-box--inactivated': !item.active}" @click="toggleLegend(index)">
<div class="table__below-color"><div :style="{backgroundColor: getChartColor(index)}"></div></div> <div class="table__below-color"><div :style="{backgroundColor: getChartColor(index)}"></div></div>
<div class="table__below-title" :title="item.legend">{{item.legend}}</div> <div class="table__below-title" :title="item.legend">{{item.legend}}</div>
<div class="table__below-statistics" :title="item.aggregation.avg">{{unitConvert(item.aggregation.avg, chartInfo.params.unitType).join(' ')}}</div> <div class="table__below-statistics" :title="item.aggregation.avg">{{valueToRangeValue(item.aggregation.avg, chartInfo.params.unitType).join(' ')}}</div>
<div class="table__below-statistics" :title="item.aggregation.max">{{unitConvert(item.aggregation.max, chartInfo.params.unitType).join(' ')}}</div> <div class="table__below-statistics" :title="item.aggregation.max">{{valueToRangeValue(item.aggregation.max, chartInfo.params.unitType).join(' ')}}</div>
</div> </div>
</div> </div>
</div> </div>
@@ -20,7 +20,7 @@
<script> <script>
import { getChartColor } from '@/components/charts/chart-options' import { getChartColor } from '@/components/charts/chart-options'
import unitConvert from '@/utils/unit-convert' import unitConvert, { valueToRangeValue } from '@/utils/unit-convert'
export default { export default {
name: 'StatisticsLegend', name: 'StatisticsLegend',
props: { props: {
@@ -35,7 +35,8 @@ export default {
setup () { setup () {
return { return {
getChartColor, getChartColor,
unitConvert unitConvert,
valueToRangeValue
} }
} }
} }

View File

@@ -138,9 +138,6 @@ export default {
from: String, from: String,
pageObj: Object, pageObj: Object,
loading: Boolean loading: Boolean
},
components: {
}, },
data () { data () {
return { return {

View File

@@ -117,6 +117,9 @@
position: absolute; position: absolute;
top: 21px; top: 21px;
left: 82px; left: 82px;
overflow: hidden;
max-width: 200px;
text-overflow: ellipsis;
} }
} }
} }

View File

@@ -62,7 +62,7 @@ export function timeUnitFormatter (time, sourceUnit = 'ms', targetUnit, dot = 2)
} }
/* 单位转换,返回转换后的[value, unit] */ /* 单位转换,返回转换后的[value, unit] */
// unitType = time / number / byte // unitType = time / number / byte / percent
export default function unitConvert (value, unitType, sourceUnit, targetUnit, dot = 2) { export default function unitConvert (value, unitType, sourceUnit, targetUnit, dot = 2) {
if (unitType === unitTypes.string) { if (unitType === unitTypes.string) {
if (value) { if (value) {
@@ -111,3 +111,26 @@ export function getUnitType (column) {
return unitTypes.number return unitTypes.number
} }
} }
/* 单位转换,返回转换后的[value, unit]type=time时若value<1ms返回<1mstype=percent时若value<0.01%,返回<0.01% */
export function valueToRangeValue (value, unitType) {
const values = unitConvert(value, unitType)
if (values[0] || values[0] === 0) {
switch (unitType) {
case unitTypes.time: {
if (values[0] < 1) {
return ['<1', 'ms']
}
break
}
case unitTypes.percent: {
if (values[0] < 0.01) {
return ['<0.01', '']
}
break
}
default: break
}
}
return values
}

View File

@@ -247,7 +247,6 @@
<span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span> <span class="header__operation-btn"><i class="cn-icon el-icon-info"></i></span>
</template> </template>
</el-popover> </el-popover>
<span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
<div class="header__operation header__operation--table"> <div class="header__operation header__operation--table">
<el-select <el-select
size="mini" size="mini"
@@ -275,6 +274,7 @@
</template> </template>
</el-select> </el-select>
</div> </div>
<span class="header__operation-btn" @click="refresh"><i class="cn-icon cn-icon-refresh"></i></span>
<!-- <div class="header__operation header__operation&#45;&#45;table"> <!-- <div class="header__operation header__operation&#45;&#45;table">
<span class="option__button"><i class="cn-icon cn-icon-style"></i></span> <span class="option__button"><i class="cn-icon cn-icon-style"></i></span>
<div class="icon-group-divide"></div> <div class="icon-group-divide"></div>
@@ -510,7 +510,7 @@ import ChartMap from '@/components/charts/ChartMap'
import PieTable from '@/components/charts/PieTable' import PieTable from '@/components/charts/PieTable'
import StatisticsLegend from '@/components/charts/StatisticsLegend' import StatisticsLegend from '@/components/charts/StatisticsLegend'
import ChartTablePagination from '@/components/charts/ChartTablePagination' import ChartTablePagination from '@/components/charts/ChartTablePagination'
import unitConvert, { getUnitType } from '@/utils/unit-convert' import unitConvert, { getUnitType, valueToRangeValue } from '@/utils/unit-convert'
import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions, unitTypes } from '@/utils/constants' import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions, unitTypes } from '@/utils/constants'
import { get, post } from '@/utils/http' import { get, post } from '@/utils/http'
import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools' import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools'
@@ -762,57 +762,14 @@ export default {
} }
}) })
}, },
getTitle (r) { generateTooltipHTML () {
let title = '' return `
if (r.establishLatency || r.httpResponseLatency || r.sslConLatency) { <div style="padding-bottom: 10px;">
title += `: ${unitConvert(r.establishLatency || r.httpResponseLatency || r.sslConLatency, unitTypes.time).join(' ')}` <div style="color: #333; font-size: 16px; height: 30px; line-height: 30px;">{name}</div>
} <span style="color: #666; font-size: 14px; padding-right: 15px;">{labelText}</span>
if (r.sequenceGapLossPercent || r.pktRetransPercent) { <span style="color: #666; font-size: 14px;">{showValue}</span>
const d = unitConvert(r.sequenceGapLossPercent || r.pktRetransPercent, unitTypes.number) </div>
title += d[0] === '0.00' ? ': 0' : `: ${d.join(' ')} %` `
}
if (r.sessions) {
title += `\nSessions: ${unitConvert(r.sessions, unitTypes.number).join(' ')}`
}
if (r.packets) {
title += `\nPackets: ${unitConvert(r.packets, unitTypes.number).join(' ')}`
}
if (r.bytes) {
title += `\nBytes: ${unitConvert(r.bytes, unitTypes.byte).join(' ')}`
}
title = title || ': 0'
return title
},
getTitle2 (item, valueColumn) {
let title = ''
switch (valueColumn) {
case 'sessions': {
title = `\nSessions: ${unitConvert(item.value, unitTypes.number).join(' ')}`
break
}
case 'packets': {
title = `\nPackets: ${unitConvert(item.value, unitTypes.number).join(' ')}`
break
}
case 'bytes': {
title = `\nBytes: ${unitConvert(item.value, unitTypes.byte).join(' ')}`
break
}
case 'establishLatency':
case 'httpResponseLatency':
case 'sslConLatency': {
const result = unitConvert(item.value, unitTypes.time)
title = `: ${result[0] === 0 ? 0 : result.join(' ')}`
break
}
case 'sequenceGapLossPercent':
case 'pktRetransPercent': {
title = `: ${unitConvert(item.value, unitTypes.number).join(' ')}`
break
}
default: break
}
return title
}, },
changeTab (tab) { changeTab (tab) {
this.activeTab = tab.paneName this.activeTab = tab.paneName
@@ -879,7 +836,6 @@ export default {
circle.fillOpacity = 0.7 circle.fillOpacity = 0.7
circle.nonScaling = true circle.nonScaling = true
circle.tooltipText = '{title}'
const radiusHeat = imageSeries.heatRules.push({ const radiusHeat = imageSeries.heatRules.push({
target: circle, target: circle,
property: 'radius', property: 'radius',
@@ -900,14 +856,12 @@ export default {
pointData.push({ pointData.push({
...d, ...d,
latitude: parseFloat(d.serverLatitude), latitude: parseFloat(d.serverLatitude),
longitude: parseFloat(d.serverLongitude), longitude: parseFloat(d.serverLongitude)
title: this.getTitle(d)
}) })
pointData.push({ pointData.push({
...d, ...d,
latitude: parseFloat(d.clientLatitude), latitude: parseFloat(d.clientLatitude),
longitude: parseFloat(d.clientLongitude), longitude: parseFloat(d.clientLongitude)
title: this.getTitle(d)
}) })
}) })
imageSeries.data = pointData imageSeries.data = pointData
@@ -915,22 +869,23 @@ export default {
const sumData = [] const sumData = []
data.forEach(r => { data.forEach(r => {
const hit = sumData.find(s => s.id === r.serverId) const hit = sumData.find(s => s.id === r.serverId)
const value = Number(r.establishLatency || r.httpResponseLatency || r.sslConLatency || r.sequenceGapLossPercent || r.pktRetransPercent || r.sessions) || 0 const { key, labelText } = this.getDataKey(r)
const value = Number(r[key]) || 0
if (hit) { if (hit) {
hit.value += value hit.value += value
} else { } else {
sumData.push({ sumData.push({
id: r.serverId, id: r.serverId,
key,
labelText,
value value
}) })
} }
}) })
const seriesData = sumData.map(r => { const seriesData = sumData.map(r => ({
return { ...r,
...r, showValue: (r.value || r.value === 0) ? valueToRangeValue(r.value, chartParams.unitType).join(' ') : ''
title: this.getTitle2(r, chartParams.valueColumn) }))
}
})
polygonSeries.data = [...seriesData] polygonSeries.data = [...seriesData]
const sorted = seriesData.sort((a, b) => b.value - a.value) const sorted = seriesData.sort((a, b) => b.value - a.value)
const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0 // 数据全为0的情况legend只显示1个颜色 const allZero = this.$_.isEmpty(sorted) || Number(sorted[0].value) === 0 // 数据全为0的情况legend只显示1个颜色
@@ -965,7 +920,9 @@ export default {
}) })
const polygonTemplate = polygonSeries.mapPolygons.template const polygonTemplate = polygonSeries.mapPolygons.template
polygonTemplate.tooltipText = '{name}{title}' polygonTemplate.tooltipHTML = this.generateTooltipHTML()
polygonSeries.tooltip.getFillFromObject = false
polygonSeries.tooltip.background.fill = am4Core.color('#FFFFFF')
polygonTemplate.nonScalingStroke = true polygonTemplate.nonScalingStroke = true
polygonTemplate.strokeWidth = 0.5 polygonTemplate.strokeWidth = 0.5
polygonTemplate.fill = am4Core.color('rgba(176,196,222,.5)') polygonTemplate.fill = am4Core.color('rgba(176,196,222,.5)')
@@ -989,6 +946,30 @@ export default {
refresh () { refresh () {
this.initChart() this.initChart()
}, },
getDataKey (r) {
let key = ''
let labelText = ''
if (r.establishLatency || r.establishLatency === 0) {
key = 'establishLatency'
labelText = this.$t('networkAppPerformance.tripTime')
} else if (r.httpResponseLatency || r.httpResponseLatency === 0) {
key = 'httpResponseLatency'
labelText = this.$t('networkAppPerformance.httpResponse')
} else if (r.sslConLatency || r.sslConLatency === 0) {
key = 'sslConLatency'
labelText = this.$t('networkAppPerformance.sslResponse')
} else if (r.sequenceGapLossPercent || r.sequenceGapLossPercent === 0) {
key = 'sequenceGapLossPercent'
labelText = this.$t('networkAppPerformance.packetlossRate')
} else if (r.pktRetransPercent || r.pktRetransPercent === 0) {
key = 'pktRetransPercent'
labelText = this.$t('networkAppPerformance.retransmissionRate')
} else if (r.sessions || r.sessions === 0) {
key = 'sessions'
labelText = this.$t('overall.sessions')
}
return { key, labelText }
},
getTableTitle (data) { getTableTitle (data) {
if (data.length > 0) { if (data.length > 0) {
const dataColumns = Object.keys(data[0]) // 返回数据的字段 const dataColumns = Object.keys(data[0]) // 返回数据的字段

View File

@@ -127,12 +127,14 @@ export default {
const params = { from: this.from, q: doubleQuotationToSingle(this.searchContent) } const params = { from: this.from, q: doubleQuotationToSingle(this.searchContent) }
this.loading = true this.loading = true
try { try {
this.listData = (await getEntityList({ ...this.pageObjRight, ...params })).map(d => ({ this.listData = (await getEntityList({ ...this.pageObjRight, ...params })).map(d => {
...d, return {
id: window.btoa(d.ip || d.domainName || d.appName), ...d,
latestSent: null, id: window.btoa(unescape(encodeURIComponent(d.ip || d.domainName || d.appName))),
latestReceived: null latestSent: null,
})) latestReceived: null
}
})
this.pageObjRight.total = await getEntityCount(params) this.pageObjRight.total = await getEntityCount(params)
const { topFilterData, bottomFilterData } = await this.queryFilterData(params) const { topFilterData, bottomFilterData } = await this.queryFilterData(params)
this.topFilterData = topFilterData this.topFilterData = topFilterData