Jelajahi Sumber

feat: coordinate picker

Casper Dai 2 tahun lalu
induk
melakukan
ca324af5a3

+ 137 - 0
src/components/dialog/CoordinateDialog/bak.vue

@@ -0,0 +1,137 @@
+<template>
+  <confirm-dialog
+    ref="confirmDialg"
+    title="坐标拾取"
+    v-bind="$attrs"
+    @confirm="onConfirm"
+  >
+    <div class="c-grid-form u-align-self--center">
+      <span class="c-grid-form__label">来源</span>
+      <schema-select
+        v-model="info.type"
+        :schema="typeSelectSchema"
+      />
+      <span class="c-grid-form__label" />
+      <div class="c-grid-form__option">
+        <div class="l-flex--row c-sibling-item--v">
+          <span class="c-sibling-item c-grid-form__label u-required">经度</span>
+          <el-input
+            v-model.trim="info.longitude"
+            class="c-sibling-item u-width--xs"
+            placeholder="-180 ~ +180"
+            maxlength="13"
+          />
+          <span class="c-sibling-item far c-grid-form__label u-required">纬度</span>
+          <el-input
+            v-model.trim="info.latitude"
+            class="c-sibling-item far u-width--xs"
+            placeholder="-90 ~ +90"
+            maxlength="12"
+          />
+        </div>
+        <a
+          class="c-sibling-item--v nearer o-link"
+          href="https://lbs.amap.com/tools/picker"
+          target="_blank"
+        >
+          高德地图拾取器(需登录提升精度)
+        </a>
+        <a
+          class="c-sibling-item--v nearer o-link"
+          href="http://api.map.baidu.com/lbsapi/getpoint/index.html"
+          target="_blank"
+        >
+          百度地图拾取器
+        </a>
+      </div>
+    </div>
+  </confirm-dialog>
+</template>
+
+<script>
+import AMapLoader from '@amap/amap-jsapi-loader'
+
+export default {
+  name: 'CoordinateDialog',
+  data () {
+    return {
+      info: {},
+      typeSelectSchema: {
+        options: [
+          { value: 'gd', label: '高德' },
+          { value: 'baidu', label: '百度' },
+          { value: 'gps', label: 'GPS' }
+        ]
+      }
+    }
+  },
+  methods: {
+    show (data) {
+      this.info = {
+        type: 'gd',
+        longitude: '',
+        latitude: '',
+        ...data
+      }
+      AMapLoader.load({
+        key: process.env.VUE_APP_GAODE_MAP_KEY,
+        version: '2.0',
+        plugins: ['']
+      }).then(AMap => {
+        this.$map = AMap
+      })
+      this.$refs.confirmDialg.show()
+    },
+    onConfirm (done) {
+      if (!this.info.longitude) {
+        this.$message({
+          type: 'warning',
+          message: '请填写经度'
+        })
+        return
+      }
+      if (!this.info.latitude) {
+        this.$message({
+          type: 'warning',
+          message: '请填写纬度'
+        })
+        return
+      }
+      if (this.info.type === 'gd') {
+        this.$emit('confirm', {
+          value: {
+            longitude: this.info.longitude,
+            latitude: this.info.latitude
+          },
+          done
+        })
+      } else {
+        if (!this.$map) {
+          this.$message({
+            type: 'warning',
+            message: '转换坐标失败,请关闭后重试'
+          })
+          return
+        }
+        this.$map.convertFrom([this.info.longitude, this.info.latitude], this.info.type, (status, result) => {
+          console.log('coordinate', result)
+          if (result.info === 'ok') {
+            this.$emit('confirm', {
+              value: {
+                longitude: result.locations[0].lng,
+                latitude: result.locations[0].lat
+              },
+              done
+            })
+          } else {
+            this.$message({
+              type: 'warning',
+              message: '转换坐标失败,请稍后重试'
+            })
+          }
+        })
+      }
+    }
+  }
+}
+</script>

+ 20 - 109
src/components/dialog/CoordinateDialog/index.vue

@@ -2,135 +2,46 @@
   <confirm-dialog
     ref="confirmDialg"
     title="坐标拾取"
-    v-bind="$attrs"
+    size="lg fixed"
     @confirm="onConfirm"
   >
-    <div class="c-grid-form u-align-self--center">
-      <span class="c-grid-form__label">来源</span>
-      <schema-select
-        v-model="info.type"
-        :schema="typeSelectSchema"
+    <template #default>
+      <coordinate-picker
+        ref="picker"
+        class="l-flex__fill"
+        v-bind="info"
       />
-      <span class="c-grid-form__label" />
-      <div class="c-grid-form__option">
-        <div class="l-flex--row c-sibling-item--v">
-          <span class="c-sibling-item c-grid-form__label u-required">经度</span>
-          <el-input
-            v-model.trim="info.longitude"
-            class="c-sibling-item u-width--xs"
-            placeholder="-180 ~ +180"
-            maxlength="13"
-          />
-          <span class="c-sibling-item far c-grid-form__label u-required">纬度</span>
-          <el-input
-            v-model.trim="info.latitude"
-            class="c-sibling-item far u-width--xs"
-            placeholder="-90 ~ +90"
-            maxlength="12"
-          />
-        </div>
-        <a
-          class="c-sibling-item--v nearer o-link"
-          href="https://lbs.amap.com/tools/picker"
-          target="_blank"
-        >
-          高德地图拾取器(需登录提升精度)
-        </a>
-        <a
-          class="c-sibling-item--v nearer o-link"
-          href="http://api.map.baidu.com/lbsapi/getpoint/index.html"
-          target="_blank"
-        >
-          百度地图拾取器
-        </a>
-      </div>
-    </div>
+    </template>
   </confirm-dialog>
 </template>
 
 <script>
-import AMapLoader from '@amap/amap-jsapi-loader'
-
 export default {
   name: 'CoordinateDialog',
   data () {
     return {
-      info: {},
-      typeSelectSchema: {
-        options: [
-          { value: 'gd', label: '高德' },
-          { value: 'baidu', label: '百度' },
-          { value: 'gps', label: 'GPS' }
-        ]
-      }
+      info: {}
     }
   },
   methods: {
     show (data) {
       this.info = {
-        type: 'gd',
-        longitude: '',
-        latitude: '',
-        ...data
+        lng: data?.longitude,
+        lat: data?.latitude,
+        address: data?.address || ''
       }
-      AMapLoader.load({
-        key: process.env.VUE_APP_GAODE_MAP_KEY,
-        version: '2.0',
-        plugins: ['']
-      }).then(AMap => {
-        this.$map = AMap
-      })
       this.$refs.confirmDialg.show()
     },
     onConfirm (done) {
-      if (!this.info.longitude) {
-        this.$message({
-          type: 'warning',
-          message: '请填写经度'
-        })
-        return
-      }
-      if (!this.info.latitude) {
-        this.$message({
-          type: 'warning',
-          message: '请填写纬度'
-        })
-        return
-      }
-      if (this.info.type === 'gd') {
-        this.$emit('confirm', {
-          value: {
-            longitude: this.info.longitude,
-            latitude: this.info.latitude
-          },
-          done
-        })
-      } else {
-        if (!this.$map) {
-          this.$message({
-            type: 'warning',
-            message: '转换坐标失败,请关闭后重试'
-          })
-          return
-        }
-        this.$map.convertFrom([this.info.longitude, this.info.latitude], this.info.type, (status, result) => {
-          console.log('coordinate', result)
-          if (result.info === 'ok') {
-            this.$emit('confirm', {
-              value: {
-                longitude: result.locations[0].lng,
-                latitude: result.locations[0].lat
-              },
-              done
-            })
-          } else {
-            this.$message({
-              type: 'warning',
-              message: '转换坐标失败,请稍后重试'
-            })
-          }
-        })
-      }
+      const { lng, lat, address } = this.$refs.picker.getValue()
+      this.$emit('confirm', {
+        value: {
+          longitude: lng,
+          latitude: lat,
+          address
+        },
+        done
+      })
     }
   }
 }

+ 150 - 0
src/components/service/CoordinatePicker/index.vue

@@ -0,0 +1,150 @@
+<template>
+  <div class="l-flex--col c-coordinate-picker u-relative">
+    <div
+      ref="map"
+      class="l-flex__fill"
+    />
+    <el-input
+      id="searchInput"
+      v-model.trim="posName"
+      class="c-coordinate-picker__search u-width--md"
+      placeholder="输入搜索地址"
+      suffix-icon="el-icon-search"
+      clearable
+    />
+    <el-input
+      v-model="posAddress"
+      placeholder="标注地址"
+    />
+  </div>
+</template>
+
+<script>
+import AMapLoader from '@amap/amap-jsapi-loader'
+
+export default {
+  name: 'CoordinatePicker',
+  props: {
+    lng: {
+      type: [String, Number],
+      default: null
+    },
+    lat: {
+      type: [String, Number],
+      default: null
+    },
+    address: {
+      type: String,
+      default: ''
+    }
+  },
+  data () {
+    return {
+      posName: '',
+      posAddress: ''
+    }
+  },
+  mounted () {
+    this.posAddress = this.address
+    if (this.lng !== null && this.lng !== '' && this.lat !== null && this.lat !== '') {
+      this.center = [Number(this.lng), Number(this.lat)]
+    } else {
+      this.center = null
+    }
+    this.initMap()
+  },
+  beforeDestroy () {
+    this.marker = null
+    this.map?.destroy()
+    this.map = null
+  },
+  methods: {
+    geolocation () {
+      if (navigator.geolocation && !this.center) {
+        navigator.geolocation.getCurrentPosition(position => {
+          this.center = [position.coords.longitude, position.coords.latitude]
+          this.center && this.initMap()
+        }, err => {
+          console.log(err)
+        })
+      } else {
+        this.center && this.initMap()
+      }
+    },
+    updateMarker (AMap, pos) {
+      this.center = pos
+      if (this.marker) {
+        this.marker.setPosition(pos)
+      } else {
+        this.marker = new AMap.Marker({
+          icon: 'https://webapi.amap.com/theme/v1.3/markers/n/mark_r.png',
+          position: pos,
+          offset: new AMap.Pixel(-13, -30)
+        })
+        this.marker.setMap(this.map)
+      }
+    },
+    initMap () {
+      AMapLoader.load({
+        key: process.env.VUE_APP_GAODE_MAP_KEY,
+        version: '2.0',
+        plugins: ['AMap.PlaceSearch', 'AMap.Geolocation', 'AMap.AutoComplete', 'AMap.Geocoder']
+      }).then(AMap => {
+        this.map = new AMap.Map(this.$refs.map, { center: this.center })
+        this.center && this.updateMarker(AMap, this.center)
+        this.map.setFitView()
+
+        const geocoder = new AMap.Geocoder({ extensions: 'base' })
+
+        this.map.on('click', e => {
+          console.log(e)
+          this.updateMarker(AMap, [e.lnglat.lng, e.lnglat.lat])
+          geocoder.getAddress(this.center, (status, result) => {
+            console.log(result)
+            this.posAddress = result.regeocode.formattedAddress || ''
+          })
+          this.map.setFitView()
+        })
+
+        const placeSearch = new AMap.PlaceSearch({ map: this.map })
+        new AMap.Autocomplete({
+          input: 'searchInput' // 绑定的搜索关键字的input标签ID,用这个注册
+        }).on('select', e => {
+          console.log(e)
+          if (e.poi.location) {
+            this.updateMarker(AMap, [e.poi.location.lng, e.poi.location.lat])
+            this.posAddress = e.poi.name
+          }
+          placeSearch.setCity(e.poi.adcode)
+          placeSearch.search(e.poi.name)
+        })
+      })
+    },
+    getValue () {
+      return {
+        lng: this.center ? `${this.center[0]}` : '',
+        lat: this.center ? `${this.center[1]}` : '',
+        address: this.posAddress
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.c-coordinate-picker {
+  position: relative;
+
+  &__search {
+    position: absolute;
+    top: $spacing;
+    left: $spacing;
+  }
+}
+</style>
+<style>
+.amap-sug-result {
+  z-index: 9999 !important;
+  border: none !important;
+}
+</style>

+ 5 - 3
src/views/external/box/components/Device.vue

@@ -250,15 +250,17 @@ export default {
       this.$refs.editDialog.show()
     },
     onEditCoordinate () {
-      const { longitude, latitude } = this.currObj
+      const { longitude, latitude, address } = this.currObj
       this.$refs.coordinateDialog.show({
         longitude,
-        latitude
+        latitude,
+        address
       })
     },
-    onChangeCoordinate ({ value: { longitude, latitude }, done }) {
+    onChangeCoordinate ({ value: { longitude, latitude, address }, done }) {
       this.currObj.longitude = longitude
       this.currObj.latitude = latitude
+      this.currObj.address = address
       done()
     },
     onSave (done) {

+ 5 - 3
src/views/external/index.vue

@@ -113,15 +113,17 @@ export default {
       this.$refs.editDialog.show()
     },
     onEditCoordinate () {
-      const { longitude, latitude } = this.mesh
+      const { longitude, latitude, address } = this.mesh
       this.$refs.coordinateDialog.show({
         longitude,
-        latitude
+        latitude,
+        address
       })
     },
-    onChangeCoordinate ({ value: { longitude, latitude }, done }) {
+    onChangeCoordinate ({ value: { longitude, latitude, address }, done }) {
       this.mesh.longitude = longitude
       this.mesh.latitude = latitude
+      this.mesh.address = address
       done()
     },
     onConfirm (done) {

+ 5 - 3
src/views/realm/device/index.vue

@@ -242,15 +242,17 @@ export default {
       this.$refs.editDialog.show()
     },
     onEditCoordinate () {
-      const { longitude, latitude } = this.info
+      const { longitude, latitude, address } = this.info
       this.$refs.coordinateDialog.show({
         longitude,
-        latitude
+        latitude,
+        address
       })
     },
-    onChangeCoordinate ({ value: { longitude, latitude }, done }) {
+    onChangeCoordinate ({ value: { longitude, latitude, address }, done }) {
       this.info.longitude = longitude
       this.info.latitude = latitude
+      this.info.address = address
       done()
     },
     onSave (done) {