fix: 优化动态列表和弹框UI体验

This commit is contained in:
imeepos
2025-07-18 18:45:13 +08:00
parent da4aeaccb9
commit 4da48c3281
16 changed files with 1601 additions and 346 deletions

View 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);
};
};