使用高德地图必须要有对应的key和密钥,方法也很简单,直接去官网按照流程申请就可以了
高德地图注册申请流程https://lbs.amap.com/api/javascript-api-v2/prerequisites
elementUi想必大家也不陌生,这边也不展开说明了,有需要的可以去官网了解
elementUi开发指南https://element.eleme.cn/#/zh-CN/component/installation
页面功能展示:
直接展示完整代码:(有注释)
index.vue小说明
1、联系人选择我选用的是el-popover弹出层,这样可以自定义内容(比如表格),在复杂情况下可以看到更多的参数,不使用下拉框就是因为这个(下拉框展示数据太少,容易误选)
官方文档 => elementUI el-popover弹出框文档
2、下拉框和级联框中文赋值是因为我这边项目有需求将id和中文都上传,正常情况不需要change事件,只传id即可
3、这里懒加载级联框赋值回显我用的是最简单暴力的方法,因为懒加载的级联框会在组件加载的时候根据绑定的值去搜索,所以我直接用v-if:false让它消失,然后在$nextTick再将它v-if:true,直接回显,这样就不用写一大堆获取节点数据和children赋值的逻辑
除了地图小弹窗之外的CSS部分就不展示了,没啥必要(~OvO~)
<template>
<basic-container>
<div class="uploadbox">
<el-form ref="form" :model="addData" :rules="rules" label-width="120px">
<el-form-item label="地点名称" prop="name">
<el-input size="small" v-model="addData.name" placeholder="请输入地点名称"></el-input>
</el-form-item>
<el-form-item label="地点类别" prop="category">
<el-select size="small" v-model="addData.category" placeholder="请选择地点类别" :key="isResouceShow"
@change="categoryChange">
<el-option v-for="item in kdTypeList" :value="item.dictKey" :label="item.dictValue"
:key="item.dictKey"></el-option>
</el-select>
</el-form-item>
<el-form-item label="联系人" prop="contactMan">
<el-popover placement="bottom-start" ref="popoverRef" width="550" trigger="manual" v-model="diagnosisPopover">
<el-table :data="userList" @row-click="diagnosisrowClick" ref="eltableCurrentRow" highlight-current-row
:header-cell-style="{background:'#ECF5FF',color:'#4c5058',fontWeight: '600', padding: '8px 0',textAlign: 'center'}"
style="width: 100%;height: auto;user-select: none;">
<el-table-column align="center" width="150" property="name" label="姓名"
:show-overflow-tooltip="true"></el-table-column>
<el-table-column align="center" property="phone" label="手机号"
:show-overflow-tooltip="true"></el-table-column>
</el-table>
<div class="popover_pagination">
<el-button type="text" @click="handlediagnosisPrev" :disabled="userpage.current === 1">上一页</el-button>
<el-button type="text" @click="handlediagnosisNext"
:disabled="userpage.total<= userpage.current*6 ">下一页</el-button>
<el-button type="text" @click="diagnosisPopover = false">关闭</el-button>
</div>
<el-input size="small" v-model="addData.contactMan" placeholder="输入人员姓名搜索(回车确认)" @change="getUserListChange"
@focus="getUserList" slot="reference">
</el-input>
</el-popover>
</el-form-item>
<el-form-item label="联系电话" prop="contactPhone">
<el-input size="small" disabled v-model="addData.contactPhone" placeholder="请选择联系人"></el-input>
</el-form-item>
<el-form-item label="详细地址" prop="address">
<el-button @click="showMap" size="small">地图选择</el-button>
<el-input disabled size="small" v-model="addData.address" placeholder="地图选择详细地址"></el-input>
</el-form-item>
<el-form-item label="地点省市区/县" prop="city" class="cityarr" v-if="isResouceShow">
<el-cascader ref="cityarr" size="small" v-model="cityarr" :props="props" :show-all-levels="false"
@change="ciytChange"></el-cascader>
</el-form-item>
<el-form-item label="经纬度" prop="contactPhone">
<template>
<span>{{addData.longitude?addData.longitude+ ',' +addData.latitude:''}}</span>
</template>
</el-form-item>
<el-form-item label="启用状态">
<el-select size="small" v-model="addData.status" placeholder="请选择地点类别">
<el-option :value="0" label="关闭"></el-option>
<el-option :value="1" label="启用"></el-option>
</el-select>
</el-form-item>
</el-form>
</div>
<el-dialog title="地点地址选择" :visible.sync="mapshow" append-to-body width='50%' :close-on-click-modal="false"
destroy-on-close class="mapDialog" :before-close="mapClose">
<div class="mapCenter">
<div class="mapleft">
<gdMap @showresult="showresult" @setCascader="setCascader" ref="gdmap" :cityName="addData.cityName"
:address="addData.address" :lng="addData.longitude" :lat="addData.latitude" v-if="mapshow"></gdMap>
</div>
<div class="mapright">
<div style="margin-bottom:15px;text-align:right">
<el-button size="small" @click="mapClose">取 消</el-button>
<el-button size="small" type="primary" @click="sureAddress">确 定</el-button>
</div>
<div class="rightBottom">
<div class="maprightPoi" :class="{check:checkedAddressId===item.id}" v-for="item in poiList" :key="item.id"
@click="poiClick(item)">
<i class="el-icon-location-outline" style="margin-right:5px;width:15px"></i>
<div class="addressCenter">
<div>
<div class="poiname">{{item.name}}</div>
<el-tooltip effect="dark" :content="item.address" placement="top">
<div class="poiaddress">{{item.address}}</div>
</el-tooltip>
</div>
<div v-if="checkedAddressId===item.id">
<i class="el-icon-check" style="margin-left:5px;width:15px"></i>
</div>
</div>
</div>
</div>
</div>
</div>
</el-dialog>
</basic-container>
</template>
<script>
// 这是我自己的接口引用,可以忽略
import { getDictionary, getCityList } from '@/api/ExaminationPoints/index';
import { getListkd } from '@/api/administrators/index';
// 引入地图组件
import gdMap from './MapContainer.vue';
import { mapGetters } from 'vuex';
export default {
name: '',
components: { gdMap },
props: {},
data() {
return {
isResouceShow: true,
checkedAddressId: '',
checkedData: {},
poiList: [],
mapshow: false,
diagnosisPopover: false,
userList: [],
cityarr: [],
options: [],
kdTypeList: [],
// 级联框懒加载
props: {
lazy: true,
lazyLoad: (node, resolve) => {
const { value, level } = node;
let code = value || '';
getCityList(code).then((res) => {
res.data.data.forEach((i) => {
i.value = i.code;
i.label = i.name;
i.leaf = level === 2;
});
resolve(res.data.data);
});
},
},
addData: {
name: '',
category: '',
categoryText: '',
fullArea: '',
contactMan: '',
contactPhone: '',
province: '', // 省
city: '', //市
cityName: '',
district: '', //区
longitude: '', //经度
latitude: '', //纬度
address: '',
status: 1,
},
rules: {
name: [{ required: true, message: '请输入地点名称', trigger: 'blur' }],
category: [
{ required: true, message: '请选择地点类别', trigger: 'change' },
],
contactMan: [
{ required: true, message: '请输入地点联系人', trigger: 'change' },
],
contactPhone: [
{ required: true, message: '请输入联系电话', trigger: 'blur' },
],
city: [{ required: true, message: '请选择省市区', trigger: 'blur' }],
address: [
{ required: true, message: '请输入详细地址', trigger: 'blur' },
],
},
userpage: {
size: 6,
current: 1,
total: 0,
},
};
},
computed: {
...mapGetters(['userInfo']),
},
watch: {},
created() {
this.getDicData();
},
mounted() {},
destroyed() {},
methods: {
// 确认地址
sureAddress() {
if (!this.checkedAddressId) {
this.$message.error('请选择地点');
return;
}
this.addData.address = this.checkedData.name;
this.addData.longitude = this.checkedData.location.lng;
this.addData.latitude = this.checkedData.location.lat;
this.$refs.gdmap.getAddress(
this.checkedData.location.lng,
this.checkedData.location.lat
);
},
// 更据地址获取省市区
setCascader(data) {
this.cityarr = [
data.adcode.slice(0, 2),
data.adcode.slice(0, 4),
data.adcode,
];
this.addData.fullArea =
data.province +
(data.city[0] ? data.city : data.province) +
data.district;
this.addData.cityName = data.city[0] ? data.city : data.province;
this.addData.province = data.adcode.slice(0, 2);
this.addData.city = data.adcode.slice(0, 4);
this.addData.district = data.adcode;
console.log(this.$refs['cityarr']);
// 重新加载省市区级联
this.isResouceShow = false;
this.$nextTick(() => {
this.isResouceShow = true;
});
this.mapClose();
},
// 展示地图
showMap() {
this.mapshow = true;
},
// 展示搜索地址列表
showresult(val) {
this.poiList = val;
},
// 点击搜索结果
poiClick(data) {
this.checkedData = data;
this.checkedAddressId = data.id;
this.$refs.gdmap.searchText = data.name;
this.$refs.gdmap.markerResult(data);
},
// 关闭地图
mapClose() {
this.checkedAddressId = '';
this.poiList = [];
this.mapshow = false;
},
// 获取人员列表
getUserList() {
const obj = {
realName: this.addData.contactMan,
};
getListkd(
this.userpage.current,
this.userpage.size,
obj,
this.userInfo.dept_id
).then((res) => {
if (res.data.code === 200) {
this.userList = res.data.data.records;
this.userpage.total = res.data.data.total;
this.diagnosisPopover = true;
}
});
},
// 人员弹出层搜索值改变
getUserListChange() {
this.userpage.current = 1;
this.userpage.total = 0;
this.addData.contactPhone = '';
this.getUserList();
},
// 人员弹出层点击事件
diagnosisrowClick(row) {
this.addData.contactMan = row.name;
this.addData.contactPhone = row.phone;
this.diagnosisPopover = false;
this.userpage.current = 1;
this.userpage.total = 0;
},
// 人员弹出层上一页下一页
handlediagnosisPrev() {
this.userpage.current--;
this.getUserList();
},
handlediagnosisNext() {
this.userpage.current++;
this.getUserList();
},
// 省市区级联修改
ciytChange(val) {
let e = this.$refs['cityarr'].getCheckedNodes();
console.log(e);
this.addData.fullArea =
e[0].pathLabels[0] + e[0].pathLabels[1] + e[0].pathLabels[2];
this.addData.cityName = e[0].pathLabels[1];
this.addData.province = val[0];
this.addData.city = val[1];
this.addData.district = val[2];
console.log(this.cityarr);
},
// 修改地点类型,将类型中文赋值给data
categoryChange(val) {
const thisLabel = this.kdTypeList.find(
(item) => item.dictKey === val
).dictValue;
this.addData.categoryText = thisLabel;
},
//获取地点类型字典
getDicData() {
getDictionary({ code: 'test_center_category' }).then((res) => {
this.kdTypeList = res.data.data;
});
},
},
};
</script>
<style lang='scss' scoped>
.mapDialog {
height: 700px;
}
.mapCenter {
display: flex;
.mapright {
flex: 1;
padding: 0 15px;
.rightBottom {
height: 400px;
display: flex;
justify-content: start;
flex-direction: column;
}
.check {
color: #6b9df2;
}
.maprightPoi {
width: 100%;
height: 40px;
display: flex;
align-items: center;
cursor: default;
.addressCenter {
flex: 1;
display: flex;
justify-content: space-between;
align-items: center;
}
.poiaddress {
max-width: 300px;
overflow: hidden; /* 超出一行文字自动隐藏 */
text-overflow: ellipsis; /*文字隐藏后添加省略号*/
white-space: nowrap; /*强制不换行*/
}
}
}
}
</style>
MapContainer.vue小说明
1、key和对应的密钥一定要配置!(最重要的)
2、因为涉及到地图回显,所以在初始化地图的时候做个一个判断,有值的时候就是按照之前选择的地点回显,没有值就是正常初始化
3、搜索可以有搜索提示组件AutoComplete,我注册了但是没有用,觉得麻烦(0.0),反正我的右边有列表展示,有需要的可以自己试试, 官方文档=>高德地图JS API2.0 输入提示与 POI 搜索
<template>
<div>
<el-input id="tipInput" size="small" class="mapinput" v-model="searchText" placeholder="为提高精准度请输入(城市名+搜索地点关键字)"
@keyup.enter.native="searchKeyWord"></el-input>
<div id="container"></div>
</div>
</template>
<script>
import AMapLoader from '@amap/amap-jsapi-loader';
export default {
name: '',
components: {},
props: ['address', 'lat', 'lng', 'cityName'],
data() {
return {
map: null, //地图实例
searchText: '', //搜索关键词
mapModule: null, // AMap
placeSearchComponent: null,
poiList: [],
};
},
computed: {},
watch: {},
created() {},
mounted() {
this.initAMap();
window._AMapSecurityConfig = {
securityJsCode: '', // 申请key对应的秘钥 -> 注意了,如果不搭配密钥使用,搜索将没有结果
};
},
beforeDestroy() {
this.map.clearMap(); // 清除所有覆盖物(点标志)
this.searchText = '';
this.map = null;
this.mapModule = null;
},
destroyed() {},
methods: {
initAMap() {
const _this = this;
AMapLoader.load({
key: '', // 申请好的Web端开发者Key,首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
//在初始化函数中有一个plugins的配置给他穿入插件的名字即可
//如
plugins: [
'AMap.ToolBar',
'AMap.Scale',
'AMap.HawkEye',
'AMap.MapType',
'AMap.Geolocation',
'AMap.AutoComplete',
'AMap.PlaceSearch',
'AMap.Geocoder',
], // 需要使用的的插件列表,如比例尺'AMap.Scale'等
})
.then((AMap) => {
_this.mapModule = AMap;
if (this.lng) {
this.searchText = this.address;
this.map = new AMap.Map('container', {
// 设置地图容器id
// viewMode: '3D', // 是否为3D地图模式
zoom: 17, // 初始化地图级别
center: [this.lng, this.lat], // 初始化地图中心点位置
});
var marker = new AMap.Marker({
position: [Number(this.lng), Number(this.lat)],
});
this.map.add(marker);
} else {
this.map = new AMap.Map('container', {
// 设置地图容器id
// viewMode: '3D', // 是否为3D地图模式
zoom: 12, // 初始化地图级别
// center: [116.397428, 39.90923], // 初始化地图中心点位置 不设置则为ip的中心点
});
}
var toolbar = new AMap.ToolBar(); //创建工具条插件实例
this.map.addControl(toolbar); //添加工具条插件到页面
var scale = new AMap.Scale();
this.map.addControl(scale);
this.mapSearchInit(AMap);
})
.catch((e) => {
console.log(e);
});
},
/** 初始化搜索 */
mapSearchInit(AMap) {
// 注册AutoComplete组件
let autoOptions = {
input: 'tipInput',
};
let autoCompleteComponent = new AMap.AutoComplete(autoOptions);
this.autoCompleteComponent = autoCompleteComponent;
// 注册placeSearch组件
this.placeSearchComponent = new AMap.PlaceSearch();
},
//根据输入内容查询
searchKeyWord() {
let that = this;
that.placeSearchComponent.search(
that.cityName + that.searchText,
function (status, result) {
if (status === 'complete' && result.info === 'OK') {
that.poiList = result.poiList.pois;
that.$emit('showresult', that.poiList);
} else {
that.poiList = [];
that.$message({
message: '没有查到结果',
type: 'warning',
});
}
}
);
},
// 显示地图点标记
markerResult(data) {
var marker = new this.mapModule.Marker({
position: [Number(data.location.lng), Number(data.location.lat)],
});
this.map.clearMap(); // 清除所有覆盖物(点标志)
this.map.add(marker); // 添加点标志
setTimeout(() => {
this.map.setCenter(data.location);
this.map.setZoom(17);
}, 50);
},
// 逆推详细地址行政区
async getAddress(lng, lat) {
let that = this;
var geocoder = new this.mapModule.Geocoder({
city: '010', //城市设为北京,默认:“全国”
radius: 1000, //范围,默认:500
});
geocoder.getAddress([lng, lat], (status, result) => {
if (status === 'complete' && result.regeocode) {
var address = result.regeocode.addressComponent;
console.log(address);
that.$emit('setCascader', address);
} else {
log.error('根据经纬度查询地址失败');
}
});
},
},
};
</script>
<style lang='scss' scoped>
#container {
padding: 0px;
margin: 0px;
width: 400px;
height: 400px;
}
.mapinput {
margin-bottom: 15px;
width: 400px;
}
</style>