Browse Source

fix(subapp-loading): 微应用挂载遮罩超时兜底 + 就绪等待防中断

- domUtils.resetMicroContentWH 增加 maxWaitMs(默认60s):原实现无限轮询等待
  容器出现内容,子应用挂载失败时遮罩永久转圈;超时强制放行并 console.error 定位
- 四个子应用容器组件(ventModal/ventModal2D/needAir/ventDoc)onMounted 改
  try/finally:mountMicroApp 同步抛错不再导致就绪等待被跳过
- 依据 docs/17 §8 实测(风量监测新开标签页永久加载)与 docs/16 基座审核 #6
86132 4 days ago
parent
commit
13622a5f08

+ 8 - 4
src/components/vent/micro/needAir.vue

@@ -13,10 +13,14 @@
     setup() {
       const loading = ref(true);
       onMounted(() => {
-        mountMicroApp('micro-need-air');
-        resetMicroContentWH('micro-need-air', () => {
-          loading.value = false;
-        });
+        // [fix-subapp-loading] try/finally 保证就绪等待始终启动(同 ventModal)
+        try {
+          mountMicroApp('micro-need-air');
+        } finally {
+          resetMicroContentWH('micro-need-air', () => {
+            loading.value = false;
+          });
+        }
       });
 
       onBeforeUnmount(async () => {

+ 8 - 4
src/components/vent/micro/ventDoc.vue

@@ -15,10 +15,14 @@
       const loading = ref(true);
       onMounted(() => {
         // 判断子应用是否存在,不存在注册
-        mountMicroApp('micro-vent-doc');
-        resetMicroContentWH('micro-vent-doc', () => {
-          loading.value = false;
-        });
+        // [fix-subapp-loading] try/finally 保证就绪等待始终启动(同 ventModal)
+        try {
+          mountMicroApp('micro-vent-doc');
+        } finally {
+          resetMicroContentWH('micro-vent-doc', () => {
+            loading.value = false;
+          });
+        }
       });
 
       onBeforeUnmount(async () => {

+ 9 - 4
src/components/vent/micro/ventModal.vue

@@ -15,10 +15,15 @@
       const loading = ref(true);
       onMounted(() => {
         // 判断子应用是否存在,不存在注册
-        mountMicroApp('micro-vent-3dModal', true);
-        resetMicroContentWH('micro-vent-3dModal', () => {
-          loading.value = false;
-        });
+        // [fix-subapp-loading] mountMicroApp 同步抛错会让后续 resetMicroContentWH 不再执行 → 遮罩永久卡死;
+        // try/finally 保证就绪等待始终启动(配合 domUtils 的 60s 超时兜底)
+        try {
+          mountMicroApp('micro-vent-3dModal', true);
+        } finally {
+          resetMicroContentWH('micro-vent-3dModal', () => {
+            loading.value = false;
+          });
+        }
       });
 
       onBeforeUnmount(async () => {

+ 8 - 4
src/components/vent/micro/ventModal2D.vue

@@ -13,10 +13,14 @@
     setup() {
       const loading = ref(true);
       onMounted(() => {
-        mountMicroApp('micro-vent-2dModal');
-        resetMicroContentWH('micro-vent-2dModal', () => {
-          loading.value = false;
-        });
+        // [fix-subapp-loading] try/finally 保证就绪等待始终启动(同 ventModal)
+        try {
+          mountMicroApp('micro-vent-2dModal');
+        } finally {
+          resetMicroContentWH('micro-vent-2dModal', () => {
+            loading.value = false;
+          });
+        }
       });
 
       onBeforeUnmount(async () => {

+ 23 - 11
src/utils/domUtils.ts

@@ -171,15 +171,27 @@ export function useRafThrottle<T extends FunctionArgs>(fn: T): T {
   };
 }
 
-export function resetMicroContentWH(domId, callBack?: Function) {
-  const contentDom = document.getElementById(domId);
-  if (contentDom && contentDom.firstChild) {
-    (contentDom.firstChild as HTMLElement).style.height = '100%';
-    (contentDom.firstChild as HTMLElement).style.width = '100%';
-    if (callBack) callBack();
-  } else {
-    setTimeout(() => {
-      resetMicroContentWH(domId, callBack);
-    }, 1000);
-  }
+export function resetMicroContentWH(domId, callBack?: Function, maxWaitMs = 60000) {
+  // [fix-subapp-loading] 增加超时兜底:原实现每秒无限轮询等待微应用容器出现内容,
+  // 微应用挂载失败/被卸载时容器永远为空 → 加载遮罩永久转圈(整页"正在加载"卡死,见 docs/17 §8)。
+  // 超时后强制放行(隐藏遮罩),把"整页永久卡死"降级为"页面可见但内容可能缺失"。
+  const start = Date.now();
+  let done = false;
+  const poll = () => {
+    if (done) return;
+    const contentDom = document.getElementById(domId);
+    if (contentDom && contentDom.firstChild) {
+      done = true;
+      (contentDom.firstChild as HTMLElement).style.height = '100%';
+      (contentDom.firstChild as HTMLElement).style.width = '100%';
+      if (callBack) callBack();
+    } else if (Date.now() - start >= maxWaitMs) {
+      done = true;
+      console.error('[fix-subapp-loading] 微应用容器等待超时,强制放行:', domId);
+      if (callBack) callBack();
+    } else {
+      setTimeout(poll, 1000);
+    }
+  };
+  poll();
 }