This commit is contained in:
TimSpan 2024-10-16 15:02:31 +08:00
parent 4e714f4c60
commit aca5e39d18
7 changed files with 320 additions and 104 deletions

1
.gitignore vendored
View File

@ -10,6 +10,7 @@ target/
*.ipr
### VS Code ###
public/roadmap
*.log
npm-debug.log*
yarn-debug.log*

9
package-lock.json generated
View File

@ -38,6 +38,7 @@
"js-md5": "^0.8.3",
"jwt-decode": "^3.1.2",
"leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",
@ -3035,6 +3036,14 @@
"resolved": "https://registry.npmmirror.com/leaflet/-/leaflet-1.9.4.tgz",
"integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA=="
},
"node_modules/leaflet.markercluster": {
"version": "1.5.3",
"resolved": "https://registry.npmmirror.com/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz",
"integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==",
"peerDependencies": {
"leaflet": "^1.3.1"
}
},
"node_modules/less": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/less/-/less-4.2.0.tgz",

View File

@ -46,6 +46,7 @@
"js-md5": "^0.8.3",
"jwt-decode": "^3.1.2",
"leaflet": "^1.9.4",
"leaflet.markercluster": "^1.5.3",
"lodash": "^4.17.21",
"lodash-es": "^4.17.21",
"nprogress": "^0.2.0",

View File

@ -11,7 +11,7 @@ import lodasha from 'lodash';
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import zhCn from 'element-plus/dist/locale/zh-cn.mjs';
// import '@types/leaflet'
// 高德地图typescript支持
import "@amap/amap-jsapi-types";
// vue Router
@ -35,13 +35,13 @@ import "@/assets/iconfont/iconfont.css";
//自定义指令
import vCopy from "@/directives/copy";
const vueApp = createApp(App);
vueApp.config.globalProperties.day=dayjs//全局挂载
vueApp.config.globalProperties.lodash=lodasha//全局挂载
vueApp.config.globalProperties.day = dayjs//全局挂载
vueApp.config.globalProperties.lodash = lodasha//全局挂载
vueApp.directive('copy', vCopy)
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
vueApp.component(key, component)
vueApp.component(key, component)
}
vueApp

View File

@ -1 +0,0 @@
declare module 'leaflet';

View File

@ -370,8 +370,13 @@
</div>
</template>
<script lang="ts" setup>
// import L, {Marker} from 'leaflet'
// import * as Leaf from 'leaflet'
import L from 'leaflet'
import 'leaflet/dist/leaflet.css'
import 'leaflet.markercluster'
import 'leaflet.markercluster/dist/MarkerCluster.Default.css'
import {JsonResult} from '@/axios'
import * as _ from 'lodash'
import api from '@/axios'
@ -690,7 +695,7 @@ onMounted(() => {
getAi()
getjingqing()
})
//
let deviceInfoWindow = ref<any>(null)
const treedata = () => {
api
.post('/multialarm/client/alarm_point/count', {
@ -706,67 +711,85 @@ const treedata = () => {
pagesize: res1.data.count
})
.then((res: JsonResult<any>) => {
var points: any[] = []
const points: L.Marker[] = []
res.data.map((x: any) => {
const marker = new AMap.Marker({
position: new AMap.LngLat(x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude),
offset: new AMap.Pixel(-15, -15),
icon: new AMap.Icon({
image: x.deviceType == '00' ? image3 : x.deviceType == '03' ? image1 : x.deviceType == '04' ? image2 : '',
size: new AMap.Size(40, 46.5),
imageSize: new AMap.Size(30, 30) //
// MarkerClusterGroup
//@ts-ignore
const markers = L.markerClusterGroup({
maxClusterRadius: 80, //
iconCreateFunction: (cluster: any) => {
//
const count = cluster.getChildCount()
const factor = Math.pow(count / res.data.length, 1 / 18)
const size = Math.round(30 + Math.pow(count / res.data.length, 1 / 5) * 2)
const hue = 180 - factor * 180
const div = document.createElement('div')
div.style.backgroundColor = `hsla(${hue}, 100%, 50%, 0.7)`
div.style.width = div.style.height = `${size}px`
div.style.border = `solid 1px hsla(${hue}, 100%, 40%, 1)`
div.style.borderRadius = `${size / 2}px`
div.style.boxShadow = `0 0 1px hsla(${hue}, 100%, 50%, 1)`
div.innerHTML = count.toString()
div.style.lineHeight = `${size}px`
div.style.color = `hsla(${hue}, 100%, 20%, 1)`
div.style.fontSize = '14px'
div.style.textAlign = 'center'
// Leaflet divIcon
return L.divIcon({
html: div,
className: 'custom-cluster-icon',
iconSize: L.point(size, size)
})
}
})
//
res.data.forEach((x: any) => {
const lat = x.latitude ?? 0
const lng = x.longitude ?? 0
const iconUrl = x.deviceType === '00' ? image3 : x.deviceType === '03' ? image1 : x.deviceType === '04' ? image2 : ''
const marker = L.marker([lat, lng], {
icon: L.icon({
iconUrl,
iconSize: [30, 30],
iconAnchor: [15, 15]
}),
title: ''
})
marker.on('click', function () {
deviceInfoWindow.value = new AMap.InfoWindow({
isCustom: true, //使
content: createSubstanceInfowindow2(x, '1'),
offset: new AMap.Pixel(5, -13)
//
marker.on('click', () => {
console.log('deviceInfoWindow.value', deviceInfoWindow.value)
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove()
}
deviceInfoWindow.value = L.popup({
closeButton: false
})
deviceInfoWindow.value.open(state.map, [x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude])
.setLatLng([lat, lng])
.setContent(createSubstanceInfowindow2(x, '1'))
.openOn(state.map)
})
state.map.add(marker)
points.push(marker)
markers.addLayer(marker) //
})
var count = points.length
//
var _renderClusterMarker = function (context: any) {
var factor = Math.pow(context.count / count, 1 / 18)
var div = document.createElement('div')
var Hue = 180 - factor * 180
var bgColor = 'hsla(' + Hue + ',100%,50%,0.7)'
var fontColor = 'hsla(' + Hue + ',100%,20%,1)'
var borderColor = 'hsla(' + Hue + ',100%,40%,1)'
var shadowColor = 'hsla(' + Hue + ',100%,50%,1)'
div.style.backgroundColor = bgColor
var size = Math.round(30 + Math.pow(context.count / count, 1 / 5) * 2)
div.style.width = div.style.height = size + 'px'
div.style.border = 'solid 1px ' + borderColor
div.style.borderRadius = size / 2 + 'px'
div.style.boxShadow = '0 0 1px ' + shadowColor
div.innerHTML = context.count
div.style.lineHeight = size + 'px'
div.style.color = fontColor
div.style.fontSize = '14px'
div.style.textAlign = 'center'
context.marker.setOffset(new AMap.Pixel(-size / 2, -size / 2))
context.marker.setContent(div)
}
var cluster = new AMap.MarkerClusterer(state.map, points, {
gridSize: 80,
maxZoom: 12,
renderClusterMarker: _renderClusterMarker
})
state.map.plugin(['AMap.MarkerClusterer'], () => {
let zoom = state.map.getZoom()
//
state.map.addLayer(markers)
//
state.map.on('zoomend', () => {
const zoom = state.map.getZoom()
console.log('当前地图的缩放级别是:' + zoom)
cluster
})
})
})
}
//
const jinbao = ref([])
const getdayline = () => {
@ -784,49 +807,56 @@ const getdayline = () => {
jinbao.value = res.data
if (res.data.length > 0) {
res.data.map((x: any) => {
const lat = x.latitude ?? 0
const lng = x.longitude ?? 0
if (x.state == 'close') {
const marker = new AMap.Marker({
position: new AMap.LngLat(x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude),
offset: new AMap.Pixel(-10, -10),
icon: new AMap.Icon({
image: yes,
size: new AMap.Size(40, 46.5),
imageSize: new AMap.Size(40, 46.5) //
const marker = L.marker([lat, lng], {
icon: L.icon({
iconUrl: yes,
iconSize: [30, 30],
iconAnchor: [15, 15]
}),
title: ''
})
marker.on('click', function () {
deviceInfoWindow.value = new AMap.InfoWindow({
isCustom: true, //使
content: createSubstanceInfowindow(x, '1'),
offset: new AMap.Pixel(5, -13)
//
marker.on('click', () => {
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove()
}
deviceInfoWindow.value = L.popup({
closeButton: false
})
deviceInfoWindow.value.open(state.map, [x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude])
.setLatLng([lat, lng])
.setContent(createSubstanceInfowindow(x, '1'))
.openOn(state.map)
})
state.map.add(marker)
// marker
marker.addTo(state.map)
} else {
const marker = new AMap.Marker({
position: new AMap.LngLat(x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude),
offset: new AMap.Pixel(-20, -10),
content: `<div class="indexMarkerImg">
<img style="width:30px;height:30px;left:9px;top:7px" src='${no}'>
<div class="markerClass">
<div></div>
<div></div>
<div></div>
</div>
</div>`,
title: ''
})
marker.on('click', function () {
deviceInfoWindow.value = new AMap.InfoWindow({
isCustom: true, //使
content: createSubstanceInfowindow1(x, '1'),
offset: new AMap.Pixel(5, -13)
})
deviceInfoWindow.value.open(state.map, [x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude])
})
state.map.add(marker)
// const marker = new AMap.Marker({
// position: new AMap.LngLat(x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude),
// offset: new AMap.Pixel(-20, -10),
// content: `<div class="indexMarkerImg">
// <img style="width:30px;height:30px;left:9px;top:7px" src='${no}'>
// <div class="markerClass">
// <div></div>
// <div></div>
// <div></div>
// </div>
// </div>`,
// title: ''
// })
// marker.on('click', function () {
// deviceInfoWindow.value = new AMap.InfoWindow({
// isCustom: true, //使
// content: createSubstanceInfowindow1(x, '1'),
// offset: new AMap.Pixel(5, -13)
// })
// deviceInfoWindow.value.open(state.map, [x.longitude == null ? 0 : x.longitude, x.latitude == null ? 0 : x.latitude])
// })
// state.map.add(marker)
}
})
}
@ -886,21 +916,35 @@ const gettotal = () => {
})
}
//
let deviceInfoWindow = ref<any>()
const selectA = (selectedKeys: any, e: any) => {
console.log('selectedKeys', selectedKeys, e)
if (selectedKeys[0].length >= 13) {
let targetLangLat = [e.selectedNodes[0].longitude == null ? 0 : e.selectedNodes[0].longitude, e.selectedNodes[0].latitude == null ? 0 : e.selectedNodes[0].latitude]
// if (selectedKeys[0].length >= 13) {
try {
console.log('selectedKeys', selectedKeys, e)
let targetLatLngt = [e.selectedNodes[0].latitude == null ? 0 : e.selectedNodes[0].latitude, e.selectedNodes[0].longitude == null ? 0 : e.selectedNodes[0].longitude]
console.log('targetLangLat', targetLatLngt)
//
const popupContent = createSubstanceInfowindow2(e.selectedNodes[0], '1')
const lat = e.selectedNodes[0].latitude ?? 0
const lng = e.selectedNodes[0].longitude ?? 0
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove()
}
deviceInfoWindow.value = new AMap.InfoWindow({
isCustom: true, //使
content: createSubstanceInfowindow2(e.selectedNodes[0], '1'),
offset: new AMap.Pixel(5, -13)
deviceInfoWindow.value = L.popup({
closeButton: false
})
deviceInfoWindow.value.open(state.map, [e.selectedNodes[0].longitude == null ? 0 : e.selectedNodes[0].longitude, e.selectedNodes[0].latitude == null ? 0 : e.selectedNodes[0].latitude])
state.map.setZoomAndCenter(205, targetLangLat)
.setLatLng([lat, lng])
.setContent(popupContent)
.openOn(state.map)
// setView(<LatLng> center, <Number> zoom, <Zoom/pan options> options?) LatLngLat
state.map.setView(targetLatLngt, 15)
} catch (error) {
console.log('🚀 ~ selectA ~ error:', error)
}
// state.map.setZoomAndCenter(205, targetLangLat)
// }
}
const createSubstanceInfowindow = (obj: any, type: any) => {
@ -917,7 +961,11 @@ const createSubstanceInfowindow = (obj: any, type: any) => {
var closeX = document.createElement('img')
closeX.src = closeimag
closeX.onclick = () => {
deviceInfoWindow.value.close()
//
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove() //
deviceInfoWindow.value = null //
}
}
var popMian = document.createElement('div')
@ -948,7 +996,11 @@ const createSubstanceInfowindow1 = (obj: any, type: any) => {
var closeX = document.createElement('img')
closeX.src = closeimag
closeX.onclick = () => {
deviceInfoWindow.value.close()
//
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove() //
deviceInfoWindow.value = null //
}
}
var popMian = document.createElement('div')
@ -979,7 +1031,17 @@ const createSubstanceInfowindow2 = (obj: any, type: any) => {
var closeX = document.createElement('img')
closeX.src = closeimag
closeX.onclick = () => {
deviceInfoWindow.value.close()
//
try {
console.log('deviceInfoWindow.value', deviceInfoWindow.value)
if (deviceInfoWindow.value) {
deviceInfoWindow.value.remove() //
deviceInfoWindow.value = null //
}
} catch (error) {
console.log('🚀 ~ createSubstanceInfowindow2 ~ error:', error)
}
}
var popMian = document.createElement('div')
@ -1917,4 +1979,145 @@ iframe {
border-radius: 5px;
// padding-top: 20px;
}
//
:deep(.leaflet-popup-content-wrapper) {
// background: #07315e !important;
background: none;
box-shadow: none;
width: 500px;
color: #fff !important;
font-size: 14px;
padding: none;
}
:deep(.leaflet-popup-content) {
width: calc(100% - 40px) !important;
}
:deep(.leaflet-popup-content > div) {
width: 100%;
}
:deep(.leaflet-popup-content .sb_bInfo) {
width: 100%;
}
:deep(.leaflet-popup-content p) {
margin: 10px 0 !important;
}
:deep(.sb_grade > div > div) {
float: left;
width: 16%;
margin-top: 3px;
}
:deep(.sb_grade > div > div > p) {
line-height: 20px;
}
:deep(.schoolWindowInfo .sb_grade) {
margin-top: 10px;
}
:deep(.leaflet-popup-content-wrapper),
:deep(.leaflet-popup-tip) {
background: none !important;
}
:deep(.leaflet-popup-close-button) {
color: #fff !important;
width: 30px !important;
height: 30px !important;
font-size: 30px !important;
}
:deep(.warnEventInfoWindow) {
overflow: hidden;
}
:deep(.warnEventInfoWindow > p) {
float: left;
width: 120px;
}
:deep(.warnEventInfoWindow > div) {
float: left;
width: calc(100% - 130px);
margin-left: 10px;
}
:deep(.warnEventInfoWindow > p > img) {
width: 100%;
}
//
// :deep(.leaflet-popup-content-wrapper) {
// background: #07315e !important;
// width: 500px;
// color: #fff !important;
// font-size: 14px;
// }
// :deep(.leaflet-popup-content) {
// width: calc(100% - 40px) !important;
// }
// :deep(.leaflet-popup-content > div) {
// width: 100%;
// }
// :deep(.leaflet-popup-content .sb_bInfo) {
// width: 100%;
// }
// :deep(.leaflet-popup-content p) {
// margin: 10px 0 !important;
// }
// :deep(.sb_grade > div > div) {
// float: left;
// width: 16%;
// margin-top: 3px;
// }
// :deep(.sb_grade > div > div > p) {
// line-height: 20px;
// }
// :deep(.schoolWindowInfo .sb_grade) {
// margin-top: 10px;
// }
// :deep(.leaflet-popup-content-wrapper),
// :deep(.leaflet-popup-tip) {
// background: #07315e !important;
// }
// :deep(.leaflet-popup-close-button) {
// color: #fff !important;
// width: 30px !important;
// height: 30px !important;
// font-size: 30px !important;
// }
// :deep(.warnEventInfoWindow) {
// overflow: hidden;
// }
// :deep(.warnEventInfoWindow > p) {
// float: left;
// width: 120px;
// }
// :deep(.warnEventInfoWindow > div) {
// float: left;
// width: calc(100% - 130px);
// margin-left: 10px;
// }
// :deep(.warnEventInfoWindow > p > img) {
// width: 100%;
// }
</style>

View File

@ -1,5 +1,8 @@
{
"compilerOptions": {
// "types": [
// "leaflet"
// ],
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",