Browse Source

位置轨迹

master
xh 5 days ago
parent
commit
57013d207b
  1. 9
      web/src/api/gas/handdetector/index.ts
  2. 9
      web/src/api/gas/tdengine/index.ts
  3. 50
      web/src/views/HandDevice/Home/components/OpenLayerMap.vue
  4. 2
      web/src/views/HandDevice/Home/components/composables/useMapWatchers.ts
  5. 24
      web/src/views/HandDevice/Home/components/composables/useTrajectoryControls.ts
  6. 3
      web/src/views/HandDevice/Home/components/constants/map.constants.ts
  7. 9
      web/src/views/HandDevice/Home/components/services/map.service.ts
  8. 93
      web/src/views/HandDevice/Home/index.vue

9
web/src/api/gas/handdetector/index.ts

@ -28,10 +28,11 @@ export interface HandDetector {
export interface HandDetectorData extends HandDetector { export interface HandDetectorData extends HandDetector {
time?: number // 时间 time?: number // 时间
value?: number // 数值 value?: number // 数值
gasStatus?: number //气体报警状态
batteryStatus?: number //电池报警状态
fenceStatus?: number //电子围栏报警状态
onlineStatus?: number //在线状态
battery?: number // 电池电量
gasStatus?: number //气体报警状态 (0:正常;1:报警)
batteryStatus?: number //电池报警状态 (0:正常;1:报警)
fenceStatus?: number //电子围栏报警状态 (0:正常;1:报警)
onlineStatus?: number //在线状态 (0:离线;1:在线)
} }
// GAS手持探测器 API // GAS手持探测器 API

9
web/src/api/gas/tdengine/index.ts

@ -26,6 +26,11 @@ export interface tdengineOriginalStruct {
ts: string | number // 更新时间 ts: string | number // 更新时间
} }
interface tdHistoricalSnStructParams {
sn: string // 设备编号
startTime?: string | number // 开始时间
endTime?: string | number // 结束时间
}
// 历史记录 // 历史记录
export const tdengineApi = { export const tdengineApi = {
// 获取历史数据 // 获取历史数据
@ -35,5 +40,9 @@ export const tdengineApi = {
// 获取原始数据 // 获取原始数据
getOriginalLogPage: async (params: any) => { getOriginalLogPage: async (params: any) => {
return await request.get({ url: `/gas/tdengine/originalLogPage`, params }) return await request.get({ url: `/gas/tdengine/originalLogPage`, params })
},
// 获取轨迹数据
getHistoricalSn: async (params: tdHistoricalSnStructParams) => {
return await request.get<tdStruct[]>({ url: `/gas/tdengine/HistoricalSn`, params })
} }
} }

50
web/src/views/HandDevice/Home/components/OpenLayerMap.vue

@ -22,7 +22,7 @@
@stop="stopTrajectory" @stop="stopTrajectory"
@speed-change="setTrajectorySpeed" @speed-change="setTrajectorySpeed"
@time-change="setTrajectoryTime" @time-change="setTrajectoryTime"
@time-range-change="setTrajectoryTimeRange"
@time-range-change="setTrajectoryTimeRangeCustom"
/> />
<div v-if="panelVisible" class="info-panel"> <div v-if="panelVisible" class="info-panel">
@ -81,6 +81,7 @@ const props = withDefaults(defineProps<MapProps>(), {
const emit = defineEmits<{ const emit = defineEmits<{
(e: 'fence-draw-complete', coordinates: [number, number][]): void (e: 'fence-draw-complete', coordinates: [number, number][]): void
(e: 'refresh-fences'): void (e: 'refresh-fences'): void
(e: 'time-range-change', range: { startTime: number; endTime: number }): void
}>() }>()
// //
const showMarkers = ref(props.showMarkers) const showMarkers = ref(props.showMarkers)
@ -127,12 +128,15 @@ const {
setupTrajectoryWatcher, setupTrajectoryWatcher,
cleanup: cleanupTrajectory cleanup: cleanupTrajectory
} = useTrajectoryControls() } = useTrajectoryControls()
//
const setTrajectoryTimeRangeCustom = (range: { startTime: number; endTime: number }) => {
setTrajectoryTimeRange(range)
emit('time-range-change', range)
}
const { setupMapEventListeners } = useMapEvents() const { setupMapEventListeners } = useMapEvents()
// //
const toggleTrajectories = () => { const toggleTrajectories = () => {
if (showTrajectoriesStatus.value && trajectoryPlayState.value.isPlaying) { if (showTrajectoriesStatus.value && trajectoryPlayState.value.isPlaying) {
cleanupTrajectory() cleanupTrajectory()
} }
@ -141,8 +145,6 @@ const toggleTrajectories = () => {
if (showTrajectoriesStatus.value) { if (showTrajectoriesStatus.value) {
setTrajectoriesVisible(showTrajectoriesStatus.value, props.markers) setTrajectoriesVisible(showTrajectoriesStatus.value, props.markers)
} }
} }
const toggleMarkers = () => { const toggleMarkers = () => {
@ -181,7 +183,7 @@ const init = () => {
// //
setMarkersVisible(showMarkers.value) setMarkersVisible(showMarkers.value)
setTrajectoriesVisible(showTrajectoriesStatus.value, props.markers)
setTrajectoriesVisible(showTrajectoriesStatus.value, [])
setFencesVisible(showFences.value) setFencesVisible(showFences.value)
// ,, marker // ,, marker
@ -199,9 +201,8 @@ const init = () => {
panelVisible.value = true panelVisible.value = true
}, },
onZoomEnd: (zoom: number) => { onZoomEnd: (zoom: number) => {
// console.log('onZoomEnd', zoom)
console.log('onZoomEnd', zoom)
services.markerService?.createMarkerLayer(props) services.markerService?.createMarkerLayer(props)
// updateMarkers(props.markers || [],props)
} }
// refreshMarkerStyles // refreshMarkerStyles
} }
@ -259,6 +260,37 @@ const fitToMarkers = () => {
services.mapService?.fitToMarkers(markerCoords) services.mapService?.fitToMarkers(markerCoords)
} }
} }
const setCenter = (coords: [number, number]) => {
console.log('setCenter', coords)
if (isMapInitialized) {
services.mapService?.setCenter(coords)
}
}
/**
* 显示轨迹
*/
const showTrajectory = (startTime: number, endTime: number, markers: MarkerData[]) => {
if (isMapInitialized) {
// if (!markers || markers.length === 0) {
// return
// }
setTrajectoryTimeRange({ startTime, endTime })
var latLng: [number, number][] = []
markers.map((marker) => [
marker.data.map((item) => {
if (item.longitude && item.latitude) {
latLng.push([item.longitude, item.latitude])
}
})
])
services.mapService?.fitToMarkers(latLng)
showTrajectoriesStatus.value = true
console.log('showTrajectory', latLng)
setTrajectoriesVisible(true, markers)
}
}
const refreshFences = () => { const refreshFences = () => {
if (isMapInitialized) { if (isMapInitialized) {
@ -290,7 +322,7 @@ onMounted(() => {
}, 100) }, 100)
}) })
defineExpose({ refreshFences, fitToMarkers })
defineExpose({ refreshFences, fitToMarkers, setCenter, showTrajectory })
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">

2
web/src/views/HandDevice/Home/components/composables/useMapWatchers.ts

@ -57,7 +57,7 @@ export const useMapWatchers = (options: WatchOptions) => {
if (showMarkers.value) { if (showMarkers.value) {
showMarkers.value = false showMarkers.value = false
} }
setTrajectoriesVisible(true, markers)
// setTrajectoriesVisible(true, markers)
} else { } else {
setTrajectoriesVisible(false) setTrajectoriesVisible(false)
// 隐藏轨迹时,显示标记 // 隐藏轨迹时,显示标记

24
web/src/views/HandDevice/Home/components/composables/useTrajectoryControls.ts

@ -23,15 +23,13 @@ export const useTrajectoryControls = () => {
* *
*/ */
const playTrajectory = () => { const playTrajectory = () => {
debugger
if (trajectoryPlayTimer.value) { if (trajectoryPlayTimer.value) {
window.clearInterval(trajectoryPlayTimer.value) window.clearInterval(trajectoryPlayTimer.value)
} }
trajectoryPlayState.value.isPlaying = true
trajectoryPlayTimer.value = window.setInterval(() => { trajectoryPlayTimer.value = window.setInterval(() => {
trajectoryPlayState.value.currentTime += 1000 * trajectoryPlayState.value.speed trajectoryPlayState.value.currentTime += 1000 * trajectoryPlayState.value.speed
trajectoryPlayState.value.isPlaying = true
}, 1000)
}, 500)
} }
/** /**
@ -40,10 +38,10 @@ export const useTrajectoryControls = () => {
const pauseTrajectory = () => { const pauseTrajectory = () => {
if (trajectoryPlayTimer.value) { if (trajectoryPlayTimer.value) {
window.clearInterval(trajectoryPlayTimer.value) window.clearInterval(trajectoryPlayTimer.value)
}
trajectoryPlayTimer.value = null trajectoryPlayTimer.value = null
trajectoryPlayState.value.isPlaying = false trajectoryPlayState.value.isPlaying = false
} }
}
/** /**
* *
@ -51,10 +49,10 @@ export const useTrajectoryControls = () => {
const stopTrajectory = () => { const stopTrajectory = () => {
if (trajectoryPlayTimer.value) { if (trajectoryPlayTimer.value) {
window.clearInterval(trajectoryPlayTimer.value) window.clearInterval(trajectoryPlayTimer.value)
}
trajectoryPlayTimer.value = null trajectoryPlayTimer.value = null
trajectoryPlayState.value.isPlaying = false trajectoryPlayState.value.isPlaying = false
} }
}
/** /**
* *
@ -63,12 +61,12 @@ export const useTrajectoryControls = () => {
trajectoryPlayState.value.speed = speed trajectoryPlayState.value.speed = speed
// 如果正在播放,重启定时器以应用新速度 // 如果正在播放,重启定时器以应用新速度
if (trajectoryPlayTimer.value) {
window.clearInterval(trajectoryPlayTimer.value)
trajectoryPlayTimer.value = window.setInterval(() => {
trajectoryPlayState.value.currentTime += 1000 * trajectoryPlayState.value.speed
}, 1000)
}
// if (trajectoryPlayTimer.value) {
// window.clearInterval(trajectoryPlayTimer.value)
// trajectoryPlayTimer.value = window.setInterval(() => {
// trajectoryPlayState.value.currentTime += 1000 * trajectoryPlayState.value.speed
// }, 1000)
// }
} }
/** /**
@ -127,8 +125,8 @@ export const useTrajectoryControls = () => {
const cleanup = () => { const cleanup = () => {
if (trajectoryPlayTimer.value) { if (trajectoryPlayTimer.value) {
window.clearInterval(trajectoryPlayTimer.value) window.clearInterval(trajectoryPlayTimer.value)
trajectoryPlayTimer.value = null
} }
trajectoryPlayTimer.value = null
} }
return { return {

3
web/src/views/HandDevice/Home/components/constants/map.constants.ts

@ -46,7 +46,8 @@ export const DEFAULT_MARKERS = []
// 地图默认配置 // 地图默认配置
export const MAP_DEFAULTS = { export const MAP_DEFAULTS = {
tileUrl: 'http://qtbj.icpcdev.site/roadmap/{z}/{x}/{y}.png',
// tileUrl: 'http://qtbj.icpcdev.site/roadmap/{z}/{x}/{y}.png',
tileUrl: 'https://webrd04.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={x}&y={y}&z={z}',
center: [116.3912757, 39.906217] as [number, number], center: [116.3912757, 39.906217] as [number, number],
zoom: 10, zoom: 10,
maxZoom: 18, maxZoom: 18,

9
web/src/views/HandDevice/Home/components/services/map.service.ts

@ -98,6 +98,15 @@ export class MapService {
}) })
} }
/** /**
*
*/
setCenter(center: number[]): void {
if (!this.map) return
center = fromLonLat(center)
this.map.getView().setCenter(center)
}
/**
* *
*/ */
getMap(): Map | null { getMap(): Map | null {

93
web/src/views/HandDevice/Home/index.vue

@ -8,6 +8,7 @@
:showTrajectories="true" :showTrajectories="true"
:markers="filterMarkers" :markers="filterMarkers"
:fences="fences" :fences="fences"
@time-range-change="timeRangeChange"
/> />
<TopPanel <TopPanel
v-model="search" v-model="search"
@ -18,32 +19,44 @@
<div class="markerList"> <div class="markerList">
<el-scrollbar height="100%"> <el-scrollbar height="100%">
<!--marker列表 --> <!--marker列表 -->
<el-collapse accordion @change="collapseChange">
<el-collapse-item :name="item.name" v-for="item in filterMarkers" :key="item.id">
<el-collapse accordion>
<el-collapse-item :name="item.sn" v-for="item in filterMarkers" :key="item.id">
<template #title> <template #title>
<div class="flex flex-row w-100%"> <div class="flex flex-row w-100%">
<div class="flex-1 text-left font-500"> <div class="flex-1 text-left font-500">
{{ item.name }} {{ item.name }}
</div> </div>
<div class="text-gray-500 font-400 text-12px"> <div class="text-gray-500 font-400 text-12px">
{{ item.onlineStatus === 1 ? '在线' : '线' }}
{{ item.onlineStatus === 1 ? '在线' : '线' }}
</div> </div>
</div> </div>
</template> </template>
<div class="markerList-content"> <div class="markerList-content">
<div> <span>SN</span>{{ item.sn }}</div> <div> <span>SN</span>{{ item.sn }}</div>
<div> <span>类型</span>{{ item.gasChemical }}</div> <div> <span>类型</span>{{ item.gasChemical }}</div>
<hr />
<div> <span>气体状态</span>{{ item.gasStatus }}</div> <div> <span>气体状态</span>{{ item.gasStatus }}</div>
<div> <span>电池告警状态</span>{{ item.batteryStatus }}</div> <div> <span>电池告警状态</span>{{ item.batteryStatus }}</div>
<div> <span>电池</span>{{ item.battery }}</div>
<div> <span>围栏状态</span>{{ item.fenceStatus }}</div> <div> <span>围栏状态</span>{{ item.fenceStatus }}</div>
<!-- <div> <span>在线状态</span>{{ item.onlineStatus }}</div> -->
<div> <span>在线状态</span>{{ item.onlineStatus }}</div>
<div> <span>启用状态</span>{{ item.enableStatus === 1 ? '启用' : '备用' }}</div>
<hr />
<div> <span>电量</span>{{ item.battery }}</div>
<div> <span>数值</span>{{ item.value }} {{ item.unit }}</div> <div> <span>数值</span>{{ item.value }} {{ item.unit }}</div>
<div> <span>时间</span>{{ dayjs(item.time).format('YYYY-MM-DD HH:mm:ss') }}</div> <div> <span>时间</span>{{ dayjs(item.time).format('YYYY-MM-DD HH:mm:ss') }}</div>
<!-- <div>
<el-button type="primary" size="small">定位</el-button>
<el-button type="primary" size="small">轨迹</el-button>
</div> -->
<div>
<el-button
type="primary"
size="small"
v-if="item.latitude && item.longitude"
@click="setCenter(item)"
>定位</el-button
>
<el-button type="primary" size="small" @click="onClickTrajectory(item)"
>轨迹</el-button
>
</div>
<!-- {{ item }} --> <!-- {{ item }} -->
</div> </div>
@ -67,7 +80,7 @@ import { tdengineApi, tdStruct, tdQuery } from '@/api/gas/tdengine/index'
import { MarkerData, FenceData } from './components/types/map.types' import { MarkerData, FenceData } from './components/types/map.types'
import { useHandDetectorStore } from '@/store/modules/handDetector' import { useHandDetectorStore } from '@/store/modules/handDetector'
import { ElMessage } from 'element-plus'
import dayjs from 'dayjs' import dayjs from 'dayjs'
const handDetectorStore = useHandDetectorStore() // store const handDetectorStore = useHandDetectorStore() // store
@ -78,9 +91,6 @@ const fences = ref<FenceData[]>([])
const mapRef = ref<typeof OpenLayerMap>() const mapRef = ref<typeof OpenLayerMap>()
const search = ref('') const search = ref('')
function collapseChange(name: string) {
console.log('collapseChange', name)
}
watch( watch(
() => search.value, () => search.value,
(newSearch, oldSearch) => { (newSearch, oldSearch) => {
@ -90,6 +100,7 @@ watch(
}, },
{ immediate: false } { immediate: false }
) )
// //
const handDetectorCount = computed(() => markers.value.length) const handDetectorCount = computed(() => markers.value.length)
const onlineCount = computed(() => markers.value.filter((item) => item.onlineStatus === 1).length) const onlineCount = computed(() => markers.value.filter((item) => item.onlineStatus === 1).length)
@ -128,7 +139,6 @@ const getMarkers = async () => {
} }
}) })
markers.value = res2 as unknown as any[] markers.value = res2 as unknown as any[]
getMarkersHistory()
}) })
} }
const getFences = async () => { const getFences = async () => {
@ -145,18 +155,44 @@ const getFences = async () => {
fences.value = fencesData as unknown as FenceData[] fences.value = fencesData as unknown as FenceData[]
}) })
} }
// const markersHistory = ref<tdStruct[]>([])
const getMarkersHistory = async () => {
//
function setCenter(item: MarkerData) {
console.log('setCenter', item)
if (item.longitude && item.latitude) {
mapRef.value?.setCenter([item.longitude || 0, item.latitude || 0])
}
}
let currentMarker: MarkerData | null = null
var trajectoryTimeRange = ref([dayjs().subtract(1, 'hour').valueOf(), dayjs().valueOf()])
//
function timeRangeChange(range: { startTime: number; endTime: number }) {
console.log('timeRangeChange', range)
trajectoryTimeRange.value = [range.startTime,range.endTime]
if (currentMarker) {
showTrajectory(currentMarker)
}
}
//
async function showTrajectory(item: MarkerData) {
console.log('showTrajectory', item)
try { try {
const data = await tdengineApi.getPage({
pageNo: 1,
pageSize: 100,
sn: '867989072729904'
if (!item.sn) {
ElMessage.error('手持设备无效')
return
}
currentMarker = item
const data = await tdengineApi.getHistoricalSn({
sn: item.sn,
startTime: dayjs(trajectoryTimeRange.value[0]).format('YYYY-MM-DD HH:mm:ss'),
endTime: dayjs(trajectoryTimeRange.value[1]).format('YYYY-MM-DD HH:mm:ss')
// sn: '867989072729904'
}) })
// markersHistory.value = data.list
markers.value.map((item) => {
if (item.sn === '867989072729904') {
item.data = data.list.map((j) => {
item.data = data
.filter((i) => i.longitude && i.latitude)
.map((j) => {
return { return {
...j, ...j,
lng: j.longitude, lng: j.longitude,
@ -165,11 +201,16 @@ const getMarkersHistory = async () => {
timeStr: dayjs(j.ts).format('YYYY-MM-DD HH:mm:ss') timeStr: dayjs(j.ts).format('YYYY-MM-DD HH:mm:ss')
} }
}) })
}
})
mapRef.value?.showTrajectory(trajectoryTimeRange.value[0], trajectoryTimeRange.value[1], [item])
} finally { } finally {
} }
} }
//
function onClickTrajectory(item: MarkerData) {
console.log('onClickTrajectory', item)
trajectoryTimeRange.value = [dayjs().subtract(1, 'hour').valueOf(), dayjs().valueOf()]
showTrajectory(item)
}
onMounted(() => { onMounted(() => {
getMarkers() getMarkers()

Loading…
Cancel
Save