<!--
|
* @Author : yuan
|
* @Date : 2025-10-13 16:15:19
|
* @LastEditors : yuan
|
* @LastEditTime : 2025-12-19 15:32:56
|
* @FilePath : \applications\mobile-web-view\src\appPages\Map\searchBar.vue
|
* @Description :
|
* Copyright 2025 OBKoro1, All Rights Reserved.
|
* 2025-10-13 16:15:19
|
-->
|
<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" @click="onSelect">
|
<van-image width="16" height="16" :src="switchoverIcon" />
|
|
<div class="search-type">{{ curSearchType === 0 ? '机巢' : '地址' }}</div>
|
</div>
|
</template>
|
|
<template #right-icon v-if="isWeb">
|
<div class="search-right-box" @click="scanCode">
|
<van-image width="20" height="20" :src="qrCodeIcon" />
|
</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-show="curSearchType === 0" v-for="item in list" :key="item" @click="flyToDrone(item)">
|
<template #title>{{ item.nickname }}</template>
|
</van-cell>
|
|
<van-cell v-show="curSearchType === 1" v-for="item in list" :key="item" @click="flyToAddress(item)">
|
<template #title>{{ item.name }}</template>
|
<template #value>{{ item.district }}</template>
|
</van-cell>
|
</van-list>
|
</van-floating-panel>
|
</template>
|
|
<script setup>
|
import switchoverIcon from '@/appDataSource/leafletMapIcon/switchover-icon.svg'
|
|
import qrCodeIcon from '@/appDataSource/leafletMapIcon/qr-code.svg'
|
import { showToast } from 'vant'
|
import _ from 'lodash'
|
import { searchWithPlugin } from '@/utils/util'
|
import { useStore } from 'vuex'
|
import { selectDeviceList } from '@/api/home/common'
|
import { selectDevicePageSimplify } from '@/api/home/machineNest.js'
|
|
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 actions = ref([{ text: '地址' }])
|
|
const curSearchType = ref(0) // 0机巢 1地址
|
|
const onSelect = () => {
|
searchVal.value = ''
|
list.value = []
|
finished.value = false
|
|
curSearchType.value = curSearchType.value === 0 ? 1 : 0
|
actions.value = [{ text: curSearchType.value === 0 ? '地址' : '机巢' }]
|
|
EventBus.emit('mapClearMarker')
|
EventBus.emit('mapOnlyShowDrone')
|
|
if (curSearchType.value === 0) {
|
getDeviceList() // 切换到机巢时展示全部机巢
|
}
|
}
|
|
// 获取地址搜索结果
|
const getAddressList = () => {
|
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 getDeviceList = async () => {
|
const params = {
|
nickname: searchVal.value,
|
current: 1,
|
size: 999,
|
}
|
const res = await selectDevicePageSimplify(params)
|
|
if (res.data.code !== 0) return
|
|
if (res?.data?.data?.records && res?.data?.data?.records.length > 0) {
|
list.value = res?.data?.data?.records.filter(item => item.status !== 'OFFLINE') || []
|
|
finishedText.value = list.value.length > 0 ? '' : '暂无数据'
|
} else {
|
finishedText.value = '暂无数据'
|
}
|
|
setTimeout(() => {
|
finished.value = true
|
loadingTest.value = false
|
}, 800)
|
}
|
|
const tooltipText = computed(() => {
|
if (loadingTest.value) {
|
return ''
|
}
|
if (searchVal.value.trim() === '') {
|
return curSearchType.value === 0 ? '' : `支持搜索${curSearchType.value === 0 ? '机巢' : '地址'}`
|
}
|
return finishedText.value || ''
|
})
|
|
// input对应下拉数据初始化
|
const inputSelect = () => {
|
list.value = []
|
finished.value = false
|
loadingTest.value = true
|
|
EventBus.emit('mapClearMarker')
|
|
if (curSearchType.value === 1) {
|
getAddressList()
|
} else if (curSearchType.value === 0) {
|
getDeviceList()
|
}
|
}
|
|
// 输入框input事件
|
const handlerInput = _.debounce(() => {
|
if (searchVal.value.trim() === '') {
|
if (curSearchType.value === 0) {
|
// 搜索机巢时,输入框为空展示全部机巢
|
inputSelect()
|
} else {
|
loadingTest.value = false
|
list.value = []
|
finishedText.value = ''
|
}
|
return
|
}
|
inputSelect()
|
}, 300)
|
|
// 输入框clear事件
|
const handlerClear = () => {
|
EventBus.emit('mapClearMarker')
|
EventBus.emit('mapOnlyShowDrone')
|
}
|
|
// 飞到机巢位置
|
const flyToDrone = item => {
|
height.value = anchors[0]
|
|
searchVal.value = item.nickname
|
inputSelect()
|
|
EventBus.emit('mapOnlyShowDrone', { device_sn: item.device_sn })
|
|
EventBus.emit('mapSetView', {
|
lat: item.latitude,
|
lng: item.longitude,
|
zoom: 11,
|
})
|
}
|
|
const flyToAddress = item => {
|
if (!item.location) {
|
showToast('当前地址无坐标信息')
|
|
return
|
}
|
|
const [longitude, latitude] = gcj02ToWgs84(item.location.lng, item.location.lat)
|
|
height.value = anchors[0]
|
|
searchVal.value = item.name
|
inputSelect()
|
|
EventBus.emit('mapAddMarker', {
|
lat: latitude,
|
lng: longitude,
|
name: searchVal.value,
|
customClassName: 'address-marker',
|
})
|
}
|
|
const scanCode = () => {
|
const transmitData = { data: { type: 'scanCode' } }
|
wx.miniProgram.navigateTo({ url: "/subPackages/qrCode/index" })
|
wx.miniProgram.postMessage(transmitData)
|
uni.postMessage(transmitData)
|
}
|
|
watch(
|
() => route.query,
|
(newValue, oldValue) => {
|
if (newValue.updateKey) {
|
height.value = anchors[0]
|
}
|
},
|
{ deep: true }
|
)
|
|
onMounted(() => {
|
if (curSearchType.value === 0) {
|
getDeviceList()
|
}
|
|
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: #1d6fe9;
|
}
|
}
|
}
|
}
|
|
::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>
|