CN-240 feat: 实体列表、详情细节完善
This commit is contained in:
@@ -7,6 +7,20 @@
|
||||
justify-content: center;
|
||||
transition: all linear .2s;
|
||||
|
||||
.entity__loading {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
z-index: 1;
|
||||
|
||||
i {
|
||||
position: absolute;
|
||||
left: calc(50% - 15px);
|
||||
top: calc(50% - 15px);
|
||||
font-size: 30px;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
&.entity-explorer--show-list {
|
||||
background-color: unset;
|
||||
justify-content: flex-start;
|
||||
|
||||
@@ -4,6 +4,22 @@
|
||||
flex-direction: column;
|
||||
padding: 0 30px;
|
||||
|
||||
.overview-map {
|
||||
position: absolute;
|
||||
right: 50px;
|
||||
top: 0;
|
||||
width: 550px;
|
||||
height: 350px;
|
||||
|
||||
.cn-chart__map {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
.chart-drawing {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
.overview-item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@@ -84,7 +100,8 @@
|
||||
}
|
||||
}
|
||||
.row__charts-msg {
|
||||
width:105px;
|
||||
width: auto;
|
||||
padding-right: 20px;
|
||||
}
|
||||
.row__charts {
|
||||
height: 20px;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
.entity-list {
|
||||
width: calc(100% - 290px);
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.entity-list__content {
|
||||
height: 100%;
|
||||
@@ -29,6 +30,7 @@
|
||||
width: 100vw;
|
||||
left: 0;
|
||||
top: 0;
|
||||
z-index: 1;
|
||||
background-color: rgba(0, 0, 0, .2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="search__suffix">
|
||||
<i class="cn-icon cn-icon-search-advance"></i>
|
||||
</div>
|
||||
<div class="search__suffix" @click="search">
|
||||
<div class="search__suffix" @click="enter">
|
||||
<i class="el-icon-search"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -18,7 +18,7 @@
|
||||
<div class="search__suffix">
|
||||
<i class="cn-icon cn-icon-search-advance"></i>
|
||||
</div>
|
||||
<div class="search__suffix" @click="search">
|
||||
<div class="search__suffix" @click="enter">
|
||||
<i class="el-icon-search"></i>
|
||||
</div>
|
||||
</div>
|
||||
@@ -28,6 +28,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { objToStr, strToObj } from '@/utils/tools'
|
||||
export default {
|
||||
name: 'AdvancedSearch',
|
||||
props: {
|
||||
@@ -54,31 +55,10 @@ export default {
|
||||
addParams (params) {
|
||||
if (params) {
|
||||
const newParams = { ...this.searchParams, ...params }
|
||||
this.searchContentTemp = this.objToStr(newParams)
|
||||
this.searchContentTemp = objToStr(newParams)
|
||||
this.enter()
|
||||
}
|
||||
},
|
||||
strToObj (n) {
|
||||
const paramsArr = n.split(/\s[aA][nN][dD]\s/)
|
||||
const paramsObj = {}
|
||||
paramsArr.forEach(string => {
|
||||
const param = string.split('=')
|
||||
if (param.length > 1) {
|
||||
let value = param[1].trim()
|
||||
const valueArr = value.split('"')
|
||||
if (valueArr.length > 2) {
|
||||
value = valueArr[1].trim()
|
||||
}
|
||||
paramsObj[param[0].trim()] = value
|
||||
}
|
||||
})
|
||||
return paramsObj
|
||||
},
|
||||
objToStr (obj) {
|
||||
return Object.keys(obj).map(k => {
|
||||
return `${k}="${obj[k]}"`
|
||||
}).join(' AND ')
|
||||
},
|
||||
enter () {
|
||||
if (!this.searchContentTemp) {
|
||||
this.reset()
|
||||
@@ -90,7 +70,7 @@ export default {
|
||||
watch: {
|
||||
searchContent (n) {
|
||||
if (n) {
|
||||
this.searchParams = this.strToObj(n)
|
||||
this.searchParams = strToObj(n)
|
||||
} else {
|
||||
this.reset()
|
||||
}
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
<div class="cn-chart cn-chart__map">
|
||||
<div class="cn-chart__header chart-header-position" >
|
||||
<slot name="chartErrorInfo"></slot>
|
||||
<div class="header__title" >
|
||||
<div class="header__title" v-if="!hideHeader">
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
<div class="header__operations">
|
||||
<div class="header__operations" v-if="!hideHeader">
|
||||
<slot name="operations"></slot>
|
||||
</div>
|
||||
</div>
|
||||
@@ -26,7 +26,8 @@
|
||||
export default {
|
||||
name: 'ChartMap',
|
||||
props: {
|
||||
loading: Boolean
|
||||
loading: Boolean,
|
||||
hideHeader: Boolean
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
</div>
|
||||
<div class="single-value__content single-value__content--with-chart" v-if="type === 52">
|
||||
<div class="single-value__content single-value__content--with-chart" v-if="type === 52 || type === 55">
|
||||
<div class="content__title">
|
||||
<slot name="title"></slot>
|
||||
</div>
|
||||
@@ -72,6 +72,7 @@ export default {
|
||||
c = 'cn-chart__single-value--icon-left'
|
||||
break
|
||||
}
|
||||
case 55:
|
||||
case 52: {
|
||||
c = 'cn-chart__single-value--chart'
|
||||
break
|
||||
|
||||
@@ -652,6 +652,10 @@ export function isSingleValue (type) {
|
||||
export function isSingleValueWithEcharts (type) {
|
||||
return type === 52
|
||||
}
|
||||
/* 带折线图的单值 */
|
||||
export function isSingleValueWithEchartsTemp (type) {
|
||||
return type === 55
|
||||
}
|
||||
/* 带Table的饼图 */
|
||||
export function isEchartsWithTable (type) {
|
||||
return type === 31
|
||||
|
||||
@@ -226,7 +226,7 @@ export default {
|
||||
if (!this.$_.isEmpty(n) && !this.$_.isEqual(n, o)) {
|
||||
this.entityList = []
|
||||
setTimeout(() => {
|
||||
const now = new Date()
|
||||
const now = window.$dayJs.tz().valueOf()
|
||||
const queryParams = { startTime: Math.floor(now.getTime() / 1000 - 3600), endTime: Math.floor(now.getTime() / 1000) }
|
||||
switch (this.from) {
|
||||
case ('ip'): {
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
</div>
|
||||
<div class="filter-top-box" >
|
||||
<div class="filter-top-body">
|
||||
<div class="entity__loading" v-show="loading">
|
||||
<i class="el-icon-loading"></i>
|
||||
</div>
|
||||
<div class="filter-top-type">{{item.value}}{{$t('overall.operator')}}{{item.label}}</div>
|
||||
<el-table
|
||||
:data="entityTopTenData"
|
||||
@@ -44,6 +47,7 @@
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
loading: Boolean
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
@@ -19,7 +19,8 @@ export default {
|
||||
delete: false,
|
||||
refresh: false,
|
||||
query: false
|
||||
}
|
||||
},
|
||||
timeout: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -51,6 +52,9 @@ export default {
|
||||
},
|
||||
utcTimeToLocalhost (str) { // 系统设置的时区 到 utc 0
|
||||
return str
|
||||
},
|
||||
parseMsDate (ms, format = 'YYYY-MM-DD HH:mm:ss') {
|
||||
return this.dayJs.tz(parseFloat(ms)).format(format)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,7 +443,29 @@ export function lineToSpace (name) {
|
||||
export function humpToLine (name) {
|
||||
return name.replace(/([A-Z])/g, '_$1').toLowerCase()
|
||||
}
|
||||
|
||||
// 搜索功能:对象转字符串
|
||||
export function objToStr (obj) {
|
||||
return Object.keys(obj).map(k => {
|
||||
return `${k}='${obj[k]}'`
|
||||
}).join(' AND ')
|
||||
}
|
||||
// 搜索功能:字符串转对象
|
||||
export function strToObj (n) {
|
||||
const paramsArr = n.split(/\s[aA][nN][dD]\s/)
|
||||
const paramsObj = {}
|
||||
paramsArr.forEach(string => {
|
||||
const param = string.split('=')
|
||||
if (param.length > 1) {
|
||||
let value = param[1].trim()
|
||||
const valueArr = value.split(/[\"\']/g)
|
||||
if (valueArr.length > 2) {
|
||||
value = valueArr[1].trim()
|
||||
}
|
||||
paramsObj[param[0].trim()] = value
|
||||
}
|
||||
})
|
||||
return paramsObj
|
||||
}
|
||||
// 加载geo数据
|
||||
export function loadGeoData (key) {
|
||||
const keys = []
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
v-else-if="isMap"
|
||||
:style="computePosition"
|
||||
:loading="loading"
|
||||
:hide-header="hideHeader"
|
||||
>
|
||||
<template #chartErrorInfo>
|
||||
<chart-error
|
||||
@@ -58,11 +59,11 @@
|
||||
<template #default>
|
||||
<template v-if="isIpBasicInfo">
|
||||
<el-descriptions :column="1">
|
||||
<el-descriptions-item label="ASN:">{{detailData ? detailData.asn : '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="AS Org:">{{detailData ? detailData.asnOrg : '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('entities.asSubnet') + ':'">{{detailData.asnSubnet || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="ASN:">{{detailData.asn || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="AS Org:">{{detailData.asOrganization || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item :label="$t('entities.asSubnet') + ':'">{{detailData.asSubnet || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="ISP:">{{detailData.isp || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="DNS PTR:">{{detailData.dnsPTR || '-'}}</el-descriptions-item>
|
||||
<el-descriptions-item label="DNS PTR:">{{detailData.dnsPtr || '-'}}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div class="chart-location">
|
||||
<el-descriptions :column="1">
|
||||
@@ -434,7 +435,7 @@
|
||||
<div class="domain-detail-list">
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">{{$t('entities.sponsor')}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.sponsor || '-'}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.registrar || '-'}}</div>
|
||||
</div>
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">{{$t('entities.org')}}</div>
|
||||
@@ -442,19 +443,19 @@
|
||||
</div>
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">Email</div>
|
||||
<div class="domain-detail-list__content">{{detailData.email || '-'}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.postcode || '-'}}</div>
|
||||
</div>
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">{{$t('overall.country')}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.orgCountry || '-'}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.country || '-'}}</div>
|
||||
</div>
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">{{$t('entities.creationDate')}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.creationDate || '-'}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.createTime ? parseMsDate(detailData.createTime) : '-'}}</div>
|
||||
</div>
|
||||
<div class="domain-detail-list__row">
|
||||
<div class="domain-detail-list__label">{{$t('entities.expirationDate')}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.expirationDate || '-'}}</div>
|
||||
<div class="domain-detail-list__content">{{detailData.expirationTime ? parseMsDate(detailData.expirationTime) : '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -627,6 +628,7 @@ import {
|
||||
isMapLine,
|
||||
isMapBlock,
|
||||
isSingleValueWithEcharts,
|
||||
isSingleValueWithEchartsTemp,
|
||||
isRelationShip,
|
||||
isTabs,
|
||||
isGroup,
|
||||
@@ -672,6 +674,7 @@ export default {
|
||||
timeFilter: Object,
|
||||
parentData: Object,
|
||||
fromBlock: Boolean,
|
||||
hideHeader: Boolean,
|
||||
entity: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
@@ -871,6 +874,7 @@ export default {
|
||||
})
|
||||
this.myChart.setOption(this.chartOption)
|
||||
this.singleValue.value = result[0].values[result[0].values.length - 1][1]
|
||||
|
||||
/* const queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }
|
||||
const dom = document.getElementById(`chart${this.chartInfo.id}`)
|
||||
!this.myChart && (this.myChart = echarts.init(dom))
|
||||
@@ -969,7 +973,7 @@ export default {
|
||||
setTimeout(() => { this.loading = false }, 250)
|
||||
})
|
||||
} else if (this.isAppBasicInfo) {
|
||||
const queryParams = { app: this.entity.app }
|
||||
const queryParams = { appName: this.entity.appName }
|
||||
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.detailData = response.data.result
|
||||
@@ -1135,6 +1139,7 @@ export default {
|
||||
}
|
||||
})
|
||||
|
||||
console.info(this.entity)
|
||||
this.showMapBackButton = !!country
|
||||
const chartParams = this.chartInfo.params
|
||||
const queryParams = { ...this.queryTimeRange, country: country || '', region: '', ...this.entity } // 统计数据的查询参数
|
||||
@@ -1321,16 +1326,13 @@ export default {
|
||||
},
|
||||
// 获取最新时间
|
||||
getChartCurrentTimeRange (callback) {
|
||||
console.info(this.isGroup)
|
||||
if (this.isGroup) {
|
||||
this.$emit('getChartCurrentTimeRange', ({ startTime, endTime }) => {
|
||||
console.info(startTime, endTime)
|
||||
callback({ startTime, endTime })
|
||||
})
|
||||
} else {
|
||||
const myEndTime = window.$dayJs.tz().valueOf()
|
||||
const myStartTime = myEndTime - this.chartTimeFilter.dateRangeValue * 60 * 1000
|
||||
console.info(myStartTime, myEndTime)
|
||||
callback({ startTime: myStartTime, endTime: myEndTime })
|
||||
}
|
||||
},
|
||||
@@ -1820,7 +1822,7 @@ export default {
|
||||
]
|
||||
this.myChart.setOption(this.chartOption)
|
||||
this.myChart2.setOption(this.chartOption)
|
||||
get(replaceUrlPlaceholder(chartParams.url, { app: this.entity.app })).then(response => {
|
||||
get(replaceUrlPlaceholder(chartParams.url, { appName: this.entity.appName })).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (this.$_.isEmpty(response.data.result)) {
|
||||
this.noData = true
|
||||
@@ -2476,12 +2478,22 @@ export default {
|
||||
if (this.detailData) {
|
||||
if (this.detailData.country) {
|
||||
location = this.detailData.country
|
||||
if (this.detailData.region) {
|
||||
if (this.detailData.province) {
|
||||
location += ', '
|
||||
location += this.detailData.region
|
||||
location += this.detailData.province
|
||||
if (this.detailData.city) {
|
||||
location += ', '
|
||||
location += this.detailData.city
|
||||
}
|
||||
} else if (this.detailData.region) {
|
||||
location = this.detailData.region
|
||||
}
|
||||
} else if (this.detailData.province) {
|
||||
location = this.detailData.province
|
||||
if (this.detailData.city) {
|
||||
location += ', '
|
||||
location += this.detailData.city
|
||||
}
|
||||
} else if (this.detailData.city) {
|
||||
location = this.detailData.city
|
||||
}
|
||||
}
|
||||
return location
|
||||
@@ -2505,6 +2517,8 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
console.info(this.chart)
|
||||
console.info(this.entity)
|
||||
this.initChart()
|
||||
this.throttle = this.$_.throttle(this.echartsResize, 500)
|
||||
window.addEventListener('resize', this.throttle)
|
||||
@@ -2565,6 +2579,7 @@ export default {
|
||||
isEchartsWithStatistics: isEchartsWithStatistics(props.chart.type),
|
||||
isSingleValue: isSingleValue(props.chart.type),
|
||||
isSingleValueWithEcharts: isSingleValueWithEcharts(props.chart.type),
|
||||
isSingleValueWithEchartsTemp: isSingleValueWithEchartsTemp(props.chart.type),
|
||||
isRelationShip: isRelationShip(props.chart.type),
|
||||
isTable: isTable(props.chart.type),
|
||||
isActiveIpTable: isActiveIpTable(props.chart.type),
|
||||
|
||||
@@ -36,7 +36,9 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
anchorPoints: [], // { id, label, top, height }
|
||||
top: 0
|
||||
top: 0,
|
||||
scrollHeight: 0,
|
||||
clientHeight: 0
|
||||
}
|
||||
},
|
||||
setup (props, ctx) {
|
||||
@@ -73,6 +75,9 @@ export default {
|
||||
chartLoaded (chartList) {
|
||||
this.anchorPoints = []
|
||||
let anchorPoints = []
|
||||
const panelDom = document.querySelector('#cn-panel')
|
||||
this.scrollHeight = panelDom.scrollHeight
|
||||
this.clientHeight = panelDom.clientHeight
|
||||
chartList.forEach(chart => {
|
||||
if (chart.params.anchorPoint) {
|
||||
const dom = document.querySelector(`#${chart.params.anchorPoint}`)
|
||||
@@ -128,11 +133,15 @@ export default {
|
||||
},
|
||||
currentAnchor () {
|
||||
let currentAnchor = null
|
||||
if (this.top + this.clientHeight === this.scrollHeight) {
|
||||
currentAnchor = this.anchorPoints[this.anchorPoints.length - 1]
|
||||
} else {
|
||||
this.anchorPoints.forEach(anchor => {
|
||||
if (anchor.top <= this.top) {
|
||||
currentAnchor = anchor
|
||||
}
|
||||
})
|
||||
}
|
||||
return currentAnchor
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
:time-filter="timeFilter"
|
||||
@pageSize="pageSize"
|
||||
@pageNo="pageNo"
|
||||
:loading="listLoading"
|
||||
></entity-list>
|
||||
</div>
|
||||
<div class="explorer-foot" v-else>
|
||||
@@ -145,7 +146,6 @@ export default {
|
||||
pageSize: defaultPageSize,
|
||||
total: 0
|
||||
},
|
||||
timeFilter: {},
|
||||
filterData: [
|
||||
{
|
||||
type: 'ip',
|
||||
@@ -155,28 +155,28 @@ export default {
|
||||
{
|
||||
label: this.$t('overall.country'),
|
||||
column: 'countryDistinctCount',
|
||||
topColumn: 'ipLocationCountry', // top弹框查询字段
|
||||
topColumn: 'ip_location_country', // top弹框查询字段
|
||||
icon: entityFilterType.ip[0].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.province'),
|
||||
column: 'provinceDistinctCount',
|
||||
topColumn: 'ipLocationProvince', // top弹框查询字段
|
||||
topColumn: 'ip_location_province', // top弹框查询字段
|
||||
icon: entityFilterType.ip[1].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.city'),
|
||||
column: 'cityDistinctCount',
|
||||
topColumn: 'ipLocationCity', // top弹框查询字段
|
||||
topColumn: 'ip_location_city', // top弹框查询字段
|
||||
icon: entityFilterType.ip[2].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('entities.asn'),
|
||||
column: 'asnDistinctCount',
|
||||
topColumn: 'ipAsn', // top弹框查询字段
|
||||
topColumn: 'ip_asn', // top弹框查询字段
|
||||
icon: entityFilterType.ip[3].icon,
|
||||
value: 0
|
||||
}
|
||||
@@ -190,21 +190,21 @@ export default {
|
||||
{
|
||||
label: this.$t('entities.category'),
|
||||
column: 'categoryDistinctCount',
|
||||
topColumn: 'appCategory', // top弹框查询字段
|
||||
topColumn: 'app_category', // top弹框查询字段
|
||||
icon: entityFilterType.app[0].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('entities.subcategory'),
|
||||
column: 'subcategoryDistinctCount',
|
||||
topColumn: 'appSubcategory', // top弹框查询字段
|
||||
topColumn: 'app_subcategory', // top弹框查询字段
|
||||
icon: entityFilterType.app[1].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('entities.risk'),
|
||||
column: 'riskDistinctCount',
|
||||
topColumn: 'appRisk', // top弹框查询字段
|
||||
topColumn: 'app_risk', // top弹框查询字段
|
||||
icon: entityFilterType.app[2].icon,
|
||||
value: 0
|
||||
}
|
||||
@@ -218,29 +218,30 @@ export default {
|
||||
{
|
||||
label: this.$t('entities.domainDetail.categoryGroup'),
|
||||
column: 'categoryGroupDistinctCount',
|
||||
topColumn: 'domainCategoryGroup', // top弹框查询字段
|
||||
topColumn: 'domain_category_group', // top弹框查询字段
|
||||
icon: entityFilterType.domain[0].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('entities.category'),
|
||||
column: 'categoryDistinctCount',
|
||||
topColumn: 'domainCategory', // top弹框查询字段
|
||||
topColumn: 'domain_category', // top弹框查询字段
|
||||
icon: entityFilterType.domain[1].icon,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('entities.reputationLevel'),
|
||||
column: 'reputationLevelDistinctCount',
|
||||
topColumn: 'domainReputationLevel', // top弹框查询字段
|
||||
topColumn: 'domain_reputation_level', // top弹框查询字段
|
||||
icon: entityFilterType.domain[2].icon,
|
||||
value: 0
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
listData: []
|
||||
/* listData: JSON.parse(`[
|
||||
listData: [],
|
||||
listLoading: false/*,
|
||||
listData: JSON.parse(`[
|
||||
{
|
||||
"entityType": "app",
|
||||
"appName": "360cn",
|
||||
@@ -261,7 +262,7 @@ export default {
|
||||
"ipAsn": "",
|
||||
"ipLocationCountry": "China",
|
||||
"entityType": "ip",
|
||||
"ipLocation_province": "Other",
|
||||
"ipLocationProvince": "Other",
|
||||
"ipAddr": "116.178.30.96",
|
||||
"ipLocationCity": "Other"
|
||||
},
|
||||
@@ -490,6 +491,10 @@ export default {
|
||||
})
|
||||
},
|
||||
queryList (params) {
|
||||
this.timeout = setTimeout(() => {
|
||||
this.listLoading = true
|
||||
}, 500)
|
||||
this.listData = []
|
||||
const queryParams = {
|
||||
...params,
|
||||
startTime: parseInt(params.startTime / 1000),
|
||||
@@ -499,6 +504,9 @@ export default {
|
||||
if (response.code === 200) {
|
||||
this.listData = response.data.result
|
||||
}
|
||||
}).finally(() => {
|
||||
clearTimeout(this.timeout)
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
@@ -516,11 +524,16 @@ export default {
|
||||
},
|
||||
handleQ (params) {
|
||||
return Object.keys(params).map(param => {
|
||||
return `${param}="${params[param]}"`
|
||||
return `${param}='${params[param]}'`
|
||||
}).join(' AND ')
|
||||
},
|
||||
|
||||
getEntityIndexData () {
|
||||
const now = window.$dayJs.tz().valueOf()
|
||||
const timeFilter = {
|
||||
startTime: parseInt(now / 1000 - 3600),
|
||||
endTime: parseInt(now / 1000)
|
||||
}
|
||||
// Total
|
||||
get(api.entityTotal, { entityType: 'app' }).then(response => {
|
||||
if (response.code === 200) {
|
||||
@@ -538,33 +551,33 @@ export default {
|
||||
}
|
||||
})
|
||||
// New
|
||||
get(api.entityNew, { entityType: 'app' }).then(response => {
|
||||
get(api.entityNew, { entityType: 'app', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityAppNew = response.data.result
|
||||
}
|
||||
})
|
||||
get(api.entityNew, { entityType: 'domain' }).then(response => {
|
||||
get(api.entityNew, { entityType: 'domain', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityDomainNew = response.data.result
|
||||
}
|
||||
})
|
||||
get(api.entityNew, { entityType: 'ip' }).then(response => {
|
||||
get(api.entityNew, { entityType: 'ip', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityIpNew = response.data.result
|
||||
}
|
||||
})
|
||||
// Active
|
||||
get(api.entityActive, { entityType: 'app' }).then(response => {
|
||||
get(api.entityActive, { entityType: 'app', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityAppActive = response.data.result
|
||||
}
|
||||
})
|
||||
get(api.entityActive, { entityType: 'domain' }).then(response => {
|
||||
get(api.entityActive, { entityType: 'domain', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityDomainActive = response.data.result
|
||||
}
|
||||
})
|
||||
get(api.entityActive, { entityType: 'ip' }).then(response => {
|
||||
get(api.entityActive, { entityType: 'ip', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityIpActive = response.data.result
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
<entity-top
|
||||
v-show="showTopTen"
|
||||
ref="entityTopTenPop"
|
||||
:loading="loading"
|
||||
@filter="filter"
|
||||
@close="showTopTen = false"
|
||||
></entity-top>
|
||||
@@ -35,7 +36,7 @@
|
||||
import EntityTop from '@/components/entities/EntityTop'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
import { objToStr } from '@/utils/tools'
|
||||
export default {
|
||||
name: 'EntityFilter',
|
||||
components: {
|
||||
@@ -51,7 +52,8 @@ export default {
|
||||
topList: 'list',
|
||||
topData: [],
|
||||
showTopTen: false, // 自定义列弹框是否显示
|
||||
entityTopTenData: []
|
||||
entityTopTenData: [],
|
||||
loading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -60,8 +62,18 @@ export default {
|
||||
const width = this.$refs['entityTopTen' + i].offsetWidth
|
||||
const offsetLeft = this.$refs['entityTopTen' + i].offsetLeft
|
||||
const leftVal = offsetLeft + width
|
||||
|
||||
get(api.filterTop, { entityType: type, q: this.searchParams, column: item.topColumn, top: 10, ...this.timeFilter }).then(response => {
|
||||
const queryParams = {
|
||||
q: objToStr(this.searchParams),
|
||||
entityType: type,
|
||||
column: item.topColumn,
|
||||
top: 10,
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000)
|
||||
}
|
||||
this.timeout = setTimeout(() => {
|
||||
this.loading = true
|
||||
}, 500)
|
||||
get(api.filterTop, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.$refs.entityTopTenPop.initEntityTop(leftVal, item, response.data.result, filter.totalCount)
|
||||
} else {
|
||||
@@ -70,6 +82,8 @@ export default {
|
||||
}).catch(e => {
|
||||
this.$refs.entityTopTenPop.initEntityTop(leftVal, item, [], filter.totalCount)
|
||||
}).finally(() => {
|
||||
clearTimeout(this.timeout)
|
||||
this.loading = false
|
||||
this.showTopTen = true
|
||||
})
|
||||
},
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<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-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 0}} bps</div>
|
||||
<div class="body__detail" @click="entityDetail({ip: entityData.ipAddr, type: 4})">{{$t('overall.detail')}}></div>
|
||||
<div class="body__detail" @click="showDetail">{{$t('overall.detail')}}></div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'domain'">
|
||||
@@ -89,7 +89,7 @@
|
||||
<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-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 0}} bps</div>
|
||||
<div class="body__detail" @click="entityDetail({domain: entityData.domainName, type: 5})">{{$t('overall.detail')}}></div>
|
||||
<div class="body__detail" @click="showDetail">{{$t('overall.detail')}}></div>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'app'">
|
||||
@@ -103,7 +103,7 @@
|
||||
</div>
|
||||
<div class="body__row">
|
||||
<span class="body__row-label"><i class="cn-icon cn-icon-sub-category"></i>{{$t('entities.subcategory')}}:</span>
|
||||
<div class="body__row-value" :title="entityData.appSubategory">{{entityData.appSubategory || '-'}}</div>
|
||||
<div class="body__row-value" :title="entityData.appSubcategory">{{entityData.appSubcategory || '-'}}</div>
|
||||
</div>
|
||||
<div class="body__row">
|
||||
<span class="body__row-label"><i class="cn-icon cn-icon-entity-alert"></i>{{$t('entities.recentAlert')}}:</span>
|
||||
@@ -118,9 +118,9 @@
|
||||
<div class="body__drawing" :id="`entityListChart${entityData.appName}`"></div>
|
||||
</div>
|
||||
<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-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 0}} bps</div>
|
||||
<div class="body__detail" @click="entityDetail({app: entityData.appName, type: 6})">{{$t('overall.detail')}}></div>
|
||||
<div class="entity-statics-down"><i class="cn-icon cn-icon-fall entity-statics-icon"></i>{{entityData.bytesReceivedRate ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</div>
|
||||
<div class="entity-statics-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate ? unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</div>
|
||||
<div class="body__detail" @click="showDetail">{{$t('overall.detail')}}></div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
@@ -129,8 +129,16 @@
|
||||
|
||||
<script>
|
||||
import entityListMixin from './entityListMixin'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
export default {
|
||||
name: 'Card',
|
||||
mixins: [entityListMixin]
|
||||
mixins: [entityListMixin],
|
||||
setup () {
|
||||
return {
|
||||
unitTypes,
|
||||
unitConvert
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -66,12 +66,12 @@
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-rise"></i>
|
||||
<span>{{$t('entities.sentThroughput')}} : </span>
|
||||
<span>{{entityData.bytesSentRate || '-'}}</span>
|
||||
<span>{{entityData.bytesSentRate ? unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-fall"></i>
|
||||
<span>{{$t('entities.receivedThroughput')}} : </span>
|
||||
<span>{{entityData.bytesReceivedRate || '-'}}</span>
|
||||
<span>{{entityData.bytesReceivedRate ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-entity-alert"></i>
|
||||
@@ -97,6 +97,7 @@
|
||||
<el-divider></el-divider>
|
||||
<detail-overview
|
||||
:entity="entityData"
|
||||
:time-filter="timeFilter"
|
||||
></detail-overview>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
@@ -107,6 +108,8 @@
|
||||
<script>
|
||||
import entityListMixin from './entityListMixin'
|
||||
import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/DetailOverview'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
export default {
|
||||
name: 'Row',
|
||||
props: {
|
||||
@@ -122,6 +125,12 @@ export default {
|
||||
isCollapse: true // 是否是折叠状态
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
return {
|
||||
unitConvert,
|
||||
unitTypes
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* 切换折叠状态 */
|
||||
switchCollapse () {
|
||||
@@ -131,16 +140,6 @@ export default {
|
||||
/* 设为折叠状态 */
|
||||
collapse () {
|
||||
this.isCollapse = true
|
||||
},
|
||||
showDetail () {
|
||||
const { href } = this.$router.resolve({
|
||||
path: '/entityDetail',
|
||||
query: {
|
||||
entityType: this.entityData.entityType,
|
||||
name: this.entityData.ipAddr || this.entityData.domainName || this.entityData.appName
|
||||
}
|
||||
})
|
||||
window.open(href, '_blank')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,22 +25,22 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div>
|
||||
<div class="row__content">{{entityData.max}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.max, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div>
|
||||
<div class="row__content">{{entityData.avg}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.avg, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
|
||||
<div class="row__contents">
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{entityData.bytesSentRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailSend${entityData.appName}`" ></div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{entityData.bytesReceivedRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailReceived${entityData.appName}`" ></div>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.alertList && entityData.alertList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -98,23 +98,35 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.securityList && entityData.securityList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-map">
|
||||
<chart
|
||||
:chart="chart"
|
||||
:entity="entityCopy"
|
||||
:hide-header="true"
|
||||
@getCurrentTimeRange="getCurrentTimeRange"
|
||||
></chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api } from '@/utils/api'
|
||||
import entityDetailMixin from './entityDetailMixin'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import Chart from '@/views/charts/Chart'
|
||||
import _ from "lodash";
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
props: {
|
||||
// entity: Object
|
||||
},
|
||||
mixins: [entityDetailMixin],
|
||||
components: {
|
||||
Chart
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// entityData: {}
|
||||
@@ -125,16 +137,12 @@ export default {
|
||||
securityUrl: api.entityAppDetailSecurity,
|
||||
listMode: 'list'
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
},
|
||||
methods: {
|
||||
getQueryParams () {
|
||||
const now = new Date()
|
||||
const queryParams = {
|
||||
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||
endTime: Math.floor(now.getTime() / 1000),
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
appName: this.entityData.appName
|
||||
}
|
||||
return queryParams
|
||||
@@ -143,7 +151,23 @@ export default {
|
||||
this.entityData.domainCount = result.domainCount
|
||||
this.entityData.ipCount = result.ipCount
|
||||
}
|
||||
|
||||
},
|
||||
setup (props) {
|
||||
return {
|
||||
chart: {
|
||||
params: {
|
||||
url: '/interface/entity/detail/app/trafficMap?startTime={{startTime}}&endTime={{endTime}}&country={{country}}&appName={{appName}}',
|
||||
unitType: 'number',
|
||||
valueColumn: 'sessions'
|
||||
},
|
||||
type: 2
|
||||
},
|
||||
unitTypes,
|
||||
entityCopy: {
|
||||
..._.cloneDeep(props.entity)
|
||||
},
|
||||
unitConvert
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<template>
|
||||
<div class="entity-detail-overview">
|
||||
<template v-if="entity.entityType === 'ip'">
|
||||
<ip-overview :entity="entity"></ip-overview>
|
||||
<ip-overview :entity="entity" :time-filter="timeFilter"></ip-overview>
|
||||
</template>
|
||||
<template v-else-if="entity.entityType === 'domain'">
|
||||
<domain-overview :entity="entity"></domain-overview>
|
||||
<domain-overview :entity="entity" :time-filter="timeFilter"></domain-overview>
|
||||
</template>
|
||||
<template v-else-if="entity.entityType === 'app'">
|
||||
<app-overview :entity="entity"></app-overview>
|
||||
<app-overview :entity="entity" :time-filter="timeFilter"></app-overview>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -21,7 +21,8 @@ export default {
|
||||
/* 详情概览 */
|
||||
name: 'DetailOverview',
|
||||
props: {
|
||||
entity: Object
|
||||
entity: Object,
|
||||
timeFilter: Object
|
||||
},
|
||||
components: {
|
||||
'domain-overview': Domain,
|
||||
|
||||
@@ -33,22 +33,22 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div>
|
||||
<div class="row__content">{{entityData.max}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.max, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div>
|
||||
<div class="row__content">{{entityData.avg}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.avg, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
|
||||
<div class="row__contents">
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{entityData.bytesSentRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailSend${entityData.domainName}`" ></div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{entityData.bytesReceivedRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailReceived${entityData.domainName}`" ></div>
|
||||
</div>
|
||||
@@ -86,7 +86,7 @@
|
||||
<span>{{$t('entities.avgRoundTripTime')}}</span>
|
||||
</template>
|
||||
<template #data>
|
||||
<span>{{entityData.establishLatency?entityData.establishLatency+'ms':'-'}}</span>
|
||||
<span>{{entityData.establishLatency ? unitConvert(entityData.establishLatency, unitTypes.time).join(' ') : '-'}}</span>
|
||||
</template>
|
||||
</single-value>
|
||||
<single-value
|
||||
@@ -100,7 +100,7 @@
|
||||
<span>{{$t('entities.httpResponseLatency')}}</span>
|
||||
</template>
|
||||
<template #data>
|
||||
<span>{{entityData.httpResponseLatency?entityData.httpResponseLatency+'ms':'-'}}</span>
|
||||
<span>{{entityData.httpResponseLatency ? unitConvert(entityData.httpResponseLatency, unitTypes.time).join(' ') : '-'}}</span>
|
||||
</template>
|
||||
</single-value>
|
||||
<single-value
|
||||
@@ -114,7 +114,7 @@
|
||||
<span>{{$t('entities.sslConLatency')}}</span>
|
||||
</template>
|
||||
<template #data>
|
||||
<span>{{entityData.sslConLatency?entityData.sslConLatency+'ms':'-'}}</span>
|
||||
<span>{{entityData.sslConLatency ? unitConvert(entityData.sslConLatency, unitTypes.time).join(' ') : '-'}}</span>
|
||||
</template>
|
||||
</single-value>
|
||||
<single-value
|
||||
@@ -128,7 +128,7 @@
|
||||
<span>{{$t('entities.sequenceGapLossPercent')}}</span>
|
||||
</template>
|
||||
<template #data>
|
||||
<span>{{entityData.sequenceGapLossPercent?entityData.sequenceGapLossPercent+'%':'-'}}</span>
|
||||
<span>{{entityData.sequenceGapLossPercent ? unitConvert(entityData.sequenceGapLossPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</template>
|
||||
</single-value>
|
||||
<single-value
|
||||
@@ -142,7 +142,7 @@
|
||||
<span>{{$t('entities.pktRetransPercent')}}</span>
|
||||
</template>
|
||||
<template #data>
|
||||
<span>{{entityData.pktRetransPercent?entityData.pktRetransPercent+'%':'-'}}</span>
|
||||
<span>{{entityData.pktRetransPercent ? unitConvert(entityData.pktRetransPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</template>
|
||||
</single-value>
|
||||
</div>
|
||||
@@ -154,11 +154,11 @@
|
||||
<div class="overview__tags">
|
||||
<div class="overview__tag">
|
||||
<span class="tag__desc">{{$t('entities.outLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutPercent?entityData.linkOutPercent+'%':'-'}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') + '%' : '-'}}</span>
|
||||
</div>
|
||||
<div class="overview__tag">
|
||||
<span class="tag__desc">{{$t('entities.inLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInPercent?entityData.linkInPercent+'%':'-'}}</span>
|
||||
<span class="tag__value">{{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') + '%' : '-'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -178,7 +178,7 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.alertList && entityData.alertList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -198,25 +198,34 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.securityList && entityData.securityList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-map">
|
||||
<chart
|
||||
:chart="chart"
|
||||
:entity="entityCopy"
|
||||
:hide-header="true"
|
||||
@getCurrentTimeRange="getCurrentTimeRange"
|
||||
></chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SingleValue from '@/components/charts/ChartSingleValue'
|
||||
import { api } from '@/utils/api'
|
||||
import entityDetailMixin from './entityDetailMixin'
|
||||
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import Chart from '@/views/charts/Chart'
|
||||
import _ from "lodash";
|
||||
export default {
|
||||
name: 'Domain',
|
||||
components: {
|
||||
SingleValue
|
||||
},
|
||||
props: {
|
||||
entity: Object
|
||||
SingleValue,
|
||||
Chart
|
||||
},
|
||||
mixins: [entityDetailMixin],
|
||||
data () {
|
||||
@@ -235,10 +244,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getQueryParams () {
|
||||
const now = new Date()
|
||||
const queryParams = {
|
||||
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||
endTime: Math.floor(now.getTime() / 1000),
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
domain: this.entityData.domainName
|
||||
}
|
||||
return queryParams
|
||||
@@ -247,6 +255,25 @@ export default {
|
||||
this.entityData.appCount = result.appCount
|
||||
this.entityData.ipCount = result.ipCount
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const entityCopy = {
|
||||
..._.cloneDeep(props.entity),
|
||||
domain: props.entity.domainName
|
||||
}
|
||||
return {
|
||||
chart: {
|
||||
params: {
|
||||
url: '/interface/entity/detail/domain/trafficMap?startTime={{startTime}}&endTime={{endTime}}&country={{country}}&domain={{domain}}',
|
||||
unitType: 'number',
|
||||
valueColumn: 'sessions'
|
||||
},
|
||||
type: 2
|
||||
},
|
||||
entityCopy,
|
||||
unitTypes,
|
||||
unitConvert
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -17,22 +17,22 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div>
|
||||
<div class="row__content">{{entityData.max}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.max, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div>
|
||||
<div class="row__content">{{entityData.avg}} Kb/s</div>
|
||||
<div class="row__content">{{unitConvert(entityData.avg, unitTypes.byte).join(' ')}}/s</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
|
||||
<div class="row__contents">
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{entityData.bytesSentRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailSend${entityData.ipAddr}`"></div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{entityData.bytesReceivedRate}}bps</div>
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__charts" :id="`entityDetailReceived${entityData.ipAddr}`"></div>
|
||||
</div>
|
||||
@@ -70,7 +70,7 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.alertList && entityData.alertList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -90,20 +90,35 @@
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font">
|
||||
<div class="overview__row overview__row--small-font" v-if="entityData.securityList && entityData.securityList.length > 3">
|
||||
<div class="show-more">{{$t('overall.showMore')}}>></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-map">
|
||||
<chart
|
||||
:chart="chart"
|
||||
:entity="entityCopy"
|
||||
:hide-header="true"
|
||||
@getCurrentTimeRange="getCurrentTimeRange"
|
||||
></chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import entityDetailMixin from './entityDetailMixin'
|
||||
import { api } from '@/utils/api'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import Chart from '@/views/charts/Chart'
|
||||
import _ from "lodash";
|
||||
|
||||
export default {
|
||||
name: 'Ip',
|
||||
mixins: [entityDetailMixin],
|
||||
components: {
|
||||
Chart
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// entityData: {}
|
||||
@@ -117,10 +132,9 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getQueryParams () {
|
||||
const now = new Date()
|
||||
const queryParams = {
|
||||
startTime: Math.floor(now.getTime() / 1000 - 3600),
|
||||
endTime: Math.floor(now.getTime() / 1000),
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
ip: this.entityData.ipAddr
|
||||
}
|
||||
return queryParams
|
||||
@@ -129,6 +143,25 @@ export default {
|
||||
this.entityData.appCount = result.appCount
|
||||
this.entityData.domainCount = result.domainCount
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
const entityCopy = {
|
||||
..._.cloneDeep(props.entity),
|
||||
ip: props.entity.ipAddr
|
||||
}
|
||||
return {
|
||||
chart: {
|
||||
params: {
|
||||
url: '/interface/entity/detail/ip/trafficMap?startTime={{startTime}}&endTime={{endTime}}&country={{country}}&ip={{ip}}',
|
||||
unitType: 'number',
|
||||
valueColumn: 'sessions'
|
||||
},
|
||||
type: 2
|
||||
},
|
||||
entityCopy,
|
||||
unitTypes,
|
||||
unitConvert
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -3,10 +3,12 @@ import { get } from '@/utils/http'
|
||||
import * as echarts from 'echarts'
|
||||
import { entityListLineOption } from '@/components/charts/chart-options'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
|
||||
export default {
|
||||
props: {
|
||||
entity: Object
|
||||
entity: Object,
|
||||
timeFilter: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -46,11 +48,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCurrentTimeRange (callback) {
|
||||
const myEndTime = window.$dayJs.tz().valueOf()
|
||||
const myStartTime = myEndTime - this.timeFilter.dateRangeValue * 60 * 1000
|
||||
callback({ startTime: myStartTime, endTime: myEndTime })
|
||||
},
|
||||
queryEntityDetailTraffic () {
|
||||
this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`))
|
||||
this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`))
|
||||
get(this.trafficUrl, this.getQueryParams()).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (response.code === 200 && response.data.result && response.data.result.length > 0) {
|
||||
response.data.result.forEach(t => {
|
||||
if (t.legend === 'bytesRate') {
|
||||
this.entityData.max = t.aggregation.max
|
||||
@@ -101,15 +108,17 @@ export default {
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
this.sentChart.setOption(this.chartOptionSent)
|
||||
this.receivedChart.setOption(this.chartOptionReceived)
|
||||
}
|
||||
}).finally(() => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
this.$nextTick(() => {
|
||||
this.sentChart && this.sentChart.resize()
|
||||
this.receivedChart && this.receivedChart.resize()
|
||||
})
|
||||
} catch (e) {}
|
||||
}, 250)
|
||||
})
|
||||
},
|
||||
@@ -192,7 +201,9 @@ export default {
|
||||
},
|
||||
setup () {
|
||||
return {
|
||||
chartOption: entityListLineOption
|
||||
chartOption: entityListLineOption,
|
||||
unitTypes,
|
||||
unitConvert
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
|
||||
@@ -77,7 +77,7 @@ export default {
|
||||
},
|
||||
queryParams () {
|
||||
let params
|
||||
const now = new Date()
|
||||
const now = window.$dayJs.tz().valueOf()
|
||||
switch (this.entityData.entityType) {
|
||||
case ('ip'): {
|
||||
params = {
|
||||
@@ -115,11 +115,24 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
entityDetail (entity) {
|
||||
|
||||
showDetail () {
|
||||
const { href } = this.$router.resolve({
|
||||
path: '/entityDetail',
|
||||
query: {
|
||||
entityType: this.entityData.entityType,
|
||||
name: this.entityData.ipAddr || this.entityData.domainName || this.entityData.appName
|
||||
}
|
||||
})
|
||||
window.open(href, '_blank')
|
||||
},
|
||||
queryTraffic () {
|
||||
get(api.entityTraffic, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||
const queryParams = {
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
entityType: this.entityData.entityType,
|
||||
name: this.entityName
|
||||
}
|
||||
get(api.entityTraffic, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
response.data.result.forEach(t => {
|
||||
if (t.name === 'bytes_sent_rate') {
|
||||
@@ -133,14 +146,26 @@ export default {
|
||||
})
|
||||
},
|
||||
querySecurity () {
|
||||
get(api.entitySecurityNum, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||
const queryParams = {
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
entityType: this.entityData.entityType,
|
||||
name: this.entityName
|
||||
}
|
||||
get(api.entitySecurityNum, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityData.securityCount = response.data.result[0].count
|
||||
}
|
||||
})
|
||||
},
|
||||
queryAlert () {
|
||||
get(api.entityAlertNum, { entityType: this.entityData.entityType, name: this.entityName }).then(response => {
|
||||
const queryParams = {
|
||||
startTime: parseInt(this.timeFilter.startTime / 1000),
|
||||
endTime: parseInt(this.timeFilter.endTime / 1000),
|
||||
entityType: this.entityData.entityType,
|
||||
name: this.entityName
|
||||
}
|
||||
get(api.entityAlertNum, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityData.alertCount = response.data.result[0].value
|
||||
}
|
||||
@@ -211,6 +236,7 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
return {}
|
||||
})
|
||||
chartOption = {
|
||||
...this.chartOption,
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
<span>{{$t('search.searchHistory')}}</span>
|
||||
</div>
|
||||
<div class="foot__item">
|
||||
<span @click="search">{{$t('overall.explore')}}</span>
|
||||
<span @click="search({})">{{$t('overall.explore')}}</span>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<span>{{$t('overall.help')}}</span>
|
||||
</div>
|
||||
@@ -41,7 +41,7 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search (params) {
|
||||
search (params = {}) {
|
||||
this.$emit('search', params)
|
||||
},
|
||||
addParams (params) {
|
||||
|
||||
Reference in New Issue
Block a user