CN-1577 fix: Subscriber实体详情地图内容更换为新版

This commit is contained in:
刘洪洪
2024-03-12 18:39:49 +08:00
parent bfcae5b3cc
commit 39ca0457b3
2 changed files with 381 additions and 8 deletions

View File

@@ -1,6 +1,9 @@
.subscriber-map {
height: 100%;
svg {
fill: #fff;
}
.subscriber-map-header {
height: 34px;
padding-bottom: 10px;
@@ -32,6 +35,202 @@
.panel-chart__no-data {
height: calc(100% - 46px);
}
.analysis-statistics {
width: 310px;
overflow-y: auto;
//padding-right: 5px;
.analysis-statistics__subscribers {
padding-left: 20px;
.analysis-statistics__subscriber {
margin-bottom: 10px;
&:last-of-type {
margin-bottom: 0;
}
background-color: #F7F7F7;
border-left: 1px solid rgb(226,229,236);
border-radius: 2px;
.subscriber__body {
padding: 0 12px;
margin-top: -10px;
.body__item {
display: flex;
.item__label {
padding-right: 10px;
text-align: right;
width: 60px;
font-size: 12px;
color: #353636;
}
.item__value {
font-size: 12px;
font-weight: bold;
color: #233447;
}
}
.body-item-record {
margin-top: 10px;
.item-record__header {
font-family: Helvetica;
font-size: 16px;
color: #353636;
font-weight: 400;
height: 38px;
line-height: 38px;
}
.item-record__info {
}
.item-record__timeline {
margin-left: 6px;
.el-timeline {
padding-left: 0;
//min-height: 300px;
height: 360px;
overflow: auto;
&.el-timeline--hide {
}
.el-timeline-item {
padding-bottom: 0;
.el-timeline-item__tail {
border-left: 2px dotted #cccccc;
margin-left: 2px;
}
.el-timeline-item__node--normal {
background-image: radial-gradient(#DE3434 20%, transparent);
outline: #F7F7F7 solid 6px;
margin-left: 2px;
}
}
.el-timeline-item:last-child {
padding-bottom: 0;
}
}
.timeline__info {
display: flex;
padding-bottom: 10px;
.timeline__info--circle {
display: flex;
flex-direction: column;
.info__circle {
width: 17px;
height: 17px;
margin-left: -2px;
border-radius: 50%;
background-image: radial-gradient(#DE3434 20%, transparent);
outline: rgba(222,52,52,0.30) solid 4px;
margin-top: 2px;
}
.info__line {
border-left: 2px #cccccc dotted;
height: 34px;
margin-left: 6px;
transition: all 0.2s;
}
}
.timeline__info--item {
padding-left: 13px;
display: flex;
flex-direction: column;
font-size: 12px;
color: #666666;
.info--item__value {
color: #333;
font-weight: 500;
margin-left: 4px;
}
}
}
.timeline__item {
display: flex;
flex-direction: column;
font-size: 12px;
color: #666666;
.item__value {
color: #333;
font-weight: 500;
margin-left: 4px;
}
}
.item-record__btn, .item-record__btn-disabled {
padding-right: 6px;
cursor: pointer;
text-align: center;
}
.item-record__btn-disabled {
cursor: no-drop;
}
.scroll-view {
width: 100%;
height: 384px;
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;
}
}
}
}
}
}
}
}
}
.subscriber-map-point-tooltip {

View File

@@ -13,9 +13,55 @@
</div>
<div class="subscriber-map-body">
<chart-no-data v-if="isNoData" test-id="noData"></chart-no-data>
<chart-error v-if="showError" :content="errorMsg" />
<div id="subscriberMap" class="subscriber-map"></div>
<chart-no-data v-if="isNoData" test-id="noData" style="width: calc(100% - 312px)"></chart-no-data>
<chart-error v-if="showError" :content="errorMsg" style="width: calc(100% - 312px)" />
<div id="subscriberMap" class="subscriber-map" style="width: calc(100% - 310px)"></div>
<!-- 右侧数据栏-trace -->
<div class="analysis-statistics" id="subscribersBlock" style="position: absolute;right: 0;top: 0;">
<div class="analysis-statistics__subscribers">
<div class="analysis-statistics__subscriber" style="height: 664px;">
<chart-no-data v-if="trackingNoData" test-id="trackingNoData" style="width: calc(100% - 30px);height: 100%;"></chart-no-data>
<chart-error v-if="showTrackingError" :content="trackingErrorMsg" style="width: calc(100% - 30px)" />
<div v-if="!trackingNoData && !showTrackingError" class="subscriber__body">
<div class="body-item-record">
<div class="item-record__header">{{ $t('location.trackRecord') }}</div>
<div class="item-record__info">
<div class="circle"></div>
</div>
<div class="item-record__timeline">
<div class="scroll-view" @scroll="onScroll" :id="trackingSubscriber.subscriberId">
<!-- 虚拟列表 -->
<div class="virtual-scroller" :style="`height: ${trackingSubscriber.listHeight}px`"></div>
<div class="scroll-list" :style="`transform: translateY(${trackingSubscriber.startOffset}px)`">
<div class="scroll__item"
v-for="(record, index) in trackingSubscriber.trackRecords.slice(trackingSubscriber.scrollStartIndex, trackingSubscriber.scrollEndIndex)"
:key="index">
<div class="item-circle">
<div class="circle-circle"></div>
<div class="circle-line"></div>
</div>
<div class="item-content">
<div>
<span>{{$t('overall.location')}}: </span><span class="item__value">{{record.subscriberLongitude}},&nbsp;{{record.subscriberLatitude}}</span>
</div>
<div>
<span>{{ $t('location.timeOfArrival') }}: </span><span class="item__value">{{dateFormatByAppearance(Number(record.time))}}</span>
</div>
<div>
<span>{{ $t('location.residenceTime') }}: </span><span class="item__value">{{record.stayTime}}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 地图point悬浮框 -->
@@ -46,7 +92,9 @@ import { api } from '@/utils/api'
import 'maplibre-gl/dist/maplibre-gl.css'
import _ from 'lodash'
import { ref, shallowRef } from 'vue'
import { getNowTime, getSecond } from '@/utils/date-util'
import { getNowTime, getSecond, dateFormatByAppearance } from '@/utils/date-util'
import unitConvert from '@/utils/unit-convert'
import { unitTypes } from '@/utils/constants'
export default {
name: 'EntityDetailMap',
@@ -57,12 +105,14 @@ export default {
},
mounted () {
this.initMap()
this.queryTraceTracking()
},
unmounted () {
this.myChart && this.myChart.remove()
this.myChart && this.myChart?.remove?.()
this.myChart = null
},
methods: {
dateFormatByAppearance,
async initMap () {
const _this = this
const map = new maplibregl.Map({
@@ -142,7 +192,7 @@ export default {
})
},
queryData () {
/*return new Promise((resolve, reject) => {
/* return new Promise((resolve, reject) => {
resolve({
status: 200,
data: {
@@ -182,7 +232,7 @@ export default {
}
}
})
})*/
}) */
const params = {
resource: this.entity.entityName,
startTime: getSecond(this.timeFilter.startTime),
@@ -305,6 +355,104 @@ export default {
}).finally(() => {
this.toggleLoading(false)
})
},
async queryTraceTracking () {
const params = {
...this.timeFilter,
subscriberIds: `'${this.entity.entityName}'`,
level: this.mapLevel
}
this.trackingSubscriber.subscriberId = this.entity.entityName
try {
const response = await axios.get(api.location.tracking, { params })
if (response.data.data.result) {
const find = response.data.data.result.find(item => item.subscriberId === this.trackingSubscriber.subscriberId)
if (find) {
this.trackingSubscriber.trackRecords = find.trackRecords
} else {
this.trackingSubscriber.trackRecords = []
}
this.trackingSubscriber.show = false
} else {
this.trackingSubscriber.trackRecords = []
}
// 计算停留时间
if (this.trackingSubscriber.trackRecords.length > 0) {
this.trackingNoData = false
this.showTrackingError = false
const trackRecords = this.trackingSubscriber.trackRecords
// 初始化时间线可视范围角标
if (trackRecords.length < 7) {
this.trackingSubscriber.scrollStartIndex = 0
this.trackingSubscriber.scrollEndIndex = trackRecords.length
} else {
this.trackingSubscriber.scrollStartIndex = 0
this.trackingSubscriber.scrollEndIndex = 7
}
if (trackRecords && trackRecords.length > 0) {
for (let i = 0; i < trackRecords.length; i++) {
if (i > 0) {
if ((trackRecords[i - 1].subscriberLongitude === trackRecords[i].subscriberLongitude) && (trackRecords[i - 1].subscriberLatitude === trackRecords[i].subscriberLatitude)) {
// 如果连续两条地址重复,则将时间累加,并将上一条删除,键值-1继续循环
if (i > 1 && trackRecords[i - 2]) {
const stayTime = unitConvert(trackRecords[i - 2].time - trackRecords[i].time, unitTypes.time, 's')
if (Number(stayTime[0]) === Number(Number(stayTime[0]).toFixed(0))) {
stayTime[0] = Number(stayTime[0]).toFixed(0)
}
trackRecords[i].stayTime = stayTime.join(' ')
} else {
// 数据只有2条或者第1条和第2条地点重复删除1合并时间
const stayTime = unitConvert(trackRecords[i - 1].time - trackRecords[i].time, unitTypes.time, 's')
if (Number(stayTime[0]) === Number(Number(stayTime[0]).toFixed(0))) {
stayTime[0] = Number(stayTime[0]).toFixed(0)
}
trackRecords[i].stayTime = stayTime.join(' ')
}
trackRecords.splice(i - 1, 1)
i = i - 1
} else {
const stayTime = unitConvert(trackRecords[i - 1].time - trackRecords[i].time, unitTypes.time, 's')
if (Number(stayTime[0]) === Number(Number(stayTime[0]).toFixed(0))) {
stayTime[0] = Number(stayTime[0]).toFixed(0)
}
trackRecords[i].stayTime = stayTime.join(' ')
}
if (i === trackRecords.length - 1) {
// 初始化数据时,重置偏移量和列表高度
this.trackingSubscriber.startOffset = 0
this.trackingSubscriber.listHeight = i * this.scrollInfo.itemSize
}
} else {
trackRecords[i].stayTime = '-'
}
}
}
this.trackingSubscriber.trackRecords = trackRecords
} else {
this.trackingNoData = true
}
} catch (e) {
this.showTrackingError = true
this.trackingErrorMsg = this.errorMsgHandler(e)
console.error(e)
} finally {
// this.loading.trackingMapLoading = false
}
},
onScroll (e) {
// 当前滚动位置
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)
this.trackingSubscriber.scrollStartIndex = startIndex
this.trackingSubscriber.scrollEndIndex = endIndex
// 列表距离顶部距离
this.trackingSubscriber.startOffset = scrollTop - (scrollTop % this.scrollInfo.itemSize)
}
},
setup () {
@@ -319,6 +467,25 @@ export default {
showTooltip: false
})
const myChart = shallowRef({})
const mapLevel = ref('2')
const trackingSubscriber = ref({
subscriberId: '',
show: false,
showLine: false,
scrollStartIndex: 0,
scrollEndIndex: 7,
startOffset: 0,
listHeight: 0,
trackRecords: []
})
const trackingSubscriberList = ref([])
const scrollInfo = ref({
itemSize: 50,
containerHeight: 360
})
const trackingNoData = ref(true)
const showTrackingError = ref(false)
const trackingErrorMsg = ref('')
return {
timeFilter,
@@ -327,7 +494,14 @@ export default {
myChart,
maxZoom: 13,
minZoom: 1,
center: [116.38, 39.9]
center: [116.38, 39.9],
mapLevel,
trackingSubscriber,
trackingSubscriberList,
scrollInfo,
trackingNoData,
showTrackingError,
trackingErrorMsg
}
}
}