CzRger před 4 dny
rodič
revize
90b192b70a

Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 19 - 0
src/assets/images/web/map-warning-icon-blue.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 16 - 0
src/assets/images/web/map-warning-icon-red.svg


Rozdílová data souboru nebyla zobrazena, protože soubor je příliš velký
+ 19 - 0
src/assets/images/web/map-warning-icon-yellow.svg


+ 10 - 0
src/assets/svg/track.svg

@@ -0,0 +1,10 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
+        "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg t="1736929441944" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4251"
+     xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200">
+    <path d="M816 624h-1 1zM1024 992c0 17.7-14.3 32-32 32H240.3v-0.6l-0.3 0.6h-1c-35.9 0-69.8-14-95.6-39.5-26-25.9-40.4-60.1-40.4-96.5s14.4-70.6 40.4-96.5c26-25.8 60.3-39.8 96.6-39.5h575c17.3 0 32-14.7 32-32 0-17.4-14.7-32-32-32H432l48-64h336c52.5 0.5 95 43.4 95 96s-42.5 95.5-95 96H239c-18.9 0-36.9 7.4-50.5 21-13.8 13.7-21.5 31.8-21.5 51s7.6 37.3 21.5 51c13.7 13.6 31.6 21 50.5 21h0.7l0.3 0.6v-0.6h752c17.7 0 32 14.3 32 32z"
+          p-id="4252"></path>
+    <path d="M240.3 1024h-0.3l0.3-0.6zM816 816h-1 1z" p-id="4253"></path>
+    <path d="M288.3 0.4C129.5 0.4 0.7 129.3 0.7 288.1c0 63.1 20.4 121.5 55 169.2l232.6 312.3 227.3-305.3c37.7-48.8 60.4-109.6 60.4-176.1C576 129.3 447.2 0.4 288.3 0.4z m-0.3 371.4c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"
+          p-id="4254"></path>
+</svg>

+ 35 - 9
src/stores/ship-map/map-style.ts

@@ -2,15 +2,18 @@ import * as style from 'ol/style'
 import * as geom from 'ol/geom'
 import * as extent from "ol/extent";
 
-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'
-import FIXED from './/ship-type/FIXED.svg'
+import MapWarningIconRed from "@/assets/images/web/map-warning-icon-red.svg";
+import MapWarningIconYellow from "@/assets/images/web/map-warning-icon-yellow.svg";
+import MapWarningIconBlue from "@/assets/images/web/map-warning-icon-blue.svg";
+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'
+import FIXED from './ship-type/FIXED.svg'
 const shipIcon = {
     AIS, AIS_BEIDOU, AIS_BEIDOU_RADAR, AIS_RADAR, BEIDOU, BEIDOU_RADAR, OTHER, RADAR, FIXED
 }
@@ -202,8 +205,31 @@ const trackPointNormalStyle = (color) => {
     }))
     return _style
 }
+
+const warningStyle = (level) => {
+    let icon = MapWarningIconBlue;
+    switch (warningStyle) {
+        case 1: {icon = MapWarningIconRed}
+            break;
+        case 2: {icon = MapWarningIconYellow}
+            break;
+        case 3: {icon = MapWarningIconBlue}
+            break;
+    }
+    return new style.Style({
+        image: new style.Icon({
+            src: icon,
+            scale: 2,
+            anchor: [0.5, 0],
+            anchorOrigin: 'bottom-left',
+            anchorXUnits: 'fraction', // 定位点的单位
+            anchorYUnits: 'fraction',
+        }),
+    })
+}
 export default {
     ShipNormalStyle,
     trackStyle,
     trackPointNormalStyle,
+    warningStyle,
 }

+ 52 - 75
src/stores/ship-map/ship-map.ts

@@ -28,32 +28,6 @@ export const useShipMapStore = defineStore('shipMap', () => {
     },
     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,
-    //   }
-    // }]]
     trackKeys: {
       lon: 'targetLongitude',
       lat: 'targetLatitude',
@@ -119,12 +93,14 @@ export const useShipMapStore = defineStore('shipMap', () => {
   const clickShip = (feature) => {
     if (feature && feature.get('_featureType') == 'ship') {
       if (!state.trackMap.has(feature.get('_id'))) {
+        const isWarning = feature.get('_warning')
         const d = feature.get('_data')
         state.trackMap.set(feature.get('_id'), {
+          isWarning: !!isWarning,
           data: feature.get('_data'),
-          color: '#FC60FF', //randomColor(1),
+          color: isWarning ? '#ea3147' : '#FC60FF', //randomColor(1),
           history: [],
-          real: [d],
+          real: isWarning ? [] : [d],
           trackId: feature.get('_trackId'),
           moveToTrack: () => {
             const position: any = []
@@ -133,20 +109,25 @@ export const useShipMapStore = defineStore('shipMap', () => {
             arr.forEach(v => {
               position.push([v[state.trackKeys.lon], v[state.trackKeys.lat]])
             })
-            getShapeView(state.map, position)
+            if (position.length > 0) {
+              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'),
+          warningLayer: 'warningLayer_' + 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.map.removeLayer(state.map.getLayers().getArray().filter(v => v.get('__layerName') === state.trackMap.get(feature.get('_id')).warningLayer)[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)
+            state.map.getLayers().getArray().filter(v => v.get('__layerName') === t.warningLayer)[0]?.setVisible(visible)
             t.showTrack = visible
             if (visible) {
               t.moveToTrack()
@@ -230,16 +211,39 @@ export const useShipMapStore = defineStore('shipMap', () => {
           declutter: true,
           __layerName: state.trackMap.get(feature.get('_id')).pointsLayer
         })
+        const warningLayer = new layer.Vector({
+          zIndex: 3999,
+          __layerName: state.trackMap.get(feature.get('_id')).warningLayer,
+        })
         state.map.addLayer(lineLayer)
         state.map.addLayer(pointsLayer)
+        state.map.addLayer(warningLayer)
+        if (isWarning) {
+          console.log(d)
+          const wf: any = new format.WKT().readFeature(`POINT(${d[state.trackKeys.lon]} ${d[state.trackKeys.lat]})`)
+          wf.setStyle(MapStyle.warningStyle(feature.get('_warning').ruleInfo.level))
+          warningLayer.setSource(new source.Vector({
+            features: [wf],
+            wrapX: false,
+          }))
+        }
         const ws = new WebSocket(`ws://${location.host}/history-track-ws-api/historyshiptrack`)
         ws.onopen = (e) => {
-          const str = {
-            mergeTarget: feature.get('_id'),
-            startTime: YMDHms(new Date(d[state.trackKeys.mergeTime]).getTime() - 1000 * 60 * 60),
-            endTime: YMDHms(d[state.trackKeys.mergeTime]),
+          if (isWarning) {
+            const str = {
+              mergeTarget: feature.get('_data')[state.trackKeys.mergeTarget],
+              startTime: YMDHms(new Date(feature.get('_warning').warnTime).getTime() - 1000 * 60 * 60),
+              endTime: YMDHms(new Date(feature.get('_warning').warnTime).getTime() + 1000 * 60 * 60),
+            }
+            ws.send(JSON.stringify(str))
+          } else {
+            const str = {
+              mergeTarget: feature.get('_id'),
+              startTime: YMDHms(new Date(d[state.trackKeys.mergeTime]).getTime() - 1000 * 60 * 60),
+              endTime: YMDHms(d[state.trackKeys.mergeTime]),
+            }
+            ws.send(JSON.stringify(str))
           }
-          ws.send(JSON.stringify(str))
         }
         ws.onmessage = (e) => {
           try {
@@ -249,6 +253,9 @@ export const useShipMapStore = defineStore('shipMap', () => {
             } else if (json?.length > 0) {
               state.trackMap.get(feature.get('_id')).history.push(...json)
               state.trackMap.get(feature.get('_id')).refreshTrackStyle()
+              if (isWarning) {
+                state.trackMap.get(feature.get('_id')).moveToTrack()
+              }
             }
           } catch (e) {
           }
@@ -324,7 +331,9 @@ export const useShipMapStore = defineStore('shipMap', () => {
     if (state.trackMap.size > 0) {
       let arr = []
       state.trackMap.forEach((v, k) => {
-        arr.push(`'${k}'`)
+        if (!v.isWarning) {
+          arr.push(`'${k}'`)
+        }
       })
       idCql = `${state.trackKeys.mergeTarget} in (${arr.join(',')})`
     }
@@ -396,7 +405,7 @@ export const useShipMapStore = defineStore('shipMap', () => {
     });
     state.ws.layerShip.setSource(vectorSource)
   }
-  const initShipFeature = (data) => {
+  const initShipFeature = (data, warning = null) => {
     const feat: any = new format.WKT().readFeature(`POINT(${data[state.trackKeys.lon]} ${data[state.trackKeys.lat]})`)
     feat.set('_course', data[state.trackKeys.course] || 0)
     feat.set('_speed', data[state.trackKeys.speed] || 0)
@@ -406,47 +415,13 @@ export const useShipMapStore = defineStore('shipMap', () => {
     feat.set('_trackId', data[state.trackKeys.mergeId])
     feat.set('_data', data)
     feat.set('_featureType', 'ship')
+    if (warning) {
+      feat.set('_id', warning.id + '_' + data[state.trackKeys.mergeTarget])
+      feat.set('_warning', warning)
+    }
     return feat
   }
   const initWarningWS = () => {
-    // const js = {
-    //   "createBy" : "admin",
-    //   "createTime" : "2025-01-14 11:19:26",
-    //   "updateBy" : "admin",
-    //   "updateTime" : "2025-01-14 11:19:26",
-    //   "id" : "0b3bae57-c422-4b5e-a700-860e346755b1",
-    //   "modelCode" : "TJ_CB_00_01",
-    //   "modelId" : "1",
-    //   "ruleId" : "d4dde331749847618f163e6a0c25472d",
-    //   "ruleName" : "北斗终端异常-10分钟",
-    //   "modelName" : "北斗终端异常",
-    //   "warnTime" : "2025-01-14 11:10:18.464",
-    //   "dynamicShipList" : [ {
-    //     "mergeId" : "814640307768528896",
-    //     "mergeTarget" : "100000000015005642",
-    //     "mergeTime" : "2025-01-14 11:00:18.176",
-    //     "mergeType" : "BEIDOU",
-    //     "targetName" : "万0308014",
-    //     "targetShipType" : "30",
-    //     "targetNationality" : "412",
-    //     "targetSpeed" : 0.0,
-    //     "targetCourse" : 0.0,
-    //     "targetLongitude" : 110.390722,
-    //     "targetLatitude" : 18.704444,
-    //     "targetLength" : 13.7,
-    //     "targetSource" : [ {
-    //       "id" : "1724073477",
-    //       "time" : "2025-01-14 11:00:14",
-    //       "type" : "BEIDOU",
-    //       "signalLoss" : false,
-    //       "trackDeviceNo" : "15005642",
-    //       "trackId" : "15005642"
-    //     } ]
-    //   } ]
-    // }
-    // setTimeout(() => {
-    //   state.warningInfo = js
-    // }, 1000)
     const ws = new WebSocket(`ws://${location.host}/ws-api/shipwarnrecord`)
     ws.onopen = (e) => {
     }
@@ -497,6 +472,8 @@ export const useShipMapStore = defineStore('shipMap', () => {
   return {
     ...toRefs(state),
     initMap,
-    toShip
+    toShip,
+    clickShip,
+    initShipFeature
   }
 })

+ 0 - 7
src/views/web/config/rule-detail.vue

@@ -277,13 +277,6 @@ const onAreaMap = (areas) => {
   state.areaMap.show = true
 }
 onMounted(() => {
-  warnAreaQueryAll().then(res => {
-    DictionaryStore.initOtherDict('warningArea', res.data.map(v => {
-      v.dictLabel = v.name
-      v.dictValue = v.id
-      return v
-    }))
-  })
 })
 const initDictionary = () => {
 }

+ 22 - 2
src/views/web/index.vue

@@ -67,7 +67,7 @@
       </div>
       <configCom ref="ref_config" v-model:show="state.tools.showConfig" :map="state.map" :mapFunc="state.mapFunc"/>
       <archiveCom v-model:show="state.tools.showArchive"/>
-      <warningCom v-model:show="state.tools.showWarning"/>
+      <warningCom v-model:show="state.tools.showWarning" :map="state.map"/>
       <exampleCom v-if="state.mapFunc" v-model:show="state.tools.showExample" :mapHeight="state.mapFunc.mapHeight" :mapWidth="state.mapFunc.mapWidth"/>
       <trackCom v-model:show="state.tools.showTrack"/>
       <searchCom v-model:show="state.tools.showSearch"/>
@@ -88,10 +88,13 @@ import trackCom from './track/index.vue'
 import searchCom from './search/index.vue'
 import exampleCom from './example.vue'
 import trackArchiveCom from './track/archive.vue'
-import {useShipMapStore} from "@/stores";
+import {useDictionaryStore, useShipMapStore} from "@/stores";
 import trackPointCom from './track/track-point.vue'
 import assistantCom from './warning/assistant.vue'
+import {warnModelRuleTree} from "@/api/modules/web/model";
+import {warnAreaQueryAll} from "@/api/modules/web/area";
 
+const DictionaryStore = useDictionaryStore()
 const ShipMapStore = useShipMapStore()
 const {proxy} = getCurrentInstance()
 const state: any = reactive({
@@ -126,6 +129,23 @@ const refreshArea = () => {
 watch(() => ShipMapStore.trackMap, (n) => {
   state.tools.showTrack = n.size > 0
 }, {deep: true})
+
+onMounted(() => {
+  warnModelRuleTree().then(res => {
+    DictionaryStore.initOtherDict('warningModel', res.data.map(v => {
+      v.dictLabel = v.name
+      v.dictValue = v.id
+      return v
+    }))
+  })
+  warnAreaQueryAll().then(res => {
+    DictionaryStore.initOtherDict('warningArea', res.data.map(v => {
+      v.dictLabel = v.name
+      v.dictValue = v.id
+      return v
+    }))
+  })
+})
 </script>
 
 <style lang="scss" scoped>

+ 9 - 4
src/views/web/track/index.vue

@@ -17,7 +17,7 @@
         <template v-for="([key, value], index) in ShipMapStore.trackMap">
           <div class="row" :style="`color: ${value.color};`">
             <div class="index">{{index + 1}}</div>
-            <div class="target __hover" @click="value.moveToTrack(), value.showArchive = true">{{key}}</div>
+            <div class="target __hover" @click="value.moveToTrack(), value.showArchive = true">{{value.isWarning ? value.data[ShipMapStore.trackKeys.mergeTarget] : key}}</div>
             <div class="time">
               {{getDuration(value)}}
             </div>
@@ -69,11 +69,16 @@ const state: any = reactive({
 })
 const getDuration = (value) => {
   let start = null
-  const end = value.real[value.real.length - 1].mergeTime
+  let end = null
   if (value.history.length > 0) {
     start = value.history[0].mergeTime
-  } else if (value.real.length > 0) {
-    start = value.real[0].mergeTime
+    end = value.history[value.history.length - 1].mergeTime
+  }
+  if (value.real.length > 0) {
+    if (!start) {
+      start = value.real[0].mergeTime
+    }
+    end = value.real[value.real.length - 1].mergeTime
   }
   return comTimeByArea(start, end, true)
 }

+ 72 - 15
src/views/web/warning/index.vue

@@ -2,7 +2,7 @@
   <DragWindow
     ref="ref_warning"
     v-if="show"
-    @onClose="$emit('update:show', false)"
+    @onClose="onClose"
     :title="`预警记录(${state.query.result.total}条)`"
     v-model:layout="state.layout"
     close
@@ -30,7 +30,7 @@
             <div class="search-btn __hover" @click="onSearch">搜索</div>
           </template>
         </CusFormColumn>
-        <div class="reset-button __hover" @click="onReset">重置</div>
+        <div class="reset-button __hover" @click="onReset()">重置</div>
         <div class="more-button __hover" @click="onMore">更多</div>
       </CusForm>
 <!--      <div class="new-msg">xx条新预警,点击<span class="__hover">刷新列表</span></div>-->
@@ -41,8 +41,9 @@
               <template v-for="ship in item.dynamicShipList">
                 <div class="target">
                   <SvgIcon name="warning" color="#FF0D0D"/>
-                  {{ ship.targetName || ship.mergeTarget }}
-                  <SvgIcon name="focus" color="#ffffff" class="__hover" style="margin-left: auto"/>
+                  {{ ship[ShipMapStore.trackKeys.targetName] || ship[ShipMapStore.trackKeys.mergeTarget] }}
+                  <SvgIcon name="track" color="#ffffff" class="__hover" style="margin-left: auto" @click="toTrack(ship, item)"/>
+                  <SvgIcon name="focus" color="#ffffff" class="__hover" style="margin-left: 10px;" @click="ShipMapStore.toShip(ship[ShipMapStore.trackKeys.mergeTarget])"/>
                 </div>
               </template>
               <div class="info">
@@ -52,7 +53,7 @@
                 <div class="info-detail">
                   <div class="info-item">预警名称:<div>{{item.ruleName}}</div></div>
                   <div class="info-item">预警时间:<div>{{$util.YMDHms(item.warnTime)}}</div></div>
-                  <div class="info-item">预警区域:<div>{{item.areaName}}</div><span class="__hover" style="color: #1CFEFF; margin-left: 10px;margin-right: 10px;"><SvgIcon name="eye" color="#ffffff"/></span></div>
+                  <div class="info-item">预警区域:<div>{{item.areaName}}</div><span class="__hover" style="color: #1CFEFF; margin-left: 10px;margin-right: 10px;"><SvgIcon name="eye" color="#ffffff" @click="toArea(item)"/></span></div>
                 </div>
               </div>
             </div>
@@ -137,7 +138,7 @@
         </CusForm>
       </div>
       <div class="more-buttons">
-        <div class="cancel __hover" @click="onReset">重置</div>
+        <div class="cancel __hover" @click="onReset()">重置</div>
         <div class="submit __hover" @click="onSearch">搜索</div>
       </div>
     </div>
@@ -145,13 +146,20 @@
 </template>
 
 <script setup lang="ts">
-import {computed, getCurrentInstance, markRaw, onMounted, reactive, ref, watch} from "vue";
+import {computed, getCurrentInstance, markRaw, nextTick, onMounted, reactive, ref, watch} from "vue";
 import DragWindow from '../components/drag-window.vue'
 import {warnModelRuleTree} from "@/api/modules/web/model";
 import {useDictionaryStore, useShipMapStore} from "@/stores";
 import {warnRecordList} from "@/api/modules/web/record";
 import {ElMessage} from "element-plus";
 import {YMD, YMDHms} from "@/utils/util";
+import {warnAreaQueryAll} from "@/api/modules/web/area";
+import * as layer from "ol/layer";
+import * as style from "ol/style";
+import * as format from "ol/format";
+import * as source from "ol/source";
+import {getShapeView} from "@/utils/easyMap";
+import {warnRuleDetail} from "@/api/modules/web/rule";
 
 const emit = defineEmits(['update:show'])
 
@@ -160,7 +168,7 @@ const ShipMapStore = useShipMapStore()
 const {proxy} = getCurrentInstance()
 const props = defineProps({
   show: {},
-  mapFunc: {}
+  map: {}
 })
 const state: any = reactive({
   layout: {
@@ -190,12 +198,36 @@ const state: any = reactive({
       left: 585,
       top: 110
     }
+  },
+  layers: {
+    area: null,
   }
 })
 const ref_warning = ref()
 watch(() => props.show, (n) => {
   if (n) {
     onSearch()
+    if (!state.layers.area) {
+      state.layers.area = new layer.Vector({
+        zIndex: 3000,
+        source: new source.Vector({
+          features: [],
+          wrapX: false
+        }),
+        style: (f) => {
+          return new style.Style({
+            stroke: new style.Stroke({
+              color: f.get("__data")?.lineColor,
+              width: f.get("__data")?.lineWidth,
+            }),
+            fill: new style.Fill({
+              color: f.get("__data")?.fillColor,
+            }),
+          })
+        }
+      });
+      props.map.addLayer(state.layers.area)
+    }
   }
 })
 const onPage = (pageNum, pageSize) => {
@@ -256,6 +288,38 @@ const onMore = () => {
   state.more.layout.left = state.layout.width + state.layout.left + 20
   state.more.show = true
 }
+const toArea = (row) => {
+  const s = state.layers.area.getSource()
+  const id = row.areaId || 'f7a4952b076a4079aff40ec8cc143035'
+  if (s.getFeatureById(id)) {
+    s.removeFeature(s.getFeatureById(id))
+  } else {
+    const area = DictionaryStore.warningAreaObjMap.get(id)
+    const feat: any = new format.WKT().readFeature(area.location)
+    feat.setId(id)
+    feat.set('__data', area)
+    s.addFeature(feat)
+    getShapeView(props.map, feat.getGeometry().getCoordinates()[0])
+  }
+}
+const toTrack = (ship, warning) => {
+  const id = warning.id + '_' + ship[ShipMapStore.trackKeys.mergeTarget]
+  if (ShipMapStore.trackMap.has(id)) {
+    ShipMapStore.trackMap.get(id).moveToTrack()
+  } else {
+    warnRuleDetail(proxy.$util.formatGetParam({id: warning.ruleId})).then(res => {
+      if (res.code == 0) {
+        ShipMapStore.clickShip(ShipMapStore.initShipFeature(ship, {...warning, ruleInfo: res.data}))
+      } else {
+        ElMessage.error(res.msg)
+      }
+    })
+  }
+}
+const onClose = () => {
+  emit('update:show', false)
+  state.layers.area.getSource().clear()
+}
 watch(() => ShipMapStore.warningParams, (n) => {
   if (n) {
     onReset(false)
@@ -270,13 +334,6 @@ watch(() => ShipMapStore.warningParams, (n) => {
 })
 onMounted(() => {
   onReset()
-  warnModelRuleTree().then(res => {
-    DictionaryStore.initOtherDict('warningModel', res.data.map(v => {
-      v.dictLabel = v.name
-      v.dictValue = v.id
-      return v
-    }))
-  })
 })
 </script>