<template>
|
<div class="searchBox" ref="searchBoxRef">
|
<div class="searchInput">
|
<el-select v-model="optionsValue" @change="optionChange" placeholder="请选择查询">
|
<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
|
</el-select>
|
|
<el-input
|
v-model="searchKey"
|
@input="handlerInput"
|
@focus="handleFocus"
|
placeholder="请输入搜索关键字"
|
></el-input>
|
</div>
|
<div class="searchBtn" @click="searchClick"></div>
|
<div class="region">
|
<el-tree-select
|
popper-class="custom-tree-select"
|
v-model="treeValue"
|
check-strictly
|
lazy
|
:load="load"
|
:props="props"
|
style="width: 240px"
|
@node-click="handleNodeClick"
|
/>
|
</div>
|
</div>
|
<div class="select-down-list" ref="selectDownRef" v-show="isSelectDown">
|
<div class="item" v-for="item in downList" @click="selectedValue(item)">{{ item.nickname || item.name }}</div>
|
</div>
|
</template>
|
<script setup>
|
import _ from 'lodash'
|
import { getRegion } from '@/api/home'
|
import { searchByKeyword, selectDeviceList } from '@/api/home/common'
|
import { useStore } from 'vuex'
|
import cesiumOperation from '@/utils/cesium-tsa'
|
|
const { flyTo } = cesiumOperation()
|
|
const store = useStore()
|
const searchKey = ref('')
|
const userAreaCode = computed(() => store.state.user.userInfo.detail.areaCode)
|
const selectedAreaCode = computed(() => store.state.user.selectedAreaCode)
|
const areaValue = ref('江西省')
|
const treeValue = ref(userAreaCode.value)
|
let first = true
|
const searchBoxRef = ref(null)
|
const selectDownRef = ref(null)
|
|
function handleNodeClick(data) {
|
areaValue.value = data.name
|
store.commit('setSelectedAreaCode', data.code)
|
}
|
|
const props = {
|
label: 'name',
|
value: 'code',
|
children: 'children',
|
}
|
const load = async (node, resolve) => {
|
if (first) {
|
first = false
|
const res = await getRegion(userAreaCode.value)
|
const { provinceCode, provinceName } = res?.data?.data?.[0] || {}
|
resolve([{ code: provinceCode, name: provinceName }])
|
return
|
}
|
const code = node?.data?.code || userAreaCode.value
|
if ((node?.data?.regionLevel || 0) > 2) return resolve([])
|
getRegion(code).then(res => {
|
resolve(res?.data?.data || [])
|
})
|
}
|
|
const optionsValue = ref('1')
|
const options = [
|
{
|
value: '1',
|
label: '机巢',
|
},
|
{
|
value: '2',
|
label: '地址',
|
},
|
]
|
|
const isSelectDown = ref(false)
|
|
// 地址搜索结果
|
const downList = ref([])
|
const position = ref({})
|
|
// 获取机巢搜索结果
|
const getDeviceList = async () => {
|
const res = await selectDeviceList({ nickname: searchKey.value })
|
if (res.data.code !== 0) return
|
downList.value = res?.data?.data || []
|
}
|
// 获取地址搜索结果
|
const getAddressList = async () => {
|
const res = await searchByKeyword(encodeURIComponent(`${areaValue.value}+${searchKey.value}`))
|
if (res.data.code !== 0) return
|
downList.value = res?.data?.data.tips || []
|
if (downList.value.length > 0) {
|
isSelectDown.value = true
|
}
|
}
|
// 搜索结果
|
const searchClick = () => {
|
const longitude = Number(position.value.longitude)
|
const latitude = Number(position.value.latitude)
|
flyTo({ longitude, latitude }, 1, 1000)
|
}
|
|
// 地址和机巢的切换
|
const optionChange = () => {
|
searchKey.value = ''
|
downList.value = []
|
|
inputSelect()
|
}
|
|
// input对应下拉数据初始化
|
const inputSelect = () => {
|
if (optionsValue.value === '2') {
|
getAddressList()
|
} else {
|
getDeviceList()
|
}
|
}
|
|
inputSelect()
|
|
// 输入框input事件
|
const handlerInput = _.debounce(inputSelect, 1000)
|
|
// 输入框获取焦点
|
const handleFocus = () => {
|
isSelectDown.value = true
|
}
|
// 机巢下拉获取值
|
const selectedValue = item => {
|
searchKey.value = item.nickname || item.name
|
if (optionsValue.value === '1') {
|
position.value = item
|
} else {
|
position.value = { longitude: item.location.split(',')[0], latitude: item.location.split(',')[1] }
|
}
|
|
isSelectDown.value = false
|
}
|
|
onMounted(() => {
|
document.addEventListener('click', handleClickOutside)
|
})
|
|
onUnmounted(() => {
|
document.removeEventListener('click', handleClickOutside)
|
})
|
|
const handleClickOutside = event => {
|
if (!searchBoxRef.value?.contains(event.target) && !selectDownRef.value?.contains(event.target)) {
|
isSelectDown.value = false
|
}
|
}
|
</script>
|
<style scoped lang="scss">
|
.select-down-list {
|
position: absolute;
|
top: 188px;
|
left: 44%;
|
transform: translateX(-40%);
|
width: 220px;
|
height: 256px;
|
overflow-y: auto;
|
background: linear-gradient(180deg, #0d3556 0%, #012350 100%);
|
border-radius: 0px 0px 8px 8px;
|
border: 1px solid;
|
border-image: linear-gradient(180deg, rgba(255, 255, 255, 0), rgba(115, 192, 255, 1)) 1 1;
|
opacity: 0.8;
|
&::-webkit-scrollbar {
|
width: 0;
|
display: none;
|
}
|
-ms-overflow-style: none; /* IE and Edge */
|
scrollbar-width: none; /* Firefox */
|
.item {
|
color: #ffffff;
|
height: 32px;
|
line-height: 32px;
|
text-align: center;
|
cursor: pointer;
|
&:hover {
|
background: linear-gradient(90deg, rgba(0, 122, 255, 0) 0%, rgba(0, 98, 204, 0.6) 50%, rgba(0, 73, 153, 0) 100%);
|
border: 1px solid;
|
border-image: linear-gradient(90deg, rgba(0, 199, 190, 0), rgba(48, 176, 199, 1), rgba(0, 199, 190, 0)) 1 1;
|
}
|
}
|
}
|
.searchBox {
|
width: 420px;
|
height: 43px;
|
position: absolute;
|
top: 145px;
|
left: 50%;
|
transform: translateX(-50%);
|
display: flex;
|
|
.el-select {
|
width: 130px;
|
height: 100%;
|
|
:deep() {
|
.el-select__wrapper {
|
background: transparent;
|
border: none;
|
box-shadow: none;
|
height: 100%;
|
padding-left: 20px;
|
}
|
|
.el-select__selected-item {
|
font-family: Source Han Sans CN, Source Han Sans CN, serif;
|
font-weight: 400;
|
font-size: 14px;
|
color: #ffffff;
|
line-height: 18px;
|
}
|
}
|
}
|
|
.searchInput {
|
width: 243px;
|
height: 100%;
|
background: url('@/assets/images/home/searchBox/searchBg1.png') no-repeat center / 100% 100%;
|
display: flex;
|
|
.el-input {
|
height: 100%;
|
|
:deep() {
|
.el-input__wrapper {
|
background: transparent;
|
border: none;
|
box-shadow: none;
|
height: 100%;
|
}
|
|
.el-input__inner {
|
font-family: Source Han Sans CN, Source Han Sans CN, serif;
|
font-weight: 400;
|
font-size: 14px;
|
color: #ffffff;
|
line-height: 18px;
|
}
|
}
|
}
|
}
|
|
.searchBtn {
|
width: 67px;
|
height: 100%;
|
background: url('@/assets/images/home/searchBox/searchBg2.png') no-repeat center / 100% 100%;
|
cursor: pointer;
|
}
|
|
.region {
|
width: 0;
|
flex-grow: 1;
|
background: url('@/assets/images/home/searchBox/searchBg3.png') no-repeat center / 100% 100%;
|
|
:deep() {
|
.el-select__wrapper {
|
width: 100px;
|
padding-left: 20px;
|
}
|
}
|
}
|
}
|
</style>
|