powerbank/pages/nearbystores/index.vue
2024-05-31 18:01:02 +08:00

425 lines
12 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="page">
<u-navbar title="附近共享" :border-bottom="false" :background="bgc" title-color='#000' title-size='36' height='58'></u-navbar>
<view class="dtxs">
<map class='map' id="map" :latitude="latitude" :longitude="longitude" @markertap="handleMarkerClick"
:show-location="true" :markers="covers" :scale="mapScale" />
</view>
<view class="listbox">
<view class="list" v-for="(item,index) in gxlist" :key="index">
<view class="pic">
<image :src="item.picture" mode=""></image>
</view>
<view class="cen" @click="handleMarkerClicks(item)">
<view class="cena" style="font-weight: 600;">
{{item.name}}
</view>
<view class="cenb">
{{item.address}}
</view>
<view class="cenc">
营业时间{{item.businessTimeStart}}-{{item.businessTimeEnd}}
<view class="" style="display: flex;margin-top: 20rpx;">
<view class="wz" style="color: #109F64;" v-if="item.availableDeviceCount > 0">可租借</view>
<view class="wz" style="color: #109F64;" v-if="item.slotCount - item.deviceCount > 0">可归还</view>
<view class="wz" style="background-color: #FFEFEF;color: #FF4444;" v-if="item.slotCount - item.deviceCount == 0">不可还</view>
</view>
</view>
</view>
<view class="right">
<image src="https://api.ccttiot.com/smartmeter/img/static/uraUDWkEx5OvJB29kMnS" mode="" @click="mapFun(item)"></image>
<text>{{String(item.distance).split('.')[0]}}m</text>
</view>
</view>
<view class="" style="width: 448rpx;height: 448rpx;margin: auto;margin-top: 100rpx;text-align: center;"
v-if="showflag">
<image style="width: 448rpx;height: 448rpx;"
src="https://api.ccttiot.com/smartmeter/img/static/ufLi6IZd5kh1MIEZFYTo" mode=""></image>
<view class="" style="font-size: 30rpx;color: #ccc;margin-top: 30rpx;">附近暂无店铺...</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
latitude: '',
longitude: '',
covers: [],
isMch:false,
gxlist:[],
bgc:{
background:'#25D088'
},
listmap: [],
mapScale: 15,
datetime: 0,
dingobj: '',
mapContext: null,
mapScaleInterval: null,
showflag: false
}
},
onLoad() {
},
onReady() {
this.mapContext = uni.createMapContext('map', this);
this.mapScaleInterval = setInterval(this.updateMarkers, 1000);
},
beforeDestroy() {
if (this.mapScaleInterval) {
clearInterval(this.mapScaleInterval);
this.mapScaleInterval = null;
}
},
onShow() {
this.getshanghu()
},
methods: {
updateMarkers() {
this.mapContext.getScale({
success: (res) => {
this.covers = []; // 清空之前的覆盖物
if (res.scale <= 14) {
this.addMarkersWithoutLabels();
} else {
this.addMarkersWithLabels();
}
},
fail: (error) => {
console.error('获取地图缩放级别失败:', error);
},
});
},
addMarkersWithoutLabels() {
this.listmap.forEach((item) => {
const shopCover = {
id: parseFloat(item.storeId),
latitude: item.lat,
longitude: item.lng,
width: 25,
height: 30,
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uI3B6yPwtiUBD3vafLtw',
};
this.covers.push(shopCover);
});
},
addMarkersWithLabels() {
this.listmap.forEach((item) => {
const distance = this.getDistance(this.latitude, this.longitude, item.lat, item.lng)
const shopCover = {
id: parseFloat(item.storeId),
latitude: item.lat,
longitude: item.lng,
width: 25,
height: 30,
distance: distance,
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uI3B6yPwtiUBD3vafLtw',
label: {
content: item.name,
anchorX:this.calculateAnchorX(item.name),
fontWeight: 700,
color: '#25D088',
textShadow: '2px 2px 0px #000, -2px -2px 0px #000, 2px -2px 0px #000, -2px 2px 0px #000',
rotate:20
}
}
this.covers.push(shopCover);
});
},
calculateAnchorX(name) {
let chineseLength = 0;
let englishLength = 0;
for (let i = 0; i < name.length; i++) {
const charCode = name.charCodeAt(i);
if (charCode >= 0x4e00 && charCode <= 0x9fa5) {
chineseLength++;
} else if (/[a-zA-Z]/.test(name[i])) {
englishLength = englishLength+0.3;
}
}
const totalLength = chineseLength + englishLength * 2;
return -totalLength * 6.5
},
// 跳转导航
mapFun(item) {
uni.openLocation({
latitude: item.lat,
longitude: item.lng,
name: item.county,
address: item.address
});
},
getshanghu(){
this.$u.get("/app/user/userInfo").then((res) => {
if (res.code == 200) {
this.isMch = res.data.isMch
}
})
},
getMyLocation() {
uni.getLocation({
type: 'wgs84',
success: (res) => {
this.latitude = res.latitude;
this.longitude = res.longitude;
this.jinweidu = this.longitude + ',' + this.latitude;
// 请求附近的店铺
this.$u.get("/app/store/listNearBy?center=" + this.jinweidu + '&radius=' + 1000).then(res => {
if (res.code == 200) {
this.gxlist = res.data;
if (this.gxlist.length > 0) {
this.showflag = false
} else {
this.showflag = true
}
this.listmap = res.data
this.gxlist.forEach(item => {
// 计算距离
const distance = this.getDistance(this.latitude, this.longitude, item.lat, item.lng);
// 将距离添加到店铺对象中
item.distance = distance;
// 创建店铺覆盖物对象
const shopCover = {
id: parseFloat(item.storeId),
latitude: item.lat,
longitude: item.lng,
width: 25,
height: 30,
iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uI3B6yPwtiUBD3vafLtw',
distance: distance ,// 可以在这里也添加距离到覆盖物对象中,但通常只需要在店铺对象中
label: {
content: item.name,
// anchorX:-20,
// textAlign: 'center'
anchorX: (() => {
if (item.name.length <= 2) {
return -12
} else if (item.name.length <= 3) {
return -20
} else if (item.name.length <= 4) {
return -25
} else if (item.name.length <= 5) {
return -30
} else if (item.name.length <= 6) {
return -35
} else if (item.name.length <= 8) {
return -40
} else if (item.name.length <=
10) {
return -45
} else {
return -item.name.length * 5
}
})(),
fontWeight: 700,
color: '#25D088',
textShadow: '2px 2px 0px white, -2px -2px 0px white, 2px -2px 0px white, -2px 2px 0px white',
}
};
this.covers.push(shopCover);
});
}
}).catch(error => {
console.error('请求店铺列表失败:', error);
});
},
fail: (err) => {
console.error('获取位置失败:', err);
}
});
},
// 计算距离多少米
getDistance(lat1, lon1, lat2, lon2) {
const R = 6371000; // 地球半径,单位:米
const phi1 = lat1 * Math.PI / 180;
const phi2 = lat2 * Math.PI / 180;
const deltaPhi = (lat2 - lat1) * Math.PI / 180;
const deltaLambda = (lon2 - lon1) * Math.PI / 180;
const a = Math.sin(deltaPhi / 2) * Math.sin(deltaPhi / 2) + Math.cos(phi1) * Math.cos(phi2) * Math.sin(deltaLambda / 2) * Math.sin(deltaLambda / 2);
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
const distance = R * c;
return distance;
},
handleMarkerClick(event) {
const markerId = event.markerId;
uni.navigateTo({
url: '/page_user/ditu?markerId=' + markerId
})
},
handleMarkerClicks(item) {
const markerId = item.storeId;
uni.navigateTo({
url: '/page_user/ditu?markerId=' + markerId
})
},
},
mounted() {
this.getMyLocation();
}
}
</script>
<style lang="scss">
/deep/ .u-title,
/deep/ .uicon-nav-back {
padding-bottom: 40rpx;
}
/deep/ .map{
width: 100%;
height: 100%;
}
page {
background: linear-gradient(180deg, #25D088 0%, rgba(255, 255, 255, 0) 100%);
border-radius: 0rpx 0rpx 0rpx 0rpx;
}
.page {
width: 750rpx;
position: fixed;
top: 0;
left: 0;
.dtxs{
width: 100%;
height: 70vh;
position: fixed;
top: 0;
left: 0;
z-index: -1;
}
.listbox{
margin-top: 820rpx;
background: #FFFFFF;
border-radius: 64rpx 64rpx 0 0;
box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0,0,0,0.08);
padding-left: 32rpx;
padding-right: 32rpx;
box-sizing: border-box;
height: 40vh;
overflow-y: scroll;
padding-bottom: 400rpx;
.moshi{
position: fixed;
top: 570rpx;
left: 30rpx;
z-index: 99;
image{
width: 210rpx;
height: 62rpx;
}
.img{
height: 50rpx;
margin-bottom: 8rpx;
}
}
.title{
border-radius: 64rpx 64rpx 0 0;
display: flex;
justify-content: space-between;
font-weight: 500;
font-size: 36rpx;
color: #3D3D3D;
line-height: 160rpx;
padding: 0 76rpx;
width: 100%;
background-color: #fff;
position: fixed;
height: 160rpx;
top: 40vh;
left: 0;
padding-bottom: 20rpx;
}
.list{
display: flex;
// justify-content: space-between;
margin-top: 44rpx;
border-bottom: 1px solid #eee;
padding-bottom: 16rpx;
.pic{
width: 134rpx;
height: 134rpx;
background-color: #D9D8FF;
border-radius: 10rpx;
margin-right: 20rpx;
image{
width: 100%;
height: 100%;
border-radius: 20rpx;
}
}
.cen{
width: 488rpx;
.cena{
font-weight: 500;
font-size: 28rpx;
color: #3D3D3D;
line-height: 38rpx;
}
.cenb{
font-weight: 400;
font-size: 24rpx;
color: #3D3D3D;
line-height: 32rpx;
margin-top: 14rpx;
}
.cenc{
font-weight: 400;
font-size: 24rpx;
color: #3D3D3D;
line-height: 32rpx;
margin-top: 14rpx;
// display: flex;
.wz{
font-size: 20rpx;
margin-left: 5rpx;
padding: 4rpx 14rpx;
box-sizing: border-box;
// width:100rpx;
border-radius: 20rpx;
text-align: center;
}
text{
display: inline-block;
padding: 4rpx 18rpx;
box-sizing: border-box;
border-radius: 20rpx;
}
.bu{
margin-left: 10rpx;
background:#D9D8FF;
color: #4D48B5;
}
}
}
.right{
padding-top: 40rpx;
text-align: center;
image{
width: 40rpx;
height: 40rpx;
}
text{
display: block;
font-weight: 400;
font-size: 20rpx;
color: #808080;
line-height: 28rpx;
}
}
}
}
}
.active{
border-bottom: 10rpx solid #D9D8FF;
border-radius: 7rpx;
padding-bottom: 10rpx;
font-weight: 700;
}
</style>