You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

501 lines
12 KiB

<template>
<view class="section">
<!-- <view class="cu-bar search bg-white searchIn">
<view class="search-form round"><text class="cuIcon-search"></text>
<input type="text" placeholder="搜索目的地" confirm-type="search" @input="inputSearch"
v-model="stationName" />
</view>
</view> -->
<view class="map">
<map style="width: 100%; height:100%; z-index: 0;" show-location='true' ref="map" id="map"
:latitude="latitude" :longitude="longitude" :markers="marker.markers" :scale="scale"
@markertap="callouttap" @callouttap='callouttap'>
<!-- <view class="" v-if="showSearch">
<scroll-view scroll-y="true" class="scrollView">
<view class="cu-bar bg-white solid-bottom" v-for="item in searchData.searchList" :key="item.id"
@click="goMap(item)">
<view class="action text-lg">{{item.stationName}}</view>
<view class="action text-df text-gray">{{item.distance}}km</view>
</view>
</scroll-view>
</view> -->
</map>
<view class="goToast" v-if="showToast">
<view class=" cu-card bg-white margin-sm card-border">
<view class="cu-item shadow">
<view class="flex padding-tb-sm">
<view class="flex">
<view class="titleState">营业中</view>
</view>
<view class="name">{{searchStationName}}</view>
</view>
<view class="flex padding-tb-sm justify-between">
<view class="flex">
<view class="lg text-gray cuIcon-location"></view>
<view class="titleFont text-df text-gray">{{searchAreaName}}</view>
</view>
<view class="searchDistance text-df">{{searchDistance.toFixed(2)}}km</view>
</view>
<view class="flex padding-tb-xs justify-center">
<view class="flex">
<view class="goDetail" @click="goDetail"></view>
</view>
</view>
</view>
</view>
</view>
</view>
<uv-notify ref="errornotify" message="当前无操作权限,请审核通过后再试" type="error"></uv-notify>
<uv-popup ref="bottom_popup" round="30" :overlay="false">
<view style="position: relative;">
<view class="line_tops" @click="handle_close_popup"></view>
<view class="position_right_tops" @click.stop="goMap_address(address.longitude,address.latitude)">
<uv-icon name="arrow-up-fill" size="21" color="#fff"></uv-icon>
<view class="" style="font-size: 12px;">
导航
</view>
</view>
<view style="padding: 0 20rpx;">
<view class="cu-item shadow">
<view class="flex padding-tb-sm">
<view class="flex">
<view class="titleState">营业中</view>
</view>
<view class="name">{{searchStationName}}</view>
</view>
<view class="flex padding-tb-sm justify-between">
<view class="flex">
<view class="lg text-gray cuIcon-location"></view>
<view class="titleFont text-df text-gray">{{searchAreaName}}</view>
</view>
<view class="searchDistance text-df">
{{searchDistance == null? '--': searchDistance.toFixed(2) }}km
</view>
</view>
<view class="flex padding-tb-xs justify-center">
<view class="flex">
<view class="goDetail" @click="goDetail"></view>
</view>
</view>
</view>
</view>
</view>
</uv-popup>
</view>
</template>
<script setup>
import config from '@/common/config/config.js';
import piniaPro from '@/stores/piniaPro.js';
import {
globalStore
} from "@/stores/globalData.js";
const globalData = globalStore(piniaPro);
import {
reactive,
ref,
} from "vue";
import {
onLoad,
onShow,
} from "@dcloudio/uni-app";
let id = ref(0) // 使用 marker点击事件 需要填写id
let latitude = ref()
let longitude = ref()
let scale = ref(12)
let marker = reactive({
markers: []
})
const popup_mean = ref(null)
const bottom_popup = ref(false)
const bdlongitude = ref()
const bdlatitude = ref()
const stationName = ref()
const searchData = reactive({
searchList: []
})
const showSearch = ref(false)
const showToast = ref(false)
const searchStationName = ref()
const searchAreaName = ref()
const searchDistance = ref(null)
const showPoints = reactive({
pointList: []
})
const searchNo = ref()
const searchID = ref()
const pointsList = ref()
const realNameAuthFlag = reactive(uni.getStorageSync("realNameAuthFlag"))
const errornotify = ref(null)
const address = ref({
longitude: null,
latitude: null,
stationName: null,
stationLocation: null,
})
onLoad(() => {
})
onShow(() => {
// console.log(globalData.isLogin,'调用了')
// if (globalData.isLogin) {
// setTimeout(() => {
// localtion_map()
// }, 500)
// }
localtion_map()
})
const localtion_map = () => {
// let location = uni.getStorageSync('location');
// let longitude = ''
// let latitude = ''
uni.getLocation({
type: 'gcj02',
geocode: true,
success: (res) => {
console.log(res, 'res');
address.value = res
uni.setStorageSync('location', res)
longitude.value = res.longitude
latitude.value = res.latitude
handle_maps_now()
},
fail: (err) => {
// console.log(err, 'uni.getLocation解析失败');
},
});
}
const handle_close_popup = () => {
bottom_popup.value.close()
}
const goMap_address = (longitude, latitude) => {
uni.openLocation({
latitude: Number(latitude),
longitude: Number(longitude),
name: undefined, //企业名称
address: undefined, //详细地址
success: function() {
console.log('success');
},
fail: (err) => {
console.log(err, 'err');
}
});
}
const handle_maps_now = async () => {
let data = {
latitude: latitude.value,
longitude: longitude.value,
distance: 400
}
// console.log(data, 'data');
await uni.$request({
url: config.baseUrl + "app-api/cloud/op/nearbyStation",
method: 'POST',
data: data,
}).then((res) => {
// console.log(res, '地址');
if (res.data.data.list.length > 0) {
let copy = JSON.parse(JSON.stringify(res.data.data.list))
pointsList.value = copy
showPoints.pointList = copy
setMarkersAndCluster(showPoints.pointList) // 3、调用聚合功能
}
})
}
const setMarkersAndCluster = (markerList) => {
let mapContext = uni.createMapContext('map')
// 1.组装数据之后并赋值给地图上的marker
const allMarkers = Array.from(markerList).map((e, i) => {
// console.log(e,'e')
return {
id: e.id,
longitude: e.longitude,
latitude: e.latitude,
iconPath: '../../static/home/marker.png',
rotate: 0, // 旋转度数
width: 50, //宽
height: 50, //高
alpha: 1, //透明
joinCluster: true, //参与点聚合
callout: {
content: e.stationName,
color: '#000',
fontSize: 16,
display: 'ALWAYS',
padding: 8,
bgColor: "#fff",
borderRadius: 5
},
}
});
marker.markers = allMarkers
mapContext.moveToLocation({
longitude: Number(marker.markers[0].longitude),
latitude: Number(marker.markers[0].latitude)
})
// 2.初始化点聚合的配置,未调用时采用默认配置
mapContext.initMarkerCluster({
enableDefaultStyle: false, // 是否启用默认的聚合样式(是否用自定义图标)
zoomOnClick: true,
gridSize: 60,
complete(res) {
// console.log('initMarkerCluster', res)
}
});
// 3.发生聚合时给聚合点设置marker标签
mapContext.on('markerClusterCreate', res => {
// console.log('clusterCreate', res)
const clusters = res.clusters
const markers = clusters.map(cluster => {
const {
center,
clusterId,
markerIds
} = cluster
return {
...center,
width: 0,
height: 0,
clusterId, // 必须
label: {
content: markerIds.length + '',
fontSize: 12,
color: '#fff',
width: 50,
height: 50,
bgColor: '#4C91FF',
borderRadius: 10,
textAlign: 'center',
anchorX: 0,
anchorY: -50,
}
}
})
// 4. 添加聚合簇标签
mapContext.addMarkers({
markers,
clear: false,
complete(res) {
// console.log('clusterCreate addMarkers', res)
}
})
})
}
const goMap = (e) => {
showSearch.value = false //关闭搜索展示列表
showToast.value = true
// console.log(e, 'eeeeeeeeeee');
searchStationName.value = e.stationName
searchAreaName.value = e.areaName
searchDistance.value = e.distance
searchNo.value = e.stationNo
let flag = marker.markers.some((item) => {
item.longitude == e.longitude
item.latitude == e.latitude
})
if (flag) {
uni.createMapContext('map').moveToLocation({
longitude: Number(e.longitude),
latitude: Number(e.latitude)
})
} else {
// 展示点位
let posArr = [{
id: e.id,
longitude: e.longitude,
latitude: e.latitude,
iconPath: '../../../static/home/marker.png',
rotate: 0, // 旋转度数
width: 50, //宽
height: 50, //高
alpha: 1, //透明
callout: {
content: e.stationName,
color: '#000',
fontSize: 16,
display: 'ALWAYS',
padding: 8,
bgColor: "#fff",
borderRadius: 5
}
}]
marker.markers.push(...posArr)
// console.log(marker.markers, 'marker');
uni.createMapContext('map').moveToLocation({
longitude: Number(e.longitude),
latitude: Number(e.latitude)
})
}
}
const emit = defineEmits(['handle_errornotify']);
const goDetail = () => {
if (!uni.getStorageSync("userInfo")) {
uni.showToast({
title: '请先完成登录',
duration: 2000,
icon: 'error'
});
return;
} else if (uni.getStorageSync("realNameAuthFlag") != 1) {
// errornotify.value.show()
emit('handle_errornotify')
return
} else {
if (searchNo.value) {
let station = searchNo.value
uni.navigateTo({
url: '/pages/index/stationDetails/stationDetails?station=' + JSON.stringify(station) +
'&distance=' +
JSON.parse(searchDistance.value) + '&searchID=' + JSON.parse(searchID.value)
})
}
}
}
const callouttap = (e) => {
let showInf = pointsList.value.filter((item) => {
return item.id == e.detail.markerId
})
searchStationName.value = showInf[0].stationName
searchAreaName.value = showInf[0].areaName
searchDistance.value = showInf[0].distance
searchNo.value = showInf[0].stationNo
searchID.value = showInf[0].id
bottom_popup.value.open('bottom')
// showToast.value = !showToast.value
}
const handle_open = (showInf) => {
for (let item of pointsList.value) {
if (showInf.id == item.id) {
// console.log(item,'平移了');
uni.createMapContext('map').moveToLocation({
longitude: item.longitude,
latitude: item.latitude
})
}
}
// console.log(showInf,'showInf');
// console.log(pointsList.value,'pointsList.value');
}
defineExpose({
handle_open
})
</script>
<style lang="scss">
.section {
width: 100%;
height: 100%;
border-radius: 16rpx;
overflow: hidden;
// height: 100vh;
position: relative;
}
.searchIn {
height: 100rpx;
}
.map {
width: 100%;
height: 100%;
// height: calc(100% - 100rpx);
// overflow: hidden;
// overflow-y: auto;
}
.goToast {
width: 100%;
position: absolute;
bottom: 1%;
z-index: 99;
}
.card-border {
border-radius: 8px;
}
.titleState {
padding: 8rpx 16rpx;
border: 1px solid #4C91FF;
border-radius: 5px;
background-color: #4C91FF;
color: #fff;
}
.name {
font-size: 36rpx;
padding: 8rpx 16rpx;
}
.goDetail {
border: 1px solid #4C91FF;
padding: 8rpx 32rpx;
color: #4C91FF;
border-radius: 20px;
}
.goMap {
width: 24rpx;
height: 24rpx;
color: #4C91FF;
background: url('/static/home/goMap.svg') no-repeat;
background-size: 100% 100%;
}
.searchDistance {
color: #4C91FF;
}
.scrollView {
height: calc(100vh - 100rpx);
}
.line_tops {
width: 20%;
height: 10rpx;
margin: 20rpx auto;
background: #e5e5e5;
border-radius: 5rpx;
}
.position_right_tops {
width: 100rpx;
height: 100rpx;
background: #2bbd69;
border-radius: 50%;
position: absolute;
right: 20rpx;
top: 10rpx;
color: #fff;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}
</style>