CN-318 feat: detection服务质量界面
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
<detection-row
|
||||
v-for="(data, index) in listData"
|
||||
:detection="data"
|
||||
:page-type="pageType"
|
||||
:timeFilter="timeFilter"
|
||||
:key="index"
|
||||
:ref="`detectionRow${index}`"
|
||||
@@ -33,7 +34,8 @@ export default {
|
||||
from: String,
|
||||
pageObj: Object,
|
||||
loading: Boolean,
|
||||
timeFilter: Object
|
||||
timeFilter: Object,
|
||||
pageType: String // 安全事件、服务质量
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
|
||||
</div>
|
||||
<div class="cn-detection__case">
|
||||
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[detection.eventSecurity]}`">
|
||||
|
||||
</div>
|
||||
<div class="cn-detection__icon" :style="`background-color: ${eventSeverityColor[detection.eventSecurity]}`"></div>
|
||||
<div class="cn-detection__row">
|
||||
<div class="cn-detection__header">
|
||||
<div class="cn-detection__header" v-if="pageType === detectionPageType.securityEvent">
|
||||
<i class="cn-icon cn-icon-attacker" ></i>{{detection.offenderIp}}
|
||||
<span class="line">-------</span>
|
||||
<span class="circle"></span>
|
||||
<i class="cn-icon cn-icon-attacked" ></i>{{detection.victimIp}}
|
||||
</div>
|
||||
<div class="cn-detection__body">
|
||||
<div class="cn-detection__header" v-else-if="pageType === detectionPageType.performanceEvent">
|
||||
<div class="cn-entity__icon"><i :class="iconClass"></i></div>
|
||||
<div style="padding-left: 3px;">{{detection.serverIp || detection.domain || detection.appName || 'Unknown'}}</div>
|
||||
</div>
|
||||
<div class="cn-detection__body">
|
||||
<div class="body__basic-info">
|
||||
<div class="basic-info">
|
||||
<div class="basic-info__item">
|
||||
@@ -28,12 +30,12 @@
|
||||
<span>{{$t('detection.list.securityType')}} : </span>
|
||||
<span>{{detection.securityType}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-if="detection.malwareName && detection.malwareName.length > 0 ">
|
||||
<div class="basic-info__item" v-if="detection.malwareName">
|
||||
<i class="cn-icon cn-icon-trojan"></i>
|
||||
<span>{{$t('detection.list.malwareName')}} : </span>
|
||||
<span>{{detection.malwareName}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-if="detection.cryptominingPool && detection.cryptominingPool.length > 0 ">
|
||||
<div class="basic-info__item" v-if="detection.cryptominingPool">
|
||||
<i class="cn-icon cn-icon-mining-pool"></i>
|
||||
<span>{{$t('detection.list.cryptominingPool')}} : </span>
|
||||
<span>{{detection.cryptominingPool}}</span>
|
||||
@@ -43,6 +45,13 @@
|
||||
<span>{{$t('detection.list.startTime')}} : </span>
|
||||
<span>{{dayJs.tz(getMillisecond(detection.startTime)).format('YYYY-MM-DD HH:mm:ss')}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-time2"></i>
|
||||
<span>{{$t('overall.duration')}} : </span>
|
||||
<span style="display: inline-block;height: 6px;width: 6px;border-radius: 50%;margin-right: 8px;"
|
||||
:style="pointColor(detection)"></span>
|
||||
<span>{{unitConvert(detection.durationMs, 'time', null, null, 0).join(' ')}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -50,10 +59,28 @@
|
||||
<el-collapse-transition>
|
||||
<div class="cn-detection__detail-overview" v-if="!isCollapse">
|
||||
<el-divider></el-divider>
|
||||
<detection-overview
|
||||
<detection-security-event-overview
|
||||
v-if="pageType === detectionPageType.securityEvent"
|
||||
:detection="detection"
|
||||
:time-filter="timeFilter"
|
||||
></detection-overview>
|
||||
></detection-security-event-overview>
|
||||
<template v-else>
|
||||
<detection-performance-event-ip-overview
|
||||
v-if="detection.entityType === entityType.ip.toLowerCase()"
|
||||
:detection="detection"
|
||||
:time-filter="timeFilter"
|
||||
></detection-performance-event-ip-overview>
|
||||
<detection-performance-event-domain-overview
|
||||
v-else-if="detection.entityType === entityType.domain.toLowerCase()"
|
||||
:detection="detection"
|
||||
:time-filter="timeFilter"
|
||||
></detection-performance-event-domain-overview>
|
||||
<detection-performance-event-app-overview
|
||||
v-else-if="detection.entityType === entityType.app.toLowerCase()"
|
||||
:detection="detection"
|
||||
:time-filter="timeFilter"
|
||||
></detection-performance-event-app-overview>
|
||||
</template>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
@@ -61,26 +88,70 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { eventSeverityColor } from '@/utils/constants'
|
||||
import { eventSeverityColor, detectionPageType, entityType } from '@/utils/constants'
|
||||
import { getMillisecond } from '@/utils/date-util'
|
||||
import DetectionOverview from '@/views/detections/DetectionOverview'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
import DetectionSecurityEventOverview from '@/views/detections/overview/DetectionSecurityEventOverview'
|
||||
import DetectionPerformanceEventIpOverview from '@/views/detections/overview/DetectionPerformanceEventIpOverview'
|
||||
import DetectionPerformanceEventAppOverview from '@/views/detections/overview/DetectionPerformanceEventAppOverview'
|
||||
import DetectionPerformanceEventDomainOverview from '@/views/detections/overview/DetectionPerformanceEventDomainOverview'
|
||||
export default {
|
||||
name: 'DetectionRow',
|
||||
components: {
|
||||
DetectionOverview
|
||||
DetectionSecurityEventOverview,
|
||||
DetectionPerformanceEventIpOverview,
|
||||
DetectionPerformanceEventAppOverview,
|
||||
DetectionPerformanceEventDomainOverview
|
||||
},
|
||||
props: {
|
||||
index: Number,
|
||||
timeFilter: Object,
|
||||
detection: Object
|
||||
detection: Object,
|
||||
pageType: String // 安全事件、服务质量
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
entityType,
|
||||
detectionPageType,
|
||||
isCollapse: true, // 是否是折叠状态
|
||||
eventSeverityColor
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
iconClass () {
|
||||
let className
|
||||
switch (this.detection.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
|
||||
},
|
||||
pointColor () {
|
||||
return function (detection) {
|
||||
let color = '#8FA1BE'
|
||||
if (detection.startTime && detection.endTime) {
|
||||
if (getMillisecond(detection.endTime) - getMillisecond(detection.startTime) < 5 * 60 * 1000) {
|
||||
color = '#D84C4C'
|
||||
}
|
||||
}
|
||||
return { backgroundColor: color }
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
unitConvert,
|
||||
getMillisecond,
|
||||
/* 切换折叠状态 */
|
||||
switchCollapse () {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<div class="detection-detail-overview">
|
||||
<div class="overview__left">
|
||||
<div class="overview__title">{{$t('overall.remark')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__title">Fields</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.category')}}</div>
|
||||
<div class="row__content">{{basicInfo.appCategory}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.subcategory')}}</div>
|
||||
<div class="row__content">{{basicInfo.appSubcategory || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.riskLevel')}}</div>
|
||||
<div class="row__content">
|
||||
<div class="row__tag" :style="`background-color:${eventSeverityColor[basicInfo.appRisk]}`">{{basicInfo.appRisk || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__right">
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.appName})}}</div>
|
||||
</div>
|
||||
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import { eventSeverityColor } from '@/utils/constants'
|
||||
export default {
|
||||
name: 'DetectionPerformanceEventAppOverview',
|
||||
props: {
|
||||
detection: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
eventSeverityColor,
|
||||
basicInfo: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computeLocation () {
|
||||
return function (basicInfo) {
|
||||
let result = ''
|
||||
if (basicInfo.serverLocationCountry) {
|
||||
result += basicInfo.serverLocationCountry
|
||||
}
|
||||
if (basicInfo.serverLocationProvince) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationProvince
|
||||
}
|
||||
if (basicInfo.serverLocationRegion) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationRegion
|
||||
}
|
||||
return result || '-'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
query () {
|
||||
this.basicInfo = {
|
||||
"clientLocationCountry": 1212,
|
||||
"clientLocationProvince": "112.2.2.3",
|
||||
"clientLocationRegion": "China",
|
||||
"clientAsn": "Hebei",
|
||||
"serverLocationCountry": "Xingtai",
|
||||
"serverLocationProvince": "hehe",
|
||||
"serverLocationRegion": "2.2.2.2",
|
||||
"serverAsn": "China",
|
||||
"domainCategoryName": "Hebei",
|
||||
"domainCategoryGroup": "Xingtai",
|
||||
"domainReputationScore": "hehe",
|
||||
"domainReputationLevel": "high",
|
||||
"appCategory": "vpn",
|
||||
"appSubcategory": "foreign vpn",
|
||||
"appRisk": "critical"
|
||||
}
|
||||
/*this.queryBasic().then(responses => {
|
||||
})*/
|
||||
},
|
||||
queryBasic () {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
|
||||
if (response.code === 200) {
|
||||
resolve(response.data.list)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.query()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,121 @@
|
||||
<template>
|
||||
<div class="detection-detail-overview">
|
||||
<div class="overview__left">
|
||||
<div class="overview__title">{{$t('overall.remark')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__title">Fields</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.category')}}</div>
|
||||
<div class="row__content">{{basicInfo.domainCategoryName}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.group')}}</div>
|
||||
<div class="row__content">{{basicInfo.domainCategoryGroup || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.credit')}}</div>
|
||||
<div class="row__content">{{basicInfo.domainReputationScore || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('entities.reputationLevel')}}</div>
|
||||
<div class="row__content">
|
||||
<div class="row__tag" :style="`background-color:${eventSeverityColor[basicInfo.domainReputationLevel]}`">{{basicInfo.domainReputationLevel || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__right">
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.domain})}}</div>
|
||||
</div>
|
||||
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import { eventSeverityColor } from '@/utils/constants'
|
||||
export default {
|
||||
name: 'DetectionPerformanceEventDomainOverview',
|
||||
props: {
|
||||
detection: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
eventSeverityColor,
|
||||
basicInfo: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computeLocation () {
|
||||
return function (basicInfo) {
|
||||
let result = ''
|
||||
if (basicInfo.serverLocationCountry) {
|
||||
result += basicInfo.serverLocationCountry
|
||||
}
|
||||
if (basicInfo.serverLocationProvince) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationProvince
|
||||
}
|
||||
if (basicInfo.serverLocationRegion) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationRegion
|
||||
}
|
||||
return result || '-'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
query () {
|
||||
this.basicInfo = {
|
||||
"clientLocationCountry": 1212,
|
||||
"clientLocationProvince": "112.2.2.3",
|
||||
"clientLocationRegion": "China",
|
||||
"clientAsn": "Hebei",
|
||||
"serverLocationCountry": "Xingtai",
|
||||
"serverLocationProvince": "hehe",
|
||||
"serverLocationRegion": "2.2.2.2",
|
||||
"serverAsn": "China",
|
||||
"domainCategoryName": "Hebei",
|
||||
"domainCategoryGroup": "Xingtai",
|
||||
"domainReputationScore": "hehe",
|
||||
"domainReputationLevel": "high",
|
||||
"appCategory": "vpn",
|
||||
"appSubcategory": "foreign vpn",
|
||||
"appRisk": "critical"
|
||||
}
|
||||
/*this.queryBasic().then(responses => {
|
||||
})*/
|
||||
},
|
||||
queryBasic () {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
get(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.appName }).then(response => {
|
||||
if (response.code === 200) {
|
||||
resolve(response.data.list)
|
||||
} else {
|
||||
reject(response)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.query()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -0,0 +1,106 @@
|
||||
<template>
|
||||
<div class="detection-detail-overview">
|
||||
<div class="overview__left">
|
||||
<div class="overview__title">{{$t('overall.remark')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content">{{basicInfo.malwareDescription || '-'}}</div>
|
||||
</div>
|
||||
<div class="overview__title">Fields</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">{{$t('overall.location')}}</div>
|
||||
<div class="row__content">{{computeLocation(basicInfo)}}</div>
|
||||
</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__label">ASN</div>
|
||||
<div class="row__content">{{basicInfo.serverAsn || '-'}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview__right">
|
||||
<div class="overview__title">{{$t('detections.goToEntity')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewDetailOf', {ip: detection.serverIp})}}</div>
|
||||
</div>
|
||||
<div class="overview__title">{{$t('detections.goToHunt')}}</div>
|
||||
<div class="overview__row">
|
||||
<div class="row__content row__content--link">{{$t('detections.viewAllRelated')}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { api, getData } from '@/utils/api'
|
||||
export default {
|
||||
name: 'DetectionPerformanceEventIpOverview',
|
||||
props: {
|
||||
detection: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
basicInfo: {}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
computeLocation () {
|
||||
return function (basicInfo) {
|
||||
let result = ''
|
||||
if (basicInfo.serverLocationCountry) {
|
||||
result += basicInfo.serverLocationCountry
|
||||
}
|
||||
if (basicInfo.serverLocationProvince) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationProvince
|
||||
}
|
||||
if (basicInfo.serverLocationRegion) {
|
||||
if (result) {
|
||||
result += ', '
|
||||
}
|
||||
result += basicInfo.serverLocationRegion
|
||||
}
|
||||
return result || '-'
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
query () {
|
||||
this.basicInfo = {
|
||||
"clientLocationCountry": 1212,
|
||||
"clientLocationProvince": "112.2.2.3",
|
||||
"clientLocationRegion": "China",
|
||||
"clientAsn": "Hebei",
|
||||
"serverLocationCountry": "Xingtai",
|
||||
"serverLocationProvince": "hehe",
|
||||
"serverLocationRegion": "2.2.2.2",
|
||||
"serverAsn": "China",
|
||||
"domainCategoryName": "Hebei",
|
||||
"domainCategoryGroup": "Xingtai",
|
||||
"domainReputationScore": "hehe",
|
||||
"domainReputationLevel": "high",
|
||||
"appCategory": "vpn",
|
||||
"appSubcategory": "foreign vpn",
|
||||
"appRisk": "critical"
|
||||
}
|
||||
/*this.queryBasic().then(responses => {
|
||||
})*/
|
||||
},
|
||||
queryBasic () {
|
||||
return new Promise((resolve, reject) => {
|
||||
try {
|
||||
getData(api.detection.performanceEvent.overviewBasic, { serverIp: this.detection.serverIp }).then(data => {
|
||||
resolve(data)
|
||||
}).catch(error => {
|
||||
reject(error)
|
||||
})
|
||||
} catch (e) {
|
||||
reject(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.query()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user