CN-240 feat: 实体列表、详情细节完善

This commit is contained in:
chenjinsong
2022-01-05 23:56:27 +08:00
parent db27d6213f
commit 6e9b208818
24 changed files with 403 additions and 174 deletions

View File

@@ -7,6 +7,20 @@
justify-content: center; justify-content: center;
transition: all linear .2s; 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 { &.entity-explorer--show-list {
background-color: unset; background-color: unset;
justify-content: flex-start; justify-content: flex-start;

View File

@@ -4,6 +4,22 @@
flex-direction: column; flex-direction: column;
padding: 0 30px; 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 { .overview-item {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -84,12 +100,13 @@
} }
} }
.row__charts-msg { .row__charts-msg {
width:105px; width: auto;
padding-right: 20px;
} }
.row__charts { .row__charts {
height:20px; height: 20px;
width:60px; width: 60px;
padding-left:5px; padding-left: 5px;
} }
} }
.row__desc { .row__desc {

View File

@@ -1,6 +1,7 @@
.entity-list { .entity-list {
width: calc(100% - 290px); width: calc(100% - 290px);
flex: 1; flex: 1;
position: relative;
.entity-list__content { .entity-list__content {
height: 100%; height: 100%;
@@ -29,6 +30,7 @@
width: 100vw; width: 100vw;
left: 0; left: 0;
top: 0; top: 0;
z-index: 1;
background-color: rgba(0, 0, 0, .2); background-color: rgba(0, 0, 0, .2);
} }
} }

View File

@@ -10,7 +10,7 @@
<div class="search__suffix"> <div class="search__suffix">
<i class="cn-icon cn-icon-search-advance"></i> <i class="cn-icon cn-icon-search-advance"></i>
</div> </div>
<div class="search__suffix" @click="search"> <div class="search__suffix" @click="enter">
<i class="el-icon-search"></i> <i class="el-icon-search"></i>
</div> </div>
</div> </div>
@@ -18,7 +18,7 @@
<div class="search__suffix"> <div class="search__suffix">
<i class="cn-icon cn-icon-search-advance"></i> <i class="cn-icon cn-icon-search-advance"></i>
</div> </div>
<div class="search__suffix" @click="search"> <div class="search__suffix" @click="enter">
<i class="el-icon-search"></i> <i class="el-icon-search"></i>
</div> </div>
</div> </div>
@@ -28,6 +28,7 @@
</template> </template>
<script> <script>
import { objToStr, strToObj } from '@/utils/tools'
export default { export default {
name: 'AdvancedSearch', name: 'AdvancedSearch',
props: { props: {
@@ -54,31 +55,10 @@ export default {
addParams (params) { addParams (params) {
if (params) { if (params) {
const newParams = { ...this.searchParams, ...params } const newParams = { ...this.searchParams, ...params }
this.searchContentTemp = this.objToStr(newParams) this.searchContentTemp = objToStr(newParams)
this.enter() 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 () { enter () {
if (!this.searchContentTemp) { if (!this.searchContentTemp) {
this.reset() this.reset()
@@ -90,7 +70,7 @@ export default {
watch: { watch: {
searchContent (n) { searchContent (n) {
if (n) { if (n) {
this.searchParams = this.strToObj(n) this.searchParams = strToObj(n)
} else { } else {
this.reset() this.reset()
} }

View File

@@ -2,10 +2,10 @@
<div class="cn-chart cn-chart__map"> <div class="cn-chart cn-chart__map">
<div class="cn-chart__header chart-header-position" > <div class="cn-chart__header chart-header-position" >
<slot name="chartErrorInfo"></slot> <slot name="chartErrorInfo"></slot>
<div class="header__title" > <div class="header__title" v-if="!hideHeader">
<slot name="title"></slot> <slot name="title"></slot>
</div> </div>
<div class="header__operations"> <div class="header__operations" v-if="!hideHeader">
<slot name="operations"></slot> <slot name="operations"></slot>
</div> </div>
</div> </div>
@@ -26,7 +26,8 @@
export default { export default {
name: 'ChartMap', name: 'ChartMap',
props: { props: {
loading: Boolean loading: Boolean,
hideHeader: Boolean
}, },
data () { data () {
return { return {

View File

@@ -15,7 +15,7 @@
<slot name="title"></slot> <slot name="title"></slot>
</div> </div>
</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"> <div class="content__title">
<slot name="title"></slot> <slot name="title"></slot>
</div> </div>
@@ -72,6 +72,7 @@ export default {
c = 'cn-chart__single-value--icon-left' c = 'cn-chart__single-value--icon-left'
break break
} }
case 55:
case 52: { case 52: {
c = 'cn-chart__single-value--chart' c = 'cn-chart__single-value--chart'
break break

View File

@@ -652,6 +652,10 @@ export function isSingleValue (type) {
export function isSingleValueWithEcharts (type) { export function isSingleValueWithEcharts (type) {
return type === 52 return type === 52
} }
/* 带折线图的单值 */
export function isSingleValueWithEchartsTemp (type) {
return type === 55
}
/* 带Table的饼图 */ /* 带Table的饼图 */
export function isEchartsWithTable (type) { export function isEchartsWithTable (type) {
return type === 31 return type === 31

View File

@@ -226,7 +226,7 @@ export default {
if (!this.$_.isEmpty(n) && !this.$_.isEqual(n, o)) { if (!this.$_.isEmpty(n) && !this.$_.isEqual(n, o)) {
this.entityList = [] this.entityList = []
setTimeout(() => { 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) } const queryParams = { startTime: Math.floor(now.getTime() / 1000 - 3600), endTime: Math.floor(now.getTime() / 1000) }
switch (this.from) { switch (this.from) {
case ('ip'): { case ('ip'): {

View File

@@ -9,6 +9,9 @@
</div> </div>
<div class="filter-top-box" > <div class="filter-top-box" >
<div class="filter-top-body"> <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> <div class="filter-top-type">{{item.value}}{{$t('overall.operator')}}{{item.label}}</div>
<el-table <el-table
:data="entityTopTenData" :data="entityTopTenData"
@@ -44,6 +47,7 @@
<script> <script>
export default { export default {
props: { props: {
loading: Boolean
}, },
data () { data () {
return { return {

View File

@@ -19,7 +19,8 @@ export default {
delete: false, delete: false,
refresh: false, refresh: false,
query: false query: false
} },
timeout: null
} }
}, },
methods: { methods: {
@@ -51,6 +52,9 @@ export default {
}, },
utcTimeToLocalhost (str) { // 系统设置的时区 到 utc 0 utcTimeToLocalhost (str) { // 系统设置的时区 到 utc 0
return str return str
},
parseMsDate (ms, format = 'YYYY-MM-DD HH:mm:ss') {
return this.dayJs.tz(parseFloat(ms)).format(format)
} }
} }
} }

View File

@@ -443,7 +443,29 @@ export function lineToSpace (name) {
export function humpToLine (name) { export function humpToLine (name) {
return name.replace(/([A-Z])/g, '_$1').toLowerCase() 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数据 // 加载geo数据
export function loadGeoData (key) { export function loadGeoData (key) {
const keys = [] const keys = []

View File

@@ -37,6 +37,7 @@
v-else-if="isMap" v-else-if="isMap"
:style="computePosition" :style="computePosition"
:loading="loading" :loading="loading"
:hide-header="hideHeader"
> >
<template #chartErrorInfo> <template #chartErrorInfo>
<chart-error <chart-error
@@ -58,11 +59,11 @@
<template #default> <template #default>
<template v-if="isIpBasicInfo"> <template v-if="isIpBasicInfo">
<el-descriptions :column="1"> <el-descriptions :column="1">
<el-descriptions-item label="ASN:">{{detailData ? detailData.asn : '-'}}</el-descriptions-item> <el-descriptions-item label="ASN:">{{detailData.asn || '-'}}</el-descriptions-item>
<el-descriptions-item label="AS Org:">{{detailData ? detailData.asnOrg : '-'}}</el-descriptions-item> <el-descriptions-item label="AS Org:">{{detailData.asOrganization || '-'}}</el-descriptions-item>
<el-descriptions-item :label="$t('entities.asSubnet') + ':'">{{detailData.asnSubnet || '-'}}</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="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> </el-descriptions>
<div class="chart-location"> <div class="chart-location">
<el-descriptions :column="1"> <el-descriptions :column="1">
@@ -434,7 +435,7 @@
<div class="domain-detail-list"> <div class="domain-detail-list">
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.sponsor')}}</div> <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>
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.org')}}</div> <div class="domain-detail-list__label">{{$t('entities.org')}}</div>
@@ -442,19 +443,19 @@
</div> </div>
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">Email</div> <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>
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('overall.country')}}</div> <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>
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.creationDate')}}</div> <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>
<div class="domain-detail-list__row"> <div class="domain-detail-list__row">
<div class="domain-detail-list__label">{{$t('entities.expirationDate')}}</div> <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> </div>
</div> </div>
@@ -627,6 +628,7 @@ import {
isMapLine, isMapLine,
isMapBlock, isMapBlock,
isSingleValueWithEcharts, isSingleValueWithEcharts,
isSingleValueWithEchartsTemp,
isRelationShip, isRelationShip,
isTabs, isTabs,
isGroup, isGroup,
@@ -672,6 +674,7 @@ export default {
timeFilter: Object, timeFilter: Object,
parentData: Object, parentData: Object,
fromBlock: Boolean, fromBlock: Boolean,
hideHeader: Boolean,
entity: { entity: {
type: Object, type: Object,
default: () => {} default: () => {}
@@ -871,6 +874,7 @@ export default {
}) })
this.myChart.setOption(this.chartOption) this.myChart.setOption(this.chartOption)
this.singleValue.value = result[0].values[result[0].values.length - 1][1] 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 queryParams = { startTime: parseInt(this.timeFilter.startTime / 1000), endTime: parseInt(this.timeFilter.endTime / 1000), ...this.entity }
const dom = document.getElementById(`chart${this.chartInfo.id}`) const dom = document.getElementById(`chart${this.chartInfo.id}`)
!this.myChart && (this.myChart = echarts.init(dom)) !this.myChart && (this.myChart = echarts.init(dom))
@@ -969,7 +973,7 @@ export default {
setTimeout(() => { this.loading = false }, 250) setTimeout(() => { this.loading = false }, 250)
}) })
} else if (this.isAppBasicInfo) { } else if (this.isAppBasicInfo) {
const queryParams = { app: this.entity.app } const queryParams = { appName: this.entity.appName }
get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => { get(replaceUrlPlaceholder(chartParams.url, queryParams)).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.detailData = response.data.result this.detailData = response.data.result
@@ -1135,6 +1139,7 @@ export default {
} }
}) })
console.info(this.entity)
this.showMapBackButton = !!country this.showMapBackButton = !!country
const chartParams = this.chartInfo.params const chartParams = this.chartInfo.params
const queryParams = { ...this.queryTimeRange, country: country || '', region: '', ...this.entity } // 统计数据的查询参数 const queryParams = { ...this.queryTimeRange, country: country || '', region: '', ...this.entity } // 统计数据的查询参数
@@ -1321,16 +1326,13 @@ export default {
}, },
// 获取最新时间 // 获取最新时间
getChartCurrentTimeRange (callback) { getChartCurrentTimeRange (callback) {
console.info(this.isGroup)
if (this.isGroup) { if (this.isGroup) {
this.$emit('getChartCurrentTimeRange', ({ startTime, endTime }) => { this.$emit('getChartCurrentTimeRange', ({ startTime, endTime }) => {
console.info(startTime, endTime)
callback({ startTime, endTime }) callback({ startTime, endTime })
}) })
} else { } else {
const myEndTime = window.$dayJs.tz().valueOf() const myEndTime = window.$dayJs.tz().valueOf()
const myStartTime = myEndTime - this.chartTimeFilter.dateRangeValue * 60 * 1000 const myStartTime = myEndTime - this.chartTimeFilter.dateRangeValue * 60 * 1000
console.info(myStartTime, myEndTime)
callback({ startTime: myStartTime, endTime: myEndTime }) callback({ startTime: myStartTime, endTime: myEndTime })
} }
}, },
@@ -1820,7 +1822,7 @@ export default {
] ]
this.myChart.setOption(this.chartOption) this.myChart.setOption(this.chartOption)
this.myChart2.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 (response.code === 200) {
if (this.$_.isEmpty(response.data.result)) { if (this.$_.isEmpty(response.data.result)) {
this.noData = true this.noData = true
@@ -2476,12 +2478,22 @@ export default {
if (this.detailData) { if (this.detailData) {
if (this.detailData.country) { if (this.detailData.country) {
location = this.detailData.country location = this.detailData.country
if (this.detailData.region) { if (this.detailData.province) {
location += ', ' location += ', '
location += this.detailData.region location += this.detailData.province
if (this.detailData.city) {
location += ', '
location += this.detailData.city
}
} }
} else if (this.detailData.region) { } else if (this.detailData.province) {
location = this.detailData.region location = this.detailData.province
if (this.detailData.city) {
location += ', '
location += this.detailData.city
}
} else if (this.detailData.city) {
location = this.detailData.city
} }
} }
return location return location
@@ -2505,6 +2517,8 @@ export default {
} }
}, },
mounted () { mounted () {
console.info(this.chart)
console.info(this.entity)
this.initChart() this.initChart()
this.throttle = this.$_.throttle(this.echartsResize, 500) this.throttle = this.$_.throttle(this.echartsResize, 500)
window.addEventListener('resize', this.throttle) window.addEventListener('resize', this.throttle)
@@ -2565,6 +2579,7 @@ export default {
isEchartsWithStatistics: isEchartsWithStatistics(props.chart.type), isEchartsWithStatistics: isEchartsWithStatistics(props.chart.type),
isSingleValue: isSingleValue(props.chart.type), isSingleValue: isSingleValue(props.chart.type),
isSingleValueWithEcharts: isSingleValueWithEcharts(props.chart.type), isSingleValueWithEcharts: isSingleValueWithEcharts(props.chart.type),
isSingleValueWithEchartsTemp: isSingleValueWithEchartsTemp(props.chart.type),
isRelationShip: isRelationShip(props.chart.type), isRelationShip: isRelationShip(props.chart.type),
isTable: isTable(props.chart.type), isTable: isTable(props.chart.type),
isActiveIpTable: isActiveIpTable(props.chart.type), isActiveIpTable: isActiveIpTable(props.chart.type),

View File

@@ -36,7 +36,9 @@ export default {
data () { data () {
return { return {
anchorPoints: [], // { id, label, top, height } anchorPoints: [], // { id, label, top, height }
top: 0 top: 0,
scrollHeight: 0,
clientHeight: 0
} }
}, },
setup (props, ctx) { setup (props, ctx) {
@@ -73,6 +75,9 @@ export default {
chartLoaded (chartList) { chartLoaded (chartList) {
this.anchorPoints = [] this.anchorPoints = []
let anchorPoints = [] let anchorPoints = []
const panelDom = document.querySelector('#cn-panel')
this.scrollHeight = panelDom.scrollHeight
this.clientHeight = panelDom.clientHeight
chartList.forEach(chart => { chartList.forEach(chart => {
if (chart.params.anchorPoint) { if (chart.params.anchorPoint) {
const dom = document.querySelector(`#${chart.params.anchorPoint}`) const dom = document.querySelector(`#${chart.params.anchorPoint}`)
@@ -128,11 +133,15 @@ export default {
}, },
currentAnchor () { currentAnchor () {
let currentAnchor = null let currentAnchor = null
this.anchorPoints.forEach(anchor => { if (this.top + this.clientHeight === this.scrollHeight) {
if (anchor.top <= this.top) { currentAnchor = this.anchorPoints[this.anchorPoints.length - 1]
currentAnchor = anchor } else {
} this.anchorPoints.forEach(anchor => {
}) if (anchor.top <= this.top) {
currentAnchor = anchor
}
})
}
return currentAnchor return currentAnchor
} }
} }

View File

@@ -33,6 +33,7 @@
:time-filter="timeFilter" :time-filter="timeFilter"
@pageSize="pageSize" @pageSize="pageSize"
@pageNo="pageNo" @pageNo="pageNo"
:loading="listLoading"
></entity-list> ></entity-list>
</div> </div>
<div class="explorer-foot" v-else> <div class="explorer-foot" v-else>
@@ -145,7 +146,6 @@ export default {
pageSize: defaultPageSize, pageSize: defaultPageSize,
total: 0 total: 0
}, },
timeFilter: {},
filterData: [ filterData: [
{ {
type: 'ip', type: 'ip',
@@ -155,28 +155,28 @@ export default {
{ {
label: this.$t('overall.country'), label: this.$t('overall.country'),
column: 'countryDistinctCount', column: 'countryDistinctCount',
topColumn: 'ipLocationCountry', // top弹框查询字段 topColumn: 'ip_location_country', // top弹框查询字段
icon: entityFilterType.ip[0].icon, icon: entityFilterType.ip[0].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('overall.province'), label: this.$t('overall.province'),
column: 'provinceDistinctCount', column: 'provinceDistinctCount',
topColumn: 'ipLocationProvince', // top弹框查询字段 topColumn: 'ip_location_province', // top弹框查询字段
icon: entityFilterType.ip[1].icon, icon: entityFilterType.ip[1].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('overall.city'), label: this.$t('overall.city'),
column: 'cityDistinctCount', column: 'cityDistinctCount',
topColumn: 'ipLocationCity', // top弹框查询字段 topColumn: 'ip_location_city', // top弹框查询字段
icon: entityFilterType.ip[2].icon, icon: entityFilterType.ip[2].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('entities.asn'), label: this.$t('entities.asn'),
column: 'asnDistinctCount', column: 'asnDistinctCount',
topColumn: 'ipAsn', // top弹框查询字段 topColumn: 'ip_asn', // top弹框查询字段
icon: entityFilterType.ip[3].icon, icon: entityFilterType.ip[3].icon,
value: 0 value: 0
} }
@@ -190,21 +190,21 @@ export default {
{ {
label: this.$t('entities.category'), label: this.$t('entities.category'),
column: 'categoryDistinctCount', column: 'categoryDistinctCount',
topColumn: 'appCategory', // top弹框查询字段 topColumn: 'app_category', // top弹框查询字段
icon: entityFilterType.app[0].icon, icon: entityFilterType.app[0].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('entities.subcategory'), label: this.$t('entities.subcategory'),
column: 'subcategoryDistinctCount', column: 'subcategoryDistinctCount',
topColumn: 'appSubcategory', // top弹框查询字段 topColumn: 'app_subcategory', // top弹框查询字段
icon: entityFilterType.app[1].icon, icon: entityFilterType.app[1].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('entities.risk'), label: this.$t('entities.risk'),
column: 'riskDistinctCount', column: 'riskDistinctCount',
topColumn: 'appRisk', // top弹框查询字段 topColumn: 'app_risk', // top弹框查询字段
icon: entityFilterType.app[2].icon, icon: entityFilterType.app[2].icon,
value: 0 value: 0
} }
@@ -218,29 +218,30 @@ export default {
{ {
label: this.$t('entities.domainDetail.categoryGroup'), label: this.$t('entities.domainDetail.categoryGroup'),
column: 'categoryGroupDistinctCount', column: 'categoryGroupDistinctCount',
topColumn: 'domainCategoryGroup', // top弹框查询字段 topColumn: 'domain_category_group', // top弹框查询字段
icon: entityFilterType.domain[0].icon, icon: entityFilterType.domain[0].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('entities.category'), label: this.$t('entities.category'),
column: 'categoryDistinctCount', column: 'categoryDistinctCount',
topColumn: 'domainCategory', // top弹框查询字段 topColumn: 'domain_category', // top弹框查询字段
icon: entityFilterType.domain[1].icon, icon: entityFilterType.domain[1].icon,
value: 0 value: 0
}, },
{ {
label: this.$t('entities.reputationLevel'), label: this.$t('entities.reputationLevel'),
column: 'reputationLevelDistinctCount', column: 'reputationLevelDistinctCount',
topColumn: 'domainReputationLevel', // top弹框查询字段 topColumn: 'domain_reputation_level', // top弹框查询字段
icon: entityFilterType.domain[2].icon, icon: entityFilterType.domain[2].icon,
value: 0 value: 0
} }
] ]
} }
], ],
listData: [] listData: [],
/* listData: JSON.parse(`[ listLoading: false/*,
listData: JSON.parse(`[
{ {
"entityType": "app", "entityType": "app",
"appName": "360cn", "appName": "360cn",
@@ -261,7 +262,7 @@ export default {
"ipAsn": "", "ipAsn": "",
"ipLocationCountry": "China", "ipLocationCountry": "China",
"entityType": "ip", "entityType": "ip",
"ipLocation_province": "Other", "ipLocationProvince": "Other",
"ipAddr": "116.178.30.96", "ipAddr": "116.178.30.96",
"ipLocationCity": "Other" "ipLocationCity": "Other"
}, },
@@ -490,6 +491,10 @@ export default {
}) })
}, },
queryList (params) { queryList (params) {
this.timeout = setTimeout(() => {
this.listLoading = true
}, 500)
this.listData = []
const queryParams = { const queryParams = {
...params, ...params,
startTime: parseInt(params.startTime / 1000), startTime: parseInt(params.startTime / 1000),
@@ -499,6 +504,9 @@ export default {
if (response.code === 200) { if (response.code === 200) {
this.listData = response.data.result this.listData = response.data.result
} }
}).finally(() => {
clearTimeout(this.timeout)
this.listLoading = false
}) })
}, },
@@ -516,11 +524,16 @@ export default {
}, },
handleQ (params) { handleQ (params) {
return Object.keys(params).map(param => { return Object.keys(params).map(param => {
return `${param}="${params[param]}"` return `${param}='${params[param]}'`
}).join(' AND ') }).join(' AND ')
}, },
getEntityIndexData () { getEntityIndexData () {
const now = window.$dayJs.tz().valueOf()
const timeFilter = {
startTime: parseInt(now / 1000 - 3600),
endTime: parseInt(now / 1000)
}
// Total // Total
get(api.entityTotal, { entityType: 'app' }).then(response => { get(api.entityTotal, { entityType: 'app' }).then(response => {
if (response.code === 200) { if (response.code === 200) {
@@ -538,33 +551,33 @@ export default {
} }
}) })
// New // New
get(api.entityNew, { entityType: 'app' }).then(response => { get(api.entityNew, { entityType: 'app', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityAppNew = response.data.result this.entityAppNew = response.data.result
} }
}) })
get(api.entityNew, { entityType: 'domain' }).then(response => { get(api.entityNew, { entityType: 'domain', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityDomainNew = response.data.result this.entityDomainNew = response.data.result
} }
}) })
get(api.entityNew, { entityType: 'ip' }).then(response => { get(api.entityNew, { entityType: 'ip', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityIpNew = response.data.result this.entityIpNew = response.data.result
} }
}) })
// Active // Active
get(api.entityActive, { entityType: 'app' }).then(response => { get(api.entityActive, { entityType: 'app', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityAppActive = response.data.result this.entityAppActive = response.data.result
} }
}) })
get(api.entityActive, { entityType: 'domain' }).then(response => { get(api.entityActive, { entityType: 'domain', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityDomainActive = response.data.result this.entityDomainActive = response.data.result
} }
}) })
get(api.entityActive, { entityType: 'ip' }).then(response => { get(api.entityActive, { entityType: 'ip', ...timeFilter }).then(response => {
if (response.code === 200) { if (response.code === 200) {
this.entityIpActive = response.data.result this.entityIpActive = response.data.result
} }

View File

@@ -22,6 +22,7 @@
<entity-top <entity-top
v-show="showTopTen" v-show="showTopTen"
ref="entityTopTenPop" ref="entityTopTenPop"
:loading="loading"
@filter="filter" @filter="filter"
@close="showTopTen = false" @close="showTopTen = false"
></entity-top> ></entity-top>
@@ -35,7 +36,7 @@
import EntityTop from '@/components/entities/EntityTop' import EntityTop from '@/components/entities/EntityTop'
import { get } from '@/utils/http' import { get } from '@/utils/http'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import { objToStr } from '@/utils/tools'
export default { export default {
name: 'EntityFilter', name: 'EntityFilter',
components: { components: {
@@ -51,7 +52,8 @@ export default {
topList: 'list', topList: 'list',
topData: [], topData: [],
showTopTen: false, // 自定义列弹框是否显示 showTopTen: false, // 自定义列弹框是否显示
entityTopTenData: [] entityTopTenData: [],
loading: false
} }
}, },
methods: { methods: {
@@ -60,8 +62,18 @@ export default {
const width = this.$refs['entityTopTen' + i].offsetWidth const width = this.$refs['entityTopTen' + i].offsetWidth
const offsetLeft = this.$refs['entityTopTen' + i].offsetLeft const offsetLeft = this.$refs['entityTopTen' + i].offsetLeft
const leftVal = offsetLeft + width const leftVal = offsetLeft + width
const queryParams = {
get(api.filterTop, { entityType: type, q: this.searchParams, column: item.topColumn, top: 10, ...this.timeFilter }).then(response => { 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) { if (response.code === 200) {
this.$refs.entityTopTenPop.initEntityTop(leftVal, item, response.data.result, filter.totalCount) this.$refs.entityTopTenPop.initEntityTop(leftVal, item, response.data.result, filter.totalCount)
} else { } else {
@@ -70,6 +82,8 @@ export default {
}).catch(e => { }).catch(e => {
this.$refs.entityTopTenPop.initEntityTop(leftVal, item, [], filter.totalCount) this.$refs.entityTopTenPop.initEntityTop(leftVal, item, [], filter.totalCount)
}).finally(() => { }).finally(() => {
clearTimeout(this.timeout)
this.loading = false
this.showTopTen = true this.showTopTen = true
}) })
}, },

View File

@@ -58,7 +58,7 @@
<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>
<div class="entity-statics-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 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> </div>
</template> </template>
<template v-else-if="entityData.entityType === 'domain'"> <template v-else-if="entityData.entityType === 'domain'">
@@ -89,7 +89,7 @@
<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>
<div class="entity-statics-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 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> </div>
</template> </template>
<template v-else-if="entityData.entityType === 'app'"> <template v-else-if="entityData.entityType === 'app'">
@@ -103,7 +103,7 @@
</div> </div>
<div class="body__row"> <div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-sub-category"></i>{{$t('entities.subcategory')}}</span> <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>
<div class="body__row"> <div class="body__row">
<span class="body__row-label"><i class="cn-icon cn-icon-entity-alert"></i>{{$t('entities.recentAlert')}}</span> <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 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 ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</div>
<div class="entity-statics-up" ><i class="cn-icon cn-icon-rise"></i>{{entityData.bytesSentRate || 0}} bps</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="entityDetail({app: entityData.appName, type: 6})">{{$t('overall.detail')}}></div> <div class="body__detail" @click="showDetail">{{$t('overall.detail')}}></div>
</div> </div>
</template> </template>
</div> </div>
@@ -129,8 +129,16 @@
<script> <script>
import entityListMixin from './entityListMixin' import entityListMixin from './entityListMixin'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
export default { export default {
name: 'Card', name: 'Card',
mixins: [entityListMixin] mixins: [entityListMixin],
setup () {
return {
unitTypes,
unitConvert
}
}
} }
</script> </script>

View File

@@ -66,12 +66,12 @@
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-rise"></i> <i class="cn-icon cn-icon-rise"></i>
<span>{{$t('entities.sentThroughput')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('entities.sentThroughput')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{entityData.bytesSentRate || '-'}}</span> <span>{{entityData.bytesSentRate ? unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-fall"></i> <i class="cn-icon cn-icon-fall"></i>
<span>{{$t('entities.receivedThroughput')}}&nbsp;:&nbsp;&nbsp;</span> <span>{{$t('entities.receivedThroughput')}}&nbsp;:&nbsp;&nbsp;</span>
<span>{{entityData.bytesReceivedRate || '-'}}</span> <span>{{entityData.bytesReceivedRate ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'}}</span>
</div> </div>
<div class="basic-info__item"> <div class="basic-info__item">
<i class="cn-icon cn-icon-entity-alert"></i> <i class="cn-icon cn-icon-entity-alert"></i>
@@ -97,6 +97,7 @@
<el-divider></el-divider> <el-divider></el-divider>
<detail-overview <detail-overview
:entity="entityData" :entity="entityData"
:time-filter="timeFilter"
></detail-overview> ></detail-overview>
</div> </div>
</el-collapse-transition> </el-collapse-transition>
@@ -107,6 +108,8 @@
<script> <script>
import entityListMixin from './entityListMixin' import entityListMixin from './entityListMixin'
import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/DetailOverview' import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/DetailOverview'
import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
export default { export default {
name: 'Row', name: 'Row',
props: { props: {
@@ -122,6 +125,12 @@ export default {
isCollapse: true // 是否是折叠状态 isCollapse: true // 是否是折叠状态
} }
}, },
setup () {
return {
unitConvert,
unitTypes
}
},
methods: { methods: {
/* 切换折叠状态 */ /* 切换折叠状态 */
switchCollapse () { switchCollapse () {
@@ -131,16 +140,6 @@ export default {
/* 设为折叠状态 */ /* 设为折叠状态 */
collapse () { collapse () {
this.isCollapse = true 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')
} }
} }
} }

View File

@@ -25,22 +25,22 @@
<div class="overview__content"> <div class="overview__content">
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div> <div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
<div class="row__contents"> <div class="row__contents">
<div class="row__content"> <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 class="row__charts" :id="`entityDetailSend${entityData.appName}`" ></div>
</div> </div>
<div class="row__content"> <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 class="row__charts" :id="`entityDetailReceived${entityData.appName}`" ></div>
</div> </div>
@@ -78,7 +78,7 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
@@ -98,23 +98,35 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
</div> </div>
<div class="overview-map">
<chart
:chart="chart"
:entity="entityCopy"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
></chart>
</div>
</template> </template>
<script> <script>
import { api } from '@/utils/api' import { api } from '@/utils/api'
import entityDetailMixin from './entityDetailMixin' 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 { export default {
name: 'App', name: 'App',
props: {
// entity: Object
},
mixins: [entityDetailMixin], mixins: [entityDetailMixin],
components: {
Chart
},
data () { data () {
return { return {
// entityData: {} // entityData: {}
@@ -125,16 +137,12 @@ export default {
securityUrl: api.entityAppDetailSecurity, securityUrl: api.entityAppDetailSecurity,
listMode: 'list' listMode: 'list'
} }
},
mounted () {
}, },
methods: { methods: {
getQueryParams () { getQueryParams () {
const now = new Date()
const queryParams = { const queryParams = {
startTime: Math.floor(now.getTime() / 1000 - 3600), startTime: parseInt(this.timeFilter.startTime / 1000),
endTime: Math.floor(now.getTime() / 1000), endTime: parseInt(this.timeFilter.endTime / 1000),
appName: this.entityData.appName appName: this.entityData.appName
} }
return queryParams return queryParams
@@ -143,7 +151,23 @@ export default {
this.entityData.domainCount = result.domainCount this.entityData.domainCount = result.domainCount
this.entityData.ipCount = result.ipCount 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> </script>

View File

@@ -1,13 +1,13 @@
<template> <template>
<div class="entity-detail-overview"> <div class="entity-detail-overview">
<template v-if="entity.entityType === 'ip'"> <template v-if="entity.entityType === 'ip'">
<ip-overview :entity="entity"></ip-overview> <ip-overview :entity="entity" :time-filter="timeFilter"></ip-overview>
</template> </template>
<template v-else-if="entity.entityType === 'domain'"> <template v-else-if="entity.entityType === 'domain'">
<domain-overview :entity="entity"></domain-overview> <domain-overview :entity="entity" :time-filter="timeFilter"></domain-overview>
</template> </template>
<template v-else-if="entity.entityType === 'app'"> <template v-else-if="entity.entityType === 'app'">
<app-overview :entity="entity"></app-overview> <app-overview :entity="entity" :time-filter="timeFilter"></app-overview>
</template> </template>
</div> </div>
</template> </template>
@@ -21,7 +21,8 @@ export default {
/* 详情概览 */ /* 详情概览 */
name: 'DetailOverview', name: 'DetailOverview',
props: { props: {
entity: Object entity: Object,
timeFilter: Object
}, },
components: { components: {
'domain-overview': Domain, 'domain-overview': Domain,

View File

@@ -33,22 +33,22 @@
<div class="overview__content"> <div class="overview__content">
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div> <div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
<div class="row__contents"> <div class="row__contents">
<div class="row__content"> <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 class="row__charts" :id="`entityDetailSend${entityData.domainName}`" ></div>
</div> </div>
<div class="row__content"> <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 class="row__charts" :id="`entityDetailReceived${entityData.domainName}`" ></div>
</div> </div>
@@ -86,7 +86,7 @@
<span>{{$t('entities.avgRoundTripTime')}}</span> <span>{{$t('entities.avgRoundTripTime')}}</span>
</template> </template>
<template #data> <template #data>
<span>{{entityData.establishLatency?entityData.establishLatency+'ms':'-'}}</span> <span>{{entityData.establishLatency ? unitConvert(entityData.establishLatency, unitTypes.time).join(' ') : '-'}}</span>
</template> </template>
</single-value> </single-value>
<single-value <single-value
@@ -100,7 +100,7 @@
<span>{{$t('entities.httpResponseLatency')}}</span> <span>{{$t('entities.httpResponseLatency')}}</span>
</template> </template>
<template #data> <template #data>
<span>{{entityData.httpResponseLatency?entityData.httpResponseLatency+'ms':'-'}}</span> <span>{{entityData.httpResponseLatency ? unitConvert(entityData.httpResponseLatency, unitTypes.time).join(' ') : '-'}}</span>
</template> </template>
</single-value> </single-value>
<single-value <single-value
@@ -114,7 +114,7 @@
<span>{{$t('entities.sslConLatency')}}</span> <span>{{$t('entities.sslConLatency')}}</span>
</template> </template>
<template #data> <template #data>
<span>{{entityData.sslConLatency?entityData.sslConLatency+'ms':'-'}}</span> <span>{{entityData.sslConLatency ? unitConvert(entityData.sslConLatency, unitTypes.time).join(' ') : '-'}}</span>
</template> </template>
</single-value> </single-value>
<single-value <single-value
@@ -128,7 +128,7 @@
<span>{{$t('entities.sequenceGapLossPercent')}}</span> <span>{{$t('entities.sequenceGapLossPercent')}}</span>
</template> </template>
<template #data> <template #data>
<span>{{entityData.sequenceGapLossPercent?entityData.sequenceGapLossPercent+'%':'-'}}</span> <span>{{entityData.sequenceGapLossPercent ? unitConvert(entityData.sequenceGapLossPercent, unitTypes.percent).join(' ') : '-'}}</span>
</template> </template>
</single-value> </single-value>
<single-value <single-value
@@ -142,7 +142,7 @@
<span>{{$t('entities.pktRetransPercent')}}</span> <span>{{$t('entities.pktRetransPercent')}}</span>
</template> </template>
<template #data> <template #data>
<span>{{entityData.pktRetransPercent?entityData.pktRetransPercent+'%':'-'}}</span> <span>{{entityData.pktRetransPercent ? unitConvert(entityData.pktRetransPercent, unitTypes.percent).join(' ') : '-'}}</span>
</template> </template>
</single-value> </single-value>
</div> </div>
@@ -154,11 +154,11 @@
<div class="overview__tags"> <div class="overview__tags">
<div class="overview__tag"> <div class="overview__tag">
<span class="tag__desc">{{$t('entities.outLinkTrafficPercentage')}}</span> <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>
<div class="overview__tag"> <div class="overview__tag">
<span class="tag__desc">{{$t('entities.inLinkTrafficPercentage')}}</span> <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> </div>
</div> </div>
@@ -170,7 +170,7 @@
<div class="row__label">{{$t('entities.recentAlert')}}</div> <div class="row__label">{{$t('entities.recentAlert')}}</div>
<div class="row__content">{{entityData.alertNum || '-'}}</div> <div class="row__content">{{entityData.alertNum || '-'}}</div>
</div> </div>
<div class="overview__row overview__row--small-font" v-for="alert in entityData.alertList"> <div class="overview__row overview__row--small-font" v-for="alert in entityData.alertList">
<div class="row__label row__label--width160">{{alert.startTime}}</div> <div class="row__label row__label--width160">{{alert.startTime}}</div>
<div class="row__content row__content--width200"> <div class="row__content row__content--width200">
<div class="alert-level-tag alert-level-tag--high">{{alert.alertSeverity}}</div> <div class="alert-level-tag alert-level-tag--high">{{alert.alertSeverity}}</div>
@@ -178,7 +178,7 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
@@ -198,25 +198,34 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
</div> </div>
<div class="overview-map">
<chart
:chart="chart"
:entity="entityCopy"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
></chart>
</div>
</template> </template>
<script> <script>
import SingleValue from '@/components/charts/ChartSingleValue' import SingleValue from '@/components/charts/ChartSingleValue'
import { api } from '@/utils/api' import { api } from '@/utils/api'
import entityDetailMixin from './entityDetailMixin' 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 { export default {
name: 'Domain', name: 'Domain',
components: { components: {
SingleValue SingleValue,
}, Chart
props: {
entity: Object
}, },
mixins: [entityDetailMixin], mixins: [entityDetailMixin],
data () { data () {
@@ -235,10 +244,9 @@ export default {
}, },
methods: { methods: {
getQueryParams () { getQueryParams () {
const now = new Date()
const queryParams = { const queryParams = {
startTime: Math.floor(now.getTime() / 1000 - 3600), startTime: parseInt(this.timeFilter.startTime / 1000),
endTime: Math.floor(now.getTime() / 1000), endTime: parseInt(this.timeFilter.endTime / 1000),
domain: this.entityData.domainName domain: this.entityData.domainName
} }
return queryParams return queryParams
@@ -247,6 +255,25 @@ export default {
this.entityData.appCount = result.appCount this.entityData.appCount = result.appCount
this.entityData.ipCount = result.ipCount 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> </script>

View File

@@ -17,24 +17,24 @@
<div class="overview__content"> <div class="overview__content">
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.peak')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.mean')}}</div> <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>
<div class="overview__row"> <div class="overview__row">
<div class="row__label row__label--width130">{{$t('overall.throughput')}}</div> <div class="row__label row__label--width130">{{$t('overall.throughput')}}</div>
<div class="row__contents"> <div class="row__contents">
<div class="row__content"> <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 class="row__charts" :id="`entityDetailSend${entityData.ipAddr}`"></div>
</div> </div>
<div class="row__content"> <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 class="row__charts" :id="`entityDetailReceived${entityData.ipAddr}`"></div>
</div> </div>
</div> </div>
</div> </div>
@@ -70,7 +70,7 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
@@ -90,20 +90,35 @@
</div> </div>
<div class="row__desc"></div> <div class="row__desc"></div>
</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 class="show-more">{{$t('overall.showMore')}}>></div>
</div> </div>
</div> </div>
</div> </div>
<div class="overview-map">
<chart
:chart="chart"
:entity="entityCopy"
:hide-header="true"
@getCurrentTimeRange="getCurrentTimeRange"
></chart>
</div>
</template> </template>
<script> <script>
import entityDetailMixin from './entityDetailMixin' import entityDetailMixin from './entityDetailMixin'
import { api } from '@/utils/api' 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 { export default {
name: 'Ip', name: 'Ip',
mixins: [entityDetailMixin], mixins: [entityDetailMixin],
components: {
Chart
},
data () { data () {
return { return {
// entityData: {} // entityData: {}
@@ -117,10 +132,9 @@ export default {
}, },
methods: { methods: {
getQueryParams () { getQueryParams () {
const now = new Date()
const queryParams = { const queryParams = {
startTime: Math.floor(now.getTime() / 1000 - 3600), startTime: parseInt(this.timeFilter.startTime / 1000),
endTime: Math.floor(now.getTime() / 1000), endTime: parseInt(this.timeFilter.endTime / 1000),
ip: this.entityData.ipAddr ip: this.entityData.ipAddr
} }
return queryParams return queryParams
@@ -129,6 +143,25 @@ export default {
this.entityData.appCount = result.appCount this.entityData.appCount = result.appCount
this.entityData.domainCount = result.domainCount 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> </script>

View File

@@ -3,10 +3,12 @@ import { get } from '@/utils/http'
import * as echarts from 'echarts' import * as echarts from 'echarts'
import { entityListLineOption } from '@/components/charts/chart-options' import { entityListLineOption } from '@/components/charts/chart-options'
import { unitTypes } from '@/utils/constants' import { unitTypes } from '@/utils/constants'
import unitConvert from '@/utils/unit-convert'
export default { export default {
props: { props: {
entity: Object entity: Object,
timeFilter: Object
}, },
data () { data () {
return { return {
@@ -46,11 +48,16 @@ export default {
} }
}, },
methods: { methods: {
getCurrentTimeRange (callback) {
const myEndTime = window.$dayJs.tz().valueOf()
const myStartTime = myEndTime - this.timeFilter.dateRangeValue * 60 * 1000
callback({ startTime: myStartTime, endTime: myEndTime })
},
queryEntityDetailTraffic () { queryEntityDetailTraffic () {
this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`)) this.sentChart = echarts.init(document.getElementById(`entityDetailSend${this.entityName}`))
this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`)) this.receivedChart = echarts.init(document.getElementById(`entityDetailReceived${this.entityName}`))
get(this.trafficUrl, this.getQueryParams()).then(response => { 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 => { response.data.result.forEach(t => {
if (t.legend === 'bytesRate') { if (t.legend === 'bytesRate') {
this.entityData.max = t.aggregation.max this.entityData.max = t.aggregation.max
@@ -101,15 +108,17 @@ export default {
} }
} }
}) })
this.sentChart.setOption(this.chartOptionSent)
this.receivedChart.setOption(this.chartOptionReceived)
} }
this.sentChart.setOption(this.chartOptionSent)
this.receivedChart.setOption(this.chartOptionReceived)
}).finally(() => { }).finally(() => {
setTimeout(() => { setTimeout(() => {
this.$nextTick(() => { try {
this.sentChart && this.sentChart.resize() this.$nextTick(() => {
this.receivedChart && this.receivedChart.resize() this.sentChart && this.sentChart.resize()
}) this.receivedChart && this.receivedChart.resize()
})
} catch (e) {}
}, 250) }, 250)
}) })
}, },
@@ -192,7 +201,9 @@ export default {
}, },
setup () { setup () {
return { return {
chartOption: entityListLineOption chartOption: entityListLineOption,
unitTypes,
unitConvert
} }
}, },
mounted () { mounted () {

View File

@@ -77,7 +77,7 @@ export default {
}, },
queryParams () { queryParams () {
let params let params
const now = new Date() const now = window.$dayJs.tz().valueOf()
switch (this.entityData.entityType) { switch (this.entityData.entityType) {
case ('ip'): { case ('ip'): {
params = { params = {
@@ -115,11 +115,24 @@ export default {
} }
}, },
methods: { 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 () { 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) { if (response.code === 200) {
response.data.result.forEach(t => { response.data.result.forEach(t => {
if (t.name === 'bytes_sent_rate') { if (t.name === 'bytes_sent_rate') {
@@ -133,14 +146,26 @@ export default {
}) })
}, },
querySecurity () { 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) { if (response.code === 200) {
this.entityData.securityCount = response.data.result[0].count this.entityData.securityCount = response.data.result[0].count
} }
}) })
}, },
queryAlert () { 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) { if (response.code === 200) {
this.entityData.alertCount = response.data.result[0].value this.entityData.alertCount = response.data.result[0].value
} }
@@ -211,6 +236,7 @@ export default {
} }
} }
} }
return {}
}) })
chartOption = { chartOption = {
...this.chartOption, ...this.chartOption,

View File

@@ -18,7 +18,7 @@
<span>{{$t('search.searchHistory')}}</span> <span>{{$t('search.searchHistory')}}</span>
</div> </div>
<div class="foot__item"> <div class="foot__item">
<span @click="search">{{$t('overall.explore')}}</span> <span @click="search({})">{{$t('overall.explore')}}</span>
<el-divider direction="vertical"></el-divider> <el-divider direction="vertical"></el-divider>
<span>{{$t('overall.help')}}</span> <span>{{$t('overall.help')}}</span>
</div> </div>
@@ -41,7 +41,7 @@ export default {
} }
}, },
methods: { methods: {
search (params) { search (params = {}) {
this.$emit('search', params) this.$emit('search', params)
}, },
addParams (params) { addParams (params) {