123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- import { ref, toRefs } from 'vue';
- import AMapLoader from '@amap/amap-jsapi-loader';
- import { message } from 'ant-design-vue';
- interface EnhancedAMapOptions {
- key?: string;
- version?: string;
- plugins?: string[];
- securityJsCode?: string;
- }
- interface MapInstance {
- AMap: any;
- map: AMap.Map | null;
- }
- // 全局单例变量
- let globalAMap: any = null;
- let globalMap: AMap.Map | null = null;
- let isInitialized = false;
- let initPromise: Promise<MapInstance> | null = null;
- const currentObj = ref({
- currentAdcode: '',
- currentAddress: '',
- });
- const lnglat = ref<number[]>([]);
- export function useAMapEnhanced(options: EnhancedAMapOptions = {}) {
- const isLoading = ref(false);
- const error = ref<string | null>(null);
- // 默认配置
- const defaultOptions: EnhancedAMapOptions = {
- key: import.meta.env.VITE_MAPKEY || '',
- version: '2.0',
- plugins: ['AMap.PlaceSearch', 'AMap.Geolocation'],
- securityJsCode: 'cbbb175f5c77d9ddf74c9b7d37f52f1c',
- };
- // 合并配置
- const mergedOptions = { ...defaultOptions, ...options };
- // 设置安全密钥
- if (mergedOptions.securityJsCode) {
- window._AMapSecurityConfig = {
- securityJsCode: mergedOptions.securityJsCode,
- };
- }
- /**
- * 初始化地图(全局单例)
- * @param container 地图容器ID或元素
- * @param mapOptions 地图配置选项
- */
- const initMap = async (container: string | HTMLElement, mapOptions: AMap.MapOptions = {}): Promise<MapInstance> => {
- // 如果已经在初始化中,则返回该Promise
- if (initPromise) {
- await initPromise;
- return {
- AMap: globalAMap,
- map: globalMap,
- };
- }
- // 如果已经初始化完成,直接返回
- if (isInitialized) {
- return {
- AMap: globalAMap,
- map: globalMap,
- };
- }
- // 检查是否提供了key
- if (!mergedOptions.key) {
- error.value = '缺少高德地图key';
- throw new Error('Missing AMap key');
- }
- isLoading.value = true;
- error.value = null;
- // 创建初始化Promise
- initPromise = new Promise(async (resolve, reject) => {
- try {
- // 加载AMap API
- const loadedAMap = await AMapLoader.load({
- key: mergedOptions.key!,
- version: mergedOptions.version || '2.0',
- plugins: mergedOptions.plugins,
- });
- globalAMap = loadedAMap;
- // 默认地图配置
- const defaultMapOptions: AMap.MapOptions = {
- zoom: 11, // 默认缩放级别
- ...mapOptions,
- };
- // 创建地图实例
- globalMap = new globalAMap.Map(container, defaultMapOptions);
- isInitialized = true;
- resolve({
- AMap: globalAMap,
- map: globalMap,
- });
- } catch (err: any) {
- error.value = err.message || '地图加载失败';
- reject(err);
- } finally {
- isLoading.value = false;
- initPromise = null;
- }
- });
- return initPromise;
- };
- /**
- * 搜索POI并定位到结果
- * @param keyword 搜索关键词
- */
- const searchAndLocate = async (keyword: string): Promise<void> => {
- if (!globalAMap || !globalMap) {
- throw new Error('地图未初始化');
- }
- return new Promise((resolve, reject) => {
- globalAMap.plugin(['AMap.PlaceSearch'], () => {
- const placeSearch = new globalAMap.PlaceSearch({
- pageSize: 10,
- pageIndex: 1,
- autoFitView: true,
- });
- placeSearch.search(keyword, (status: string, result: any) => {
- if (status === 'complete' && result.poiList && result.poiList.pois.length > 0) {
- const firstPoi = result.poiList.pois[0];
- if (firstPoi.location) {
- globalMap?.setCenter(firstPoi.location);
- globalMap?.setZoom(18);
- // // 添加标记点
- // const marker = new globalAMap.Marker({
- // position: firstPoi.location,
- // title: firstPoi.name,
- // });
- // globalMap?.add(marker);
- }
- resolve(firstPoi);
- } else {
- reject(new Error('未找到相关地点'));
- }
- });
- });
- });
- };
- /**
- * 根据城市码定位地图
- * @param cityCode 城市编码
- */
- const setCityByCode = async (cityCode: string): Promise<void> => {
- if (!globalAMap || !globalMap) {
- throw new Error('地图未初始化');
- }
- return new Promise((resolve, reject) => {
- globalMap?.setCity(cityCode, (result) => {
- if (result) {
- resolve(result);
- } else {
- reject(new Error('设置城市失败'));
- }
- });
- });
- };
- /**
- * 获取当前位置
- */
- const getCurrentPosition = async (): Promise<any> => {
- if (!globalAMap) {
- throw new Error('AMap未加载');
- }
- return new Promise((resolve, reject) => {
- globalAMap.plugin(['AMap.Geolocation'], () => {
- const geolocation = new globalAMap.Geolocation({
- enableHighAccuracy: true,
- timeout: 10000,
- });
- geolocation.getCurrentPosition((status: string, result: any) => {
- if (status === 'complete') {
- // 定位到当前位置
- getAddressByLngLat(result.position.lng, result.position.lat);
- if (result.position) {
- globalMap?.setCenter(result.position);
- globalMap?.setZoom(18);
- }
- resolve(result);
- } else {
- reject(result);
- }
- });
- });
- });
- };
- /**
- * 通过经纬度获取省市区信息
- * @param longitude 经度
- * @param latitude 纬度
- * @returns 省市区信息
- */
- const getAddressByLngLat = async (longitude: number, latitude: number): Promise<any> => {
- if (!globalAMap) {
- throw new Error('AMap未加载');
- }
- return new Promise((resolve, reject) => {
- globalAMap.plugin(['AMap.Geocoder'], () => {
- const geocoder = new globalAMap.Geocoder({
- city: '全国',
- radius: 1000,
- extensions: 'all',
- });
- lnglat.value = [longitude, latitude];
- geocoder.getAddress(lnglat.value, (status: string, result: any) => {
- if (status === 'complete' && result.regeocode) {
- currentObj.value.currentAddress = result.regeocode.formattedAddress;
- if (result.regeocode.addressComponent) {
- currentObj.value.currentAdcode = result.regeocode.addressComponent.adcode;
- }
- resolve(result.regeocode);
- } else {
- reject(new Error('无法获取地址信息'));
- }
- });
- });
- });
- };
- /**
- * 根据城市码和详细地址精确定位
- * @param cityCode 城市编码
- * @param address 详细地址
- */
- const locateByCityAndAddress = async (cityCode: string, address: string): Promise<any> => {
- if (!globalAMap || !globalMap) {
- throw new Error('地图未初始化');
- }
- // 先根据城市码设置地图城市
- await setCityByCode(cityCode);
- // 然后在指定城市内搜索详细地址
- return new Promise((resolve, reject) => {
- globalAMap.plugin(['AMap.PlaceSearch'], () => {
- const placeSearch = new globalAMap.PlaceSearch({
- city: cityCode,
- citylimit: true,
- pageSize: 10,
- pageIndex: 1,
- autoFitView: true,
- });
- placeSearch.search(address, (status: string, result: any) => {
- if (status === 'complete' && result.poiList && result.poiList.pois.length > 0) {
- const firstPoi = result.poiList.pois[0];
- if (firstPoi.location) {
- globalMap?.setCenter(firstPoi.location);
- globalMap?.setZoom(18);
- }
- resolve(firstPoi);
- } else {
- reject(new Error('未找到相关地点'));
- message.error('该区域下暂无该地点');
- }
- });
- });
- });
- };
- /**
- * 销毁地图
- */
- const destroyMap = () => {
- if (globalMap) {
- globalMap.destroy();
- globalMap = null;
- }
- isInitialized = false;
- initPromise = null;
- currentObj.value.currentAdcode = ''; // 清空adcode数据
- currentObj.value.currentAddress = '';
- lnglat.value = [];
- };
- return {
- // 响应式数据
- isLoading,
- error,
- currentObj,
- lnglat,
- // 方法
- initMap,
- searchAndLocate,
- getCurrentPosition,
- destroyMap,
- setCityByCode,
- locateByCityAndAddress,
- getAddressByLngLat,
- // 提供获取全局地图实例的方法
- getGlobalMap: () => globalMap,
- getGlobalAMap: () => globalAMap,
- isMapInitialized: () => isInitialized,
- };
- }
|