feat: 通过虚拟列表优化情报--追踪页右侧时间线过多导致的卡顿现象
This commit is contained in:
@@ -227,16 +227,21 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-timeline :id="subscriber.subscriberId" v-show="subscriber.show" :class="subscriber.show ? '' : 'el-timeline--hide'">
|
|
||||||
<template v-for="(record, index) in trackingSubscriberRecordMap[subscriber.subscriberId].slice(0, subscriber.scrollNum)">
|
<div class="scroll-view" @scroll="onScroll" :id="subscriber.subscriberId" v-show="subscriber.show">
|
||||||
<el-timeline-item
|
<!-- 虚拟列表 -->
|
||||||
:key="index"
|
<div class="virtual-scroller" :style="`height: ${subscriber.listHeight}px`"></div>
|
||||||
v-if="index > 0"
|
<div class="scroll-list" :style="`transform: translateY(${subscriber.startOffset}px)`">
|
||||||
color="#de3434"
|
<div class="scroll__item"
|
||||||
@mouseenter="timelineMouseEnter(subscriber, record)"
|
v-for="(record, index) in trackingSubscriberRecordMap[subscriber.subscriberId].slice(subscriber.scrollStartIndex, subscriber.scrollEndIndex)"
|
||||||
@mouseleave="timelineMouseLeave(subscriber, record)"
|
:key="index"
|
||||||
>
|
@mouseenter="timelineMouseEnter(subscriber, record)"
|
||||||
<div class="timeline__item">
|
@mouseleave="timelineMouseLeave(subscriber, record)">
|
||||||
|
<div class="item-circle">
|
||||||
|
<div class="circle-circle"></div>
|
||||||
|
<div class="circle-line"></div>
|
||||||
|
</div>
|
||||||
|
<div class="item-content">
|
||||||
<div>
|
<div>
|
||||||
<span>{{$t('overall.location')}}: </span><span class="item__value">{{record.subscriberLongitude}}, {{record.subscriberLatitude}}</span>
|
<span>{{$t('overall.location')}}: </span><span class="item__value">{{record.subscriberLongitude}}, {{record.subscriberLatitude}}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -247,9 +252,9 @@
|
|||||||
<span>{{ $t('location.residenceTime') }}: </span><span class="item__value">{{record.stayTime}}</span>
|
<span>{{ $t('location.residenceTime') }}: </span><span class="item__value">{{record.stayTime}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-timeline-item>
|
</div>
|
||||||
</template>
|
</div>
|
||||||
</el-timeline>
|
</div>
|
||||||
|
|
||||||
<div :class="trackingSubscriberRecordMap[subscriber.subscriberId].length === 1 ? 'item-record__btn-disabled' : 'item-record__btn'" @click.stop="clickTrackBlock(index)">
|
<div :class="trackingSubscriberRecordMap[subscriber.subscriberId].length === 1 ? 'item-record__btn-disabled' : 'item-record__btn'" @click.stop="clickTrackBlock(index)">
|
||||||
<span v-if="!subscriber.show"><i class="cn-icon cn-icon-down2" :style="trackingSubscriberRecordMap[subscriber.subscriberId].length === 1 ? 'color: #C0C4CC' : ''"></i></span>
|
<span v-if="!subscriber.show"><i class="cn-icon cn-icon-down2" :style="trackingSubscriberRecordMap[subscriber.subscriberId].length === 1 ? 'color: #C0C4CC' : ''"></i></span>
|
||||||
@@ -409,7 +414,11 @@ export default {
|
|||||||
activeNames: '',
|
activeNames: '',
|
||||||
initFlag: true,
|
initFlag: true,
|
||||||
emptyTip: '',
|
emptyTip: '',
|
||||||
opacity: 1
|
opacity: 1,
|
||||||
|
scrollInfo: {
|
||||||
|
itemSize: 50, // 一个滚动item高度
|
||||||
|
containerHeight: 300 // 滚动列表
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
@@ -700,12 +709,15 @@ export default {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 计算停留时间
|
// 计算停留时间
|
||||||
this.trackingSubscribers.forEach(s => {
|
this.trackingSubscribers.forEach((s, index) => {
|
||||||
const trackRecords = this.trackingSubscriberRecordMap[s.subscriberId]
|
const trackRecords = this.trackingSubscriberRecordMap[s.subscriberId]
|
||||||
if (trackRecords.length < 20) {
|
// 初始化时间线可视范围角标
|
||||||
s.scrollNum = trackRecords.length
|
if (trackRecords.length < 6) {
|
||||||
|
s.scrollStartIndex = 1
|
||||||
|
s.scrollEndIndex = trackRecords.length
|
||||||
} else {
|
} else {
|
||||||
s.scrollNum = 20
|
s.scrollStartIndex = 1
|
||||||
|
s.scrollEndIndex = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trackRecords && trackRecords.length > 0) {
|
if (trackRecords && trackRecords.length > 0) {
|
||||||
@@ -736,6 +748,11 @@ export default {
|
|||||||
}
|
}
|
||||||
trackRecords[i].stayTime = stayTime.join(' ')
|
trackRecords[i].stayTime = stayTime.join(' ')
|
||||||
}
|
}
|
||||||
|
if (i === trackRecords.length - 1) {
|
||||||
|
// 初始化数据时,重置偏移量和列表高度
|
||||||
|
s.startOffset = 0
|
||||||
|
s.listHeight = i * this.scrollInfo.itemSize
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1143,6 +1160,15 @@ export default {
|
|||||||
this.trackingSubscribers[i].show = !this.trackingSubscribers[i].show
|
this.trackingSubscribers[i].show = !this.trackingSubscribers[i].show
|
||||||
if (this.trackingSubscribers[i].show) {
|
if (this.trackingSubscribers[i].show) {
|
||||||
this.trackingSubscribers[i].showLine = true
|
this.trackingSubscribers[i].showLine = true
|
||||||
|
this.trackingSubscribers[i].scrollStartIndex = 1
|
||||||
|
this.trackingSubscribers[i].scrollEndIndex = 6
|
||||||
|
this.trackingSubscribers[i].startOffset = 0
|
||||||
|
this.trackingSubscribers[i].listHeight = 0
|
||||||
|
// 高度置为0,是为了切换时间后再打开时间线,让滚动条置顶
|
||||||
|
const timer = setTimeout(() => {
|
||||||
|
this.trackingSubscribers[i].listHeight = this.trackingSubscriberRecordMap[this.trackingSubscribers[i].subscriberId].length * this.scrollInfo.itemSize
|
||||||
|
clearTimeout(timer)
|
||||||
|
}, 100)
|
||||||
} else {
|
} else {
|
||||||
const timer = setTimeout(() => {
|
const timer = setTimeout(() => {
|
||||||
this.trackingSubscribers[i].showLine = false
|
this.trackingSubscribers[i].showLine = false
|
||||||
@@ -1150,23 +1176,6 @@ export default {
|
|||||||
}, 200)
|
}, 200)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const dom = document.getElementById(this.trackingSubscribers[i].subscriberId)
|
|
||||||
if (dom) {
|
|
||||||
dom.addEventListener('scroll', (e) => {
|
|
||||||
const clientHeight = e.target.clientHeight
|
|
||||||
const scrollTop = e.target.scrollTop
|
|
||||||
const scrollHeight = e.target.scrollHeight
|
|
||||||
if (scrollTop && _.ceil(clientHeight + scrollTop) >= scrollHeight) {
|
|
||||||
if (this.trackingSubscribers[i].scrollNum < length) {
|
|
||||||
this.trackingSubscribers[i].scrollNum = this.trackingSubscribers[i].scrollNum + 20
|
|
||||||
if (this.trackingSubscribers[i].scrollNum > length) {
|
|
||||||
this.trackingSubscribers[i].scrollNum = length
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
changeCurrentShowSubscriber (subscriber) {
|
changeCurrentShowSubscriber (subscriber) {
|
||||||
if (subscriber.subscriberId !== this.currentShowSubscriber.subscriberId) {
|
if (subscriber.subscriberId !== this.currentShowSubscriber.subscriberId) {
|
||||||
@@ -1180,7 +1189,7 @@ export default {
|
|||||||
const index = this.trackingSubscribers.findIndex(s => s.subscriberId === subscriber.subscriberId)
|
const index = this.trackingSubscribers.findIndex(s => s.subscriberId === subscriber.subscriberId)
|
||||||
this.trackingSubscribers.splice(index, 1)
|
this.trackingSubscribers.splice(index, 1)
|
||||||
} else {
|
} else {
|
||||||
this.trackingSubscribers.push({ ...subscriber, show: false, showLine: false, scrollNum: 0 })
|
this.trackingSubscribers.push({ ...subscriber, show: false, showLine: false, scrollStartIndex: 1, scrollEndIndex: 6, startOffset: 0, listHeight: 0 })
|
||||||
}
|
}
|
||||||
this.opacity = 0
|
this.opacity = 0
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
@@ -1215,7 +1224,7 @@ export default {
|
|||||||
trackSubscriber (subscriber) {
|
trackSubscriber (subscriber) {
|
||||||
const find = this.trackingSubscribers.find(s => s.subscriberId === subscriber.subscriberId)
|
const find = this.trackingSubscribers.find(s => s.subscriberId === subscriber.subscriberId)
|
||||||
if (!find) {
|
if (!find) {
|
||||||
this.trackingSubscribers.push({ ...subscriber, show: false, showLine: false, scrollNum: 0 })
|
this.trackingSubscribers.push({ ...subscriber, show: false, showLine: false, scrollStartIndex: 1, scrollEndIndex: 6, startOffset: 0, listHeight: 0 })
|
||||||
}
|
}
|
||||||
this.currentShowSubscriber = subscriber
|
this.currentShowSubscriber = subscriber
|
||||||
this.activeTab = 'traceTracking'
|
this.activeTab = 'traceTracking'
|
||||||
@@ -1372,6 +1381,19 @@ export default {
|
|||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.mapDomHeight = document.getElementById('analysisMap').offsetHeight + 150
|
this.mapDomHeight = document.getElementById('analysisMap').offsetHeight + 150
|
||||||
})
|
})
|
||||||
|
},
|
||||||
|
onScroll (e) {
|
||||||
|
const find = this.trackingSubscribers.find(d => d.subscriberId === e.target.id)
|
||||||
|
// 当前滚动位置
|
||||||
|
const scrollTop = e.target.scrollTop
|
||||||
|
// 列表开始索引
|
||||||
|
const startIndex = Math.floor(scrollTop / this.scrollInfo.itemSize) || 1
|
||||||
|
// 列表结束索引
|
||||||
|
const endIndex = Math.ceil((scrollTop + this.scrollInfo.containerHeight) / this.scrollInfo.itemSize)
|
||||||
|
find.scrollStartIndex = startIndex
|
||||||
|
find.scrollEndIndex = endIndex
|
||||||
|
// 列表距离顶部距离
|
||||||
|
find.startOffset = scrollTop - (scrollTop % this.scrollInfo.itemSize)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
@@ -1548,7 +1570,7 @@ export default {
|
|||||||
|
|
||||||
// 从localStorage中获取数据
|
// 从localStorage中获取数据
|
||||||
const trackingSubscribers = ref([])
|
const trackingSubscribers = ref([])
|
||||||
sessionStorage.getItem(storageKey.trackingSubscribers) && (trackingSubscribers.value = JSON.parse(sessionStorage.getItem(storageKey.trackingSubscribers)).map(item => ({ ...item, show: false, showLine: false, scrollNum: 0 })))
|
sessionStorage.getItem(storageKey.trackingSubscribers) && (trackingSubscribers.value = JSON.parse(sessionStorage.getItem(storageKey.trackingSubscribers)).map(item => ({ ...item, show: false, showLine: false, scrollStartIndex: 1, scrollEndIndex: 6, startOffset: 0, listHeight: 0 })))
|
||||||
/* const test = ['gary6411', 'test6431', 'test6430', 'test6422']
|
/* const test = ['gary6411', 'test6431', 'test6430', 'test6422']
|
||||||
test.forEach(id => {
|
test.forEach(id => {
|
||||||
trackingSubscribers.value.push({ subscriberId: id, show: false, showLine: false })
|
trackingSubscribers.value.push({ subscriberId: id, show: false, showLine: false })
|
||||||
@@ -2084,14 +2106,15 @@ export default {
|
|||||||
|
|
||||||
.el-timeline {
|
.el-timeline {
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
max-height: 300px;
|
//min-height: 300px;
|
||||||
|
height: 300px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
|
||||||
&.el-timeline--hide {
|
&.el-timeline--hide {
|
||||||
}
|
}
|
||||||
|
|
||||||
.el-timeline-item {
|
.el-timeline-item {
|
||||||
padding-bottom: 4px;
|
padding-bottom: 0;
|
||||||
.el-timeline-item__tail {
|
.el-timeline-item__tail {
|
||||||
border-left: 2px dotted #cccccc;
|
border-left: 2px dotted #cccccc;
|
||||||
margin-left: 2px;
|
margin-left: 2px;
|
||||||
@@ -2108,7 +2131,7 @@ export default {
|
|||||||
}
|
}
|
||||||
.timeline__info {
|
.timeline__info {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding-bottom: 13px;
|
padding-bottom: 10px;
|
||||||
|
|
||||||
.timeline__info--circle {
|
.timeline__info--circle {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -2163,6 +2186,57 @@ export default {
|
|||||||
.item-record__btn-disabled {
|
.item-record__btn-disabled {
|
||||||
cursor: no-drop;
|
cursor: no-drop;
|
||||||
}
|
}
|
||||||
|
.scroll-view {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
overflow-y: scroll;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.scroll__item {
|
||||||
|
width: 100%;
|
||||||
|
height: 58px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.item-circle {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.circle-circle {
|
||||||
|
width: 10px;
|
||||||
|
height: 10px;
|
||||||
|
margin-left: 2px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background-color: #DE3434;
|
||||||
|
}
|
||||||
|
.circle-line {
|
||||||
|
border-left: 2px #cccccc dotted;
|
||||||
|
height: 34px;
|
||||||
|
margin-left: 6px;
|
||||||
|
margin-top: 6px;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #666666;
|
||||||
|
padding-left: 16px;
|
||||||
|
|
||||||
|
.item__value {
|
||||||
|
color: #333;
|
||||||
|
font-weight: 500;
|
||||||
|
margin-left: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.scroll-list {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user