diff --git a/src/assets/css/components/views/charts/chartEchartAppRelateDomain.scss b/src/assets/css/components/views/charts/chartEchartAppRelateDomain.scss index 0a47394b..6f847e39 100644 --- a/src/assets/css/components/views/charts/chartEchartAppRelateDomain.scss +++ b/src/assets/css/components/views/charts/chartEchartAppRelateDomain.scss @@ -3,12 +3,12 @@ .chart-list { .vue-grid-layout > .vue-grid-item { .cn-chart { - .app-detail__related-domain { + .app-detail__related-domain { display: flex; flex-direction: row; height: 100%; width: 100%; - .related-domain__list { + .related-domain__list { display: flex; flex-direction: column; flex: 0 0 25%; diff --git a/src/assets/css/components/views/charts/chartEchartWithTable.scss b/src/assets/css/components/views/charts/chartEchartWithTable.scss index 88bcb1d1..0d08ee21 100644 --- a/src/assets/css/components/views/charts/chartEchartWithTable.scss +++ b/src/assets/css/components/views/charts/chartEchartWithTable.scss @@ -34,9 +34,9 @@ } } - .chart-drawing{ + /*.chart-drawing{ height: calc(100% - 36px) !important; - } + }*/ } .cn-chart__body.pie-with-table { flex-basis: 40%; diff --git a/src/assets/css/components/views/charts/chartSingleValue.scss b/src/assets/css/components/views/charts/chartSingleValue.scss index 1b9892a5..c0845307 100644 --- a/src/assets/css/components/views/charts/chartSingleValue.scss +++ b/src/assets/css/components/views/charts/chartSingleValue.scss @@ -14,6 +14,11 @@ .single-value__content { .content__data { font-size: 14px; + color: #333; + .single-value__unit { + font-size: 14px; + color: #333; + } } .content__title { font-size: 12px; diff --git a/src/assets/css/components/views/entityExplorer/entityList/detail-overview.scss b/src/assets/css/components/views/entityExplorer/entityList/detail-overview.scss index f2ac0663..2d918e63 100644 --- a/src/assets/css/components/views/entityExplorer/entityList/detail-overview.scss +++ b/src/assets/css/components/views/entityExplorer/entityList/detail-overview.scss @@ -11,6 +11,12 @@ width: 550px; height: 350px; + &.overview-map--ip { + height: 300px; + } + &.overview-map--app { + height: 325px; + } .cn-chart { height: 100%; width: 100%; @@ -128,11 +134,11 @@ border-radius: 4px; .tag__value { - padding-right: 5px; color: #3976CB; font-weight: bold; } .tag__desc { + padding-right: 5px; color: #3976CB; } } diff --git a/src/components/advancedSearch/TagMode.vue b/src/components/advancedSearch/TagMode.vue index 365e911f..1f91d0b5 100644 --- a/src/components/advancedSearch/TagMode.vue +++ b/src/components/advancedSearch/TagMode.vue @@ -36,7 +36,7 @@
- +
{{meta.value.label}}
diff --git a/src/components/advancedSearch/meta/sql-parser.js b/src/components/advancedSearch/meta/sql-parser.js index 8800dabd..a9d981de 100644 --- a/src/components/advancedSearch/meta/sql-parser.js +++ b/src/components/advancedSearch/meta/sql-parser.js @@ -1,5 +1,6 @@ import { GenericSQL, SqlParserVisitor } from 'dt-sql-parser' import Meta, { connection, condition, columnType, cloneMeta } from '@/components/advancedSearch/meta/meta' +import { riskLevelMapping } from '@/utils/constants' import _ from 'lodash' // 补全语句,用于解析 const sqlPrev = 'select a from b where ' @@ -87,7 +88,7 @@ export default class SqlParser extends SqlParserVisitor { if (isFullText) { if (meta.meta === condition) { if (meta.column.type !== columnType.fullText) { - sql += `${meta.column.name}${meta.operator.value}${meta.value.value} ` + sql += `${meta.column.name}${meta.operator.value}${valueHandle(meta.value.value, meta.column.name)} ` } else { sql += "QUERY('" this.columnList.forEach(column => { @@ -100,7 +101,7 @@ export default class SqlParser extends SqlParserVisitor { if (meta.meta === condition) { sql += (meta.column.name) if (meta.column.type !== columnType.fullText) { - sql += `${meta.operator.value}${meta.value.value} ` + sql += `${meta.operator.value}${valueHandle(meta.value.value, meta.column.name)} ` } else { sql += ' ' } @@ -275,3 +276,19 @@ function handleInOrLike (value, type) { handleValue: v } } + +function valueHandle (value, columnName) { + if (value === "'unknown'") { + return "''" + } else { + if (columnName) { + if (columnName === 'app_risk') { + const m = riskLevelMapping.find(mapping => { + return `'${mapping.name}'` === value || `'${mapping.value}'` === value + }) + return (m && m.value) || value + } + } + return value + } +} diff --git a/src/components/charts/PieTable.vue b/src/components/charts/PieTable.vue index eee8bb85..2615da28 100644 --- a/src/components/charts/PieTable.vue +++ b/src/components/charts/PieTable.vue @@ -9,9 +9,9 @@ :current-row-key="tableNameColumn" tooltip-effect="light" :expand-row-keys="expandRowKeys" - :size="'mini'" - :height="'100%'"> - + size="mini" + height="100%"> + diff --git a/src/views/entityExplorer/entityList/Row.vue b/src/views/entityExplorer/entityList/Row.vue index 809ffbd0..0a654915 100644 --- a/src/views/entityExplorer/entityList/Row.vue +++ b/src/views/entityExplorer/entityList/Row.vue @@ -49,17 +49,17 @@
{{$t('entities.category')}} :   - {{entityData.appId || '-'}} + {{entityData.appCategory || '-'}}
{{$t('entities.subcategory')}} :   - {{entityData.appCategory || '-'}} + {{entityData.appSubategory || '-'}}
{{$t('entities.risk')}} :   - {{entityData.appSubategory || '-'}} + {{appRisk(entityData.appRisk) || '-'}}
diff --git a/src/views/entityExplorer/entityList/detailOverview/App.vue b/src/views/entityExplorer/entityList/detailOverview/App.vue index c7ec6673..fc6c91cd 100644 --- a/src/views/entityExplorer/entityList/detailOverview/App.vue +++ b/src/views/entityExplorer/entityList/detailOverview/App.vue @@ -63,6 +63,35 @@ +
+
{{$t('overall.networkQuality')}}
+
+
+ +
+
+
+
+
{{$t('entities.accessLink')}}
+
+
+
+ {{$t('entities.outLinkTrafficPercentage')}} + {{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') + '%' : '-'}} +
+
+ {{$t('entities.inLinkTrafficPercentage')}} + {{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') + '%' : '-'}} +
+
+
+
{{$t('overall.alert')}}
@@ -103,7 +132,7 @@
-
+
{ setTimeout(() => { this.chartGetMap()}, 250)}) + watch: { + entityData: { + immediate: true, + deep: true, + handler (n) { + this.singleValues.chartDatas.splice(0, 1, this.$_.get(n, 'establishLatency')) + this.singleValues.chartDatas.splice(1, 1, this.$_.get(n, 'httpResponseLatency')) + this.singleValues.chartDatas.splice(2, 1, this.$_.get(n, 'sslConLatency')) + this.singleValues.chartDatas.splice(3, 1, this.$_.get(n, 'sequenceGapLossPercent')) + this.singleValues.chartDatas.splice(4, 1, this.$_.get(n, 'pktRetransPercent')) + } + } + }, + mounted () { + this.$nextTick(() => { setTimeout(() => { this.chartGetMap() }, 250) }) }, setup (props) { return { diff --git a/src/views/entityExplorer/entityList/detailOverview/Domain.vue b/src/views/entityExplorer/entityList/detailOverview/Domain.vue index 8487a5d2..4af40f47 100644 --- a/src/views/entityExplorer/entityList/detailOverview/Domain.vue +++ b/src/views/entityExplorer/entityList/detailOverview/Domain.vue @@ -160,7 +160,7 @@ import { unitTypes } from '@/utils/constants' import unitConvert from '@/utils/unit-convert' import Chart2 from '@/views/charts/Chart2' import _ from 'lodash' -import {get} from "@/utils/http"; +import { get } from '@/utils/http' export default { name: 'Domain', components: { @@ -170,7 +170,7 @@ export default { mixins: [entityDetailMixin], data () { return { - entityData: {}, + // entityData: {}, entityType: 'domain', trafficUrl: api.entityDomainDetailTraffic, relationUrl: api.entityDomainDetailRelation, @@ -211,7 +211,7 @@ export default { { params: { icon: 'cn-icon cn-icon-package-loss', - unitType: unitTypes.time + unitType: unitTypes.percent }, type: 51, i18n: 'entities.sequenceGapLossPercent' @@ -219,10 +219,10 @@ export default { { params: { icon: 'cn-icon cn-icon-upload', - unitType: unitTypes.time + unitType: unitTypes.percent }, type: 51, - i18n: 'entities.avgRoundTripTime' + i18n: 'entities.pktRetransPercent' } ], chartDatas: [null, null, null, null, null] @@ -255,17 +255,15 @@ export default { immediate: true, deep: true, handler (n) { - if ((n.pktRetransPercent && n.sequenceGapLossPercent && n.sslConLatency && n.establishLatency && n.httpResponseLatency) !== undefined) { - this.singleValues.chartDatas.splice(0, 1, this.$_.get(n, 'establishLatency') || null) - this.singleValues.chartDatas.splice(1, 1, this.$_.get(n, 'httpResponseLatency') || null) - this.singleValues.chartDatas.splice(2, 1, this.$_.get(n, 'sslConLatency') || null) - this.singleValues.chartDatas.splice(3, 1, this.$_.get(n, 'sequenceGapLossPercent') || null) - this.singleValues.chartDatas.splice(4, 1, this.$_.get(n, 'pktRetransPercent') || null) - } + this.singleValues.chartDatas.splice(0, 1, this.$_.get(n, 'establishLatency')) + this.singleValues.chartDatas.splice(1, 1, this.$_.get(n, 'httpResponseLatency')) + this.singleValues.chartDatas.splice(2, 1, this.$_.get(n, 'sslConLatency')) + this.singleValues.chartDatas.splice(3, 1, this.$_.get(n, 'sequenceGapLossPercent')) + this.singleValues.chartDatas.splice(4, 1, this.$_.get(n, 'pktRetransPercent')) } } }, - mounted() { + mounted () { this.$nextTick(() => { setTimeout(() => { this.chartGetMap()}, 250)}) }, setup (props) { diff --git a/src/views/entityExplorer/entityList/detailOverview/Ip.vue b/src/views/entityExplorer/entityList/detailOverview/Ip.vue index cb3875ac..29ee1a8f 100644 --- a/src/views/entityExplorer/entityList/detailOverview/Ip.vue +++ b/src/views/entityExplorer/entityList/detailOverview/Ip.vue @@ -55,6 +55,35 @@
+
+
{{$t('overall.networkQuality')}}
+
+
+ +
+
+
+
+
{{$t('entities.accessLink')}}
+
+
+
+ {{$t('entities.outLinkTrafficPercentage')}} + {{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') + '%' : '-'}} +
+
+ {{$t('entities.inLinkTrafficPercentage')}} + {{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') + '%' : '-'}} +
+
+
+
{{$t('overall.alert')}}
@@ -95,7 +124,7 @@
-
+
import entityDetailMixin from './entityDetailMixin' +import ChartSingleValue from '@/views/charts/charts/ChartSingleValue' import { api } from '@/utils/api' import { unitTypes } from '@/utils/constants' import unitConvert from '@/utils/unit-convert' import Chart2 from '@/views/charts/Chart2' import _ from 'lodash' -import {get} from "@/utils/http"; +import { get } from '@/utils/http' export default { name: 'Ip', mixins: [entityDetailMixin], components: { - Chart2 + Chart2, + ChartSingleValue }, data () { return { @@ -129,10 +160,58 @@ export default { trafficUrl: api.entityIpDetailTraffic, trafficUrlMap: api.entityIpDetailTrafficMap, relationUrl: api.entityIpDetailRelation, + networkQuantityUrl: api.entityIpDetailNetworkQuantity, + linkInUrl: api.entityIpDetailLinkIn, + linkOutUrl: api.entityIpDetailLinkOut, alertUrl: api.entityIpDetailAlert, securityUrl: api.entityIpDetailSecurity, listMode: 'list', - chartData: null + chartData: null, + singleValues: { + chartInfos: [ + { + params: { + icon: 'cn-icon cn-icon-time', + unitType: unitTypes.time + }, + type: 51, + i18n: 'entities.avgRoundTripTime' + }, + { + params: { + icon: 'cn-icon cn-icon-http', + unitType: unitTypes.time + }, + type: 51, + i18n: 'entities.httpResponseLatency' + }, + { + params: { + icon: 'cn-icon cn-icon-ssl', + unitType: unitTypes.time + }, + type: 51, + i18n: 'entities.sslConLatency' + }, + { + params: { + icon: 'cn-icon cn-icon-package-loss', + unitType: unitTypes.percent + }, + type: 51, + i18n: 'entities.sequenceGapLossPercent' + }, + { + params: { + icon: 'cn-icon cn-icon-upload', + unitType: unitTypes.percent + }, + type: 51, + i18n: 'entities.pktRetransPercent' + } + ], + chartDatas: [null, null, null, null, null] + } } }, methods: { @@ -155,10 +234,23 @@ export default { this.chartData = response.data.result } }) - }, + } }, - mounted() { - this.$nextTick(() => { setTimeout(() => { this.chartGetMap()}, 250)}) + watch: { + entityData: { + immediate: true, + deep: true, + handler (n) { + this.singleValues.chartDatas.splice(0, 1, this.$_.get(n, 'establishLatency')) + this.singleValues.chartDatas.splice(1, 1, this.$_.get(n, 'httpResponseLatency')) + this.singleValues.chartDatas.splice(2, 1, this.$_.get(n, 'sslConLatency')) + this.singleValues.chartDatas.splice(3, 1, this.$_.get(n, 'sequenceGapLossPercent')) + this.singleValues.chartDatas.splice(4, 1, this.$_.get(n, 'pktRetransPercent')) + } + } + }, + mounted () { + this.$nextTick(() => { setTimeout(() => { this.chartGetMap() }, 250) }) }, setup (props) { const entityCopy = { diff --git a/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js b/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js index 14f673ce..64b53a07 100644 --- a/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js +++ b/src/views/entityExplorer/entityList/detailOverview/entityDetailMixin.js @@ -160,10 +160,18 @@ export default { queryEntityDetailLinkOutUrl () { if (this.linkOutUrl) { get(this.linkOutUrl, this.getQueryParams()).then(response => { - if (response.code === 200 && response.data.aggregation) { - const sum = response.data.aggregation.sum - const max = response.data.aggregation.max - this.entityData.linkOutPercent = (parseFloat(max / sum) * 100).toFixed(2) + if (response.code === 200) { + if (!this.$_.isEmpty(response.data.result)) { + let sum = 0 + response.data.result.forEach(r => { + sum += parseFloat(r.bytes) + }) + const sorted = response.data.result.sort((r1, r2) => { + return parseFloat(r2.bytes) - parseFloat(r1.bytes) + }) + const max = parseFloat(sorted[0].bytes) + this.entityData.linkOutPercent = (parseFloat(max / sum) * 100).toFixed(2) + } } }) } @@ -192,11 +200,9 @@ export default { this.queryEntityDetailRelation() this.queryEntityDetailAlert() this.queryEntityDetailSecurity() - if (this.entityData.entityType === 'domain') { - this.queryEntityDetailNetworkQuantity() - this.queryEntityDetailLinkOutUrl() - this.queryEntityDetailLinkInUrl() - } + this.queryEntityDetailNetworkQuantity() + this.queryEntityDetailLinkOutUrl() + this.queryEntityDetailLinkInUrl() } }, setup () { diff --git a/src/views/entityExplorer/entityList/entityListMixin.js b/src/views/entityExplorer/entityList/entityListMixin.js index 237210d0..9da3a6ca 100644 --- a/src/views/entityExplorer/entityList/entityListMixin.js +++ b/src/views/entityExplorer/entityList/entityListMixin.js @@ -3,7 +3,7 @@ import { get } from '@/utils/http' import { api } from '@/utils/api' import * as echarts from 'echarts' import { entityListLineOption } from '@/components/charts/chart-options' -import { unitTypes } from '@/utils/constants' +import {riskLevelMapping, unitTypes} from '@/utils/constants' export default { props: { @@ -75,6 +75,14 @@ export default { } return url }, + 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() diff --git a/src/views/entityExplorer/search/ExplorerSearch.vue b/src/views/entityExplorer/search/ExplorerSearch.vue index d477ebc0..1233b2a4 100644 --- a/src/views/entityExplorer/search/ExplorerSearch.vue +++ b/src/views/entityExplorer/search/ExplorerSearch.vue @@ -187,12 +187,12 @@ export default { }, { name: 'app_risk', - type: 'long', + type: 'string', // label: this.$t('trafficSummary.appRisk') label: 'APP risk' } ], - operatorList: ['=', '!=', '>', '<', '>=', '<=', 'IN', 'NOT IN', 'LIKE', 'NOT LIKE'], + operatorList: ['=', '!=', '>', '<', '>=', '<='/*, 'IN', 'NOT IN', 'LIKE', 'NOT LIKE'*/], connectionList: [ { value: 'AND',