<template>
|
<van-floating-panel v-model:height="height" :anchors="anchors">
|
<template #header>
|
<div class="custom-header">
|
<div class="bar"></div>
|
|
<van-field
|
v-model="searchVal"
|
placeholder="搜索"
|
@focus="height === anchors[0] ? (height = anchors[1]) : null"
|
@update:model-value="handlerInput"
|
@clear="handlerClear"
|
clearable
|
:border="false"
|
>
|
<template #left-icon>
|
<div class="search-left-box">
|
<van-image width="16" height="16" :src="switchoverIcon" />
|
<div class="search-type">地址</div>
|
</div>
|
</template>
|
</van-field>
|
</div>
|
</template>
|
|
<div class="list-tooltip" v-if="loadingTest">
|
<van-loading />
|
</div>
|
<div class="list-tooltip" v-else-if="!list.length">
|
{{ tooltipText }}
|
</div>
|
|
<van-list v-else :finished="finished" :finished-text="finishedText">
|
<van-cell v-for="item in list" :key="item" @click="flyToAddress(item)">
|
<template #title>{{ item.name }}</template>
|
<template #value>{{ item?.pname }}{{ item?.cityname }}{{ item?.adname }}</template>
|
</van-cell>
|
</van-list>
|
</van-floating-panel>
|
</template>
|
|
<script setup>
|
import switchoverIcon from '@/appDataSource/leafletMapIcon/addressSearch.svg'
|
import { showToast } from 'vant'
|
import _ from 'lodash'
|
import { searchWithPlugin } from '@/utils/util'
|
import { getPlace } from '@/api/map/address'
|
import { useStore } from 'vuex'
|
import EventBus from '@/utils/eventBus'
|
import { gcj02ToWgs84 } from '@/utils/coordinateTransformation'
|
import { useRoute } from 'vue-router'
|
const route = useRoute()
|
const isWeb = ref(true)
|
const store = useStore()
|
const selectedAreaCode = computed(() => store.state.user.selectedAreaCode)
|
const searchVal = ref('')
|
const list = ref([])
|
const finished = ref(false)
|
const loadingTest = ref(false)
|
const finishedText = ref('')
|
|
const anchors = [70, Math.round(0.6 * window.innerHeight)]
|
const height = ref(anchors[0])
|
const curSearchType = ref(1) // 固定为地址搜索
|
|
// 使用插件搜索地址
|
const searchWithPluginAPI = () => {
|
searchWithPlugin(searchVal.value, selectedAreaCode.value, (err, data) => {
|
if (data && data.length > 0) {
|
list.value = data
|
finishedText.value = ''
|
} else {
|
finishedText.value = '暂无数据'
|
}
|
|
setTimeout(() => {
|
finished.value = true
|
loadingTest.value = false
|
}, 800)
|
})
|
}
|
|
// 使用新接口搜索地址
|
const searchWithNewAPI = () => {
|
getPlace({ keyworld: searchVal.value }).then(res => {
|
const data = res.data.data.pois || []
|
if (data && data.length > 0) {
|
list.value = data
|
finishedText.value = ''
|
} else {
|
finishedText.value = '暂无数据'
|
}
|
|
setTimeout(() => {
|
finished.value = true
|
loadingTest.value = false
|
}, 800)
|
}).catch(err => {
|
console.error('地址搜索失败:', err)
|
finishedText.value = '搜索失败'
|
setTimeout(() => {
|
finished.value = true
|
loadingTest.value = false
|
}, 800)
|
})
|
}
|
|
// 获取地址搜索结果
|
const getAddressList = () => {
|
searchWithNewAPI()
|
}
|
|
const tooltipText = computed(() => {
|
if (loadingTest.value) {
|
return ''
|
}
|
if (searchVal.value.trim() === '') {
|
return '支持搜索地址'
|
}
|
return finishedText.value || ''
|
})
|
|
// input对应下拉数据初始化
|
const inputSelect = () => {
|
list.value = []
|
finished.value = false
|
loadingTest.value = true
|
|
EventBus.emit('mapClearMarker')
|
|
getAddressList()
|
}
|
|
// 输入框input事件
|
const handlerInput = _.debounce(() => {
|
if (searchVal.value.trim() === '') {
|
loadingTest.value = false
|
list.value = []
|
finishedText.value = ''
|
return
|
}
|
inputSelect()
|
}, 300)
|
|
// 输入框clear事件
|
const handlerClear = () => {
|
EventBus.emit('mapClearMarker')
|
EventBus.emit('mapOnlyShowDrone')
|
}
|
|
const flyToAddress = item => {
|
if (!item.location) {
|
showToast('当前地址无坐标信息')
|
return
|
}
|
EventBus.emit('mapClearMarker')
|
const location = typeof item.location === 'string'
|
? item.location.split(',').map(Number)
|
: [item.location.lng, item.location.lat];
|
const [longitude, latitude] = gcj02ToWgs84(location[0], location[1])
|
|
height.value = anchors[0]
|
|
searchVal.value = item.name
|
|
EventBus.emit('mapAddMarker', {
|
lat: latitude,
|
lng: longitude,
|
name: searchVal.value,
|
customClassName: 'address-marker',
|
})
|
}
|
|
watch(
|
() => route.query,
|
(newValue, oldValue) => {
|
if (newValue.updateKey) {
|
height.value = anchors[0]
|
}
|
},
|
{ deep: true }
|
)
|
|
onMounted(() => {
|
const hash = window.location.hash.slice(1)
|
const [hashPath, hashParamsStr] = hash.split('?')
|
if (hashParamsStr) {
|
const urlParams = new URLSearchParams(hashParamsStr)
|
const isWebParam = urlParams.get('isWeb')
|
if (isWebParam !== null) {
|
isWeb.value = isWebParam === 'true'
|
}
|
}
|
})
|
</script>
|
|
<style lang="scss" scoped>
|
.van-floating-panel {
|
background: transparent;
|
|
::v-deep(.custom-header) {
|
.bar {
|
margin: 0 auto;
|
width: 42px;
|
height: 4px;
|
background: rgba(0, 0, 0, 0.5);
|
border-radius: 2px;
|
}
|
|
.van-field {
|
margin: 0 8px;
|
margin-top: 4px;
|
padding: 0 12px !important;
|
display: flex;
|
align-items: center;
|
position: sticky;
|
top: 0;
|
width: calc(100% - 16px);
|
height: 44px;
|
|
background: #fff;
|
box-sizing: border-box;
|
z-index: 9;
|
border-radius: 8px;
|
|
box-shadow: 0px 4px 4px 0px rgba(0, 0, 0, 0.05);
|
|
.search-left-box,
|
.search-right-box {
|
display: flex;
|
align-items: center;
|
justify-content: space-between;
|
|
.search-type {
|
margin: 0 4px;
|
color: #282828;
|
}
|
}
|
}
|
}
|
|
::v-deep(.van-floating-panel__content) {
|
margin-top: -4px;
|
padding: 12px 0;
|
position: relative;
|
background: #f1f1f1;
|
box-shadow: 0 -20px 20px #f1f1f1;
|
|
.van-list {
|
background: transparent;
|
|
.van-cell {
|
background: transparent;
|
}
|
}
|
|
.list-tooltip {
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
text-align: center;
|
color: #000;
|
}
|
}
|
:deep(.van-loading) {
|
text-align: center;
|
position: absolute;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%);
|
text-align: center;
|
color: #000;
|
}
|
}
|
</style>
|