<template> <view class="page"> <u-navbar title="地图模式" :border-bottom="false" :background="bgc" title-color='#fff' back-icon-color="#fff" title-size='44' height='50'></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" v-if="falga"> <view class="moshi"> <image src="https://api.ccttiot.com/smartmeter/img/static/uqv3e5ThWL8DqrRNBfoA" mode="" @click="btndt(1)"></image> <image src="https://api.ccttiot.com/smartmeter/img/static/u7yxUJZqgPzESeI4tmiz" mode="" @click="btndt(2)" v-if="isMch"></image> </view> <view class="saoyisao"> <view @click="scanQRCode"> <image src="https://api.ccttiot.com/smartmeter/img/static/uBh15vzRx6gV0wRQj7gi" mode=""></image> <text>扫一扫</text> </view> </view> </view> <view class="list_item" v-if="falgb"> <view class="list"> <view class="pic"> <image :src="listobj.picture" mode="aspectFill"></image> </view> <view class="cen"> <view class="cena" style="font-weight: 600;"> {{listobj.name == undefined ? '--' : listobj.name}} </view> <view class="cenb"> <image src="https://api.ccttiot.com/smartmeter/img/static/uHK2aJHvzEm3nbOPwpdr" mode=""></image> {{listobj.address == undefined ? '--' : listobj.address}} </view> <view class="cenc"> 共享时间:{{listobj.businessTimeStart == undefined ? '--' : listobj.businessTimeStart}}-{{listobj.businessTimeEnd == undefined ? '--' : listobj.businessTimeEnd}} <text class="bu">{{listobj.availableDeviceCount}}台可共享</text> </view> </view> </view> <view class="chakan" @click="btnchak(listobj.storeId)"> <view class=""> 本店共有{{listobj.deviceCount == undefined ? '--' : listobj.deviceCount}}台共享设备 </view> <view class=""> 查看 <u-icon name="arrow-right" color="#6863D9" size="24" style="margin-left: 10rpx;"></u-icon> </view> </view> <view class="anniu"> <view class="" @click="mapFun"> <image style="height: 41rpx;width: 38rpx;" class="picsm" src="https://api.ccttiot.com/smartmeter/img/static/u9Z7DXlWfjJtIrq5OEty" mode=""></image> 到这去 </view> <view class="" style="color: #fff;background-color: #8883F0;" @click="scanQRCode"> <image class="picsm" src="https://api.ccttiot.com/smartmeter/img/static/uvrsmSxGunHTI9S51ujn" mode=""></image> 扫一扫 </view> </view> </view> </view> </template> <script> export default { data() { return { latitude: '', // 初始纬度 longitude: '', // 初始经度 covers: [], // 覆盖物数组 index: 1, falga: true, falgb: false, storeId: '', listobj: {}, mapname: '', mapaddress: '', isMch: '', bgc: { backgroundColor: " #8883F0", }, mapScale: 15, mapContext: null, mapScaleInterval: null, listmap: [], } }, onLoad(option) { this.storeId = option.markerId if (option.markerId) { this.falga = false this.falgb = true } this.getxq() }, onReady() { this.mapContext = uni.createMapContext('map', this); this.mapScaleInterval = setInterval(this.updateMarkers, 1000); }, beforeDestroy() { // 在组件卸载前清除定时器 if (this.mapScaleInterval) { clearInterval(this.mapScaleInterval); this.mapScaleInterval = null; } }, // 分享到好友(会话) onShareAppMessage: function () { return { title: '创想物联', path: '/pages/shouye/index' } }, // 分享到朋友圈 onShareTimeline: function () { return { title: '创想物联', query: '', path: '/pages/shouye/index' } }, 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) => { if (item.deviceCount !== null && item.deviceCount > 0){ const shopCover = { id: parseFloat(item.storeId), latitude: item.lat, longitude: item.lng, width: 25, height: 30, iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uZXgsJE6hXbRSwbKILB4', borderColor:'#fff', borderRadius:5, bgColor: '#fff' }; this.covers.push(shopCover); } }); }, addMarkersWithLabels() { this.listmap.forEach((item) => { if (item.deviceCount !== null && item.deviceCount > 0){ const shopCover = { id: parseFloat(item.storeId), latitude: item.lat, longitude: item.lng, width: 25, height: 30, iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uZXgsJE6hXbRSwbKILB4', label: { content: item.name, anchorX: this.calculateAnchorX(item.name), fontWeight: 700, color: '#8883F0', textShadow: '2px 2px 0px white, -2px -2px 0px white, 2px -2px 0px white, -2px 2px 0px white', borderColor:'#fff', borderRadius:5, bgColor: '#fff' } } 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; // 英文长度加0.3,但视为两个中文字符长度 } } const totalLength = chineseLength + englishLength * 2; // 总长度(以中文字符为单位) return -totalLength * 6.5; // 假设每个中文字符对应的 anchorX 偏移是 -6.5 }, scanQRCode() { uni.scanCode({ onlyFromCamera: true, scanType: ['qrCode'], success: res => { function getQueryParam(url, paramName) { let regex = new RegExp(`[?&]${paramName}=([^&]*)`); let results = regex.exec(url); return results ? decodeURIComponent(results[1].replace(/\+/g, ' ')) : null; } let sceneValue = res.result let decodedValue = decodeURIComponent(sceneValue); let id = getQueryParam(decodedValue, 's') this.$u.get(`/app/device/${id}/withSuitList`).then((res) => { if (res.code == 200) { uni.navigateTo({ url: '/page_components/fuwu/index?id=' + id }) } }) }, fail: err => { console.error('扫描失败:', err); uni.showToast({ title: '扫描失败', icon: 'none' }); } }); }, btnchak(id) { uni.navigateTo({ url: '/page_fenbao/sbshouye?storeId=' + id }) }, getxq() { this.$u.get("/app/store/" + this.storeId).then(res => { if (res.code == 200) { this.listobj = res.data } }) }, getshanghu() { this.$u.get("/app/user/userInfo").then((res) => { if (res.code == 200) { this.isMch = res.data.isMch } }) }, mapFun() { uni.openLocation({ latitude: this.listobj.lat, //纬度 - 目的地/坐标点 longitude: this.listobj.lng, //经度 - 目的地/坐标点 name: this.mapname, //地点名称 address: this.mapaddress //详细地点名称 }); }, // 地图回正 async setMapScale(e, val) { let mapContext = uni.createMapContext('map', this); let setScale = () => { return new Promise((resolve, reject) => { mapContext.getScale({ success: r => { this.mapScale = 15 resolve() } }) }) }; await setScale(); mapContext.moveToLocation({ success: (res) => { const timer = setTimeout(() => { this.mapScale = 15 clearTimeout(timer); }, 500); }, }) }, getMyLocation() { uni.getLocation({ type: 'wgs84', success: (res) => { this.jinweidu = res.longitude + ',' + res.latitude this.latitude = Number(res.latitude.toFixed(5)) - 0.005 this.longitude = Number(res.longitude.toFixed(5)) + 0.005 this.setMapScale() // 请求附近的店铺 this.$u.get("/app/store/listNearBy?center=" + this.jinweidu + '&radius=' + 1000).then( res => { if (res.code == 200) { this.listmap = res.data // 假设返回的店铺数据在res.rows中,并且每个店铺有latitude和longitude字段 res.data.forEach(item => { if (item.deviceCount !== null && item.deviceCount > 0) { const shopCover = { id: parseFloat(item.storeId), latitude: item.lat, longitude: item.lng, width: 25, height: 30, iconPath: 'https://api.ccttiot.com/smartmeter/img/static/uZXgsJE6hXbRSwbKILB4', label: { content: item.name, 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: '#8883F0', textShadow: '2px 2px 0px white, -2px -2px 0px white, 2px -2px 0px white, -2px 2px 0px white', borderColor:'#fff', borderRadius:5, bgColor: '#fff' } }; this.covers.push(shopCover); } }); } }); }, fail: (err) => { console.error('获取位置失败:', err); } }); }, handleMarkerClick(e) { console.log(e); this.$u.get("/app/store/" + e.markerId).then(res => { if (res.code == 200) { this.listobj = res.data this.mapname = res.data.city this.mapaddress = res.data.address } }) this.falga = false this.falgb = true }, btntab(num) { this.index = num }, btndt(num) { if (num == 1) { uni.navigateBack() } }, btnitem() { this.falga = false this.falgb = true } }, mounted() { this.getMyLocation(); } } </script> <style lang="scss"> /deep/ .u-title { padding-bottom: 22rpx; } /deep/ .u-icon__icon { padding-bottom: 22rpx; } /deep/ .map { width: 100%; height: 100%; } page { background: linear-gradient(180deg, #D9D8FF 0%, rgba(255, 255, 255, 0) 100%); border-radius: 0rpx 0rpx 0rpx 0rpx; } .page { width: 750rpx; position: fixed; top: 0; left: 0; .list_item { position: fixed; bottom: 84rpx; left: 50%; transform: translateX(-50%); width: 706rpx; height: 420rpx; background: #FFFFFF; box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); border-radius: 20rpx; margin: auto; padding: 46rpx 40rpx; box-sizing: border-box; .chakan { display: flex; justify-content: space-between; width: 625rpx; height: 60rpx; line-height: 60rpx; padding: 0 22rpx; box-sizing: border-box; background: #D9D8FF; border-radius: 8rpx 8rpx 8rpx 8rpx; margin-top: 10rpx; view { font-size: 28rpx; color: #8883F0; } } .anniu { display: flex; justify-content: space-between; margin-top: 20rpx; view { width: 300rpx; height: 82rpx; line-height: 80rpx; border-radius: 45rpx 45rpx 45rpx 45rpx; border: 2rpx solid #8883F0; text-align: center; font-weight: 500; font-size: 36rpx; color: #8883F0; ; } } .list { display: flex; padding-bottom: 16rpx; .pic { width: 150rpx; height: 150rpx; border-radius: 20rpx; image { width: 150rpx; height: 150rpx; mode: "aspectFill"; margin-top: 10rpx; border-radius: 20rpx; } } .cen { margin-left: 20rpx; .cena { font-weight: 500; font-size: 30rpx; color: #3D3D3D; line-height: 38rpx; } .cenb { font-weight: 400; font-size: 26rpx; color: #3D3D3D; line-height: 32rpx; margin-top: 14rpx; image { display: inline-block; width: 22rpx; height: 22rpx; margin-right: 6rpx; } } .cenc { font-weight: 400; font-size: 26rpx; color: #3D3D3D; line-height: 32rpx; margin-top: 14rpx; text { display: inline-block; padding: 4rpx 18rpx; box-sizing: border-box; border-radius: 20rpx; } .bu { margin-left: 22rpx; background: #D9D8FF; color: #4D48B5; } } } .right { padding-top: 40rpx; image { width: 40rpx; height: 40rpx; } text { display: block; font-weight: 400; font-size: 20rpx; color: #808080; line-height: 28rpx; } } } } .picsm { width: 48rpx; height: 48rpx; vertical-align: middle; display: inline-block; margin-bottom: 10rpx; margin-right: 10rpx; } .dtxs { width: 100%; height: 100vh; position: fixed; top: 0; left: 0; z-index: -1; } .listbox { background: #FFFFFF; border-radius: 64rpx 64rpx 0 0; box-shadow: 0rpx 10rpx 64rpx 0rpx rgba(0, 0, 0, 0.08); height: 186rpx; width: 100%; overflow-y: scroll; position: fixed; bottom: 0; left: 0; .saoyisao { margin-top: 44rpx; view { border-radius: 54rpx 54rpx 54rpx 54rpx; text-align: center; width: 676rpx; height: 102rpx; background: linear-gradient(90deg, #8883F0 0%, #837EEB 100%); line-height: 102rpx; margin: auto; image { width: 56rpx; height: 56rpx; vertical-align: middle; display: inline-block; margin-bottom: 12rpx; margin-right: 10rpx; } text { font-weight: 500; font-size: 40rpx; color: #FFFFFF; } } } .moshi { position: fixed; bottom: 210rpx; left: 30rpx; z-index: 99; image { width: 210rpx; height: 74rpx; } } .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; } } } .active { border-bottom: 10rpx solid #D9D8FF; border-radius: 7rpx; padding-bottom: 10rpx; font-weight: 700; } </style>