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 | null = null; const currentObj = ref({ currentAdcode: '', currentAddress: '', }); const lnglat = ref([]); export function useAMapEnhanced(options: EnhancedAMapOptions = {}) { const isLoading = ref(false); const error = ref(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 => { // 如果已经在初始化中,则返回该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 => { 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 => { 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 => { 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 => { 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 => { 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, }; }