/** * 文件职责:按需加载腾讯地图 JS SDK。 * 1. 使用全局 callback + 单例 Promise,避免重复注入脚本。 * 2. 与 AdminUI 的加载策略保持一致,降低多实例冲突风险。 */ declare global { interface Window { TMap?: any; __tenantTencentMapInit?: () => void; } } const SCRIPT_ID = 'tenant-tencent-map-gljs-sdk'; const CALLBACK_NAME = '__tenantTencentMapInit'; const SCRIPT_LOAD_TIMEOUT_MS = 12_000; const TENCENT_MAP_LIBRARIES = 'visualization,geometry,vector,tools,service'; let mapSdkPromise: null | Promise = null; let scriptLoading = false; const pendingResolvers: Array<(value: any) => void> = []; const pendingRejectors: Array<(error: Error) => void> = []; function getTencentMapKey() { return (import.meta.env.VITE_TENCENT_MAP_KEY as string | undefined)?.trim(); } function flushSuccess(tmap: any) { const resolvers = pendingResolvers.splice(0); pendingRejectors.splice(0); resolvers.forEach((resolve) => resolve(tmap)); } function flushError(error: Error) { const rejectors = pendingRejectors.splice(0); pendingResolvers.splice(0); rejectors.forEach((reject) => reject(error)); } function buildScriptUrl(mapKey: string) { return `https://map.qq.com/api/gljs?v=1.exp&key=${encodeURIComponent( mapKey, )}&libraries=${TENCENT_MAP_LIBRARIES}&callback=${CALLBACK_NAME}`; } export async function loadTencentMapSdk() { if (typeof window === 'undefined') { throw new TypeError('当前环境不支持加载地图'); } if (window.TMap) { return window.TMap; } const mapKey = getTencentMapKey(); if (!mapKey) { throw new Error('未配置腾讯地图 Key(VITE_TENCENT_MAP_KEY)'); } if (mapSdkPromise) { return mapSdkPromise; } mapSdkPromise = new Promise((resolve, reject) => { pendingResolvers.push(resolve); pendingRejectors.push(reject); if (scriptLoading) { return; } scriptLoading = true; const completeWithError = (error: Error) => { scriptLoading = false; mapSdkPromise = null; flushError(error); }; const timeoutHandle = window.setTimeout(() => { completeWithError(new Error('腾讯地图 SDK 加载超时')); }, SCRIPT_LOAD_TIMEOUT_MS); window[CALLBACK_NAME] = () => { window.clearTimeout(timeoutHandle); scriptLoading = false; if (!window.TMap) { completeWithError(new Error('腾讯地图 SDK 加载失败')); return; } flushSuccess(window.TMap); }; const existingScript = document.querySelector( `#${SCRIPT_ID}`, ); if (existingScript) { existingScript.addEventListener( 'error', () => { window.clearTimeout(timeoutHandle); completeWithError(new Error('腾讯地图 SDK 加载失败')); }, { once: true }, ); return; } const script = document.createElement('script'); script.id = SCRIPT_ID; script.type = 'text/javascript'; script.async = true; script.defer = true; script.src = buildScriptUrl(mapKey); script.addEventListener( 'error', () => { window.clearTimeout(timeoutHandle); completeWithError(new Error('腾讯地图 SDK 加载失败')); }, { once: true }, ); document.body.append(script); }); return mapSdkPromise; }