CN-257 Entity Explorer--接口对接
This commit is contained in:
@@ -93,7 +93,7 @@
|
|||||||
}
|
}
|
||||||
.body__drawing-box {
|
.body__drawing-box {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100px;
|
height: 60px;
|
||||||
.chart__loading {
|
.chart__loading {
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
@@ -102,7 +102,7 @@
|
|||||||
.body__drawing {
|
.body__drawing {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
padding: 10px 30px;
|
padding: 10px 30px;
|
||||||
height: 100px;
|
height: 60px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,17 @@ export const api = {
|
|||||||
ipThroughput: '/interface/entity/ip/detail/throughput',
|
ipThroughput: '/interface/entity/ip/detail/throughput',
|
||||||
domainThroughput: '/interface/entity/domain/detail/throughput',
|
domainThroughput: '/interface/entity/domain/detail/throughput',
|
||||||
appThroughput: '/interface/entity/app/detail/throughput',
|
appThroughput: '/interface/entity/app/detail/throughput',
|
||||||
filterTop: '/interface/entity/filter/top'
|
filterTop: '/interface/entity/filter/top',
|
||||||
|
entityTotal: '/interface/entity/index/total',
|
||||||
|
entityNew: '/interface/entity/index/new',
|
||||||
|
entityActive: '/interface/entity/index/active',
|
||||||
|
entityTraffic: '/interface/entity/list/traffic',
|
||||||
|
entityAlertNum: '/interface/entity/list/alertNum',
|
||||||
|
entitySecurityNum: '/interface/entity/list/detectionNum',
|
||||||
|
ipBytes: '/interface/entity/detail/ip/bytes',
|
||||||
|
domainBytes: '/interface/entity/detail/domain/bytes',
|
||||||
|
appBytes: '/interface/entity/detail/app/bytes'
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* panel */
|
/* panel */
|
||||||
|
|||||||
@@ -32,57 +32,57 @@
|
|||||||
<el-divider direction="vertical"></el-divider>
|
<el-divider direction="vertical"></el-divider>
|
||||||
<div class="entity-overview">
|
<div class="entity-overview">
|
||||||
<div class="overview-left">
|
<div class="overview-left">
|
||||||
<span>86</span>
|
<span>{{entityAppTotal}}</span>
|
||||||
<span>APP</span>
|
<span>APP</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview-right">
|
<div class="overview-right">
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-increase"></i>
|
<i class="cn-icon cn-icon-increase"></i>
|
||||||
<div class="right-label">New</div>
|
<div class="right-label">New</div>
|
||||||
<div class="right-value">51</div>
|
<div class="right-value">{{entityAppNew}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-active"></i>
|
<i class="cn-icon cn-icon-active"></i>
|
||||||
<div class="right-label">Active</div>
|
<div class="right-label">Active</div>
|
||||||
<div class="right-value">56</div>
|
<div class="right-value">{{entityAppActive}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-divider direction="vertical"></el-divider>
|
<el-divider direction="vertical"></el-divider>
|
||||||
<div class="entity-overview">
|
<div class="entity-overview">
|
||||||
<div class="overview-left">
|
<div class="overview-left">
|
||||||
<span>186</span>
|
<span>{{entityDomainTotal}}</span>
|
||||||
<span>DOMAIN</span>
|
<span>DOMAIN</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview-right">
|
<div class="overview-right">
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-increase"></i>
|
<i class="cn-icon cn-icon-increase"></i>
|
||||||
<div class="right-label">New</div>
|
<div class="right-label">New</div>
|
||||||
<div class="right-value">40</div>
|
<div class="right-value">{{entityDomainNew}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-active"></i>
|
<i class="cn-icon cn-icon-active"></i>
|
||||||
<div class="right-label">Active</div>
|
<div class="right-label">Active</div>
|
||||||
<div class="right-value">18</div>
|
<div class="right-value">{{entityDomainActive}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-divider direction="vertical"></el-divider>
|
<el-divider direction="vertical"></el-divider>
|
||||||
<div class="entity-overview">
|
<div class="entity-overview">
|
||||||
<div class="overview-left">
|
<div class="overview-left">
|
||||||
<span>861</span>
|
<span>{{entityIpTotal}}</span>
|
||||||
<span>IP</span>
|
<span>IP</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="overview-right">
|
<div class="overview-right">
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-increase"></i>
|
<i class="cn-icon cn-icon-increase"></i>
|
||||||
<div class="right-label">New</div>
|
<div class="right-label">New</div>
|
||||||
<div class="right-value">99</div>
|
<div class="right-value">{{entityIpNew}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right-row">
|
<div class="right-row">
|
||||||
<i class="cn-icon cn-icon-active"></i>
|
<i class="cn-icon cn-icon-active"></i>
|
||||||
<div class="right-label">Active</div>
|
<div class="right-label">Active</div>
|
||||||
<div class="right-value">37</div>
|
<div class="right-value">{{entityIpActive}}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -99,6 +99,8 @@ import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
|
|||||||
import EntityFilter from '@/views/entityExplorer/EntityFilter'
|
import EntityFilter from '@/views/entityExplorer/EntityFilter'
|
||||||
import EntityList from '@/views/entityExplorer/entityList/EntityList'
|
import EntityList from '@/views/entityExplorer/entityList/EntityList'
|
||||||
import { entityType, entityFilterType } from '@/utils/constants'
|
import { entityType, entityFilterType } from '@/utils/constants'
|
||||||
|
import { get } from '@/utils/http'
|
||||||
|
import { api } from '@/utils/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'entity-explorer',
|
name: 'entity-explorer',
|
||||||
@@ -115,6 +117,18 @@ export default {
|
|||||||
listMode: 'list', // entity列表的模式,list|block
|
listMode: 'list', // entity列表的模式,list|block
|
||||||
timeFilter: {},
|
timeFilter: {},
|
||||||
|
|
||||||
|
entityAppTotal: '-',
|
||||||
|
entityAppNew: '-',
|
||||||
|
entityAppActive: '-',
|
||||||
|
|
||||||
|
entityDomainTotal: '-',
|
||||||
|
entityDomainNew: '-',
|
||||||
|
entityDomainActive: '-',
|
||||||
|
|
||||||
|
entityIpTotal: '-',
|
||||||
|
entityIpNew: '-',
|
||||||
|
entityIpActive: '-',
|
||||||
|
|
||||||
filterData: [
|
filterData: [
|
||||||
{
|
{
|
||||||
type: 'ip',
|
type: 'ip',
|
||||||
@@ -382,7 +396,62 @@ export default {
|
|||||||
},
|
},
|
||||||
queryList () {
|
queryList () {
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
getEntityIndexData () {
|
||||||
|
// Total
|
||||||
|
get(api.entityTotal, { entityType: 'app' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityAppTotal = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityTotal, { entityType: 'domain' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityDomainTotal = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityTotal, { entityType: 'ip' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityIpTotal = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
// New
|
||||||
|
get(api.entityNew, { entityType: 'app' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityAppNew = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityNew, { entityType: 'domain' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityDomainNew = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityNew, { entityType: 'ip' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityIpNew = response.data.result
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Active
|
||||||
|
get(api.entityActive, { entityType: 'app' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityAppActive = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityActive, { entityType: 'domain' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityDomainActive = response.data.result
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
get(api.entityActive, { entityType: 'ip' }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityIpActive = response.data.result
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
mounted () {
|
||||||
|
this.getEntityIndexData()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -115,7 +115,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<!-- 曲线-->
|
<!-- 曲线-->
|
||||||
<div class="body__drawing-box">
|
<div class="body__drawing-box">
|
||||||
<div class="body__drawing" :id="`entityListChart${entityData.appId}`"></div>
|
<div class="body__drawing" :id="`entityListChart${entityData.appName}`"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="body__statics">
|
<div class="body__statics">
|
||||||
<div class="entity-statics-down"><i class="cn-icon cn-icon-fall entity-statics-icon"></i>{{entityData.bytesReceivedRate || 0}} bps</div>
|
<div class="entity-statics-down"><i class="cn-icon cn-icon-fall entity-statics-icon"></i>{{entityData.bytesReceivedRate || 0}} bps</div>
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
<entity-row
|
<entity-row
|
||||||
v-for="(data, index) in listData"
|
v-for="(data, index) in listData"
|
||||||
:entity="data"
|
:entity="data"
|
||||||
|
:listMode="listMode"
|
||||||
|
:timeFilter="timeFilter"
|
||||||
:key="index"
|
:key="index"
|
||||||
:ref="`entityRow${index}`"
|
:ref="`entityRow${index}`"
|
||||||
:index="index"
|
:index="index"
|
||||||
@@ -24,6 +26,8 @@
|
|||||||
<entity-card
|
<entity-card
|
||||||
v-for="(data, index) in listData"
|
v-for="(data, index) in listData"
|
||||||
:entity="data"
|
:entity="data"
|
||||||
|
:listMode="listMode"
|
||||||
|
:timeFilter="timeFilter"
|
||||||
:key="index"
|
:key="index"
|
||||||
></entity-card>
|
></entity-card>
|
||||||
</div>
|
</div>
|
||||||
@@ -62,7 +66,8 @@ export default {
|
|||||||
from: String,
|
from: String,
|
||||||
pageObj: Object,
|
pageObj: Object,
|
||||||
loading: Boolean,
|
loading: Boolean,
|
||||||
listMode: String
|
listMode: String,
|
||||||
|
timeFilter: Object
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
'entity-card': Card,
|
'entity-card': Card,
|
||||||
|
|||||||
@@ -106,7 +106,8 @@ import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/Det
|
|||||||
export default {
|
export default {
|
||||||
name: 'Row',
|
name: 'Row',
|
||||||
props: {
|
props: {
|
||||||
index: Number
|
index: Number,
|
||||||
|
timeFilter: Object
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
DetailOverview
|
DetailOverview
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
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'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
entity: Object
|
entity: Object,
|
||||||
|
timeFilter: {},
|
||||||
|
listMode: ''
|
||||||
},
|
},
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
entityData: {}
|
entityData: {},
|
||||||
|
chartOption: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@@ -28,6 +36,82 @@ export default {
|
|||||||
default: break
|
default: break
|
||||||
}
|
}
|
||||||
return className
|
return className
|
||||||
|
},
|
||||||
|
entityName () {
|
||||||
|
let name
|
||||||
|
switch (this.entityData.entityType) {
|
||||||
|
case ('ip'): {
|
||||||
|
name = this.entity.ip
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('domain'): {
|
||||||
|
name = this.entity.domainName
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('app'): {
|
||||||
|
name = this.entity.appName
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
},
|
||||||
|
queryUrl () {
|
||||||
|
let url
|
||||||
|
switch (this.entityData.entityType) {
|
||||||
|
case ('ip'): {
|
||||||
|
url = api.ipBytes
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('domain'): {
|
||||||
|
url = api.domainBytes
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('app'): {
|
||||||
|
url = api.appBytes
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
return url
|
||||||
|
},
|
||||||
|
queryParams () {
|
||||||
|
let params
|
||||||
|
const now = new Date()
|
||||||
|
switch (this.entityData.entityType) {
|
||||||
|
case ('ip'): {
|
||||||
|
params = {
|
||||||
|
queryTimeRange: {
|
||||||
|
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||||
|
endTime: Math.floor(now.getTime() / 1000)
|
||||||
|
},
|
||||||
|
ip: this.entityData.ip
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('domain'): {
|
||||||
|
params = {
|
||||||
|
queryTimeRange: {
|
||||||
|
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||||
|
endTime: Math.floor(now.getTime() / 1000)
|
||||||
|
},
|
||||||
|
domain: this.entityData.domainName
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case ('app'): {
|
||||||
|
params = {
|
||||||
|
queryTimeRange: {
|
||||||
|
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||||
|
endTime: Math.floor(now.getTime() / 1000)
|
||||||
|
},
|
||||||
|
appName: this.entityData.appName
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: break
|
||||||
|
}
|
||||||
|
return params
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -35,13 +119,110 @@ export default {
|
|||||||
|
|
||||||
},
|
},
|
||||||
queryTraffic () {
|
queryTraffic () {
|
||||||
|
get(api.entityTraffic, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
response.data.result.forEach(t => {
|
||||||
|
if (t.name === 'bytes_sent_rate') {
|
||||||
|
this.entityData.bytesSentRate = t.value
|
||||||
|
}
|
||||||
|
if (t.name === 'bytes_received_rate') {
|
||||||
|
this.entityData.bytesReceivedRate = t.value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
querySecurity () {
|
querySecurity () {
|
||||||
|
get(api.entitySecurityNum, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityData.securityCount = response.data.result[0].count
|
||||||
|
}
|
||||||
|
})
|
||||||
},
|
},
|
||||||
queryAlert () {
|
queryAlert () {
|
||||||
|
get(api.entityAlertNum, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
this.entityData.securityCount = response.data.result[0].value
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
queryTrafficLine () {
|
||||||
|
let chartOption
|
||||||
|
this.chartOption = this.$_.cloneDeep(entityListLineOption)
|
||||||
|
get(this.queryUrl, this.queryParams).then(response => {
|
||||||
|
if (response.code === 200) {
|
||||||
|
const seriesTemplate = this.chartOption.series[0]
|
||||||
|
const series = response.data.result.map((r, i) => {
|
||||||
|
if (r.legend === 'bytes_sent_rate') {
|
||||||
|
return {
|
||||||
|
...seriesTemplate,
|
||||||
|
name: this.$t('entities.sentThroughput'), // 'bytes_sent_rate',//legendMapping[`ip_${r.legend}`],
|
||||||
|
data: r.values.map(v => [Number(v[0]), Number(v[1]), unitTypes.byte]),
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: '#69b072',
|
||||||
|
lineStyle: {
|
||||||
|
width: 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
smooth: true,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: '#f0fff8'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#f0fff8'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (r.legend === 'bytes_received_rate') {
|
||||||
|
return {
|
||||||
|
...seriesTemplate,
|
||||||
|
name: this.$t('entities.receivedThroughput'), // legendMapping[`ip_${r.legend}`],
|
||||||
|
data: r.values.map(v => [Number(v[0]), Number(v[1]), unitTypes.byte]),
|
||||||
|
itemStyle: {
|
||||||
|
normal: {
|
||||||
|
color: '#7899c6',
|
||||||
|
lineStyle: {
|
||||||
|
width: 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
smooth: true,
|
||||||
|
areaStyle: {
|
||||||
|
opacity: 0.8,
|
||||||
|
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||||
|
{
|
||||||
|
offset: 0,
|
||||||
|
color: '#f0f4ff'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
offset: 1,
|
||||||
|
color: '#f0f4ff'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
chartOption = {
|
||||||
|
...this.chartOption,
|
||||||
|
series
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}).finally(() => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const myChart = echarts.init(document.getElementById(`entityListChart${this.entityName}`))
|
||||||
|
myChart.setOption(chartOption)
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted () {
|
mounted () {
|
||||||
@@ -49,5 +230,8 @@ export default {
|
|||||||
setTimeout(() => { this.queryTraffic() })
|
setTimeout(() => { this.queryTraffic() })
|
||||||
setTimeout(() => { this.querySecurity() })
|
setTimeout(() => { this.querySecurity() })
|
||||||
setTimeout(() => { this.queryAlert() })
|
setTimeout(() => { this.queryAlert() })
|
||||||
|
if (this.listMode === 'block') {
|
||||||
|
setTimeout(() => { this.queryTrafficLine() })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user