diff --git a/src/components/EpisodeFilterSettings.tsx b/src/components/EpisodeFilterSettings.tsx index e3b4dc5..99564e9 100644 --- a/src/components/EpisodeFilterSettings.tsx +++ b/src/components/EpisodeFilterSettings.tsx @@ -3,6 +3,7 @@ import { Plus, ToggleLeft, ToggleRight,Trash2, X } from 'lucide-react'; import { useEffect, useRef,useState } from 'react'; +import { createPortal } from 'react-dom'; import { getEpisodeFilterConfig, saveEpisodeFilterConfig } from '@/lib/db.client'; import { EpisodeFilterConfig, EpisodeFilterRule } from '@/lib/types'; @@ -29,6 +30,12 @@ export default function EpisodeFilterSettings({ const [isAnimating, setIsAnimating] = useState(false); const [inputKey, setInputKey] = useState(0); // 用于强制重新渲染输入框 const inputRef = useRef(null); // 用于直接操作输入框 DOM + const [mounted, setMounted] = useState(false); + + // 确保组件在客户端挂载后才渲染 Portal + useEffect(() => { + setMounted(true); + }, []); // 控制动画状态 useEffect(() => { @@ -210,11 +217,11 @@ export default function EpisodeFilterSettings({ })); }; - if (!isVisible) return null; + if (!isVisible || !mounted) return null; - return ( + const content = (
{ // 阻止最外层容器的触摸移动,防止背景滚动 e.preventDefault(); @@ -247,7 +254,7 @@ export default function EpisodeFilterSettings({ {/* 弹窗主体 */}
{ // 允许弹窗内部滚动,阻止事件冒泡到外层 e.stopPropagation(); @@ -284,7 +291,7 @@ export default function EpisodeFilterSettings({
{/* 内容区域 */} -
+
{/* 添加规则 */}

@@ -450,4 +457,7 @@ export default function EpisodeFilterSettings({

); + + // 使用 Portal 将组件渲染到 document.body + return createPortal(content, document.body); }