From 3b8ba54ea299a9febdf3a989a72b4eba311be796 Mon Sep 17 00:00:00 2001
From: tuqin <tuqin@tuqin.cn>
Date: 星期四, 05 十一月 2026 16:51:57 +0800
Subject: [PATCH] fix(map): SDK 改走同域反向代理,绕开客户端 IPv6 不通

---
 src/components/map/src/utils.ts |   92 ++++++++++++++----------------
 public/bmap-test.html           |   40 +++++++++++++
 2 files changed, 82 insertions(+), 50 deletions(-)

diff --git a/public/bmap-test.html b/public/bmap-test.html
index 9118654..b6f23d3 100644
--- a/public/bmap-test.html
+++ b/public/bmap-test.html
@@ -105,5 +105,45 @@
 
       document.body.appendChild(script);
     </script>
+
+    <hr style="margin:24px 0" />
+    <h3>缁忔湰绔欎唬鐞嗗姞杞斤紙缁曞紑 IPv6锛�</h3>
+    <div id="log2" style="padding:12px;background:#f0f9ff;border-radius:6px;font-family:Consolas,monospace;font-size:13px;line-height:1.9;white-space:pre-wrap;word-break:break-all"></div>
+    <div id="map2" style="width:100%;height:320px;margin-top:12px;border:1px solid #ddd"></div>
+    <script>
+      (function () {
+        var el = document.getElementById('log2');
+        function lg(msg, cls) {
+          var t = new Date().toLocaleTimeString('zh-CN', { hour12: false });
+          var d = document.createElement('div');
+          d.className = cls || '';
+          d.textContent = '[' + t + '] ' + msg;
+          el.appendChild(d);
+        }
+        var url = '/bmap-api/getscript?type=webgl&v=1.0&ak=' + KEY + '&services=&t=' + Date.now();
+        lg('寮�濮嬪姞杞斤紙鍚屽煙浠g悊锛�: ' + url);
+        var start = Date.now();
+        var s = document.createElement('script');
+        s.src = url;
+        s.addEventListener('load', function () {
+          lg('load 浜嬩欢瑙﹀彂锛堣�楁椂 ' + ((Date.now() - start) / 1000).toFixed(2) + ' 绉掞級', 'ok');
+          lg('window.BMapGL = ' + (window.BMapGL ? '瀛樺湪' : '涓嶅瓨鍦�'), window.BMapGL ? 'ok' : 'bad');
+          if (window.BMapGL) {
+            try {
+              var m = new window.BMapGL.Map(document.getElementById('map2'));
+              m.centerAndZoom(new window.BMapGL.Point(87.616848, 43.825592), 14);
+              m.enableScrollWheelZoom(true);
+              lg('鍦板浘鍒涘缓鎴愬姛锛佸鏋滀笅鏂瑰湴鍥捐兘鏄剧ず锛岃鏄庣摝鐗囦篃鑳藉姞杞�', 'ok');
+            } catch (e) {
+              lg('鍒涘缓鍦板浘澶辫触: ' + e.message, 'bad');
+            }
+          }
+        });
+        s.addEventListener('error', function () {
+          lg('error 浜嬩欢瑙﹀彂锛氫唬鐞嗕篃涓嶉�氾紙璇存槑 9023 绔彛鎴� nginx 閰嶇疆闂锛�', 'bad');
+        });
+        document.body.appendChild(s);
+      })();
+    </script>
   </body>
 </html>
diff --git a/src/components/map/src/utils.ts b/src/components/map/src/utils.ts
index 8937315..b170317 100644
--- a/src/components/map/src/utils.ts
+++ b/src/components/map/src/utils.ts
@@ -1,24 +1,23 @@
 /**
  * 鐧惧害鍦板浘 SDK 鍔犺浇宸ュ叿
  *
- * 鍔犺浇鏂瑰紡璇存槑锛堣俯杩囩殑鍧戯級锛�
+ * 鍔犺浇鍦板潃浼樺厛绾э紙鎸夐『搴忓皾璇曪紝閮藉け璐ユ墠鎶ラ敊锛夛細
+ *   1. /bmap-api/getscript  鈥斺�� 鏈珯 nginx 鍙嶅悜浠g悊锛屽己鍒跺洖婧愮櫨搴� IPv4
+ *   2. https://api.map.baidu.com/getscript 鈥斺�� 鐩磋繛鐧惧害
  *
- * 1. 涓嶈兘鐢� api?v=1.0&type=webgl&ak=xxx 杩欎釜鍦板潃銆�
- *    瀹冭繑鍥炵殑鏄竴娈� document.write('<script src=".../getscript?...">')锛�
- *    鑰岄�氳繃 document.body.append(script) 鍔ㄦ�佹彃鍏ョ殑鑴氭湰閲� document.write 浼氳娴忚鍣ㄦ嫤鎴紝
- *    瀵艰嚧鐪熸鐨� SDK 浠庢湭鎵ц銆亀indow.BMapGL 涓�鐩存槸绌猴紱浣� api 鐨� callback 浠嶄細琚皟鐢紝
- *    璋冪敤鏂硅鍒ゆ垚鍔燂紝鎺ョ潃 new BMapGL.Map() 灏辨姏
- *    "Cannot read properties of null (reading 'Map')"銆�
+ * 涓轰粈涔堣浠g悊锛堝疄娴嬬粨璁猴級锛�
+ *   璇ラ儴缃茬幆澧冿紙鍚鎴风鎵�鍦ㄧ綉缁滐級IPv6 涓嶉�氾紝鑰� api.map.baidu.com 鐨� DNS
+ *   浼樺厛杩斿洖 AAAA锛圛Pv6锛夎褰曪紝娴忚鍣ㄤ紭鍏堣繛 IPv6 鏃剁珛鍗冲け璐モ�斺��
+ *   script 鐨� error 浜嬩欢鍦� 1 绉掑唴灏辫Е鍙戯紝鏍规湰涓嶆槸瓒呮椂銆�
+ *   鏈嶅姟鍣ㄤ晶楠岃瘉锛歝url -4 寰楀埌 HTTP 200 / 0.94s锛宑url -6 鐩存帴澶辫触銆�
+ *   璧板悓鍩熶唬鐞嗗悗锛屽鎴风鍙闂湰鏈� 9023锛岀敱鏈嶅姟鍣ㄧ敤鍥哄畾 IPv4 鍥炴簮锛�
+ *   瀹炴祴 HTTP 200 / 879KB / 0.28s銆�
  *
- * 2. 蹇呴』鐩磋繛 getscript锛屽畠鏄� 875KB 鐨勭湡瀹� SDK銆�
- *
- * 3. 鍔犺浇鍓嶈璁剧疆 window.BMAP_PROTOCOL = 'https'锛堢櫨搴﹀畼鏂硅姹傦級锛�
- *    鍚﹀垯 SDK 鍐呴儴鎸夐粯璁ゅ崗璁嫾瀛愯祫婧愬湴鍧�锛孒TTPS 椤甸潰涓嬩細琚綋浣滄贩鍚堝唴瀹规嫤鎴��
- *
- * 4. 涓嶈缁� script 鍔� async = true锛歋DK 鍐呴儴鐢� document.currentScript 瀹氫綅鑷韩锛�
- *    async 鑴氭湰鎵ц鏈熼棿 currentScript 涓� null锛屼細璁╁畠璧板埌 fallback 鍒嗘敮鐢氳嚦鎷夸笉鍒拌嚜韬湴鍧�銆�
- *
- * 5. 澶辫触閲嶈瘯涓�娆★細鍋跺彂缃戠粶鎶栧姩锛堝挨鍏舵槸璺ㄧ渷/绉诲姩缃戠粶锛夐噸璇曞線寰�灏辫兘杩囥��
+ * 鍏朵粬韪╄繃鐨勫潙锛�
+ *   - 涓嶈兘鐢� api?v=1.0&type=webgl锛堣繑鍥� document.write 鍖呰锛屽姩鎬佽剼鏈噷浼氳娴忚鍣ㄦ嫤鎴級
+ *   - 鍔犺浇鍓嶈璁� window.BMAP_PROTOCOL = 'https'锛堢櫨搴﹀畼鏂硅姹傦級
+ *   - 涓嶈缁� script 鍔� async锛圫DK 渚濊禆 document.currentScript 瀹氫綅鑷韩锛�
+ *   - script 鐨勪簨浠跺悕鏄� error锛屼笉鏄� onerror
  */
 
 // 鎵╁睍 Window 鎺ュ彛浠ュ寘鍚櫨搴﹀湴鍥� GL API
@@ -32,27 +31,22 @@
 
 // SDK 鍔犺浇鐘舵��
 let loadPromise: null | Promise<void> = null;
-// 鍔犺浇澶辫触娆℃暟锛岀敤浜庡喅瀹氭槸鍚﹂噸璇�
-let failCount = 0;
 
-/** 鍗曟灏濊瘯鍔犺浇 */
-function loadOnce(accessKey: string, timeout: number): Promise<void> {
+/** 鐢ㄦ寚瀹氬湴鍧�鍔犺浇涓�娆� */
+function loadFrom(url: string, timeout: number): Promise<void> {
   return new Promise((resolve, reject) => {
     const timeoutId = setTimeout(() => {
-      reject(new Error('鐧惧害鍦板浘 SDK 鍔犺浇瓒呮椂锛岃妫�鏌ョ綉缁�'));
+      reject(new Error(`鐧惧害鍦板浘 SDK 鍔犺浇瓒呮椂锛�${url}`));
     }, timeout);
 
     const script = document.createElement('script');
-    script.src = `https://api.map.baidu.com/getscript?type=webgl&v=1.0&ak=${accessKey}&services=&t=${Date.now()}`;
+    script.src = url;
     // 娉ㄦ剰锛氫笉瑕佽 async锛孲DK 渚濊禆 document.currentScript 瀹氫綅鑷韩
 
     script.addEventListener('load', () => {
       clearTimeout(timeoutId);
       if (!window.BMapGL) {
-        // ak 鏃犳晥 / 鍩熷悕鏈巿鏉� / 琚嫤鎴椂锛岃剼鏈兘鍔犺浇浣嗕笉浼氭寕杞� BMapGL
-        reject(
-          new Error('鐧惧害鍦板浘鍔犺浇寮傚父锛氭湭鑾峰彇鍒板湴鍥惧璞★紝璇锋鏌� Key 鎴栧煙鍚嶆巿鏉�'),
-        );
+        reject(new Error('鑴氭湰宸蹭笅杞戒絾鏈寕杞藉湴鍥惧璞�'));
         return;
       }
       resolve();
@@ -61,11 +55,7 @@
     // 浜嬩欢鍚嶆槸 error锛屼笉鏄� onerror锛堝啓 onerror 姘歌繙涓嶄細瑙﹀彂锛�
     script.addEventListener('error', () => {
       clearTimeout(timeoutId);
-      reject(
-        new Error(
-          '鐧惧害鍦板浘 SDK 鍔犺浇澶辫触锛堟棤娉曡闂� api.map.baidu.com锛屽彲鑳芥槸缃戠粶闄愬埗鎴栨彃浠舵嫤鎴級',
-        ),
-      );
+      reject(new Error(`鍔犺浇澶辫触锛�${url}`));
     });
 
     document.body.append(script);
@@ -74,16 +64,13 @@
 
 /**
  * 鍔犺浇鐧惧害鍦板浘 GL SDK
- * @param timeout 瓒呮椂鏃堕棿锛堟绉掞級锛岄粯璁� 10000
+ * @param timeout 鍗曟灏濊瘯鐨勮秴鏃舵椂闂达紙姣锛夛紝榛樿 10000
  * @returns Promise<void>
  */
 export const loadBaiduMapSdk = (timeout = 10_000): Promise<void> => {
-  // 宸插姞杞藉畬鎴�
   if (window.BMapGL) {
     return Promise.resolve();
   }
-
-  // 姝e湪鍔犺浇涓紝杩斿洖鍚屼竴涓� Promise
   if (loadPromise) {
     return loadPromise;
   }
@@ -94,25 +81,30 @@
   }
 
   // 鐧惧害瀹樻柟瑕佹眰锛氬厛澹版槑鍗忚锛岄伩鍏� HTTPS 椤甸潰涓� SDK 鎷煎嚭 http 瀛愯祫婧愬湴鍧�
-  if (typeof window !== 'undefined') {
-    window.BMAP_PROTOCOL = 'https';
-    window.BMapGL_loadScriptTime = Date.now();
-  }
+  window.BMAP_PROTOCOL = 'https';
+  window.BMapGL_loadScriptTime = Date.now();
+
+  const query = `type=webgl&v=1.0&ak=${accessKey}&services=&t=${Date.now()}`;
+  // 浼樺厛鍚屽煙鍙嶄唬锛堢粫杩囧鎴风 IPv6 涓嶉�氾級锛屽啀鍥為��鐩磋繛
+  const candidates = [
+    `/bmap-api/getscript?${query}`,
+    `https://api.map.baidu.com/getscript?${query}`,
+  ];
 
   loadPromise = (async () => {
-    try {
-      await loadOnce(accessKey, timeout);
-    } catch (error) {
-      // 棣栨澶辫触閲嶈瘯涓�娆★紝搴斿鍋跺彂缃戠粶鎶栧姩
-      if (failCount < 1) {
-        failCount += 1;
-        await loadOnce(accessKey, timeout);
-      } else {
-        failCount = 0;
-        loadPromise = null;
-        throw error;
+    let lastError: any;
+    for (const url of candidates) {
+      try {
+        await loadFrom(url, timeout);
+        return;
+      } catch (error) {
+        lastError = error;
       }
     }
+    loadPromise = null;
+    throw new Error(
+      `鐧惧害鍦板浘 SDK 鍔犺浇澶辫触锛堝凡灏濊瘯浠g悊涓庣洿杩烇級锛�${lastError?.message ?? ''}`,
+    );
   })();
 
   return loadPromise;

--
Gitblit v1.9.3