123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583 |
- <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)">
- {{ 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: [{
- id: 1,
- name: '腾讯地图',
- value: 'qqMap'
- }, {
- id: 2,
- name: '百度地图',
- value: 'baiduMap'
- }, {
- id: 3,
- name: '高德地图',
- value: 'aMap'
- }],
- // 只触发一次
- 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.lng
- this.form.latitude = locationRes.data.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) => {
- try {
- mapLocation.postMessage('获取定位')
- window['setMapLocation'] = res => {
- let e = JSON.parse(res)
- resolve({
- status: 'complete',
- data: {
- lng: e.longitude,
- lat: e.latitude
- }
- })
- }
- } catch {
- this.AMap.plugin('AMap.Geolocation', function () {
- geolocation.getCurrentPosition(function (status, res) {
- resolve({
- status: status,
- data: res.position
- })
- })
- })
- }
- })
- },
- // 获取城市信息
- 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 (getApp().globalData.inside) {
- openOtherApp.postMessage(`?page=${e.value}&longitude=${this.toLng}&latitude=${this.toLat}&name=${this.toName}`)
- } else {
- // 腾讯地图
- if (e.id === 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.id === 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®ion=${this.province}&output=html&coord_type=gcj02&src=webapp.airsmart.猫王妙播Pro`
- }
- // 高德地图
- if (e.id === 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: 20px;
- 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>
|