| | |
| | | <template> |
| | | <div class="w-[320px]"> |
| | | <div class="search flex-items-center"> |
| | | <el-input v-model="searchText" clearable placeholder="查找对象"> </el-input> |
| | | <div class="bg-blue-400 flex-center px-4 h-[32px] cursor-pointer hover:bg-blue-500 active:bg-blue-400"> |
| | | <span class="ywifont ywicon-sousuo text-white"></span> |
| | | </div> |
| | | </div> |
| | | <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" /> |
| | | |
| | | <div class="search-result w-min-[340px] bg-white px-2"> |
| | | <div class="flex-items-center gap-2 hover:bg-[#ebebeb] cursor-pointer text-gray-500"> |
| | | <span class="ywifont ywicon-sousuo text-gray-400 !text-[12px]"></span> |
| | | <span>测试aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa</span> |
| | | <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'; |
| | | 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); |
| | | 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"></style> |
| | | <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> |