CN-240 feat: 实体详情

This commit is contained in:
chenjinsong
2022-01-03 22:46:22 +08:00
parent e37e967b5d
commit 6d73abf18f
19 changed files with 481 additions and 126 deletions

View File

@@ -0,0 +1,140 @@
<template>
<div class="cn-home entity-detail">
<div class="entity-detail__header">
<div class="cn-entity__icon"><i :class="iconClass"></i></div>
<div class="cn-entity__name">{{entityData.name}}</div>
</div>
<main class="cn-body entity-detail__body">
<div class="entity-detail__menu">
<template v-for="anchor in anchorPoints" :key="anchor.id">
<div class="menu-item" :class="{'menu-item--active': menuIsActive(anchor)}" @click="jumpToAnchor(anchor)">
<span>{{anchor.label}}</span>
</div>
</template>
</div>
<div class="entity-detail__content">
<cn-panel
ref="cnPanel"
:entity="entityData"
:is-entity-detail="true"
@chartLoaded="chartLoaded"
@scroll="scroll"
></cn-panel>
</div>
</main>
</div>
</template>
<script>
import { useRoute } from 'vue-router'
import Panel from '@/views/charts/Panel'
export default {
name: 'EntityDetail',
components: {
cnPanel: Panel
},
data () {
return {
anchorPoints: [], // { id, label, top, height }
top: 0
}
},
setup (props, ctx) {
const { query } = useRoute()
let panelType
const entityData = {}
switch (query.entityType) {
case 'ip': {
panelType = 4
entityData.ip = query.name
break
}
case 'domain': {
panelType = 5
entityData.domain = query.name
break
}
case 'app': {
panelType = 6
entityData.appName = query.name
break
}
default: {
panelType = 4
break
}
}
entityData.type = panelType
return {
entityData
}
},
methods: {
chartLoaded (chartList) {
this.anchorPoints = []
let anchorPoints = []
chartList.forEach(chart => {
if (chart.params.anchorPoint) {
const dom = document.querySelector(`#${chart.params.anchorPoint}`)
anchorPoints.push({
id: chart.params.anchorPoint,
label: chart.i18n ? this.$t(chart.i18n) : chart.name,
top: dom.offsetTop/* ,
height: document.querySelector(`#${chart.params.anchorPoint}}`).scrollHeight */
})
}
})
// 从小到大排序
anchorPoints = anchorPoints.sort((a, b) => {
return a.top - b.top
})
if (!this.$_.isEmpty(anchorPoints)) {
anchorPoints[0].top = 0
}
this.anchorPoints = anchorPoints
},
scroll ({ top }) {
this.top = top || 0
},
jumpToAnchor (anchor) {
this.top = anchor.top
this.$refs.cnPanel.jumpToTop(anchor.top)
}
},
computed: {
iconClass () {
let className
switch (this.entityData.entityType) {
case ('ip'): {
className = 'cn-icon cn-icon-ip'
break
}
case ('domain'): {
className = 'cn-icon cn-icon-domain'
break
}
case ('app'): {
className = 'cn-icon cn-icon-app'
break
}
default: break
}
return className
},
menuIsActive () {
return function (anchor) {
return this.currentAnchor ? this.currentAnchor.id === anchor.id : false
}
},
currentAnchor () {
let currentAnchor = null
this.anchorPoints.forEach(anchor => {
if (anchor.top <= this.top) {
currentAnchor = anchor
}
})
return currentAnchor
}
}
}
</script>

View File

@@ -150,28 +150,28 @@ export default {
data: [
{
label: this.$t('overall.country'),
column: 'country_distinct_count',
topColumn: 'ip_location_country', // top弹框查询字段
column: 'countryDistinctCount',
topColumn: 'ipLocationCountry', // top弹框查询字段
icon: entityFilterType.ip[0].icon,
value: 0
},
{
label: this.$t('overall.province'),
column: 'province_distinct_count',
topColumn: 'ip_location_province', // top弹框查询字段
column: 'provinceDistinctCount',
topColumn: 'ipLocationProvince', // top弹框查询字段
icon: entityFilterType.ip[1].icon,
value: 0
},
{
label: this.$t('overall.city'),
column: 'city_distinct_count',
column: 'cityDistinctCount',
topColumn: 'ip_location_city', // top弹框查询字段
icon: entityFilterType.ip[2].icon,
value: 0
},
{
label: this.$t('entities.asn'),
column: 'asn_distinct_count',
column: 'asnDistinctCount',
topColumn: 'ip_asn', // top弹框查询字段
icon: entityFilterType.ip[3].icon,
value: 0
@@ -185,21 +185,21 @@ export default {
data: [
{
label: this.$t('entities.category'),
column: 'category_distinct_count',
column: 'categoryDistinctCount',
topColumn: 'app_category', // top弹框查询字段
icon: entityFilterType.app[0].icon,
value: 0
},
{
label: this.$t('entities.subcategory'),
column: 'subcategory_distinct_count',
column: 'subcategoryDistinctCount',
topColumn: 'app_subcategory', // top弹框查询字段
icon: entityFilterType.app[1].icon,
value: 0
},
{
label: this.$t('entities.risk'),
column: 'risk_distinct_count',
column: 'riskDistinctCount',
topColumn: 'app_risk', // top弹框查询字段
icon: entityFilterType.app[2].icon,
value: 0
@@ -213,22 +213,22 @@ export default {
data: [
{
label: this.$t('entities.domainDetail.categoryGroup'),
column: 'category_group_distinct_count',
column: 'categoryGroupDistinctCount',
topColumn: 'domain_category_group', // top弹框查询字段
icon: entityFilterType.domain[0].icon,
value: 0
},
{
label: this.$t('entities.category'),
column: 'category_distinct_count',
column: 'categoryDistinctCount',
topColumn: 'domain_category', // top弹框查询字段
icon: entityFilterType.domain[1].icon,
value: 0
},
{
label: this.$t('entities.reputationLevel'),
column: 'reputation_level_distinct_count',
topColumn: 'domain_reputation_level', // top弹框查询字段
column: 'reputationLevelDistinctCount',
topColumn: 'domainReputationLevel', // top弹框查询字段
icon: entityFilterType.domain[2].icon,
value: 0
}

View File

@@ -84,7 +84,11 @@
<span>{{entityData.securityCount || '-'}}</span>
</div>
</div>
<div class="show-detail" :style="{visibility: !isCollapse ? 'visible' : 'hidden'}">{{$t('overall.detail')}}>></div>
<div
class="show-detail"
:style="{visibility: !isCollapse ? 'visible' : 'hidden'}"
@click="showDetail"
>{{$t('overall.detail')}}>></div>
</div>
</div>
</div>
@@ -127,6 +131,16 @@ export default {
/* 设为折叠状态 */
collapse () {
this.isCollapse = true
},
showDetail () {
const { href } = this.$router.resolve({
path: '/entityDetail',
query: {
entityType: this.entityData.entityType,
name: this.entityData.ipAddr || this.entityData.domainName || this.entityData.appName
}
})
window.open(href, '_blank')
}
}
}

View File

@@ -41,7 +41,7 @@ export default {
let name
switch (this.entityData.entityType) {
case ('ip'): {
name = this.entity.ip
name = this.entity.ipAddr
break
}
case ('domain'): {
@@ -85,7 +85,7 @@ export default {
startTime: Math.floor(now.getTime() / 1000 - 3600),
endTime: Math.floor(now.getTime() / 1000)
},
ip: this.entityData.ip
ip: this.entityData.ipAddr
}
break
}