소스 검색

重构地图选点,组件化

yukai 1 년 전
부모
커밋
edf3952a3f
2개의 변경된 파일148개의 추가작업 그리고 21개의 파일을 삭제
  1. 26 21
      src/views/iot/device/instance/component/edit.vue
  2. 122 0
      src/views/iot/device/instance/component/map.vue

+ 26 - 21
src/views/iot/device/instance/component/edit.vue

@@ -13,9 +13,14 @@
             <el-option v-for="item in productData" :key="item.id" :label="item.name" :value="item.id" />
           </el-select>
         </el-form-item>
-        <el-form-item label="设备坐标" prop="lng">
+        <!-- <el-form-item label="设备坐标" prop="lng">
           <el-input :value="ruleForm.lng ? (ruleForm.lng + ' , ' + ruleForm.lat) : ''" placeholder="选择设备坐标" @click="selectPosition" read-only />
+        </el-form-item> -->
+
+        <el-form-item label="设备坐标" prop="lng">
+          <el-input :value="ruleForm.lng ? (ruleForm.lng + ' , ' + ruleForm.lat) : ''" placeholder="选择设备坐标" @click="selectMap" read-only />
         </el-form-item>
+
         <el-form-item label="标签设置" prop="lng">
           <div class="tags-wrapper">
             <el-button type="primary" size="small" @click="toAddTag">添加标签</el-button>
@@ -69,10 +74,8 @@
         </span>
       </template>
     </el-dialog>
-    <el-dialog title="地图选点(点击地图即可)" v-model="mapVisible" width="1000px" append-to-body>
-      <div class="map" id="map-container-conpany" style="height: 65vh"></div>
-    </el-dialog>
     <tagVue ref="tagRef"></tagVue>
+    <Map ref="mapRef" @updateMap="updateMap"></Map>
   </div>
 </template>
 
@@ -81,6 +84,7 @@ import { reactive, toRefs, defineComponent, ref, unref, nextTick } from 'vue';
 import api from '/@/api/device';
 import { ElMessage } from "element-plus";
 import tagVue from './tag.vue'
+import Map from './map.vue'
 import certApi from '/@/api/certificateManagement';
 
 interface RuleFormState {
@@ -134,11 +138,12 @@ export default defineComponent({
   name: 'deviceEditPro',
   components: {
     tagVue,
+    Map,
   },
   setup(prop, { emit }) {
     const formRef = ref<HTMLElement | null>(null);
     const tagRef = ref<HTMLElement | null>(null);
-    const mapVisible = ref(false);
+    const mapRef = ref();
     const certList = ref([])
     const state = reactive<DicState>({
       isShowDialog: false,
@@ -157,6 +162,11 @@ export default defineComponent({
         productId: [{ required: true, message: '所属产品不能为空', trigger: 'blur' }],
       }
     });
+
+    //地图选点
+    const selectMap=()=>{
+      mapRef.value.openDialog();
+    }
     // 打开弹窗
     const openDialog = (row: RuleFormState | null) => {
       resetForm();
@@ -228,20 +238,7 @@ export default defineComponent({
     function delTagRow(i: number) {
       state.ruleForm.tags.splice(i, 1)
     }
-    function selectPosition() {
-      mapVisible.value = true;
-      nextTick(() => {
-        var map = new BMapGL.Map("map-container-conpany");
-        map.centerAndZoom("沈阳市", 8);
-        map.enableScrollWheelZoom(true);
-        map.addEventListener("click", (e) => {
-          // console.log("点击位置经纬度:" + e.latlng.lng + "," + e.latlng.lat);
-          state.ruleForm.lng = e.latlng.lng.toFixed(5);
-          state.ruleForm.lat = e.latlng.lat.toFixed(5);
-          mapVisible.value = false;
-        });
-      });
-    }
+
     // 所属产品变化的时候,更新产品详情
     const productIdChange = (productId: number) => {
       api.product.detail(productId).then((res: any) => {
@@ -255,15 +252,23 @@ export default defineComponent({
       })
     }
 
+    //回调地图选点
+    const updateMap=(data:any)=>{
+      console.log(data);
+      state.ruleForm.lng = data.lng;
+      state.ruleForm.lat = data.lat;
+    }
+
     return {
       certList,
       productIdChange,
       tagRef,
+      selectMap,
+      mapRef,
+      updateMap,
       delTagRow,
       toAddTag,
       addTag,
-      mapVisible,
-      selectPosition,
       openDialog,
       closeDialog,
       onCancel,

+ 122 - 0
src/views/iot/device/instance/component/map.vue

@@ -0,0 +1,122 @@
+<template>
+    <div>
+      <el-dialog title="地图选点" v-model="isShowDialog" width="900px" append-to-body>
+        <div class="map-container">
+          <div class="coordinate-search">
+            <el-input v-model="lng" placeholder="经度" />
+            <div>-</div>
+            <el-input v-model="lat" placeholder="纬度" />
+            <el-button @click="searchByCoordinate" type="primary">搜索</el-button>
+          </div>
+          <div class="map" ref="mapContainer"></div>
+          <!-- 地址解析结果 -->
+          <div class="address-result" v-if="address">
+            解析到地址:{{ address }}
+            <el-button @click="confirmAddress" style="margin-left: 10px;" type="success">确认地址</el-button>
+          </div>
+        </div>
+      </el-dialog>
+    </div>
+  </template>
+  
+  <script lang="ts" setup>
+  import { defineEmits, defineExpose, nextTick, ref } from 'vue';
+  
+  const mapContainer = ref<HTMLElement | null>(null);
+  const address = ref('');
+  const lng = ref('');
+  const lat = ref('');
+  const isShowDialog = ref(false);
+  const marker = ref<BMapGL.Marker | null>(null);
+  let map: BMapGL.Map | null = null;
+  
+  const openDialog = () => {
+    isShowDialog.value = true;
+  
+    nextTick(() => {
+      map = new BMapGL.Map(mapContainer.value!);
+      map.centerAndZoom("沈阳市", 10);
+      map.enableScrollWheelZoom(true);
+  
+      searchByCoordinate();
+  
+      map.addEventListener("click", (e: any) => {
+        lng.value = e.latlng.lng.toFixed(5);
+        lat.value = e.latlng.lat.toFixed(5);
+        setMarker(lng.value, lat.value);
+        setAddressByCoordinate(lng.value, lat.value);
+      });
+    });
+  };
+  
+  const confirmAddress = () => {
+    isShowDialog.value = false;
+    emit('updateMap', { lng: lng.value, lat: lat.value });
+  };
+  
+  const setMarker = (lng: string, lat: string) => {
+    // 删除之前的标记
+    if (marker.value) {
+      map?.removeOverlay(marker.value);
+    }
+    // 创建新的标记
+    const point = new BMapGL.Point(lng, lat);
+    marker.value = new BMapGL.Marker(point);
+    map?.addOverlay(marker.value);
+    // 移动地图中心到选点位置
+    map?.panTo(point);
+  };
+  
+  const setAddressByCoordinate = (lng: string | number, lat: string | number) => {
+    const point = new BMapGL.Point(lng, lat);
+    const geocoder = new BMapGL.Geocoder();
+    geocoder.getLocation(point, (result: any) => {
+      if (result) {
+        const formattedAddress = result.address;
+        address.value = formattedAddress;
+      }
+    });
+  };
+  
+  const searchByCoordinate = () => {
+    if (lng.value && lat.value) {
+      setMarker(lng.value, lat.value);
+      setAddressByCoordinate(lng.value, lat.value);
+    }
+  };
+  
+  const emit = defineEmits(['updateMap']);
+  
+  defineExpose({ openDialog });
+  </script>
+  
+  <style scoped>
+  .map-container {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+  }
+  
+  .map {
+    width: 100%;
+    height: 50vh;
+  }
+  
+  .coordinate-search {
+    display: flex;
+    margin-bottom: 20px;
+  }
+  
+  .coordinate-search > div {
+    margin-right: 10px;
+  }
+  
+  .coordinate-search input {
+    margin-right: 10px;
+    width: 100px;
+  }
+  
+  .address-result {
+    margin-top: 20px;
+  }
+  </style>