Files
shz-front-cms/src/components/ProFromMap/index.tsx
Lishundong b1781d9aef
Some checks failed
Node CI / build (14.x, macOS-latest) (push) Has been cancelled
Node CI / build (14.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (14.x, windows-latest) (push) Has been cancelled
Node CI / build (16.x, macOS-latest) (push) Has been cancelled
Node CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node CI / build (16.x, windows-latest) (push) Has been cancelled
coverage CI / build (push) Has been cancelled
Node pnpm CI / build (16.x, macOS-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, ubuntu-latest) (push) Has been cancelled
Node pnpm CI / build (16.x, windows-latest) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
init
2025-10-24 09:40:46 +08:00

227 lines
7.6 KiB
TypeScript
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.

import React, { Fragment, useEffect, useRef, useState } from 'react';
import style from './index.less';
import AMapLoader from '@amap/amap-jsapi-loader';
import { ProFormSelect } from '@ant-design/pro-components';
import img from './point.png';
import { Modal } from 'antd';
import { debounce } from '@/utils/tools';
declare global {
interface Window {
_AMapSecurityConfig?: {
securityJsCode: string;
};
}
}
export type MapProps = {
onSelect: (flag?: boolean, formVals?: unknown) => void;
onCancel: (flag?: boolean, formVals?: unknown) => void;
open: boolean;
};
export const aMapConfig = {
key: '9cfc9370bd8a941951da1cea0308e9e3',
securityJsCode: '7b16386c7f744c3ca05595965f2b037f',
};
const ProFromMap: React.FC<MapProps> = ({ open, onSelect, onCancel }) => {
const mapRef = useRef<any>(null);
const geocoderRef = useRef<any>(null);
const autoCompleteRef = useRef<any>(null);
const addMarkerRef = useRef<any>(null);
const markerRef = useRef<any>(null);
const locationList = useRef<any>([]);
const localData = useRef(null);
const [selectValue, setSelectValue] = useState<any>(null);
const [locationOptions, setLocationOptions] = useState(null);
useEffect(() => {
console.log('open', open);
if (!open) return;
window._AMapSecurityConfig = {
securityJsCode: aMapConfig.securityJsCode,
};
AMapLoader.load({
key: aMapConfig.key, // 申请好的Web端开发者Key首次调用 load 时必填
version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.Scale'], //需要使用的的插件列表,如比例尺'AMap.Scale',支持添加多个如:['...','...']
})
.then((AMap) => {
mapRef.current = new AMap.Map('container', {
// 设置地图容器id
viewMode: '3D', // 是否为3D地图模式
zoom: 11, // 初始化地图级别
center: [120.384599, 36.062687], // 初始化地图中心点位置
});
// 浏览器定位
AMap.plugin('AMap.Geolocation', function () {
var geolocation = new AMap.Geolocation({
enableHighAccuracy: false, //是否使用高精度定位,默认:true
timeout: 10000, //超过10秒后停止定位默认5s
position: 'RB', //定位按钮的停靠位置
offset: [10, 20], //定位按钮与设置的停靠位置的偏移量,默认:[10, 20]
zoomToAccuracy: true, //定位成功后是否自动调整地图视野到定位点
});
mapRef.current.addControl(geolocation);
geolocation.getCurrentPosition();
});
// 添加插件
AMap.plugin('AMap.AutoComplete', function () {
// 注意输入提示插件2.0版本需引入AMap.AutoComplete而1.4版本应使用AMap.Autocomplete
// 实例化AutoComplete
autoCompleteRef.current = new AMap.AutoComplete({
city: '370200', // 青岛市
citylimit: false,
});
});
// 将经纬度坐标转化为详细地址
AMap.plugin('AMap.Geocoder', () => {
geocoderRef.current = new AMap.Geocoder({
extensions: 'base',
batch: false,
city: '370200', // 青岛市
});
});
// 添加事件
mapRef.current.on('click', (eve) => {
console.log(eve);
const { lat, lng } = eve.lnglat;
if (geocoderRef.current && addMarkerRef.current) {
const lnglat1 = [lng, lat];
geocoderRef.current.getAddress(lnglat1, (status, result) => {
if (status === 'complete' && result.info === 'OK') {
const { formattedAddress } = result.regeocode;
const id = Date.now();
result.id = id;
result.address = formattedAddress;
result.location = {
lat: lat,
lng: lng,
};
setSelectValue(id);
setLocationOptions([result]);
localData.current = result;
console.log(result, '详细地址');
}
});
addMarkerRef.current && addMarkerRef.current(lnglat1);
}
});
addMarkerRef.current = (LngLat: any) => {
if (markerRef.current) {
mapRef.current.remove(markerRef.current);
markerRef.current = null;
addMarkerRef.current && addMarkerRef.current(LngLat);
} else {
markerRef.current = new AMap.Marker({
icon: new AMap.Icon({
size: new AMap.Size(32, 32), // 图标显示大小
image: img, // 自定义图标 URL
imageSize: new AMap.Size(32, 32), // 强制缩放原始图片大小
}),
anchor: 'bottom-center', // 设置锚点方位
position: LngLat, //标注点位置
title: `鼠标移入显示的提示`, //标注点标题
map: mapRef.current, //将标注点添加到地图上
});
}
};
// 获取输入提示信息
})
.catch((e) => {
console.log(e);
});
}, [open]);
useEffect(() => {
return () => {
mapRef.current?.destroy();
};
}, []);
function autoInput(keywords: string) {
return new Promise((resolve, reject) => {
autoCompleteRef.current.search(keywords, function (status: string, result) {
if (status === 'complete' && result.info === 'OK') {
// 搜索成功时result即是对应的匹配数据
resolve(result.tips);
} else {
reject(null);
}
});
});
}
const searchLocation = async (keyWords: string) => {
const keywordsToSearch = keyWords || '青岛';
const resData = await autoInput(keywordsToSearch);
locationList.current = resData;
setLocationOptions(resData);
return resData || [];
};
// 防抖版本(确保组件卸载时清除)
const debounceSearch = useRef(debounce(searchLocation, 500)).current;
function selectItem(id: any) {
const items = locationList.current.filter((item) => item.id === id);
if (items.length) {
const value = items[0];
setSelectValue(value.id);
addMarkerRef.current([value.location.lng, value.location.lat]);
mapRef.current.setZoomAndCenter(16, [value.location.lng, value.location.lat]);
localData.current = value;
}
}
function locationSuccess() {
if (localData.current) {
onSelect && onSelect(localData.current);
}
}
return (
<Fragment>
<Modal
open={open}
title="选择位置"
okText="确定"
cancelText="取消"
width={800}
onCancel={onCancel}
onOk={locationSuccess}
>
<div className={style.AmapContainer}>
<div className={style.Amap_search}>
<ProFormSelect
style={{
width: '100%',
}}
debounceTime={500}
name="select"
// request={searchLocation}
showSearch
placeholder="请输入地点"
fieldProps={{
onSelect: selectItem,
onSearch: debounceSearch,
value: selectValue,
options: locationOptions,
fieldNames: {
label: 'address',
value: 'id',
},
}}
/>
</div>
<div id="container" className={style.mapContent}></div>
</div>
</Modal>
</Fragment>
);
};
export default ProFromMap;