CzRger 1 year ago
parent
commit
5f716628f9

+ 73 - 52
src/views/ship-test/business/v2/index.vue

@@ -40,27 +40,12 @@
         </template>
       </div>
     </div>
-    <div class="hover-info" id="ID_shipHover" ref="ref_shipHover">
-      <div class="hover-info-head">
-        <span>{{shipHoverInfo?.config?.name}}_{{ shipHoverInfo?.isHistory ? '历史' : '实时'}}</span>
-      </div>
-      <div class="hover-info-close __hover" @click="null">
-        <img src="@/components/easyMap/images/close.png" alt=""/>
-      </div>
-      <div class="hover-main" v-if="shipHoverInfo?.data">
-        <template v-for="item in shipHoverInfoCpt">
-          <div class="hover-item">
-            <div class="hover-item-label">{{item.label}}:</div>
-            <div class="hover-item-value">{{item.value}}</div>
-          </div>
-        </template>
-      </div>
-    </div>
   </div>
 </template>
 
 <script lang="ts">
 import {
+  createApp,
   defineComponent,
   computed,
   onMounted,
@@ -78,6 +63,7 @@ import {ElMessage, ElMessageBox} from "element-plus";
 import ShipFilterCom from "../ship-filter.vue";
 import AisImg from '../AIS.svg'
 import mapboxgl from "mapbox-gl";
+import ShipHover from "./ship-hover.vue";
 
 export default defineComponent({
   name: '',
@@ -115,7 +101,8 @@ export default defineComponent({
         data: {},
         config: {},
         isHistory: false
-      }
+      },
+      staticList: []
     })
     const ref_shipHover = ref()
     const handleShipFilter = ({cql, shipParams}) => {
@@ -178,14 +165,28 @@ export default defineComponent({
         if (state.popupHover) {
           state.popupHover.setLngLat(e.lngLat)
         } else {
+          const p = reactive({
+            that: that,
+            info: state.shipHoverInfo,
+            staticList: state.staticList
+          })
+          const app = createApp(ShipHover, p)
+          // 将 Vue 实例挂载到一个新的 DOM 元素上
+          const vm = app.mount(document.createElement('div'));
+          // 获取包含 Vue 模板的 DOM 元素
+          const contentElement = vm.$el;
+          console.log(ShipHover)
+          console.log(app)
+          console.log(vm)
+          console.log(contentElement)
           state.popupHover = new mapboxgl.Popup({
             className: 'cus',
             maxWidth: 'none',
             closeButton: false,
-            closeOnClick: false,
-            offset: 60
+            closeOnClick: true,
+            offset: 15
           }).setLngLat(e.lngLat)
-          .setDOMContent(document.getElementById('ID_shipHover'))
+          .setDOMContent(contentElement)
           .addTo(props.map);
           state.popupHover.on('close', () => {
             state.popupHover = null
@@ -272,42 +273,63 @@ export default defineComponent({
       })
       props.map.setPaintProperty(state.mapIds.current.layer.ship, 'icon-color', state.shipFilter.config.color)
     }
-    const shipHoverInfoCpt = computed(() => {
-      const arr: any = []
-      const DATA = state.shipHoverInfo.data
-      if (DATA.isHistory) {
-        state.shipHoverInfo?.config?.hover?.forEach(h => {
-          if (h.historyValue) {
-            let value = eval(h.historyValue)
-            h.options?.forEach(v => {
-              if (String(value) == v.value) {
-                value = v.label
-              }
-            })
-            arr.push({
-              label: h.name,
-              value: value
-            })
-          }
-        })
-      } else {
-        state.shipHoverInfo?.config?.hover?.forEach(h => {
-          let value = eval(h.value)
-          h.options?.forEach(v => {
-            if (String(value) == v.value) {
-              value = v.label
+
+    const initStatic = () => {
+      state.staticList = []
+      that.$api.shipTestStaticList().then(res => {
+        if (res.code === 200) {
+          state.staticList = res.data
+          const sId = 'source-static-point'
+          props.map.addSource(sId, {
+            type: 'geojson',
+            data: {
+              type: 'FeatureCollection',
+              features: state.staticList.map(v => {
+                return {
+                  type: 'Feature',
+                  geometry: {
+                    type: 'Point',
+                    coordinates: that.$easyMap.formatPosition.wptTcpt(v.wkt)
+                  },
+                  properties: {
+                    color: v.color,
+                    name: v.name
+                  }
+                }
+              })
             }
           })
-          arr.push({
-            label: h.name,
-            value: value
+          props.map?.addLayer({
+            id: 'layer-static-point-circle',
+            type: "circle",
+            source: sId,
+            paint: {
+              'circle-color': ['get', 'color'],
+              'circle-radius': 10,
+            }
           })
-        })
-      }
-      return arr
-    })
+          props.map?.addLayer({
+            id: 'layer-static-point-text',
+            type: "symbol",
+            source: sId,
+            layout: {
+              'text-allow-overlap': true,
+              'text-field': '{name}',
+              "text-font": ["cus"],
+              'text-offset': [0, -1.5],
+            },
+            paint: {
+              'text-color': '#ffffff',
+              'text-halo-color': '#D26CDB',
+              'text-halo-width': 1
+            }
+          })
+        }
+      })
+    }
     onMounted(() => {
       initMap()
+      initStatic()
     })
     onUnmounted(() => {
     })
@@ -315,7 +337,6 @@ export default defineComponent({
       ...toRefs(state),
       handleShipFilter,
       ref_shipHover,
-      shipHoverInfoCpt
     }
   },
 })

+ 65 - 0
src/views/ship-test/business/v2/popup-style.scss

@@ -0,0 +1,65 @@
+:deep(.hover-info) {
+  $footH: 10px;
+  width: 300px;
+  background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
+  border-radius: 0px 4px 4px 4px;
+  position: relative;
+  display: flex;
+  justify-content: center;
+  &:after {
+    content: '';
+    position: absolute;
+    bottom: -$footH;
+    border-top: $footH solid #0043C4;
+    border-left: $footH solid transparent;
+    border-right: $footH solid transparent;
+  }
+  .hover-info-head {
+    padding: 0 4px;
+    height: 18px;
+    position: absolute;
+    top: -18px;
+    left: 0;
+    font-size: 12px;
+    font-family: PingFang SC;
+    font-weight: 500;
+    color: #FFFFFF;
+    display: flex;
+    align-items: center;
+    line-height: 8px;
+    background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
+    border-radius: 2px 2px 0 0;/* 设置圆角 */
+    >img {
+      margin: 0 4px 0 6px;
+    }
+  }
+  .hover-info-close {
+    position: absolute;
+    right: 0;
+    top: -16px;
+  }
+  .hover-main {
+    width: 100%;
+    height: auto;
+    padding: 10px;
+    .hover-item {
+      display: flex;
+      .hover-item-label {
+        min-width: 42px;
+        font-size: 14px;
+        font-family: PingFang SC;
+        font-weight: 600;
+        color: #08FFFF;
+        line-height: 20px;
+      }
+      .hover-item-value {
+        flex: 1;
+        font-size: 14px;
+        font-family: PingFang SC;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 20px;
+      }
+    }
+  }
+}

+ 173 - 0
src/views/ship-test/business/v2/ship-hover.vue

@@ -0,0 +1,173 @@
+<template>
+  <div class="hover-info" id="ID_shipHover" ref="ref_shipHover">
+    <div class="hover-info-head">
+      <span>{{info?.config?.name}}_{{ info?.isHistory ? '历史' : '实时'}}</span>
+    </div>
+    <div class="hover-info-close __hover" @click="null">
+      <img src="@/components/easyMap/images/close.png" alt=""/>
+    </div>
+    <div class="hover-main" v-if="info?.data">
+      <template v-for="item in shipHoverInfoCpt">
+        <div class="hover-item">
+          <div class="hover-item-label">{{item.label}}:</div>
+          <div class="hover-item-value">{{item.value}}</div>
+        </div>
+      </template>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import * as turf from "@turf/turf";
+
+export default defineComponent({
+  name: '',
+  components: {},
+  props: {
+    that: <any>{},
+    info: <any>{},
+    staticList: {
+      default: () => []
+    }
+  },
+  setup(props, {emit}) {
+    const state = reactive({})
+    const STATIC = (id) => {
+      if (id) {
+        return props.staticList.filter(v => id == v.id)?.[0].wkt
+      }
+      return null
+    }
+    const DISTANCE = (p1, p2) => {
+      if (p1 && p2) {
+        return turf.distance(props.that.$easyMap.formatPosition.wptTcpt(p1), props.that.$easyMap.formatPosition.wptTcpt(p2), {units: 'kilometers'}).toFixed(2) + 'km'
+      }
+      return null
+    }
+    const shipHoverInfoCpt = computed(() => {
+      const arr: any = []
+      const DATA = props.info.data
+      if (DATA.isHistory) {
+        props.info?.config?.hover?.forEach(h => {
+          if (h.historyValue) {
+            let value = eval(h.historyValue)
+            h.options?.forEach(v => {
+              if (String(value) == v.value) {
+                value = v.label
+              }
+            })
+            arr.push({
+              label: h.name,
+              value: value
+            })
+          }
+        })
+      } else {
+        props.info?.config?.hover?.forEach(h => {
+          let value = eval(h.value)
+          h.options?.forEach(v => {
+            if (String(value) == v.value) {
+              value = v.label
+            }
+          })
+          arr.push({
+            label: h.name,
+            value: value
+          })
+        })
+      }
+      return arr
+    })
+    onMounted(() => {
+      // eval注册函数动态方法,不调用一下的话打包不包含
+      DISTANCE(null, null)
+      STATIC(null)
+    })
+    return {
+      ...toRefs(state),
+      shipHoverInfoCpt
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+.hover-info {
+  $footH: 10px;
+  width: 300px;
+  background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
+  border-radius: 0px 4px 4px 4px;
+  position: relative;
+  display: flex;
+  justify-content: center;
+  &:after {
+    content: '';
+    position: absolute;
+    bottom: -$footH;
+    border-top: $footH solid #0043C4;
+    border-left: $footH solid transparent;
+    border-right: $footH solid transparent;
+  }
+  .hover-info-head {
+    padding: 0 4px;
+    height: 18px;
+    position: absolute;
+    top: -18px;
+    left: 0;
+    font-size: 12px;
+    font-family: PingFang SC;
+    font-weight: 500;
+    color: #FFFFFF;
+    display: flex;
+    align-items: center;
+    line-height: 8px;
+    background: linear-gradient(180deg, #3874C9 0%, #0043C4 100%);
+    border-radius: 2px 2px 0 0;/* 设置圆角 */
+    >img {
+      margin: 0 4px 0 6px;
+    }
+  }
+  .hover-info-close {
+    position: absolute;
+    right: 0;
+    top: -16px;
+  }
+  .hover-main {
+    width: 100%;
+    height: auto;
+    padding: 10px;
+    .hover-item {
+      display: flex;
+      .hover-item-label {
+        min-width: 42px;
+        font-size: 14px;
+        font-family: PingFang SC;
+        font-weight: 600;
+        color: #08FFFF;
+        line-height: 20px;
+      }
+      .hover-item-value {
+        flex: 1;
+        font-size: 14px;
+        font-family: PingFang SC;
+        font-weight: 400;
+        color: #FFFFFF;
+        line-height: 20px;
+      }
+    }
+  }
+}
+
+</style>

+ 1 - 1
src/views/ship-test/index.vue

@@ -55,7 +55,7 @@ export default defineComponent({
     const state = reactive({
       map: <any>null,
       mapFunc: <any>null,
-      version: 'v1'
+      version: 'v2'
     })
     const mapLoad = (map, func) => {
       state.map = map