CN-784: Detection列表样式按新版UI图修改
This commit is contained in:
@@ -2,12 +2,12 @@
|
||||
display: flex;
|
||||
|
||||
.cn-detection__collapse {
|
||||
margin-bottom: 1px;
|
||||
padding-top: 18px;
|
||||
width: 24px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 1px;
|
||||
padding-top: 33px;
|
||||
background-color: #F3F7FA;
|
||||
|
||||
span {
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
.explorer-top-tools {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 18px;
|
||||
|
||||
|
||||
@@ -20,7 +20,8 @@ export default {
|
||||
entityDetectionStyle () {
|
||||
const route = this.$route.name !== undefined ? this.$route.name : this.$route
|
||||
if (listScrollPath.indexOf(route.path) > -1) {
|
||||
return 'overflow:auto;background-color: #EFF2F5;'
|
||||
const style = route.path === listScrollPath[0] ? 'overflow:auto;background-color: #EFF2F5;' : 'overflow:auto;'
|
||||
return style
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
</div>
|
||||
<div class="cn-header__nav">
|
||||
<i class="cn-icon cn-icon-a-NetworkAnalytics"></i>
|
||||
<el-breadcrumb class="header__left-breadcrumb" separator=">">
|
||||
<el-breadcrumb class="header__left-breadcrumb" :separator="route.indexOf('detection') === -1 ? '>' : ''">
|
||||
<el-breadcrumb-item class="header__left-breadcrumb-item" :id="`breadcrumb${item}`" :title="item" v-for="(item,index) in breadcrumb" :key="item">
|
||||
<template v-if="index===3">
|
||||
<div class="header__left-breadcrumb-item-select">
|
||||
@@ -96,30 +96,30 @@
|
||||
</template>
|
||||
<template v-else-if="index===1">
|
||||
<span class="route-menu" @click="jump(route,'','',2)" v-if="route.indexOf('detection') === -1">{{item}}</span>
|
||||
<div class="header__left-breadcrumb-item-select" v-if="route.indexOf('detection') > -1">
|
||||
<el-popover placement="bottom-start"
|
||||
v-if="route.indexOf('detection') > -1"
|
||||
ref="breadcrumbPopover"
|
||||
:show-arrow="false"
|
||||
:append-to-body="false"
|
||||
:hide-after="0"
|
||||
:show-after="0"
|
||||
popper-class="breadcrumb__popper"
|
||||
trigger="click">
|
||||
<template #reference>
|
||||
<div class="breadcrumb-button" id="breadcrumbButton2" :class="showBackground?'breadcrumb-button__active':''" v-if="route.indexOf('detection') > -1">
|
||||
<span id="breadcrumbValue2"> {{item}}</span><i class="cn-icon-xiala cn-icon"></i>
|
||||
</div>
|
||||
</template>
|
||||
<el-row type="flex" justify="center" style="width: fit-content;flex-direction: column;">
|
||||
<ul class="select-dropdown" id="breadcrumbSelectDropdown2">
|
||||
<li v-for="item in detectionMenuList" title='' :key="item.name" :id="item.name" class="select-dropdown__item" @click="jump(item.path,'','',2)">
|
||||
<span>{{$t(item.i18n)}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</el-row>
|
||||
</el-popover>
|
||||
</div>
|
||||
<!-- <div class="header__left-breadcrumb-item-select" v-if="route.indexOf('detection') > -1">-->
|
||||
<!-- <el-popover placement="bottom-start"-->
|
||||
<!-- v-if="route.indexOf('detection') > -1"-->
|
||||
<!-- ref="breadcrumbPopover"-->
|
||||
<!-- :show-arrow="false"-->
|
||||
<!-- :append-to-body="false"-->
|
||||
<!-- :hide-after="0"-->
|
||||
<!-- :show-after="0"-->
|
||||
<!-- popper-class="breadcrumb__popper"-->
|
||||
<!-- trigger="click">-->
|
||||
<!-- <template #reference>-->
|
||||
<!-- <div class="breadcrumb-button" id="breadcrumbButton2" :class="showBackground?'breadcrumb-button__active':''" v-if="route.indexOf('detection') > -1">-->
|
||||
<!-- <span id="breadcrumbValue2"> {{item}}</span><i class="cn-icon-xiala cn-icon"></i>-->
|
||||
<!-- </div>-->
|
||||
<!-- </template>-->
|
||||
<!-- <el-row type="flex" justify="center" style="width: fit-content;flex-direction: column;">-->
|
||||
<!-- <ul class="select-dropdown" id="breadcrumbSelectDropdown2">-->
|
||||
<!-- <li v-for="item in detectionMenuList" title='' :key="item.name" :id="item.name" class="select-dropdown__item" @click="jump(item.path,'','',2)">-->
|
||||
<!-- <span>{{$t(item.i18n)}}</span>-->
|
||||
<!-- </li>-->
|
||||
<!-- </ul>-->
|
||||
<!-- </el-row>-->
|
||||
<!-- </el-popover>-->
|
||||
<!-- </div>-->
|
||||
</template>
|
||||
<template v-else>
|
||||
<span>{{item}}</span>
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
<div class="no-data" v-if="noData">No data</div>
|
||||
<div v-if="!isCollapse" @click="collapse" class="cn-detection__shadow"></div>
|
||||
<detection-row
|
||||
style="margin-bottom: 10px"
|
||||
class="detection-border"
|
||||
v-for="(data, index) in listData"
|
||||
:detection="data"
|
||||
:page-type="pageType"
|
||||
|
||||
@@ -2,12 +2,19 @@
|
||||
<div class="cn-detection--list" :style="{zIndex: !isCollapse ? 1 : 'unset'}">
|
||||
<!-- 左侧下拉按钮 -->
|
||||
<div class="cn-detection__collapse">
|
||||
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
|
||||
<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__row">
|
||||
<div class="cn-detection__header" v-if="pageType === detectionPageType.securityEvent">
|
||||
<span
|
||||
class="detection-event-severity-color-block"
|
||||
:style="`background-color: ${eventSeverityColor[detection.eventSeverity]}`">
|
||||
</span>
|
||||
<span class="detection-event-severity-block">{{ detection.securityType || '-' }}</span>
|
||||
<i class="cn-icon cn-icon-attacker" ></i>{{detection.offenderIp || '-'}}
|
||||
<div v-if="detection.domain" class="domain">{{detection.domain}}</div>
|
||||
<span class="line">-------</span>
|
||||
@@ -31,11 +38,6 @@
|
||||
<span>{{$t('detections.eventSeverity')}} : </span>
|
||||
<span>{{detection.eventSeverity || '-'}}</span>
|
||||
</div>
|
||||
<div class="basic-info__item" v-if="detection.securityType">
|
||||
<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" v-if="detection.eventType">
|
||||
<i class="cn-icon cn-icon-event-type"></i>
|
||||
<span>{{$t('detections.eventType')}} : </span>
|
||||
@@ -176,3 +178,25 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.detection-event-severity-color-block {
|
||||
width: 5px;
|
||||
height: 20px;
|
||||
border-radius: 2.5px;
|
||||
margin-left: -16px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
.detection-event-severity-block {
|
||||
font-family: NotoSansHans-Medium;
|
||||
font-size: 12px;
|
||||
color: #046EC9;
|
||||
font-weight: 500;
|
||||
padding: 2px 10px;
|
||||
background: rgba(56,172,210,0.10);
|
||||
border: 1px solid #ADC7DB;
|
||||
box-shadow: 0 2px 0.28571rem 0 rgb(51 51 51 / 2%);
|
||||
border-radius: 3px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
</style>
|
||||
|
||||
94
src/views/detections/DetectionTabs.vue
Normal file
94
src/views/detections/DetectionTabs.vue
Normal file
@@ -0,0 +1,94 @@
|
||||
<template>
|
||||
<div class="npm-tabs">
|
||||
12345678
|
||||
<div class="npm-tabs__active-bar"></div>
|
||||
<el-tabs v-model="currentTab" ref="elTabs" type="border-card" @tab-click="jumpPage">
|
||||
<el-tab-pane
|
||||
v-for="(tab,index) in tabs"
|
||||
:key="tab.i18n"
|
||||
:name="index"
|
||||
:disabled="tab.disable">
|
||||
<template #label>
|
||||
<div class="npm-tab__label">
|
||||
<i :class="tab.icon"></i>
|
||||
<span>{{ $t(tab.i18n) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import chartMixin from '@/views/charts2/chart-mixin'
|
||||
import { overwriteUrl, urlParamsHandler } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { ref } from 'vue'
|
||||
|
||||
export default {
|
||||
name: 'DetectionTabs',
|
||||
data () {
|
||||
return {
|
||||
leftOffset: 27
|
||||
}
|
||||
},
|
||||
mixins: [chartMixin],
|
||||
setup (props) {
|
||||
const tabs = ref([])
|
||||
if (props.chart) {
|
||||
tabs.value = [...props.chart]
|
||||
tabs.value.forEach(item => {
|
||||
item.disable = false
|
||||
})
|
||||
}
|
||||
const { query } = useRoute()
|
||||
const tabIndexParam = query.tabIndex
|
||||
const currentTab = ref(tabIndexParam ? parseInt(tabIndexParam) : 0)
|
||||
return {
|
||||
currentTab,
|
||||
tabs
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentTab (n) {
|
||||
const { query } = this.$route
|
||||
const newUrl = urlParamsHandler(window.location.href, query, {
|
||||
tabIndex: n
|
||||
})
|
||||
overwriteUrl(newUrl)
|
||||
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(n)
|
||||
})
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleActiveBar (index) {
|
||||
const tabDom = document.getElementById('tab-' + index)
|
||||
if (tabDom) {
|
||||
const offsetLeft = tabDom.offsetLeft
|
||||
const clientWidth = tabDom.clientWidth
|
||||
const clientLeft = tabDom.clientLeft
|
||||
const activeBar = document.querySelector('.npm-tabs .npm-tabs__active-bar')
|
||||
activeBar.style.cssText += `width: ${clientWidth + 2}px; left: ${offsetLeft + this.leftOffset + clientLeft - 1}px;`
|
||||
}
|
||||
},
|
||||
jumpPage (item) {
|
||||
this.$router.push({
|
||||
path: this.tabs[item.index].path,
|
||||
query: {
|
||||
t: +new Date(),
|
||||
tabIndex: this.currentTab
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
// setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
this.handleActiveBar(this.currentTab)
|
||||
})
|
||||
// }, 120)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,37 +1,57 @@
|
||||
<template>
|
||||
<div
|
||||
class="entity-explorer entity-explorer--show-list"
|
||||
>
|
||||
<div class="entity-explorer entity-explorer--show-list">
|
||||
<!-- 顶部工具栏,在列表页显示 -->
|
||||
<div class="explorer-top-tools">
|
||||
<DateTimeRange class="date-time-range" :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"/>
|
||||
<div class="explorer-top-tools-title">{{$t('overall.detections')}}</div>
|
||||
<div style="display: flex">
|
||||
<div class="explorer-top-tools-block">
|
||||
<i class="cn-icon cn-icon-setting detection-icon-setting"></i>
|
||||
<span>Configure Policies</span>
|
||||
</div>
|
||||
<DateTimeRange
|
||||
class="date-time-range"
|
||||
: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"/>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: 100%;padding-bottom: 26px;">
|
||||
<detection-tabs :time-filter="timeFilter" :chart="tabsData" />
|
||||
</div>
|
||||
|
||||
<!-- 搜索组件 -->
|
||||
<detection-search
|
||||
class="detection-border"
|
||||
ref="search"
|
||||
:page-type="pageType"
|
||||
@search="search"
|
||||
></detection-search>
|
||||
<!-- 内容区 -->
|
||||
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
|
||||
<div class="explorer-container" style="height: calc(100% - 20px);flex-direction: column">
|
||||
<loading :loading="loading"></loading>
|
||||
<template v-if="isEventSeverityNoData">
|
||||
<div class="no-data detection__event-severity-bar" >No data</div>
|
||||
</template>
|
||||
<template v-if="!isEventSeverityNoData">
|
||||
<div class="detection__event-severity-bar" :id="`eventSeverityTrendBar${pageType}`">
|
||||
<div class="detection__event-severity-bar detection-border" :id="`eventSeverityTrendBar${pageType}`">
|
||||
</div>
|
||||
</template>
|
||||
<div style="display: flex; flex-grow: 1; height: 100%;">
|
||||
<detection-filter
|
||||
class="detection-border"
|
||||
:filter-data="filterData[pageType]"
|
||||
:q="q"
|
||||
:time-filter="timeFilter"
|
||||
></detection-filter>
|
||||
|
||||
<div class="detection__list">
|
||||
<div class="detection__list-statistics">
|
||||
<div class="detection__list-statistics detection-border">
|
||||
<div class="statistics__severity">
|
||||
<div class="chart-header">
|
||||
<div class="chart-header__title">{{$t('detection.severity')}}</div>
|
||||
@@ -81,15 +101,14 @@
|
||||
></detection-list>
|
||||
<div class="entity__pagination" >
|
||||
<Pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
>
|
||||
</Pagination>
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
></Pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,12 +127,13 @@ import { defaultPageSize, detectionPageType } from '@/utils/constants'
|
||||
import { getNowTime, getSecond, rTime } from '@/utils/date-util'
|
||||
import { ref, shallowRef } from 'vue'
|
||||
import * as echarts from 'echarts'
|
||||
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor, getSeriesIndex } from '@/views/detections/options/detectionOptions'
|
||||
import { multipleBarOption, pieForSeverity, activeAttackBar, getAttackColor, getSeverityColor } from '@/views/detections/options/detectionOptions'
|
||||
import { api, getData } from '@/utils/api'
|
||||
import { reverseSortBy, sortBy, extensionEchartY } from '@/utils/tools'
|
||||
import { reverseSortBy, extensionEchartY } from '@/utils/tools'
|
||||
import { useRoute } from 'vue-router'
|
||||
import DetectionNoData from '@/views/detections/DetectionNoData'
|
||||
// import DetectionNoData from '@/views/detections/DetectionNoData'
|
||||
import Loading from '@/components/common/Loading'
|
||||
import DetectionTabs from '@/views/detections/DetectionTabs'
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
@@ -125,10 +145,32 @@ export default {
|
||||
DetectionFilter,
|
||||
DetectionList,
|
||||
Pagination,
|
||||
DetectionNoData
|
||||
// DetectionNoData,
|
||||
DetectionTabs
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
tabsData: [
|
||||
// todo icon名称可能不一致,后续改
|
||||
{
|
||||
name: 'SecurityEvents',
|
||||
i18n: 'entities.securityEvents',
|
||||
path: '/detection/securityEvent',
|
||||
icon: 'cn-icon cn-icon-SecurityEvent'
|
||||
},
|
||||
{
|
||||
name: 'Regulatory Risk Event',
|
||||
i18n: 'entities.regulatoryRiskEvents',
|
||||
path: '/detection/securityEvent',
|
||||
icon: 'cn-icon cn-icon-RegulatoryRiskEvent'
|
||||
},
|
||||
{
|
||||
name: 'PerformanceEvents',
|
||||
i18n: 'overall.performanceEvents',
|
||||
path: '/detection/performanceEvent',
|
||||
icon: 'cn-icon cn-icon-PerformanceEvent'
|
||||
}
|
||||
],
|
||||
chartInit: [],
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
@@ -231,7 +273,6 @@ export default {
|
||||
isStatisticsCategoryNoData: false,
|
||||
isStatisticsActiveAttackNoData: false,
|
||||
loading: false,
|
||||
|
||||
oldActiveEntitySearchValue: ''
|
||||
}
|
||||
},
|
||||
@@ -270,8 +311,10 @@ export default {
|
||||
const seriesData = []
|
||||
xData.forEach(item => {
|
||||
if (dataMap.has(serie.name)) {
|
||||
// todo 下面这行注释可解决eslint报红线的问题,暂不知道原因,后续解决
|
||||
// eslint-disable-next-line array-callback-return
|
||||
const hasX = dataMap.get(serie.name).some(function (v) {
|
||||
if (item == v[0]) {
|
||||
if (item === v[0]) {
|
||||
seriesData.push(Number(v[1]))
|
||||
return true
|
||||
}
|
||||
@@ -296,7 +339,7 @@ export default {
|
||||
// this.isEventSeverityNoData = true
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
}).finally(() => {
|
||||
this.$nextTick(() => {
|
||||
this.loading = false
|
||||
@@ -329,7 +372,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initEventTypeData (params) {
|
||||
@@ -357,7 +400,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initSecurityTypeData (params) {
|
||||
@@ -385,7 +428,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initOffenderIpData (params) {
|
||||
@@ -419,7 +462,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
|
||||
@@ -430,7 +473,7 @@ export default {
|
||||
this.filterData[this.pageType][2].showMore = showMore
|
||||
this.filterData[this.pageType][2].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initVictimLocationData (params) {
|
||||
@@ -440,7 +483,7 @@ export default {
|
||||
this.filterData[this.pageType][3].showMore = showMore
|
||||
this.filterData[this.pageType][3].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initOffenderLocationData (params) {
|
||||
@@ -450,7 +493,7 @@ export default {
|
||||
this.filterData[this.pageType][5].showMore = showMore
|
||||
this.filterData[this.pageType][5].showIndex = showIndex
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
initActiveEntity (params) {
|
||||
@@ -510,6 +553,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}).catch(error => {
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
triggerFilterDataValue (array, value) {
|
||||
@@ -539,12 +583,12 @@ export default {
|
||||
getData(api.detection[this.pageType].listBasic, params).then(data => {
|
||||
this.listData = data
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
getData(api.detection[this.pageType].listCount, params).then(data => {
|
||||
this.pageObj.total = data
|
||||
}).catch(error => {
|
||||
|
||||
console.log(error)
|
||||
})
|
||||
},
|
||||
timeRefreshChange () {
|
||||
@@ -789,3 +833,33 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.explorer-top-tools-title {
|
||||
font-size: 24px;
|
||||
line-height: 24px;
|
||||
font-weight: 900;
|
||||
color: #353636;
|
||||
}
|
||||
.explorer-top-tools-block {
|
||||
font-family: NotoSansHans-Medium;
|
||||
height: 28px;
|
||||
line-height: 28px;
|
||||
font-size: 14px;
|
||||
color: #353636;
|
||||
font-weight: 500;
|
||||
padding: 0 10px;
|
||||
margin-right: 10px;
|
||||
border: 1px solid #E0E0E0;
|
||||
border-radius: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.detection-icon-setting {
|
||||
margin-right: 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
.detection-border {
|
||||
border: 1px solid #E0E0E0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user