diff --git a/src/assets/css/components/components/common/TimeRange/date-time-range.scss b/src/assets/css/components/components/common/TimeRange/date-time-range.scss index 6df8ded9..bad3efc7 100644 --- a/src/assets/css/components/components/common/TimeRange/date-time-range.scss +++ b/src/assets/css/components/components/common/TimeRange/date-time-range.scss @@ -206,6 +206,7 @@ } .my-date-picker { + z-index: 100004 !important; .el-popper__arrow { position: absolute; top: 20px !important; diff --git a/src/components/common/TimeRange/DateTimeRange.vue b/src/components/common/TimeRange/DateTimeRange.vue index 259f0b67..9898e4e0 100644 --- a/src/components/common/TimeRange/DateTimeRange.vue +++ b/src/components/common/TimeRange/DateTimeRange.vue @@ -14,7 +14,7 @@ - +
diff --git a/src/utils/api.js b/src/utils/api.js index aeece9e9..045e75f5 100644 --- a/src/utils/api.js +++ b/src/utils/api.js @@ -275,6 +275,9 @@ export const api = { domainNameResolutionAboutAppsOfDomain: apiVersion + '/entity/detail/domain/relate/apps', domainNameResolutionAboutIpsOfDomain: apiVersion + '/entity/detail/domain/relate/ips', domainNameResolutionAboutFQDNsOfDomain: apiVersion + '/entity/detail/domain/relate/fqdns', + // subscriber + subscriberKpi: apiVersion + '/entity/detail/traffic/overview/subscriber', + subscriberTopApp: apiVersion + '/entity/detail/subscriber/relate/apps', // 开放端口:ip、domain、app相关 openPortOfIp: apiVersion + '/entity/detail/ip/relate/ports', openPortOfDomain: apiVersion + '/entity/detail/domain/relate/ports', @@ -282,8 +285,8 @@ export const api = { basicInfo: apiVersion + '/entity/detail/basic', tags: apiVersion + '/entity/detail/kb/intelligence/tag', informationAggregation: apiVersion + '/entity/detail/kb/intelligence/list', - deviceInformation: apiVersion + '/entity/detail/subscribe/device', // 暂时写的值 - accountInformation: apiVersion + '/entity/detail/subscribe/account', // 暂时写的值 + deviceInformation: apiVersion + '/entity/detail/subscriber/device', // 暂时写的值 + accountInformation: apiVersion + '/entity/detail/subscriber/account', // 暂时写的值 locationTrack: apiVersion + '/entity/detail/subscribe/track', // 实体关系 entityGraph: { diff --git a/src/views/charts2/charts/entityDetail/EntityDetailSubscriberKpi.vue b/src/views/charts2/charts/entityDetail/EntityDetailSubscriberKpi.vue index db0ecebe..88d115f7 100644 --- a/src/views/charts2/charts/entityDetail/EntityDetailSubscriberKpi.vue +++ b/src/views/charts2/charts/entityDetail/EntityDetailSubscriberKpi.vue @@ -22,89 +22,86 @@
{{$t('subscriber.volume')}}
- - +
+ {{$_.get(kpiData, 'volume')[2]}} +
+
+ +
+
{{$t('subscriber.throughput')}}
- - +
{{$_.get(kpiData, 'throughput') ? unitConvert($_.get(kpiData, 'throughput')[0], unitTypes.bps).join(' ') : '-'}}
+
+
+ {{$_.get(kpiData, 'throughput')[2]}} +
+
+ {{$_.get(kpiData, 'throughput')[2]}} +
+
+ +
+
-
{{$t('subscriber.latency')}}
+
{{$t('subscriber.httpLatency')}}
- - +
+ {{$_.get(kpiData, 'httpLatency')[2]}} +
+
+ +
+
+
+ +
+
{{$t('subscriber.sslLatency')}}
+
+
{{$_.get(kpiData, 'sslLatency') ? unitConvert($_.get(kpiData, 'sslLatency')[0], unitTypes.time).join(' ') : '-'}}
+
+
+ {{$_.get(kpiData, 'sslLatency')[2]}} +
+
+ {{$_.get(kpiData, 'sslLatency')[2]}} +
+
+ +
+
{{$t('subscriber.packetLoss')}}
- - +
+ {{$_.get(kpiData, 'packetLoss')[2]}} +
+
+ +
+
@@ -163,11 +160,12 @@ export default { data () { return { kpiData: { + /* volume: [5300000000, 'up', '6%'], throughput: [600000, 'noChange', '6%'], httpLatency: [21, 'down', '6%'], sslLatency: [21, 'down', '6%'], - packetLoss: [0.0192, 'down', '2%'] + packetLoss: [0.0192, 'down', '2%']*/ }, unitConvert, unitTypes, @@ -187,32 +185,39 @@ export default { handleTrendData (curData, preData) { let trend = '' let trendPercent = '' - const totalDiff = curData - preData - const chainRatio = getChainRatio(curData, preData) - if (chainRatio !== '-') { - trendPercent = parseFloat(Math.abs(chainRatio) * 100).toFixed(2) - if (totalDiff > 0) { - trend = 'up' - if (trendPercent <= 500) { - trendPercent = trendPercent + '%' + curData = Number(curData) + preData = Number(preData) + if(curData === 0 && preData === 0) { + trend = 'noChange' + trendPercent = '' + } else if(curData && preData) { + const totalDiff = curData - preData + const chainRatio = getChainRatio(curData, preData) + if (chainRatio !== '-') { + trendPercent = parseFloat(Math.abs(chainRatio) * 100).toFixed(2) + if (totalDiff > 0) { + trend = 'up' + if (trendPercent <= 500) { + trendPercent = trendPercent + '%' + } else { + trendPercent = '>500%' + } + } else if (totalDiff < 0) { + trend = 'down' + if (trendPercent <= 500) { + trendPercent = trendPercent + '%' + } else { + trendPercent = '>500%' + } + } else if (totalDiff === 0) { + trend = 'noChange'// 横向图标 } else { - trendPercent = '>500%' + trend = '' } - } else if (totalDiff < 0) { - trend = 'down' - if (trendPercent <= 500) { - trendPercent = trendPercent + '%' - } else { - trendPercent = '>500%' + if (trendPercent === '0%') { + trend = 'noChange' + trendPercent = '' } - } else if (totalDiff === 0) { - trend = 'noChange'// 横向图标 - } else { - trend = '' - } - if (trendPercent === '0%') { - trend = 'noChange' - trendPercent = '' } } return [curData, trend, trendPercent] @@ -240,11 +245,11 @@ export default { this.showError = false if (!this.isNoData) { this.kpiData = { - volume: [data ? data.total_bytes : '', '', ''], - throughput: [data ? data.avg_bits_per_sec : '', '', ''], - httpLatency: [data ? data.avg_http_response_latency_ms : '', '', ''], - sslLatency: [data ? data.avg_ssl_handshake_latency_ms : '', '', ''], - packetLoss: [data ? data.tcp_lost_bytes_ratio : '', '', ''] + volume: [data ? data.total_bytes : null], + throughput: [data ? data.avg_bits_per_sec : null], + httpLatency: [data ? data.avg_http_response_latency_ms : null], + sslLatency: [data ? data.avg_ssl_handshake_latency_ms : null], + packetLoss: [data ? data.tcp_lost_bytes_ratio : null] } axios.get(api.entity.subscriberKpi, { params: preParams }).then(preCycleRes => { @@ -252,25 +257,25 @@ export default { if (preCycleRes.status === 200) { const data = preRes.data if (Object.keys(data).length > 0) { - const preVolume = data ? data.avg_bits_per_sec : '' - const preThroughput = data ? data.total_bytes : '' - const preHttpLatency = data ? data.avg_http_response_latency_ms : '' - const preSslLatency = data ? data.avg_ssl_handshake_latency_ms : '' - const prePacketLoss = data ? data.tcp_lost_bytes_ratio : '' + const preVolume = data ? data.avg_bits_per_sec : null + const preThroughput = data ? data.total_bytes : null + const preHttpLatency = data ? data.avg_http_response_latency_ms : null + const preSslLatency = data ? data.avg_ssl_handshake_latency_ms : null + const prePacketLoss = data ? data.tcp_lost_bytes_ratio : null - if (this.kpiData.volume[0] !== '' && preVolume !== '') { + if (this.kpiData.volume[0] !==null && preVolume !==null) { this.kpiData.volume = this.handleTrendData(this.kpiData.volume[0], preVolume) } - if (this.kpiData.throughput[0] !== '' && preThroughput !== '') { + if (this.kpiData.throughput[0] !==null && preThroughput !==null) { this.kpiData.throughput = this.handleTrendData(this.kpiData.throughput[0], preThroughput) } - if (this.kpiData.httpLatency[0] !== '' && preHttpLatency !== '') { + if (this.kpiData.httpLatency[0] !==null && preHttpLatency !==null) { this.kpiData.httpLatency = this.handleTrendData(this.kpiData.httpLatency[0], preHttpLatency) } - if (this.kpiData.sslLatency[0] !== '' && preSslLatency !== '') { + if (this.kpiData.sslLatency[0] !==null && preSslLatency !==null) { this.kpiData.sslLatency = this.handleTrendData(this.kpiData.sslLatency[0], preSslLatency) } - if (this.kpiData.packetLoss[0] !== '' && prePacketLoss !== '') { + if (this.kpiData.packetLoss[0] !==null && prePacketLoss !==null) { this.kpiData.packetLoss = this.handleTrendData(this.kpiData.packetLoss[0], prePacketLoss) } } diff --git a/src/views/charts2/charts/entityDetail/EntityDetailSubscriberTopApp.vue b/src/views/charts2/charts/entityDetail/EntityDetailSubscriberTopApp.vue index 69663c83..ba6d95ca 100644 --- a/src/views/charts2/charts/entityDetail/EntityDetailSubscriberTopApp.vue +++ b/src/views/charts2/charts/entityDetail/EntityDetailSubscriberTopApp.vue @@ -14,26 +14,26 @@
- +
-
+
{{++index}}
-
{{app.name}}
+
{{appData.app}}
-
{{app.up}}
+
{{appData.up ? unitConvert(appData.up, unitTypes.byte,null,null,1).join('') : '-'}}
-
{{app.down}}
+
{{appData.down ? unitConvert(appData.down, unitTypes.byte,null,null,1).join('') : '-'}}
-
+
@@ -48,7 +48,7 @@ import chartMixin from '@/views/charts2/chart-mixin' import ChartError from '@/components/common/Error' import unitConvert from '@/utils/unit-convert' import { unitTypes } from '@/utils/constants' -import { overwriteUrl, urlParamsHandler } from '@/utils/tools' +import { overwriteUrl, urlParamsHandler, reverseSortBy } from '@/utils/tools' import axios from 'axios' import { useRoute } from 'vue-router' import { getNowTime, getSecond } from '@/utils/date-util' @@ -93,52 +93,52 @@ export default { return { topAppData: [ { - name: 'Wetchat', + app: 'Wetchat', up: '1.2GB', down: '28MB' }, { - name: 'QQ', + app: 'QQ', up: '1.2GB', down: '28MB' }, { - name: 'Douyin', + app: 'Douyin', up: '1.2GB', down: '28MB' }, { - name: 'Weibo', + app: 'Weibo', up: '1.2GB', down: '28MB' }, { - name: 'Tecent', + app: 'Tecent', up: '1.2GB', down: '28MB' }, { - name: 'Kuaishou', + app: 'Kuaishou', up: '1.2GB', down: '28MB' }, { - name: 'Taobao', + app: 'Taobao', up: '1.2GB', down: '28MB' }, { - name: 'Jd', + app: 'Jd', up: '1.2GB', down: '28MB' }, { - name: 'Aiqiyi', + app: 'Aiqiyi', up: '1.2GB', down: '28MB' }, { - name: 'Baidu', + app: 'Baidu', up: '1.2GB', down: '28MB' } @@ -147,7 +147,9 @@ export default { unitTypes, isNoData: false, showError: false, - errorMsg: '' + errorMsg: '', + isSetHeight: false, + newHeight: '' } }, watch: { @@ -158,26 +160,33 @@ export default { } }, methods: { - init (val, show, active, n) { + init () { const params = { resource: this.entity.entityName, startTime: getSecond(this.timeFilter.startTime), endTime: getSecond(this.timeFilter.endTime) } - if (this.queryCondition) { - // params.q = this.queryCondition - } - this.toggleLoading(true) - axios.get(`${api.entity.throughput}/${this.entity.entityType}`, { params: params }).then(response => { + axios.get(api.entity.subscriberTopApp, { params: params }).then(response => { const res = response.data if (response.status === 200) { this.isNoData = res.data.result.length === 0 this.showError = false if (!this.isNoData) { - this.topAppData = res.data.result - this.initEchart() + const appDatas = res.data.result.map(item => { + const upData = item.outbound_byte ? item.outbound_byte : 0 + const downData = item.inbound_byte ? item.inbound_byte : 0 + return { + app: item.app, + up: upData, + down: downData, + appTotal: upData + downData + } + }) + + this.topAppData = appDatas.sort(reverseSortBy('appTotal')) + this.getTotalData() } } else { this.httpError(res) @@ -187,13 +196,177 @@ export default { this.httpError(e) }).finally(() => { this.toggleLoading(false) - // 无数据时的测试代码 - //this.isNoData = false - //this.initEchart() + // 无数据时的测试代码---------- + const response = { + status: 200, + data: { + msg: 'success', + code: 200, + data: { + result: [ + { + app: 'Wetchat', + inbound_byte: 9024, + inbound_pkt: 1024 + }, /* + { + "app": "QQ", + "inbound_byte": 224, + "inbound_pkt": 1024, + "outbound_byte": 24956711, + "outbound_pkt": 2048 + },{ + "app": "Douyin", + "inbound_byte": 21356711, + "inbound_pkt": 1024, + "outbound_byte": 2048, + "outbound_pkt": 2048 + }, */{ + app: 'Weibo', + inbound_byte: 24356711, + inbound_pkt: 1024, + outbound_byte: 2048, + outbound_pkt: 2048 + }, { + app: 'Tecent', + inbound_byte: 124356711, + inbound_pkt: 1024, + outbound_byte: 2048, + outbound_pkt: 2048 + }, { + app: 'Kuaishou', + inbound_byte: 324356711, + inbound_pkt: 1024, + outbound_byte: 2048, + outbound_pkt: 2048 + }, { + app: 'Taobao', + inbound_byte: 424356711, + inbound_pkt: 1024, + outbound_byte: 2048, + outbound_pkt: 2048 + }/* { + "app": "Jd", + "inbound_byte": 924356711, + "inbound_pkt": 1024, + "outbound_byte": 2048, + "outbound_pkt": 2048 + },{ + "app": "Aiqiyi", + "inbound_byte": 624356711, + "inbound_pkt": 1024, + "outbound_byte": 2048, + "outbound_pkt": 2048 + },{ + "app": "Baidu", + "inbound_byte": 1624356711, + "inbound_pkt": 1024, + "outbound_byte": 2048, + "outbound_pkt": 2048 + } */ + ] + } + } + } + const res = response.data + if (response.status === 200) { + this.isNoData = res.data.result.length === 0 + this.showError = false + if (!this.isNoData) { + const appDatas = res.data.result.map(item => { + const upData = item.outbound_byte ? item.outbound_byte : 0 + const downData = item.inbound_byte ? item.inbound_byte : 0 + return { + app: item.app, + up: upData, + down: downData, + appTotal: upData + downData + } + }) + + this.topAppData = appDatas.sort(reverseSortBy('appTotal')) + this.getTotalData() + } + } + + // 无数据时的测试代码---------- + }) + }, + getTotalData () { + const params = { + resource: this.entity.entityName, + startTime: getSecond(this.timeFilter.startTime), + endTime: getSecond(this.timeFilter.endTime) + } + axios.get(api.entity.subscriberKpi, { params: params }).then(response => { + const res = response.data + if (response.status === 200) { + const data = res.data + this.isNoData = Object.keys(data).length === 0 + this.showError = false + if (!this.isNoData) { + const totalData = data.total_bytes ? data.total_bytes : 0 + if (totalData !== 0) { + const echartDataList = [] + this.topAppData.forEach(item => { + echartDataList.push({ + count: (item.appTotal / totalData).toFixed(3), + app: item.app + }) + }) + + this.initEchart(echartDataList) + } + } + } else { + this.httpError(res) + } + }).catch(e => { + console.error(e) + this.httpError(e) + }).finally(() => { // 无数据时的测试代码---------- + const response = { + status: 200, + data: { + code: 200, + msg: 'ok', + data: { + total_bytes: 9024356711, + total_packets: 999, + avg_bits_per_sec: 888, + avg_pkts_per_sec: 888, + avg_http_response_latency_ms: 30, + avg_ssl_handshake_latency_ms: 10, + tcp_lost_bytes_ratio: 0.10 + } + } + } + const res = response.data + if (response.status === 200) { + const data = res.data + this.isNoData = Object.keys(data).length === 0 + this.showError = false + if (!this.isNoData) { + const totalData = data.total_bytes ? data.total_bytes : 0 + if (totalData !== 0) { + const echartDataList = [] + this.topAppData.forEach(item => { + echartDataList.push({ + count: (item.appTotal / totalData).toFixed(3), + app: item.app + }) + }) + + this.initEchart(echartDataList) + } + } + } + + // 无数据时的测试代码---------- }) }, initEchart (data) { - data = [ + /* data = [ { count: 0.307, app: 1 @@ -234,8 +407,12 @@ export default { count: 0.006, app: 10 } - ] + ] */ if (data && data.length > 0) { + if (data.length < 10) { // 重新设置图标高度 + this.isSetHeight = true + this.newHeight = 'height:' + unitConvert(data.length / 10, unitTypes.percent, null, null, 0).join('') + ';' + } const chartDom = document.getElementById('subscriberTopAppChart') this.myChart = echarts.getInstanceByDom(chartDom) if (this.myChart) { diff --git a/src/views/charts2/charts/entityDetail/EntityDetailTabs.vue b/src/views/charts2/charts/entityDetail/EntityDetailTabs.vue index 2db814c9..96ddc69b 100644 --- a/src/views/charts2/charts/entityDetail/EntityDetailTabs.vue +++ b/src/views/charts2/charts/entityDetail/EntityDetailTabs.vue @@ -88,7 +88,7 @@ export default { const tabObj = entityDetailTabConfig.find(tab => tab.name === entityType) const tabs = reactive(tabObj ? tabObj.config : []) - const activeTab = ref(tabs[0].name) + const activeTab = ref(tabs[0] ? tabs[0].name : {}) const { query } = useRoute() const item = tabs.find(item => item.name === query.currentTab) @@ -180,7 +180,7 @@ export default { this.promiseData(appsOfDomain, ipsOfDomain, fqdnsOfDomain) } - if (this.entity.entityType === entityType.subscribe) { + if (this.entity.entityType === entityType.subscriber) { axios.get(api.entity.deviceInformation, { params: this.getParamsByTabType(entityDetailTabsName.deviceInformation) }).then(response => { const res = response.data if (response.status === 200) {