summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchenjinsong <[email protected]>2023-10-14 15:22:38 +0800
committerchenjinsong <[email protected]>2023-10-14 15:22:38 +0800
commitcdd3557bbea3839f32bc519ef6da01d2203f0298 (patch)
tree158c1ec573650b7f6f88617f370dcd55ca3b2519
parentb44a99f35470fbe0dbcf23e374695351c7c99862 (diff)
CN-1388 fix: 调整实体列表等待交互和接口请求顺序等23.09.1
1.调整接口请求顺序为list > 左侧筛选 > 顶部统计; 2.优化左侧筛选loading交互; 3.将默认每页条数改为10,可选条数由20,30,50改为10,20,50
-rw-r--r--src/assets/css/components/views/entityExplorer/entity-filter.scss1
-rw-r--r--src/assets/css/components/views/entityExplorer/entityList/entity-list.scss2
-rw-r--r--src/components/common/Pagination.vue31
-rw-r--r--src/components/layout/Header.vue4
-rw-r--r--src/views/entityExplorer/EntityExplorer.vue140
-rw-r--r--src/views/entityExplorer/EntityFilter.vue87
-rw-r--r--src/views/entityExplorer/entityList/EntityList.vue6
7 files changed, 172 insertions, 99 deletions
diff --git a/src/assets/css/components/views/entityExplorer/entity-filter.scss b/src/assets/css/components/views/entityExplorer/entity-filter.scss
index 11b71e9e..6d65ccb8 100644
--- a/src/assets/css/components/views/entityExplorer/entity-filter.scss
+++ b/src/assets/css/components/views/entityExplorer/entity-filter.scss
@@ -32,6 +32,7 @@
width: calc(100% - 30px);
margin: 0 10px 0 20px;
max-height: 265px;
+ min-height: 40px;
overflow-y: scroll;
overflow-x: hidden;
diff --git a/src/assets/css/components/views/entityExplorer/entityList/entity-list.scss b/src/assets/css/components/views/entityExplorer/entityList/entity-list.scss
index 8542d855..1df06a41 100644
--- a/src/assets/css/components/views/entityExplorer/entityList/entity-list.scss
+++ b/src/assets/css/components/views/entityExplorer/entityList/entity-list.scss
@@ -21,7 +21,7 @@
.entity-list--list {
display: flex;
flex-direction: column;
- height: 100%;
+ height: auto;
/*overflow: visible;/*overflow: auto;*/
.cn-entity__shadow {
diff --git a/src/components/common/Pagination.vue b/src/components/common/Pagination.vue
index 9e898ca1..0f03cadd 100644
--- a/src/components/common/Pagination.vue
+++ b/src/components/common/Pagination.vue
@@ -58,13 +58,24 @@ export default {
*/
setup (props) {
const { query } = useRoute()
- const pageSize = ref(defaultPageSize)
+ // pageSize取值顺序:1.url;2.缓存;3.pageObj;4.默认值
+ const urlPageSize = parseInt(query.pageSize)
+ const cachePageSize = parseInt(localStorage.getItem(storageKey.pageSize + '-' + localStorage.getItem(storageKey.username) + '-' + props.tableId))
+ const pageObjPageSize = props.pageObj.pageSize
+ const pageSize = ref(urlPageSize || cachePageSize || pageObjPageSize || defaultPageSize)
const currentPageNo = ref(props.storePageNoOnUrl ? (query.pageNo || (props.pageObj.pageNo || 1)) : (props.pageObj.pageNo || 1))
return {
pageSize,
currentPageNo
}
},
+ mounted () {
+ if (this.postPageSizes && this.postPageSizes.length > 0) {
+ this.resetPageSizes()
+ }
+ this.currentPageNo = parseInt(this.currentPageNo)
+ this.current(this.currentPageNo)
+ },
data () {
return {
// pageSize: defaultPageSize,
@@ -147,6 +158,7 @@ export default {
size (val) {
// eslint-disable-next-line vue/no-mutating-props
// this.pageObj.pageNo = 1
+ this.$emit('scrollbarToTop')
this.$emit('pageSize', val)
this.backgroundColor()
@@ -163,11 +175,12 @@ export default {
wrap.scrollTop = 0
}
})
+ this.$emit('scrollbarToTop')
})
},
resetPageSizes: function () {
if (this.postPageSizes) {
- this.pageSizes = this.postPageSizes.map((item) => {
+ this.pageSizes = this.postPageSizes.map(item => {
return {
label: item + this.$t('pageSize'),
value: item
@@ -183,20 +196,6 @@ export default {
// }
}
},
- mounted () {
- if (this.postPageSizes && this.postPageSizes.length > 0) {
- this.pageSize = this.postPageSizes[0]
- this.resetPageSizes()
- } else {
- const pageSize = localStorage.getItem(storageKey.pageSize + '-' + localStorage.getItem(storageKey.username) + '-' + this.tableId)
- if (pageSize != 'undefined' && pageSize != null) {
- this.pageSize = parseInt(pageSize)
- }
- }
-
- this.currentPageNo = parseInt(this.currentPageNo)
- this.current(this.currentPageNo)
- },
watch: {
postPageSizes: {
immediate: true,
diff --git a/src/components/layout/Header.vue b/src/components/layout/Header.vue
index d35603f5..541e3d48 100644
--- a/src/components/layout/Header.vue
+++ b/src/components/layout/Header.vue
@@ -804,10 +804,10 @@ export default {
}
})
}
- if (route === this.route) {
+ /* if (route === this.route) {
this.refresh()
return
- }
+ } */
if (route) {
this.$router.push({
path: route,
diff --git a/src/views/entityExplorer/EntityExplorer.vue b/src/views/entityExplorer/EntityExplorer.vue
index 5b58ae20..262deee5 100644
--- a/src/views/entityExplorer/EntityExplorer.vue
+++ b/src/views/entityExplorer/EntityExplorer.vue
@@ -185,7 +185,6 @@ export default {
},
data () {
return {
- showList: false,
listMode: 'list', // entity列表的模式,list|block
entityAppTotal: '-',
@@ -213,28 +212,36 @@ export default {
title: this.$t('entity.topCountries'),
topColumn: 'ip.country',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-city',
title: this.$t('entity.topCities'),
topColumn: 'ip.city',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-as',
title: this.$t('entity.topASNs'),
topColumn: 'ip.asn',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-operator',
title: this.$t('entity.topISPs'),
topColumn: 'ip.isp',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-open-port',
@@ -242,28 +249,36 @@ export default {
topColumn: 'ip.port',
topColumn1: 'ip.protocol',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-FQDN',
title: this.$t('entity.topFQDNCategories'),
topColumn: 'domain.category',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-category2',
title: this.$t('entity.topAppCategories'),
topColumn: 'app.category',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
},
{
icon: 'cn-icon cn-icon-tag1',
title: this.$t('entity.topTags'),
topColumn: 'tag',
totalCount: 0,
- data: []
+ data: [],
+ loading: false,
+ firstLoad: true
}
],
listData: [],
@@ -396,16 +411,17 @@ export default {
mode: mode,
range: this.timeFilter.dateRangeValue,
pageNo: this.pageObj.pageNo,
- pageSize: this.pageObj.pageSize
+ pageSize: this.pageObj.pageSize,
+ showList: true
}
})
- this.showList = true
+ // this.showList = true
// 跳转页面,则不执行搜索功能
return true
}
- this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
this.queryList({ q: this.q, ...this.pageObj, ...this.timeFilter })
+ this.queryFilterNew({ q: this.q, ...this.pageObj, ...this.timeFilter })
this.queryCount({ q: this.q, ...this.pageObj, ...this.timeFilter })
// 延时一秒,避免初始化时pageSize为20,pageNo为1也会调用“搜索”的情况
@@ -489,8 +505,8 @@ export default {
/** 新版查询filter数据 */
queryFilterNew (params) {
const queryParams = {
- // startTime: getSecond(params.startTime),
- // endTime: getSecond(params.endTime),
+ startTime: getSecond(params.startTime),
+ endTime: getSecond(params.endTime),
resource: params.q || ''
}
this.loadingLeft = true
@@ -502,8 +518,48 @@ export default {
const aggDomain = axios.get(api.entity.entityList.aggDomain, { params: queryParams })
const aggAppCategory = axios.get(api.entity.entityList.aggAppCategory, { params: queryParams })
const aggTag = axios.get(api.entity.entityList.aggTag, { params: queryParams })
-
- Promise.all([aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]).then(response => {
+ const requests = [aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]
+ requests.forEach((req, index) => {
+ this.newFilterData[index].loading = true
+ req.then(response => {
+ if (response.status === 200 && response.data.data.list) {
+ if (response.data.data.list.length >= 5) {
+ this.newFilterData[index].showNum = 5
+ } else {
+ this.newFilterData[index].showNum = response.data.data.list.length
+ }
+ this.newFilterData[index].data = []
+ response.data.data.list.forEach((item, i) => {
+ let obj = {
+ label: item.value,
+ topColumn: this.newFilterData[index].topColumn,
+ value: item.uniqueEntities,
+ showNum: 5
+ }
+ if (index === 0) {
+ obj.flag = item.value // 接口字段名称为'China',svg名称为'CN',通过countryNameIdMapping进行转换
+ }
+ if (index === 4) {
+ obj = {
+ topColumn: this.newFilterData[index].topColumn,
+ topColumn1: this.newFilterData[index].topColumn1,
+ port: item.port,
+ l7Protocol: item.l7Protocol,
+ value: item.uniqueEntities,
+ showNum: 5
+ }
+ }
+ this.newFilterData[index].data.push(obj)
+ })
+ }
+ }).catch(e => {
+ this.$message.error(e.response.data.message)
+ }).finally(() => {
+ this.newFilterData[index].loading = false
+ this.newFilterData[index].firstLoad = false
+ })
+ })
+ /*Promise.all([aggCountry, aggCity, aggIPAsn, aggIPIsp, aggPort, aggDomain, aggAppCategory, aggTag]).then(response => {
response.forEach((item1, index) => {
if (item1.status === 200 && item1.data.data.list) {
if (item1.data.data.list.length >= 5) {
@@ -540,7 +596,7 @@ export default {
this.$message.error(e.response.data.message)
}).finally(() => {
this.loadingLeft = false
- })
+ })*/
},
/** 实体列表查询 */
queryList (params) {
@@ -548,8 +604,8 @@ export default {
const queryParams = {
pageSize: params.pageSize,
pageNo: params.pageNo,
- // startTime: getSecond(params.startTime),
- // endTime: getSecond(params.endTime),
+ startTime: getSecond(params.startTime),
+ endTime: getSecond(params.endTime),
resource: params.q || ''
}
axios.get(api.entity.entityList.list, { params: queryParams }).then(response => {
@@ -570,8 +626,8 @@ export default {
queryCount (params) {
this.loadingCount = true
const queryParams = {
- // startTime: getSecond(params.startTime),
- // endTime: getSecond(params.endTime),
+ startTime: getSecond(params.startTime),
+ endTime: getSecond(params.endTime),
resource: params.q || ''
}
axios.get(api.entity.entityList.summaryCount, { params: queryParams }).then(response => {
@@ -692,23 +748,25 @@ export default {
}
},
mounted () {
- this.getEntityIndexData()
- let { q, listMode } = this.$route.query
+ if (!this.showList) {
+ this.getEntityIndexData()
+ } else {
+ let { q, listMode } = this.$route.query
- // 如果地址栏有listMode,即列表页,并非首页,则开始搜索
- if (listMode) {
- this.showList = true
- // %位置为0是输入中文时能解码,%20,25%分别是空格和%的情况
- if (q && (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1)) {
- q = decodeURI(q)
- }
- // %位置不为0,即内容包含非英文时
- const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
- if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
- q = decodeURI(q)
+ // 如果地址栏有listMode,即列表页,并非首页,则开始搜索
+ if (listMode) {
+ // %位置为0是输入中文时能解码,%20,25%分别是空格和%的情况
+ if (q && (q.indexOf('%') === 0 || q.indexOf('%20') > -1 || q.indexOf('%25') > -1)) {
+ q = decodeURI(q)
+ }
+ // %位置不为0,即内容包含非英文时
+ const str1 = q.substring(q.indexOf('%'), q.indexOf('%') + 3)
+ if (q && q.indexOf('%') > 0 && (str1 !== '%20' || str1 === '%25')) {
+ q = decodeURI(q)
+ }
+ this.initSearch(q)
+ this.listMode = listMode
}
- this.initSearch(q)
- this.listMode = listMode
}
},
watch: {
@@ -722,11 +780,12 @@ export default {
const rangeParam = query.range
const startTimeParam = query.startTime
const endTimeParam = query.endTime
+ const showList = ref(Boolean(query.showList))
// 若url携带了,使用携带的值,否则使用默认值。
- const dateRangeValue = rangeParam ? parseInt(query.range) : 60
+ const dateRangeValue = rangeParam ? parseInt(query.range) : 60 * 24
const timeFilter = ref({ dateRangeValue })
if (!startTimeParam || !endTimeParam) {
- const { startTime, endTime } = getNowTime(60)
+ const { startTime, endTime } = getNowTime(60 * 24)
timeFilter.value.startTime = startTime
timeFilter.value.endTime = endTime
} else {
@@ -737,12 +796,13 @@ export default {
pageNo: query.pageNo ? parseInt(query.pageNo) : 1,
// 是否重置pageNo,在执行新搜索时是true
resetPageNo: true,
- pageSize: query.pageSize ? parseInt(query.pageSize) : defaultPageSize,
+ pageSize: query.pageSize ? parseInt(query.pageSize) : 10, // TODO 23-10-14 默认暂时改为10
total: 0
})
return {
timeFilter,
- pageObj
+ pageObj,
+ showList
}
},
beforeUnmount () {
diff --git a/src/views/entityExplorer/EntityFilter.vue b/src/views/entityExplorer/EntityFilter.vue
index 0200c592..b29b765e 100644
--- a/src/views/entityExplorer/EntityFilter.vue
+++ b/src/views/entityExplorer/EntityFilter.vue
@@ -2,51 +2,49 @@
<div class="entity-filter-case" style="position: relative">
<div class="filter-case__header">{{ $t('entities.filter1') }}</div>
- <div v-if="filterDataLength>0">
+ <div v-if="filterDataLength > 0">
<div class="entity-filter" v-for="(item, index) in myFilterData" :key="index">
- <div v-if="item.data.length>0">
- <div class="filter__header">
- <i :class="item.icon"></i>
- {{ item.title }}
- </div>
+ <div class="filter__header">
+ <i :class="item.icon"></i>
+ {{ item.title }}
+ </div>
- <div class="filter__body" style="position: relative">
- <loading :loading="loadingLeft" style="top: -5px;"></loading>
+ <div class="filter__body" style="position: relative">
+ <loading :loading="item.loading" style="top: -5px;"></loading>
- <div class="filter__body-item"
- v-for="(data, i) in item.data.slice(0, item.showNum)"
- :key="i"
- @click="filter(data.label, data)">
- <div class="filter__body-item-left">
- <div v-if="data.flag">
- <img v-if="data.flag===countryNameIdMapping.Unknown || !countryNameIdMapping[data.flag]" src="../../../public/images/flag/Unknown.svg" class="filter-country-flag">
- <img v-else :src="require(`../../../public/images/flag/${countryNameIdMapping[data.flag]}.png`)" class="filter-country-flag"/>
- </div>
- <div v-else class="filter__body-item-left-index">{{ i+1 }}</div>
- <div class="filter__body-item-left-label">
- <el-tooltip :content="data.label" placement="top" effect="light" :disabled="disabledLabel">
- <span @mouseenter="handleMouse(`filter${index}${i}`)" :id="`filter${index}${i}`">
- <span v-if="item.topColumn==='ip.port'">
- {{ data.port }}/{{ data.l7Protocol }}
- </span>
- <span v-else>{{ data.label }}</span>
+ <div class="filter__body-item"
+ v-for="(data, i) in item.data.slice(0, item.showNum)"
+ :key="i"
+ @click="filter(data.label, data)">
+ <div class="filter__body-item-left">
+ <div v-if="data.flag">
+ <img v-if="data.flag===countryNameIdMapping.Unknown || !countryNameIdMapping[data.flag]" src="../../../public/images/flag/Unknown.svg" class="filter-country-flag">
+ <img v-else :src="require(`../../../public/images/flag/${countryNameIdMapping[data.flag]}.png`)" class="filter-country-flag"/>
+ </div>
+ <div v-else class="filter__body-item-left-index">{{ i+1 }}</div>
+ <div class="filter__body-item-left-label">
+ <el-tooltip :content="data.label" placement="top" effect="light" :disabled="disabledLabel">
+ <span @mouseenter="handleMouse(`filter${index}${i}`)" :id="`filter${index}${i}`">
+ <span v-if="item.topColumn==='ip.port'">
+ {{ data.port }}/{{ data.l7Protocol }}
</span>
- </el-tooltip>
- </div>
+ <span v-else>{{ data.label }}</span>
+ </span>
+ </el-tooltip>
</div>
- <div class="filter__body-item-right">{{ data.value }}</div>
</div>
+ <div class="filter__body-item-right">{{ data.value }}</div>
</div>
- <div @click="showMoreFilter(item, index)"
- :class="item.showNum === item.data.length ? 'filter-no-show-more' : 'filter-show-more'">
- {{ $t('entity.showMore') }}
- </div>
- <div class="filter-hr"></div>
</div>
+ <div @click="showMoreFilter(item, index)"
+ :class="item.showNum >= item.data.length || item.data.length <= 5 ? 'filter-no-show-more' : 'filter-show-more'">
+ {{ $t('entity.showMore') }}
+ </div>
+ <div class="filter-hr"></div>
</div>
</div>
+ <loading v-else-if="isFirstLoad" :loading="isFirstLoad"></loading>
<chart-no-data v-else style="padding-top: 40px"></chart-no-data>
-
</div>
</template>
@@ -54,6 +52,7 @@
import Loading from '@/components/common/Loading'
import ChartNoData from '@/views/charts/charts/ChartNoData'
import { countryNameIdMapping } from '@/utils/constants'
+import _ from 'lodash'
export default {
name: 'EntityFilter',
components: { ChartNoData, Loading },
@@ -73,6 +72,9 @@ export default {
})
return length
+ },
+ isFirstLoad () {
+ return this.myFilterData.some(d => d.firstLoad)
}
},
data () {
@@ -85,6 +87,14 @@ export default {
mounted () {
this.myFilterData = this.filterData
},
+ watch: {
+ filterData: {
+ deep: true,
+ handler (n) {
+ this.myFilterData = _.cloneDeep(n)
+ }
+ }
+ },
methods: {
/**
* 判断文字是否溢出,超出则鼠标移入tooltip显示,否则鼠标移入不显示
@@ -103,17 +113,14 @@ export default {
this.$emit('filter', name, data)
},
showMoreFilter (item, index) {
- if ((item.data.length - item.showNum) >= 5) {
+ this.myFilterData[index].showNum = item.data.length
+ /*if ((item.data.length - item.showNum) >= 5) {
item.shouNum += 5
this.myFilterData[index].showNum += 5
} else {
this.myFilterData[index].showNum += (item.data.length - item.showNum)
- }
+ }*/
}
}
}
</script>
-
-<style lang="scss" scoped>
-
-</style>
diff --git a/src/views/entityExplorer/entityList/EntityList.vue b/src/views/entityExplorer/entityList/EntityList.vue
index 20dc36ea..830beb24 100644
--- a/src/views/entityExplorer/entityList/EntityList.vue
+++ b/src/views/entityExplorer/entityList/EntityList.vue
@@ -38,11 +38,13 @@
<Pagination
ref="pagination"
:page-obj="pageObj"
+ :post-page-sizes="[10, 20, 50]"
@pageNo='pageNo'
@pageSize='pageSize'
@size-change="pageSize"
@prev-click="prev"
@next-click="next"
+ @scrollbarToTop="scrollbarToTop"
>
</Pagination>
</div>
@@ -124,6 +126,10 @@ export default {
const container = document.getElementById('cnContainer')
container.scrollTop += e.deltaY / 2
}
+ },
+ scrollbarToTop () {
+ const container = document.getElementById('cnContainer')
+ container.scrollTop = 0
}
},
mounted () {