CN-376 feat : 实体列表添加流量曲线
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
.cn-entity--list {
|
||||
display: flex;
|
||||
|
||||
.cn-entity__collapse {
|
||||
margin-bottom: 1px;
|
||||
padding-top: 30px;
|
||||
@@ -19,6 +20,7 @@
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
}
|
||||
|
||||
span:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -28,6 +30,7 @@
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.cn-entity__case {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
@@ -55,6 +58,7 @@
|
||||
color: #4E84B4;
|
||||
}
|
||||
}
|
||||
|
||||
.cn-entity__row {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -67,6 +71,7 @@
|
||||
padding-bottom: 3px;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.cn-entity__body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -83,22 +88,60 @@
|
||||
|
||||
.basic-info__item {
|
||||
padding-right: 40px;
|
||||
|
||||
.item__box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: row;
|
||||
|
||||
i {
|
||||
padding-right: 6px;
|
||||
color: #8FA1BE;
|
||||
font-size: 12px;
|
||||
height: 13px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
span:first-of-type {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
span:last-of-type {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.row__charts {
|
||||
height: 19px;
|
||||
width: 60px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
padding-right: 6px;
|
||||
color: #8FA1BE;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
span {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
span:first-of-type {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
span:last-of-type {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.show-detail {
|
||||
flex-shrink: 0;
|
||||
padding: 0 30px;
|
||||
@@ -112,6 +155,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cn-entity__detail-overview {
|
||||
flex-basis: 100%;
|
||||
padding: 0 10px;
|
||||
@@ -122,4 +166,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,94 +1,176 @@
|
||||
<template>
|
||||
<div class="cn-entity--list" :style="{zIndex: !isCollapse ? 1 : 'unset'}">
|
||||
<div class="cn-entity--list" :style="{ zIndex: !isCollapse ? 1 : 'unset' }">
|
||||
<!-- 左侧下拉按钮 -->
|
||||
<div class="cn-entity__collapse">
|
||||
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
|
||||
<span @click="switchCollapse" :class="{ 'reg-down': !isCollapse }"
|
||||
><i class="cn-icon cn-icon-arrow-right"></i
|
||||
></span>
|
||||
</div>
|
||||
<div class="cn-entity__case">
|
||||
<div class="cn-entity__icon"><i :class="iconClass"></i></div>
|
||||
<div class="cn-entity__row">
|
||||
<div class="cn-entity__header">{{entityData.ipAddr || entityData.domainName || entityData.appName || 'Unknown'}}</div>
|
||||
<div class="cn-entity__header">
|
||||
{{
|
||||
entityData.ipAddr ||
|
||||
entityData.domainName ||
|
||||
entityData.appName ||
|
||||
'Unknown'
|
||||
}}
|
||||
</div>
|
||||
<div class="cn-entity__body">
|
||||
<div class="body__basic-info">
|
||||
<div class="basic-info">
|
||||
<template v-if="entityData.entityType === 'ip'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-country"></i>
|
||||
<span>{{$t('overall.country')}} : </span>
|
||||
<span>{{entityData.ipLocationCountry || '-'}}</span>
|
||||
<span>{{ $t('overall.country') }} : </span>
|
||||
<span>{{ entityData.ipLocationCountry || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-position"></i>
|
||||
<span>{{$t('overall.region')}} : </span>
|
||||
<span>{{ipLocationRegion(entityData)}}</span>
|
||||
<span>{{ $t('overall.region') }} : </span>
|
||||
<span>{{ ipLocationRegion(entityData) }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-cloud"></i>
|
||||
<span>{{$t('entities.asn')}} : </span>
|
||||
<span>{{entityData.ipAsn || '-'}}</span>
|
||||
<span>{{ $t('entities.asn') }} : </span>
|
||||
<span>{{ entityData.ipAsn || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'domain'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category"></i>
|
||||
<span>{{$t('entities.domainDetail.categoryGroup')}} : </span>
|
||||
<span>{{entityData.domainCategoryGroup || '-'}}</span>
|
||||
<span
|
||||
>{{
|
||||
$t('entities.domainDetail.categoryGroup')
|
||||
}} : </span
|
||||
>
|
||||
<span>{{ entityData.domainCategoryGroup || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span>{{$t('entities.category')}} : </span>
|
||||
<span>{{entityData.domainCategory || '-'}}</span>
|
||||
<span>{{ $t('entities.category') }} : </span>
|
||||
<span>{{ entityData.domainCategory || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-credit"></i>
|
||||
<span>{{$t('entities.reputationLevel')}} : </span>
|
||||
<span>{{entityData.domainReputationScore || '-'}}</span>
|
||||
<span
|
||||
>{{
|
||||
$t('entities.reputationLevel')
|
||||
}} : </span
|
||||
>
|
||||
<span>{{ entityData.domainReputationScore || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'app'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-id"></i>
|
||||
<span>{{$t('entities.category')}} : </span>
|
||||
<span>{{entityData.appCategory || '-'}}</span>
|
||||
<span>{{ $t('entities.category') }} : </span>
|
||||
<span>{{ entityData.appCategory || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category"></i>
|
||||
<span>{{$t('entities.subcategory')}} : </span>
|
||||
<span>{{entityData.appSubcategory || '-'}}</span>
|
||||
<span
|
||||
>{{ $t('entities.subcategory') }} : </span
|
||||
>
|
||||
<span>{{ entityData.appSubcategory || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span>{{$t('entities.risk')}} : </span>
|
||||
<span>{{appRisk(entityData.appRisk) || '-'}}</span>
|
||||
<span>{{ $t('entities.risk') }} : </span>
|
||||
<span>{{ appRisk(entityData.appRisk) || '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 通用字段 -->
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-rise"></i>
|
||||
<span>{{$t('entities.sentThroughput')}} : </span>
|
||||
<span>{{entityData.bytesSentRate ? unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
|
||||
<div class="item__box">
|
||||
<i class="cn-icon cn-icon-rise"></i>
|
||||
<span
|
||||
>{{
|
||||
$t('entities.sentThroughput')
|
||||
}} : </span
|
||||
>
|
||||
<span>{{
|
||||
entityData.bytesSentRate
|
||||
? unitConvert(
|
||||
entityData.bytesSentRate,
|
||||
unitTypes.byte,
|
||||
).join(' ') + 'ps'
|
||||
: '-'
|
||||
}}</span>
|
||||
<!-- 曲线-->
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailSend${entityType}`"
|
||||
v-if="entityData.entityType === 'domain'"
|
||||
></div>
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailSend${entityType}`"
|
||||
v-if="entityData.entityType === 'app'"
|
||||
></div>
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailSend${entityType}`"
|
||||
v-if="entityData.entityType === 'ip'"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-fall"></i>
|
||||
<span>{{$t('entities.receivedThroughput')}} : </span>
|
||||
<span>{{entityData.bytesReceivedRate ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
|
||||
<div class="item__box">
|
||||
<i class="cn-icon cn-icon-fall"></i>
|
||||
<span
|
||||
>{{
|
||||
$t('entities.receivedThroughput')
|
||||
}} : </span
|
||||
>
|
||||
<span>{{
|
||||
entityData.bytesReceivedRate
|
||||
? unitConvert(
|
||||
entityData.bytesReceivedRate,
|
||||
unitTypes.byte,
|
||||
).join(' ') + 'ps'
|
||||
: '-'
|
||||
}}</span>
|
||||
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailReceived${entityType}`"
|
||||
v-if="entityData.entityType === 'domain'"
|
||||
></div>
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailReceived${entityType}`"
|
||||
v-if="entityData.entityType === 'app'"
|
||||
></div>
|
||||
<div
|
||||
class="row__charts"
|
||||
:id="`entityDetailReceived${entityType}`"
|
||||
v-if="entityData.entityType === 'ip'"
|
||||
></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-entity-alert"></i>
|
||||
<span>{{$t('entities.recentAlert')}} : </span>
|
||||
<span>{{entityData.alertCount || '-'}}</span>
|
||||
<span>{{ $t('entities.recentAlert') }} : </span>
|
||||
<span>{{ entityData.alertCount || '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-safe"></i>
|
||||
<span>{{$t('entities.recentSecurity')}} : </span>
|
||||
<span>{{entityData.securityCount || '-'}}</span>
|
||||
<span
|
||||
>{{ $t('entities.recentSecurity') }} : </span
|
||||
>
|
||||
<span>{{ entityData.securityCount || '-' }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="show-detail"
|
||||
:style="{visibility: !isCollapse ? 'visible' : 'hidden'}"
|
||||
@click="showDetail"
|
||||
>{{$t('overall.detail')}}>></div>
|
||||
class="show-detail"
|
||||
:style="{ visibility: !isCollapse ? 'visible' : 'hidden' }"
|
||||
@click="showDetail"
|
||||
>
|
||||
{{ $t('overall.detail') }}>>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -96,8 +178,8 @@
|
||||
<div class="cn-entity__detail-overview" v-if="!isCollapse">
|
||||
<el-divider></el-divider>
|
||||
<detail-overview
|
||||
:entity="entityData"
|
||||
:time-filter="timeFilter"
|
||||
:entity="entityData"
|
||||
:time-filter="timeFilter"
|
||||
></detail-overview>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
@@ -110,28 +192,40 @@ import entityListMixin from './entityListMixin'
|
||||
import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/DetailOverview'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import entityDetailMixin from './detailOverview/entityDetailMixin'
|
||||
import relatedServer from '@/mixins/relatedServer'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
export default {
|
||||
name: 'Row',
|
||||
props: {
|
||||
index: Number,
|
||||
timeFilter: Object
|
||||
timeFilter: Object,
|
||||
},
|
||||
components: {
|
||||
DetailOverview
|
||||
DetailOverview,
|
||||
},
|
||||
mixins: [entityListMixin],
|
||||
data () {
|
||||
mixins: [entityListMixin, entityDetailMixin, relatedServer],
|
||||
data() {
|
||||
return {
|
||||
isCollapse: true // 是否是折叠状态
|
||||
isCollapse: true, // 是否是折叠状态
|
||||
trafficUrl: '',
|
||||
entityType: '',
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ipLocationRegion () {
|
||||
ipLocationRegion() {
|
||||
return function (entityData) {
|
||||
const hasProvinceAndCity = entityData.ipLocationProvince && entityData.ipLocationCity &&
|
||||
entityData.ipLocationProvince !== 'null' && entityData.ipLocationCity !== 'null'
|
||||
const hasProvince = entityData.ipLocationProvince && entityData.ipLocationProvince !== 'null'
|
||||
const hasCity = entityData.ipLocationCity && entityData.ipLocationCity !== 'null'
|
||||
const hasProvinceAndCity =
|
||||
entityData.ipLocationProvince &&
|
||||
entityData.ipLocationCity &&
|
||||
entityData.ipLocationProvince !== 'null' &&
|
||||
entityData.ipLocationCity !== 'null'
|
||||
const hasProvince =
|
||||
entityData.ipLocationProvince &&
|
||||
entityData.ipLocationProvince !== 'null'
|
||||
const hasCity =
|
||||
entityData.ipLocationCity && entityData.ipLocationCity !== 'null'
|
||||
if (hasProvinceAndCity) {
|
||||
return `${entityData.ipLocationProvince}, ${entityData.ipLocationCity}`
|
||||
} else if (hasProvince) {
|
||||
@@ -142,24 +236,80 @@ export default {
|
||||
return '-'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
entityType() {
|
||||
let type
|
||||
switch (this.entityData.entityType) {
|
||||
case 'ip': {
|
||||
type = this.entityData.ipAddr
|
||||
break
|
||||
}
|
||||
case 'domain': {
|
||||
type = this.entityData.domainName
|
||||
break
|
||||
}
|
||||
case 'app': {
|
||||
type = this.entityData.appName
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
this.entityType = type
|
||||
return type
|
||||
},
|
||||
},
|
||||
setup () {
|
||||
watch: {
|
||||
entityData: {
|
||||
deep: true,
|
||||
handler(n) {
|
||||
if (n.entityType) {
|
||||
switch (n.entityType) {
|
||||
case 'ip': {
|
||||
this.trafficUrl = api.entityIpDetailTraffic
|
||||
break
|
||||
}
|
||||
case 'domain': {
|
||||
this.trafficUrl = api.entityDomainDetailTraffic
|
||||
break
|
||||
}
|
||||
case 'app': {
|
||||
this.trafficUrl = api.entityAppDetailTraffic
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
setup() {
|
||||
return {
|
||||
unitConvert,
|
||||
unitTypes
|
||||
unitTypes,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* 切换折叠状态 */
|
||||
switchCollapse () {
|
||||
switchCollapse() {
|
||||
this.isCollapse = !this.isCollapse
|
||||
this.$emit('switchCollapse', this.isCollapse, this.index)
|
||||
},
|
||||
/* 设为折叠状态 */
|
||||
collapse () {
|
||||
collapse() {
|
||||
this.isCollapse = true
|
||||
}
|
||||
}
|
||||
},
|
||||
getQueryParams() {
|
||||
const queryParams = {
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
appName: this.entityType,
|
||||
domain:this.entityType,
|
||||
ip:this.entityType
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -72,7 +72,7 @@ export default {
|
||||
this.entityData.max = t.aggregation.max
|
||||
this.entityData.avg = t.aggregation.avg
|
||||
} else if (t.legend === 'bytesSentRate') {
|
||||
this.entityData.bytesSentRate = t.aggregation.last
|
||||
this.entityData.bytesSentRate = _.nth(t.values,-3)[1]
|
||||
this.chartOptionSent = {
|
||||
...this.chartOption,
|
||||
series: [
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
}
|
||||
},
|
||||
color: '#69b072',
|
||||
data: t.values.map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.byte]),
|
||||
data: _.dropRight(t.values,2).map(v => [Number(v[0]) * 1000, Number(v[1]), unitTypes.byte]),
|
||||
showSymbol: false
|
||||
}
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user