<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>