CN-65 feat: 流量曲线图、饼图、其他内容

This commit is contained in:
chenjinsong
2021-07-20 18:58:55 +08:00
parent d37f5ec1d0
commit 05178b25be
11 changed files with 105 additions and 58 deletions

View File

@@ -6,17 +6,17 @@ const { VueLoaderPlugin } = require('vue-loader')
const libMode = process.env.LIBMODE const libMode = process.env.LIBMODE
const isFullMode = libMode === 'full' const isFullMode = libMode === 'full'
let externals = [ const externals = [
{ {
vue: { vue: {
root: 'Vue', root: 'Vue',
commonjs: 'vue', commonjs: 'vue',
commonjs2: 'vue', commonjs2: 'vue'
}, }
}, }
] ]
const plugins = [ const plugins = [
new VueLoaderPlugin(), new VueLoaderPlugin()
// new BundleAnalyzerPlugin(), // new BundleAnalyzerPlugin(),
] ]
@@ -50,20 +50,21 @@ const config = {
rules: [ rules: [
{ {
test: /\.vue$/, test: /\.vue$/,
use: 'vue-loader', use: 'vue-loader'
}, },
{ {
test: /\.(ts|js)x?$/, test: /\.(ts|js)x?$/,
exclude: /node_modules/, exclude: /node_modules/,
loader: 'babel-loader', loader: 'babel-loader'
}, }
], ]
}, },
resolve: { resolve: {
extensions: ['.ts', '.tsx', '.js', '.json'], extensions: ['.ts', '.tsx', '.js', '.json']
}, },
cache: true,
externals, externals,
plugins, plugins
} }
module.exports = config module.exports = config

View File

@@ -60,3 +60,7 @@ th *:first-letter,
height: 100%; height: 100%;
width: 100%; width: 100%;
} }
.el-table__empty-block {
width: 100% !important;
}

View File

@@ -45,7 +45,7 @@
</template> </template>
<script> <script>
import { shortFormatter } from '@/components/charts/chartFormatter' import { shortFormatter } from '@/components/charts/chart-formatter'
export default { export default {
name: 'ChartTable', name: 'ChartTable',
props: { props: {

View File

@@ -68,7 +68,7 @@
</template> </template>
<script> <script>
import { shortFormatter } from '@/components/charts/chartFormatter' import { shortFormatter } from '@/components/charts/chart-formatter'
import { get } from '@/utils/http' import { get } from '@/utils/http'
import { replaceUrlPlaceholder } from '@/utils/tools' import { replaceUrlPlaceholder } from '@/utils/tools'
@@ -188,7 +188,8 @@ export default {
startTime: parseInt(this.startTime / 1000), startTime: parseInt(this.startTime / 1000),
endTime: parseInt(this.endTime / 1000), endTime: parseInt(this.endTime / 1000),
order: this.order, order: this.order,
domain: row.domain domain: row.domain,
limit: 10
} }
get(replaceUrlPlaceholder(url, queryParams)).then(response2 => { get(replaceUrlPlaceholder(url, queryParams)).then(response2 => {
if (response2.code === 200) { if (response2.code === 200) {

View File

@@ -18,7 +18,7 @@
<script> <script>
import { getChartColor } from '@/components/charts/chart-options' import { getChartColor } from '@/components/charts/chart-options'
import { shortFormatter } from '@/components/charts/chartFormatter' import { shortFormatter } from '@/components/charts/chart-formatter'
export default { export default {
name: 'StatisticsLegend', name: 'StatisticsLegend',
props: { props: {

View File

@@ -0,0 +1,55 @@
const shortList = [' ', 'K', 'M', 'G', 'T', 'Quadrillion', 'Quintillion']
function asciiCompute (num, ascii, units, dot = 2) {
if (!num && num !== 0 && num !== '0') {
return ''
}
num = Number(num)
let carry = 0
if (num > 1) {
const log = Math.log(num) / Math.log(ascii)
carry = parseInt(log)
num = num / Math.pow(ascii, carry)
}
if (Number.isInteger(num)) {
return num + ' ' + units[carry]
} else {
return num.toFixed(dot) + ' ' + units[carry]
}
}
export function shortFormatter (value, index, dot = 2) {
return asciiCompute(value, 1000, shortList, dot)
}
/* 时间单位转换例如将ms转为h */
const timeStep = [ // 步进倍数以ms为基数
{ unit: 'ms', step: 1 },
{ unit: 's', step: 1000 },
{ unit: 'm', step: 60 },
{ unit: 'h', step: 60 },
{ unit: 'd', step: 24 }
]
export function timeUnitFormatter (time, sourceUnit = 'ms', targetUnit, dot = 2) {
let sourceIndex = -1
let targetIndex = -1
timeStep.forEach((t, i) => {
sourceUnit === t.unit && (sourceIndex = i)
targetUnit && targetUnit === t.unit && (targetIndex = i)
})
let multi = 1
let result = parseFloat(time)
if (targetIndex < 0) {
while (sourceIndex < timeStep.length - 1 && result > timeStep[sourceIndex + 1].step) {
sourceIndex++
multi = timeStep[sourceIndex].step
result /= multi
}
return [multi === 1 ? result : result.toFixed(dot), timeStep[sourceIndex].unit]
} else {
timeStep.forEach((s, i) => {
if (i <= targetIndex) {
multi *= s.step
}
})
result /= multi
return [result.toFixed(dot), targetUnit]
}
}

View File

@@ -4,7 +4,7 @@
* @description chart option和一些工具 * @description chart option和一些工具
*/ */
import { format } from 'echarts' import { format } from 'echarts'
import { shortFormatter, tooltipShortFormatter } from './chartFormatter' import { shortFormatter, timeUnitFormatter } from './chart-formatter'
import _ from 'lodash' import _ from 'lodash'
export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666', export const chartColor = ['#5370C6', '#90CC74', '#FAC858', '#EE6666',
'#73BFDE', '#3BA172', '#FC8452', '#9960B4', '#73BFDE', '#3BA172', '#FC8452', '#9960B4',
@@ -179,9 +179,7 @@ const lineStack = {
} }
const pieWithTable = { const pieWithTable = {
tooltip: { tooltip: {
appendToBody: true, appendToBody: true
trigger: 'item',
formatter: tooltipShortFormatter
}, },
color: chartColor, color: chartColor,
animation: false, animation: false,
@@ -194,10 +192,10 @@ const pieWithTable = {
itemWidth: 10, // 设置宽度 itemWidth: 10, // 设置宽度
itemHeight: 10, // 设置高度 itemHeight: 10, // 设置高度
itemGap: 20, itemGap: 20,
formatter: tooLongFormatter,
tooltip: { tooltip: {
show: true show: true
}, }
formatter: tooLongFormatter
}, },
series: [ series: [
{ {
@@ -209,6 +207,11 @@ const pieWithTable = {
label: { label: {
formatter: '{d}%' formatter: '{d}%'
}, },
tooltip: {
formatter: function (param, index, callback) {
return `${param.name}: ${shortFormatter(param.value)}`
}
},
emphasis: { emphasis: {
itemStyle: { itemStyle: {
shadowBlur: 10, shadowBlur: 10,

View File

@@ -74,8 +74,11 @@ export const allTableTitle = {
] ]
} }
export const legendMapping = { export const legendMapping = {
bytes_received_rate: 'Bytes Received Rate', bytes_received_rate: i18n.global.t('trafficSummary.throughputPerSecondC2s'),
bytes_sent_rate: 'Bytes Sent Rate', bytes_sent_rate: i18n.global.t('trafficSummary.throughputPerSecondS2c'),
bytes_rate: 'Bytes Rate', bytes_rate: i18n.global.t('trafficSummary.throughputPerSecond'),
session_rate: 'Session Rate' session_rate: i18n.global.t('trafficSummary.sessionsPerSecond'),
packets_rate: i18n.global.t('trafficSummary.packetsPerSecond'),
packets_received_rate: i18n.global.t('trafficSummary.packetsPerSecondC2s'),
packets_sent_rate: i18n.global.t('trafficSummary.packetsPerSecondS2c')
} }

View File

@@ -1,24 +0,0 @@
const shortList = [' ', 'K', 'M', 'G', 'T', 'Quadrillion', 'Quintillion']
function asciiCompute (num, ascii, units, dot = 2) {
if (!num && num !== 0 && num !== '0') {
return ''
}
num = Number(num)
let carry = 0
if (num > 1) {
const log = Math.log(num) / Math.log(ascii)
carry = parseInt(log)
num = num / Math.pow(ascii, carry)
}
if (Number.isInteger(num)) {
return num + ' ' + units[carry]
} else {
return num.toFixed(dot) + ' ' + units[carry]
}
}
export function shortFormatter (value, index, dot = 2) {
return asciiCompute(value, 1000, shortList, dot)
}
export function tooltipShortFormatter (obj, index, callback, dot = 2) {
return asciiCompute(obj.value, 1000, shortList, dot)
}

View File

@@ -17,7 +17,6 @@
:expand-on-click-node="false" :expand-on-click-node="false"
:lazy="i === 0" :lazy="i === 0"
highlight-current highlight-current
:show-checkbox="i === 1"
@node-click="nodeClick" @node-click="nodeClick"
> >
<template #default="{ node, data }"> <template #default="{ node, data }">

View File

@@ -83,8 +83,8 @@
> >
<template #title><span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span></template> <template #title><span :title="chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name">{{chartInfo.i18n ? $t(chartInfo.i18n) : chartInfo.name}}</span></template>
<template #data> <template #data>
<span>{{handleSingleValue(singleValue.value)}}</span> <span>{{handleSingleValue[0]}}</span>
<span v-if="chartInfo.params && chartInfo.params.unit" class="single-value__unit">{{chartInfo.params.unit}}</span> <span v-if="chartInfo.params && chartInfo.params.unit" class="single-value__unit">{{handleSingleValue[1]}}</span>
</template> </template>
</single-value> </single-value>
<!-- 表格 --> <!-- 表格 -->
@@ -149,7 +149,7 @@ import * as echarts from 'echarts'
import * as am4Core from '@amcharts/amcharts4/core' import * as am4Core from '@amcharts/amcharts4/core'
import * as am4Maps from '@amcharts/amcharts4/maps' import * as am4Maps from '@amcharts/amcharts4/maps'
import { shallowRef } from 'vue' import { shallowRef } from 'vue'
import { allTableTitle, legendMapping } from '@/components/charts/chartTableTitle' import { allTableTitle, legendMapping } from '@/components/charts/chart-table-title'
import { import {
isEcharts, isEcharts,
isSingleValue, isSingleValue,
@@ -174,7 +174,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 { shortFormatter } from '@/components/charts/chartFormatter' import { shortFormatter, timeUnitFormatter } from '@/components/charts/chart-formatter'
import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions } from '@/utils/constants' import { chartTableDefaultPageSize, chartTableTopOptions, storageKey, chartPieTableTopOptions } from '@/utils/constants'
import { get } from '@/utils/http' import { get } from '@/utils/http'
import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools' import { replaceUrlPlaceholder, getCapitalGeo, getGeoData, lineToSpace } from '@/utils/tools'
@@ -499,6 +499,7 @@ export default {
seriesIndex: 0, seriesIndex: 0,
dataIndex: i dataIndex: i
}) })
self.selectPieChartName = ''
self.loadPieTableData() self.loadPieTableData()
} else { } else {
if (d.name === params.name) { if (d.name === params.name) {
@@ -558,11 +559,15 @@ export default {
} }
}, },
handleSingleValue () { handleSingleValue () {
return function (value) { const value = this.singleValue.value
if (!Number(value) && Number(value) !== 0) { const unit = this.chartInfo.params.unit
return '-' if (!Number(value) && Number(value) !== 0) {
return '-'
} else {
if (unit && unit === 'ms') {
return Number(value) < 1 ? ['< 1', 'ms'] : timeUnitFormatter(value, null, 0)
} else { } else {
return Number(value) < 0.01 ? '< 0.01' : shortFormatter(value) return Number(value) < 0.01 ? ['< 0.01', ''] : [shortFormatter(value), '']
} }
} }
} }