293 lines
8.6 KiB
JavaScript
293 lines
8.6 KiB
JavaScript
|
||
import * as maptalks from 'maptalks'
|
||
import { PointLayer } from '@maptalks/vt'
|
||
import GlobalMap from '../js/GlobalMap.js'
|
||
import { getAssetsFile } from '@/utils/common'
|
||
import WebSocketClient from '@/utils/WebSocketClient'
|
||
import { findByCurrent } from '@/api/map/index.js'
|
||
import dayjs from 'dayjs'
|
||
|
||
const danger = getAssetsFile('map/boat/danger.png')
|
||
const passenger = getAssetsFile('map/boat/passenger.png')
|
||
const trawler = getAssetsFile('map/boat/trawler.png')
|
||
const other = getAssetsFile('map/boat/other.png')
|
||
const radar = getAssetsFile('map/boat/radar.png')
|
||
const netsonde = getAssetsFile('map/boat/netsonde.png')
|
||
|
||
let storeInstance = null
|
||
let globalMap = null
|
||
let glgroup = null
|
||
let dynamicBoatInfoWebSocket = null // websock
|
||
let boatsMarkerlayer = null // 渔船图层
|
||
let cleanupTimer = null
|
||
|
||
const init = (store) => {
|
||
storeInstance = store
|
||
globalMap = GlobalMap.instance
|
||
glgroup = globalMap.glGroup
|
||
glgroup.setZIndex(8)
|
||
setStyleToBoatLayer('_trawler_dynamic_boat', 8)
|
||
}
|
||
|
||
// 设置渔船样式
|
||
const setStyleToBoatLayer = (key, zIndex) => {
|
||
const style = {
|
||
style: [
|
||
{
|
||
name: 'boatStyle',
|
||
filter: true,
|
||
renderPlugin: {
|
||
dataConfig: {
|
||
type: 'point',
|
||
only2D: true
|
||
},
|
||
sceneConfig: {
|
||
fading: true,
|
||
depthFunc: 'always'
|
||
},
|
||
type: 'icon'
|
||
},
|
||
symbol: [
|
||
{
|
||
markerType: 'triangle',
|
||
markerWidth: {
|
||
type: 'interval',
|
||
stops: [
|
||
[ 5, 5 ],
|
||
[ 10, 10 ]
|
||
// [ 11, 0 ]
|
||
]
|
||
},
|
||
markerHeight: {
|
||
type: 'interval',
|
||
stops: [
|
||
[ 5, 10 ],
|
||
[ 10, 20 ]
|
||
// [ 11, 0 ]
|
||
]
|
||
},
|
||
markerFill: {
|
||
type: 'categorical',
|
||
property: 'deviceType',
|
||
default: '#f4ea2a',
|
||
// stops: [
|
||
// [ 'AIS', { type: 'categorical', property: 'boatType', stops: [
|
||
// [ '危险品货物运输船', '#d81e06' ],
|
||
// [ '液货船', '#d81e06' ],
|
||
// [ '客船', '#73f34f' ],
|
||
// [ '公务船', '#73f34f' ],
|
||
// [ '拖轮', '#73f34f' ],
|
||
// [ '渔船', '#fff' ],
|
||
// [ '其他', '#f4ea2a' ],
|
||
// [ '网位移', '#e6e6e6' ],
|
||
// [ '无线索船', '#e6e6e6' ]
|
||
// ] } ],
|
||
// [ 'RADAR', radar ]
|
||
// ],
|
||
stops: [
|
||
[ 'AIS', '#f4ea2a' ]
|
||
]
|
||
},
|
||
markerLineColor: [ 0.2, 0.29, 0.39, 1 ],
|
||
markerLineWidth: 1,
|
||
markerRotation: {
|
||
property: 'cog',
|
||
type: 'identity'
|
||
}
|
||
},
|
||
{
|
||
markerWidth: {
|
||
type: 'interval',
|
||
stops: [
|
||
[ 10, 0 ],
|
||
[ 11, 25 ],
|
||
[ 14, 25 ]
|
||
]
|
||
},
|
||
markerHeight: {
|
||
type: 'interval',
|
||
stops: [
|
||
[ 10, 0 ],
|
||
[ 11, 30 ],
|
||
[ 14, 30 ]
|
||
]
|
||
},
|
||
markerRotation: {
|
||
property: 'cog',
|
||
type: 'identity'
|
||
},
|
||
markerFile: {
|
||
type: 'categorical',
|
||
property: 'deviceType',
|
||
default: other,
|
||
// stops: [
|
||
// [ 'AIS', { type: 'categorical', property: 'boatType', stops: [
|
||
// [ '危险品货物运输船', danger ],
|
||
// [ '液货船', danger ],
|
||
// [ '客船', passenger ],
|
||
// [ '公务船', passenger ],
|
||
// [ '拖轮', passenger ],
|
||
// [ '渔船', trawler ],
|
||
// [ '其他', other ],
|
||
// [ '网位移', netsonde ],
|
||
// [ '无线索船', netsonde ]
|
||
// ] } ],
|
||
// [ 'RADAR', radar ],
|
||
// ],
|
||
stops: [
|
||
[ 'AIS', other ]
|
||
]
|
||
},
|
||
textName: {
|
||
property: 'boatName',
|
||
type: 'identity'
|
||
},
|
||
textFill: '#fff',
|
||
textHaloFill: '#3300cc',
|
||
textHaloRadius: 2,
|
||
textHaloBlur: 20,
|
||
textDy: 10,
|
||
textSize: {
|
||
type: 'interval',
|
||
stops: [
|
||
[ 14, 0 ],
|
||
[ 15, 15 ]
|
||
]
|
||
}
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
const name = `vt_${key}`
|
||
if (boatsMarkerlayer) {
|
||
boatsMarkerlayer.remove()
|
||
}
|
||
// 初始化动态渔船图层
|
||
boatsMarkerlayer = new PointLayer(name, {
|
||
cursor: 'pointer'
|
||
})
|
||
boatsMarkerlayer.setStyle(style)
|
||
boatsMarkerlayer.addTo(glgroup)
|
||
glgroup.setZIndex(zIndex)
|
||
}
|
||
|
||
// 单独的清理函数
|
||
const cleanupExpiredBoats = () => {
|
||
boatsMarkerlayer.getGeometries().forEach(item => {
|
||
const properties = item.getProperties()
|
||
if (dayjs().diff(properties.gpsTime, 'hours') > 24) {
|
||
item.remove()
|
||
}
|
||
})
|
||
}
|
||
|
||
const getShip = () => {
|
||
findByCurrent().then(res => {
|
||
console.log('初始获取')
|
||
addBoats(res.result)
|
||
})
|
||
// ----------船只数据------------------
|
||
dynamicBoatInfoWebSocket = new WebSocketClient(`${import.meta.env.VITE_WS_BASE_URL}`)
|
||
dynamicBoatInfoWebSocket.onopen(event => {
|
||
})
|
||
dynamicBoatInfoWebSocket.onmessage(event => {
|
||
console.log('接收数据:', JSON.parse(event.data))
|
||
if(Array.isArray(JSON.parse(event.data))) {
|
||
addBoats(JSON.parse(event.data))
|
||
|
||
}
|
||
})
|
||
|
||
dynamicBoatInfoWebSocket.onclose(event => {
|
||
// 可以尝试重新连接
|
||
dynamicBoatInfoWebSocket.reconnect()
|
||
})
|
||
|
||
dynamicBoatInfoWebSocket.onerror(event => {
|
||
dynamicBoatInfoWebSocket.close()
|
||
dynamicBoatInfoWebSocket = null
|
||
})
|
||
// 启动定期清理任务(每5分钟检查一次)
|
||
if (cleanupTimer) {
|
||
clearInterval(cleanupTimer)
|
||
}
|
||
cleanupTimer = setInterval(() => {
|
||
cleanupExpiredBoats()
|
||
}, 5 * 60 * 1000) // 5分钟
|
||
// 初始化连接
|
||
dynamicBoatInfoWebSocket.connect()
|
||
}
|
||
|
||
const addBoats = (boatList) => {
|
||
|
||
boatList.forEach((boat) => {
|
||
// let types = [ '危险品货物运输船', '液货船', '客船', '公务船', '拖轮', '渔船', '其他', '网位移', '无线索船' ]
|
||
let { longitude, latitude, cog, boatName, sog, terminalCode, deviceType, gpsTime } = boat
|
||
let isContain = boatsMarkerlayer.getGeometryById(terminalCode)
|
||
if (isContain !== null) {
|
||
isContain.setCoordinates([ longitude, latitude ])
|
||
isContain.setProperties({
|
||
cog: 360 - Number(cog),
|
||
angle: Number(cog),
|
||
sog: Number(sog),
|
||
boatName,
|
||
latitude,
|
||
longitude,
|
||
deviceType,
|
||
gpsTime
|
||
// boatType: types[Math.floor(Math.random() * types.length)]
|
||
})
|
||
} else {
|
||
let mm = new maptalks.Marker([ longitude, latitude ], {
|
||
id: terminalCode,
|
||
properties: {
|
||
cog: 360 - Number(cog),
|
||
angle: Number(cog),
|
||
sog: Number(sog),
|
||
boatName,
|
||
latitude,
|
||
longitude,
|
||
deviceType,
|
||
gpsTime
|
||
// boatType: types[Math.floor(Math.random() * types.length)]
|
||
},
|
||
cursor: 'pointer'
|
||
})
|
||
mm.on('click', (e) => {
|
||
storeInstance.updateWindowInfo({
|
||
visible: true,
|
||
type: '_trawler_dynamic',
|
||
data: { ...boat,
|
||
...e.target.getProperties()
|
||
// boatType: types[Math.floor(Math.random() * types.length)]
|
||
}
|
||
})
|
||
globalMap.map.animateTo(
|
||
{
|
||
zoom: 20,
|
||
center: [ boat.longitude, boat.latitude ]
|
||
},
|
||
{
|
||
duration: 1000 * 0.5,
|
||
easing: 'out'
|
||
}
|
||
)
|
||
})
|
||
mm.addTo(boatsMarkerlayer)
|
||
}
|
||
})
|
||
}
|
||
const destroyWebsocket = () => {
|
||
dynamicBoatInfoWebSocket.close()
|
||
if (cleanupTimer) {
|
||
clearInterval(cleanupTimer)
|
||
cleanupTimer = null
|
||
}
|
||
}
|
||
export {
|
||
destroyWebsocket,
|
||
init,
|
||
getShip,
|
||
boatsMarkerlayer
|
||
} |