892 lines
30 KiB
Vue
892 lines
30 KiB
Vue
<template>
|
||
<div
|
||
class="entity-explorer"
|
||
:class="{'entity-explorer--show-list': showList}">
|
||
<!-- 顶部工具栏,在列表页显示 -->
|
||
<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>
|
||
<!-- 搜索组件 -->
|
||
<explorer-search
|
||
v-if="!showList"
|
||
ref="search"
|
||
:class="{'explorer-search--show-list': showList}"
|
||
:show-list="showList"
|
||
@search="search"
|
||
></explorer-search>
|
||
<!-- 内容区 -->
|
||
<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 explorer-container-new">
|
||
<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" style="position: relative;">
|
||
<loading :loading="loadingCount" style="width: 240px"></loading>
|
||
<span>{{ summaryCount.total }} </span>results,IP
|
||
<span>{{ summaryCount.ipCount }}</span>,Domain
|
||
<span>{{ summaryCount.domainCount }}</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-if="!showList">
|
||
<div>
|
||
<el-divider direction="vertical"></el-divider>
|
||
<div class="entity-overview">
|
||
<div class="overview-left">
|
||
<span class="overview-left-loading">
|
||
<loading :loading="loadingApp"></loading>
|
||
<span class="overview-left-loading-span">{{ numberWithCommas(entityAppTotal) }}</span>
|
||
</span>
|
||
</div>
|
||
<div class="overview-right">
|
||
<div class="right-row">
|
||
APP
|
||
</div>
|
||
<div class="right-row">
|
||
<i class="cn-icon cn-icon-active"></i>
|
||
<div class="right-label">Active</div>
|
||
<div class="right-label-loading">
|
||
<loading :loading="loadingAppActive" size="small"></loading>
|
||
<div class="right-value">{{ numberWithCommas(entityAppActive) }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<el-divider direction="vertical"></el-divider>
|
||
<div class="entity-overview">
|
||
<div class="overview-left">
|
||
<span class="overview-left-loading">
|
||
<loading :loading="loadingDomain"></loading>
|
||
<span class="overview-left-loading-span">{{ numberWithCommas(entityDomainTotal) }}</span>
|
||
</span>
|
||
</div>
|
||
<div class="overview-right">
|
||
<div class="right-row">
|
||
DOMAIN
|
||
</div>
|
||
<div class="right-row">
|
||
<i class="cn-icon cn-icon-active"></i>
|
||
<div class="right-label">Active</div>
|
||
<div class="right-label-loading">
|
||
<loading :loading="loadingDomainActive" size="small"></loading>
|
||
<div class="right-value">{{ numberWithCommas(entityDomainActive) }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<el-divider direction="vertical"></el-divider>
|
||
<div class="entity-overview">
|
||
<div class="overview-left">
|
||
<span class="overview-left-loading">
|
||
<loading :loading="loadingIp"></loading>
|
||
<span class="overview-left-loading-span">{{ numberWithCommas(entityIpTotal) }}</span>
|
||
</span>
|
||
</div>
|
||
<div class="overview-right">
|
||
<div class="right-row">
|
||
IP
|
||
</div>
|
||
<div class="right-row">
|
||
<i class="cn-icon cn-icon-active"></i>
|
||
<div class="right-label">Active</div>
|
||
<div class="right-label-loading">
|
||
<loading :loading="loadingIpActive" size="small"></loading>
|
||
<div class="right-value">{{ numberWithCommas(entityIpActive) }}</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<el-divider direction="vertical"></el-divider>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
import ExplorerSearch from '@/views/entityExplorer/search/ExplorerSearch'
|
||
import EntityFilter from '@/views/entityExplorer/EntityFilter'
|
||
import EntityList from '@/views/entityExplorer/entityList/EntityList'
|
||
import { entityType, defaultPageSize, riskLevelMapping } from '@/utils/constants'
|
||
import { get } from '@/utils/http'
|
||
import { api } from '@/utils/api'
|
||
import { getNowTime, getSecond } from '@/utils/date-util'
|
||
import { ref } from 'vue'
|
||
import _ from 'lodash'
|
||
import Loading from '@/components/common/Loading'
|
||
import { overwriteUrl, urlParamsHandler, numberWithCommas } from '@/utils/tools'
|
||
import Parser from '@/components/advancedSearch/meta/parser'
|
||
import { handleErrorTip } from '@/components/advancedSearch/meta/error'
|
||
import { columnList } from '@/utils/static-data'
|
||
import { useRoute } from 'vue-router'
|
||
|
||
export default {
|
||
name: 'entity-explorer',
|
||
components: {
|
||
Loading,
|
||
ExplorerSearch,
|
||
EntityFilter,
|
||
EntityList
|
||
},
|
||
data () {
|
||
return {
|
||
showList: false,
|
||
listMode: 'list', // entity列表的模式,list|block
|
||
|
||
entityAppTotal: '-',
|
||
entityAppNew: '-',
|
||
entityAppActive: '-',
|
||
|
||
entityDomainTotal: '-',
|
||
entityDomainNew: '-',
|
||
entityDomainActive: '-',
|
||
|
||
entityIpTotal: '-',
|
||
entityIpNew: '-',
|
||
entityIpActive: '-',
|
||
|
||
pageObj: {
|
||
pageNo: 1,
|
||
// 是否重置pageNo,在执行新搜索时是true
|
||
resetPageNo: true,
|
||
pageSize: defaultPageSize,
|
||
total: 0
|
||
},
|
||
filterData: [
|
||
{
|
||
type: 'ip',
|
||
title: entityType.ip,
|
||
totalCount: 0,
|
||
data: [
|
||
{
|
||
label: this.$t('overall.country'),
|
||
column: 'countryDistinctCount',
|
||
topColumn: 'Country', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-country',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('overall.city'),
|
||
column: 'cityDistinctCount',
|
||
topColumn: 'City', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-city',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('entities.asn'),
|
||
column: 'asnDistinctCount',
|
||
topColumn: 'ASN', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-cloud',
|
||
showTopTen: false,
|
||
value: 0
|
||
}
|
||
]
|
||
},
|
||
{
|
||
type: 'app',
|
||
title: entityType.app,
|
||
totalCount: 0,
|
||
data: [
|
||
{
|
||
label: this.$t('entities.category'),
|
||
column: 'categoryDistinctCount',
|
||
topColumn: 'app_category', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-category',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('entities.subcategory'),
|
||
column: 'subcategoryDistinctCount',
|
||
topColumn: 'app_subcategory', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-sub-category',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('entities.risk'),
|
||
column: 'riskDistinctCount',
|
||
topColumn: 'app_risk', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-risk',
|
||
showTopTen: false,
|
||
value: 0
|
||
}
|
||
]
|
||
},
|
||
{
|
||
type: 'domain',
|
||
title: entityType.domain,
|
||
totalCount: 0,
|
||
data: [
|
||
{
|
||
label: this.$t('entities.domainDetail.categoryGroup'),
|
||
column: 'categoryGroupDistinctCount',
|
||
topColumn: 'domain_category_group', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-category',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('entities.category'),
|
||
column: 'categoryDistinctCount',
|
||
topColumn: 'domain_category', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-sub-category',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('entities.reputationLevel'),
|
||
column: 'reputationLevelDistinctCount',
|
||
topColumn: 'domain_reputation_level', // top弹框查询字段
|
||
icon: 'cn-icon cn-icon-credit',
|
||
showTopTen: false,
|
||
value: 0
|
||
}
|
||
]
|
||
},
|
||
{
|
||
type: 'dns',
|
||
title: this.$t('dns.dnsServer'),
|
||
totalCount: 0,
|
||
osTotalCount: 0,
|
||
orgTotalCount: 0,
|
||
softwareTotalCount: 0,
|
||
data: [
|
||
{
|
||
label: this.$t('overall.dnsServerInfo.role'),
|
||
column: 'dnsServerRoleCount',
|
||
topColumn: 'dns_server_role',
|
||
icon: 'cn-icon cn-icon-role',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('dns.managementOrganization'),
|
||
column: 'dnsServerOrgCount',
|
||
topColumn: 'dns_server_org',
|
||
icon: 'cn-icon cn-icon-org',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('overall.dnsServerInfo.software'),
|
||
column: 'dnsServerSoftwareCount',
|
||
topColumn: 'dns_server_software',
|
||
icon: 'cn-icon cn-icon-software',
|
||
showTopTen: false,
|
||
value: 0
|
||
},
|
||
{
|
||
label: this.$t('overall.dnsServerInfo.system'),
|
||
column: 'dnsServerOsCount',
|
||
topColumn: 'dns_server_os',
|
||
icon: 'cn-icon cn-icon-os',
|
||
showTopTen: false,
|
||
value: 0
|
||
}
|
||
]
|
||
}
|
||
],
|
||
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: [],
|
||
limitFilterType: true, // 是否限定了filter的类型
|
||
listLoading: false,
|
||
// 实体详情搜索页面 底部列表
|
||
loadingApp: false,
|
||
loadingDomain: false,
|
||
loadingIp: false,
|
||
// New
|
||
loadingAppNew: false,
|
||
loadingDomainNew: false,
|
||
loadingIpNew: false,
|
||
// Active
|
||
loadingAppActive: false,
|
||
loadingDomainActive: false,
|
||
loadingIpActive: false,
|
||
|
||
// 实体详情列表页面 左侧筛选条件
|
||
loadingLeft: false,
|
||
initFlag: false, // 初始化标志,避免初始化时pageSize和pageNo会调用搜索
|
||
timer: null, // 初始化标志的延时器,需要销毁
|
||
summaryCount: {
|
||
total: 0,
|
||
domainCount: 0,
|
||
ipCount: 0,
|
||
appCount: 0
|
||
},
|
||
loadingCount: false // 实体基数统计的loading
|
||
}
|
||
},
|
||
methods: {
|
||
numberWithCommas,
|
||
timeRefreshChange () {
|
||
if (!this.$refs.dateTimeRange.isCustom) {
|
||
const value = this.timeFilter.dateRangeValue
|
||
this.$refs.dateTimeRange.quickChange(value)
|
||
}
|
||
},
|
||
reload (s, e, v) {
|
||
this.dateTimeRangeChange(s, e, v)
|
||
},
|
||
// methods
|
||
dateTimeRangeChange (s, e, v) {
|
||
this.timeFilter = { startTime: s, endTime: e, dateRangeValue: v }
|
||
},
|
||
// sql特殊字段转换
|
||
specialColumnHandle (sql) {
|
||
const columns = [
|
||
{
|
||
target: "app_risk='1'",
|
||
original: `app_risk='${riskLevelMapping[0].name.toLowerCase()}'`
|
||
},
|
||
{
|
||
target: "app_risk='2'",
|
||
original: `app_risk='${riskLevelMapping[1].name.toLowerCase()}'`
|
||
},
|
||
{
|
||
target: "app_risk='3'",
|
||
original: `app_risk='${riskLevelMapping[2].name.toLowerCase()}'`
|
||
},
|
||
{
|
||
target: "app_risk='4'",
|
||
original: `app_risk='${riskLevelMapping[3].name.toLowerCase()}'`
|
||
},
|
||
{
|
||
target: "app_risk='5'",
|
||
original: `app_risk='${riskLevelMapping[4].name.toLowerCase()}'`
|
||
},
|
||
{
|
||
target: "=''",
|
||
original: "='unknown'"
|
||
}
|
||
]
|
||
let result = sql
|
||
columns.forEach(c => {
|
||
result = _.replace(result, c.original, c.target)
|
||
})
|
||
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) {
|
||
q = param.q
|
||
metaList = param.metaList
|
||
}
|
||
if (q) {
|
||
this.q = this.specialColumnHandle(q)
|
||
this.metaList = metaList
|
||
} else {
|
||
this.q = ''
|
||
this.metaList = []
|
||
}
|
||
|
||
// 在非列表模式下选择tag模式,在地址栏输入内容时将mode添加到地址栏
|
||
const mode = this.$route.query.mode || 'text'
|
||
|
||
this.reloadUrl({
|
||
listMode: this.listMode,
|
||
q: q,
|
||
mode: mode,
|
||
startTime: getSecond(this.timeFilter.startTime),
|
||
endTime: getSecond(this.timeFilter.endTime),
|
||
range: this.timeFilter.dateRangeValue
|
||
})
|
||
|
||
if (!this.showList) {
|
||
// 首页进入搜索时重载页面,视觉上进入列表页面
|
||
this.$router.push({
|
||
path: '/entityExplorer',
|
||
query: {
|
||
listMode: this.listMode,
|
||
q: q,
|
||
mode: mode,
|
||
startTime: getSecond(this.timeFilter.startTime),
|
||
endTime: getSecond(this.timeFilter.endTime),
|
||
range: this.timeFilter.dateRangeValue
|
||
}
|
||
})
|
||
this.showList = true
|
||
// 跳转页面,则不执行搜索功能
|
||
return true
|
||
}
|
||
if (this.pageObj.resetPageNo) {
|
||
this.pageObj.pageNo = 1
|
||
} else {
|
||
this.pageObj.resetPageNo = true
|
||
}
|
||
// 带参数时,只查询对应类型的entity;不带参数时,3种entity都查
|
||
if (q) {
|
||
// entity_type处理,不查其他两种entity_type对应的左侧筛选
|
||
const entityTypeMeta = metaList.find(meta => {
|
||
return meta.column && meta.column.name === 'entity_type'
|
||
})
|
||
if (entityTypeMeta && entityTypeMeta.operator.value === '=') {
|
||
let entityType = ''
|
||
this.limitFilterType = false
|
||
if (entityTypeMeta.value.value.toLowerCase() === 'ip') {
|
||
this.limitFilterType = true
|
||
entityType = 'ip'
|
||
} else if (entityTypeMeta.value.value.toLowerCase() === 'domain') {
|
||
this.limitFilterType = true
|
||
entityType = 'domain'
|
||
} else if (entityTypeMeta.value.value.toLowerCase() === 'app') {
|
||
this.limitFilterType = true
|
||
entityType = 'app'
|
||
} 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.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||
this.queryList({ q: this.q, ...this.pageObj, ...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.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
|
||
this.queryList({ q: this.q, ...this.pageObj, ...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.queryFilterNew({ ...this.pageObj, ...this.timeFilter })
|
||
this.queryList({ ...this.pageObj, ...this.timeFilter })
|
||
this.queryCount({ ...this.pageObj, ...this.timeFilter })
|
||
// this.queryListTotal({ ...this.timeFilter })
|
||
|
||
// 延时一秒,避免初始化时pageSize为20,pageNo为1也会调用“搜索”的情况
|
||
if (!this.initFlag) {
|
||
this.timer = setTimeout(() => {
|
||
this.initFlag = true
|
||
}, 1000)
|
||
}
|
||
}
|
||
},
|
||
pageSize (val) {
|
||
this.pageObj.pageSize = val
|
||
if (this.initFlag) {
|
||
this.search({ metaList: this.metaList, q: this.q })
|
||
} else {
|
||
if (val !== 20) {
|
||
this.search({ metaList: this.metaList, q: this.q })
|
||
}
|
||
}
|
||
},
|
||
pageNo (val) {
|
||
this.pageObj.pageNo = val
|
||
this.pageObj.resetPageNo = false
|
||
if (this.initFlag) {
|
||
this.search({ metaList: this.metaList, q: this.q })
|
||
} else {
|
||
if (val !== 1) {
|
||
this.search({ metaList: this.metaList, q: this.q })
|
||
}
|
||
}
|
||
},
|
||
// 点击上一页箭头
|
||
prev () {
|
||
this.scrollbarToTop()
|
||
},
|
||
// 点击下一页箭头
|
||
next () {
|
||
this.scrollbarToTop()
|
||
},
|
||
// currentPage 改变时会触发
|
||
current (val) {
|
||
this.$emit('pageNo', val)
|
||
this.scrollbarToTop()
|
||
},
|
||
scrollbarToTop () {
|
||
this.$nextTick(() => {
|
||
const wraps = document.querySelector('#entityList')
|
||
wraps.scrollTop = 0
|
||
})
|
||
},
|
||
/* filter组件内点击后查询 */
|
||
filter (name, topData) {
|
||
const params = {
|
||
column: topData.topColumn,
|
||
operator: '=',
|
||
value: name
|
||
}
|
||
this.$refs.search.addParams([params])
|
||
this.$nextTick(() => {
|
||
this.emitter.emit('advanced-search')
|
||
})
|
||
},
|
||
/* 查询filter数据 */
|
||
queryFilter (params) {
|
||
const queryParams = {
|
||
...params,
|
||
startTime: getSecond(params.startTime),
|
||
endTime: getSecond(params.endTime)
|
||
}
|
||
this.loadingLeft = true
|
||
get(api.entityFilter, queryParams).then(response => {
|
||
if (response.code === 200 && response.data && response.data.result) {
|
||
switch (params.entityType) {
|
||
case 'ip': {
|
||
this.filterData[0].data.forEach(d => {
|
||
d.value = response.data.result[d.column] || 0
|
||
})
|
||
this.filterData[0].totalCount = response.data.result.count
|
||
if (this.limitFilterType) {
|
||
this.cleanFilterData(1)
|
||
this.cleanFilterData(2)
|
||
}
|
||
break
|
||
}
|
||
case 'app': {
|
||
this.filterData[1].data.forEach(d => {
|
||
d.value = response.data.result[d.column] || 0
|
||
})
|
||
this.filterData[1].totalCount = response.data.result.count
|
||
if (this.limitFilterType) {
|
||
this.cleanFilterData(0)
|
||
this.cleanFilterData(2)
|
||
this.cleanFilterData(3)
|
||
}
|
||
break
|
||
}
|
||
case 'domain': {
|
||
this.filterData[2].data.forEach(d => {
|
||
d.value = response.data.result[d.column] || 0
|
||
})
|
||
this.filterData[2].totalCount = response.data.result.count
|
||
if (this.limitFilterType) {
|
||
this.cleanFilterData(0)
|
||
this.cleanFilterData(1)
|
||
this.cleanFilterData(3)
|
||
}
|
||
break
|
||
}
|
||
case 'dns': {
|
||
this.filterData[3].data.forEach(d => {
|
||
d.value = response.data.result[d.column] || 0
|
||
})
|
||
this.filterData[3].totalCount = response.data.result.count
|
||
this.filterData[3].osTotalCount = response.data.result.osTotalCount
|
||
this.filterData[3].orgTotalCount = response.data.result.orgTotalCount
|
||
this.filterData[3].softwareTotalCount = response.data.result.softwareTotalCount
|
||
break
|
||
}
|
||
}
|
||
this.loadingLeft = false
|
||
} else {
|
||
this.loadingLeft = false
|
||
}
|
||
})
|
||
},
|
||
/** 新版查询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, topColumn: 'Country', value: item.uniqueEntities }
|
||
if (index === 0) {
|
||
obj.flag = item.value // 接口字段名称为'China',svg名称为'CN',通过countryNameIdMapping进行转换
|
||
}
|
||
if (index === 1) {
|
||
obj.topColumn = 'City'
|
||
}
|
||
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 = {
|
||
pageSize: params.pageSize,
|
||
pageNo: params.pageNo,
|
||
// startTime: getSecond(params.startTime),
|
||
// endTime: getSecond(params.endTime),
|
||
resource: params.q || ''
|
||
}
|
||
get(api.entity.entityList.list, queryParams).then(response => {
|
||
if (response.code === 200) {
|
||
this.listData = []
|
||
this.$nextTick(() => {
|
||
this.listData = response.data.list
|
||
this.pageObj.total = response.data.total
|
||
})
|
||
} else {
|
||
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, domainCount: 0, ipCount: 0, appCount: 0 }
|
||
}
|
||
}).catch(e => {
|
||
console.log(e)
|
||
this.summaryCount = { total: 0, domainCount: 0, ipCount: 0, appCount: 0 }
|
||
}).finally(() => {
|
||
this.loadingCount = false
|
||
})
|
||
},
|
||
|
||
queryListTotal (params) {
|
||
const queryParams = {
|
||
...params,
|
||
startTime: getSecond(params.startTime),
|
||
endTime: getSecond(params.endTime)
|
||
}
|
||
get(api.entityListTotal, queryParams).then(response => {
|
||
if (response.code === 200) {
|
||
this.pageObj.total = response.data.result
|
||
}
|
||
})
|
||
},
|
||
handleQ (params) {
|
||
return Object.keys(params).map(param => {
|
||
return `${param}='${params[param]}'`
|
||
}).join(' AND ')
|
||
},
|
||
|
||
getEntityIndexData () {
|
||
// Total
|
||
this.loadingApp = true
|
||
this.loadingDomain = true
|
||
this.loadingIp = true
|
||
// New
|
||
this.loadingAppNew = true
|
||
this.loadingDomainNew = true
|
||
this.loadingIpNew = true
|
||
// Active
|
||
this.loadingAppActive = true
|
||
this.loadingDomainActive = true
|
||
this.loadingIpActive = true
|
||
|
||
get(api.entity.entityList.entityActive).then(response => {
|
||
if (response.code === 200) {
|
||
this.entityDomainTotal = response.data.domainCount
|
||
this.entityIpTotal = response.data.ipCount
|
||
this.entityAppTotal = response.data.appCount
|
||
}
|
||
this.loadingDomain = false
|
||
this.loadingIp = false
|
||
this.loadingApp = false
|
||
})
|
||
// New
|
||
get(api.entity.entityList.entityNew).then(response => {
|
||
if (response.code === 200) {
|
||
this.entityDomainNew = response.data.domainCount
|
||
this.entityIpNew = response.data.ipCount
|
||
this.entityAppNew = response.data.appCount
|
||
}
|
||
this.loadingDomainNew = false
|
||
this.loadingIpNew = false
|
||
this.loadingAppNew = false
|
||
})
|
||
// Active
|
||
get(api.entity.entityList.entityActive).then(response => {
|
||
if (response.code === 200) {
|
||
this.entityDomainActive = response.data.domainCount
|
||
this.entityIpActive = response.data.ipCount
|
||
this.entityAppActive = response.data.appCount
|
||
}
|
||
this.loadingDomainActive = false
|
||
this.loadingIpActive = false
|
||
this.loadingAppActive = false
|
||
})
|
||
},
|
||
cleanFilterData (index) {
|
||
this.filterData[index].data.forEach(d => {
|
||
d.value = 0
|
||
})
|
||
this.filterData[index].totalCount = 0
|
||
},
|
||
setListMode (mode) {
|
||
this.listMode = mode
|
||
const newParam = {
|
||
listMode: mode
|
||
}
|
||
this.reloadUrl(newParam)
|
||
},
|
||
/**
|
||
* 向地址栏添加/删除参数
|
||
*/
|
||
reloadUrl (newParam, clean) {
|
||
const { query } = this.$route
|
||
let newUrl = urlParamsHandler(window.location.href, query, newParam)
|
||
if (clean) {
|
||
newUrl = urlParamsHandler(window.location.href, query, newParam, clean)
|
||
}
|
||
overwriteUrl(newUrl)
|
||
},
|
||
/**
|
||
* 初始化搜索,分享url或者刷新界面,保留本次搜索结果
|
||
* @param q
|
||
*/
|
||
initSearch (q) {
|
||
let str = q
|
||
// 此处的mode不做text和tag区分,是因为text和tag构造搜索参数过程不一样,但结果的参数一致
|
||
// 故采用text的参数形式进行搜索,tag形式在tagMode.vue的mounted里根据地址栏的参数q构造metaList
|
||
if (str) {
|
||
// 为避免地址栏任意输入导致全查询的q带QUERY,解析时不识别导致的语法错误
|
||
// 如地址栏输入116.178.222.171,此时的q很长,刷新界面时需要把q里的116.178.222.171拿出来进行搜索
|
||
if (str.indexOf('QUERY') > -1) {
|
||
const strList = str.split(' ')
|
||
if (strList.length > 0) {
|
||
// 此时strList[1]为ip_addr:116.178.222.171,获取116.178.222.171
|
||
str = strList[1].slice(8)
|
||
}
|
||
}
|
||
const parser = new Parser(columnList)
|
||
const errorList = parser.validateStr(str)
|
||
if (_.isEmpty(errorList)) {
|
||
this.search(parser.parseStr(str))
|
||
} else {
|
||
this.$message.error(handleErrorTip(errorList[0]))
|
||
}
|
||
} else {
|
||
this.search({ q: '', str: '', metaList: [] })
|
||
}
|
||
}
|
||
},
|
||
mounted () {
|
||
this.getEntityIndexData()
|
||
const { q, listMode } = this.$route.query
|
||
|
||
// 如果地址栏有listMode,即列表页,并非首页,则开始搜索
|
||
if (listMode) {
|
||
this.showList = true
|
||
this.initSearch(q)
|
||
this.listMode = listMode
|
||
}
|
||
},
|
||
watch: {
|
||
timeFilter () {
|
||
this.search({ metaList: this.metaList, q: this.q })
|
||
}
|
||
},
|
||
setup () {
|
||
const { query } = useRoute()
|
||
// 获取url携带的range、startTime、endTime
|
||
const rangeParam = query.range
|
||
const startTimeParam = query.startTime
|
||
const endTimeParam = query.endTime
|
||
// 若url携带了,使用携带的值,否则使用默认值。
|
||
const dateRangeValue = rangeParam ? parseInt(query.range) : 60
|
||
const timeFilter = ref({ dateRangeValue })
|
||
if (!startTimeParam || !endTimeParam) {
|
||
const { startTime, endTime } = getNowTime(60)
|
||
timeFilter.value.startTime = startTime
|
||
timeFilter.value.endTime = endTime
|
||
} else {
|
||
timeFilter.value.startTime = parseInt(startTimeParam)
|
||
timeFilter.value.endTime = parseInt(endTimeParam)
|
||
}
|
||
return {
|
||
timeFilter
|
||
}
|
||
},
|
||
beforeUnmount () {
|
||
clearTimeout(this.timer)
|
||
}
|
||
}
|
||
</script>
|