| New file |
| | |
| | | <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"> |
| | | <div class="list-item" v-for="item in list" :key="item" @click="flyToAddress(item)"> |
| | | <div class="name">{{ item.airspaceName }}</div> |
| | | <div class="item"> |
| | | <div class="laber">空域管制时间</div> |
| | | <div class="value">{{item.createTime}}</div> |
| | | </div> |
| | | <div class="item"> |
| | | <div class="laber">空域管制类型</div> |
| | | <div class="value">{{item.airspaceType === '1' ? '禁飞区' : item.airspaceType === '2' ? '危险区' : item.airspaceType === '3' ? '限制区' : item.airspaceType === '0' ? '适飞区' : '未知'}}</div> |
| | | </div> |
| | | </div> |
| | | </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 { getAirspaceDetail } 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 = () => { |
| | | // 构建请求参数,搜索框为空时不传递airspaceName |
| | | const params = { |
| | | current: 1, |
| | | size: 9999 |
| | | } |
| | | if (searchVal.value.trim() !== '') { |
| | | params.airspaceName = searchVal.value |
| | | } |
| | | |
| | | getAirspaceDetail(params).then(res => { |
| | | const data = res.data.data.records || [] |
| | | if (data && data.length > 0) { |
| | | list.value = data |
| | | finishedText.value = '' |
| | | EventBus.emit('mapAddAirMarker', list.value) |
| | | } else { |
| | | finishedText.value = '暂无数据' |
| | | EventBus.emit('mapClearAirMarker') |
| | | } |
| | | |
| | | 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 '' |
| | | } |
| | | return finishedText.value || '' |
| | | }) |
| | | |
| | | // input对应下拉数据初始化 |
| | | const inputSelect = () => { |
| | | list.value = [] |
| | | finished.value = false |
| | | loadingTest.value = true |
| | | |
| | | EventBus.emit('mapClearMarker') |
| | | |
| | | getAddressList() |
| | | } |
| | | |
| | | // 输入框input事件 |
| | | const handlerInput = _.debounce(() => { |
| | | inputSelect() |
| | | }, 300) |
| | | |
| | | // 输入框clear事件 |
| | | const handlerClear = () => { |
| | | EventBus.emit('mapClearAirMarker') |
| | | // 请求接口查全部 |
| | | getAddressList() |
| | | } |
| | | |
| | | 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', |
| | | // }) |
| | | EventBus.emit('signFlyToMarker', item) |
| | | } |
| | | |
| | | 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' |
| | | } |
| | | } |
| | | getAddressList() |
| | | }) |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .van-floating-panel { |
| | | background: transparent; |
| | | |
| | | ::v-deep(.custom-header) { |
| | | // border: 2px solid red; |
| | | .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; |
| | | position: relative; |
| | | background: #f1f1f1; |
| | | box-shadow: 0 -20px 20px #f1f1f1; |
| | | |
| | | .van-list { |
| | | background: white; |
| | | |
| | | .van-cell { |
| | | background: white; |
| | | } |
| | | } |
| | | |
| | | .list-tooltip { |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | text-align: center; |
| | | color: #000; |
| | | } |
| | | } |
| | | .list-item { |
| | | padding: 12px; |
| | | border-bottom: 1px solid #e5e5e5; |
| | | font-family: Source Han Sans CN, Source Han Sans CN; |
| | | .name { |
| | | font-weight: bold; |
| | | font-size: 16px; |
| | | color: #222324; |
| | | } |
| | | .item { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | } |
| | | .laber { |
| | | font-weight: 400; |
| | | font-size: 15px; |
| | | color: #222324; |
| | | } |
| | | .value { |
| | | font-weight: 400; |
| | | font-size: 14px; |
| | | color: #7B7B7B; |
| | | } |
| | | } |
| | | :deep(.van-loading) { |
| | | text-align: center; |
| | | position: absolute; |
| | | top: 50%; |
| | | left: 50%; |
| | | transform: translate(-50%, -50%); |
| | | text-align: center; |
| | | color: #000; |
| | | } |
| | | } |
| | | </style> |