chooseLocation.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. <template>
  2. <view class="uni-app">
  3. <view class="status-bar" />
  4. <view class="main-container">
  5. <wk-nav-bar title="选择地址" pervent @back="handleCancel">
  6. <!-- #ifndef MP-WEIXIN -->
  7. <!-- <button
  8. v-if="!showSearch"
  9. class="button white-btn"
  10. @click="handleConfirm">
  11. 确定
  12. </button> -->
  13. <!-- #endif -->
  14. </wk-nav-bar>
  15. <view v-if="!showSearch" class="container">
  16. <view class="search-box">
  17. <view class="search" @click="handleToggleSearch">
  18. <image :src="$static('images/icon/search.png')" alt="" class="search-icon" />
  19. <text>搜索地点</text>
  20. </view>
  21. </view>
  22. <map
  23. id="chooseMap"
  24. :style="{
  25. width: mapStyle.width,
  26. flex: mapStyle.flex
  27. }"
  28. :longitude="centerPoint.longitude"
  29. :latitude="centerPoint.latitude"
  30. :markers="markers"
  31. @tap="handleMapClick" />
  32. <view class="poi-container">
  33. <view
  34. v-for="(poi, index) in poiList"
  35. :key="poi.id"
  36. class="poi-item"
  37. @click="handleChoosePoi(index, $event)">
  38. <view class="left">
  39. <view class="poi-item-name">
  40. {{ poi.name }}
  41. </view>
  42. <view class="poi-item-address">
  43. {{ poi.address || '' }}
  44. </view>
  45. </view>
  46. <view class="right">
  47. <text v-if="activeIndex === index" class="wk wk-check icon" />
  48. </view>
  49. </view>
  50. </view>
  51. </view>
  52. <view v-else class="container">
  53. <wk-search-box @search="handleSearch" />
  54. <view class="list-view">
  55. <wk-scroll-view
  56. :status="listStatus"
  57. :refresh="false"
  58. class="list-scroll"
  59. @loadmore="searchPois()">
  60. <template v-if="listData.length > 0">
  61. <view
  62. v-for="(poi, index) in listData"
  63. :key="poi.id"
  64. class="cell"
  65. @click="handleChooseSearchPoi(index, $event)">
  66. <view class="cell-title">
  67. {{ poi.name }}
  68. </view>
  69. <view class="cell-desc">
  70. {{ poi.address }}
  71. </view>
  72. </view>
  73. </template>
  74. </wk-scroll-view>
  75. </view>
  76. </view>
  77. </view>
  78. </view>
  79. </template>
  80. <script>
  81. import {
  82. getLocation,
  83. searchPois,
  84. searchAroundPois,
  85. getNearbyPois
  86. } from '@/utils/map.js'
  87. /**
  88. * 模仿uni.chooseLocation
  89. */
  90. export default {
  91. name: 'ChooseLocation',
  92. data() {
  93. return {
  94. mapStyle: {
  95. width: 0,
  96. flex: 1
  97. },
  98. centerPoint: {},
  99. markers: [],
  100. poiList: [],
  101. activeIndex: null,
  102. showSearch: false,
  103. listStatus: 'more',
  104. listData: [],
  105. page: 0,
  106. keyword: ''
  107. }
  108. },
  109. onLoad(options = {}) {
  110. this.mapStyle = {
  111. width: uni.upx2px(750) + 'px',
  112. flex: 1
  113. }
  114. if (this.$isEmpty(options)) {
  115. this.getLocation()
  116. } else {
  117. this.centerPoint = options
  118. this.searchAroundPois(this.centerPoint)
  119. }
  120. },
  121. methods: {
  122. /**
  123. * 定位
  124. */
  125. getLocation() {
  126. getLocation().then(data => {
  127. console.log('定位结果:', data)
  128. const city = data.hasOwnProperty('address_component') ? data.address_component.city : data.address.city
  129. this.centerPoint = {
  130. ...data,
  131. city
  132. }
  133. this.searchAroundPois(data)
  134. }).catch(() => {
  135. this.$toast('定位失败')
  136. })
  137. // this.centerPoint = {
  138. // city: '郑州',
  139. // latitude: 34.762279,
  140. // longitude: 113.77765
  141. // }
  142. // this.searchAroundPois(this.centerPoint)
  143. },
  144. /**
  145. * 获取附近500米的POI点
  146. */
  147. searchAroundPois(data) {
  148. // >> 高德地图 <<
  149. // searchAroundPois({
  150. // location: `${data.longitude},${data.latitude}`,
  151. // radius: 500
  152. // }).then(data => {
  153. // console.log('位置信息: ', data)
  154. // this.poiList = data.pois.map(o => {
  155. // return {
  156. // ...o,
  157. // longitude: o.location.split(',')[0],
  158. // latitude: o.location.split(',')[1]
  159. // }
  160. // })
  161. // if (this.poiList.length > 0) {
  162. // this.handleChoosePoi(0)
  163. // } else {
  164. // this.activeIndex = -1
  165. // this.markers = []
  166. // }
  167. // }).catch(() => {
  168. // this.$toast('获取位置信息失败')
  169. // })
  170. // >> 腾讯地图 <<
  171. console.log('getNearbyPois---', `${data.latitude},${data.longitude}`)
  172. getNearbyPois({
  173. location: `${data.latitude},${data.longitude}`,
  174. get_poi: 1,
  175. poi_options: 'radius=500'
  176. }).then(res => {
  177. this.poiList = res.result.pois.map(o => {
  178. return {
  179. ...o,
  180. name: o.title,
  181. longitude: o.location.lng,
  182. latitude: o.location.lat,
  183. }
  184. })
  185. if (this.poiList.length > 0) {
  186. this.handleChoosePoi(0)
  187. } else {
  188. this.activeIndex = -1
  189. this.markers = []
  190. }
  191. }).catch(() => {
  192. this.$toast('获取位置信息失败')
  193. })
  194. },
  195. /**
  196. * 根据关键字搜索POI
  197. */
  198. searchPois() {
  199. this.page++
  200. this.listStatus = 'loading'
  201. // >> 高德地图 <<
  202. // searchPois({
  203. // page: this.page,
  204. // keywords: this.keyword
  205. // }).then(data => {
  206. // console.log('搜索结果: ', data)
  207. // if (this.page === 1) {
  208. // this.listData = []
  209. // }
  210. // data.pois = data.pois.map(o => {
  211. // return {
  212. // ...o,
  213. // longitude: o.location.split(',')[0],
  214. // latitude: o.location.split(',')[1]
  215. // }
  216. // })
  217. // this.listData = this.listData.concat(data.pois)
  218. // this.listStatus = data.count == this.listData.length ? 'noMore' : 'more'
  219. // }).catch(() => {
  220. // this.$toast('服务异常,请稍后重试')
  221. // this.listStatus = 'more'
  222. // })
  223. // >> 腾讯地图 <<
  224. searchPois({
  225. keyword: this.keyword,
  226. region: this.centerPoint.city || '',
  227. region_fix: 0,
  228. page_index: this.page,
  229. page_size: 15
  230. }).then(res => {
  231. console.log('search res: ', res)
  232. if (this.page === 1) {
  233. this.listData = []
  234. }
  235. res.data = res.data.map(o => {
  236. return {
  237. ...o,
  238. ad_info: o,
  239. name: o.title,
  240. longitude: o.location.lng,
  241. latitude: o.location.lat
  242. }
  243. })
  244. this.listData = this.listData.concat(res.data)
  245. this.listStatus = res.data.length === 0 ? 'noMore' : 'more'
  246. }).catch(() => {
  247. this.$toast('服务异常,请稍后重试')
  248. this.listStatus = 'more'
  249. })
  250. },
  251. handleMapClick(evt) {
  252. console.log('tap', evt)
  253. },
  254. /**
  255. * 选择POI点
  256. * @param {Object} index
  257. */
  258. handleChoosePoi(index, evt = null) {
  259. this.activeIndex = index
  260. const point = this.poiList[index]
  261. this.markers = [{
  262. ...point,
  263. width: 30,
  264. height: 30,
  265. iconPath: this.$static('images/map/location.png')
  266. }]
  267. this.centerPoint = {
  268. latitude: point.latitude,
  269. longitude: point.longitude
  270. }
  271. if (evt) {
  272. this.handleConfirm()
  273. }
  274. },
  275. /**
  276. * 切换搜索状态
  277. */
  278. handleToggleSearch() {
  279. this.showSearch = !this.showSearch
  280. this.page = 0
  281. this.listData = []
  282. this.listStatus = 'more'
  283. },
  284. /**
  285. * 去搜索
  286. */
  287. handleSearch(keyword = '') {
  288. this.page = 0
  289. this.listData = []
  290. this.listStatus = 'more'
  291. this.keyword = keyword
  292. if (keyword) {
  293. this.searchPois()
  294. }
  295. },
  296. /**
  297. * 选择搜索的POI点
  298. */
  299. handleChooseSearchPoi(index, evt = null) {
  300. this.poiList = [...this.listData]
  301. this.handleToggleSearch()
  302. this.handleChoosePoi(index, evt)
  303. },
  304. /**
  305. * 取消
  306. */
  307. handleCancel() {
  308. if (this.showSearch) {
  309. this.handleToggleSearch()
  310. } else {
  311. uni.$off('choose-location')
  312. this.$Router.navigateBack()
  313. }
  314. },
  315. /**
  316. * 确定
  317. */
  318. handleConfirm() {
  319. let data = null
  320. if (this.activeIndex >= 0 && this.poiList[this.activeIndex]) {
  321. data = this.poiList[this.activeIndex]
  322. }
  323. uni.$emit('choose-location', data)
  324. this.$Router.navigateBack()
  325. }
  326. }
  327. }
  328. </script>
  329. <style scoped lang="scss">
  330. .container {
  331. flex: 1;
  332. display: flex;
  333. flex-direction: column;
  334. overflow: hidden;
  335. .search-box {
  336. width: 100%;
  337. height: 105rpx;
  338. background-color: white;
  339. @include center;
  340. .search {
  341. width: 92%;
  342. height: 70rpx;
  343. font-size: 26rpx;
  344. color: $light;
  345. background-color: $main-bg;
  346. border-radius: 8rpx;
  347. @include center;
  348. .search-icon {
  349. width: 28rpx;
  350. height: 28rpx;
  351. margin-right: 20rpx;
  352. }
  353. }
  354. }
  355. .poi-container {
  356. width: 100%;
  357. max-height: 450rpx;
  358. overflow: auto;
  359. background-color: white;
  360. .poi-item {
  361. padding: 15rpx 32rpx;
  362. border-bottom: 1rpx solid $border-color;
  363. @include left;
  364. .left {
  365. flex: 1;
  366. overflow: hidden;
  367. .poi-item-name {
  368. font-size: 30rpx;
  369. @include ellipsis;
  370. }
  371. .poi-item-address {
  372. font-size: 24rpx;
  373. color: $light;
  374. @include ellipsis;
  375. }
  376. }
  377. .right {
  378. width: 50rpx;
  379. margin-left: 20rpx;
  380. @include center;
  381. .icon {
  382. font-size: 36rpx;
  383. color: $theme-color;
  384. }
  385. }
  386. }
  387. .poi-item::last-child {
  388. border-bottom: 0 none;
  389. }
  390. }
  391. .list-view {
  392. flex: 1;
  393. background-color: white;
  394. overflow: hidden;
  395. padding: 0 34rpx;
  396. .list-scroll {
  397. width: 100%;
  398. height: 100%;
  399. overflow: hidden;
  400. .cell {
  401. border-bottom: 1rpx solid $border-color;
  402. padding: 20rpx 0;
  403. .cell-title {
  404. font-size: 30rpx;
  405. }
  406. .cell-desc {
  407. font-size: 24rpx;
  408. color: $gray;
  409. }
  410. }
  411. }
  412. }
  413. }
  414. </style>