index.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. <template>
  2. <el-dialog
  3. title="选择位置"
  4. :visible.sync="open"
  5. :close-on-click-modal="false"
  6. width="700px"
  7. append-to-body
  8. @close="cancel"
  9. >
  10. <!-- 输入框 -->
  11. <el-autocomplete
  12. class="mb10"
  13. style="width: 100%"
  14. v-model="address"
  15. value-key="name"
  16. popper-class="my-autocomplete"
  17. placeholder="请输入内容"
  18. :fetch-suggestions="querySearchAsync"
  19. clearable
  20. @select="handleSelect"
  21. >
  22. <i class="el-icon-search el-input__icon" slot="suffix"></i>
  23. <template slot-scope="{ item }">
  24. <div class="name">{{ item.name }}</div>
  25. <span class="addr">{{ item.district }}</span>
  26. </template>
  27. </el-autocomplete>
  28. <!-- 地图容器 -->
  29. <div ref="container" class="container"></div>
  30. <div class="footer" slot="footer">
  31. <el-button type="primary" @click="submitForm">确 定</el-button>
  32. </div>
  33. </el-dialog>
  34. </template>
  35. <script>
  36. let map = null,
  37. marker = null
  38. export default {
  39. name: 'BaseAmapSelect',
  40. data() {
  41. return {
  42. open: false,
  43. latitude: null,
  44. longitude: null,
  45. address: null,
  46. defaultCenter: [116.41, 39.9]
  47. }
  48. },
  49. destroyed() {
  50. console.log('销毁')
  51. map && (map = undefined)
  52. },
  53. methods: {
  54. // 重置数据
  55. reset() {
  56. this.latitude = null
  57. this.longitude = null
  58. this.address = null
  59. },
  60. // 打开组件
  61. init(options) {
  62. this.reset()
  63. this.open = true
  64. // 初始化地图
  65. // 无需频繁初始化地图
  66. if (!map) {
  67. this.$nextTick(() => {
  68. this.creatAmap(options)
  69. })
  70. } else {
  71. // 移动视角
  72. if (options.cityId) {
  73. // 如果设置了cityId就移动至cityId
  74. this.getLocationByCityId(options.cityId).then(res => {
  75. map.setCenter(res)
  76. })
  77. } else if (options.center) {
  78. // 如果设置了经纬度就移动至经纬度地址
  79. map.setCenter(options.center)
  80. }
  81. }
  82. },
  83. // 加载地图
  84. async creatAmap(options) {
  85. let pOptions = options || {}
  86. // 初始化参数
  87. let creatOptions = {
  88. resizeEnable: true, //窗口大小调整
  89. center: this.defaultCenter,
  90. zoom: 15,
  91. ...pOptions
  92. }
  93. try {
  94. // 如果设置了cityId,将center改为cityId解析后的点位
  95. if (pOptions.cityId) {
  96. // console.log(pOptions.cityId);
  97. creatOptions.center = await this.getLocationByCityId(pOptions.cityId)
  98. }
  99. } catch (error) {
  100. console.log('初始化地图出错:', error)
  101. } finally {
  102. map = new AMap.Map(this.$refs.container, creatOptions)
  103. this.mapAddClick()
  104. }
  105. },
  106. // 给地图添加点击事件
  107. mapAddClick() {
  108. if (AMap && map) {
  109. let geoCoder = new AMap.Geocoder()
  110. map.on('click', e => {
  111. if (marker) {
  112. map.remove(marker)
  113. }
  114. // 添加标记点
  115. marker = new AMap.Marker({
  116. position: e.lnglat,
  117. map: map
  118. })
  119. geoCoder.getAddress(e.lnglat, (status, res) => {
  120. if (status === 'complete' && res.info === 'OK') {
  121. this.address = res.regeocode.formattedAddress
  122. this.latitude = e.lnglat.lat
  123. this.longitude = e.lnglat.lng
  124. } else {
  125. this.$message({
  126. message: '获取位置信息失败!',
  127. type: 'warning'
  128. })
  129. }
  130. })
  131. })
  132. }
  133. },
  134. // 根据cityId搜索坐标
  135. getLocationByCityId(cityId) {
  136. if (AMap && cityId) {
  137. return new Promise((resolve, reject) => {
  138. // 基础配置
  139. const districtSearchOptions = {
  140. showbiz: false,
  141. subdistrict: 0
  142. }
  143. const amapDistrictSearch = new AMap.DistrictSearch(districtSearchOptions)
  144. amapDistrictSearch.search(cityId, (status, result) => {
  145. if (status === 'complete' && result.info === 'OK') {
  146. // 取数组第一个
  147. if (result.districtList[0]) {
  148. const resCenter = result.districtList[0].center
  149. resolve([resCenter.lng, resCenter.lat])
  150. }
  151. } else {
  152. reject(status)
  153. }
  154. // console.log('s:', status);
  155. // console.log('r:', result);
  156. })
  157. })
  158. } else {
  159. return Promise.reject('no AMap or no Id')
  160. }
  161. },
  162. // 搜索输入
  163. querySearchAsync(queryString, cb) {
  164. // 插件配置
  165. const autoOptions = {}
  166. let aMapAutoComplete = null
  167. if (AMap && queryString) {
  168. aMapAutoComplete = new AMap.AutoComplete(autoOptions)
  169. // 搜索
  170. aMapAutoComplete.search(queryString, (status, result) => {
  171. if (status === 'complete' && result.info === 'OK') {
  172. cb(result.tips)
  173. }
  174. // console.log('s:', status);
  175. // console.log('r:', result);
  176. })
  177. }
  178. },
  179. // 选择搜索项
  180. handleSelect(item) {
  181. // console.log(item);
  182. if (map) {
  183. map.setCenter([item.location.lng, item.location.lat])
  184. if (marker) {
  185. map.remove(marker)
  186. }
  187. // 添加标记点
  188. marker = new AMap.Marker({
  189. position: [item.location.lng, item.location.lat],
  190. map: map
  191. })
  192. // 给表单数据
  193. this.address = item.district + item.address
  194. this.latitude = item.location.lat
  195. this.longitude = item.location.lng
  196. }
  197. },
  198. // 确认按钮
  199. submitForm() {
  200. if (this.address && this.latitude && this.longitude) {
  201. const data = {
  202. address: this.address,
  203. latitude: this.latitude,
  204. longitude: this.longitude
  205. }
  206. this.$emit('get-address', data)
  207. this.open = false
  208. } else {
  209. this.msgError('请选择地点!')
  210. }
  211. },
  212. // 取消按钮
  213. cancel() {
  214. // 关闭地图清空按钮
  215. if (map && marker) {
  216. map.remove(marker)
  217. }
  218. }
  219. }
  220. }
  221. </script>
  222. <style lang="scss" scoped>
  223. .container {
  224. width: 100%;
  225. height: 600px;
  226. }
  227. .footer {
  228. padding: 0 20px 10px;
  229. }
  230. // 自定义样式
  231. .my-autocomplete {
  232. li {
  233. line-height: normal;
  234. padding: 7px;
  235. .name {
  236. text-overflow: ellipsis;
  237. overflow: hidden;
  238. }
  239. .addr {
  240. font-size: 12px;
  241. color: #b4b4b4;
  242. }
  243. .highlighted .addr {
  244. color: #ddd;
  245. }
  246. }
  247. }
  248. </style>