CN-434 feat: Detection--在实体详情页增加detection图表
This commit is contained in:
@@ -164,3 +164,68 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.security.cn-detection--list,.service.cn-detection--list {
|
||||
height: 100%;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
.cn-detection__case {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #E7EAED;
|
||||
border-radius: 2px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.cn-detection__case {
|
||||
padding: 18px 0;
|
||||
flex: unset;
|
||||
}
|
||||
.cn-detection__header {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
.cn-detection__case-severity {
|
||||
display: flex;
|
||||
width: 38px;
|
||||
height: 34px;
|
||||
text-align: center;
|
||||
margin: auto;
|
||||
margin-right: 20px;
|
||||
margin-left: 29px;
|
||||
line-height: 34px;
|
||||
i {
|
||||
font-size: 40px;
|
||||
}
|
||||
}
|
||||
.el-pagination__jump {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
.cn-detection__footer {
|
||||
background: #FFFFFF;
|
||||
position: relative;
|
||||
box-shadow: 0 0 4px 0 rgba(0,0,0,0.06);
|
||||
.el-pagination__total {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
.domain.cn-detection-domain {
|
||||
height: 20px;
|
||||
line-height: 20px !important;
|
||||
padding: 0 4px;
|
||||
font-style: italic;
|
||||
}
|
||||
.critical {
|
||||
color: #D84C4C !important;
|
||||
}
|
||||
.high {
|
||||
color: #FF9A79 !important;
|
||||
}
|
||||
.info {
|
||||
color: #D1BD50 !important;
|
||||
}
|
||||
.medium {
|
||||
color: #FFB65A !important;
|
||||
}
|
||||
.low {
|
||||
color: #FFD82D !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,6 +247,24 @@
|
||||
v-else-if="isDomainRecursiveResolve"
|
||||
></chart-domain-recursive-resolve>
|
||||
|
||||
<chart-detection-security
|
||||
:chart-data="chartData"
|
||||
:time-filter="timeFilter"
|
||||
:chart-info="chartInfo"
|
||||
:query-params="queryParams"
|
||||
v-else-if="isDetectionSecurity"
|
||||
@getDetectionData="getDetectionData"
|
||||
></chart-detection-security>
|
||||
|
||||
<chart-detection-service
|
||||
:chart-data="chartData"
|
||||
:time-filter="timeFilter"
|
||||
:chart-info="chartInfo"
|
||||
:query-params="queryParams"
|
||||
v-else-if="isDetectionService"
|
||||
@getDetectionData="getDetectionData"
|
||||
></chart-detection-service>
|
||||
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
@@ -280,6 +298,8 @@ import ChartOneSituationStatistics from '@/views/charts/charts/ChartOneSituation
|
||||
import ChartTwoSituationStatistics from '@/views/charts/charts/ChartTwoSituationStatistics'
|
||||
import ChartAlarmInfo from '@/views/charts/charts/ChartAlarmInfo'
|
||||
import ChartDomainRecursiveResolve from '@/views/charts/charts/ChartDomainRecursiveResolve'
|
||||
import chartDetectionSecurity from '@/views/charts/charts/chartDetectionSecurity'
|
||||
import chartDetectionService from '@/views/charts/charts/chartDetectionService'
|
||||
import {
|
||||
isEcharts,
|
||||
isEchartsLine,
|
||||
@@ -315,7 +335,9 @@ import {
|
||||
isSingleSupportStatistics,
|
||||
isTwoSupportStatistics,
|
||||
isAlarmInfo,
|
||||
isDomainRecursiveResolve
|
||||
isDomainRecursiveResolve,
|
||||
isDetectionSecurity,
|
||||
isDetectionService
|
||||
} from './charts/tools'
|
||||
import _ from 'lodash'
|
||||
|
||||
@@ -349,7 +371,9 @@ export default {
|
||||
ChartOneSituationStatistics,
|
||||
ChartTwoSituationStatistics,
|
||||
ChartAlarmInfo,
|
||||
ChartDomainRecursiveResolve
|
||||
ChartDomainRecursiveResolve,
|
||||
chartDetectionSecurity,
|
||||
chartDetectionService
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -385,7 +409,9 @@ export default {
|
||||
!this.isMap &&
|
||||
!this.isSingleSupportStatistics &&
|
||||
!this.isTwoSupportStatistics &&
|
||||
!this.isAlarmInfo
|
||||
!this.isAlarmInfo &&
|
||||
!this.isDetectionSecurity &&
|
||||
!this.isDetectionService
|
||||
)
|
||||
},
|
||||
chartOption () {
|
||||
@@ -410,6 +436,9 @@ export default {
|
||||
getChartData (url, extraParams) {
|
||||
this.$emit('getChartData', url, extraParams)
|
||||
},
|
||||
getDetectionData (url, extraParams, isRefresh, timeFilter) {
|
||||
this.$emit('getChartData', url, extraParams, isRefresh, timeFilter)
|
||||
},
|
||||
initEchartsWithTable () {
|
||||
this.$refs['chart' + this.chartInfo.id] &&
|
||||
this.$refs['chart' + this.chartInfo.id].initEchartsWithTable(
|
||||
@@ -424,8 +453,15 @@ export default {
|
||||
tabHandleClickType: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
console.log(n)
|
||||
this.tabHandleClickType = n
|
||||
}
|
||||
},
|
||||
chartData: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler (n) {
|
||||
}
|
||||
}
|
||||
},
|
||||
setup (props) {
|
||||
@@ -467,7 +503,9 @@ export default {
|
||||
),
|
||||
isTwoSupportStatistics: isTwoSupportStatistics(props.chartInfo.type),
|
||||
isAlarmInfo: isAlarmInfo(props.chartInfo.type),
|
||||
isDomainRecursiveResolve: isDomainRecursiveResolve(props.chartInfo.type)
|
||||
isDomainRecursiveResolve: isDomainRecursiveResolve(props.chartInfo.type),
|
||||
isDetectionSecurity: isDetectionSecurity(props.chartInfo.type),
|
||||
isDetectionService: isDetectionService(props.chartInfo.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
>
|
||||
<!-- title和工具栏,支持浮动 -->
|
||||
<chart-header
|
||||
v-if="!isFullscreen && showHeader && !isSingleValue && !isTabs"
|
||||
v-if="!isFullscreen && showHeader && !isSingleValue && !isTabs && !isDetectionSecurity && !isDetectionService"
|
||||
:is-error="isError"
|
||||
:error-info="errorInfo"
|
||||
:chart-data="chartData"
|
||||
@@ -79,7 +79,9 @@ import {
|
||||
isAppBasicInfo,
|
||||
isAppRelatedDomain,
|
||||
isBlock,
|
||||
isAlarmInfo
|
||||
isAlarmInfo,
|
||||
isDetectionSecurity,
|
||||
isDetectionService
|
||||
} from './charts/tools'
|
||||
import { tableTitleMapping, legendMapping } from '@/views/charts/charts/chart-table-title'
|
||||
import { replaceUrlPlaceholder } from '@/utils/tools'
|
||||
@@ -165,7 +167,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
/* 参数 extraParams 额外请求参数,isRefresh 是否是刷新 */
|
||||
getChartData (url, extraParams = {}, isRefresh, chartTimeFilter) {
|
||||
getChartData (url, extraParams = {}, isRefresh, chartTimeFilter, num) {
|
||||
const vm = this
|
||||
this.loading = true
|
||||
this.standaloneTimeRange.use = !!isRefresh
|
||||
@@ -187,12 +189,17 @@ export default {
|
||||
pageSize: 9
|
||||
}
|
||||
}
|
||||
if ((isDetectionService && JSON.stringify(extraParams) === '{}') || (isDetectionSecurity && JSON.stringify(extraParams) === '{}')) {
|
||||
extraParams = {
|
||||
pageNo: 1,
|
||||
pageSize: 6
|
||||
}
|
||||
}
|
||||
// 接口查询参数
|
||||
this.queryParams = {
|
||||
...this.handleQueryParams(),
|
||||
...this.queryTimeRange,
|
||||
...this.entity,
|
||||
|
||||
...extraParams
|
||||
}
|
||||
const requestUrl = url || (chartParams && chartParams.url)
|
||||
@@ -430,7 +437,9 @@ export default {
|
||||
isCryptocurrencyEventList: isCryptocurrencyEventList(props.chartInfo.type),
|
||||
isAppBasicInfo: isAppBasicInfo(props.chartInfo.type),
|
||||
isAppRelatedDomain: isAppRelatedDomain(props.chartInfo.type),
|
||||
isAlarmInfo: isAlarmInfo(props.chartInfo.type)
|
||||
isAlarmInfo: isAlarmInfo(props.chartInfo.type),
|
||||
isDetectionService: isDetectionService(props.chartInfo.type),
|
||||
isDetectionSecurity: isDetectionSecurity(props.chartInfo.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
src/views/charts/charts/chartDetectionPagination.vue
Normal file
47
src/views/charts/charts/chartDetectionPagination.vue
Normal file
@@ -0,0 +1,47 @@
|
||||
<template>
|
||||
<el-pagination
|
||||
small
|
||||
ref="pagination"
|
||||
:current-page="pageObj.pageNo"
|
||||
:page-size="pageObj.pageSize"
|
||||
layout="total,prev,jumper,slot,next"
|
||||
class="chart-table-pagination"
|
||||
:total="pageObj.total"
|
||||
@current-change="currentChange"
|
||||
>
|
||||
<span>/ {{totalPage}}</span>
|
||||
</el-pagination>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'chartDetectionPagination',
|
||||
props: {
|
||||
pageObj: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
totalPage () {
|
||||
const remainder = this.pageObj.total % this.pageObj.pageSize
|
||||
if (remainder) {
|
||||
return parseInt(this.pageObj.total / this.pageObj.pageSize) + 1
|
||||
} else {
|
||||
return parseInt(this.pageObj.total / this.pageObj.pageSize)
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
currentChange: function (val) {
|
||||
this.$emit('pageJump', val)
|
||||
this.pageObj.pageNo = val
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.$el.querySelector('.el-pagination__jump').childNodes[0].nodeValue = ''
|
||||
}
|
||||
}
|
||||
</script>
|
||||
85
src/views/charts/charts/chartDetectionSecurity.vue
Normal file
85
src/views/charts/charts/chartDetectionSecurity.vue
Normal file
@@ -0,0 +1,85 @@
|
||||
<template>
|
||||
<div class="security cn-detection--list">
|
||||
<div class="cn-detection-table">
|
||||
<detections-table
|
||||
v-for="(data, index) in chartData"
|
||||
:detection="data"
|
||||
:timeFilter="timeFilter"
|
||||
:key="index"
|
||||
:ref="`detectionRow${index}`"
|
||||
:index="index"
|
||||
></detections-table>
|
||||
</div>
|
||||
<div class="cn-detection__footer" v-show="pageObj.total > 0">
|
||||
<chart-detection-pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageJump="pageJump"
|
||||
:pageSizeForAlarm="pageSizeForAlarm"
|
||||
></chart-detection-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import detectionsTable from '@/views/detections/detectionsTable'
|
||||
import chartDetectionPagination from '@/views/charts/charts/chartDetectionPagination'
|
||||
import { get } from '@/utils/http'
|
||||
import { replaceUrlPlaceholder } from '@/utils/tools'
|
||||
export default {
|
||||
name: 'chartDetectionSecurity',
|
||||
props: {
|
||||
chartInfo: Object,
|
||||
chartData: Array,
|
||||
resultType: Object,
|
||||
queryParams: Object,
|
||||
timeFilter: Object
|
||||
},
|
||||
components: {
|
||||
chartDetectionPagination,
|
||||
detectionsTable
|
||||
},
|
||||
watch: {
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
pageSize: 6,
|
||||
total: 0,
|
||||
resetPageNo: true
|
||||
},
|
||||
pageSizeForAlarm: 6
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
securityCount () {
|
||||
const requestUrl = this.chartInfo.params.countUrl
|
||||
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
||||
this.pageObj.total = response.data.result
|
||||
})
|
||||
},
|
||||
getDetectionData (val) {
|
||||
this.pageObj.pageNo = val
|
||||
const extraParams = {
|
||||
pageNo: val,
|
||||
pageSize: this.pageSizeForAlarm
|
||||
}
|
||||
this.$emit('getDetectionData', this.chartInfo.params.url, extraParams, false, {
|
||||
startTime: this.queryParams.startTime,
|
||||
endTime: this.queryParams.endTime
|
||||
})
|
||||
const requestUrl = this.chartInfo.params.countUrl
|
||||
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
||||
this.pageObj.total = response.data.result
|
||||
})
|
||||
},
|
||||
pageJump (val) {
|
||||
this.getDetectionData(val)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.securityCount()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
83
src/views/charts/charts/chartDetectionService.vue
Normal file
83
src/views/charts/charts/chartDetectionService.vue
Normal file
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="service cn-detection--list">
|
||||
<div class="cn-detection-table">
|
||||
<detections-table
|
||||
v-for="(data, index) in chartData"
|
||||
:detection="data"
|
||||
:timeFilter="timeFilter"
|
||||
:key="index"
|
||||
:ref="`detectionRow${index}`"
|
||||
:index="index"
|
||||
></detections-table>
|
||||
</div>
|
||||
<div class="cn-chart__footer" v-show="pageObj.total > 0">
|
||||
<chart-detection-pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageJump="pageJump"
|
||||
:pageSizeForAlarm="pageSizeForAlarm"
|
||||
></chart-detection-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import chartDetectionPagination from '@/views/charts/charts/chartDetectionPagination'
|
||||
import detectionsTable from '@/views/detections/detectionsTable'
|
||||
import { get } from '@/utils/http'
|
||||
import { replaceUrlPlaceholder } from '@/utils/tools'
|
||||
export default {
|
||||
name: 'chartDetectionService',
|
||||
props: {
|
||||
chartInfo: Object,
|
||||
chartData: Array,
|
||||
resultType: Object,
|
||||
queryParams: Object,
|
||||
timeFilter: Object
|
||||
},
|
||||
components: {
|
||||
chartDetectionPagination,
|
||||
detectionsTable
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
pageSize: 6,
|
||||
total: 0,
|
||||
resetPageNo: true
|
||||
},
|
||||
pageSizeForAlarm: 6
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
securityCount () {
|
||||
const requestUrl = this.chartInfo.params.countUrl
|
||||
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
||||
this.pageObj.total = response.data.result
|
||||
})
|
||||
},
|
||||
getDetectionData (val) {
|
||||
this.pageObj.pageNo = val
|
||||
const extraParams = {
|
||||
pageNo: val,
|
||||
pageSize: this.pageSizeForAlarm
|
||||
}
|
||||
this.$emit('getDetectionData', this.chartInfo.params.url, extraParams, false, {
|
||||
startTime: this.queryParams.startTime,
|
||||
endTime: this.queryParams.endTime
|
||||
})
|
||||
const requestUrl = this.chartInfo.params.countUrl
|
||||
get(replaceUrlPlaceholder(requestUrl, this.queryParams)).then(response => {
|
||||
this.pageObj.total = response.data.result
|
||||
})
|
||||
},
|
||||
pageJump (val) {
|
||||
this.getDetectionData(val)
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.securityCount()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -189,6 +189,13 @@ export function isBlock (type) {
|
||||
return type === 805
|
||||
}
|
||||
|
||||
export function isDetectionSecurity (type) {
|
||||
return type === 709
|
||||
}
|
||||
|
||||
export function isDetectionService (type) {
|
||||
return type === 710
|
||||
}
|
||||
/* 根据type获取图表分类 */
|
||||
const typeCategory = {
|
||||
MAP: 'map',
|
||||
|
||||
108
src/views/detections/detectionsTable.vue
Normal file
108
src/views/detections/detectionsTable.vue
Normal file
@@ -0,0 +1,108 @@
|
||||
<template>
|
||||
<div class="cn-detection__case">
|
||||
<div class="cn-detection__case-severity"><i :class="iconClass" class="cn-icon cn-icon-alert-level"></i></div>
|
||||
<div class="cn-detection__row">
|
||||
<div class="cn-detection__header">
|
||||
<span :class="iconClass"><i :class="iconClass" class="cn-icon cn-icon-attacker"></i>{{detection.offenderIp || '-'}}</span>
|
||||
<div :class="iconClass" class="domain cn-detection-domain">{{detection.domain}}</div>
|
||||
<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="body__basic-info">
|
||||
<div class="basic-info">
|
||||
<div class="basic-info__item" v-if="detection.eventSecurity">
|
||||
<i class="cn-icon cn-icon-severity-level"></i>
|
||||
<span>{{$t('detection.list.eventSecurity')}} : </span>
|
||||
<span>{{detection.eventSecurity || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-else-if="detection.eventSeverity">
|
||||
<i class="cn-icon cn-icon-severity-level"></i>
|
||||
<span>{{$t('detections.eventSeverity')}} : </span>
|
||||
<span>{{detection.eventSeverity || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-event-type"></i>
|
||||
<span>{{$t('detection.list.securityType')}} : </span>
|
||||
<span>{{detection.securityType || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-event-type"></i>
|
||||
<span>{{$t('detections.eventType')}} : </span>
|
||||
<span>{{detection.eventType || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-trojan"></i>
|
||||
<span>{{$t('detection.list.malwareName')}} : </span>
|
||||
<span>{{detection.malwareName || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-mining-pool"></i>
|
||||
<span>{{$t('detection.list.cryptominingPool')}} : </span>
|
||||
<span>{{detection.cryptominingPool || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-time2"></i>
|
||||
<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;"></span>
|
||||
<span>{{unitConvert(detection.durationMs, 'time', null, null, 0).join(' ') || '-'}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getMillisecond } from '@/utils/date-util'
|
||||
import unitConvert from '@/utils/unit-convert'
|
||||
export default {
|
||||
name: 'detectionsTable',
|
||||
props: {
|
||||
index: Number,
|
||||
timeFilter: Object,
|
||||
detection: Object,
|
||||
pageType: String // 安全事件、服务质量
|
||||
},
|
||||
computed: {
|
||||
iconClass () {
|
||||
let className
|
||||
switch (this.detection.eventSecurity || this.detection.eventSeverity) {
|
||||
case ('critical'): {
|
||||
className = 'critical'
|
||||
break
|
||||
}
|
||||
case ('high'): {
|
||||
className = 'high'
|
||||
break
|
||||
}
|
||||
case ('info'): {
|
||||
className = 'info'
|
||||
break
|
||||
}
|
||||
case ('medium'): {
|
||||
className = 'medium'
|
||||
break
|
||||
}
|
||||
case ('low'): {
|
||||
className = 'low'
|
||||
break
|
||||
}
|
||||
default: break
|
||||
}
|
||||
return className
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
unitConvert,
|
||||
getMillisecond
|
||||
}
|
||||
}
|
||||
</script>
|
||||
Reference in New Issue
Block a user