<template>
|
<view class="ditu">
|
<map
|
id="mapId"
|
:scale="16"
|
class="ditu_map"
|
:markers="markers"
|
:show-location="true"
|
:polygons="eleBusinessArea"
|
:latitude="latitude"
|
:longitude="longitude"
|
@markertap="markertap"
|
@callouttap="toNavigation">
|
<cover-view slot="callout">
|
<cover-view v-for="(item,index) in markers" :key="index">
|
<cover-view class="customCallout" :marker-id="item.id">
|
<cover-image class="image" src="@/static/icon/ic_dingwei@2x.png" mode="widthFix"></cover-image>
|
<cover-view class="mm">{{rice > 1000 ? (rice / 1000).toFixed(1) + '千米' : rice + '米'}}</cover-view>
|
<cover-view class="h"></cover-view>
|
<cover-view class="dh">导航</cover-view>
|
</cover-view>
|
</cover-view>
|
</cover-view>
|
</map>
|
<u-popup :show="show" :overlay="false" :round="10" mode="bottom" @close="show = false">
|
<view class="ditu_box">
|
<view class="ditu_box_a">
|
<text>{{info.title}}</text>
|
<text>距离{{rice > 1000 ? (rice / 1000).toFixed(1) + '千米' : rice + '米'}}</text>
|
</view>
|
<view class="ditu_box_b">
|
{{info.addr || ''}}
|
</view>
|
<view class="ditu_box_c" @click="toNavigation">导航前往</view>
|
</view>
|
</u-popup>
|
|
<view class="search">
|
<view class="search_left"></view>
|
<image class="dw" @click="clickcontrol" src="@/static/icon/map_relocation@2x.png" mode="widthFix"></image>
|
</view>
|
|
<view class="index_scancode" v-if="!userInfo.mobile || isShow">
|
<button class="index_scancode_bottom" open-type="getPhoneNumber" @getphonenumber="getPhone"
|
v-if="!userInfo.mobile">扫码租车</button>
|
<view class="index_scancode_bottom" v-else-if="isShow" @click="saoma">扫码租车</view>
|
<view class="index_scancode_zw"></view>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import { distance } from '@/utils/utils.js'
|
import { mapState } from 'vuex'
|
export default {
|
data() {
|
return {
|
type: null,
|
show: false,
|
latitude: '',
|
longitude: '',
|
markers: [],
|
info: {},
|
rice: '',
|
infoData: {},
|
eleBusinessArea: [],
|
isShow: false
|
};
|
},
|
computed: {
|
...mapState(['userInfo'])
|
},
|
onLoad(options) {
|
this.type = options.type
|
this.getAddress()
|
this.refresh()
|
},
|
methods: {
|
saoma() {
|
uni.$emit('update', { msg:'页面更新' })
|
uni.navigateBack({ delta: 1 });
|
},
|
// 刷新首页信息
|
refresh() {
|
this.$u.api.home()
|
.then(res => {
|
if (res.code === 200) {
|
this.isShow = res.data.memberRidesResponse ? false : true
|
}
|
})
|
},
|
// 获取经纬度
|
getAddress() {
|
let that = this;
|
// 1、判断手机定位服务【GPS】 是否授权
|
uni.getSystemInfo({
|
success(res) {
|
let locationEnabled = res.locationEnabled; // 判断手机定位服务是否开启
|
let locationAuthorized = res.locationAuthorized; // 判断定位服务是否允许微信授权
|
if (locationEnabled == false || locationAuthorized == false) {
|
//手机定位服务(GPS)未授权
|
uni.showToast({ title: "请打开手机GPS", icon: "none" });
|
} else {
|
// 2、判断微信小程序是否授权位置信息
|
uni.authorize({
|
//授权请求窗口
|
scope: "scope.userLocation",
|
success: (res) => {
|
that.fnGetlocation();
|
},
|
fail: (err) => {
|
err = err["errMsg"];
|
uni.showModal({ content: "需要授权位置信息", confirmText: "确认授权" })
|
.then((res) => {
|
if (res.confirm) {
|
uni.openSetting({
|
success: (res) => {
|
if (res.authSetting["scope.userLocation"]) {
|
uni.showToast({ title: "授权成功", icon: "success" });
|
that.fnGetlocation();
|
} else {
|
that.getSite()
|
// 未授权
|
uni.showToast({ title: "授权失败,请重新授权", icon: "none" });
|
uni.showModal({
|
title: "授权",
|
content: "获取授权失败,是否前往授权设置?",
|
success: function(result) {
|
if (result.confirm) {
|
uni.openSetting();
|
}
|
},
|
fail: function() {
|
uni.showToast({ title: "系统错误!", icon: "none" });
|
}
|
});
|
}
|
}
|
});
|
}
|
if (res.cancel) {
|
// 取消授权
|
uni.showToast({ title: "你拒绝了授权,无法获得周边信息", icon: "none" });
|
that.getSite()
|
}
|
});
|
}
|
});
|
}
|
},
|
});
|
},
|
async getEleBikeList() {
|
let res = await this.$u.api.eleBikeList({})
|
if (res.code === 200) {
|
res.data.forEach((item, index) => {
|
let num = distance(this.latitude, this.longitude, item.latitude, item.longitude)
|
this.markers.push({
|
id: index,
|
width: 40,
|
height: 40,
|
distance: this.latitude && this.longitude ? num : '未知距离',
|
latitude: item.latitude,
|
longitude: item.longitude,
|
title: item.code,
|
iconPath: '/static/icon/ic_bike@2x.png',
|
customCallout: {
|
anchorY: 0,
|
anchorX: 0,
|
display: 'BYCLICK'
|
}
|
})
|
})
|
}
|
},
|
// 定位获取
|
fnGetlocation() {
|
let that = this;
|
uni.getLocation({
|
type: "gcj02",
|
altitude: true,
|
isHighAccuracy: true,
|
success: function(res) {
|
that.latitude = res.latitude
|
that.longitude = res.longitude
|
if (that.type == 1) {
|
console.log('自行车')
|
that.getSite()
|
} else {
|
console.log('电动车')
|
that.getEleBikeList()
|
that.getEleSiteList()
|
}
|
},
|
fail(err) {
|
if (err.errMsg === "getLocation:fail 频繁调用会增加电量损耗,可考虑使用 wx.onLocationChange 监听地理位置变化") {
|
uni.showToast({ title: "请勿频繁定位", icon: "none" });
|
}
|
if (err.errMsg === "getLocation:fail auth deny") {
|
// 未授权
|
uni.showToast({ title: "无法定位,请重新获取位置信息", icon: "none" });
|
}
|
if (err.errMsg === "getLocation:fail:ERROR_NOCELL&WIFI_LOCATIONSWITCHOFF") {
|
uni.showModal({ content: "请开启手机定位服务", showCancel: false });
|
}
|
},
|
});
|
},
|
//导航--传终点的坐标即可
|
toNavigation: function() {
|
uni.openLocation({
|
longitude: parseFloat(this.info.longitude),
|
latitude: parseFloat(this.info.latitude),
|
scale: 28,
|
name: this.info.title,
|
address: this.info.addr,
|
success: function (res) {
|
console.log('success:',res);
|
}
|
});
|
},
|
//右下角定位按钮的点击事件
|
clickcontrol(){
|
let mapObjs = uni.createMapContext('mapId', this)
|
mapObjs.moveToLocation({
|
complete: res => {
|
console.log('移动完成:', res)
|
}
|
})
|
},
|
// 获取范围
|
async getEleSiteList() {
|
let array = []
|
let quan = await this.$u.api.getEleBusinessArea({})
|
if (quan.code === 200) {
|
let arrs = JSON.parse(quan.data)
|
array.push({
|
points: arrs.map(item => {
|
return {
|
latitude: item.lat,
|
longitude: item.lng
|
}
|
}),
|
fillColor: "#0077FF12",
|
strokeColor: "#0077FF",
|
strokeWidth: 3,
|
zIndex: 7
|
})
|
}
|
let res = await this.$u.api.eleSiteList({})
|
if (res.code === 200) {
|
res.data.forEach(item => {
|
let arr = JSON.parse(item.electronicFence)
|
item.electronicFence = arr.map(data => {
|
return {
|
latitude: data.lat,
|
longitude: data.lng
|
}
|
})
|
})
|
this.eleBusinessArea = res.data.map(item => {
|
return {
|
points: item.electronicFence,
|
title: item.name,
|
fillColor: "#0077FF4D",
|
strokeColor: "#0077FF",
|
strokeWidth: 3,
|
zIndex: 7
|
}
|
})
|
this.eleBusinessArea.forEach(item => {
|
let { latitude, longitude } = this.calculatePolygonCenter(item.points)
|
let num = distance(this.latitude, this.longitude, latitude, longitude)
|
this.markers.push({
|
id: Math.floor(Math.random() * 900) + 100,
|
width: 30,
|
height: 40,
|
isShow: false,
|
title: item.title,
|
distance: this.latitude && this.longitude ? num : '未知距离',
|
latitude: latitude,
|
longitude: longitude,
|
iconPath: '/static/icon/ic_park@2x.png',
|
customCallout: {
|
anchorY: 0,
|
anchorX: 0,
|
display: 'BYCLICK'
|
}
|
})
|
})
|
}
|
this.eleBusinessArea = [...array, ...this.eleBusinessArea]
|
},
|
// 计算多边形中心点
|
calculatePolygonCenter(polygonPoints) {
|
let x = 0, y = 0;
|
const numPoints = polygonPoints.length;
|
|
for (let i = 0; i < numPoints; i++) {
|
x += polygonPoints[i].latitude;
|
y += polygonPoints[i].longitude;
|
}
|
|
return {
|
latitude: x / numPoints,
|
longitude: y / numPoints
|
};
|
},
|
getSite() {
|
this.$u.api.rentSiteList()
|
.then(res => {
|
if (res.code === 200) {
|
this.markers = []
|
res.data.forEach((item, index) => {
|
let num = distance(this.latitude, this.longitude, item.latitude, item.longitude)
|
this.markers.push({
|
id: index,
|
width: 40,
|
height: 40,
|
isShow: true,
|
distance: this.latitude && this.longitude ? num : '未知距离',
|
latitude: item.latitude,
|
longitude: item.longitude,
|
title: item.name,
|
iconPath: '/static/icon/ic_bike@2x.png',
|
addr: item.addr,
|
customCallout: {
|
anchorY: 0,
|
anchorX: 0,
|
display: 'BYCLICK'
|
}
|
})
|
})
|
}
|
})
|
},
|
markertap(e) {
|
this.show = false
|
this.markers.forEach(item => {
|
if (item.id === e.markerId) {
|
this.rice = item.distance
|
item.customCallout.display = 'ALWAYS'
|
if (item.isShow) {
|
item.width = 50
|
item.height = 50
|
} else {
|
item.width = 40
|
item.height = 50
|
}
|
setTimeout(() => {
|
this.info = item
|
this.show = true
|
}, 300)
|
} else {
|
if (item.isShow) {
|
item.width = 40
|
item.height = 40
|
} else {
|
item.width = 30
|
item.height = 40
|
}
|
item.customCallout.display = 'BYCLICK'
|
}
|
})
|
},
|
navigation(item) {
|
uni.openLocation({
|
latitude: Number(item.latitude),
|
longitude: Number(item.longitude),
|
name: '测试名称',
|
address: '测试详细地址',
|
success: function() {
|
console.log('打开地图导航成功');
|
},
|
fail: function(err) {
|
console.log('打开地图导航失败', err);
|
}
|
});
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss" scoped>
|
.ditu {
|
width: 100vw;
|
height: 100vh;
|
.index_scancode {
|
width: 100%;
|
background: linear-gradient(360deg, #FFFFFF 0%, #FFFFFF 58%, #D0FFFD 100%);
|
box-shadow: 0rpx -6rpx 16rpx 0rpx rgba(0, 0, 0, 0.1);
|
border-radius: 32rpx 32rpx 0rpx 0rpx;
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
padding: 30rpx 20rpx;
|
box-sizing: border-box;
|
z-index: 9999;
|
|
.index_scancode_bottom {
|
width: 100%;
|
height: 96rpx;
|
line-height: 96rpx;
|
text-align: center;
|
background: #01B6AD;
|
box-shadow: 0rpx 6rpx 16rpx 0rpx rgba(1, 182, 173, 0.24);
|
border-radius: 46rpx;
|
font-size: 32rpx;
|
font-family: PingFangSC-Medium, PingFang SC;
|
font-weight: 500;
|
color: #FFFFFF;
|
}
|
}
|
.ditu_map {
|
width: 100%;
|
height: 100%;
|
.customCallout {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
padding: 16rpx 20rpx;
|
box-sizing: border-box;
|
height: 80rpx;
|
background: #FFFFFF;
|
border-radius: 50rpx;
|
box-shadow: 0rpx 0rpx 12rpx 0rpx rgba(0,0,0,0.1);
|
.image {
|
width: 28rpx;
|
height: 28rpx;
|
background-repeat: no-repeat;
|
background-size: 100% 100%;
|
}
|
.mm {
|
font-size: 28rpx;
|
font-family: PingFangSC-Regular, PingFang SC;
|
font-weight: 400;
|
color: #222222;
|
}
|
.h {
|
width: 2rpx;
|
height: 28rpx;
|
margin: 0 16rpx;
|
background-color: #E5E5E5;
|
}
|
.dh {
|
font-size: 28rpx;
|
font-family: PingFangSC-Regular, PingFang SC;
|
font-weight: 400;
|
color: #01B6AD;
|
}
|
}
|
}
|
.ditu_box {
|
width: 100%;
|
padding: 30rpx 20rpx;
|
box-sizing: border-box;
|
background: linear-gradient(360deg, #FFFFFF 0%, #FFFFFF 58%, #D0FFFD 100%);
|
box-shadow: 0rpx -6rpx 16rpx 0rpx rgba(0,0,0,0.1);
|
border-radius: 32rpx 32rpx 0rpx 0rpx;
|
.ditu_box_a {
|
width: 100%;
|
padding: 0 20rpx;
|
box-sizing: border-box;
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
text {
|
&:first-child {
|
font-size: 34rpx;
|
font-family: PingFangSC-Medium, PingFang SC;
|
font-weight: 500;
|
color: #222222;
|
}
|
&:last-child {
|
font-size: 26rpx;
|
font-family: PingFangSC-Regular, PingFang SC;
|
font-weight: 400;
|
color: #01B6AD;
|
}
|
}
|
}
|
.ditu_box_b {
|
width: 100%;
|
padding: 0 20rpx;
|
box-sizing: border-box;
|
font-size: 26rpx;
|
font-family: PingFangSC-Regular, PingFang SC;
|
font-weight: 400;
|
color: #666666;
|
margin-top: 6rpx;
|
}
|
.ditu_box_c {
|
width: 100%;
|
height: 96rpx;
|
line-height: 96rpx;
|
text-align: center;
|
background: #01B6AD;
|
box-shadow: 0rpx 6rpx 16rpx 0rpx rgba(1,182,173,0.24);
|
border-radius: 46rpx;
|
font-size: 32rpx;
|
font-family: PingFangSC-Medium, PingFang SC;
|
font-weight: 500;
|
color: #FFFFFF;
|
margin-top: 40rpx;
|
}
|
}
|
.search {
|
width: 100%;
|
position: absolute;
|
padding: 0 30rpx;
|
box-sizing: border-box;
|
bottom: calc(env(safe-area-inset-bottom) + 100rpx);
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
z-index: 9999;
|
.search_left {
|
width: 400rpx;
|
height: 60rpx;
|
// background: #FFFFFF;
|
// box-shadow: 0rpx 0rpx 12rpx 0rpx rgba(0,0,0,0.08);
|
border-radius: 30rpx;
|
display: flex;
|
align-items: center;
|
padding: 0 20rpx;
|
box-sizing: border-box;
|
image {
|
width: 28rpx;
|
height: 28rpx;
|
flex-shrink: 0;
|
}
|
text {
|
font-weight: 400;
|
font-size: 26rpx;
|
color: #222222;
|
margin-left: 10rpx;
|
flex-shrink: 0;
|
}
|
.search_left_x {
|
width: 2rpx;
|
height: 24rpx;
|
margin: 0 10rpx;
|
background-color: #E5E5E5;
|
flex-shrink: 0;
|
}
|
input {
|
flex: 1;
|
height: 100%;
|
font-weight: 400;
|
font-size: 26rpx;
|
color: #000000;
|
}
|
}
|
.dw {
|
width: 80rpx;
|
height: 80rpx;
|
}
|
}
|
}
|
</style>
|