添加地点搜索
parent
a39c2a8e6d
commit
0fb01cd478
|
|
@ -1,12 +1,29 @@
|
||||||
<template>
|
<template>
|
||||||
<!-- 地图容器 -->
|
<div id="map-container" ref="mapContainer">
|
||||||
<div id="map-container" ref="mapContainer"></div>
|
<div id="panel">
|
||||||
|
<el-input
|
||||||
|
id="keyword"
|
||||||
|
v-model="keyword"
|
||||||
|
placeholder="请输入关键字"
|
||||||
|
@input="getSuggestions"
|
||||||
|
style="width: 180px; margin-right: 8px; font-size: 16px;"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
|
<ul id="suggestionList" v-if="suggestionList.length">
|
||||||
|
<li v-for="(item, index) in suggestionList" :key="item.id">
|
||||||
|
<a href="#" @click.prevent="setSuggestion(index)">
|
||||||
|
{{ item.title }}<span class="item_info">{{ item.address }}</span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div id="tmap-inner" ref="tmapInner"></div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onMounted, onUnmounted, watch } from 'vue'
|
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue'
|
||||||
|
|
||||||
// 定义 props
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
center: {
|
center: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
@ -22,35 +39,44 @@ const props = defineProps({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// 地图实例
|
|
||||||
const map = ref(null)
|
const map = ref(null)
|
||||||
const mapContainer = ref(null)
|
const tmapInner = ref(null)
|
||||||
const emit = defineEmits(['map-click'])
|
const emit = defineEmits(['map-click', 'suggestion-select'])
|
||||||
let markerLayer = null
|
let markerLayer = null
|
||||||
|
let suggest = null
|
||||||
|
const suggestionList = ref([])
|
||||||
|
const keyword = ref('')
|
||||||
const API_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY
|
const API_KEY = import.meta.env.VITE_APP_TENCENT_MAP_KEY
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const script = document.createElement('script')
|
const script = document.createElement('script')
|
||||||
script.src = `https://map.qq.com/api/gljs?v=1.exp&key=${API_KEY}`
|
script.src = `https://map.qq.com/api/gljs?v=1.exp&libraries=service&key=${API_KEY}`
|
||||||
script.onload = initMap
|
script.onload = () => nextTick(initMap)
|
||||||
document.head.appendChild(script)
|
document.head.appendChild(script)
|
||||||
})
|
})
|
||||||
|
|
||||||
function initMap() {
|
function initMap() {
|
||||||
if (!window.TMap) {
|
if (!window.TMap) {
|
||||||
console.error('腾讯地图API加载失败')
|
console.error('腾讯地图API加载失败')
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
map.value = new TMap.Map(mapContainer.value, {
|
map.value = new TMap.Map(tmapInner.value, {
|
||||||
center: new TMap.LatLng(props.center.lat, props.center.lng),
|
center: new TMap.LatLng(props.center.lat, props.center.lng),
|
||||||
zoom: props.zoom,
|
zoom: props.zoom,
|
||||||
viewMode: '2D'
|
viewMode: '2D'
|
||||||
})
|
})
|
||||||
map.value.on('click', (evt) => {
|
map.value.on('click', (evt) => {
|
||||||
// 触发自定义事件
|
|
||||||
emit('map-click', evt)
|
emit('map-click', evt)
|
||||||
})
|
})
|
||||||
|
markerLayer = new TMap.MultiMarker({
|
||||||
|
map: map.value,
|
||||||
|
geometries: []
|
||||||
|
})
|
||||||
|
suggest = new TMap.service.Suggestion({
|
||||||
|
pageSize: 10,
|
||||||
|
region: '杭州',
|
||||||
|
regionFix: false
|
||||||
|
})
|
||||||
if (props.markers && props.markers.length > 0) {
|
if (props.markers && props.markers.length > 0) {
|
||||||
addMarkers()
|
addMarkers()
|
||||||
}
|
}
|
||||||
|
|
@ -62,7 +88,7 @@ function addMarkers() {
|
||||||
markerLayer = new TMap.MultiMarker({
|
markerLayer = new TMap.MultiMarker({
|
||||||
map: map.value,
|
map: map.value,
|
||||||
styles: {
|
styles: {
|
||||||
"marker": new TMap.MarkerStyle({
|
marker: new TMap.MarkerStyle({
|
||||||
width: 25,
|
width: 25,
|
||||||
height: 35,
|
height: 35,
|
||||||
anchor: { x: 12.5, y: 35 }
|
anchor: { x: 12.5, y: 35 }
|
||||||
|
|
@ -83,8 +109,38 @@ function removeMarker() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getSuggestions() {
|
||||||
|
suggestionList.value = []
|
||||||
|
if (!suggest || !keyword.value) return
|
||||||
|
suggest.getSuggestions({ keyword: keyword.value, location: map.value.getCenter() })
|
||||||
|
.then((result) => {
|
||||||
|
suggestionList.value = result.data
|
||||||
|
})
|
||||||
|
.catch(() => {})
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSuggestion(index) {
|
||||||
|
const selected = suggestionList.value[index]
|
||||||
|
if (!selected) return
|
||||||
|
keyword.value = selected.title
|
||||||
|
suggestionList.value = []
|
||||||
|
const position = selected.location
|
||||||
|
map.value.setCenter(new TMap.LatLng(position.lat, position.lng))
|
||||||
|
markerLayer.setGeometries([
|
||||||
|
{
|
||||||
|
position: new TMap.LatLng(position.lat, position.lng),
|
||||||
|
id: selected.id,
|
||||||
|
styleId: 'marker'
|
||||||
|
}
|
||||||
|
])
|
||||||
|
// emit 选中建议事件,传递经纬度和名称
|
||||||
|
emit('suggestion-select', {
|
||||||
|
lat: position.lat,
|
||||||
|
lng: position.lng,
|
||||||
|
name: selected.title + (selected.address ? ' ' + selected.address : '')
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 监听 props 变化,动态更新地图
|
|
||||||
watch(() => props.center, (val) => {
|
watch(() => props.center, (val) => {
|
||||||
if (map.value && val) {
|
if (map.value && val) {
|
||||||
map.value.setCenter(new TMap.LatLng(val.lat, val.lng))
|
map.value.setCenter(new TMap.LatLng(val.lat, val.lng))
|
||||||
|
|
@ -112,5 +168,43 @@ onUnmounted(() => {
|
||||||
#map-container {
|
#map-container {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
#tmap-inner {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
#panel {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 10px;
|
||||||
|
z-index: 9999;
|
||||||
|
}
|
||||||
|
#suggestionList {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#suggestionList li a {
|
||||||
|
margin-top: -1px;
|
||||||
|
background-color: #f6f6f6;
|
||||||
|
text-decoration: none;
|
||||||
|
font-size: 18px;
|
||||||
|
color: black;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
#suggestionList li .item_info {
|
||||||
|
font-size: 12px;
|
||||||
|
color: grey;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
#suggestionList li a:hover:not(.header) {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
#keyword {
|
||||||
|
width: 180px;
|
||||||
|
margin-right: 8px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -89,6 +89,7 @@
|
||||||
:zoom="16"
|
:zoom="16"
|
||||||
:markers="tempLocation.lat && tempLocation.lng ? [{ id: 'selected', content: formData, position: { lat: tempLocation.lat, lng: tempLocation.lng } }] : []"
|
:markers="tempLocation.lat && tempLocation.lng ? [{ id: 'selected', content: formData, position: { lat: tempLocation.lat, lng: tempLocation.lng } }] : []"
|
||||||
@map-click="handleMapClick"
|
@map-click="handleMapClick"
|
||||||
|
@suggestion-select="handleSuggestionSelect"
|
||||||
/>
|
/>
|
||||||
<div style="margin-top: 10px; text-align: right;">
|
<div style="margin-top: 10px; text-align: right;">
|
||||||
<el-button @click="mapDialogVisible = false">取消</el-button>
|
<el-button @click="mapDialogVisible = false">取消</el-button>
|
||||||
|
|
@ -536,4 +537,11 @@ const confirmManagementSelection = () => {
|
||||||
}
|
}
|
||||||
managementDialogVisible.value = false
|
managementDialogVisible.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function handleSuggestionSelect({ lat, lng, name }) {
|
||||||
|
formData.value.locationLat = lat
|
||||||
|
formData.value.locationLng = lng
|
||||||
|
formData.value.locationName = name
|
||||||
|
tempLocation.value = { lat, lng }
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
Loading…
Reference in New Issue