123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401 |
- import {defineStore} from "pinia";
- import {ElMessage} from "element-plus";
- import {computed, reactive, toRefs} from "vue";
- import * as format from "ol/format";
- import * as layer from "ol/layer";
- import * as source from "ol/source";
- import MapStyle from "./map-style";
- import * as ol from "ol";
- import {randomColor, YMDHms} from "@/utils/util";
- import {formatPosition, getShapeView} from "@/utils/easyMap";
- import { v4 } from "uuid";
- export const useShipMapStore = defineStore('shipMap', () => {
- const state: any = reactive({
- warningOpen: true,
- warningInfo: {},
- map: null,
- mapFunc: null,
- zoom: 0,
- layerWMS: null,
- ws: {
- instance: null,
- layerShip: null,
- overlayTrack: null,
- },
- trackHoverData: null,
- trackMap: new Map([['123', {
- data: {
- targetSourceJson: '[]'
- },
- color: randomColor(1),
- history: [],
- real: [{}],
- trackId: '123',
- moveToTrack: () => {},
- // 直接用图层的话declutter: true会报错,Uncaught TypeError: Failed to execute 'clip' on 'CanvasRenderingContext2D': parameter 1 is not of type 'Path2D'.
- lineLayer: 'lineLayer_' + 123,
- pointsLayer: 'pointsLayer_' + 123,
- del: () => {},
- visibleTrack: (visible) => {},
- refreshTrackStyle: () => {},
- showTrack: true,
- showArchive: true,
- archiveLayout: {
- width: 480,
- top: 10,
- left: 200
- },
- archiveParams: {
- tab: 1,
- }
- }]])
- })
- const initMap = (map, mapFunc, {trackPointDom}) => {
- state.map = map
- state.mapFunc = mapFunc
- state.zoom = state.map.getView().getZoom()
- state.map.on('movestart', e => {
- map.un('pointermove', mapPointerMove)
- map.un('singleclick', mapSingleClick)
- })
- state.map.on('moveend', e => {
- state.trackHover = new Date().getTime()
- state.zoom = e.map.getView().getZoom()
- switchZoom()
- map.on('singleclick', mapSingleClick)
- map.on('pointermove', mapPointerMove)
- })
- state.ws.overlayTrack = new ol.Overlay({
- element: trackPointDom,
- autoPan: false,
- offset: [0, -22],
- positioning: 'bottom-center',
- stopEvent: true,
- })
- state.map.addOverlay(state.ws.overlayTrack)
- // 预警助手
- initWarningWS()
- }
- const mapPointerMove = (ev) => {
- let pixel = ev.pixel
- let feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
- return feature
- })
- if (feature && (feature.get('_featureType') == 'ship' || feature.get('_featureType') == 'trackPoint')) {
- state.map.getTargetElement().style.cursor = 'pointer'
- state.trackHoverData = feature.get('_data')
- state.ws.overlayTrack.setPosition(feature.getGeometry().getCoordinates())
- } else {
- state.map.getTargetElement().style.cursor = ''
- state.trackHoverData = null
- state.ws.overlayTrack.setPosition(undefined)
- }
- }
- const mapSingleClick = (ev) => {
- let pixel = ev.pixel
- let feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
- return feature
- })
- if (feature && feature.get('_featureType') == 'ship') {
- if (!state.trackMap.has(feature.get('_id'))) {
- const d = feature.get('_data')
- state.trackMap.set(feature.get('_id'), {
- data: feature.get('_data'),
- color: randomColor(1),
- history: [],
- real: [d],
- trackId: feature.get('_trackId'),
- moveToTrack: () => {
- const position = []
- const t = state.trackMap.get(feature.get('_id'))
- const arr = [...t.history, ...t.real]
- arr.forEach(v => {
- position.push([v.targetLongitude, v.targetLatitude])
- })
- getShapeView(state.map, position)
- },
- // 直接用图层的话declutter: true会报错,Uncaught TypeError: Failed to execute 'clip' on 'CanvasRenderingContext2D': parameter 1 is not of type 'Path2D'.
- lineLayer: 'lineLayer_' + feature.get('_id'),
- pointsLayer: 'pointsLayer_' + feature.get('_id'),
- del: () => {
- state.map.removeLayer(state.map.getLayers().getArray().filter(v => v.get('__layerName') === state.trackMap.get(feature.get('_id')).lineLayer)[0])
- state.map.removeLayer(state.map.getLayers().getArray().filter(v => v.get('__layerName') === state.trackMap.get(feature.get('_id')).pointsLayer)[0])
- state.trackMap.delete(feature.get('_id'))
- },
- visibleTrack: (visible) => {
- const t = state.trackMap.get(feature.get('_id'))
- state.map.getLayers().getArray().filter(v => v.get('__layerName') === t.lineLayer)[0]?.setVisible(visible)
- state.map.getLayers().getArray().filter(v => v.get('__layerName') === t.pointsLayer)[0]?.setVisible(visible)
- t.showTrack = visible
- if (visible) {
- t.moveToTrack()
- }
- },
- refreshTrackStyle: () => {
- const t = state.trackMap.get(feature.get('_id'))
- const arr = [...t.history, ...t.real]
- let lineWkt = ''
- if (arr.length > 1) {
- arr.forEach((v, i) => {
- if (i === 0) {
- lineWkt += `LINESTRING(${v.targetLongitude} ${v.targetLatitude}`
- } else if (i === arr.length - 1) {
- lineWkt += `,${v.targetLongitude} ${v.targetLatitude})`
- } else {
- lineWkt += `,${v.targetLongitude} ${v.targetLatitude}`
- }
- v.wkt = `POINT(${v.targetLongitude} ${v.targetLatitude})`
- })
- }
- if (lineWkt) {
- const lS = new source.Vector({
- features: [],
- wrapX: false
- })
- const lineF: any = new format.WKT().readFeature(lineWkt)
- lineF.set('trackPointList', arr)
- lineF.setStyle((f, r) => MapStyle.trackStyle(f, r, state.map, t.color, (_s, pointList) => {
- const pointFeatures: any = []
- pointList.forEach(DATA => {
- try {
- const feat: any = new format.WKT().readFeature(DATA.wkt)
- feat.set('_featureType', 'trackPoint')
- feat.set('_data', DATA)
- feat.setStyle(MapStyle.trackPointNormalStyle(t.color))
- pointFeatures.push(feat)
- } catch (e) {
- console.log(e)
- }
- })
- lS.clear()
- lS.addFeatures(pointFeatures)
- return _s
- }))
- state.map.getLayers().getArray().filter(v => v.get('__layerName') === t.lineLayer)[0].setSource(new source.Vector({
- features: [lineF],
- wrapX: false
- }))
- state.map.getLayers().getArray().filter(v => v.get('__layerName') === t.pointsLayer)[0].setSource(lS)
- }
- },
- showTrack: true,
- showArchive: true,
- archiveLayout: {
- width: 480,
- top: 10,
- left: state.mapFunc.mapWidth - 350 - 10
- },
- archiveParams: {
- tab: 1,
- }
- })
- const lineLayer = new layer.Vector({
- zIndex: 4000,
- __layerName: state.trackMap.get(feature.get('_id')).lineLayer
- })
- const pointsLayer = new layer.Vector({
- zIndex: 4100,
- declutter: true,
- __layerName: state.trackMap.get(feature.get('_id')).pointsLayer
- })
- state.map.addLayer(lineLayer)
- state.map.addLayer(pointsLayer)
- const ws = new WebSocket(`ws://${location.host}/history-track-ws-api/history-fkShips-track`)
- ws.onopen = (e) => {
- const str = {
- shipId: feature.get('_id'),
- startTime: YMDHms(new Date(d.mergeTime).getTime() - 1000 * 60 * 60),
- endTime: YMDHms(d.mergeTime),
- searchType: 1,
- sendInterval: 1
- }
- ws.send(JSON.stringify(str))
- }
- ws.onmessage = (e) => {
- try {
- const json = JSON.parse(e.data)
- if (json.message === '查询结束') {
- ws.close()
- } else if (json.data?.length > 0) {
- state.trackMap.get(feature.get('_id')).history.push(...json.data.map(v => ({
- targetName: v.shipName,
- mergeTarget: v.shipId,
- targetLongitude: v.shipLon,
- targetLatitude: v.shipLat,
- targetCourse: v.shipCourse,
- targetSpeed: v.shipSpeed,
- mergeTime: v.trackTime,
- targetSourceJson: v.targetSource,
- })))
- state.trackMap.get(feature.get('_id')).refreshTrackStyle()
- }
- } catch (e) {
- }
- }
- initWebSocket()
- }
- }
- }
- const zoomWMS = computed(() => {
- return state.zoom <= 14
- })
- const switchZoom = () => {
- if (zoomWMS.value) {
- if (state.ws.instance && state.trackMap.size === 0) {
- state.ws.instance.close()
- state.ws.instance = null
- state.map.removeLayer(state.ws.layerShip)
- state.ws.layerShip = null
- }
- // 瓦片
- initWMS()
- // ws
- if (state.trackMap.size > 0) {
- initWebSocket()
- }
- } else {
- if (state.layerWMS) {
- state.map.removeLayer(state.layerWMS)
- state.layerWMS = null
- }
- // ws
- initWebSocket()
- }
- }
- const initWMS = () => {
- const __flag = 'shipWMS'
- if (!state.layerWMS) {
- const _l = state.map?.getLayers().getArray().filter(v => v.get('__layerName') === __flag)
- if (_l?.length > 0) {
- _l.forEach(v => {
- state.map.removeLayer(v)
- })
- }
- const _tileWMS = new source.TileWMS({
- url: `/geoserver-api/geoserver/redis/wms`,
- params: {
- 'FORMAT': 'image/png8',
- 'VERSION': '1.1.1',
- LAYERS: 'redis:geo_fusion_ship',
- "exceptions": 'application/vnd.ogc.se_inimage',
- // CQL_FILTER: CQL,
- refresh: new Date().getTime()
- }
- })
- state.layerWMS = new layer.Tile({
- source: _tileWMS,
- zIndex: 3333,
- __layerName: __flag,
- })
- state.map.addLayer(state.layerWMS)
- }
- }
- const getBBOX = () => {
- return `BBOX(location, ${state.map.getView().calculateExtent(state.map.getSize()).join(',')})`;
- };
- const getWSParams = () => {
- const param = {
- cql: '',
- realCql: '',
- userId: "18889231165"
- }
- let idCql = ''
- if (state.trackMap.size > 0) {
- let arr = []
- state.trackMap.forEach((v, k) => {
- arr.push(`'${k}'`)
- })
- idCql = `mergeTarget in (${arr.join(',')})`
- }
- if (zoomWMS.value) {
- param.cql = idCql
- } else {
- param.cql = getBBOX()
- param.realCql = idCql
- }
- return JSON.stringify(param)
- }
- const initWebSocket = () => {
- if (!state.ws.instance) {
- state.ws.instance = new WebSocket(`ws://${location.host}/rh-ws-api/webSocket`)
- state.ws.instance.onopen = (e) => {
- state.ws.instance.send(getWSParams())
- }
- state.ws.instance.onmessage = (e) => {
- try {
- const json = JSON.parse(e.data)
- const shipData = json.data
- initShip(shipData)
- } catch (e) {
- }
- }
- } else {
- if (state.ws.instance.readyState == 1) {
- state.ws.instance.send(getWSParams())
- }
- }
- }
- const initShip = (data) => {
- if (!state.ws.layerShip) {
- state.ws.layerShip = new layer.Vector({
- zIndex: 4444,
- style: (f) => {
- return MapStyle.ShipNormalStyle({
- course: f.get('_course'),
- speed: f.get('_speed'),
- head: f.get('_head'),
- mergeType: f.get('_mergeType'),
- color: state.trackMap.get(f.get('_id'))?.color
- })
- }
- })
- state.map.addLayer(state.ws.layerShip)
- }
- // 动态拼接数据的唯一标识DATA,不可修改
- const features = data.map(v => {
- try {
- const feat: any = new format.WKT().readFeature(`POINT(${v.targetLongitude} ${v.targetLatitude})`)
- feat.set('_course', v.targetCourse || 0)
- feat.set('_speed', v.targetSpeed || 0)
- feat.set('_head', v.targetHeading)
- feat.set('_mergeType', v.mergeType)
- feat.set('_id', v.mergeTarget)
- feat.set('_trackId', v.mergeId)
- feat.set('_data', v)
- feat.set('_featureType', 'ship')
- // 实时轨迹
- const t = state.trackMap.get(feat.get('_id'))
- if (t && t.trackId !== feat.get('_trackId')) {
- t.real.push(feat.get('_data'))
- t.trackId = feat.get('_trackId')
- t.data = feat.get('_data')
- t.refreshTrackStyle()
- }
- return feat
- } catch (e) {
- console.log(e)
- }
- })
- const vectorSource = new source.Vector({
- features: features,
- wrapX: false
- });
- state.ws.layerShip.setSource(vectorSource)
- }
- const mockWarningWS = () => {
- state.warningInfo = {
- name: v4(),
- time: new Date().getTime(),
- }
- }
- const initWarningWS = () => {
- }
- return {
- ...toRefs(state),
- initMap,
- mockWarningWS,
- }
- })
|