/** * Modal Portal 工具函数 * 专门处理复杂容器结构中的 Modal 渲染问题 */ /** * 创建 Modal 容器并确保正确的层级 */ export const createModalContainer = (id: string = 'modal-root'): HTMLElement => { // 检查是否已存在容器 let container = document.getElementById(id); if (!container) { container = document.createElement('div'); container.id = id; // 设置容器样式,确保不受任何父级影响 container.style.cssText = ` position: fixed; top: 0; left: 0; right: 0; bottom: 0; pointer-events: none; z-index: 999999; isolation: isolate; `; // 直接添加到 body,避免复杂容器结构的影响 document.body.appendChild(container); } return container; }; /** * 清理 Modal 容器 */ export const cleanupModalContainer = (id: string = 'modal-root'): void => { const container = document.getElementById(id); if (container && container.children.length === 0) { document.body.removeChild(container); } }; /** * 检测当前环境是否有复杂的容器结构 */ export const detectComplexContainerStructure = (element?: HTMLElement): boolean => { const targetElement = element || document.querySelector('[class*="h-screen"]') as HTMLElement; if (!targetElement) return false; const indicators = [ 'h-screen', 'flex-col', 'overflow-y-auto', 'overflow-auto', 'overflow-scroll' ]; // 检查是否包含复杂容器结构的指示器 const hasComplexStructure = indicators.some(indicator => document.querySelector(`[class*="${indicator}"]`) ); if (hasComplexStructure) { console.log('Complex container structure detected in DOM'); } return hasComplexStructure; }; /** * 应用复杂容器结构的修复 */ export const applyComplexContainerFix = (modalElement: HTMLElement): void => { if (!modalElement) return; // 添加修复类 modalElement.classList.add('complex-container-fix'); modalElement.setAttribute('data-complex-container', 'true'); // 强制样式修复 const fixStyles = { position: 'fixed', top: '0', left: '0', right: '0', bottom: '0', width: '100vw', height: '100vh', zIndex: '999999', transform: 'translateZ(0)', isolation: 'isolate', contain: 'none', clipPath: 'none', clip: 'auto' }; Object.assign(modalElement.style, fixStyles); // 修复背景遮罩 const backdrop = modalElement.querySelector('.modal-backdrop-fixed') as HTMLElement; if (backdrop) { const backdropStyles = { position: 'fixed', top: '0', left: '0', right: '0', bottom: '0', width: '100vw', height: '100vh', zIndex: '-1' }; Object.assign(backdrop.style, backdropStyles); } console.log('Applied complex container fix to modal'); }; /** * 移除复杂容器结构的修复 */ export const removeComplexContainerFix = (modalElement: HTMLElement): void => { if (!modalElement) return; modalElement.classList.remove('complex-container-fix'); modalElement.removeAttribute('data-complex-container'); // 重置样式(让 CSS 类接管) const stylesToReset = [ 'position', 'top', 'left', 'right', 'bottom', 'width', 'height', 'zIndex', 'transform', 'isolation', 'contain', 'clipPath', 'clip' ]; stylesToReset.forEach(prop => { modalElement.style.removeProperty(prop); }); const backdrop = modalElement.querySelector('.modal-backdrop-fixed') as HTMLElement; if (backdrop) { stylesToReset.forEach(prop => { backdrop.style.removeProperty(prop); }); } }; /** * 获取安全的 Modal 渲染容器 * 确保 Modal 始终渲染在正确的位置 */ export const getSafeModalContainer = (): HTMLElement => { // 优先使用专门的 modal 容器 let container = document.getElementById('modal-root'); if (!container) { container = createModalContainer('modal-root'); } // 确保容器在 body 的最后,避免被其他元素覆盖 if (container.parentElement === document.body) { document.body.appendChild(container); } return container; }; /** * 监听窗口大小变化,确保 Modal 始终正确覆盖 */ export const setupModalResizeHandler = (modalElement: HTMLElement): (() => void) => { const handleResize = () => { if (modalElement.hasAttribute('data-complex-container')) { // 重新应用修复 applyComplexContainerFix(modalElement); } }; window.addEventListener('resize', handleResize); window.addEventListener('orientationchange', handleResize); // 返回清理函数 return () => { window.removeEventListener('resize', handleResize); window.removeEventListener('orientationchange', handleResize); }; };