Browse Source

门店页面

DESKTOP-SVI9JE1\muzen 1 year ago
parent
commit
4fecd593ef
1 changed files with 562 additions and 0 deletions
  1. 562 0
      src/pages/map/index.vue

+ 562 - 0
src/pages/map/index.vue

@@ -0,0 +1,562 @@
+<template>
+  <view class='app-container'>
+    <!-- 定位 + 城市选择器 -->
+    <view class="tab" flex between>
+      <view class="address" @click="getRep">
+        <uni-icons :type="location === '定位中...' ? 'spinner-cycle' : 'location'" />
+        <text>{{ location }}</text>
+      </view>
+      <picker class="list" mode="multiSelector" :range="locationList" range-key="name" :value="pickerValue"
+        @columnchange="handleColumn" @change="handleChange">
+        <view flex style="width: 100%">
+          <view class="item" flex>
+            <view class="name">{{ province }}</view>
+            <uni-icons type="bottom" />
+          </view>
+          <view class="item" flex>
+            <view class="name">{{ city }}</view>
+            <uni-icons type="bottom" />
+          </view>
+          <view class="item" flex>
+            <view class="name">{{ district }}</view>
+            <uni-icons type="bottom" />
+          </view>
+        </view>
+      </picker>
+    </view>
+    <!-- 地图 -->
+    <view id="container" />
+    <!-- 范围内的门店 -->
+    <scroll-view scroll-y class="poi" @scrolltolower="scrollTolower">
+      <view v-if="list.length > 0" style="height: 100%; padding: 16px">
+        <view :class="['list', active === index ? 'active' : '']" flex center v-for="(item, index) in list" :key="item.id"
+          @click="changeActive(item, index)">
+          <img :src="item.icon" width="80" height="80" />
+          <view class="info">
+            <view class="name">{{ item.name }}</view>
+            <view class="distance">距离:{{ item.distance / 1000 }}KM</view>
+            <view class="address">地址:{{ item.address }}</view>
+          </view>
+          <view class="button" flex around>
+            <img class="icon" v-show="item.linkPhone" src="../../static/phone.png" @click="getPhone(item.linkPhone)" />
+            <img class="icon" src="../../static/address.png" @click="getMap(item)" />
+          </view>
+        </view>
+      </view>
+      <view v-else style="height: 100%;  padding: 0 16px">
+        <view class="storeList" v-for="item in storeList" :key="item.id" flex between>
+          <img :src="item.icon" width="56" height="56" />
+          <view class="info">
+            <view class="name">{{ item.name }}</view>
+          </view>
+          <button type="submit" @click="getStore(item.url)">进店逛逛</button>
+        </view>
+      </view>
+    </scroll-view>
+    <!-- 打开地图app弹窗 -->
+    <uni-popup ref="popup" type="bottom">
+      <view class="popup">
+        <view class="title" flex center>请选择地图</view>
+        <view class="item" flex center v-for="item in mapList" :key="item.value" @click="openMap(item.value)">
+          {{ item.name }}
+        </view>
+      </view>
+    </uni-popup>
+  </view>
+</template>
+
+<script>
+import AMapLoader from '@amap/amap-jsapi-loader'
+// 安全密钥
+window._AMapSecurityConfig = {
+  securityJsCode: 'fd78b73eba80ab3f887c9ba60744048f'
+}
+import { options, list, storeList } from '@/api/map'
+export default {
+  data() {
+    return {
+      // 定位
+      location: '定位中...',
+      // 省市区列表
+      locationList: [],
+      // 选中焦点 
+      pickerValue: [18, 0, 0],
+      province: '',
+      city: '',
+      district: '',
+      // 表单
+      form: {
+        pageNum: 1,
+        pageSize: 10,
+        longitude: 116.397428,
+        latitude: 39.90923
+      },
+      // 线下店铺
+      list: [],
+      // 默认选中第一家店铺
+      active: 0,
+      // 第三方店铺
+      storeList: [],
+      // 店铺坐标
+      toLng: '',
+      toLat: '',
+      toName: '',
+
+      // 地图
+      AMap: null,
+      map: null,
+      geolocation: null,
+      // 地图App
+      mapList: [{
+        value: 1,
+        name: '腾讯地图'
+      }, {
+        value: 2,
+        name: '百度地图'
+      }, {
+        value: 3,
+        name: '高德地图'
+      }],
+      // 只触发一次
+      only: true
+    }
+  },
+  onLoad() {
+    this.initAMap()
+  },
+  methods: {
+    async initAMap() {
+      // 调用高德
+      this.AMap = await this.getMapLoader()
+      // 自定义定位按钮
+      this.geolocation = new AMap.Geolocation({
+        enableHighAccuracy: true, // 高精度定位
+        timeout: 3000, // 定位超时时间
+        // zoomToAccuracy: true, // 定位成功后再调整视野
+        showCircle: false, // 定位成功有个圆形范围
+        showButton: false // 是否显示按钮
+      })
+      const locationRes = await this.getLocation(this.geolocation)
+      // 当前定位
+      if (locationRes.status === 'complete') {
+        this.form.longitude = locationRes.data.position.lng
+        this.form.latitude = locationRes.data.position.lat
+      }
+      // 获取城市信息
+      this.getGeocoder([this.form.longitude, this.form.latitude], locationRes.status)
+      // 绘制地图
+      this.map = new AMap.Map('container', {
+        zoom: 16,
+        center: [this.form.longitude, this.form.latitude]
+      })
+      // 调用插件
+      this.map.addControl(this.geolocation)
+      // 地图加载完
+      this.map.on('complete', () => {
+        // 自动定位一次
+        this.geolocation.getCurrentPosition()
+      })
+      // this.map.on('dragend', this.moveMapHandler)
+    },
+
+    // 调用高德
+    getMapLoader() {
+      return new Promise((resolve, reject) => {
+        AMapLoader.load({
+          key: '5dcf4cf0260059dade51d0d9b5e3c1ef',
+          version: '2.0',
+          plugins: ['AMap.Geolocation', 'AMap.Geocoder']
+        }).then((AMap) => {
+          resolve(AMap)
+        }).catch((err) => {
+          reject(err)
+        })
+      })
+    },
+
+    // 获取定位
+    getLocation(geolocation) {
+      return new Promise((resolve, reject) => {
+        this.AMap.plugin('AMap.Geolocation', function () {
+          geolocation.getCurrentPosition(function (status, res) {
+            resolve({
+              status: status,
+              data: res
+            })
+          })
+        })
+      })
+    },
+
+    // 获取城市信息
+    async getGeocoder(lnglat, locationStatus) {
+      const that = this
+      this.AMap.plugin('AMap.Geocoder', function () {
+        var geocoder = new AMap.Geocoder()
+        geocoder.getAddress(lnglat, function (status, resolve) {
+          if (status === 'complete' && resolve.info === 'OK' && resolve.regeocode.formattedAddress !== '中华人民共和国') {
+            let e = resolve.regeocode.addressComponent
+            that.location = locationStatus === 'complete' ? `${e.city ? e.city : e.province}${e.district}` : that.location = '重新定位'
+            that.form.city = null
+            that.city = '全部'
+            that.form.area = null
+            that.district = '全部'
+            that.locationList = []
+            options().then(res => {
+              if (res.data.code === 0) {
+                let value = []
+                // 市
+                that.locationList[0] = res.data.data
+                value[0] = that.locationList[0].findIndex(i => e.province.includes(i.name))
+                that.form.province = that.locationList[0][value[0]].id
+                that.province = that.locationList[0][value[0]].name
+                that.locationList[1] = that.locationList[0][value[0]].childList
+                value[1] = that.locationList[1].findIndex(i => i.citycode === e.citycode)
+                // 省
+                if (value[1] !== -1) {
+                  that.form.city = that.locationList[1][value[1]].id
+                  that.city = that.locationList[1][value[1]].name
+                  // 区
+                  that.locationList[2] = that.locationList[1][value[1]].childList
+                  value[2] = that.locationList[2].findIndex(i => i.adcode === e.adcode)
+                  if (value[2] !== -1) {
+                    that.form.area = that.locationList[2][value[2]].id
+                    that.district = that.locationList[2][value[2]].name
+                  }
+                }
+                that.pickerValue = value
+                that.getList()
+              }
+            })
+          }
+        })
+      })
+    },
+
+    // // 移动地图 中心坐标
+    // moveMapHandler() {
+    //   const center = this.map.getCenter()
+    //   this.form.longitude = center.lng
+    //   this.form.latitude = center.lat
+    //   this.getGeocoder([center.lng, center.lat], 'complete')
+    // },
+
+    // 添加标点
+    getMarker(lng, lat) {
+      const icon = new AMap.Icon({
+        size: new AMap.Size(30, 30),
+        imageSize: new AMap.Size(30, 30),
+        image: '../../static/location.png'
+      })
+      const marker = new AMap.Marker({
+        position: new AMap.LngLat(lng, lat),
+        offset: new AMap.Pixel(-5, -25),
+        icon: icon,
+        zoom: 16
+      })
+      marker.setMap(this.map)
+    },
+
+    // 打开地图
+    openMap(e) {
+      this.$refs.popup.close()
+      let url = ''
+      // 腾讯地图
+      if (e === 1) {
+        url = `https://apis.map.qq.com/uri/v1/routeplan?type=drive&from=我的位置&fromcoord=${this.form.latitude},${this.form.longitude}&to=${this.toName}&tocoord=${this.toLat},${this.toLng}&coord_type=2&referer=猫王妙播Pro}`
+      }
+
+      // 百度地图
+      if (e === 2) {
+        url = `http://api.map.baidu.com/direction?origin=latlng:${this.form.latitude},${this.form.longitude}|name:我的位置&destination=latlng:${this.toLat},${this.toLng}|name:${this.toName}&mode=driving&region=${this.province}&output=html&coord_type=gcj02&src=webapp.airsmart.猫王妙播Pro`
+      }
+
+      // 高德地图
+      if (e === 3) {
+        url = `https://uri.amap.com/navigation?from=${this.form.longitude},${this.form.latitude},我的位置&to=${this.toLng},${this.toLat},${this.toName}&callnative=1`
+      }
+      window.location.href = url
+    },
+
+    // 重新定位
+    getRep() {
+      this.location = '定位中...'
+      this.initAMap()
+    },
+
+    // 选择省
+    handleColumn(e) {
+      let column = e.detail.column
+      let index = e.detail.value
+      if (column === 0) {
+        this.pickerValue = [index, 0, 0]
+        this.locationList[1] = this.locationList[0][index].childList
+        this.locationList[2] = this.locationList[1].length > 0 ? this.locationList[1][0].childList : []
+      }
+      if (column === 1) {
+        this.pickerValue = [this.pickerValue[0], index, 0]
+        this.locationList[2] = this.locationList[1][index].childList
+      }
+    },
+
+    // 确定
+    handleChange(e) {
+      this.form.province = ''
+      this.form.city = ''
+      this.city = '全部'
+      this.form.area = ''
+      this.district = '全部'
+      let index = e.detail.value
+      this.form.province = this.locationList[0][index[0]].id
+      this.province = this.locationList[0][index[0]].name
+      if (this.locationList[1].length > 0) {
+        this.form.city = this.locationList[1][index[1]].id
+        this.city = this.locationList[1][index[1]].name
+      }
+      if (this.locationList[2].length > 0) {
+        this.form.area = this.locationList[2][index[2]].id
+        this.district = this.locationList[2][index[2]].name
+      }
+      this.getList()
+    },
+
+    // 线下店铺
+    getList() {
+      this.list = []
+      this.storeList = []
+      this.map.clearMap()
+      list(this.form).then(res => {
+        if (res.data.code === 0) {
+          if (res.data.data.records.length > 0) {
+            res.data.data.records.map(i => {
+              this.list.push(i)
+              this.getMarker(i.longitude, i.latitude)
+            })
+            this.hasMore = res.data.data.hasMore
+            this.map.setCenter([this.list[0].longitude, this.list[0].latitude])
+          } else {
+            this.getStoreList()
+          }
+        }
+      })
+    },
+
+    // 切换店铺
+    changeActive(item, index) {
+      this.active = index
+      this.map.setCenter([item.longitude, item.latitude])
+    },
+
+
+    // 第三方店铺
+    getStoreList() {
+      storeList().then(res => {
+        if (res.data.code === 0) {
+          this.storeList = res.data.data
+        }
+      })
+    },
+
+    // 跳转第三方店铺
+    getStore(url) {
+      window.location.href = url
+    },
+
+    // 拨打电话
+    getPhone(e) {
+      uni.makePhoneCall({
+        phoneNumber: e
+      })
+    },
+
+    // 打开地图
+    getMap(e) {
+      this.$refs.popup.open()
+      // 店铺坐标
+      this.toLng = e.longitude
+      this.toLat = e.latitude
+      this.toName = e.name
+    },
+
+    // 触底
+    scrollTolower() {
+      if (this.hasMore) {
+        this.form.pageNum++
+        this.getList()
+      } else {
+        if (this.only) {
+          uni.showToast({
+            icon: 'none',
+            title: '暂无更多店铺'
+          })
+          this.only = false
+        }
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+.app-container {
+  margin: 0;
+  padding: 0;
+  height: 100%;
+  position: relative;
+  color: #000;
+  font-size: 28rpx;
+  overflow-y: hidden;
+  display: flex;
+  flex-direction: column;
+
+  .tab {
+    width: 100%;
+    height: 88rpx;
+    line-height: 88rpx;
+    padding: 0 12px;
+    background-color: #FFF;
+    white-space: nowrap;
+
+    .address {
+      width: 100px;
+      overflow: hidden;
+      white-space: nowrap;
+      text-overflow: ellipsis;
+    }
+
+    uni-picker {
+      width: calc(100% - 100px);
+
+      .item {
+        width: calc(100% / 3);
+        margin: 0 5px;
+
+        .name {
+          width: 100%;
+          overflow: hidden;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          text-align: right;
+        }
+      }
+    }
+  }
+
+  #container {
+    width: 100%;
+    height: 100%;
+    flex: 1;
+  }
+
+  .poi {
+    width: 100%;
+    height: 270px;
+    overflow-y: auto;
+    z-index: 99;
+    background-color: #FFF;
+
+    .list,
+    .storeList {
+      width: 100%;
+      height: 104px;
+      padding: 12px;
+      border-bottom: 1px solid #e8e8e8;
+
+      img {
+        border-radius: 8px;
+      }
+
+      button {
+        height: auto;
+        line-height: 1;
+        font-size: 12px;
+        padding: 8px 10px;
+        border-radius: 8px;
+        margin: 0;
+      }
+
+      .info {
+        flex: 1;
+        padding: 0 8px;
+        overflow: hidden;
+
+        .name {
+          font-weight: bold;
+          overflow: hidden;
+          text-overflow: ellipsis;
+          white-space: nowrap;
+        }
+
+        .distance,
+        .address {
+          font-size: 10px;
+          color: #999;
+        }
+      }
+
+      .button {
+        flex-direction: column;
+
+        .icon:first-child {
+          margin-bottom: 20px;
+        }
+
+        .icon {
+          width: 24px;
+          background-color: #a4d099;
+          border-radius: 50%;
+        }
+      }
+    }
+
+    .list {
+      border-radius: 16px;
+      margin-bottom: 12px;
+    }
+
+    .storeList:last-child {
+      border: none;
+    }
+
+    .active {
+      background-color: #F2F5F7;
+    }
+  }
+
+  .uni-icons {
+    vertical-align: bottom;
+  }
+}
+
+.uni-popup {
+  z-index: 999;
+
+  .popup {
+    width: 90%;
+    background-color: #FFF;
+    border-radius: 16px;
+    margin: 0 auto;
+    position: absolute;
+    bottom: 0px;
+    left: 50%;
+    transform: translate(-50%);
+
+    .title {
+      height: 40px;
+      font-size: 12px;
+      border-bottom: 1px solid #e8e8e8;
+    }
+
+    .item {
+      width: 100%;
+      height: 60px;
+      border-bottom: 1px solid #e8e8e8;
+      font-size: 18px;
+    }
+
+    .item:last-child {
+      border: none;
+    }
+  }
+}
+</style>