fix: 优化动态列表和弹框UI体验
This commit is contained in:
190
apps/desktop/src/utils/modalPortal.ts
Normal file
190
apps/desktop/src/utils/modalPortal.ts
Normal file
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* 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);
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user