115 lines
3.8 KiB
Vue
Raw Normal View History

2023-03-20 15:49:41 +08:00
<template>
<el-dialog
class="map-dialog"
:style="{ width: '80%' }"
:modelValue="modelValue"
:show-close="true"
@update:model-value="emit('update:modelValue', $event)"
@open="open"
@close="close"
>
<template #header="{ titleId, titleClass }">
<div class="header">
<h4 :id="titleId" :class="titleClass">坐标拾取</h4>
<div class="search-container">
<div class="search-item">
<label class="search"><span>请输入地址</span><el-input id="map-input" v-model="address" /></label>
<!-- <el-button class="btn-search" type="primary">搜索</el-button> -->
</div>
<div class="search-item">
<label class="address"><span>地址</span><el-input disabled :model-value="coordinateInfo.address" /></label>
<label class="lon"><span>经度</span><el-input disabled :model-value="coordinateInfo.lng" /></label>
<label class="lat"><span>纬度</span><el-input disabled :model-value="coordinateInfo.lat" /></label>
<el-button class="btn-submit" type="primary" @click="submit">提交</el-button>
</div>
</div>
</div>
</template>
<div id="map-container" class="map"></div>
</el-dialog>
</template>
<script lang="ts" setup>
import { ElMessage } from "element-plus";
import { ref, shallowRef, reactive } from "vue";
import initAMap from "./AMap";
defineProps<{ modelValue: boolean }>();
const emit = defineEmits<{
(e: "update:modelValue", data: boolean): void;
(e: "getAddress", data: typeof coordinateInfo): void;
}>();
const address = ref("");
const coordinateInfo = reactive({ address: "", lng: "", lat: "" });
const map = shallowRef<AMap.Map>();
const search = shallowRef<any>();
const autocomplete = shallowRef<any>();
const open = async () => {
const AMap = await initAMap();
// 地图加载与点击
map.value = new AMap.Map("map-container", { zoom: 8, resizeEnable: true });
map.value?.on("click", e => {
map.value?.clearMap();
map.value?.add(new AMap.Marker({ position: e.lnglat }));
map.value?.setCenter(e.lnglat);
coordinateInfo.lng = e.lnglat.getLng();
coordinateInfo.lat = e.lnglat.getLat();
const geocoder = new AMap.Geocoder();
geocoder.getAddress(e.lnglat, (status: string, result: any) => {
if (status === "complete" && result.info === "OK") {
const regeocode = result.regeocode;
coordinateInfo.address = regeocode.formattedAddress;
}
});
});
// 联想输入与 POI 搜索
autocomplete.value = new AMap.AutoComplete({ extensions: "all", input: "map-input" });
search.value = new AMap.PlaceSearch({ map: map.value, extensions: "base" });
autocomplete.value?.on("select", (e: any) => {
map.value?.clearMap();
if (e.poi.location) {
coordinateInfo.lng = e.poi.location.lng;
coordinateInfo.lat = e.poi.location.lat;
map.value?.add(new AMap.Marker({ position: e.poi.location }));
} else {
const geocoder = new AMap.Geocoder({ city: e.adcode });
geocoder.getLocation(e.poi.name, (status: string, result: any) => {
if (status === "complete" && result.info === "OK") {
const data = result.geocodes;
if (data.length > 1) ElMessage.success("检索到多个结果,已为您定位到第一个地址");
coordinateInfo.lng = data[0].location.lng;
coordinateInfo.lat = data[0].location.lat;
map.value?.add(new AMap.Marker({ position: data[0].location }));
}
});
}
coordinateInfo.address = e.poi.district;
search.value.setCity(e.poi.adcode);
search.value.search(e.poi.name);
});
};
const submit = () => {
if (coordinateInfo.address && coordinateInfo.lng && coordinateInfo.lat) {
emit("getAddress", coordinateInfo);
}
};
const close = () => {
map.value?.destroy();
address.value = "";
coordinateInfo.address = "";
coordinateInfo.lng = "";
coordinateInfo.lat = "";
};
</script>
<style lang="scss" scoped>
@import "./AMap.scss";
</style>