index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. <template>
  2. <view class='app'>
  3. <!-- 当前选择地址 -->
  4. <view class="current-address row b-b">
  5. <view class="left">
  6. <view class="row">
  7. <text class="red">[当前]</text>
  8. <text class="title">{{ currentAddress.title }}</text>
  9. </view>
  10. <text class="addr clamp">{{ currentAddress.address }}</text>
  11. </view>
  12. <!-- 搜索图标 -->
  13. <image
  14. class="ser-icon"
  15. src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADwAAAA8CAYAAAA6/NlyAAAENElEQVRoQ+2a/1XcMAzHlQkKExQmaJmAMgHtBJQJqkzQMsGpExQm6HWCHhMUJihMUJjAfd97znuucc6Sklxf4PwXjzixPtYPS/I19MJG88J4aQf83DW+0/BOw89sByY3aWbea5rmDREdhBAO0v1rmmYVQrgXkbtt7eskwMz8lojOiOgdEeHv2nggolXTNMvFYnFVmzzk+ajAbduehhA4gnrlArwQ0VcRwd+jjlGAo0YXA0FzsDW4iFyMSTwYmJk/E9GXDULdEtGSiOCnqa/uRXOHX78nolc937ghog9j+bkbGMGIiKDVjwVB7+MmLLVmGa0E7gDfL2n7REQAP2i4gCPsz0JAWoOKyKVXKmaGxmExJfDzId+GTF5gwCICp+MHtK3VaG1DmBlmjo1LTR1+PUjTZmBmRgT9lAl8ISKb/LjGV3wezRz+/zqZAOhD78aagOOuf8+kaxFKXUSKl6L7INilml6JyIni9SdT1MBx4V/ImJKvXIlIKWh5ZOl9J2p6lUG7/NkCDJPFEdSNWxHRZFGjwDMzIjhOhW64TFsFHLX7m4hwFHUDwQO7vrXBzFjvOFnQrGUtMMz2W7LQtYjkUXpycGbGmjghunEnIoeWhbXAiJSnyYePxkgCLIJ2c5kZyQeqr26YZKkCR3P+kyyAcu6fMs8juPedgi+bjkQNcG5GW4nMfRsSMzHEk26Y3EsDnEdnJPIw8f82MrN+EJF9rTAaYKR3aV679eicw+TRWkSqHN03qhMLR8G+N63TaqE2j5ndSjADW3azJrj3OTPnbqa2urkC5wUMiglVI1ADnJ/B6t30arD23tQ+7DafmuDe51MD52nlpOVgbRMKidDo5zCyqvSgvxGRo5pgUz0v1ORo56KSUo2qD+MrzIyAkHYd1EFCJYVh0pAjCctogXM/NuWvBp6NU2NaiSZEV6Y+ikhaslaX0gLnZo3iG1WK6iioSqGcUNCuOa9XAUezzrMb82JKruK0QtHwiHaTNeuzAOdahmDmjoMHuqcP7nIrNXDUcu7L+LepAHcCo1OKPnU3XNpVB61UyELHYXBzfNMmMDNaS3ln1L3JJg1HLcO00WbJbwSQkLivWHLoDdc5gxIfM3CERns27xPjEYAh0KB73bZtz0IIKBDyI8fctMs30gVcgXZfaMeuJHrfmzqilyJy7okFLh/O/BnmjWoq7SKmU5bxdxzId59cdcbffxyHEBCQAKltDrqh3RrOwEvRu08JAAeYJkO6jgGrdH3qgh4FOAlmffe6Vgt8cs9cyLLWMcNq3qMBd0QxI0L1AjNNCw4NNO6YcRlZvMIZA3p04IKPd75ZCkTd7z5w/am6pxoKPSmwRqWeOUOgZwkcY0ZezODf1WbAbIH7oGtt5FkDF6Cr/a3ZA0fodWDU5PLPAtgS+HbAlt2a49ydhueoNYvMOw1bdmuOc/8C4xLETHORTG0AAAAASUVORK5CYII="
  16. @click="navTo('search?city='+curCity)"
  17. ></image>
  18. </view>
  19. <!-- 补充详细地址 -->
  20. <view class="confirm-wrap row">
  21. <!-- <input class="input" placeholder="补充详细地址:楼号、门牌等(选填)" placeholder-class="placeholder" v-model="room" @confirm='submit'></input> -->
  22. <view class="btn" @click="submit">确定</view>
  23. </view>
  24. <map
  25. id="map"
  26. :latitude="map.latitude"
  27. :longitude="map.longitude"
  28. :scale="15"
  29. :show-location="true"
  30. class="map"
  31. @regionchange="onRegionchange"
  32. >
  33. <cover-image class="map-center-icon"
  34. src="https://7478-tx-cloud-mix-mall-d6944c-1302673523.tcb.qcloud.la/5bfbd58b18200d8e16f6b17a02e6ed9.png"></cover-image>
  35. </map>
  36. <!-- 结果集 -->
  37. <scroll-view class="addr-list-scroll" scroll-y>
  38. <view class="addr-list">
  39. <view v-for="(item, index) in list" :key="index" class="addr-item b-b row" @click="chooseAddress(index)">
  40. <view class="left">
  41. <text class="title">{{ item.title }}</text>
  42. <text class="addr">{{ item.address }}</text>
  43. </view>
  44. <icon v-if='checked === index' class="icon_circle" color="#2979ff" size="18" type="success"/>
  45. </view>
  46. </view>
  47. </scroll-view>
  48. </view>
  49. </template>
  50. <script>
  51. const QQMapWX = require('./js/qqmap-wx-jssdk.min.js')
  52. const qqmapsdk = new QQMapWX({
  53. key: 'FALBZ-J2G3I-ZY5GX-5ATUZ-GHOOZ-YVFAR'
  54. })
  55. let _mapCtx = null;
  56. export default {
  57. data() {
  58. return {
  59. curCity: '',
  60. mapStatus: 1,
  61. map: {
  62. longitude: 116.39742,
  63. latitude: 39.909,
  64. },
  65. room: '', //补充地址 门牌号、房间号
  66. list: [], //地址列表
  67. checked: 0, //当前选择选择地址下标
  68. tempAddress: null, //编辑或者搜索到地址时,需要手动将结果添加到poi集
  69. }
  70. },
  71. computed: {
  72. currentAddress() {
  73. if (this.list.length === 0) {
  74. return {};
  75. }
  76. return this.list[this.checked];
  77. }
  78. },
  79. created() {
  80. _mapCtx = uni.createMapContext('map');
  81. },
  82. onNavigationBarButtonTap() {
  83. this.submit();
  84. },
  85. async onLoad(options) {
  86. //编辑地址时参数
  87. let optionData = options.data;
  88. let lng, lat;
  89. if (optionData) {
  90. //编辑地址时
  91. this.tempAddress = JSON.parse(optionData);
  92. this.room = this.tempAddress.room;
  93. lng = this.tempAddress.location.lng;
  94. lat = this.tempAddress.location.lat;
  95. } else {
  96. //没有传坐标时获取用户当前定位
  97. const userLocation = await this.getLocation();
  98. lng = +userLocation.longitude;
  99. lat = +userLocation.latitude;
  100. }
  101. this.map = {
  102. longitude: lng,
  103. latitude: lat
  104. }
  105. this.position = {
  106. longitude: lng,
  107. latitude: lat
  108. }
  109. this.getAddressList(1)
  110. },
  111. methods: {
  112. //确定选择
  113. submit() {
  114. const {currentAddress, room} = this;
  115. const {ad_info, address, location, title} = currentAddress;
  116. // this.$util.prePage().setAddress(Object.assign({}, {
  117. // ad_info, address, location, title,room
  118. // }));
  119. uni.$emit('changeAddressConfig', address, location.lng, location.lat);
  120. uni.navigateBack();
  121. },
  122. //获取poi列表
  123. getAddressList(s = 0) {
  124. //在ios下防止搜索返回时多次加载地址列表的问题
  125. if (this.isSetTempAddress === 1) {
  126. return;
  127. }
  128. qqmapsdk.reverseGeocoder({
  129. location: {
  130. latitude: this.position.latitude,
  131. longitude: this.position.longitude
  132. },
  133. get_poi: 1,
  134. poi_options: "page_size=30;page_index=1",
  135. success: res => {
  136. res.result.pois.forEach(poi => {
  137. if (!poi.ad_info) {
  138. poi.ad_info = {
  139. adcode: poi.adcode,
  140. city: poi.city,
  141. district: poi.district,
  142. province: poi.province
  143. }
  144. }
  145. })
  146. //有搜索结果时,手动追加到列表顶部
  147. if (this.tempAddress) {
  148. if (this.tempAddress.title != res.result.pois[0].title) {
  149. if (!this.tempAddress.ad_info) {
  150. this.tempAddress.ad_info = {
  151. adcode: this.tempAddress.adcode,
  152. city: this.tempAddress.city,
  153. district: this.tempAddress.district,
  154. province: this.tempAddress.province
  155. }
  156. }
  157. res.result.pois.unshift(this.tempAddress);
  158. }
  159. this.tempAddress = null;
  160. this.isSetTempAddress = 1;
  161. setTimeout(() => {
  162. this.isSetTempAddress = 0;
  163. }, 500)
  164. }
  165. if (s) {
  166. const ad_info = res.result.pois[0].ad_info;
  167. this.curCity = ad_info.city || '';
  168. res.result.pois[0].select = 1
  169. this.list = res.result.pois;
  170. this.checked = 0;
  171. } else {
  172. this.list = res.result.pois;
  173. }
  174. },
  175. fail: err => {
  176. console.log(err)
  177. }
  178. })
  179. },
  180. //地图区域改变
  181. onRegionchange(e) {
  182. clearTimeout(this.timer)
  183. this.timer = setTimeout(() => {
  184. //h5 end 安卓 regionchange
  185. if (e.type === 'end' || e.type === 'regionchange') {
  186. _mapCtx.getCenterLocation({
  187. success: res => {
  188. this.position = {
  189. latitude: res.latitude,
  190. longitude: res.longitude
  191. }
  192. if (this.mapStatus == 1) { // 防止地图点击时 进行多次加载
  193. this.getAddressList(1)
  194. }
  195. },
  196. fail: err => {
  197. console.log(err);
  198. }
  199. })
  200. }
  201. }, 200)
  202. },
  203. //地址列表点击
  204. chooseAddress(index) {
  205. let list = this.list
  206. this.map = {
  207. longitude: list[index].location.lng,
  208. latitude: list[index].location.lat
  209. }
  210. this.checked = index;
  211. this.mapStatus = 0;
  212. //防止ios下触发多次加载列表的bug
  213. clearTimeout(this.mapStatusTimer);
  214. this.mapStatusTimer = setTimeout(() => {
  215. this.mapStatus = 1;
  216. }, 1000)
  217. },
  218. //获取用户定位
  219. getLocation() {
  220. return new Promise(resolve => {
  221. // #ifndef H5
  222. uni.getLocation({
  223. type: 'gcj02',
  224. success: res => {
  225. resolve({
  226. longitude: res.longitude,
  227. latitude: res.latitude
  228. })
  229. },
  230. err: err => {
  231. console.log(err)
  232. resolve({
  233. longitude: 116.39742,
  234. latitude: 39.909,
  235. })
  236. },
  237. complete(res) {
  238. console.log(res);
  239. }
  240. })
  241. // #endif
  242. // #ifdef H5
  243. //h5的定位没有写,这里直接默认天安门,可以根据项目需求使用对应jssdk获取定位
  244. resolve({
  245. longitude: 116.39742,
  246. latitude: 39.909,
  247. })
  248. // #endif
  249. })
  250. },
  251. navTo(url) {
  252. uni.navigateTo({
  253. url
  254. })
  255. }
  256. }
  257. }
  258. </script>
  259. <style>
  260. page {
  261. height: 100%;
  262. background: #F6F6F6;
  263. }
  264. </style>
  265. <style lang="scss" scoped>
  266. .app {
  267. display: flex;
  268. flex-direction: column;
  269. height: 100%;
  270. overflow: hidden;
  271. }
  272. .row {
  273. display: flex;
  274. align-items: center;
  275. }
  276. .b-b {
  277. position: relative;
  278. &:after {
  279. position: absolute;
  280. z-index: 3;
  281. left: 0;
  282. top: auto;
  283. bottom: 0;
  284. right: 0;
  285. height: 0;
  286. content: '';
  287. transform: scaleY(.5);
  288. border-bottom: 1px solid #e5e5e5;
  289. }
  290. }
  291. .clamp {
  292. /* #ifdef APP-PLUS-NVUE */
  293. lines: 1;
  294. /* #endif */
  295. /* #ifndef APP-PLUS-NVUE */
  296. overflow: hidden;
  297. text-overflow: ellipsis;
  298. white-space: nowrap;
  299. display: block;
  300. /* #endif */
  301. }
  302. .current-address {
  303. height: 120 rpx;
  304. padding: 0 24 rpx;
  305. background-color: #fff;
  306. .left {
  307. width: 634 rpx;
  308. }
  309. .red {
  310. flex-shrink: 0;
  311. margin-right: 6 rpx;
  312. font-size: 28 rpx;
  313. color: #2979ff;
  314. line-height: 36 rpx;
  315. }
  316. .title {
  317. font-size: 28 rpx;
  318. color: #333;
  319. font-weight: bold;
  320. line-height: 36 rpx;
  321. }
  322. .addr {
  323. width: 700 rpx;
  324. margin-top: 12 rpx;
  325. font-size: 24 rpx;
  326. color: #909399;
  327. line-height: 1.4;
  328. }
  329. .ser-icon {
  330. flex-shrink: 0;
  331. width: 66 rpx;
  332. height: 66 rpx;
  333. padding: 12 rpx 4 rpx 12 rpx 20 rpx;
  334. }
  335. }
  336. .confirm-wrap {
  337. height: 88 rpx;
  338. padding: 0 24 rpx;
  339. background-color: #fff;
  340. .input {
  341. flex: 1;
  342. font-size: 28 rpx;
  343. color: #303133;
  344. }
  345. .btn {
  346. width: 700 rpx;
  347. padding: 0 25 rpx;
  348. font-size: 26 rpx;
  349. color: #fff;
  350. height: 60 rpx;
  351. line-height: 60 rpx;
  352. background-color: #2979ff;
  353. border-radius: 100 rpx;
  354. text-align: center;
  355. }
  356. }
  357. .map {
  358. width: 750 rpx;
  359. height: 700 rpx;
  360. .map-center-icon {
  361. position: absolute;
  362. left: 339 rpx;
  363. top: 264 rpx;
  364. width: 72 rpx;
  365. height: 72 rpx;
  366. }
  367. }
  368. .addr-list-scroll {
  369. flex: 1;
  370. overflow: hidden;
  371. .addr-list {
  372. background-color: #fff;
  373. }
  374. .addr-item {
  375. padding: 24 rpx;
  376. }
  377. .left {
  378. flex: 1;
  379. display: flex;
  380. flex-direction: column;
  381. padding-right: 50 rpx;
  382. }
  383. .title {
  384. font-size: 28 rpx;
  385. color: #303133;
  386. }
  387. .addr {
  388. margin-top: 10 rpx;
  389. font-size: 24 rpx;
  390. color: #909399;
  391. line-height: 1.4;
  392. }
  393. }
  394. </style>