index.vue 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <template>
  2. <div v-if="props.isWrite">
  3. <el-form ref="form" label-width="120px">
  4. <el-form-item label="设备位置:">
  5. <el-select
  6. style="width: 100%"
  7. v-model="state.address"
  8. clearable
  9. filterable
  10. remote
  11. reserve-keyword
  12. placeholder="请输入地址"
  13. :remote-method="autoSearch"
  14. @change="regeoCode"
  15. :loading="state.loading"
  16. >
  17. <el-option
  18. v-for="item in state.mapAddrOptions"
  19. :key="item.value"
  20. :label="item.name"
  21. :value="item.value"
  22. />
  23. </el-select>
  24. </el-form-item>
  25. <el-form-item label="设备地图:">
  26. <div id="rwMap" class="mapContainer"></div>
  27. </el-form-item>
  28. </el-form>
  29. </div>
  30. <div v-else>
  31. <el-descriptions :column="2" border :labelStyle="{ 'font-weight': 'bold' }">
  32. <el-descriptions-item label="设备位置:">{{ state.address }}</el-descriptions-item>
  33. </el-descriptions>
  34. <div id="rMap" class="mapContainer"></div>
  35. </div>
  36. </template>
  37. <script setup lang="ts">
  38. import AMapLoader from '@amap/amap-jsapi-loader'
  39. import { propTypes } from '@/utils/propTypes'
  40. const emits = defineEmits(['locateChange', 'update:center'])
  41. const state = reactive({
  42. lonLat: '',
  43. address: '',
  44. loading: false,
  45. //纬度、经度
  46. latitude: '',
  47. longitude: '',
  48. //地图对象
  49. map: null as any,
  50. mapAddrOptions: [] as any[],
  51. //标记对象
  52. mapMarker: null as any,
  53. geocoder: null as any,
  54. autoComplete: null as any,
  55. //搜索提示
  56. tips: []
  57. })
  58. const props = defineProps({
  59. clickMap: propTypes.bool.def(false),
  60. isWrite: propTypes.bool.def(false),
  61. center: propTypes.string.def('')
  62. })
  63. const loadMap = () => {
  64. ;(window as any)._AMapSecurityConfig = {
  65. securityJsCode: import.meta.env.VITE_AMAP_SECURITY_CODE
  66. }
  67. state.address = ''
  68. state.latitude = ''
  69. state.longitude = ''
  70. AMapLoader.load({
  71. key: import.meta.env.VITE_AMAP_KEY, // 申请好的Web端开发者Key,首次调用 load 时必填
  72. version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
  73. plugins: [
  74. //逆解析插件
  75. 'AMap.Geocoder',
  76. 'AMap.AutoComplete'
  77. ]
  78. }).then(() => {
  79. initMap()
  80. if (props.clickMap) {
  81. state.map.on('click', (e) => {
  82. state.lonLat = e.lnglat.lng + ',' + e.lnglat.lat
  83. regeoCode(state.lonLat)
  84. })
  85. }
  86. initGeocoder()
  87. initAutoComplete()
  88. if (props.center) {
  89. regeoCode(props.center)
  90. }
  91. })
  92. }
  93. const initMap = () => {
  94. let mapId = props.isWrite ? 'rwMap' : 'rMap'
  95. state.map = new (window as any).AMap.Map(mapId, {
  96. resizeEnable: true,
  97. zoom: 11, //地图显示的缩放级别
  98. keyboardEnable: false
  99. })
  100. }
  101. const initGeocoder = () => {
  102. state.geocoder = new (window as any).AMap.Geocoder({
  103. city: '010', //城市设为北京,默认:“全国”
  104. radius: 500, //范围,默认:500
  105. extensions: 'all'
  106. })
  107. }
  108. const initAutoComplete = () => {
  109. const autoOptions = {
  110. city: '全国'
  111. }
  112. state.autoComplete = new (window as any).AMap.AutoComplete(autoOptions)
  113. }
  114. const autoSearch = (queryValue: string) => {
  115. state.autoComplete.search(queryValue, (status, result) => {
  116. var res = result.tips || [] // 搜索成功时,result即是对应的匹配数据
  117. const temp = ref<any[]>([])
  118. res.forEach((p) => {
  119. if ((p.name, p.location.lng && p.location.lat)) {
  120. temp.value.push({
  121. name: p.district + p.name,
  122. value: p.location.lng + ',' + p.location.lat
  123. })
  124. }
  125. })
  126. state.mapAddrOptions = temp.value
  127. })
  128. }
  129. //添加标记点
  130. const setMarker = (lnglat) => {
  131. if (lnglat) {
  132. if (state.mapMarker !== null) {
  133. // 如果点标记已存在则先移除原点
  134. state.map.remove(state.mapMarker)
  135. state.lonLat = ''
  136. }
  137. state.mapMarker = new (window as any).AMap.Marker({
  138. // 定义点标记对象
  139. position: new (window as any).AMap.LngLat(lnglat[0], lnglat[1])
  140. })
  141. state.map.add(state.mapMarker) // 添加点标记在地图上
  142. state.map.setCenter(lnglat)
  143. state.map.setZoom(16)
  144. state.mapMarker.setPosition(lnglat)
  145. }
  146. }
  147. //经纬度转化为地址、添加标记点
  148. const regeoCode = (lonLat) => {
  149. if (lonLat) {
  150. let lnglat = lonLat.split(',')
  151. state.latitude = lnglat[0]
  152. state.longitude = lnglat[1]
  153. emits('locateChange', lnglat)
  154. emits('update:center', lonLat)
  155. setMarker(lnglat)
  156. getAddress(lnglat)
  157. console.log('经纬度', lnglat)
  158. }
  159. }
  160. // 把拿到的经纬度转化为地址信息
  161. const getAddress = (lnglat) => {
  162. state.geocoder.getAddress(lnglat, (status, result) => {
  163. if (status === 'complete' && result.info === 'OK') {
  164. if (result && result.regeocode) {
  165. state.address = result.regeocode.formattedAddress
  166. }
  167. }
  168. })
  169. }
  170. onMounted(() => {
  171. loadMap()
  172. })
  173. </script>
  174. <style scoped>
  175. .mapContainer {
  176. width: 100%;
  177. height: 400px;
  178. }
  179. </style>