添加地点搜索

pull/853/head
wersd 2025-06-26 21:23:04 +08:00
parent a39c2a8e6d
commit 0fb01cd478
2 changed files with 117 additions and 15 deletions

View File

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

View File

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