Bläddra i källkod

定点分析增加地址、经纬度选点功能

Hwf 1 månad sedan
förälder
incheckning
8d1ddb5f5d
1 ändrade filer med 128 tillägg och 16 borttagningar
  1. 128 16
      src/views/globalMap/RightMenu/FixedPointAnalysis.vue

+ 128 - 16
src/views/globalMap/RightMenu/FixedPointAnalysis.vue

@@ -1,20 +1,34 @@
 <template>
   <div class="menu-content">
-    <div class="gradient-text common-dialog-title2">定点分析</div>
+    <div class="gradient-text title">定点分析</div>
     <div class="scroll-box">
-      <div v-if="!tempState.address" class="search-box">
-        <div class="text-box">
+      <div class="search-box">
+        <di class="text-box">
           <i class="icon-position2" />
-          <div class="text1" :title="selectData.event_title">{{ selectData.event_title }}</div>
-        </div>
-        <div class="common-btn-primary3" @click="toSelect">定点选取</div>
+          <div class="text1" :title="tempState.address ? tempState.address : selectData.event_title">
+            {{ tempState.address ? tempState.address : selectData.event_title }}
+          </div>
+        </di>
+        <div v-if="tempState.address" class="common-btn-primary4" @click="confirmSelect">确定定位</div>
       </div>
-      <div v-else class="search-box">
-        <div class="text-box">
-          <i class="icon-position2" />
-          <div class="text1" :title="tempState.address">{{ tempState.address }}</div>
+      <div ref="inputRef" class="search-item" style="position: relative">
+        <el-input v-model="inputText" class="custom-input2" placeholder="请输入地址或经纬度后回车搜索" @keyup.enter="handleSearch" />
+        <div v-if="searchPop" class="scroll_box">
+          <div style="height: 60px; line-height: 60px">
+            <span style="font-weight: bold">搜索结果列表</span>
+            <i class="el-icon-close" style="float: right; font-size: 20px; cursor: pointer" @click="closeSearchList()" />
+          </div>
+          <el-scrollbar class="scroll" style="height: 350px">
+            <div v-for="(item, index) in searchList" v-show="searchList.length" :key="index" class="item" @click="handleSearchSelect(item)">
+              <div>
+                <div class="text">{{ item.name }}</div>
+                <div>{{ item.address }}</div>
+              </div>
+            </div>
+            <div v-show="!searchList.length" class="empty" style="text-align: center">没有搜索到内容</div>
+          </el-scrollbar>
         </div>
-        <div class="common-btn-primary4" @click="confirmSelect">确定定位</div>
+        <div class="common-btn-primary4" @click="toSelect">地图选取</div>
       </div>
       <div class="search-item">
         <div class="text1">选择救灾资源:</div>
@@ -45,12 +59,12 @@
         </div>
         <div class="list-content">
-          <div v-for="(item, index) in dataList" :key="index" class="list-item">
+          <div v-for="(item, index) in dataList" :key="index" class="list-item" @click="handleRoutes(item)">
             <div class="text-box2">
               <div class="text2">{{ item.name }}</div>
               <div class="text3">{{ item.address }}</div>
             </div>
-            <div class="operate" @click="handleRoutes(item)">
+            <div class="operate">
               <i class="icon2" />
               路线
             </div>
@@ -73,7 +87,7 @@
           >
             <div class="text-box1">
               <div :class="'tag tag' + index">{{ getTag(index) }}</div>
-<!--              <div class="text1">{{ item.strategy }}</div>-->
+              <!--              <div class="text1">{{ item.strategy }}</div>-->
             </div>
             <div class="route-info">
               <div class="text-box2">
@@ -111,6 +125,7 @@ import useMapStore from '@/store/modules/map';
 import markImg from '@/assets/images/map/mark.png';
 import startImg from '@/assets/images/map/start.png';
 import endImg from '@/assets/images/map/end.png';
+import { onClickOutside } from '@vueuse/core';
 
 interface Props {
   location?: string | number[];
@@ -122,6 +137,7 @@ const getMap = inject('getMap');
 const getMapUtils = inject('getMapUtils');
 const mapStore = useMapStore();
 const amapKey = 'e45d4caa2bef3c84714a2ed9b1e27d98';
+let inputRef = ref();
 let showAddress = ref(true);
 let routeData = ref([]);
 let routeLine, startMarker, endMarker;
@@ -145,8 +161,11 @@ let queryParams = reactive({
   keyword: '',
   dataType: '2'
 });
+let inputText = ref('');
 let total = ref(0);
 let dataList = ref([]);
+let searchList = ref([]);
+let searchPop = ref(false);
 watch(
   () => mapStore.mapLoaded,
   (loaded) => {
@@ -159,6 +178,10 @@ watch(
     immediate: true
   }
 );
+onClickOutside(inputRef, (event) => {
+  searchPop.value = false;
+  searchList.value = [];
+});
 const toSelect = () => {
   map.on('click', handleClickMap);
   mapStore.setIsMapSelect(true);
@@ -463,6 +486,61 @@ const clearLine = () => {
     }
   }
 };
+// 搜索地址或者经纬度
+const handleSearch = () => {
+  const value = inputText.value.trim();
+  // 1. 检测是否为经纬度格式
+  const isCoordinate = /^\s*[-+]?\d{1,3}(\.\d+)?\s*[,,]\s*[-+]?\d{1,3}(\.\d+)?\s*$/.test(value);
+
+  if (isCoordinate) {
+    // 2. 分割并验证经纬度范围
+    const parts = value.split(/[,,]/);
+    if (parts.length !== 2) {
+      handleAddress(value);
+      return;
+    }
+
+    const lng = parseFloat(parts[0]);
+    const lat = parseFloat(parts[1]);
+
+    if (lng < -180 || lng > 180 || lat < -90 || lat > 90) {
+      proxy.$modal.msgError('请输入合法的坐标');
+      return;
+    }
+
+    handleCoordinate([lng, lat]); // 处理经纬度逻辑
+  } else {
+    handleAddress(value); // 处理地址逻辑
+  }
+};
+const handleCoordinate = (lnglat) => {
+  const newMap = mapStore.isAMap ? map : map.getView();
+  newMap.setCenter(lnglat);
+  getAddress(lnglat);
+};
+
+const handleAddress = async (value) => {
+  const url = `https://restapi.amap.com/v5/place/text?key=${amapKey}&keywords=${value}`;
+  const response = await fetch(url);
+  const result = await response.json();
+  searchList.value = result.pois;
+  searchPop.value = true;
+};
+
+const handleSearchSelect = (item) => {
+  const newMap = mapStore.isAMap ? map : map.getView();
+  const location = item.location.split(',');
+  newMap.setCenter(location);
+  const gcj02Coord = gcoord.transform(location, gcoord.WGS84, gcoord.GCJ02);
+  createMarks({ longitude: gcj02Coord[0], latitude: gcj02Coord[1] }, true);
+  tempState.address = item.address;
+};
+
+const closeSearchList = () => {
+  searchPop.value = false;
+  searchList.value = [];
+};
+
 onMounted(() => {
   if (mapStore.isAMap) {
     AMap = mapUtils.getAMap();
@@ -489,7 +567,7 @@ onMounted(() => {
   }
   .search-box {
     width: 100%;
-    height: 150px;
+    height: 75px;
     background: url('@/assets/images/electronicDisasterMapManage/box6.png') no-repeat;
     background-size: 100% 100%;
     padding: 0 10px 0 30px;
@@ -576,7 +654,7 @@ onMounted(() => {
       }
     }
     .list-content {
-      height: 210px;
+      height: 350px;
       overflow-y: auto;
       .list-item {
         display: flex;
@@ -736,4 +814,38 @@ onMounted(() => {
     }
   }
 }
+.scroll_box {
+  width: calc(100% - 105px);
+  background: #0a2c5c;
+  position: absolute;
+  left: 0;
+  top: 45px;
+  z-index: 9;
+  padding: 10px;
+  border-radius: 3px;
+  .close {
+    position: absolute;
+    right: 10px;
+    top: 10px;
+    cursor: pointer;
+    font-size: 14px;
+  }
+}
+.scroll {
+  width: 100%;
+  .item {
+    display: flex;
+    font-size: 14px;
+    cursor: pointer;
+    padding: 8px;
+    border-bottom: 1px solid #4574d5;
+    &:hover {
+      background-color: #102e76;
+    }
+    .text {
+      font-size: 16px;
+      margin-bottom: 6px;
+    }
+  }
+}
 </style>