Browse Source

搜索缩放等

master
xh 6 days ago
parent
commit
1ff99ae4be
  1. 57
      web/src/views/HandDevice/Home/components/OpenLayerMap.vue
  2. 149
      web/src/views/HandDevice/Home/components/TopPanel.vue
  3. 54
      web/src/views/HandDevice/Home/components/composables/useMapEvents.ts
  4. 32
      web/src/views/HandDevice/Home/components/composables/useMapServices.ts
  5. 32
      web/src/views/HandDevice/Home/components/composables/useMapWatchers.ts
  6. 29
      web/src/views/HandDevice/Home/components/services/map.service.ts
  7. 9
      web/src/views/HandDevice/Home/components/services/marker.service.ts
  8. 10
      web/src/views/HandDevice/Home/components/types/map.types.ts
  9. 201
      web/src/views/HandDevice/Home/index.vue

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

@ -44,7 +44,6 @@
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, watch } from 'vue'
import { ElMessage } from 'element-plus'
//
@ -59,7 +58,6 @@ import { useMapEvents } from './composables/useMapEvents'
import { useTrajectoryControls } from './composables/useTrajectoryControls'
import { useMapWatchers } from './composables/useMapWatchers'
import { MapService } from './services/map.service'
//
import TrajectoryControls from './TrajectoryControls.vue'
import MapControls from './MapControls.vue'
@ -108,7 +106,7 @@ enableStatus 1启用 0未启用
const {
services,
initializeMapAndLayers,
initMap,
setMarkersVisible,
setTrajectoriesVisible,
setFencesVisible,
@ -160,26 +158,19 @@ const toggleDrawFences = () => {
}
}
let mapService: MapService | null = null
let isMapInitialized = false
/**
* 初始化地图
*/
const initMap = () => {
const init = () => {
if (!mapContainerRef.value) return
//
mapService = new MapService(mapContainerRef.value, props)
try {
// const mapInstance = mapService.initMap(mapContainerRef.value, props)
//
const { map, popupOverlay } = initializeMapAndLayers(mapService, props)
initMap(mapContainerRef.value, props)
if (!services.mapService?.map) {
throw new Error('Map instance is null')
}
//
setMarkersVisible(showMarkers.value)
@ -188,14 +179,14 @@ const initMap = () => {
// ,, marker
setupMapEventListeners(
map,
popupOverlay,
services.trajectoryService as any,
services.mapService.map,
services.mapService.popupOverlay,
services.trajectoryService,
services.popupService,
{
isDrawing: () => !!services.fenceDrawService?.isCurrentlyDrawing?.(),
onMarkerClick: (marker: MarkerData) => {
console.log('marker clicked', marker);
console.log('marker clicked', marker)
selectedMarker.value = marker
panelVisible.value = true
@ -204,7 +195,7 @@ const initMap = () => {
// console.log('onZoomEnd', zoom)
services.markerService?.createMarkerLayer(props)
// updateMarkers(props.markers || [],props)
},
}
// refreshMarkerStyles
}
)
@ -221,7 +212,7 @@ const initMap = () => {
setTrajectoriesVisible,
setFencesVisible,
toggleFenceDrawing,
updateMarkers,
markers: props.markers || []
})
@ -230,7 +221,7 @@ const initMap = () => {
//
isMapInitialized = true
console.log('地图初始化成功', { map, services: services })
console.log('地图初始化成功')
} catch (error) {
console.error('地图初始化失败:', error)
}
@ -251,6 +242,16 @@ const handleFenceDrawComplete = (coordinates: [number, number][]) => {
//
showDrawFences.value = false
}
//
const fitToMarkers = () => {
if (isMapInitialized && props.markers && props.markers.length > 0) {
const markerCoords = props.markers.map((marker) => [
marker.longitude || 0,
marker.latitude || 0
])
services.mapService?.fitToMarkers(markerCoords)
}
}
const refreshFences = () => {
if (isMapInitialized) {
@ -260,9 +261,10 @@ const refreshFences = () => {
// markers props
watch(
() => props.markers,
(newMarkers) => {
if (newMarkers && newMarkers.length > 0 && isMapInitialized) {
(newMarkers, oldMarkers) => {
updateMarkers(newMarkers, props)
if (newMarkers.length !== oldMarkers.length) {
fitToMarkers()
}
},
{ deep: true, immediate: false }
@ -270,21 +272,18 @@ watch(
watch(
() => props.fences,
(newFences) => {
if (newFences && newFences.length > 0 && isMapInitialized) {
refreshFences()
}
},
{ deep: true, immediate: false }
)
onMounted(() => {
setTimeout(() => {
initMap()
init()
}, 100)
})
defineExpose({ refreshFences })
defineExpose({ refreshFences,fitToMarkers })
</script>
<style scoped lang="scss">

149
web/src/views/HandDevice/Home/components/TopPanel.vue

@ -0,0 +1,149 @@
<template>
<div class="top-panel" v-show="!appStore.mobile">
<div class="top-panel__left">
<div class="search-group">
<el-input v-model="search" class="search-input" placeholder="请输入关键词" />
</div>
</div>
<div class="top-panel__center">
<div class="data_item">
<span class="data_item__title">手持设备</span>
<span class="data_item__value">{{ handDetectorCount }}</span>
<span class="data_item__unit"></span>
</div>
<div class="data_item">
<span class="data_item__title">在线数量</span>
<span class="data_item__value">{{ onlineCount }}</span>
<span class="data_item__unit"></span>
</div>
</div>
<div class="top-panel__right">
<span class="legend-title">报警图例</span>
<div class="normal-legend">正常状态</div>
<div class="alarm1-legend">围栏报警</div>
<div class="alarm2-legend">气体报警</div>
</div>
</div>
</template>
<script lang="ts" setup>
// import { ref, computed } from 'vue'
import { useAppStore } from '@/store/modules/app'
const appStore = useAppStore()
var props = defineProps({
handDetectorCount: {
type: Number,
default: 0
},
onlineCount: {
type: Number,
default: 0
}
})
var search = defineModel({
type: String,
default: ''
})
</script>
<style scoped lang="scss">
/* 顶部面板样式 */
.top-panel {
position: absolute;
top: 0px;
left: 50px;
right: 10px;
z-index: 999;
display: flex;
align-items: center;
justify-content: space-between;
// gap: 12px;
padding: 6px 0px;
flex-wrap: wrap;
box-sizing: border-box;
.top-panel__left {
background: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 10px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
height: 100%;
margin-right: 12px;
padding: 10px;
}
.top-panel__center {
flex: 1 1 auto;
display: flex;
align-items: center;
.data_item {
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
width: 200px;
background: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 8px;
padding: 12px 12px;
margin-right: 12px;
.data_item__title {
font-size: 14px;
color: #3f3f3f;
vertical-align: middle;
}
.data_item__value {
display: inline-block;
padding: 0 10px;
font-size: 18px;
font-weight: 600;
color: #3399ff;
vertical-align: middle;
}
.data_item__unit {
font-size: 14px;
color: #3f3f3f;
vertical-align: middle;
}
}
}
.top-panel__right {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(0, 0, 0, 0.06);
padding: 12px 12px;
border-radius: 8px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
white-space: nowrap;
height: 100%;
.legend-title {
color: #606266;
font-size: 14px;
}
.normal-legend,
.alarm1-legend,
.alarm2-legend {
padding: 4px 8px;
border-radius: 999px;
color: #fff;
font-size: 12px;
line-height: 1;
}
.normal-legend {
background: #67c23a;
}
.alarm1-legend {
background: #e6a23c;
}
.alarm2-legend {
background: #f56c6c;
}
}
}
</style>

54
web/src/views/HandDevice/Home/components/composables/useMapEvents.ts

@ -3,25 +3,28 @@
*/
import type { Map } from 'ol'
import type Overlay from 'ol/Overlay'
import type FeatureLike from 'ol/Feature'
import { MarkerData, FenceData } from '../types/map.types'
import dayjs from 'dayjs'
import { fromLonLat } from 'ol/proj'
import { TrajectoryService } from '../services/trajectory.service'
import { PopupService } from '../services/popup.service'
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
interface PopupContentGenerator {
handleTrajectoryPoint: (feature: any) => string
handleTrajectoryLine: (feature: any) => string
handleFence: (feature: any) => string
handleMarker: (feature: any) => string
handleTrajectoryPoint: (feature: FeatureLike) => string
handleTrajectoryLine: (feature: FeatureLike) => string
handleFence: (feature: FeatureLike) => string
handleMarker: (feature: FeatureLike) => string
}
export const useMapEvents = () => {
// 创建弹窗内容生成器
const createPopupContentGenerator = (
trajectoryService: any,
popupService: any
trajectoryService: TrajectoryService,
popupService: PopupService
): PopupContentGenerator => ({
handleTrajectoryPoint: (feature: any): string => {
handleTrajectoryPoint: (feature: FeatureLike): string => {
const timeText = feature.get('timeText') || ''
const trajectoryId = feature.get('trajectoryId') || ''
const timestamp = feature.get('timestamp')
@ -40,7 +43,7 @@ export const useMapEvents = () => {
`
},
handleTrajectoryLine: (feature: any): string => {
handleTrajectoryLine: (feature: FeatureLike): string => {
const deviceId = feature.get('deviceId') || ''
const deviceName =
trajectoryService?.getTrajectoryData().find((t) => t.deviceId === deviceId)?.name ||
@ -53,8 +56,8 @@ export const useMapEvents = () => {
`
},
handleFence: (feature: any): string => {
const fenceData = feature.get('fenceData')
handleFence: (feature: FeatureLike): string => {
const fenceData: FenceData = feature.get('fenceData')
const statusText = getDictLabel(DICT_TYPE.HAND_DETECTOR_FENCE_STATUS, fenceData.status)
const typeText = getDictLabel(DICT_TYPE.HAND_DETECTOR_FENCE_TYPE, fenceData.type)
@ -70,7 +73,7 @@ export const useMapEvents = () => {
`
},
handleMarker: (feature: any): string => {
handleMarker: (feature: FeatureLike): string => {
return popupService?.handlePopupContent(feature) || ''
}
})
@ -85,12 +88,16 @@ export const useMapEvents = () => {
popupService: PopupService | null,
opts?: {
isDrawing?: () => boolean
onMarkerClick?: (markerData: any) => void
onMarkerClick?: (markerData: MarkerData) => void
onZoomEnd?: (zoom: number) => void
// markerLayer?: any
// refreshMarkerStyles?: () => void
}
) => {
if (!trajectoryService || !popupService) {
return
}
const popupGenerator = createPopupContentGenerator(trajectoryService, popupService)
// 鼠标悬停事件
@ -101,7 +108,7 @@ export const useMapEvents = () => {
return
}
//
const feature = map.forEachFeatureAtPixel(event.pixel, (feature: any) => feature)
const feature = map.forEachFeatureAtPixel(event.pixel, (feature: FeatureLike) => feature)
if (feature) {
map.getTargetElement().style.cursor = 'pointer'
@ -118,7 +125,7 @@ export const useMapEvents = () => {
if (opts?.isDrawing && opts.isDrawing()) {
return
}
const feature = map.forEachFeatureAtPixel(event.pixel, (feature: any) => feature)
const feature = map.forEachFeatureAtPixel(event.pixel, (feature: FeatureLike) => feature)
if (feature) {
handleFeatureClick(feature, map, opts)
}
@ -142,7 +149,6 @@ export const useMapEvents = () => {
map.on('click', handleClick)
map.on('moveend', handleMoveEnd)
return {
destroy: () => {
map.un('pointermove', handlePointerMove)
@ -157,7 +163,7 @@ export const useMapEvents = () => {
*/
const showPopup = (
event: any,
feature: any,
feature: FeatureLike,
popupOverlay: Overlay | null,
popupGenerator: PopupContentGenerator
) => {
@ -202,8 +208,8 @@ export const useMapEvents = () => {
*
*/
const handleFeatureClick = (
feature: any,
map: any,
feature: FeatureLike,
map: Map,
opts?: { onMarkerClick?: (markerData: any) => void }
) => {
const featureType = feature.get('type')
@ -226,8 +232,8 @@ export const useMapEvents = () => {
*
*/
const handleMarkerClick = (
feature: any,
map: any,
feature: FeatureLike,
map: Map,
opts?: { onMarkerClick?: (markerData: any) => void }
) => {
const markerData = feature.get('markerData')
@ -245,7 +251,7 @@ export const useMapEvents = () => {
}
} else if (markerData) {
// 处理非聚合的单个标记点击
animateToCoordinate(markerData.coordinates, map, 15)
animateToCoordinate(markerData.coordinates, map, 17)
opts?.onMarkerClick?.(markerData)
}
}
@ -253,9 +259,9 @@ export const useMapEvents = () => {
/**
*
*/
const handleClusterClick = (features: any[], map: any) => {
const handleClusterClick = (features: FeatureLike[], map: Map) => {
// 计算聚合标记的中心点
const coordinates = features.map((f: any) => f.get('markerData').coordinates)
const coordinates = features.map((f: FeatureLike) => f.get('markerData').coordinates)
const centerLon =
coordinates.reduce((sum: number, coord: any) => sum + coord[0], 0) / coordinates.length
const centerLat =
@ -267,7 +273,7 @@ export const useMapEvents = () => {
/**
*
*/
const animateToCoordinate = (coordinates: [number, number], map: any, zoom: number) => {
const animateToCoordinate = (coordinates: [number, number], map: Map, zoom: number) => {
const view = map.getView()
view.animate({

32
web/src/views/HandDevice/Home/components/composables/useMapServices.ts

@ -4,7 +4,7 @@
import type { Map } from 'ol'
import { ref, onUnmounted, reactive } from 'vue'
import type { MapProps, MapInstance } from '../types/map.types'
import type { MapProps } from '../types/map.types'
import { MapService } from '../services/map.service'
import { MarkerService } from '../services/marker.service'
import { AnimationService } from '../services/animation.service'
@ -25,7 +25,7 @@ interface ServiceInstances {
export const useMapServices = () => {
// 服务实例状态
const services = reactive<ServiceInstances>({
const services: ServiceInstances = {
mapService: null,
markerService: null,
animationService: null,
@ -33,27 +33,26 @@ export const useMapServices = () => {
trajectoryService: null,
fenceService: null,
fenceDrawService: null
})
}
/**
*
*/
const initializeMapAndLayers = (mapInstance: MapService, props: MapProps) => {
const initMap = (mapContainerRef: HTMLElement, props: MapProps) => {
// 初始化地图
const map = mapInstance.map
const popupOverlay = mapInstance.popupOverlay
if (!map) {
const mapService = new MapService(mapContainerRef, props)
if (!mapService.map) {
throw new Error('Map instance is null')
}
// 重新初始化服务,确保markerService有地图实例
services.mapService = mapInstance
services.markerService = new MarkerService(map)
services.animationService = new AnimationService(map)
services.mapService = mapService
services.markerService = new MarkerService(mapService.map)
services.animationService = new AnimationService(mapService.map)
services.popupService = new PopupService()
services.trajectoryService = new TrajectoryService(map)
services.fenceService = new FenceService(map)
services.fenceDrawService = new FenceDrawService(map)
services.trajectoryService = new TrajectoryService(mapService.map)
services.fenceService = new FenceService(mapService.map)
services.fenceDrawService = new FenceDrawService(mapService.map)
// 创建marker图层
services.markerService.createMarkerLayer(props)
@ -65,11 +64,6 @@ export const useMapServices = () => {
services.fenceService.createFenceLayer(props.fences || [])
// 初始化围栏绘制服务
services.fenceDrawService.createDrawLayer()
return {
map,
popupOverlay
}
}
/**
@ -208,7 +202,7 @@ export const useMapServices = () => {
// 方法
initializeMapAndLayers,
initMap,
setMarkersVisible,
setTrajectoriesVisible,
setFencesVisible,

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

@ -15,7 +15,6 @@ interface WatchOptions {
isDrawing: boolean,
onComplete?: (coordinates: [number, number][]) => void
) => void
updateMarkers: (markers: any[]) => void
markers: any[]
}
@ -29,7 +28,7 @@ export const useMapWatchers = (options: WatchOptions) => {
setTrajectoriesVisible,
setFencesVisible,
toggleFenceDrawing,
updateMarkers,
markers
} = options
@ -93,18 +92,18 @@ export const useMapWatchers = (options: WatchOptions) => {
/**
*
*/
const setupMarkersDataWatcher = () => {
return watch(
markers,
(newMarkers) => {
if (newMarkers && newMarkers.length > 0) {
console.log('Markers data changed, updating markers:', newMarkers.length)
updateMarkers(newMarkers)
}
},
{ deep: true, immediate: false }
)
}
// const setupMarkersDataWatcher = () => {
// return watch(
// markers,
// (newMarkers = []) => {
// // if (newMarkers && newMarkers.length > 0) {
// console.log('Markers data changed, updating markers:', newMarkers.length)
// updateMarkers(newMarkers)
// // }
// },
// { deep: true, immediate: false }
// )
// }
/**
*
@ -114,8 +113,7 @@ export const useMapWatchers = (options: WatchOptions) => {
setupMarkersWatcher(),
setupTrajectoriesWatcher(),
setupFencesWatcher(),
setupDrawFencesWatcher(),
setupMarkersDataWatcher()
setupDrawFencesWatcher()
]
// 返回清理函数
@ -133,7 +131,7 @@ export const useMapWatchers = (options: WatchOptions) => {
setupTrajectoriesWatcher,
setupFencesWatcher,
setupDrawFencesWatcher,
setupMarkersDataWatcher,
setupAllWatchers
}
}

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

@ -2,11 +2,14 @@
*
*/
import { Map, View } from 'ol'
import { Tile as TileLayer } from 'ol/layer'
import { OSM, XYZ } from 'ol/source'
import { fromLonLat } from 'ol/proj'
import { fromLonLat,transformExtent } from 'ol/proj'
import { boundingExtent } from 'ol/extent'
import Overlay from 'ol/Overlay'
import type { MapProps, MapInstance } from '../types/map.types'
import type { MapProps } from '../types/map.types'
export class MapService {
map: Map | null = null
@ -35,14 +38,6 @@ export class MapService {
minZoom: props.minZoom
})
})
// return {
// map: this.map,
// tileLayer: this.tileLayer,
// markerLayer: null,
// rippleLayer: null,
// popupOverlay: this.popupOverlay
// }
}
/**
@ -89,6 +84,20 @@ export class MapService {
}
/**
*
*/
fitToMarkers(lonLats: number[][]): void {
if (!this.map || lonLats.length === 0) return
const extent = boundingExtent(lonLats)
const webMercatorExtent = transformExtent(extent, 'EPSG:4326', 'EPSG:3857')
this.map.getView().fit(webMercatorExtent, {
padding: [80, 50, 50, 50],
maxZoom: 15
})
}
/**
*
*/
getMap(): Map | null {

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

@ -8,6 +8,7 @@ import { Feature } from 'ol'
import { Point } from 'ol/geom'
import { Style } from 'ol/style'
import { fromLonLat } from 'ol/proj'
import type { MarkerData, MapProps } from '../types/map.types'
import { createMarkerStyle, getClusterMarkerData } from '../utils/map.utils'
import { ANIMATION_CONFIG } from '../constants/map.constants'
@ -30,7 +31,7 @@ export class MarkerService {
*
*/
createMarkerLayer(props: MapProps): VectorLayer<VectorSource | Cluster> {
console.log('createMarkerLayer')
// console.log('createMarkerLayer')
if (this.markerLayer) {
this.map?.removeLayer(this.markerLayer)
}
@ -77,13 +78,13 @@ export class MarkerService {
const shouldForceSingleMark = () => {
if (!props.forceSingleMark || !this.map) return false
const currentZoom = this.map.getView().getZoom()
console.log('currentZoom', currentZoom)
// console.log('currentZoom', currentZoom)
// return currentZoom && currentZoom >= props.forceSingleMark
return currentZoom && currentZoom >= ANIMATION_CONFIG.clusterThreshold
}
// console.log('createMarkerLayerFromProps shouldForceSingleMark', shouldForceSingleMark())
// 如果启用聚合且不强制使用单个marker模式
console.log('shouldForceSingleMark()', shouldForceSingleMark())
// console.log('shouldForceSingleMark()', shouldForceSingleMark())
if (props.enableCluster && !shouldForceSingleMark()) {
const clusterSource = new Cluster({
@ -122,7 +123,7 @@ export class MarkerService {
renderOrder: (a, b) => {
// console.log('renderOrder',a,b.get('markerData').time);
// 按priority属性降序排列
// 按xxx属性降序排列
return b.get('markerData').time - a.get('markerData').time
}
})

10
web/src/views/HandDevice/Home/components/types/map.types.ts

@ -168,13 +168,3 @@ export interface TrajectoryPlayState {
/** 播放结束时间 */
endTime?: number
}
// 地图实例接口
export interface MapInstance {
map: Map
tileLayer: TileLayer<XYZ | OSM>
markerLayer: any
rippleLayer: any
popupOverlay: Overlay|null
trajectoryLayer?: any
}

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

@ -1,67 +1,72 @@
<template>
<div class="flex flex-row overflow-auto" style="height: calc(100vh - 160px)">
<div class="flex-1 h-full position-relative">
<OpenLayerMap
class="w-full map-container"
v-if="inited"
ref="mapRef"
class="map-container"
:showDrawFences="true"
:showTrajectories="true"
:markers="markers"
:markers="filterMarkers"
:fences="fences"
/>
<div class="top-panel" v-show="!appStore.mobile">
<div class="top-panel__left">
<div class="search-group">
<el-input v-model="search" class="search-input" placeholder="请输入关键词" />
</div>
<!-- <div>
<el-checkbox-group v-model="openFences">
<el-checkbox label="显示电子围栏" value="1" />
</el-checkbox-group>
</div> -->
</div>
<div class="top-panel__center">
<div class="data_item">
<span class="data_item__title">手持设备</span>
<span class="data_item__value">{{ handDetectorCount }}</span>
<span class="data_item__unit"></span>
</div>
<div class="data_item">
<span class="data_item__title">在线数量</span>
<span class="data_item__value">{{ onlineCount }}</span>
<span class="data_item__unit"></span>
<TopPanel
v-model="search"
:handDetectorCount="handDetectorCount"
:onlineCount="onlineCount"
/>
</div>
<div class="markerList">
<!--marker列表 -->
<div v-for="item in filterMarkers" :key="item.id" class="marker-item">
<div>{{ item.name }}{{ item.onlineStatus === 1 ? '在线' : '离线' }}</div>
</div>
<div class="top-panel__right">
<span class="legend-title">报警图例</span>
<div class="normal-legend">正常状态</div>
<div class="alarm1-legend">围栏报警</div>
<div class="alarm2-legend">气体报警</div>
</div>
</div>
</template>
<script lang="ts" setup>
import OpenLayerMap from './components/OpenLayerMap.vue'
import TopPanel from './components/TopPanel.vue'
import { getLastDetectorData } from '@/api/gas'
import { HandDetectorData } from '@/api/gas/handdetector'
import { MarkerData, FenceData } from './components/types/map.types'
import { useAppStore } from '@/store/modules/app'
import { useHandDetectorStore } from '@/store/modules/handDetector'
import dayjs from 'dayjs'
const appStore = useAppStore()
const handDetectorStore = useHandDetectorStore() // store
const getDataTimer = ref<NodeJS.Timeout | null>(null)
const markers = ref<MarkerData[]>([])
const fences = ref<FenceData[]>([])
const inited = ref(false)
const mapRef = ref<typeof OpenLayerMap>()
const search = ref('')
watch(
() => search.value,
(newSearch, oldSearch) => {
if (newSearch !== oldSearch) {
mapRef.value?.fitToMarkers()
}
},
{ immediate: false }
)
//
const handDetectorCount = computed(() => markers.value.length)
const onlineCount = computed(() => markers.value.filter((item) => item.onlineStatus === 1).length)
const filterMarkers = computed(() => {
if (search.value) {
return markers.value.filter((item) => {
var isName = item.name.includes(search.value)
var isSn = item.sn?.includes(search.value)
var isGasChemical = item.gasChemical?.includes(search.value)
return isName || isSn || isGasChemical
})
}
return markers.value
})
const getMarkers = async () => {
console.log('getMarkers')
@ -85,7 +90,6 @@ const getMarkers = async () => {
}
})
markers.value = res2 as unknown as any[]
inited.value = true
})
}
const getFences = async () => {
@ -102,16 +106,16 @@ const getFences = async () => {
}
onMounted(() => {
getMarkers()
setTimeout(() => {
getFences()
}, 2000)
// getFences()
console.log('定时器,暂时关掉,太烦了')
// getDataTimer.value = setInterval(() => {
// getMarkers()
// getFences()
// }, 5000)
getDataTimer.value = setInterval(() => {
getMarkers()
getFences()
}, 5000)
})
onUnmounted(() => {
clearInterval(getDataTimer.value as NodeJS.Timeout)
@ -120,116 +124,13 @@ onUnmounted(() => {
<style scoped lang="scss">
.map-container {
width: 100%;
height: calc(100vh - 140px);
}
/* 顶部面板样式 */
.top-panel {
position: absolute;
top: 12px;
left: 50px;
right: 10px;
z-index: 999;
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 10px 12px;
flex-wrap: wrap;
box-sizing: border-box;
.top-panel__left {
// flex: 0 0 260px;
width: 260px;
background: rgba(255, 255, 255, 0.7);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 10px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
height: 100%;
display: flex;
align-items: center;
padding: 10px;
.search-group {
.search-input {
width: 100%;
}
}
}
.top-panel__center {
flex: 1 1 auto;
display: flex;
align-items: center;
.data_item {
width: 200px;
background: rgba(255, 255, 255, 0.9);
border: 1px solid rgba(0, 0, 0, 0.06);
border-radius: 8px;
padding: 12px 12px;
margin-right: 12px;
.data_item__title {
font-size: 14px;
color: #3f3f3f;
vertical-align: middle;
}
.data_item__value {
display: inline-block;
padding: 0 10px;
font-size: 18px;
font-weight: 600;
color: #3399ff;
vertical-align: middle;
}
.data_item__unit {
font-size: 14px;
color: #3f3f3f;
vertical-align: middle;
}
}
}
.top-panel__right {
display: flex;
align-items: center;
gap: 8px;
background: rgba(255, 255, 255, 0.85);
border: 1px solid rgba(0, 0, 0, 0.06);
padding: 12px 12px;
border-radius: 8px;
box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);
white-space: nowrap;
}
.markerList {
width: 220px;
height: 100%;
.legend-title {
color: #606266;
font-size: 14px;
}
.normal-legend,
.alarm1-legend,
.alarm2-legend {
padding: 4px 8px;
border-radius: 999px;
color: #fff;
font-size: 12px;
line-height: 1;
}
.normal-legend {
background: #67c23a;
}
.alarm1-legend {
background: #e6a23c;
}
.alarm2-legend {
background: #f56c6c;
}
}
background-color: white;
padding:0 10px;
margin-left: 10px;
}
</style>

Loading…
Cancel
Save