最终效果:
?
?
?相关代码:areaSearch.vue
<template>
<div class="area-search">
<div class="city-chose" ref="cityChose">
<el-input
readonly
v-model="curCity"
@click.native.stop="iptClick"
class="cur-ipt"
>
<span slot="suffix" class="el-icon-arrow-down ipt-fate-suffix"></span>
</el-input>
<div class="cityChose-panel" v-show="panelShow">
<div class="cityChose-panel-top">
当前城市:{{ curCity }}
<em
class="fd-fr el-icon-close panel-close"
@click="panelShow = false"
></em>
</div>
<div class="hotCity-div clearfix">
<div
class="fd-fl hotCity-item"
v-for="item in hotCity"
:key="item.name_en"
@click="cityClick(item)"
>
{{ item.name }}
</div>
</div>
<div
class="panel-tackle clearfix"
style="margin: 5px 0; padding-right: 10px"
>
<div class="panel-toggle clearfix fd-fl">
<div
:class="[
'fd-fl',
'panel-toggle-item',
{ 'active-item': activeItem === 1 },
]"
@click="toggleClick(1)"
>
按省份
</div>
<div
:class="[
'fd-fl',
'panel-toggle-item',
{ 'active-item': activeItem === 2 },
]"
@click="toggleClick(2)"
>
按城市
</div>
</div>
<el-autocomplete
class="fd-fr"
style="width: 150px"
prefix-icon="el-icon-search"
placeholder="请输入城市"
:fetch-suggestions="querySearch"
:trigger-on-focus="false"
v-model="manualSearch"
value-key="name"
@select="autoSelect"
></el-autocomplete>
</div>
<div class="anchor-out clearfix">
<div
:class="['anchor', 'fd-fl', { activeAnchor: curAnchor === item }]"
v-for="item in anchorArr"
:key="item"
@click="anchorClick(item)"
>
{{ item }}
</div>
</div>
<!-- 按省份 -->
<div class="city-list" v-if="activeItem === 1">
<div v-for="(item, key) in provinceByLetter" :key="key" :id="key">
<div v-for="(item1, key1) in item" class="clearfix" :key="key1">
<div
v-for="(item2, key2) in item1"
:key="key2"
class="clearfix city-circle"
>
<div class="fd-fl city-bold">{{ key2 }}:</div>
<div class="fd-fl city-content clearfix">
<div
v-for="item3 in item2"
:key="item3.adcode"
class="fd-fl cityName"
@click="cityClick(item3)"
>
{{ item3.name }}
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 按城市 -->
<div class="city-list" v-if="activeItem === 2">
<div
v-for="(item, key) in cityByLetter"
:key="key"
:id="key"
class="clearfix city-circle"
>
<div class="fd-fl city-bold">{{ key }}:</div>
<div class="fd-fl city-content clearfix">
<div
v-for="item2 in item"
:key="item2.adcode"
class="fd-fl cityName"
@click="cityClick(item2)"
>
{{ item2.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data () {
return {
hotCity: [], // 热门城市列表
activeItem: 1, // 1:按省份 2:按城市
cityByLetter: null, // 按城市数据
provinceByLetter: null, // 按省份数据
anchorArr: [],
curCity: '北京',
curAnchor: '', // 当前锚点
panelShow: false,
allCitys: [], // 所有城市数据
manualSearch: '' // 手动搜索的城市名称
}
},
created () {
this.getAllData()
},
mounted () {
this.$nextTick(() => {
document.addEventListener('click', this.docClick)
})
},
beforeDestroy () {
document.removeEventListener('click', this.docClick)
},
methods: {
getAllData () {
this.$axios.get('static/json/geoinfo-all.json').then((res) => {
// console.log(res.data, 'ge0-all')
this.hotCity = res.data.data.cityData.hotCitys
this.cityByLetter = res.data.data.cityByLetter
this.provinceByLetter = res.data.data.provinceByLetter
this.getAllCitys(res.data.data.cityData.provinces)
this.toggleClick(1)
})
},
/**
* 获取所有城市
* @param {} data
*/
getAllCitys (data) {
this.allCitys = []
for (const key in data) {
if (data[key].cities.length === 0) {
this.allCitys.push({
name: data[key].name,
adcode: data[key].adcode,
x: data[key].x,
y: data[key].y
})
} else {
data[key].cities.forEach((city) => {
this.allCitys.push({
name: city.name,
adcode: city.adcode,
x: city.x,
y: city.y
})
})
}
}
// console.log(this.allCitys, 'all-city')
},
/**
*
* @param {*} num 1按省份 2按城市
*/
toggleClick (num) {
this.activeItem = num
this.curAnchor = ''
if (num === 1) {
this.anchorArr = Object.keys(this.provinceByLetter)
} else {
this.anchorArr = Object.keys(this.cityByLetter)
}
},
/**
* 字母锚点 点击
* @param {} val
*/
anchorClick (val) {
this.curAnchor = val
document.getElementById(val).scrollIntoView({ behavior: 'smooth' })
},
iptClick () {
this.panelShow = !this.panelShow
},
/**
* document 点击事件
* @param {*} e
*/
docClick (e) {
if (!this.$refs.cityChose.contains(e.target)) {
this.panelShow = false
}
},
querySearch (queryString, cb) {
var allCitys = this.allCitys
var results = queryString
? allCitys.filter((city) => {
return (
city.name.toLowerCase().indexOf(queryString.toLowerCase()) === 0
)
})
: allCitys
// 调用 callback 返回建议列表的数据
cb(results)
},
/**
* 手动搜索选定
* @param {*} item
*/
autoSelect (item) {
this.curCity = item.name
this.$emit('city', item)
this.panelShow = false
},
/**
* 城市点击
* @param {*} item
*/
cityClick (item) {
if (item.name === '全国') {
this.curCity = '全国'
this.$emit('city', item)
this.panelShow = false
return
}
const len = this.allCitys.length
for (let i = 0; i < len; i++) {
if (item.adcode === this.allCitys[i].adcode) {
this.curCity = this.allCitys[i].name
this.$emit('city', this.allCitys[i])
this.panelShow = false
break
}
}
}
}
}
</script>
<style scoped lang="scss">
$border-corlor: rgba(121, 121, 121, 1);
$hoverColor: #33ccff;
.area-search {
position: relative;
}
.city-chose {
position: relative;
.cityChose-panel {
position: absolute;
right: 0;
width: 410px;
height: 500px;
border: 1px solid $border-corlor;
margin-top: 10px;
background-color: rgba(0, 0, 0, 0.537254901960784);
display: flex;
flex-direction: column;
}
}
.hotCity-item {
color: $hoverColor;
margin: 2px 6px;
cursor: pointer;
&:hover {
text-decoration: underline;
}
}
.panel-toggle-item {
color: rgba(204, 204, 204, 0.847058823529412);
font-weight: bold;
font-size: 15px;
margin: 4px 6px;
border-bottom: 2px solid transparent;
cursor: pointer;
&.active-item {
color: $hoverColor;
border-color: $hoverColor;
}
}
.panel-tackle {
/deep/.el-input__inner {
height: 24px;
}
/deep/.el-input {
.el-input__prefix {
top: -8px;
}
}
}
.anchor {
background-color: rgba(204, 204, 204, 1);
color: #666;
margin: 2px 6px;
width: 18px;
text-align: center;
cursor: pointer;
&:hover {
background-color: $hoverColor;
color: #fff;
}
&.activeAnchor {
background-color: $hoverColor;
color: #fff;
}
}
.city-list {
flex: 1;
overflow: auto;
color: rgba(255, 255, 255, 0.847058823529412);
}
.city-circle {
display: flex;
padding: 6px;
.city-bold {
font-weight: 700;
}
.city-content {
flex: 1;
}
.cityName {
margin: 0 4px;
cursor: pointer;
line-height: 22px;
&:hover {
color: $hoverColor;
}
}
}
.cityChose-panel-top {
font-weight: 700;
font-style: normal;
font-size: 16px;
color: #cccccc;
margin: 6px 6px 8px 6px;
border-bottom: 1px solid $border-corlor;
padding-bottom: 8px;
}
.panel-close {
cursor: pointer;
&:hover {
opacity: 0.8;
}
}
.ipt-fate-suffix {
position: relative;
top: 5px;
}
.cur-ipt {
/deep/ input {
background: transparent;
color: #fff;
border-color: $border-corlor;
cursor: pointer;
}
}
.fd-fl {
float: left;
}
.fd-fr {
float: right;
}
.clearfix::after {
content: ' ';
height: 0;
visibility: hidden;
display: block;
clear: both;
}
</style>
?注意事项:
? ? ????????axios.get('static/json/geoinfo-all.json') 获取到的数据是高德地图搜索面板的后台数据,以上所有代码都是基于该数据结构编写。在高德地图首页打开开发者工具查看network即可看到该数据,即https://amap.com/service/cityList?version=20225815
|