<template>
|
<div class="h-full">
|
<AdvanceSearch v-if="isAdvanceSearch" class="h-full" :ol-map="olMap" @close="advanceSearchClose" :propertyMap="propertyMap" :propertyConfigMap="propertyConfigMap" />
|
<div v-else class="simple-search mt-3">
|
<div class="search flex-items-center">
|
<el-input class="w-[320px]" v-model="searchText" clearable placeholder="查找对象" @input="searchInput" @clear="clearSearch">
|
<template #prefix>
|
<el-switch v-model="isSearchObj" inline-prompt active-text="对象" inactive-text="道路" @change="changeSearchType" />
|
|
<el-button
|
class="bg-white flex-center px-2 cursor-pointer hover:bg-[#f5f5f5] active:bg-[#f5f5f5]"
|
text
|
title="高级搜索"
|
@click="handleAdvanceSearchClick"
|
>
|
<span class="ywifont ywicon-liebiao text-black !text-[22px]"></span>
|
</el-button>
|
</template>
|
</el-input>
|
|
<div
|
class="bg-blue-400 flex-center px-4 h-[32px] search-btn cursor-pointer hover:bg-blue-500 active:bg-blue-400"
|
@click="searchClick(searchText)"
|
>
|
<span v-if="isLoading" class="ywifont ywicon-loading1 text-white animate-spin"></span>
|
<span v-else class="ywifont ywicon-sousuo text-white"></span>
|
</div>
|
</div>
|
|
<div class="search-result w-[320px] bg-white text-sm">
|
<div
|
class="flex-items-center gap-2 hover:bg-[#ebebeb] cursor-pointer text-gray-500 w-full py-2 px-2"
|
v-for="item in searchResultList"
|
@click="searchResultClick(item)"
|
:key="item.name"
|
>
|
<span class="ywifont ywicon-sousuo text-gray-400 !text-[12px]"></span>
|
<span class="over-ellipsis"
|
>{{ item.name }}
|
|
<span class="text-gray-400 text-[12px]">{{ item.cityname }} {{ item.adname }}</span>
|
</span>
|
</div>
|
</div>
|
</div>
|
</div>
|
</template>
|
|
<script setup lang="ts" name="Search">
|
import { debounce } from 'lodash-es';
|
import Feature from 'ol/Feature';
|
import Circle from 'ol/geom/Circle';
|
import { fromLonLat } from 'ol/proj';
|
import type { PropType } from 'vue';
|
import { ref } from 'vue';
|
import { getSearchMapElement } from '/@/api/map';
|
import type { OLMap } from '/@/model/map/OLMap';
|
import { formatDate } from '/@/utils/formatTime';
|
import AdvanceSearch from './advanceSearch/index.vue';
|
import { systemGlobalConfig } from '/@/stores/global';
|
const props = defineProps({
|
olMap: {
|
type: Object as PropType<OLMap>,
|
},
|
propertyMap: {
|
type: Object as PropType<Record<string, any>>,
|
},
|
propertyConfigMap: {
|
type: Object as PropType<Record<string, any>>,
|
},
|
});
|
|
const isLoading = ref(false);
|
const searchText = ref('');
|
const isSearchObj = ref(true);
|
const searchInput = (e) => {
|
debounceSearch(e);
|
};
|
const changeSearchType = () => {
|
clearSearch(!isSearchObj.value);
|
searchClick(searchText.value);
|
};
|
|
const searchResultList = ref([]);
|
const searchResultClick = (item) => {
|
if (item.isSearchObj) {
|
props.olMap.displaySearchResult(item.model);
|
} else {
|
if (!item.location) return;
|
const [lon, lat] = item.location.split(',').map(Number);
|
const point = fromLonLat([lon, lat]);
|
const WKT = `SRID=3857;POINT(${point[0]} ${point[1]})`;
|
props.olMap.displaySearchResult({ WKT });
|
}
|
};
|
const debounceSearch = debounce((text) => {
|
searchClick(text);
|
}, 500);
|
const searchClick = async (text) => {
|
if (!text.trim()) {
|
clearSearch(isSearchObj.value);
|
return;
|
}
|
|
try {
|
isLoading.value = true;
|
if (isSearchObj.value) {
|
const res = await getSearchMapElement({
|
search_text: text,
|
max_count: 10,
|
time: formatDate(new Date()),
|
});
|
searchResultList.value = (res?.values ?? []).map((item) => {
|
return {
|
name: item.ONAME,
|
model: item,
|
isSearchObj: true,
|
// address: item.ADDRESS,
|
};
|
});
|
// props.olMap.displaySearchResult(res?.values ?? []);
|
} else {
|
const result = await props.olMap.gaodeAddressSearch(text, systemGlobalConfig.value['ui.project_city']);
|
const pois = result?.pois ?? [];
|
searchResultList.value =
|
pois
|
.map((item) => {
|
return {
|
name: item.name,
|
// address: item.address,
|
cityname: item.cityname,
|
adname: item.adname,
|
model: item,
|
isSearchObj: false,
|
location: item.location,
|
};
|
})
|
?.slice(0, 5) ?? [];
|
}
|
} finally {
|
isLoading.value = false;
|
}
|
};
|
const clearSearch = (isSearchObj = true) => {
|
searchResultList.value = [];
|
if (isSearchObj) {
|
props.olMap.clearObjectSearch();
|
} else {
|
props.olMap.clearObjectSearch();
|
}
|
};
|
|
//#region ====================== 高级搜索 ======================
|
const isAdvanceSearch = ref(false);
|
const handleAdvanceSearchClick = () => {
|
isAdvanceSearch.value = true;
|
};
|
const advanceSearchClose = () => {
|
isAdvanceSearch.value = false;
|
};
|
//#endregion
|
</script>
|
<style scoped lang="scss">
|
.search {
|
--radius-size: 8px;
|
--search-height: 35px;
|
:deep(.el-input__wrapper) {
|
border-top-right-radius: 0;
|
border-bottom-right-radius: 0;
|
|
border-top-left-radius: var(--radius-size);
|
border-bottom-left-radius: var(--radius-size);
|
.el-input__inner {
|
--el-input-inner-height: calc(var(--search-height) - 2px);
|
}
|
}
|
|
.search-btn {
|
height: var(--search-height);
|
border-bottom-right-radius: var(--radius-size);
|
border-top-right-radius: var(--radius-size);
|
}
|
|
.el-switch {
|
--el-switch-on-color: #1676fc;
|
}
|
}
|
</style>
|