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 }