CN-299 feat: detection布局
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
@import './views/entityExplorer/entityList/card';
|
||||
@import './views/entityExplorer/entityList/row';
|
||||
@import 'views/entityExplorer/entityList/detail-overview';
|
||||
@import './views/detections/detections';
|
||||
@import './views/charts/panel';
|
||||
@import 'views/charts/chartIpOpenPortBar';
|
||||
@import './views/charts/chartTable';
|
||||
|
||||
19
src/assets/css/components/views/detections/detections.scss
Normal file
19
src/assets/css/components/views/detections/detections.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
.detection__event-severity-bar {
|
||||
flex: 0 0 175px;
|
||||
background-color: white;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.detection__list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
|
||||
.detection__list-statistics {
|
||||
display: flex;
|
||||
flex: 0 0 192px;
|
||||
margin-bottom: 10px;
|
||||
width: 100%;
|
||||
background-color: white;
|
||||
}
|
||||
}
|
||||
@@ -10,10 +10,6 @@ const routes = [
|
||||
path: '/entityDetail',
|
||||
component: () => import('@/views/entityExplorer/EntityDetail')
|
||||
},
|
||||
{
|
||||
path: '/detections',
|
||||
component: () => import('@/views/detections/Index')
|
||||
},
|
||||
{
|
||||
path: '/',
|
||||
component: () => import('@/components/layout/Home'),
|
||||
@@ -42,6 +38,10 @@ const routes = [
|
||||
path: '/entityExplorer',
|
||||
component: () => import('@/views/entityExplorer/EntityExplorer')
|
||||
},
|
||||
{
|
||||
path: '/detections',
|
||||
component: () => import('@/views/detections/Index')
|
||||
},
|
||||
{
|
||||
path: '/galaxyProxy',
|
||||
component: () => import('@/views/settings/GalaxyProxy')
|
||||
|
||||
11
src/views/detections/DetectionFilter.vue
Normal file
11
src/views/detections/DetectionFilter.vue
Normal file
@@ -0,0 +1,11 @@
|
||||
<template>
|
||||
<div class="entity-filter-case" style="background-color: white; height: 1000px;">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DetectionFilter'
|
||||
}
|
||||
</script>
|
||||
76
src/views/detections/DetectionList.vue
Normal file
76
src/views/detections/DetectionList.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<div class="entity-list" id="detectionList">
|
||||
<div class="entity__loading" style="background: #eff2f5;opacity: .6;" v-show="loading">
|
||||
<i class="el-icon-loading"></i>
|
||||
</div>
|
||||
<div class="entity-list__content">
|
||||
<div class="entity-list--list">
|
||||
<div class="no-data" v-if="noData">No data</div>
|
||||
<div v-if="!isCollapse" @click="collapse" class="cn-entity__shadow"></div>
|
||||
<detection-row
|
||||
v-for="(data, index) in listData"
|
||||
:detection="data"
|
||||
:timeFilter="timeFilter"
|
||||
:key="index"
|
||||
:ref="`detectionRow${index}`"
|
||||
:index="index"
|
||||
@switchCollapse="switchCollapse"
|
||||
></detection-row>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetectionRow from '@/views/detections/DetectionRow'
|
||||
export default {
|
||||
name: 'DetectionList',
|
||||
components: {
|
||||
DetectionRow
|
||||
},
|
||||
props: {
|
||||
listData: Array,
|
||||
from: String,
|
||||
pageObj: Object,
|
||||
loading: Boolean,
|
||||
timeFilter: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
showDetail: false,
|
||||
typeName: '',
|
||||
detectionList: [],
|
||||
isCollapse: true,
|
||||
collapseIndex: 0,
|
||||
tableId: 'detectionList',
|
||||
listDataCopy: [],
|
||||
noData: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
switchCollapse (isCollapse, index) {
|
||||
this.isCollapse = isCollapse
|
||||
this.collapseIndex = index
|
||||
},
|
||||
collapse () {
|
||||
this.isCollapse = true
|
||||
this.$refs[`detectionRow${this.collapseIndex}`].collapse()
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
listData: {
|
||||
deep: true,
|
||||
handler (n) {
|
||||
if (!n || n.length === 0) {
|
||||
this.timeout = setTimeout(() => {
|
||||
this.noData = true
|
||||
}, 500)
|
||||
} else {
|
||||
clearTimeout(this.timeout)
|
||||
this.noData = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
9
src/views/detections/DetectionOverview.vue
Normal file
9
src/views/detections/DetectionOverview.vue
Normal file
@@ -0,0 +1,9 @@
|
||||
<template>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'DetectionOverview'
|
||||
}
|
||||
</script>
|
||||
75
src/views/detections/DetectionRow.vue
Normal file
75
src/views/detections/DetectionRow.vue
Normal file
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="cn-entity--list" :style="{zIndex: !isCollapse ? 1 : 'unset'}">
|
||||
<!-- 左侧下拉按钮 -->
|
||||
<div class="cn-entity__collapse">
|
||||
<span @click="switchCollapse" :class="{'reg-down': !isCollapse}"><i class="cn-icon cn-icon-arrow-right"></i></span>
|
||||
</div>
|
||||
<div class="cn-entity__case">
|
||||
<div class="cn-entity__icon"><i class="el-icon-search"></i></div>
|
||||
<div class="cn-entity__row">
|
||||
<div class="cn-entity__header">3.4.5.6</div>
|
||||
<div class="cn-entity__body">
|
||||
<div class="body__basic-info">
|
||||
<div class="basic-info">
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-country"></i>
|
||||
<span>{{$t('overall.country')}} : </span>
|
||||
<span>hehe</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-position"></i>
|
||||
<span>{{$t('overall.region')}} : </span>
|
||||
<span>xixi</span>
|
||||
</div>
|
||||
<div class="basic-info__item">
|
||||
<i class="cn-icon cn-icon-cloud"></i>
|
||||
<span>{{$t('entities.asn')}} : </span>
|
||||
<span>heihei</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-collapse-transition>
|
||||
<div class="cn-entity__detail-overview" v-if="!isCollapse">
|
||||
<el-divider></el-divider>
|
||||
<detection-overview
|
||||
:entity="entityData"
|
||||
:time-filter="timeFilter"
|
||||
></detection-overview>
|
||||
</div>
|
||||
</el-collapse-transition>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetectionOverview from '@/views/detections/DetectionOverview'
|
||||
export default {
|
||||
name: 'DetectionRow',
|
||||
components: {
|
||||
DetectionOverview
|
||||
},
|
||||
props: {
|
||||
index: Number,
|
||||
timeFilter: Object
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
entityData: [],
|
||||
isCollapse: true // 是否是折叠状态
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
/* 切换折叠状态 */
|
||||
switchCollapse () {
|
||||
this.isCollapse = !this.isCollapse
|
||||
this.$emit('switchCollapse', this.isCollapse, this.index)
|
||||
},
|
||||
/* 设为折叠状态 */
|
||||
collapse () {
|
||||
this.isCollapse = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
42
src/views/detections/DetectionSearch.vue
Normal file
42
src/views/detections/DetectionSearch.vue
Normal file
@@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="explorer-search">
|
||||
<div class="explorer-search__input-case explorer-search__input-case--question-mark-in-line">
|
||||
<div class="explorer-search__input">
|
||||
<advanced-search
|
||||
ref="search"
|
||||
:column-list="columnList"
|
||||
:operator-list="operatorList"
|
||||
:connection-list="connectionList"
|
||||
:full-text="true"
|
||||
class="advanced-search--show-list"
|
||||
@search="search"
|
||||
></advanced-search>
|
||||
</div>
|
||||
<div class="search-symbol-inline">
|
||||
<i class="cn-icon cn-icon-help"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AdvancedSearch from '@/components/advancedSearch/Index'
|
||||
export default {
|
||||
name: 'DetectionSearch',
|
||||
components: {
|
||||
AdvancedSearch
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
columnList: [],
|
||||
operatorList: [],
|
||||
connectionList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
search () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -1,13 +1,148 @@
|
||||
<template>
|
||||
|
||||
<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" ref="dateTimeRange" @change="reload"/>
|
||||
<TimeRefresh class="date-time-range" @change="timeRefreshChange" :end-time="timeFilter.endTime"/>
|
||||
</div>
|
||||
<!-- 搜索组件 -->
|
||||
<detection-search
|
||||
ref="search"
|
||||
@search="search"
|
||||
></detection-search>
|
||||
<!-- 内容区 -->
|
||||
<div class="explorer-container" style="height: calc(100% - 20px); flex-direction: column">
|
||||
<div class="detection__event-severity-bar"></div>
|
||||
<div style="display: flex; height: 100%;">
|
||||
<detection-filter
|
||||
:filter-data="filterData"
|
||||
:q="q"
|
||||
:time-filter="timeFilter"
|
||||
@filter="filter"
|
||||
></detection-filter>
|
||||
<div class="detection__list">
|
||||
<div class="detection__list-statistics"></div>
|
||||
<detection-list
|
||||
:list-data="listData"
|
||||
:pageObj="pageObj"
|
||||
:time-filter="timeFilter"
|
||||
@pageSize="pageSize"
|
||||
@pageNo="pageNo"
|
||||
:loading="listLoading"
|
||||
></detection-list>
|
||||
</div>
|
||||
</div>
|
||||
<div class="entity__pagination" style="position: absolute; bottom: 0; width: 100%;">
|
||||
<Pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@pageSize='pageSize'
|
||||
@size-change="pageSize"
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
>
|
||||
</Pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetectionSearch from '@/views/detections/DetectionSearch'
|
||||
import DateTimeRange from '@/components/common/TimeRange/DateTimeRange'
|
||||
import TimeRefresh from '@/components/common/TimeRange/TimeRefresh'
|
||||
import DetectionFilter from '@/views/detections/DetectionFilter'
|
||||
import DetectionList from '@/views/detections/DetectionList'
|
||||
import Pagination from '@/components/common/Pagination'
|
||||
import { defaultPageSize } from '@/utils/constants'
|
||||
import { getNowTime } from '@/utils/date-util'
|
||||
import { ref } from 'vue'
|
||||
export default {
|
||||
name: 'Index'
|
||||
name: 'Index',
|
||||
components: {
|
||||
DetectionSearch,
|
||||
DateTimeRange,
|
||||
TimeRefresh,
|
||||
DetectionFilter,
|
||||
DetectionList,
|
||||
Pagination
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
pageSize: defaultPageSize,
|
||||
total: 0
|
||||
},
|
||||
q: '',
|
||||
filterData: [],
|
||||
listData: [],
|
||||
listLoading: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
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 }
|
||||
},
|
||||
search () {
|
||||
|
||||
},
|
||||
filter () {
|
||||
|
||||
},
|
||||
pageSize (val) {
|
||||
this.pageObj.pageSize = val
|
||||
this.search(this.metaList, this.q)
|
||||
},
|
||||
pageNo (val) {
|
||||
this.pageObj.pageNo = val
|
||||
this.search(this.metaList, this.q)
|
||||
},
|
||||
// 点击上一页箭头
|
||||
prev () {
|
||||
this.scrollbarToTop()
|
||||
},
|
||||
// 点击下一页箭头
|
||||
next () {
|
||||
this.scrollbarToTop()
|
||||
},
|
||||
// currentPage 改变时会触发
|
||||
current (val) {
|
||||
this.$emit('pageNo', val)
|
||||
this.scrollbarToTop()
|
||||
},
|
||||
scrollbarToTop () {
|
||||
this.$nextTick(() => {
|
||||
const wraps = document.querySelector('#detectionList')
|
||||
wraps.scrollTop = 0
|
||||
})
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
timeFilter (n) {
|
||||
this.search(this.metaList, this.q)
|
||||
}
|
||||
},
|
||||
setup () {
|
||||
const dateRangeValue = 60
|
||||
const { startTime, endTime } = getNowTime(dateRangeValue)
|
||||
const timeFilter = ref({ startTime, endTime, dateRangeValue })
|
||||
return {
|
||||
timeFilter
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
></entity-list>
|
||||
</div>
|
||||
<div class="entity__pagination" style="position: absolute; bottom: 0; width: 100%;">
|
||||
<pagination
|
||||
<Pagination
|
||||
ref="pagination"
|
||||
:page-obj="pageObj"
|
||||
@pageNo='pageNo'
|
||||
@@ -47,7 +47,7 @@
|
||||
@prev-click="prev"
|
||||
@next-click="next"
|
||||
>
|
||||
</pagination>
|
||||
</Pagination>
|
||||
</div>
|
||||
</div>
|
||||
<div class="explorer-foot" v-else>
|
||||
@@ -126,7 +126,7 @@ import { get } from '@/utils/http'
|
||||
import { api } from '@/utils/api'
|
||||
import { getNowTime, getSecond } from '@/utils/date-util'
|
||||
import { ref } from 'vue'
|
||||
import pagination from '@/components/common/Pagination'
|
||||
import Pagination from '@/components/common/Pagination'
|
||||
|
||||
export default {
|
||||
name: 'entity-explorer',
|
||||
@@ -136,7 +136,7 @@ export default {
|
||||
TimeRefresh,
|
||||
EntityFilter,
|
||||
EntityList,
|
||||
pagination: pagination
|
||||
Pagination
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
@@ -155,7 +155,6 @@ export default {
|
||||
entityIpNew: '-',
|
||||
entityIpActive: '-',
|
||||
|
||||
showFilter: ['ip', 'app', 'domain'], // ip,domain,app
|
||||
pageObj: {
|
||||
pageNo: 1,
|
||||
pageSize: defaultPageSize,
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
import AdvancedSearch from '@/components/advancedSearch/Index'
|
||||
import { columnType } from '@/components/advancedSearch/meta/meta'
|
||||
import SqlParser from '@/components/advancedSearch/meta/sql-parser'
|
||||
import {storageKey} from "@/utils/constants";
|
||||
import { storageKey } from '@/utils/constants'
|
||||
export default {
|
||||
name: 'CnSearch',
|
||||
components: {
|
||||
|
||||
Reference in New Issue
Block a user