Files
SaaS-lib/lib/component/form/map/mapV2.vue
xuziqiang d0155dbe3c push
2024-05-15 17:29:42 +08:00

386 lines
11 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!-- @format -->
<template>
<div style="display: flex; width: 100%">
<a-form-item-rest>
<div class="rightBox">
<div class="inputArea">
<div style="margin-right: 10px">经度</div>
<div class="longitude">
<ns-input
v-model:value="longLatTudeobj.longitude"
type="number"
class="input"
placeholder="请输入经度"
:disabled="viewOnly"
@change="inputChange('longitude', $event)" /> </div
><div style="margin: 0 10px">纬度</div>
<div class="latitude">
<ns-input
v-model:value="longLatTudeobj.latitude"
type="number"
class="input"
placeholder="请输入纬度"
:disabled="viewOnly"
@change="inputChange('latitude', $event)" />
</div>
</div>
<div class="inputSearch" style="margin: 15px 0 15px 0">
<label style="margin-right: 10px">地址</label>
<ns-input
v-model:value="longLatTudeobj.address"
class="inputAdress"
:disabled="viewOnly"
placeholder="请输入地址" />
<ns-button type="primary" @click="onSearch" :disabled="viewOnly">查询</ns-button>
</div>
<div class="mapArea">
<div id="map-container"></div>
<div v-if="isShowResult" id="map-result" style="overflow: auto"></div>
</div>
</div>
</a-form-item-rest>
</div>
</template>
<script lang="ts">
import { defineComponent, watch, ref, reactive, onMounted, onBeforeUnmount, nextTick } from 'vue';
import AMapLoader from '@amap/amap-jsapi-loader';
import { shallowRef } from 'vue';
import { isArray, isEqual, isEmpty } from 'lodash-es';
export default defineComponent({
name: 'NsMapV2',
props: {
defaultValue: {
type: Array,
default: () => {
return [];
},
},
viewOnly: {
type: Boolean,
default: false,
},
value: {
type: Array,
default: () => {
return [];
},
},
fieldMap: {
type: Object || Array,
default: () => {
return [];
},
},
formModel: {
type: Object || Array,
},
//兼容v1写法
longitude: {
type: String,
default: '',
},
latitude: {
type: String,
default: '',
},
defaultAddress: {
type: String,
default: '',
},
//兼容v1写法end
},
emits: ['change', 'updata:longLat'],
setup(props, { emit }) {
let map: Recordable;
let geoc: any, localSearch: any, Amap: any;
const isShowResult = ref(false);
const hasload = ref(false);
const longLatTudeobj = ref({
longitude: '',
latitude: '',
address: '',
});
const delay = (time) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(map);
}, time);
});
};
const circleDelay = async () => {
let res = await delay(100);
if (res) {
return res;
} else {
return circleDelay();
}
};
//更新值
const updateValue = async (event) => {
if (!map) {
//循环等待map初始化
await circleDelay();
}
if (isArray(event)) {
if (!event.length) return;
longLatTudeobj.value['latitude'] = event[0] || '';
longLatTudeobj.value['longitude'] = event[1] || '';
longLatTudeobj.value['address'] = event[2] || '';
if (longLatTudeobj.value['latitude'] && longLatTudeobj.value['longitude']) {
map.clearMap();
getAddressBylnglat(longLatTudeobj.value, (res) => {
longLatTudeobj.value.address = res;
});
addMark({ position: [event[1], event[0]] });
map.setFitView();
}
}
};
const resultPanelClick = (data: { [x: string]: string }) => {
if (data && data['location']) {
if (data['location']) {
const location = data['location']; // 当前marker的经纬度信息
longLatTudeobj.value.longitude = location['lng'].toFixed(6);
longLatTudeobj.value.latitude = location['lat'].toFixed(6);
}
if (data['address']) {
longLatTudeobj.value.address = data['address'];
}
}
};
//搜索
const onSearch = () => {
isShowResult.value = true;
map.clearMap();
if (!localSearch) return;
localSearch.search(longLatTudeobj.value.address, (status: string, result: Recordable) => {
if (status == 'complete' && result.info == 'OK') {
const resultPoi = result['poiList']['pois'];
if (resultPoi && resultPoi instanceof Array && resultPoi.length > 0) {
const pois = result.poiList.pois;
for (let i = 0; i < pois.length; i++) {
const poi = pois[i];
const marker = [];
marker[i] = addMark({
position: poi.location, // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: poi.name,
});
}
map.setFitView();
}
} else {
}
});
};
//初始化
const initMap = async () => {
AMapLoader.load({
key: '2694972059c3b978de5d7e073efdfc64', // 申请好的Web端开发者Key首次调用 load 时必填
version: '1.4.15',
plugins: ['AMap.Geocoder', 'AMap.PlaceSearch'],
})
.then((AMap) => {
Amap = AMap;
// 需要传入AMap ,否则方法无法调用
map = new AMap.Map('map-container', {
// center: [117.000923, 36.675807],
resizeEnable: true,
zoom: 12,
});
//精准搜索插件
geoc = new AMap.Geocoder({
city: '021',
});
//模糊匹配插件
AMap.service('AMap.PlaceSearch', function () {
// 回调函数
// 实例化PlaceSearch
localSearch = new AMap.PlaceSearch({
pageSize: 5, // 每页显示多少行
pageIndex: 1, // 显示的下标从那个开始
type: '', // 类别,可以以|后面加其他类
city: '021',
panel: 'map-result', // 服务显示 的面板
autoFitView: true,
});
});
if (AMap.event) {
// 搜索结果列表的点标记
AMap.event.addListener(localSearch, 'listElementClick', (e) => {
resultPanelClick(e['data']);
});
// 标记物点击
AMap.event.addListener(localSearch, 'markerClick', (e) => {
// console.log('搜索结果标记物点击');
resultPanelClick(e['data']);
});
}
//不可编辑状态
if (!props.viewOnly) {
map.on('click', (e) => {
map.clearMap();
getAddressByaddress(e, (res) => {
longLatTudeobj.value.address = res;
longLatTudeobj.value.latitude = e.lnglat['lat'].toFixed(6);
longLatTudeobj.value.longitude = e.lnglat['lng'].toFixed(6);
});
addMark({
position: e.lnglat,
});
map.setFitView();
});
}
})
.catch((e) => {});
};
//根据经纬度搜索
const getAddressBylnglat = (event, callBack) => {
geoc.getAddress(event.lnglat, (status, result) => {
if (status == 'complete' && result.info == 'OK') {
const addComp = result['regeocode']['addressComponent'];
let address =
addComp.province +
addComp.city +
addComp.district +
addComp.street +
addComp.streetNumber;
callBack(address, result);
}
});
};
//根据关键字搜索
const getAddressByaddress = (event, callBack) => {
geoc.getAddress(event.lnglat, function (status, result) {
if (status == 'complete' && result.info == 'OK') {
const addComp = result['regeocode']['addressComponent'];
let address =
addComp.province +
addComp.city +
addComp.district +
addComp.street +
addComp.streetNumber;
callBack(address, result);
}
});
};
//添加点标记
const addMark = (data: Recordable) => {
let marker = new Amap.Marker(data);
map.add(marker);
};
onMounted(async () => {
await initMap();
if (props.value.length) {
updateValue(props.value);
}
if (props.defaultValue.length) {
updateValue(props.defaultValue);
}
});
onBeforeUnmount(() => {
map.destroy();
// localSearch.render.markerList.clear();
isShowResult.value = false;
});
watch(
() => props.value,
(newv, oldv) => {
if (!isEqual(newv, oldv) && !isEqual(newv, longLatTudeobj.value)) {
updateValue(newv);
}
},
{
immediate: true,
},
);
watch(
() => longLatTudeobj.value,
(newv, oldv) => {
if (newv) {
emit('change', [newv['latitude'], newv['longitude'], newv['address']]);
}
},
{
deep: true,
},
);
watch(
() => props.formModel,
(newv, oldv) => {
if (!isEmpty(newv) && props.fieldMap.length && !hasload.value) {
if (isArray(props.value) && !isEmpty(props.value)) {
return;
}
let longitude = [];
props.fieldMap.forEach((el, i) => {
longitude[i] = newv[el];
});
updateValue(longitude);
hasload.value = true;
}
},
{
immediate: true,
},
);
//兼容老的处理方法
watch(
//
() => [props.latitude, props.longitude, props.defaultAddress],
//
([latitude, longitude, defaultAddress]) => {
console.log(latitude, longitude, defaultAddress);
if (latitude && longitude) {
updateValue([latitude, longitude, defaultAddress]);
}
},
{
deep: true,
immediate: true,
},
);
return {
map,
isShowResult,
longLatTudeobj,
onSearch,
};
},
});
</script>
<style lang="less" scoped>
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
}
#map-container {
height: 400px;
}
.leftBox,
.rightBox {
flex: 1;
}
.inputArea {
display: flex;
line-height: 30px;
}
.inputSearch {
.inputAdress {
width: 344px;
margin-right: 10px;
}
}
</style>