diff --git a/src/components/image-editor/model3d-preview/Model3dViewerModal.test.tsx b/src/components/image-editor/model3d-preview/Model3dViewerModal.test.tsx
index b7dc2312c..bf75637e3 100644
--- a/src/components/image-editor/model3d-preview/Model3dViewerModal.test.tsx
+++ b/src/components/image-editor/model3d-preview/Model3dViewerModal.test.tsx
@@ -195,4 +195,20 @@ describe('Model3dViewerModal', () => {
expect(screen.queryByRole('dialog', { name: '3D模型预览' })).toBeNull();
});
+
+ it('关闭面板后重开不沿用上一轮的 ready 状态', () => {
+ const layer = createLayer();
+ const { rerender } = renderModal(layer);
+ const resetButton = () =>
+ screen.getByRole('button', { name: '重置视角' }) as HTMLButtonElement;
+
+ expect(resetButton().disabled).toBe(false);
+
+ rerender();
+ // 重开后的新查看器本轮不上报状态,按钮必须保持禁用,不能继承上一轮的 ready。
+ reportedStatus.status = 'idle';
+ rerender();
+
+ expect(resetButton().disabled).toBe(true);
+ });
});
diff --git a/src/components/image-editor/model3d-preview/Model3dViewerModal.tsx b/src/components/image-editor/model3d-preview/Model3dViewerModal.tsx
index 67e2f8dfb..e33d1201b 100644
--- a/src/components/image-editor/model3d-preview/Model3dViewerModal.tsx
+++ b/src/components/image-editor/model3d-preview/Model3dViewerModal.tsx
@@ -5,7 +5,7 @@ import {
type Model3dViewerStatus,
type Model3dViewerStatusDetail,
} from '@genarrative/model3d-viewer';
-import { useRef, useState } from 'react';
+import { useEffect, useRef, useState } from 'react';
import { useResolvedAssetReadUrl } from '../../../hooks/useResolvedAssetReadUrl';
import { PlatformActionButton } from '../../common/PlatformActionButton';
@@ -111,6 +111,14 @@ export function Model3dViewerModal({
MODEL3D_VIEWER_FAILURE_FALLBACK_TEXT,
);
+ // 面板关闭(layer 变 null)时清掉状态,让下一次打开从禁用的「重置视角」重新开始。
+ // 只处理关闭、不处理换模型:换模型时查看器会立刻上报,effect 晚一步会把 loading 盖掉。
+ useEffect(() => {
+ if (viewerIdentity === null) {
+ setViewerStatus(null);
+ }
+ }, [viewerIdentity]);
+
return (