CN-1150: 实体列表接口对接
This commit is contained in:
@@ -3,60 +3,60 @@
|
||||
class="entity-explorer"
|
||||
:class="{'entity-explorer--show-list': showList}">
|
||||
<!-- 顶部工具栏,在列表页显示 -->
|
||||
<!-- <div class="explorer-top-tools explorer-top-tools-new" v-show="showList">-->
|
||||
<!-- <div class="explorer-detection-top-tools">-->
|
||||
<!-- <div class="explorer-top-tools-title">{{$t('network.entity')}}</div>-->
|
||||
<!-- </div>-->
|
||||
<!-- <div class="explorer-top-tools">-->
|
||||
<!-- <DateTimeRange :start-time="timeFilter.startTime" :end-time="timeFilter.endTime" :date-range="timeFilter.dateRangeValue" ref="dateTimeRange" @change="reload"/>-->
|
||||
<!-- <TimeRefresh class="date-time-range" @change="timeRefreshChange" :end-time="timeFilter.endTime"/>-->
|
||||
<!-- <el-button-group size="mini">-->
|
||||
<!-- <el-button size="mini" @click="listMode = 'list'" :class="{'active': listMode === 'list'}"><i class="cn-icon cn-icon-list"></i></el-button>-->
|
||||
<!-- <el-button size="mini" @click="listMode = 'block'" :class="{'active': listMode === 'block'}"><i class="cn-icon cn-icon-blocks"></i></el-button>-->
|
||||
<!-- </el-button-group>-->
|
||||
<div class="explorer-top-tools" v-show="showList">
|
||||
<DateTimeRange :start-time="timeFilter.startTime" :end-time="timeFilter.endTime" :date-range="timeFilter.dateRangeValue" ref="dateTimeRange" @change="reload"/>
|
||||
<TimeRefresh class="date-time-range" @change="timeRefreshChange" :end-time="timeFilter.endTime"/>
|
||||
<el-button-group size="mini">
|
||||
<el-button size="mini" @click="setListMode('list')" :class="{'active': listMode === 'list'}"><i class="cn-icon cn-icon-list"></i></el-button>
|
||||
<el-button size="mini" @click="setListMode('block')" :class="{'active': listMode === 'block'}"><i class="cn-icon cn-icon-blocks"></i></el-button>
|
||||
</el-button-group>
|
||||
<div class="explorer-top-tools explorer-top-tools-new" style="margin: 2px 0;" v-show="showList">
|
||||
<div class="explorer-detection-top-tools">
|
||||
<div class="explorer-top-tools-title" style="padding: 0;margin-left: -10px;">{{$t('network.entity')}}</div>
|
||||
</div>
|
||||
<!-- </div>-->
|
||||
</div>
|
||||
<!-- 搜索组件 -->
|
||||
<explorer-search
|
||||
v-if="!showList"
|
||||
ref="search"
|
||||
:class="{'explorer-search--show-list': showList}"
|
||||
:show-list="showList"
|
||||
@search="search"
|
||||
></explorer-search>
|
||||
|
||||
<!--todo静态数据,之后记得修改-->
|
||||
<!-- <div class="explorer-result" v-if="showList">-->
|
||||
<!-- 8,866 results,IP 2666,Domain 3200,APP 3000-->
|
||||
<!-- </div>-->
|
||||
<!-- 内容区 -->
|
||||
<div class="explorer-container" v-if="showList" style="height: calc(100% - 20px); flex-direction: column">
|
||||
<div style="display: flex; height: auto;">
|
||||
<entity-filter
|
||||
:filter-data="filterData"
|
||||
:loading-left="loadingLeft"
|
||||
:q="q"
|
||||
:time-filter="timeFilter"
|
||||
@filter="filter"
|
||||
></entity-filter>
|
||||
<entity-list
|
||||
:list-data="listData"
|
||||
:list-mode="listMode"
|
||||
:pageObj="pageObj"
|
||||
:time-filter="timeFilter"
|
||||
@pageSize="pageSize"
|
||||
@pageNo="pageNo"
|
||||
:loading="listLoading"
|
||||
></entity-list>
|
||||
<div v-if="showList" style="display: flex;flex-direction: row;">
|
||||
<entity-filter
|
||||
:filter-data="newFilterData"
|
||||
:loading-left="loadingLeft"
|
||||
:q="q"
|
||||
:time-filter="timeFilter"
|
||||
@filter="filter"
|
||||
></entity-filter>
|
||||
<div class="explorer-container" style="height: calc(100% - 62px);flex-direction: column;width: 100%;">
|
||||
<explorer-search
|
||||
ref="search"
|
||||
:class="{'explorer-search--show-list': showList}"
|
||||
:show-list="showList"
|
||||
@search="search"
|
||||
></explorer-search>
|
||||
|
||||
<div style="display: flex;flex-direction: column;height: calc(100% - 42px);">
|
||||
<div class="explorer-result" v-if="showList">
|
||||
<loading :loading="loadingCount"></loading>
|
||||
<span>{{ summaryCount.total }}</span>results,IP
|
||||
<span>{{ summaryCount.ipCount }}</span>,Domain
|
||||
<span>{{ summaryCount.fqdnCount }}</span>,APP
|
||||
<span>{{ summaryCount.appCount }}</span>
|
||||
</div>
|
||||
|
||||
<entity-list
|
||||
style="width: 100%;"
|
||||
:list-data="listData"
|
||||
:list-mode="listMode"
|
||||
:pageObj="pageObj"
|
||||
:time-filter="timeFilter"
|
||||
@pageSize="pageSize"
|
||||
@pageNo="pageNo"
|
||||
:loading="listLoading"
|
||||
></entity-list>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="explorer-foot" v-else>
|
||||
|
||||
<div class="explorer-foot" v-if="!showList">
|
||||
<div>
|
||||
<el-divider direction="vertical"></el-divider>
|
||||
<div class="entity-overview">
|
||||
@@ -150,8 +150,6 @@
|
||||
|
||||
<script>
|
||||
import ExplorerSearch from '@/views/entityExplorer/search/ExplorerSearch'
|
||||
import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
|
||||
import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
|
||||
import EntityFilter from '@/views/entityExplorer/EntityFilter'
|
||||
import EntityList from '@/views/entityExplorer/entityList/EntityList'
|
||||
import { entityType, defaultPageSize, riskLevelMapping } from '@/utils/constants'
|
||||
@@ -172,8 +170,6 @@ export default {
|
||||
components: {
|
||||
Loading,
|
||||
ExplorerSearch,
|
||||
DateTimeRange,
|
||||
TimeRefresh,
|
||||
EntityFilter,
|
||||
EntityList
|
||||
},
|
||||
@@ -210,23 +206,15 @@ export default {
|
||||
{
|
||||
label: this.$t('overall.country'),
|
||||
column: 'countryDistinctCount',
|
||||
topColumn: 'ip_location_country', // top弹框查询字段
|
||||
topColumn: 'country', // top弹框查询字段
|
||||
icon: 'cn-icon cn-icon-country',
|
||||
showTopTen: false,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.province'),
|
||||
column: 'provinceDistinctCount',
|
||||
topColumn: 'ip_location_province', // top弹框查询字段
|
||||
icon: 'cn-icon cn-icon-position',
|
||||
showTopTen: false,
|
||||
value: 0
|
||||
},
|
||||
{
|
||||
label: this.$t('overall.city'),
|
||||
column: 'cityDistinctCount',
|
||||
topColumn: 'ip_location_city', // top弹框查询字段
|
||||
topColumn: 'region', // top弹框查询字段
|
||||
icon: 'cn-icon cn-icon-city',
|
||||
showTopTen: false,
|
||||
value: 0
|
||||
@@ -234,7 +222,7 @@ export default {
|
||||
{
|
||||
label: this.$t('entities.asn'),
|
||||
column: 'asnDistinctCount',
|
||||
topColumn: 'ip_asn', // top弹框查询字段
|
||||
topColumn: 'asn', // top弹框查询字段
|
||||
icon: 'cn-icon cn-icon-cloud',
|
||||
showTopTen: false,
|
||||
value: 0
|
||||
@@ -346,6 +334,26 @@ export default {
|
||||
]
|
||||
}
|
||||
],
|
||||
newFilterData: [
|
||||
{
|
||||
icon: 'cn-icon cn-icon-registration-country',
|
||||
title: 'Top Countries',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-city',
|
||||
title: 'Top Cities',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
},
|
||||
{
|
||||
icon: 'cn-icon cn-icon-as',
|
||||
title: 'Top ASNs',
|
||||
totalCount: 0,
|
||||
data: []
|
||||
}
|
||||
],
|
||||
listData: [],
|
||||
q: '',
|
||||
metaList: [],
|
||||
@@ -367,7 +375,14 @@ export default {
|
||||
// 实体详情列表页面 左侧筛选条件
|
||||
loadingLeft: false,
|
||||
initFlag: false, // 初始化标志,避免初始化时pageSize和pageNo会调用搜索
|
||||
timer: null // 初始化标志的延时器,需要销毁
|
||||
timer: null, // 初始化标志的延时器,需要销毁
|
||||
summaryCount: {
|
||||
total: 0,
|
||||
fqdnCount: 0,
|
||||
ipCount: 0,
|
||||
appCount: 0
|
||||
},
|
||||
loadingCount: false // 实体基数统计的loading
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -420,6 +435,12 @@ export default {
|
||||
return result
|
||||
},
|
||||
search (param) {
|
||||
// todo 下版本08版本删除 ---- start
|
||||
if (param && param.q.indexOf("QUERY('") > -1) {
|
||||
this.$message.error(this.$t('overall.versionNotSupportThisFormat'))
|
||||
return true
|
||||
}
|
||||
// 下版本08版本删除 ---- end
|
||||
let q
|
||||
let metaList
|
||||
if (param) {
|
||||
@@ -489,29 +510,35 @@ export default {
|
||||
} else {
|
||||
this.limitFilterType = false
|
||||
}
|
||||
this.queryFilter({ entityType: entityType, q: this.q, ...this.timeFilter })
|
||||
if (entityType === 'ip') {
|
||||
this.queryFilter({ entityType: 'dns', q: this.q, ...this.timeFilter })
|
||||
}
|
||||
// this.queryFilter({ entityType: entityType, q: this.q, ...this.timeFilter })
|
||||
// if (entityType === 'ip') {
|
||||
// this.queryFilter({ entityType: 'dns', q: this.q, ...this.timeFilter })
|
||||
// }
|
||||
this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryList({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryListTotal({ q: this.q, ...this.timeFilter })
|
||||
this.queryCount({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
// this.queryListTotal({ q: this.q, ...this.timeFilter })
|
||||
} else {
|
||||
this.limitFilterType = false
|
||||
this.queryFilter({ entityType: 'ip', q: this.q, ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'domain', q: this.q, ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'app', q: this.q, ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'dns', q: this.q, ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'ip', q: this.q, ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'domain', q: this.q, ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'app', q: this.q, ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'dns', q: this.q, ...this.timeFilter })
|
||||
this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryList({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
this.queryListTotal({ q: this.q, ...this.timeFilter })
|
||||
this.queryCount({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||||
// this.queryListTotal({ q: this.q, ...this.timeFilter })
|
||||
}
|
||||
} else {
|
||||
this.limitFilterType = false
|
||||
this.queryFilter({ entityType: 'ip', ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'app', ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'domain', ...this.timeFilter })
|
||||
this.queryFilter({ entityType: 'dns', ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'ip', ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'app', ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'domain', ...this.timeFilter })
|
||||
// this.queryFilter({ entityType: 'dns', ...this.timeFilter })
|
||||
this.queryFilterNew({ ...this.pageObj, ...this.timeFilter })
|
||||
this.queryList({ ...this.pageObj, ...this.timeFilter })
|
||||
this.queryListTotal({ ...this.timeFilter })
|
||||
this.queryCount({ ...this.pageObj, ...this.timeFilter })
|
||||
// this.queryListTotal({ ...this.timeFilter })
|
||||
|
||||
// 延时一秒,避免初始化时pageSize为20,pageNo为1也会调用“搜索”的情况
|
||||
if (!this.initFlag) {
|
||||
@@ -636,27 +663,87 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
/** 新版查询filter数据 */
|
||||
queryFilterNew (params) {
|
||||
const queryParams = {
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
resource: params.q || ''
|
||||
}
|
||||
this.loadingLeft = true
|
||||
const aggCountry = get(api.entity.entityList.aggCountry, queryParams)
|
||||
const aggCity = get(api.entity.entityList.aggCity, queryParams)
|
||||
const aggAsn = get(api.entity.entityList.aggAsn, queryParams)
|
||||
|
||||
Promise.all([aggCountry, aggCity, aggAsn]).then(response => {
|
||||
response.forEach((item, index) => {
|
||||
if (item.code === 200 && item.data.list) {
|
||||
this.newFilterData[index].data = []
|
||||
item.data.list.forEach(item => {
|
||||
const obj = { label: item.value, flag: '011-china', topColumn: 'country', value: item.uniqueEntities }
|
||||
if (index === 0) {
|
||||
obj.flag = item.uniqueEntities // 接口字段名称为'China',目前svg名称为'011-china',后续再指定方案调整
|
||||
}
|
||||
if (index === 1) {
|
||||
obj.topColumn = 'region'
|
||||
}
|
||||
if (index === 2) {
|
||||
obj.topColumn = 'asn'
|
||||
}
|
||||
this.newFilterData[index].data.push(obj)
|
||||
})
|
||||
}
|
||||
})
|
||||
}).catch(e => {
|
||||
// e
|
||||
}).finally(() => {
|
||||
this.loadingLeft = false
|
||||
})
|
||||
},
|
||||
/** 实体列表查询 */
|
||||
queryList (params) {
|
||||
this.listLoading = true
|
||||
const queryParams = {
|
||||
...params,
|
||||
startTime: getSecond(params.startTime),
|
||||
endTime: getSecond(params.endTime)
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
resource: params.q || ''
|
||||
}
|
||||
get(api.entityList, queryParams).then(response => {
|
||||
get(api.entity.entityList.list, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.listData = []
|
||||
this.$nextTick(() => {
|
||||
this.listData = response.data.result
|
||||
this.listData = response.data.list
|
||||
this.pageObj.total = response.data.total
|
||||
})
|
||||
} else {
|
||||
console.error(response.message)
|
||||
this.$message.error(response.message)
|
||||
}
|
||||
}).finally(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
/** 实体基数统计 */
|
||||
queryCount (params) {
|
||||
this.loadingCount = true
|
||||
const queryParams = {
|
||||
// startTime: getSecond(params.startTime),
|
||||
// endTime: getSecond(params.endTime),
|
||||
resource: params.q || '' // 目前版本搜索不支持实体名称搜索,下版本改进
|
||||
}
|
||||
get(api.entity.entityList.summaryCount, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.summaryCount = response.data
|
||||
} else {
|
||||
this.summaryCount = { total: 0, fqdnCount: 0, ipCount: 0, appCount: 0 }
|
||||
}
|
||||
}).catch(e => {
|
||||
console.log(e)
|
||||
this.summaryCount = { total: 0, fqdnCount: 0, ipCount: 0, appCount: 0 }
|
||||
}).finally(() => {
|
||||
this.loadingCount = false
|
||||
})
|
||||
},
|
||||
|
||||
queryListTotal (params) {
|
||||
const queryParams = {
|
||||
@@ -677,11 +764,6 @@ export default {
|
||||
},
|
||||
|
||||
getEntityIndexData () {
|
||||
const now = window.$dayJs.tz().valueOf()
|
||||
const timeFilter = {
|
||||
startTime: parseInt(now / 1000 - 3600),
|
||||
endTime: parseInt(now / 1000)
|
||||
}
|
||||
// Total
|
||||
this.loadingApp = true
|
||||
this.loadingDomain = true
|
||||
@@ -695,61 +777,37 @@ export default {
|
||||
this.loadingDomainActive = true
|
||||
this.loadingIpActive = true
|
||||
|
||||
get(api.entityTotal, { entityType: 'app' }).then(response => {
|
||||
get(api.entity.entityList.entityActive).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityAppTotal = response.data.result
|
||||
}
|
||||
this.loadingApp = false
|
||||
})
|
||||
get(api.entityTotal, { entityType: 'domain' }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityDomainTotal = response.data.result
|
||||
this.entityDomainTotal = response.data.domainCount
|
||||
this.entityIpTotal = response.data.ipCount
|
||||
this.entityAppTotal = response.data.appCount
|
||||
}
|
||||
this.loadingDomain = false
|
||||
})
|
||||
get(api.entityTotal, { entityType: 'ip' }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityIpTotal = response.data.result
|
||||
}
|
||||
this.loadingIp = false
|
||||
this.loadingApp = false
|
||||
})
|
||||
// New
|
||||
get(api.entityNew, { entityType: 'app', ...timeFilter }).then(response => {
|
||||
get(api.entity.entityList.entityNew).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityAppNew = response.data.result
|
||||
}
|
||||
this.loadingAppNew = false
|
||||
})
|
||||
get(api.entityNew, { entityType: 'domain', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityDomainNew = response.data.result
|
||||
this.entityDomainNew = response.data.domainCount
|
||||
this.entityIpNew = response.data.ipCount
|
||||
this.entityAppNew = response.data.appCount
|
||||
}
|
||||
this.loadingDomainNew = false
|
||||
})
|
||||
get(api.entityNew, { entityType: 'ip', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityIpNew = response.data.result
|
||||
}
|
||||
this.loadingIpNew = false
|
||||
this.loadingAppNew = false
|
||||
})
|
||||
// Active
|
||||
get(api.entityActive, { entityType: 'app', ...timeFilter }).then(response => {
|
||||
get(api.entity.entityList.entityActive).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityAppActive = response.data.result
|
||||
}
|
||||
this.loadingAppActive = false
|
||||
})
|
||||
get(api.entityActive, { entityType: 'domain', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityDomainActive = response.data.result
|
||||
this.entityDomainActive = response.data.domainCount
|
||||
this.entityIpActive = response.data.ipCount
|
||||
this.entityAppActive = response.data.appCount
|
||||
}
|
||||
this.loadingDomainActive = false
|
||||
})
|
||||
get(api.entityActive, { entityType: 'ip', ...timeFilter }).then(response => {
|
||||
if (response.code === 200) {
|
||||
this.entityIpActive = response.data.result
|
||||
}
|
||||
this.loadingIpActive = false
|
||||
this.loadingAppActive = false
|
||||
})
|
||||
},
|
||||
cleanFilterData (index) {
|
||||
|
||||
@@ -1,150 +1,76 @@
|
||||
<template >
|
||||
<template>
|
||||
<div class="entity-filter-case">
|
||||
<div class="filter-case__header">{{$t('entities.filter')}}</div>
|
||||
<div
|
||||
class="entity-filter"
|
||||
v-for="(filters, index) in filterData"
|
||||
:key="index"
|
||||
>
|
||||
<div class="filter__header">{{filters.title}}</div>
|
||||
<div class="filter__body">
|
||||
<div class="filter-case__header">{{ $t('entities.filter1') }}</div>
|
||||
|
||||
<div class="filter__row" v-for="(item, i) in filters.data" :key="i">
|
||||
<el-popover popper-class="filter__row-popover" placement="right-start" :width="440" v-model:visible="item.showTopTen">
|
||||
<template #reference>
|
||||
<div class="filter__row-popover" @click="showTopDialog(i, item, filters)">
|
||||
<div class="row__label">
|
||||
<i :class="item.icon"></i>
|
||||
<span>{{item.label}}</span>
|
||||
</div>
|
||||
<div class="row__value">
|
||||
<loading :loading="loadingLeft" size="small"></loading>
|
||||
<span>{{item.value}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<entity-top
|
||||
ref="entityTopTenPop"
|
||||
:loading="loading"
|
||||
:popover-data="popoverData"
|
||||
:item-data="itemData"
|
||||
:total-count="totalCount"
|
||||
:top-column="item.topColumn"
|
||||
@filter="filter"
|
||||
></entity-top>
|
||||
</el-popover>
|
||||
<div class="entity-filter" v-for="(item, index) in filterData" :key="index">
|
||||
<div class="filter__header">
|
||||
<i :class="item.icon"></i>
|
||||
{{ item.title }}
|
||||
</div>
|
||||
|
||||
<div class="filter__body" style="position: relative">
|
||||
<loading :loading="loadingLeft" style="top: -5px;"></loading>
|
||||
<div class="filter__body-item" v-for="(data, i) in item.data" :key="i" @click="filter(data.label, data)">
|
||||
<div class="filter__body-item-left">
|
||||
<!-- 当前无更好方案匹配国旗,后续解决-->
|
||||
<!-- <div v-if="data.flag">-->
|
||||
<!-- <img :src="require(`../../../public/images/flag/${data.flag}.svg`)" class="filter-country-flag"/>-->
|
||||
<!-- </div>-->
|
||||
<div class="filter__body-item-left-index">{{ i+1 }}</div>
|
||||
<div class="filter__body-item-left-label">
|
||||
<el-tooltip :content="data.label" placement="top" effect="light" :disabled="disabledLabel">
|
||||
<span @mouseenter="handleMouse(`filter${index}${i}`)" :id="`filter${index}${i}`">{{ data.label }}</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="filter__body-item-right">{{ data.value }}</div>
|
||||
</div>
|
||||
<div class="filter-hr"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import EntityTop from '@/views/entityExplorer/EntityTop'
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
export default {
|
||||
name: 'EntityFilter',
|
||||
components: {
|
||||
Loading,
|
||||
EntityTop
|
||||
},
|
||||
components: { Loading },
|
||||
props: {
|
||||
filterData: Array,
|
||||
q: String,
|
||||
timeFilter: Object,
|
||||
loadingLeft: Boolean
|
||||
filterData: {
|
||||
type: Object
|
||||
},
|
||||
loadingLeft: {
|
||||
type: Boolean
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
topList: 'list',
|
||||
topData: [],
|
||||
entityTopTenData: [],
|
||||
currentColumn: {},
|
||||
totalCount: 0,
|
||||
loading: false,
|
||||
popoverData: [],
|
||||
itemData: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentColumn (n, o) {
|
||||
if (n.column === 'dnsServerOrgCount') {
|
||||
this.totalCount = this.filterData[3].orgTotalCount
|
||||
} else if (n.column === 'dnsServerSoftwareCount') {
|
||||
this.totalCount = this.filterData[3].softwareTotalCount
|
||||
} else if (n.column === 'dnsServerOsCount') {
|
||||
this.totalCount = this.filterData[3].osTotalCount
|
||||
} else if (n.column === 'categoryDistinctCount' && n.type === 'app') {
|
||||
this.totalCount = this.filterData[1].totalCount
|
||||
} else {
|
||||
let count = 0
|
||||
this.filterData.forEach(f => {
|
||||
const filter = f.data.some(d => d.column === n.column)
|
||||
if (filter) {
|
||||
count = f.totalCount
|
||||
}
|
||||
})
|
||||
this.totalCount = count
|
||||
}
|
||||
disabledLabel: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
showTopDialog (i, item, filter) {
|
||||
if (this.currentColumn.column === item.column && item.showTopTen) {
|
||||
item.showTopTen = false
|
||||
return
|
||||
/**
|
||||
* 判断文字是否溢出,超出则鼠标移入tooltip显示,否则鼠标移入不显示
|
||||
* @param id
|
||||
*/
|
||||
handleMouse (id) {
|
||||
const dom = document.getElementById(id)
|
||||
if (dom) {
|
||||
const width = document.getElementById(id).offsetWidth
|
||||
this.disabledLabel = width < 180
|
||||
} else {
|
||||
this.disabledLabel = true
|
||||
}
|
||||
this.filterData.forEach(f => {
|
||||
f.data.forEach(ff => {
|
||||
ff.showTopTen = false
|
||||
})
|
||||
})
|
||||
item.showTopTen = true
|
||||
this.currentColumn = {
|
||||
column: item.column,
|
||||
type: filter.type
|
||||
}
|
||||
const queryParams = {
|
||||
q: this.q,
|
||||
entityType: filter.type,
|
||||
column: item.topColumn,
|
||||
top: 10,
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime)
|
||||
}
|
||||
this.loading = true
|
||||
this.popoverData = []
|
||||
this.itemData = {}
|
||||
get(api.filterTop, queryParams).then(response => {
|
||||
if (response.code === 200) {
|
||||
if (this.currentColumn.column === item.column) {
|
||||
if (filter.type === 'dns') {
|
||||
this.popoverData = response.data.result.filter(f => {
|
||||
return f.count > 0
|
||||
})
|
||||
} else {
|
||||
this.popoverData = response.data.result
|
||||
}
|
||||
this.itemData = item
|
||||
}
|
||||
} else {
|
||||
this.popoverData = []
|
||||
this.itemData = item
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(e => {
|
||||
this.popoverData = []
|
||||
this.itemData = item
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
filter (name, topData) {
|
||||
this.showTopDialog('', topData)
|
||||
this.$emit('filter', name, topData)
|
||||
filter (name, data) {
|
||||
this.$emit('filter', name, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -9,75 +9,76 @@
|
||||
<div class="cn-entity__case">
|
||||
<div class="cn-entity__icon"><i :class="iconClass"></i></div>
|
||||
<div class="cn-entity__row">
|
||||
<div class="cn-entity__header">
|
||||
{{ entityData.ipAddr || entityData.domainName || entityData.appName || 'Unknown' }}
|
||||
<!-- <div class="cn-entity__header" style="display: flex">-->
|
||||
<!-- <span class="cn-entity__header-title">{{ entityData.ipAddr || entityData.domainName || entityData.appName || 'Unknown' }}</span>-->
|
||||
<!-- <span class="entity-detail" style="display: flex">-->
|
||||
<!-- <span style="width: 62px;" class="entity-tag entity-tag--small entity-tag--level-two-positive margin-r-6">信息技术</span>-->
|
||||
<!-- <span style="width: 50px;" class="entity-tag entity-tag--small entity-tag--level-two-normal margin-r-6">互联网</span>-->
|
||||
<!-- </span>-->
|
||||
<!--标签-->
|
||||
<div class="cn-entity__header" style="display: flex;align-items: center">
|
||||
<span class="cn-entity__header-title">{{ entityData.entityValue || 'Unknown' }}</span>
|
||||
<span class="entity-detail" style="display: flex;margin-left: 6px;margin-top: 1px;">
|
||||
<span v-for="(item, index) in levelTwoTags" :key="index" class="entity-tag entity-tag--small margin-r-10" :class="`entity-tag--level-two-${item.type}`">
|
||||
{{ item.value }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="cn-entity__body">
|
||||
<div class="body__basic-info">
|
||||
<div class="basic-info">
|
||||
<template v-if="entityData.entityType === 'ip'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-country"></i>
|
||||
<span>{{ $t('overall.country') }} : </span>
|
||||
<span>{{ entityData.ipLocationCountry || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('overall.country') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.location ? entityData.location.country : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-position"></i>
|
||||
<span>{{ $t('overall.region') }} : </span>
|
||||
<span>{{ ipLocationRegion(entityData) }}</span>
|
||||
<span class="row-item-label">{{ $t('overall.region') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.location ? ipLocationRegion(entityData.location) : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-cloud"></i>
|
||||
<span>{{ $t('entities.asn') }} : </span>
|
||||
<span>{{ entityData.ipAsn || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('entities.asn') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.asn ? entityData.asn.asn : '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'domain'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category"></i>
|
||||
<span>{{ $t('entities.domainDetail.categoryGroup') }} : </span>
|
||||
<span>{{ entityData.domainCategoryGroup || '-' }}</span>
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.name : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span>{{ $t('entities.category') }} : </span>
|
||||
<span>{{ entityData.domainCategory || '-' }}</span>
|
||||
<i class="cn-icon cn-icon-category"></i>
|
||||
<span class="row-item-label">{{ $t('entities.subcategory') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.group : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-credit"></i>
|
||||
<span>{{ $t('entities.reputationLevel') }} : </span>
|
||||
<span>{{ entityData.domainReputationScore || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('entities.reputationLevel') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.reputationLevel : '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else-if="entityData.entityType === 'app'">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-id"></i>
|
||||
<span>{{ $t('entities.category') }} : </span>
|
||||
<span>{{ entityData.appCategory || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('entities.category') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.appCategory : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-category"></i>
|
||||
<span>{{ $t('entities.subcategory') }} : </span>
|
||||
<span>{{ entityData.appSubcategory || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('entities.subcategory') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? entityData.category.appSubcategory : '-' }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-sub-category"></i>
|
||||
<span>{{ $t('entities.risk') }} : </span>
|
||||
<span>{{ appRisk(entityData.appRisk) || '-' }}</span>
|
||||
<span class="row-item-label">{{ $t('entities.risk') }} : </span>
|
||||
<span class="row-item-value">{{ entityData.category ? appRisk(entityData.category.appRisk) : '-' }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 通用字段 -->
|
||||
<div class="basic-info__item">
|
||||
<div class="item__box">
|
||||
<i class="cn-icon cn-icon-rise"></i>
|
||||
<span>{{ $t('entities.sentThroughput') }} : </span>
|
||||
<span>
|
||||
<span class="row-item-label">{{ $t('entities.sentThroughput') }} : </span>
|
||||
<span class="row-item-value">
|
||||
{{
|
||||
entityData.bytesSentRate ? unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ') + 'ps' : '-'
|
||||
}}
|
||||
@@ -107,8 +108,8 @@
|
||||
<div class="basic-info__item">
|
||||
<div class="item__box">
|
||||
<i class="cn-icon cn-icon-fall"></i>
|
||||
<span>{{ $t('entities.receivedThroughput') }} : </span>
|
||||
<span>
|
||||
<span class="row-item-label">{{ $t('entities.receivedThroughput') }} : </span>
|
||||
<span class="row-item-value">
|
||||
{{
|
||||
entityData.bytesReceivedRate ? unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ') + 'ps' : '-'
|
||||
}}
|
||||
@@ -133,23 +134,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!--新版实体列表改版,去除这一段-->
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-entity-alert"></i>
|
||||
<span>{{ $t('entities.recentAlert') }} : </span>
|
||||
<span>{{ entityData.performanceCount }}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-safe"></i>
|
||||
<span>{{ $t('entities.recentSecurity') }} : </span>
|
||||
<span>{{ entityData.securityCount }}</span>
|
||||
</div>
|
||||
<!--新版实体列表改版,去除这一段-->
|
||||
</div>
|
||||
<!-- <div class="show-detail" @click="showDetail">-->
|
||||
<!-- {{ $t('overall.detail') }}>-->
|
||||
<!-- </div>-->
|
||||
<!-- 新版实体列表改版,后续记得解开-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -172,6 +157,10 @@ import DetailOverview from '@/views/entityExplorer/entityList/detailOverview/Det
|
||||
import entityListMixin from './entityListMixin'
|
||||
import relatedServer from '@/mixins/relatedServer'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import axios from 'axios'
|
||||
import { api } from '@/utils/api'
|
||||
import { entityDetailTags, psiphon3IpType } from '@/utils/constants'
|
||||
import _ from 'lodash'
|
||||
|
||||
export default {
|
||||
name: 'Row',
|
||||
@@ -188,35 +177,109 @@ export default {
|
||||
data () {
|
||||
return {
|
||||
loading: false,
|
||||
isCollapse: true // 是否是折叠状态
|
||||
isCollapse: true, // 是否是折叠状态
|
||||
levelTwoTags: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ipLocationRegion () {
|
||||
return function (entityData) {
|
||||
const hasProvinceAndCity =
|
||||
entityData.ipLocationProvince &&
|
||||
entityData.ipLocationCity &&
|
||||
entityData.ipLocationProvince !== 'null' &&
|
||||
entityData.ipLocationCity !== 'null'
|
||||
entityData.province &&
|
||||
entityData.city &&
|
||||
entityData.province !== 'null' &&
|
||||
entityData.city !== 'null'
|
||||
const hasProvince =
|
||||
entityData.ipLocationProvince &&
|
||||
entityData.ipLocationProvince !== 'null'
|
||||
entityData.province &&
|
||||
entityData.province !== 'null'
|
||||
const hasCity =
|
||||
entityData.ipLocationCity && entityData.ipLocationCity !== 'null'
|
||||
entityData.city && entityData.city !== 'null'
|
||||
if (hasProvinceAndCity) {
|
||||
return `${entityData.ipLocationProvince}, ${entityData.ipLocationCity}`
|
||||
return `${entityData.province}, ${entityData.city}`
|
||||
} else if (hasProvince) {
|
||||
return entityData.ipLocationProvince
|
||||
return entityData.province
|
||||
} else if (hasCity) {
|
||||
return entityData.ipLocationCity
|
||||
return entityData.city
|
||||
} else {
|
||||
return '-'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.initData()
|
||||
this.initTagsData()
|
||||
},
|
||||
methods: {
|
||||
initData () {
|
||||
let url = ''
|
||||
switch (this.entity.entityType) {
|
||||
case ('domain'): {
|
||||
url = api.entity.entityList.domainBasicInfo
|
||||
break
|
||||
}
|
||||
case ('ip'): {
|
||||
url = api.entity.entityList.ipBasicInfo
|
||||
break
|
||||
}
|
||||
case ('app'): {
|
||||
url = api.entity.entityList.appBasicInfo
|
||||
break
|
||||
}
|
||||
}
|
||||
axios.get(`${url}?resource=${this.entity.entityValue}`).then(response => {
|
||||
this.$nextTick(() => {
|
||||
this.entityData = { ...response.data.data, ...this.entity }
|
||||
})
|
||||
})
|
||||
},
|
||||
initTagsData () {
|
||||
let url = ''
|
||||
switch (this.entity.entityType) {
|
||||
case ('domain'): {
|
||||
url = api.entity.entityList.domainTags
|
||||
break
|
||||
}
|
||||
case ('ip'): {
|
||||
url = api.entity.entityList.ipTags
|
||||
break
|
||||
}
|
||||
case ('app'): {
|
||||
url = api.entity.entityList.appTags
|
||||
break
|
||||
}
|
||||
}
|
||||
axios.get(`${url}?resource=${this.entity.entityValue}`).then(responese => {
|
||||
const res = responese.data
|
||||
if (res.code === 200) {
|
||||
Object.keys(res.data).forEach(k => {
|
||||
if (k !== 'userDefinedTags' && res.data[k]) {
|
||||
Object.keys(res.data[k]).forEach(k2 => {
|
||||
const find = entityDetailTags[this.entity.entityType].find(t => t.name === k2)
|
||||
if (find) {
|
||||
this.levelTwoTags.push({ key: k2, value: this.tagValueHandler(k, k2, res.data[k][k2]), type: find.type })
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
if (_.isArray(res.data.userDefinedTags)) {
|
||||
this.levelTwoTags = _.concat(this.levelTwoTags, res.data.userDefinedTags.map(tag => ({ value: tag.tagValue, type: 'normal' })))
|
||||
}
|
||||
this.hideTagArea = _.isEmpty(this.levelTwoTags)
|
||||
}
|
||||
})
|
||||
},
|
||||
tagValueHandler (k, k2, value) {
|
||||
if (k === 'psiphon3Ip') {
|
||||
if (k2 === 'type') {
|
||||
const find = psiphon3IpType.find(t => t.value === value)
|
||||
if (find) {
|
||||
return find.name
|
||||
}
|
||||
}
|
||||
}
|
||||
return value
|
||||
},
|
||||
/* 切换折叠状态 */
|
||||
switchCollapse () {
|
||||
this.isCollapse = !this.isCollapse
|
||||
|
||||
@@ -4,23 +4,23 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">APP ID</div>
|
||||
<div class="row__content">{{entity.appId|| '-'}}</div>
|
||||
<div class="row__content">{{entity.category.appId || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.category')}}</div>
|
||||
<div class="row__content">{{entity.appCategory|| '-'}}</div>
|
||||
<div class="row__content">{{entity.category.appCategory || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.subcategory')}}</div>
|
||||
<div class="row__content">{{entity.appSubcategory || '-'}}</div>
|
||||
<div class="row__content">{{entity.category.appSubcategory || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.riskLevel')}}</div>
|
||||
<div class="row__content">{{appRisk(entity.appRisk) || '-'}}</div>
|
||||
<div class="row__content">{{appRisk(parseInt(entity.category.appRisk)) || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.remark')}}</div>
|
||||
<div class="row__content">{{entity.appDescription || '-'}}</div>
|
||||
<div class="row__content">{{entity.category.appDescription || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -43,103 +43,78 @@
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.appName}`" ></div>
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.entityValue}`" ></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__content row__content-accept">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.appName}`" ></div>
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.entityValue}`" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
|
||||
<loading :loading="loadingNetworkQuality" size="small" inner-style="left: 1rem;"></loading>
|
||||
<div class="entity-score" v-if="!loadingNetworkQuality">
|
||||
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
|
||||
Score:{{score}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.relationship')}}</div>
|
||||
<div class="overview__content domain__content">
|
||||
<div class="overview__tags domain__tags" ref="relationship">
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataOne.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedDomains')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
<span class="tag__desc">{{item.domain}}</span>
|
||||
</div>
|
||||
<div class="overview__tags domain__tags" ref="relationship"></div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.tab.relatedIp')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content overview__row-related">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataOne, 1)" v-if="relationshipShowOne">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreOne" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataOne" :key="item">
|
||||
<span v-if="item.domain" :title="item.domain">{{item.domain}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowOne">
|
||||
<el-popover placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div v-for="(item, index) in relationshipDataOne" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataTwo.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedServerIp')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
<span class="tag__desc">{{item.ip}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row overview__row-related">
|
||||
<div class="row__label row__label--width130">{{$t('entities.tab.relatedIp')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataTwo, 2)" v-if="relationshipShowTwo">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreTwo" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataTwo" :key="item">
|
||||
<span v-if="item.ip" :title="item.ip">{{item.ip}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowTwo">
|
||||
<el-popover class="entity-expand-detail" placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div v-for="(item, index) in relationshipDataTwo" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.networkQuality')}}</div>
|
||||
<div class="overview__content overview__content-loading-net">
|
||||
<loading :loading="loadingNetworkQuality" size="small"></loading>
|
||||
<div class="overview__row overview__row--single-value">
|
||||
<chart-single-value
|
||||
v-for="(chartInfo, i) in singleValues.chartInfos"
|
||||
:chart-info="chartInfo"
|
||||
:chart-data="singleValues.chartDatas[i]"
|
||||
:key="i"
|
||||
class="cn-chart__single-value--detail-overview"
|
||||
></chart-single-value>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('entities.accessLink')}}</div>
|
||||
<div class="overview__content">
|
||||
<div class="overview__tags">
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingOut" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.outLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutId ? entityData.linkOutId : '-'}},</span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingIn" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.inLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInId ? entityData.linkInId : '-'}},</span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.alert')}}</div>
|
||||
<div class="overview__content overview__content-loading">
|
||||
@@ -148,20 +123,17 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="performanceData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__content">{{entityData.performanceNum}}</div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width200">
|
||||
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div>
|
||||
<div>{{performance.eventType}}</div>
|
||||
</div>
|
||||
<div class="row__content-loading" style="position: relative;" >
|
||||
<loading :loading="!loadingAlert && loadingPerformance[index]?loadingPerformance[index]:false" :id="`loading${entity.ipAddr}_${index}`" size="small"></loading>
|
||||
<div class="row__charts" :id="`entityPerformanceChart${entity.appName}_${index}`"></div>
|
||||
<div class="row__content-loading" style="position: relative;">
|
||||
<div class="performance-event-remark">{{performance.eventType}}</div>
|
||||
</div>
|
||||
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-if="performanceData && performanceData.length > 5">
|
||||
@@ -177,15 +149,26 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="securityData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__content">{{entityData.securityNum}}</div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width200">
|
||||
|
||||
<div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
|
||||
<div>{{security.securityType}}</div>
|
||||
</div>
|
||||
<div class="cn-detection__header">
|
||||
<i class="cn-icon cn-icon-attacker"></i>
|
||||
<span>{{ security.offenderIp }}</span>
|
||||
<div class="domain" v-if="security.offenderIp===security.serverIp">{{ security.domain }}</div>
|
||||
<span class="line">-------</span>
|
||||
<span class="circle"></span>
|
||||
<i class="cn-icon cn-icon-attacked"></i>
|
||||
<span>{{ security.victimIp }}</span>
|
||||
<div class="domain" v-if="security.victimIp===security.serverIp">{{ security.domain }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-if="securityData && securityData.length > 5">
|
||||
@@ -213,34 +196,38 @@ import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import Chart from '@/views/charts/Chart'
|
||||
import _ from 'lodash'
|
||||
import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
|
||||
import { get } from '@/utils/http'
|
||||
import relatedServer from '@/mixins/relatedServer'
|
||||
import { getSecond, getMillisecond } from '@/utils/date-util'
|
||||
import { dateFormatByAppearance, getMillisecond, getSecond } from '@/utils/date-util'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
mixins: [entityDetailMixin, relatedServer],
|
||||
components: {
|
||||
Chart,
|
||||
Loading,
|
||||
ChartSingleValue
|
||||
Loading
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
// entityData: {}
|
||||
entityType: 'app',
|
||||
trafficUrl: api.entityAppDetailTraffic,
|
||||
// trafficUrl: api.entityAppDetailTraffic,
|
||||
trafficUrl: api.entity.entityList.appThroughput,
|
||||
relationUrl: api.entityAppDetailRelation,
|
||||
networkQuantityUrl: api.entityAppDetailNetworkQuantity,
|
||||
// networkQuantityUrl: api.entityAppDetailNetworkQuantity,
|
||||
networkQuantityUrl: api.entity.entityList.appPerformance,
|
||||
linkInUrl: api.entityAppDetailLinkIn,
|
||||
linkOutUrl: api.entityAppDetailLinkOut,
|
||||
performanceUrl: api.entityAppDetailPerformance,
|
||||
securityUrl: api.entityAppDetailSecurity,
|
||||
trafficUrlMap: api.entityAppDetailTrafficMap,
|
||||
relatedServerDomainUrl: api.entityAppRelatedServerDomain,
|
||||
relatedServerIpUrl: api.entityAppRelatedServerIp,
|
||||
// performanceUrl: api.entityAppDetailPerformance,
|
||||
performanceUrl: api.entity.entityList.appEventPerformance,
|
||||
securityUrl: api.entity.entityList.appSecurity,
|
||||
// securityUrl: api.entityAppDetailSecurity,
|
||||
// trafficUrlMap: api.entityAppDetailTrafficMap,
|
||||
trafficUrlMap: api.entity.entityList.appTrafficMap,
|
||||
relatedServerDomainUrl: api.entity.entityList.appRelatedDomain,
|
||||
relatedServerIpUrl: api.entity.entityList.appRelatedIp,
|
||||
chartData: null,
|
||||
listMode: 'list',
|
||||
singleValues: {
|
||||
@@ -296,34 +283,34 @@ export default {
|
||||
i18n: 'entities.pktRetransPercent'
|
||||
}
|
||||
],
|
||||
chartDatas: [null, null, null, null, null],
|
||||
loadingTraffic: false,
|
||||
loadingRelationshipOne: false,
|
||||
loadingRelationshipTwo: false,
|
||||
loadingNetworkQuality: false,
|
||||
loadingOut: false,
|
||||
loadingIn: false,
|
||||
loadingAlert: false,
|
||||
loadingSecurityEvents: false,
|
||||
loadingMap: false
|
||||
}
|
||||
chartDatas: [null, null, null, null, null]
|
||||
},
|
||||
loadingTraffic: false,
|
||||
loadingRelationshipOne: false,
|
||||
loadingRelationshipTwo: false,
|
||||
loadingNetworkQuality: false,
|
||||
loadingOut: false,
|
||||
loadingIn: false,
|
||||
loadingAlert: false,
|
||||
loadingSecurityEvents: false,
|
||||
loadingMap: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMillisecond,
|
||||
dateFormatByAppearance,
|
||||
getQueryParams () {
|
||||
const queryParams = {
|
||||
return {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
appName: this.entity.appName
|
||||
resource: this.entity.entityValue,
|
||||
appName: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
getPerformanceQueryParams () {
|
||||
const queryParams = {
|
||||
appName: this.entity.appName
|
||||
return {
|
||||
appName: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
handleRelationData (result) {
|
||||
this.entityData.domainCount = result.domainCount
|
||||
@@ -353,6 +340,7 @@ export default {
|
||||
})
|
||||
},
|
||||
setup (props) {
|
||||
const entityData = ref({ ...props.entity })
|
||||
return {
|
||||
chart: {
|
||||
params: {
|
||||
@@ -366,7 +354,8 @@ export default {
|
||||
entityCopy: {
|
||||
..._.cloneDeep(props.entity)
|
||||
},
|
||||
unitConvert
|
||||
unitConvert,
|
||||
entityData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,36 +4,32 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.category')}}</div>
|
||||
<div class="row__content">{{entityData.domainCategory || '-'}}</div>
|
||||
<div class="row__content">{{entityData.category ? entityData.category.categoryName : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.domainDetail.categoryGroup')}}</div>
|
||||
<div class="row__content">{{entityData.domainCategoryGroup || '-'}}</div>
|
||||
<div class="row__content">{{entityData.category ? entityData.category.categoryGroup : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.reputationLevel')}}</div>
|
||||
<div class="row__content">{{entityData.domainReputationScore || '-'}}</div>
|
||||
<div class="row__content">{{entityData.category ? entityData.category.reputationLevel : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.registration')}}</div>
|
||||
<div class="row__content">{{entityData.domainWhoisAddress || '-'}}</div>
|
||||
<div class="row__content">{{entityData.whois ? entityData.whois.registrantCountry : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.org')}}</div>
|
||||
<div class="row__content">{{entityData.domainWhoisOrg || '-'}}</div>
|
||||
<div class="row__content">{{entityData.whois ? entityData.whois.registrantOrg : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.icpCompanyName')}}</div>
|
||||
<div class="row__content">{{entityData.domainIcpCompanyName || '-'}}</div>
|
||||
<div class="row__content">{{entityData.icp ? entityData.icp.icpCompanyName : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.icpLicense')}}</div>
|
||||
<div class="row__content">{{entityData.domainIcpSiteLicense || '-'}}</div>
|
||||
<div class="row__content">{{entityData.icp ? entityData.icp.icpSiteLicense : '-'}}</div>
|
||||
</div>
|
||||
<!-- <div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.remark')}}</div>
|
||||
<div class="row__content">{{entityData.domainDescription || '-'}}</div>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
@@ -55,103 +51,78 @@
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.domainName}`" >{</div>
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.entityValue}`" >{</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__content row__content-accept">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.domainName}`" ></div>
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.entityValue}`" ></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
|
||||
<loading :loading="loadingNetworkQuality" size="small" inner-style="left: 1rem;"></loading>
|
||||
<div class="entity-score" v-if="!loadingNetworkQuality">
|
||||
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
|
||||
Score:{{score}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.relationship')}}</div>
|
||||
<div class="overview__content domain__content">
|
||||
<div class="overview__tags domain__tags" ref="relationship">
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataOne.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedApp')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
<span class="tag__desc">{{item.appName}}</span>
|
||||
</div>
|
||||
<div class="overview__tags domain__tags" ref="relationship"></div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.tab.relatedApp')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content overview__row-related">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataOne, 1)" v-if="relationshipShowOne">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreOne" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataOne" :key="item">
|
||||
<span v-if="item.appName" :title="item.appName">{{item.appName}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowOne">
|
||||
<el-popover placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div v-for="(item, index) in relationshipDataOne" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataTwo.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedServerIp')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
<span class="tag__desc">{{item.ip}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row overview__row-related">
|
||||
<div class="row__label row__label--width130">{{$t('entities.tab.relatedIp')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataTwo, 2)" v-if="relationshipShowTwo">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreTwo" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataTwo" :key="item">
|
||||
<span v-if="item.ip" :title="item.ip">{{item.ip}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowTwo">
|
||||
<el-popover class="entity-expand-detail" placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div v-for="(item, index) in relationshipDataTwo" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.networkQuality')}}</div>
|
||||
<div class="overview__content overview__content-loading-net">
|
||||
<loading :loading="loadingNetworkQuality" size="small"></loading>
|
||||
<div class="overview__row overview__row--single-value">
|
||||
<chart-single-value
|
||||
v-for="(chartInfo, i) in singleValues.chartInfos"
|
||||
:chart-info="chartInfo"
|
||||
:chart-data="singleValues.chartDatas[i]"
|
||||
:key="i"
|
||||
class="cn-chart__single-value--detail-overview"
|
||||
></chart-single-value>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('entities.accessLink')}}</div>
|
||||
<div class="overview__content">
|
||||
<div class="overview__tags">
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingOut" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.outLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutId ? entityData.linkOutId : '-'}},</span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingIn" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.inLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInId ? entityData.linkInId : '-'}},</span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.alert')}}</div>
|
||||
<div class="overview__content overview__content-loading">
|
||||
@@ -160,18 +131,16 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="performanceData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__content">{{entityData.performanceNum}}</div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width200">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div>
|
||||
<div>{{performance.eventType}}</div>
|
||||
</div>
|
||||
<div class="row__content-loading" style="position: relative;" >
|
||||
<loading :loading="!loadingAlert && loadingPerformance[index]?loadingPerformance[index]:false" :id="`loading${entity.ipAddr}_${index}`" size="small"></loading>
|
||||
<div class="row__charts" :id="`entityPerformanceChart${entity.domainName}_${index}`"></div>
|
||||
<div class="row__content-loading" style="position: relative;">
|
||||
<div class="performance-event-remark">{{performance.eventType}}</div>
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
@@ -188,14 +157,24 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="securityData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__content">{{entityData.securityNum}}</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row overview__row--small-font" v-for="(security, i) in entityData.securityList" :key="i">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(getMillisecond(security.startTime)) || '-'}}</div>
|
||||
<div class="row__content row__content--width200">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(getMillisecond(security.startTime)) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
|
||||
<div>{{security.securityType}}</div>
|
||||
</div>
|
||||
<div class="cn-detection__header">
|
||||
<i class="cn-icon cn-icon-attacker"></i>
|
||||
<span>{{ security.offenderIp }}</span>
|
||||
<div class="domain" v-if="security.offenderIp===security.serverIp">{{ security.domain }}</div>
|
||||
<span class="line">-------</span>
|
||||
<span class="circle"></span>
|
||||
<i class="cn-icon cn-icon-attacked"></i>
|
||||
<span>{{ security.victimIp }}</span>
|
||||
<div class="domain" v-if="security.victimIp===security.serverIp">{{ security.domain }}</div>
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
@@ -218,7 +197,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
|
||||
import { api } from '@/utils/api'
|
||||
import entityDetailMixin from './entityDetailMixin'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
@@ -227,13 +205,13 @@ import Chart from '@/views/charts/Chart'
|
||||
import _ from 'lodash'
|
||||
import { get } from '@/utils/http'
|
||||
import relatedServer from '@/mixins/relatedServer'
|
||||
import { getSecond, getMillisecond } from '@/utils/date-util'
|
||||
import { dateFormatByAppearance, getMillisecond, getSecond } from '@/utils/date-util'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'Domain',
|
||||
components: {
|
||||
ChartSingleValue,
|
||||
Loading,
|
||||
Chart
|
||||
},
|
||||
@@ -242,16 +220,21 @@ export default {
|
||||
return {
|
||||
// entityData: {},
|
||||
entityType: 'domain',
|
||||
trafficUrl: api.entityDomainDetailTraffic,
|
||||
// trafficUrl: api.entityDomainDetailTraffic,
|
||||
trafficUrl: api.entity.entityList.domainThroughput,
|
||||
relationUrl: api.entityDomainDetailRelation,
|
||||
networkQuantityUrl: api.entityDomainDetailNetworkQuantity,
|
||||
networkQuantityUrl: api.entity.entityList.domainPerformance,
|
||||
// networkQuantityUrl: api.entityDomainDetailNetworkQuantity,
|
||||
linkInUrl: api.entityDomainDetailLinkIn,
|
||||
linkOutUrl: api.entityDomainDetailLinkOut,
|
||||
performanceUrl: api.entityDomainDetailPerformance,
|
||||
securityUrl: api.entityDomainDetailSecurity,
|
||||
trafficUrlMap: api.entityDomainDetailTrafficMap,
|
||||
relatedServerIpUrl: api.entityDomainRelatedServerIp,
|
||||
relatedServerAppUrl: api.entityDomainRelatedServerApp,
|
||||
// performanceUrl: api.entityDomainDetailPerformance,
|
||||
performanceUrl: api.entity.entityList.domainEventPerformance,
|
||||
// securityUrl: api.entityDomainDetailSecurity,
|
||||
securityUrl: api.entity.entityList.domainSecurity,
|
||||
// trafficUrlMap: api.entityDomainDetailTrafficMap,
|
||||
trafficUrlMap: api.entity.entityList.domainTrafficMap,
|
||||
relatedServerIpUrl: api.entity.entityList.domainRelatedIp,
|
||||
relatedServerAppUrl: api.entity.entityList.domainRelatedApp,
|
||||
basicProperties: api.entityDomainDetailBasic,
|
||||
chartData: null,
|
||||
listMode: 'list',
|
||||
@@ -308,34 +291,34 @@ export default {
|
||||
i18n: 'entities.pktRetransPercent'
|
||||
}
|
||||
],
|
||||
chartDatas: [null, null, null, null, null],
|
||||
loadingTraffic: false,
|
||||
loadingRelationshipOne: false,
|
||||
loadingRelationshipTwo: false,
|
||||
loadingNetworkQuality: false,
|
||||
loadingOut: false,
|
||||
loadingIn: false,
|
||||
loadingAlert: false,
|
||||
loadingSecurityEvents: false,
|
||||
loadingMap: false
|
||||
}
|
||||
chartDatas: [null, null, null, null, null]
|
||||
},
|
||||
loadingTraffic: false,
|
||||
loadingRelationshipOne: false,
|
||||
loadingRelationshipTwo: false,
|
||||
loadingNetworkQuality: false,
|
||||
loadingOut: false,
|
||||
loadingIn: false,
|
||||
loadingAlert: false,
|
||||
loadingSecurityEvents: false,
|
||||
loadingMap: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getMillisecond,
|
||||
dateFormatByAppearance,
|
||||
getQueryParams () {
|
||||
const queryParams = {
|
||||
return {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
domain: this.entity.domainName
|
||||
resource: this.entity.entityValue,
|
||||
domain: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
getPerformanceQueryParams () {
|
||||
const queryParams = {
|
||||
domain: this.entity.domainName
|
||||
return {
|
||||
domain: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
handleRelationData (result) {
|
||||
this.entityData.appCount = result.appCount
|
||||
@@ -383,9 +366,10 @@ export default {
|
||||
})
|
||||
},
|
||||
setup (props) {
|
||||
const entityData = ref({ ...props.entity })
|
||||
const entityCopy = {
|
||||
..._.cloneDeep(props.entity),
|
||||
domain: props.entity.domainName
|
||||
domain: props.entity.entityValue
|
||||
}
|
||||
return {
|
||||
chart: {
|
||||
@@ -398,7 +382,8 @@ export default {
|
||||
},
|
||||
entityCopy,
|
||||
unitTypes,
|
||||
unitConvert
|
||||
unitConvert,
|
||||
entityData
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,11 +4,15 @@
|
||||
<div class="overview__content">
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('overall.location')}}</div>
|
||||
<div class="row__content">{{ipLocationRegion(entity)}}</div>
|
||||
<div class="row__content">{{ipLocationRegion(entity.location)}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">ASN</div>
|
||||
<div class="row__content">{{entity.ipAsn || '-'}}</div>
|
||||
<div class="row__content">{{entity.asn ? entity.asn.asn : '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.openPort')}}</div>
|
||||
<div class="row__content">{{ openPort }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +48,7 @@
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<loading :loading="!loadingDns && loading" size="small"></loading>
|
||||
<div class="row__charts" :id="`entityDnsServerInfo${entity.ipAddr}`"></div>
|
||||
<div class="row__charts" :id="`entityDnsServerInfo${entity.entityValue}`"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -70,103 +74,77 @@
|
||||
<div class="row__charts-msg">{{$t('overall.sent')}}:{{unitConvert(entityData.bytesSentRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.ipAddr}`"></div>
|
||||
<div class="row__charts" :id="`entityDetailSend${entity.entityValue}`"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row__content">
|
||||
<div class="row__content row__content-accept">
|
||||
<div class="row__charts-msg">{{$t('overall.received')}}:{{unitConvert(entityData.bytesReceivedRate, unitTypes.byte).join(' ')}}ps</div>
|
||||
<!-- 曲线-->
|
||||
<div class="row__content-loading">
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.ipAddr}`"></div>
|
||||
<div class="row__charts" :id="`entityDetailReceived${entity.entityValue}`"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label row__label--width130">{{$t('entities.networkQualityRating')}}</div>
|
||||
<loading :loading="loadingNetworkQuality" size="small" inner-style="left: 1rem;"></loading>
|
||||
<div class="entity-score" v-if="!loadingNetworkQuality">
|
||||
<div class="circle-icon" v-if="score <= 2 || score === '-'" :class="{'data-score-red': score <= 2 || score === '-'}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 4" :class="{'data-score-yellow': score <= 4}" ></div>
|
||||
<div class="circle-icon" v-else-if="score <= 6" :class="{'data-score-green': score <= 6}" ></div>
|
||||
Score:{{score}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.relationship')}}</div>
|
||||
<div class="overview__content domain__content">
|
||||
<div class="overview__tags domain__tags" ref="relationship">
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataOne.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedDomains')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
<span class="tag__desc">{{item.domain}}</span>
|
||||
</div>
|
||||
<div class="overview__tags domain__tags" ref="relationship"></div>
|
||||
<div class="overview__row overview__row-related">
|
||||
<div class="row__label row__label--width130">{{$t('entities.tab.relatedApp')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipOne" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataOne" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataOne, 1)" v-if="relationshipShowOne">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreOne" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataOne" :key="item">
|
||||
<span v-if="item.domain" :title="item.domain">{{item.domain}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowOne">
|
||||
<el-popover placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div class="popover-content" v-for="(item, index) in relationshipDataOne" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__domain-tabs overview__domain-tabs-loading">
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="overview__domain-tab">
|
||||
<div class="overview__tag domain__tag">
|
||||
<span class="tag__value">{{relationshipDataTwo.length}}</span>
|
||||
<span class="tag__desc">{{$t('entities.relatedApp')}}</span>
|
||||
</div>
|
||||
<div class="overview__tag domain__tag-list" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
<span class="tag__desc">{{item.appName}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row overview__row-related">
|
||||
<div class="row__label row__label--width130">{{$t('entities.relatedDomain')}}</div>
|
||||
|
||||
<loading :loading="loadingRelationshipTwo" size="small" inner-style="left: 1rem;" style="width: 50%;"></loading>
|
||||
<div class="row__content">
|
||||
<div class="data-item" v-show="item.show" v-for="(item, index) in relationshipDataTwo" :key="index">
|
||||
{{item.value}}
|
||||
</div>
|
||||
<div class="overview__domain-btn">
|
||||
<div class="overview__domain-more" @click="more(relationshipDataTwo, 2)" v-if="relationshipShowTwo">...</div>
|
||||
<div class="overview__domain-more-tabs show-more-list" v-if="relationshipShowMoreTwo" v-ele-click-outside="mouseout">
|
||||
<div class="domain-more-tab" v-for="item in relationshipMoreDataTwo" :key="item">
|
||||
<span v-if="item.appName" :title="item.appName">{{item.appName}}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="relationshipShowTwo">
|
||||
<el-popover class="entity-expand-detail" placement="right-end" trigger="click" show-arrow="false" offset="20">
|
||||
<template #reference>
|
||||
<div class="data-item show-more-related">...</div>
|
||||
</template>
|
||||
<div v-for="(item, index) in relationshipDataTwo" :key="index">{{item.value}}</div>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.networkQuality')}}</div>
|
||||
<div class="overview__content overview__content-loading-net">
|
||||
<loading :loading="loadingNetworkQuality" size="small"></loading>
|
||||
<div class="overview__row overview__row--single-value">
|
||||
<chart-single-value
|
||||
v-for="(chartInfo, i) in singleValues.chartInfos"
|
||||
:chart-info="chartInfo"
|
||||
:chart-data="singleValues.chartDatas[i]"
|
||||
:key="i"
|
||||
class="cn-chart__single-value--detail-overview"
|
||||
></chart-single-value>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('entities.accessLink')}}</div>
|
||||
<div class="overview__content">
|
||||
<div class="overview__tags">
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingOut" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.outLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutId ? entityData.linkOutId : '-'}}, </span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkOutPercent ? unitConvert(entityData.linkOutPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
<div class="overview__tag overview__tag-loading">
|
||||
<loading :loading="loadingIn" size="small"></loading>
|
||||
<span class="tag__desc">{{$t('entities.inLinkTrafficPercentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInId ? entityData.linkInId : '-'}}, </span>
|
||||
<span class="tag__desc">{{$t('entities.percentage')}}</span>
|
||||
<span class="tag__value">{{entityData.linkInPercent ? unitConvert(entityData.linkInPercent, unitTypes.percent).join(' ') : '-'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="overview-item">
|
||||
<div class="overview__title">{{$t('overall.alert')}}</div>
|
||||
<div class="overview__content overview__content-loading">
|
||||
@@ -175,18 +153,16 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="performanceData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentAlert')}}</div>
|
||||
<div class="row__content">{{entityData.performanceNum}}</div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-for="(performance, index) in entityData.performanceList" :key="index">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(performance.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(performance)">{{performance.eventSeverity}}</div>
|
||||
<div>{{performance.eventType}}</div>
|
||||
</div>
|
||||
<div class="row__content-loading" style="position: relative; padding-left: 10px;">
|
||||
<loading :loading="!loadingAlert && loadingPerformance[index]?loadingPerformance[index]:false" :id="`loading${entity.ipAddr}_${index}`" size="small"></loading>
|
||||
<div class="row__charts" :id="`entityPerformanceChart${entity.ipAddr}_${index}`"></div>
|
||||
<div class="row__content-loading" style="position: relative;">
|
||||
<div class="performance-event-remark">{{performance.eventType}}</div>
|
||||
</div>
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
@@ -203,15 +179,26 @@
|
||||
<span class="no-recent-alerts"><i class="el-icon-success"></i>{{$t('relationShip.noRecentAlerts')}}</span>
|
||||
</div>
|
||||
<div class="overview__row" v-if="securityData.length > 0">
|
||||
<div class="row__label">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__label row__label--width130">{{$t('entities.recentSecurity')}}</div>
|
||||
<div class="row__content">{{entityData.securityNum}}</div>
|
||||
</div>
|
||||
|
||||
<div class="overview__row overview__row--small-font" v-for="(security, index) in entityData.securityList" :key="index">
|
||||
<div class="row__label row__label--width160">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width200">
|
||||
<div class="row__label row__label--width130">{{dateFormatByAppearance(security.startTime) || '-'}}</div>
|
||||
<div class="row__content row__content--width90">
|
||||
<div class="alert-level-tag alert-level-tag--high" :class="iconClass(security)">{{security.eventSeverity}}</div>
|
||||
<div>{{security.securityType}}</div>
|
||||
</div>
|
||||
<div class="cn-detection__header" >
|
||||
<i class="cn-icon cn-icon-attacker"></i>
|
||||
<span>{{ security.offenderIp }}</span>
|
||||
<div class="domain" v-if="security.offenderIp===security.serverIp">{{ security.domain }}</div>
|
||||
<span class="line">-------</span>
|
||||
<span class="circle"></span>
|
||||
<i class="cn-icon cn-icon-attacked"></i>
|
||||
<span>{{ security.victimIp }}</span>
|
||||
<div class="domain" v-if="security.victimIp===security.serverIp">{{ security.domain }}</div>
|
||||
</div>
|
||||
|
||||
<div class="row__desc"></div>
|
||||
</div>
|
||||
<div class="overview__row overview__row--small-font" v-if="securityData && securityData.length > 5">
|
||||
@@ -234,7 +221,6 @@
|
||||
|
||||
<script>
|
||||
import entityDetailMixin from './entityDetailMixin'
|
||||
import ChartSingleValue from '@/views/charts/charts/ChartSingleValue'
|
||||
import { api } from '@/utils/api'
|
||||
import { unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
@@ -242,30 +228,35 @@ import Chart from '@/views/charts/Chart'
|
||||
import _ from 'lodash'
|
||||
import { get } from '@/utils/http'
|
||||
import relatedServer from '@/mixins/relatedServer'
|
||||
import { getSecond, getMillisecond } from '@/utils/date-util'
|
||||
import { dateFormatByAppearance, getMillisecond, getSecond } from '@/utils/date-util'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import axios from 'axios'
|
||||
|
||||
export default {
|
||||
name: 'Ip',
|
||||
mixins: [entityDetailMixin, relatedServer],
|
||||
components: {
|
||||
Loading,
|
||||
Chart,
|
||||
ChartSingleValue
|
||||
Chart
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
entityType: 'ip',
|
||||
trafficUrl: api.entityIpDetailTraffic,
|
||||
trafficUrlMap: api.entityIpDetailTrafficMap,
|
||||
// trafficUrl: api.entityIpDetailTraffic,
|
||||
trafficUrl: api.entity.entityList.ipThroughput,
|
||||
// trafficUrlMap: api.entityIpDetailTrafficMap,
|
||||
trafficUrlMap: api.entity.entityList.ipTrafficMap,
|
||||
relationUrl: api.entityIpDetailRelation,
|
||||
networkQuantityUrl: api.entityIpDetailNetworkQuantity,
|
||||
// networkQuantityUrl: api.entityIpDetailNetworkQuantity,
|
||||
networkQuantityUrl: api.entity.entityList.ipPerformance,
|
||||
linkInUrl: api.entityIpDetailLinkIn,
|
||||
linkOutUrl: api.entityIpDetailLinkOut,
|
||||
performanceUrl: api.entityIpDetailPerformance,
|
||||
securityUrl: api.entityIpDetailSecurity,
|
||||
relatedServerDomainUrl: api.entityIpRelatedServerDomain,
|
||||
relatedServerAppUrl: api.entityIpRelatedServerApp,
|
||||
performanceUrl: api.entity.entityList.ipEventPerformance,
|
||||
// performanceUrl: api.entityIpDetailPerformance,
|
||||
// securityUrl: api.entityIpDetailSecurity,
|
||||
securityUrl: api.entity.entityList.ipSecurity,
|
||||
relatedServerDomainUrl: api.entity.entityList.ipRelatedDomain,
|
||||
relatedServerAppUrl: api.entity.entityList.ipRelatedApp,
|
||||
entityDetectionsIpUrl: api.entityDetectionsIp,
|
||||
entityDetectionsIpQueryRateUrl: api.entityDetectionsIpQueryRate,
|
||||
listMode: 'list',
|
||||
@@ -336,21 +327,22 @@ export default {
|
||||
loadingIn: false,
|
||||
loadingAlert: false,
|
||||
loadingSecurityEvents: false,
|
||||
loadingMap: false
|
||||
loadingMap: false,
|
||||
openPort: '-'
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
ipLocationRegion () {
|
||||
return function (entityData) {
|
||||
let result = ''
|
||||
if (entityData.ipLocationCountry) {
|
||||
result += `${entityData.ipLocationCountry},`
|
||||
if (entityData.country) {
|
||||
result += `${entityData.country},`
|
||||
}
|
||||
if (entityData.ipLocationProvince) {
|
||||
result += `${entityData.ipLocationProvince},`
|
||||
if (entityData.province) {
|
||||
result += `${entityData.province},`
|
||||
}
|
||||
if (entityData.ipLocationCity) {
|
||||
result += `${entityData.ipLocationCity},`
|
||||
if (entityData.city) {
|
||||
result += `${entityData.city},`
|
||||
}
|
||||
result = result.substr(0, result.length - 1)
|
||||
if (!result) {
|
||||
@@ -381,19 +373,19 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
getMillisecond,
|
||||
dateFormatByAppearance,
|
||||
getQueryParams () {
|
||||
const queryParams = {
|
||||
return {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
ip: this.entity.ipAddr
|
||||
resource: this.entity.entityValue,
|
||||
ip: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
getPerformanceQueryParams () {
|
||||
const queryParams = {
|
||||
serverIp: this.entity.ipAddr
|
||||
return {
|
||||
serverIp: this.entity.entityValue
|
||||
}
|
||||
return queryParams
|
||||
},
|
||||
handleRelationData (result) {
|
||||
this.entityData.appCount = result.appCount
|
||||
@@ -411,11 +403,29 @@ export default {
|
||||
queryRelated () {
|
||||
this.getRelatedServerDataOne(this.relatedServerDomainUrl)
|
||||
this.getRelatedServerDataTwo(this.relatedServerAppUrl)
|
||||
},
|
||||
getOpenPort () {
|
||||
const params = {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
resource: this.entity.entityValue
|
||||
}
|
||||
|
||||
axios.get(api.entity.entityList.ipRelatedPort, { params: params }).then(res => {
|
||||
if (res.data.code === 200 && res.data.data.result.length) {
|
||||
this.openPort = ''
|
||||
res.data.data.result.forEach(item => {
|
||||
this.openPort += item.port + '/' + item.l7Protocol + ','
|
||||
})
|
||||
this.openPort = this.openPort.slice(0, -1)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.queryParams = this.getQueryParams()
|
||||
this.chartGetMap()
|
||||
this.getOpenPort()
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.queryRelated()
|
||||
@@ -425,7 +435,7 @@ export default {
|
||||
setup (props) {
|
||||
const entityCopy = {
|
||||
..._.cloneDeep(props.entity),
|
||||
ip: props.entity.ipAddr
|
||||
ip: props.entity.entityValue
|
||||
}
|
||||
return {
|
||||
chart: {
|
||||
@@ -434,7 +444,7 @@ export default {
|
||||
unitType: 'number',
|
||||
valueColumn: 'sessions'
|
||||
},
|
||||
id: props.entity.ipAddr,
|
||||
id: props.entity.entityValue,
|
||||
type: 2
|
||||
},
|
||||
entityCopy,
|
||||
@@ -444,3 +454,110 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
//.type-content {
|
||||
// margin-bottom:15px;
|
||||
// display:flex;
|
||||
// flex-flow: row wrap;
|
||||
// width:100%;
|
||||
.data-item {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: rgba(119,131,145,0.06);
|
||||
border: 1px solid rgba(119,131,145,0.36);
|
||||
border-radius: 2px;
|
||||
height:28px;
|
||||
padding:8px 15px;
|
||||
margin-right:10px;
|
||||
//margin-bottom:15px;
|
||||
font-size: 12px;
|
||||
color: #353636;
|
||||
font-weight: 400;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.show-more-related {
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
padding-bottom: 12px;
|
||||
cursor: pointer;
|
||||
}
|
||||
//}
|
||||
.entity-score {
|
||||
.circle-icon {
|
||||
border-radius: 3px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.data-score-red {
|
||||
background: #E26154;
|
||||
}
|
||||
.data-score-yellow {
|
||||
background: #E5A219;
|
||||
}
|
||||
.data-score-green {
|
||||
background: #749F4D;
|
||||
}
|
||||
height:24px;
|
||||
font-size: 14px;
|
||||
color: #046ECA;
|
||||
font-weight: 500;
|
||||
display:flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.cn-detection__header {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
padding-bottom: 3px;
|
||||
color: #333333;
|
||||
align-items: center;
|
||||
font-size: 12px;
|
||||
|
||||
i {
|
||||
color: #7b8fa2;
|
||||
margin-right: 5px;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.line {
|
||||
color: #da5656;
|
||||
margin-left: 12px;
|
||||
font-size: xx-small;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.circle {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
border: 2px solid #da5656;
|
||||
border-radius: 10px;
|
||||
margin-top: 4px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.domain {
|
||||
background: #EFF2F5;
|
||||
border-radius: 2px;
|
||||
font-size: 14px;
|
||||
color: #333333;
|
||||
letter-spacing: 0;
|
||||
line-height: 14px;
|
||||
margin-left: 5px;
|
||||
font-style: italic;
|
||||
padding: 0 2px;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
.el-popper {
|
||||
min-width: 90px !important;
|
||||
width: auto !important;
|
||||
max-width: 300px !important;
|
||||
max-height: 180px !important;
|
||||
overflow: scroll !important;
|
||||
line-height: 24px !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -6,7 +6,7 @@ import { riskLevelMapping, unitTypes } from '@/utils/constants'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import { shallowRef, markRaw } from 'vue'
|
||||
import { metricOption } from '@/views/detections/options/detectionOptions'
|
||||
import { sortBy, reverseSortBy } from '@/utils/tools'
|
||||
import { sortBy, reverseSortBy, computeScore } from '@/utils/tools'
|
||||
import { getSecond } from '@/utils/date-util'
|
||||
import { api } from '@/utils/api'
|
||||
|
||||
@@ -45,29 +45,13 @@ export default {
|
||||
metricChart: null,
|
||||
performanceChartList: [],
|
||||
loadingPerformance: [],
|
||||
|
||||
score: '-', // 网络质量评分
|
||||
performanceMetricEndTimeInterval: 3600 // 服务质量事件指标的结束时间与开始时间的秒间隔
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
entityName () {
|
||||
let name
|
||||
switch (this.entity.entityType) {
|
||||
case ('ip'): {
|
||||
name = this.entity.ipAddr
|
||||
break
|
||||
}
|
||||
case ('domain'): {
|
||||
name = this.entity.domainName
|
||||
break
|
||||
}
|
||||
case ('app'): {
|
||||
name = this.entity.appName
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
return name
|
||||
return this.entity.entityValue
|
||||
},
|
||||
appRisk () {
|
||||
return function (level) {
|
||||
@@ -234,7 +218,7 @@ export default {
|
||||
this.performanceChartList.push(metricChart)
|
||||
this.echartsArray.push(shallowRef(metricChart))
|
||||
} else {
|
||||
const chartDom = document.getElementById(`entityPerformanceChart${this.entityName}${index}`)
|
||||
const chartDom = document.getElementById(`entityPerformanceChart${this.entityName}_${index}`)
|
||||
chartDom.innerHTML = '<span style="padding-left:5px;">-</span>'
|
||||
}
|
||||
})
|
||||
@@ -272,6 +256,14 @@ export default {
|
||||
if (this.networkQuantityUrl) {
|
||||
get(this.networkQuantityUrl, this.getQueryParams()).then(response => {
|
||||
if (response.code === 200) {
|
||||
const data = {
|
||||
establishLatencyMs: response.data.result.establishLatencyValue || null,
|
||||
httpResponseLatency: response.data.result.httpResponseLatencyValue || null,
|
||||
sslConLatency: response.data.result.sslConLatencyValue || null,
|
||||
tcpLostlenPercent: response.data.result.sequenceGapLossPercentValue || null,
|
||||
pktRetransPercent: response.data.result.pktRetransPercentValue || null
|
||||
}
|
||||
this.score = computeScore(data)
|
||||
this.entityData.establishLatencyValue = response.data.result.establishLatencyValue
|
||||
this.entityData.establishLatencyP50 = response.data.result.establishLatencyP50
|
||||
this.entityData.establishLatencyP90 = response.data.result.establishLatencyP90
|
||||
@@ -389,11 +381,6 @@ export default {
|
||||
this.entityData.performanceNum = response.data.result.length
|
||||
this.performanceData = response.data.result
|
||||
this.entityData.performanceList = this.getTargetPageData(1, this.showMore.performancePageSize, this.performanceData)
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
this.queryEntityDetailPerformanceChart(this.entityData.performanceList, 0)
|
||||
}, 200)
|
||||
})
|
||||
}
|
||||
this.loadingAlert = false
|
||||
})
|
||||
@@ -412,16 +399,16 @@ export default {
|
||||
},
|
||||
|
||||
performanceShowMore (num) {
|
||||
const startIndex = this.showMore.performancePageSize
|
||||
// const startIndex = this.showMore.performancePageSize
|
||||
this.showMore.performancePageSize += num
|
||||
this.entityData.performanceList = this.getTargetPageData(this.showMore.pageNo, this.showMore.performancePageSize, this.performanceData)
|
||||
this.$nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (this.entityData.performanceList && this.entityData.performanceList.length > 0) {
|
||||
this.queryEntityDetailPerformanceChart(this.entityData.performanceList.slice(startIndex, this.entityData.performanceList.length), startIndex)
|
||||
}
|
||||
}, 200)
|
||||
})
|
||||
// this.$nextTick(() => {
|
||||
// setTimeout(() => lltext
|
||||
// if (this.entityData.performanceList && this.entityData.performanceList.length > 0) {
|
||||
// this.queryEntityDetailPerformanceChart(this.entityData.performanceList.slice(startIndex, this.entityData.performanceList.length), startIndex)
|
||||
// }
|
||||
// }, 200)
|
||||
// })
|
||||
},
|
||||
|
||||
securityShowMore (num) {
|
||||
@@ -520,6 +507,7 @@ export default {
|
||||
this.chartOption = _.cloneDeep(entityListLineOption)
|
||||
setTimeout(() => { this.queryEntityDetail() })
|
||||
const _this = this
|
||||
this.entityData = { ...this.entityData, ...this.entity }
|
||||
this.emitter.on('switch-collapse', function () {
|
||||
setTimeout(() => { _this.queryEntityDetail() }, 200)
|
||||
})
|
||||
|
||||
@@ -45,43 +45,10 @@ export default {
|
||||
return className
|
||||
},
|
||||
entityType () {
|
||||
let type
|
||||
switch (this.entityData.entityType) {
|
||||
case 'ip': {
|
||||
type = this.entityData.ipAddr
|
||||
break
|
||||
}
|
||||
case 'domain': {
|
||||
type = this.entityData.domainName
|
||||
break
|
||||
}
|
||||
case 'app': {
|
||||
type = this.entityData.appName
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
return type
|
||||
return this.entity.entityValue
|
||||
},
|
||||
entityName () {
|
||||
let name
|
||||
switch (this.entityData.entityType) {
|
||||
case ('ip'): {
|
||||
name = this.entity.ipAddr
|
||||
break
|
||||
}
|
||||
case ('domain'): {
|
||||
name = this.entity.domainName
|
||||
break
|
||||
}
|
||||
case ('app'): {
|
||||
name = this.entity.appName
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
return name
|
||||
return this.entity.entityValue
|
||||
},
|
||||
appRisk () {
|
||||
return function (level) {
|
||||
@@ -94,32 +61,11 @@ export default {
|
||||
queryParams () {
|
||||
let params
|
||||
const now = window.$dayJs.tz().valueOf()
|
||||
switch (this.entityData.entityType) {
|
||||
case ('ip'): {
|
||||
params = {
|
||||
startTime: this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : Math.floor(now / 1000 - 3600),
|
||||
endTime: this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : Math.floor(now / 1000),
|
||||
ip: this.entityData.ipAddr
|
||||
}
|
||||
break
|
||||
}
|
||||
case ('domain'): {
|
||||
params = {
|
||||
startTime: this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : Math.floor(now / 1000 - 3600),
|
||||
endTime: this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : Math.floor(now / 1000),
|
||||
domain: this.entityData.domainName
|
||||
}
|
||||
break
|
||||
}
|
||||
case ('app'): {
|
||||
params = {
|
||||
startTime: this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : Math.floor(now / 1000 - 3600),
|
||||
endTime: this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : Math.floor(now / 1000),
|
||||
appName: this.entityData.appName
|
||||
}
|
||||
break
|
||||
}
|
||||
default: break
|
||||
// eslint-disable-next-line prefer-const
|
||||
params = {
|
||||
startTime: this.timeFilter.startTime ? getSecond(this.timeFilter.startTime) : Math.floor(now / 1000 - 3600),
|
||||
endTime: this.timeFilter.endTime ? getSecond(this.timeFilter.endTime) : Math.floor(now / 1000),
|
||||
resource: this.entityData.entityValue
|
||||
}
|
||||
return params
|
||||
}
|
||||
@@ -130,7 +76,7 @@ export default {
|
||||
path: '/entityDetail',
|
||||
query: {
|
||||
entityType: this.entityData.entityType,
|
||||
entityName: this.entityData.ipAddr || this.entityData.domainName || this.entityData.appName
|
||||
entityName: this.entityData.entityValue
|
||||
}
|
||||
})
|
||||
window.open(href, '_blank')
|
||||
@@ -140,7 +86,7 @@ export default {
|
||||
path: '/entityGraph',
|
||||
query: {
|
||||
entityType: this.entityData.entityType,
|
||||
entityName: this.entityData.ipAddr || this.entityData.domainName || this.entityData.appName
|
||||
entityName: this.entityData.entityValue
|
||||
}
|
||||
})
|
||||
window.open(href, '_blank')
|
||||
@@ -209,9 +155,7 @@ export default {
|
||||
return {
|
||||
startTime: getSecond(this.timeFilter.startTime),
|
||||
endTime: getSecond(this.timeFilter.endTime),
|
||||
appName: this.entityType,
|
||||
domain: this.entityType,
|
||||
ip: this.entityType
|
||||
resource: this.entityType
|
||||
}
|
||||
},
|
||||
queryEntityDetailTraffic () {
|
||||
@@ -295,30 +239,36 @@ export default {
|
||||
},
|
||||
resize () {
|
||||
this.echartsArray.forEach(item => { item.value.resize() })
|
||||
},
|
||||
initUrl () {
|
||||
if (this.entity.entityType) {
|
||||
switch (this.entity.entityType) {
|
||||
case 'ip': {
|
||||
// this.trafficUrl = api.entityIpDetailTraffic
|
||||
this.trafficUrl = api.entity.entityList.ipThroughput
|
||||
break
|
||||
}
|
||||
case 'domain': {
|
||||
// this.trafficUrl = api.entityDomainDetailTraffic
|
||||
this.trafficUrl = api.entity.entityList.domainThroughput
|
||||
break
|
||||
}
|
||||
case 'app': {
|
||||
// this.trafficUrl = api.entityAppDetailTraffic
|
||||
this.trafficUrl = api.entity.entityList.appThroughput
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
entityData: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (n.entityType) {
|
||||
switch (n.entityType) {
|
||||
case 'ip': {
|
||||
this.trafficUrl = api.entityIpDetailTraffic
|
||||
break
|
||||
}
|
||||
case 'domain': {
|
||||
this.trafficUrl = api.entityDomainDetailTraffic
|
||||
break
|
||||
}
|
||||
case 'app': {
|
||||
this.trafficUrl = api.entityAppDetailTraffic
|
||||
break
|
||||
}
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
this.initUrl()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -326,7 +276,9 @@ export default {
|
||||
this.debounceFunc = this.$_.debounce(this.resize, 200)
|
||||
window.addEventListener('resize', this.debounceFunc)
|
||||
this.chartOption = _.cloneDeep(entityListLineOption)
|
||||
this.entityData = _.cloneDeep(this.entity)
|
||||
// this.entityData = _.cloneDeep(this.entity)
|
||||
this.entityData = { ...this.entityData, ...this.entity }
|
||||
this.initUrl()
|
||||
setTimeout(() => {
|
||||
this.querySecurity()
|
||||
this.queryEntityDetailTraffic()
|
||||
|
||||
@@ -2,9 +2,7 @@
|
||||
<div class="explorer-search">
|
||||
<div class="explorer-search__title" v-show="!showList">{{$t('search.title')}}</div>
|
||||
<div class="explorer-search__input-case" :class="{'explorer-search__input-case--question-mark-in-line': showList}">
|
||||
<div class="explorer-search__input">
|
||||
<!--新版实体列表改版,后续记得解开-->
|
||||
<!--<div class="explorer-search__input" style="border: 1px #DEDEDE solid;height: 42px;">-->
|
||||
<div class="explorer-search__input" style="border: 1px #DEDEDE solid;height: 42px;">
|
||||
<advanced-search
|
||||
ref="search"
|
||||
:column-list="columnList"
|
||||
|
||||
Reference in New Issue
Block a user