CzRger 5 months ago
parent
commit
c978036509

BIN
src/assets/images/ship-type/AIS.png


BIN
src/assets/images/ship-type/AIS_BEIDOU.png


BIN
src/assets/images/ship-type/AIS_BEIDOU_RADAR.png


BIN
src/assets/images/ship-type/AIS_RADAR.png


BIN
src/assets/images/ship-type/BEIDOU.png


BIN
src/assets/images/ship-type/BEIDOU_RADAR.png


BIN
src/assets/images/ship-type/RADAR.png


+ 20 - 2
src/components/easyMap/initMapInfo.ts

@@ -16,6 +16,15 @@ const initInternet = (obj) => {
     }),
     visible: obj.visible,
   })
+
+  // const _layer = new layer.Tile({
+  //   source: new source.XYZ({
+  //     projection: "EPSG:4326",
+  //     url: `/EzServer6-api/EzServer6/Maps/${obj.key}/EzMap?Service=getImage&Type=RGB&ZoomOffset=0&Col={x}&Row={y}&Zoom={z}&V=0.3`,
+  //   }),
+  //   visible: obj.visible,
+  // })
+
   _layer.set('_maxZoom', obj.maxZoom)
   _layer.set('_minZoom', obj.minZoom)
   _layer.set('_easyMapOl_layerName', obj.name)
@@ -25,12 +34,21 @@ const initInternet = (obj) => {
 }
 
 export const baseMapLayers = [
+  // {
+  //   key: 'tdtsl',
+  //   name: 'base_tianditu',
+  //   label: '陆图',
+  //   maxZoom: 23,
+  //   minZoom: 0,
+  //   visible: true,
+  //   img: LutuImg
+  // },
   {
     key: 'tdtsl',
     name: 'base_tianditu',
     label: '陆图',
-    maxZoom: 23,
-    minZoom: 0,
+    maxZoom: 20,
+    minZoom: 8,
     visible: true,
     img: LutuImg
   },

+ 3 - 3
src/components/easyMap/ol-map.vue

@@ -10,7 +10,7 @@
           <div>层级:
             <div class="easy-map_ol-info-zoom">
               <div class="easy-map_ol-info-zoom-button easy-map_ol-info-zoom-button_min __hover" @click="zoomChange(false)">-</div>
-              <div class="easy-map_ol-info-zoom-num">{{Math.floor(interactionZoom - 4)}}</div>
+              <div class="easy-map_ol-info-zoom-num">{{Math.floor(interactionZoom)}}</div>
               <div class="easy-map_ol-info-zoom-button easy-map_ol-info-zoom-button_max __hover" @click="zoomChange(true)">+</div>
             </div>
           </div>
@@ -35,7 +35,7 @@
           <div>层级:
             <div class="easy-map_ol-form-zoom">
               <div class="easy-map_ol-form-zoom-button easy-map_ol-form-zoom-button_min __hover" @click="zoomChange(false)">-</div>
-              <div class="easy-map_ol-form-zoom-num">{{Math.floor(interactionZoom - 4)}}</div>
+              <div class="easy-map_ol-form-zoom-num">{{Math.floor(interactionZoom)}}</div>
               <div class="easy-map_ol-form-zoom-button easy-map_ol-form-zoom-button_max __hover" @click="zoomChange(true)">+</div>
             </div>
           </div>
@@ -55,7 +55,7 @@
       </div>
       <div class="easy-map_ol-default-zoom" ref="ref_easyMap_olZoom">
         <div class="easy-map_ol-default-zoom-button" @click="zoomChange(true)">+</div>
-        <div class="easy-map_ol-default-zoom-num">{{Math.floor(interactionZoom - 4)}}</div>
+        <div class="easy-map_ol-default-zoom-num">{{Math.floor(interactionZoom)}}</div>
         <div class="easy-map_ol-default-zoom-button" @click="zoomChange(false)">-</div>
       </div>
       <div class="easy-map_ol-default-scaleLine" ref="ref_easyMap_scaleLine"></div>

+ 1 - 0
src/stores/index.ts

@@ -1,2 +1,3 @@
 export * from './app'
 export * from './dictionary'
+export * from './ship-map/ship-map'

+ 71 - 0
src/stores/ship-map/map-style.ts

@@ -0,0 +1,71 @@
+import * as style from 'ol/style'
+
+import AIS from './/ship-type/AIS.svg'
+import AIS_BEIDOU from './/ship-type/AIS_BEIDOU.svg'
+import AIS_BEIDOU_RADAR from './/ship-type/AIS_BEIDOU_RADAR.svg'
+import AIS_RADAR from './/ship-type/AIS_RADAR.svg'
+import BEIDOU from './/ship-type/BEIDOU.svg'
+import BEIDOU_RADAR from './/ship-type/BEIDOU_RADAR.svg'
+import OTHER from './/ship-type/OTHER.svg'
+import RADAR from './/ship-type/RADAR.svg'
+const shipIcon = {
+    AIS, AIS_BEIDOU, AIS_BEIDOU_RADAR, AIS_RADAR, BEIDOU, BEIDOU_RADAR, OTHER, RADAR
+}
+
+const speedStyle =  (lineRadius, rotation) => {
+    return new style.Style({
+        image: new style.RegularShape({
+            stroke: new style.Stroke({
+                color: '#000000',
+                width: 1
+            }),
+            displacement: [0, lineRadius],
+            radius: lineRadius,
+            rotation,
+            points: 2
+        })
+    })
+}
+const headingStyle = (lineRadius, headAngle, rotation) => {
+    const headRadius = 6
+    return new style.Style({
+        image: new style.RegularShape({
+            stroke: new style.Stroke({
+                color: '#ee1919',
+                width: 1
+            }),
+            displacement: [
+                headRadius * Math.sin(headAngle / 180 * Math.PI),
+                (lineRadius * 2) + headRadius * Math.cos(headAngle / 180 * Math.PI)
+            ], //这是偏移量
+            radius: headRadius,
+            rotation,
+            angle: Math.PI / (180 / headAngle), //这是角度计算出的地图上显示的角度
+            points: 2
+        })
+    })
+}
+const ShipNormalStyle = ({course = 0, speed = 0, head = null, color = '#01f200', mergeType = 'OTHER'}) => {
+    const _style: any = []
+    const allRotation = Math.PI / (180 / course)
+    const lineRadius = speed * 5
+    // 船速
+    _style.push(speedStyle(lineRadius, allRotation))
+    if (head) {
+        const headAngle = head + (360 - course)
+        // 船首向
+        _style.push(headingStyle(lineRadius, headAngle, allRotation))
+    }
+    _style.push(new style.Style({
+        image: new style.Icon({
+            color: color,
+            src: eval(`shipIcon.${mergeType}`),
+            rotation: allRotation,
+            scale: 1
+        }),
+    }))
+    return _style
+}
+export default {
+    ShipNormalStyle,
+}

+ 185 - 0
src/stores/ship-map/ship-map.ts

@@ -0,0 +1,185 @@
+import {defineStore} from "pinia";
+import {ElMessage} from "element-plus";
+import {computed, createApp, markRaw, reactive, render, toRefs, watch} from "vue";
+import * as format from "ol/format";
+import * as layer from "ol/layer";
+import * as source from "ol/source";
+import * as style from "ol/style";
+import MapStyle from "./map-style";
+import * as ol from "ol";
+
+export const useShipMapStore = defineStore('shipMap', () => {
+  const state: any = reactive({
+    map: null,
+    zoom: 0,
+    layerWMS: null,
+    ws: {
+      instance: null,
+      layerShip: null,
+      overlayTrack: null,
+    },
+    trackHoverData: null
+  })
+  const initMap = (map, {trackPointDom}) => {
+    state.map = map
+    state.map.add
+    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, -12],
+      positioning: 'bottom-center',
+      stopEvent: true,
+    })
+    state.map.addOverlay(state.ws.overlayTrack)
+  }
+  const mapPointerMove = (ev) => {
+    let pixel = ev.pixel
+    let feature = state.map.forEachFeatureAtPixel(pixel, function (feature) {
+      return feature
+    })
+    if (feature) {
+      state.trackHoverData = feature.get('_data')
+      state.ws.overlayTrack.setPosition(feature.getGeometry().getCoordinates())
+    } else {
+      state.trackHoverData = null
+      state.ws.overlayTrack.setPosition(undefined)
+    }
+  }
+  const mapSingleClick = (ev) => {}
+
+  const zoomWMS = computed(() => {
+    return state.zoom <= 12
+  })
+  const switchZoom = () => {
+    if (zoomWMS.value) {
+      if (state.ws.instance) {
+        state.ws.instance.close()
+        state.ws.instance = null
+        state.map.removeLayer(state.ws.layerShip)
+        state.ws.layerShip = null
+      }
+      // 瓦片
+      initWMS()
+    } 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 initWebSocket = () => {
+    if (!state.ws.instance) {
+      state.ws.instance = new WebSocket(`ws://${location.host}/rh-ws-api/webSocket`)
+      state.ws.instance.onopen = (e) => {
+        const param = {
+          "cql": getBBOX(),
+          "realCql": null,
+          "userId": "18889231165"
+        }
+        state.ws.instance.send(JSON.stringify(param))
+      }
+      state.ws.instance.onmessage = (e) => {
+        try {
+          const json = JSON.parse(e.data)
+          const shipData = json.data
+          initShip(shipData)
+        } catch (e) {
+        }
+      }
+    } else {
+      const param = {
+        "cql": getBBOX(),
+        "realCql": null,
+        "userId": "18889231165"
+      }
+      if (state.ws.instance.readyState == 1) {
+        state.ws.instance.send(JSON.stringify(param))
+      }
+    }
+  }
+  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'),
+          })
+        }
+      })
+      state.map.addLayer(state.ws.layerShip)
+    }
+    //  动态拼接数据的唯一标识DATA,不可修改
+    const features = data.map(v => {
+      try {
+        const feat: any = new format.WKT().readFeature(v.location)
+        feat.set('_course', v.targetCourse || 0)
+        feat.set('_speed', v.targetSpeed || 0)
+        feat.set('_head', v.targetHeading)
+        feat.set('_mergeType', v.mergeType)
+        feat.set('_data', v)
+        return feat
+      } catch (e) {
+        console.log(e)
+      }
+    })
+    const vectorSource = new source.Vector({
+      features: features,
+      wrapX: false
+    });
+    state.ws.layerShip.setSource(vectorSource)
+  }
+
+  return {
+    ...toRefs(state),
+    initMap,
+  }
+})

+ 14 - 0
src/stores/ship-map/ship-type/AIS.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="21px" viewBox="0 0 14 21" version="1.1" xmlns="http://www.w3.org/2000/svg"
+     xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-AIS</title>
+    <g id="船舶状态2备份-2"
+       transform="translate(-48.000000, -1054.000000)"
+       style="fill: #fff;"
+       stroke="#000000"
+    >
+        <polygon id="融合船舶-AIS-"
+                 transform="translate(55.000000, 1064.000000) scale(-1, 1) translate(-55.000000, -1064.000000) "
+                 points="55 1054 61 1074 49 1074"></polygon>
+    </g>
+</svg>

+ 10 - 0
src/stores/ship-map/ship-type/AIS_BEIDOU.svg

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="20px" viewBox="0 0 16 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-AIS BEIDOU</title>
+    <g id="船舶状态2备份-2"
+       transform="translate(-502.000000, -1054.000000)"
+       style="fill:#fff; stroke: #000000"
+    >
+        <polygon id="融合船舶-AIS-BEIDOU" points="510 1054 517 1066.72727 510 1074 503 1066.72727"></polygon>
+    </g>
+</svg>

+ 21 - 0
src/stores/ship-map/ship-type/AIS_BEIDOU_RADAR.svg

@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="23px" viewBox="0 0 16 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-AIS BEIDOU RADAR</title>
+    <g id="首页"
+       stroke-width="1"
+
+       fill-rule="evenodd"
+       style="fill:#fff; stroke: #000000"
+    >
+        <g id="船舶状态2备份-2"
+           transform="translate(-332.000000, -1109.000000)"
+           fill-rule="nonzero"
+           >
+            <g id="融合船舶-AIS-BEIDOU-RADAR"
+               transform="translate(333.000000, 1111.000000)">
+                <polygon id="多边形备份-5" points="7 2.06779038e-13 14 12.7272727 7 20 0 12.7272727"></polygon>
+                <circle id="椭圆形备份-6" fill="#FFFFFF" cx="7" cy="13" r="2"></circle>
+            </g>
+        </g>
+    </g>
+</svg>

+ 16 - 0
src/stores/ship-map/ship-type/AIS_RADAR.svg

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="14px" height="23px" viewBox="0 0 14 23" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-AIS RADAR</title>
+    <g id="首页"
+       stroke-width="1"
+       fill-rule="evenodd"
+       style="fill:#fff; stroke: #000000"
+    >
+        <g id="船舶状态2备份-2" transform="translate(-48.000000, -1111.000000)" fill-rule="nonzero">
+            <g id="融合船舶-AIS-RADAR" transform="translate(49.000000, 1113.000000)">
+                <polygon id="三角形备份-7" transform="translate(6.000000, 10.000000) scale(-1, 1) translate(-6.000000, -10.000000) " points="6 0 12 20 0 20"></polygon>
+                <circle id="椭圆形备份-2" fill="#FFFFFF" cx="6" cy="15" r="2"></circle>
+            </g>
+        </g>
+    </g>
+</svg>

+ 14 - 0
src/stores/ship-map/ship-type/BEIDOU.svg

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="18px" height="16px" viewBox="0 0 18 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-BEIDOU</title>
+    <g id="首页"
+       stroke-width="1"
+       fill-rule="evenodd"
+       style="fill:#fff; stroke: #000000"
+
+    >
+        <g id="船舶状态2备份-2" transform="translate(-332.000000, -1056.000000)" fill-rule="nonzero">
+            <polygon id="融合船舶-BEIDOU" points="341 1056 349 1064 341 1072 333 1064"></polygon>
+        </g>
+    </g>
+</svg>

+ 17 - 0
src/stores/ship-map/ship-type/BEIDOU_RADAR.svg

@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-BEIDOU RADAR</title>
+    <g id="首页"
+       stroke-width="1"
+       fill-rule="evenodd"
+       style="fill:#fff; stroke: #000000"
+    >
+        <g id="船舶状态2备份-2" transform="translate(-189.000000, -1114.000000)"
+           fill-rule="nonzero">
+            <g id="融合船舶-BEIDOU-RADAR" transform="translate(190.000000, 1115.000000)">
+                <polygon id="多边形备份-10" points="8 0 16 8 8 16 0 8"></polygon>
+                <circle id="椭圆形备份-5" fill="#FFFFFF" cx="8" cy="8" r="2"></circle>
+            </g>
+        </g>
+    </g>
+</svg>

+ 10 - 0
src/stores/ship-map/ship-type/OTHER.svg

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="18px" height="18px" viewBox="0 0 18 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>其他</title>
+    <g id="船舶状态2"
+       transform="translate(-212.000000, -908.000000)"
+       style="fill:#fff; stroke: #303133"
+    >
+        <path d="M221,909.118034 L228.813949,924.745932 L221.005067,920.281267 L213.185423,924.747189 L221,909.118034 Z" id="其他"></path>
+    </g>
+</svg>

+ 15 - 0
src/stores/ship-map/ship-type/RADAR.svg

@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <title>融合船舶-RADAR</title>
+    <g id="首页"
+       stroke-width="1"
+       fill-rule="evenodd"
+       style="fill:#fff; stroke: #000000"
+    >
+        <g id="船舶状态2备份-2"
+           transform="translate(-189.000000, -1056.000000)"
+           fill-rule="nonzero">
+            <circle id="融合船舶-RADAR" cx="197" cy="1064" r="7"></circle>
+        </g>
+    </g>
+</svg>

+ 209 - 0
src/stores/ship-map/track-point.vue

@@ -0,0 +1,209 @@
+<template>
+  <div class="track-point-overlay">
+    <template v-if="ShipMapStore.trackHoverData">
+      <div class="name">
+        <template v-if="ShipMapStore.trackHoverData.targetName">
+          {{ShipMapStore.trackHoverData.targetName}}
+        </template>
+        <template v-else>
+          船名号未知
+        </template>
+      </div>
+      <div class="info-list">
+        <div class="item">
+          <div class="option">
+            <span>融合批次号:</span>
+            <span>{{ShipMapStore.trackHoverData.mergeTarget}}</span>
+          </div>
+        </div>
+        <div class="item">
+          <div class="option">
+            <span>雷达批次号:</span>
+            <span class="more">
+              <template v-if="formatDataCpt.radar?.length > 0">
+                <template v-for="item in formatDataCpt.radar">
+                  <span>{{item}}</span>
+                </template>
+              </template>
+              <template v-else>未知</template>
+            </span>
+          </div>
+        </div>
+        <div class="item">
+          <div class="option">
+            <span>北斗号:</span>
+            <span class="more">
+              <template v-if="formatDataCpt.beidou?.length > 0">
+                <template v-for="item in formatDataCpt.beidou">
+                  <span>{{item}}</span>
+                </template>
+              </template>
+              <template v-else>未知</template>
+            </span>
+          </div>
+          <div class="option">
+            <span>MMSI:</span>
+            <span class="more">
+              <template v-if="formatDataCpt.mmsi?.length > 0">
+                <template v-for="item in formatDataCpt.mmsi">
+                  <span>{{item}}</span>
+                </template>
+              </template>
+              <template v-else>未知</template>
+            </span>
+          </div>
+        </div>
+        <div class="item">
+          <div class="option">
+            <span>经度:</span>
+            <span>{{Number(ShipMapStore.trackHoverData.targetLongitude).toFixed(6)}}</span>
+          </div>
+          <div class="option">
+            <span>纬度:</span>
+            <span>{{Number(ShipMapStore.trackHoverData.targetLatitude).toFixed(6)}}</span>
+          </div>
+        </div>
+        <div class="item">
+          <div class="option">
+            <span>航向:</span>
+            <span>{{Number(ShipMapStore.trackHoverData.targetCourse).toFixed(2)}}°</span>
+          </div>
+          <div class="option">
+            <span>航速:</span>
+            <span>{{Number(ShipMapStore.trackHoverData.targetSpeed).toFixed(1)}}节</span>
+          </div>
+        </div>
+        <div class="item">
+          <div class="option">
+            <span>来源:</span>
+            <span v-html="formatDataCpt.source"/>
+          </div>
+        </div>
+      </div>
+      <div class="time">
+        {{ $util.YMDHms(ShipMapStore.trackHoverData.mergeTime) }}
+      </div>
+    </template>
+  </div>
+</template>
+
+<script setup lang="ts">
+import {useShipMapStore} from "@/stores";
+import {computed, reactive, watch} from "vue";
+
+const ShipMapStore = useShipMapStore()
+const formatDataCpt = computed(() => {
+  const obj = {
+    radar: [],
+    beidou: [],
+    mmsi: [],
+    source: ''
+  }
+  if (ShipMapStore.trackHoverData) {
+    const s = JSON.parse(ShipMapStore.trackHoverData.targetSourceJson)
+    obj.source = getShipSourceNew(s)
+    const {RadarbeidouNumber, faultRadarNum, faultmmsiNum} = filterShipNum(s)
+    obj.radar = faultRadarNum
+    obj.beidou = RadarbeidouNumber
+    obj.mmsi = faultmmsiNum
+  }
+  return obj
+})
+const sourceMap = {
+  TA_RADAR: '小目标雷达',
+  GLOBAL_AIS: "全球AIS",
+  BEIDOU: '北斗',
+  HLX_ZYD_RADAR: '中远海雷达',
+  HLX_RADAR: '海兰信雷达',
+  HLX_AIS: '海兰信AIS',
+  HLX_AIS_RADAR: 'AIS+雷达(海兰信)',
+  HK_SHIP_STRUCTURE: '雷云一体'
+}
+const extractArr = ['GLOBAL_AIS', 'HLX_AIS', 'HLX_AIS_RADAR']
+
+const getShipSourceNew = (data) => {
+  return data.map(x => {
+    const text = `<span style="color: ${x.signal_loss ? 'rgba(96, 98, 102, 0.50)' : '#606266'};">${sourceMap[x.type]}</span>`
+    return text
+  })
+}
+const filterShipNum = (data) => {
+  const beidou = []
+  const Rardar = []
+  const mmsi = []
+
+  data.map(s => {
+    if (!!s && s.track_device_no != 0 && extractArr.some(
+        x => x === s.type
+    )) {
+      mmsi.push(s.track_device_no ?? '')
+    } else if (!!s && s.track_device_no != 0 && s.type == 'BEIDOU') {
+      beidou.push(s.track_device_no ?? '')
+    } else {
+      !!s && s.track_id != 0 && Rardar.push(s.track_id ?? '')
+    }
+  })
+  return {
+    RadarbeidouNumber: beidou,
+    faultRadarNum: Rardar,
+    faultmmsiNum: mmsi,
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.track-point-overlay {
+  padding: 8px;
+  background: rgba(255,255,255,0.8);
+  border-radius: 4px;
+  font-size: 12px;
+  line-height: 12px;
+  color: #606266;
+  position: relative;
+  min-width: 256px;
+  &:before{
+    content: "";
+    position: absolute;
+    width: 0;
+    height: 0;
+    border: 8px solid transparent;
+    border-top-color: rgba(255,255,255,0.8);
+    left: 50%;
+    transform: translateX(-50%);
+    bottom: -16px;
+  }
+  .name{
+    height: 22px;
+    font-size: 16px;
+    font-weight: 700;
+    color: #147ffc;
+    line-height: 20px;
+    margin-bottom: 2px;
+  }
+  .info-list {
+    display: flex;
+    flex-direction: column;
+    gap: 4px;
+    .item{
+      display: flex;
+      .option {
+        flex: 1;
+        display: flex;
+        align-items: center;
+        .more {
+          display: flex;
+          flex-direction: column;
+        }
+      }
+    }
+  }
+  .time{
+    color: rgba(96,98,102,0.5);
+    font-size: 10px;
+    height: 12px;
+    line-height: 12px;
+    margin-top: 6px;
+  }
+
+}
+</style>

+ 7 - 1
src/views/web/index.vue

@@ -53,16 +53,20 @@
       <configCom v-model:show="state.tools.showConfig" :mapFunc="state.mapFunc"/>
       <archiveCom v-model:show="state.tools.showArchive"/>
       <warningCom v-model:show="state.tools.showWarning"/>
+      <trackPointCom ref="ref_trackPoint"/>
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import {computed, getCurrentInstance, reactive} from "vue";
+import {computed, getCurrentInstance, reactive, ref} from "vue";
 import configCom from './config/index.vue'
 import archiveCom from './archive/index.vue'
 import warningCom from './warning/index.vue'
+import {useShipMapStore} from "@/stores";
+import trackPointCom from '@/stores/ship-map/track-point.vue'
 
+const ShipMapStore = useShipMapStore()
 const {proxy} = getCurrentInstance()
 const state: any = reactive({
   map: null,
@@ -73,12 +77,14 @@ const state: any = reactive({
     showWarning: false,
   }
 })
+const ref_trackPoint = ref()
 const titleCpt = computed(() => {
   return import.meta.env.VITE_TITLE
 })
 const mapLoad = (map, mapFunc) => {
   state.map = map
   state.mapFunc = mapFunc
+  // ShipMapStore.initMap(state.map, {trackPointDom: ref_trackPoint.value.$el})
 }
 const refreshArea = () => {
   console.log(123)

+ 22 - 1
vite.config.ts

@@ -40,7 +40,6 @@ export default defineConfig({
       promiseImportName: i => `__tla_${i}`
     })
   ],
-  envPrefix: ['VITE_'], // 确保环境变量前缀正确
   base: '/sww/',
   resolve: {
     alias: {
@@ -78,6 +77,28 @@ export default defineConfig({
           return path.replace(/^\/ws-api/, '')
         }
       },
+      '/EzServer6-api': {
+        target: 'http://74.10.28.116:8090/',	// 地图底图代理
+        changeOrigin: true,
+        rewrite: path => {
+          return path
+        }
+      },
+      '/geoserver-api': {
+        target: 'http://74.10.28.39:8080/',	// 地图服务代理
+        changeOrigin: true,
+        rewrite: path => {
+          return path.replace(/^\/geoserver-api/, '')
+        }
+      },
+      '/rh-ws-api': {
+        target: 'http://74.10.28.28:6990/', // fk
+        ws: true,
+        changeOrigin: true,
+        rewrite: path => {
+          return path.replace(/^\/rh-ws-api/, '')
+        }
+      },
     }
   },
   css: {