<template>
|
<view class="map-selector-container">
|
<view class="search-bar">
|
<input
|
class="search-input"
|
placeholder="请输入地址"
|
v-model="searchKeyword"
|
@input="onSearchInput"
|
@focus="onSearchFocus"
|
/>
|
<button class="search-btn" @click="searchAddress">搜索</button>
|
</view>
|
|
<!-- 微信小程序使用原生map组件 -->
|
<view class="map-container" id="mapContainer">
|
<!-- #ifdef MP-WEIXIN -->
|
<map
|
id="map"
|
:longitude="longitude"
|
:latitude="latitude"
|
:markers="markers"
|
:polyline="polyline"
|
:circles="circles"
|
:controls="controls"
|
:include-points="includePoints"
|
:show-location="true"
|
@markertap="onMarkerTap"
|
@callouttap="onCalloutTap"
|
@controltap="onControlTap"
|
@regionchange="onRegionChange"
|
@tap="onMapTap"
|
class="map-webview"
|
></map>
|
<!-- #endif -->
|
|
<!-- H5平台使用web-view加载百度地图 -->
|
<!-- #ifdef H5 -->
|
<web-view
|
v-if="baiduMapUrl"
|
:src="baiduMapUrl"
|
class="map-webview"
|
@message="onWebviewMessage"
|
></web-view>
|
<!-- #endif -->
|
|
<view class="map-placeholder" v-if="!isMapLoaded">
|
<text>地图加载中...</text>
|
</view>
|
</view>
|
|
<view class="address-list" v-if="searchResults.length > 0">
|
<view
|
class="address-item"
|
v-for="(item, index) in searchResults"
|
:key="index"
|
@click="selectAddress(item)"
|
>
|
<view class="address-title">{{ item.title }}</view>
|
<view class="address-detail">{{ item.address }}</view>
|
</view>
|
</view>
|
|
<view class="selected-address" v-if="selectedAddress">
|
<view class="address-title">选中地址:</view>
|
<view class="address-detail">{{ selectedAddress.title }}</view>
|
<view class="address-detail">{{ selectedAddress.address }}</view>
|
<button class="confirm-btn" @click="confirmAddress">确认选择</button>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
export default {
|
name: 'MapSelector',
|
props: {
|
// 初始地址
|
initialAddress: {
|
type: String,
|
default: ''
|
}
|
},
|
data() {
|
return {
|
searchKeyword: '',
|
searchResults: [],
|
selectedAddress: null,
|
isMapLoaded: false,
|
// H5平台相关
|
baiduMapUrl: '',
|
ak: '您的百度地图AK',
|
// 微信小程序相关
|
longitude: 113.324520,
|
latitude: 23.099994,
|
markers: [],
|
polyline: [],
|
circles: [],
|
controls: [],
|
includePoints: []
|
}
|
},
|
mounted() {
|
// #ifdef H5
|
// 初始化百度地图
|
this.initBaiduMap()
|
// #endif
|
|
// #ifdef MP-WEIXIN
|
// 初始化微信小程序地图
|
this.initWechatMap()
|
// #endif
|
|
if (this.initialAddress) {
|
this.searchKeyword = this.initialAddress
|
// 延迟设置焦点,避免跨域问题
|
setTimeout(() => {
|
// 不自动聚焦,让用户手动点击
|
}, 500)
|
}
|
},
|
methods: {
|
// 搜索框获得焦点事件
|
onSearchFocus() {
|
// 用户主动聚焦,不会触发跨域问题
|
console.log('搜索框获得焦点')
|
},
|
|
// #ifdef H5
|
// 处理web-view消息
|
onWebviewMessage(e) {
|
// 处理来自web-view的消息
|
console.log('收到来自web-view的消息:', e)
|
},
|
|
// 初始化百度地图(H5平台)
|
initBaiduMap() {
|
// 构造百度地图URL
|
this.baiduMapUrl = `https://api.map.baidu.com/mapjs?v=3.0&ak=${this.ak}&callback=initMap`
|
this.isMapLoaded = true
|
|
// 延迟加载地图,避免阻塞
|
setTimeout(() => {
|
this.isMapLoaded = true
|
}, 1000)
|
},
|
// #endif
|
|
// #ifdef MP-WEIXIN
|
// 初始化微信小程序地图
|
initWechatMap() {
|
// 获取用户位置
|
uni.getLocation({
|
type: 'gcj02',
|
success: (res) => {
|
this.longitude = res.longitude
|
this.latitude = res.latitude
|
|
// 设置默认标记
|
this.markers = [{
|
id: 0,
|
longitude: this.longitude,
|
latitude: this.latitude,
|
title: '当前位置',
|
iconPath: '/static/icons/location.png',
|
width: 30,
|
height: 30
|
}]
|
|
// 延迟设置加载状态,确保地图完全初始化
|
setTimeout(() => {
|
this.isMapLoaded = true
|
}, 500)
|
},
|
fail: () => {
|
// 延迟设置加载状态
|
setTimeout(() => {
|
this.isMapLoaded = true
|
}, 500)
|
this.$modal.showToast('获取位置失败')
|
}
|
})
|
},
|
|
// 地图点击事件
|
onMapTap(e) {
|
// 在点击位置添加标记
|
const { longitude, latitude } = e.detail
|
this.markers = [{
|
id: Date.now(),
|
longitude,
|
latitude,
|
title: '选中位置',
|
iconPath: '/static/icons/location-selected.png',
|
width: 30,
|
height: 30
|
}]
|
|
// 逆地址解析获取地址信息
|
this.reverseGeocode(latitude, longitude)
|
},
|
|
// 逆地址解析
|
reverseGeocode(lat, lng) {
|
// 这里应该调用后台API进行逆地址解析
|
// 模拟数据
|
this.selectedAddress = {
|
title: '选中位置',
|
address: `经纬度: ${lat.toFixed(6)}, ${lng.toFixed(6)}`,
|
lat: lat,
|
lng: lng
|
}
|
},
|
// #endif
|
|
// 搜索地址
|
searchAddress() {
|
if (!this.searchKeyword) {
|
this.$modal.showToast('请输入地址')
|
return
|
}
|
|
// 在实际项目中,这里应该调用对应平台的地图API
|
// 例如H5平台调用百度地图API,微信小程序调用微信地图API
|
|
// 模拟搜索结果
|
this.searchResults = [
|
{
|
title: this.searchKeyword + '附近地点1',
|
address: '广东省广州市天河区' + this.searchKeyword + '123号',
|
lat: 23.123 + Math.random() * 0.1,
|
lng: 113.321 + Math.random() * 0.1
|
},
|
{
|
title: this.searchKeyword + '附近地点2',
|
address: '广东省广州市越秀区' + this.searchKeyword + '456号',
|
lat: 23.145 + Math.random() * 0.1,
|
lng: 113.289 + Math.random() * 0.1
|
},
|
{
|
title: this.searchKeyword + '附近地点3',
|
address: '广东省广州市白云区' + this.searchKeyword + '789号',
|
lat: 23.167 + Math.random() * 0.1,
|
lng: 113.345 + Math.random() * 0.1
|
}
|
]
|
},
|
|
// 输入框输入事件
|
onSearchInput() {
|
// 防抖搜索
|
},
|
|
// 选择地址
|
selectAddress(item) {
|
this.selectedAddress = item
|
this.markLocation(item.lat, item.lng)
|
},
|
|
// 在地图上标记位置
|
markLocation(lat, lng) {
|
// #ifdef H5
|
// H5平台标记位置逻辑
|
console.log(`H5平台标记位置: ${lat}, ${lng}`)
|
this.$modal.showToast(`已标记位置`)
|
// #endif
|
|
// #ifdef MP-WEIXIN
|
// 微信小程序标记位置逻辑
|
this.longitude = lng
|
this.latitude = lat
|
this.markers = [{
|
id: Date.now(),
|
longitude: lng,
|
latitude: lat,
|
title: item.title,
|
iconPath: '/static/icons/location-selected.png',
|
width: 30,
|
height: 30
|
}]
|
// #endif
|
},
|
|
// 确认选择地址
|
confirmAddress() {
|
if (!this.selectedAddress) {
|
this.$modal.showToast('请先选择地址')
|
return
|
}
|
|
// 触发事件,将选中的地址传递给父组件
|
this.$emit('addressSelected', {
|
title: this.selectedAddress.title,
|
address: this.selectedAddress.address,
|
lat: this.selectedAddress.lat,
|
lng: this.selectedAddress.lng
|
})
|
}
|
}
|
}
|
</script>
|
|
<style lang="scss">
|
.map-selector-container {
|
width: 100%;
|
height: 100%;
|
display: flex;
|
flex-direction: column;
|
|
.search-bar {
|
display: flex;
|
padding: 20rpx;
|
background-color: white;
|
|
.search-input {
|
flex: 1;
|
height: 70rpx;
|
padding: 0 20rpx;
|
border: 1rpx solid #eee;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
}
|
|
.search-btn {
|
width: 120rpx;
|
height: 70rpx;
|
margin-left: 20rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 28rpx;
|
}
|
}
|
|
.map-container {
|
flex: 1;
|
height: 400rpx;
|
|
.map-webview {
|
width: 100%;
|
height: 100%;
|
}
|
|
// 微信小程序地图样式
|
map {
|
width: 100%;
|
height: 100%;
|
}
|
|
.map-placeholder {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
height: 100%;
|
background-color: #f5f5f5;
|
font-size: 28rpx;
|
color: #999;
|
}
|
}
|
|
.address-list {
|
max-height: 300rpx;
|
overflow-y: auto;
|
background-color: white;
|
|
.address-item {
|
padding: 20rpx 30rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
|
.address-title {
|
font-size: 30rpx;
|
font-weight: bold;
|
margin-bottom: 10rpx;
|
}
|
|
.address-detail {
|
font-size: 26rpx;
|
color: #666;
|
}
|
}
|
}
|
|
.selected-address {
|
padding: 20rpx 30rpx;
|
background-color: white;
|
border-top: 1rpx solid #f0f0f0;
|
|
.address-title {
|
font-size: 30rpx;
|
font-weight: bold;
|
margin-bottom: 10rpx;
|
}
|
|
.address-detail {
|
font-size: 26rpx;
|
color: #666;
|
margin-bottom: 10rpx;
|
}
|
|
.confirm-btn {
|
width: 100%;
|
height: 80rpx;
|
background-color: #007AFF;
|
color: white;
|
border-radius: 10rpx;
|
font-size: 32rpx;
|
margin-top: 20rpx;
|
}
|
}
|
}
|
</style>
|