From 2e3a4a3a9c5d4f207b26a4311289e4bfe148b6cd Mon Sep 17 00:00:00 2001 From: nanako <469449812@qq.com> Date: Wed, 12 Nov 2025 10:23:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=90=8E=E7=AB=AF=E6=A8=A1?= =?UTF-8?q?=E5=9E=8B=E7=AD=9B=E9=80=89=E6=A1=86=E5=8F=AA=E5=89=A9=E4=B8=80?= =?UTF-8?q?=E4=B8=AA=E7=BB=93=E6=9E=9C=E6=97=B6=E6=97=A0=E6=B3=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/components/ui/FuzzySearchSelect.jsx | 51 +++++++++++++++++-- 1 file changed, 47 insertions(+), 4 deletions(-) diff --git a/frontend/src/components/ui/FuzzySearchSelect.jsx b/frontend/src/components/ui/FuzzySearchSelect.jsx index 62dbc7a..06b8506 100644 --- a/frontend/src/components/ui/FuzzySearchSelect.jsx +++ b/frontend/src/components/ui/FuzzySearchSelect.jsx @@ -19,6 +19,7 @@ const FuzzySearchSelect = ({ const loadedOptionsRef = useRef([]); const hasLoadedRef = useRef(false); const lastLoadOptionsRef = useRef(null); + const isUserTypingRef = useRef(false); // 标记用户是否正在输入 const fuzzySearch = (query, items) => { if (!query) return items; @@ -58,13 +59,22 @@ const FuzzySearchSelect = ({ } }, [isOpen]); // 仅依赖 isOpen - // 当 value prop 改变时,同步到 searchTerm(用于初始化或外部更新,但不打开下拉框) + // 当 value prop 改变时,同步到 searchTerm(用于初始化或外部更新) + // 但只有在用户没有正在输入的情况下才同步,避免覆盖用户输入 useEffect(() => { - if (value !== undefined && value !== null && value !== searchTerm) { + console.log('[FuzzySearchSelect] value useEffect 触发:', { + value, + searchTerm, + isUserTyping: isUserTypingRef.current, + condition: value && value !== searchTerm && !isUserTypingRef.current, + willUpdate: value && value !== searchTerm && !isUserTypingRef.current + }); + // 只有在用户没有正在输入时才接受外部的 value 更新 + if (value && value !== searchTerm && !isUserTypingRef.current) { + console.log('[FuzzySearchSelect] 强制同步 searchTerm 为 value:', value); setSearchTerm(value); - // 不打开下拉框,只更新搜索词显示 } - }, [value, searchTerm]); + }, [value]); // 当 loadOptions 函数引用改变时(提供商改变),重置加载状态 useEffect(() => { @@ -83,10 +93,22 @@ const FuzzySearchSelect = ({ if (loadOptions && hasLoadedRef.current) { // 异步加载模式:从已加载的选项中搜索 const filtered = fuzzySearch(searchTerm, loadedOptionsRef.current); + console.log('[FuzzySearchSelect] 搜索过滤结果 (异步模式):', { + searchTerm, + totalOptions: loadedOptionsRef.current.length, + filteredCount: filtered.length, + filtered + }); setFilteredOptions(filtered); } else if (!loadOptions && options.length > 0) { // 同步模式:从传入的 options 中搜索 const filtered = fuzzySearch(searchTerm, options); + console.log('[FuzzySearchSelect] 搜索过滤结果 (同步模式):', { + searchTerm, + totalOptions: options.length, + filteredCount: filtered.length, + filtered + }); setFilteredOptions(filtered); } }, [searchTerm]); // 仅依赖 searchTerm,不依赖 loadOptions 或 options @@ -104,6 +126,12 @@ const FuzzySearchSelect = ({ }, []); const handleSelect = (option) => { + console.log('[FuzzySearchSelect] 用户选择选项:', { + option, + currentSearchTerm: searchTerm + }); + // 用户选择后,清除输入标记,允许外部更新 + isUserTypingRef.current = false; onChange(option); setSearchTerm(option); setIsOpen(false); @@ -111,8 +139,22 @@ const FuzzySearchSelect = ({ const handleInputChange = (e) => { const value = e.target.value; + console.log('[FuzzySearchSelect] 用户输入改变:', { + newValue: value, + currentSearchTerm: searchTerm, + filteredOptionsCount: filteredOptions.length + }); + + // 标记用户正在输入 + isUserTypingRef.current = true; setSearchTerm(value); setIsOpen(true); + + // 使用防抖:300ms 后清除输入标记 + // 这样可以防止在用户输入过程中被外部更新覆盖 + setTimeout(() => { + isUserTypingRef.current = false; + }, 300); }; const handleInputFocus = () => { @@ -162,3 +204,4 @@ const FuzzySearchSelect = ({ }; export default FuzzySearchSelect; +