Commit 00e0378b by luoqi

fix(web): 召回池搜索改手动防抖,修中文搜索不发请求(上个 IME 修复的回归)

上个修复靠 onCompositionEnd 里 setSearch(最终值) 重触发 useEffect([search]) 防抖;
但组字中 onChange 已把 search 设成最终值 → compositionEnd 再 setSearch 同值 = 不重渲染
→ effect 不重跑 → keyword 永不更新 → 中文搜索不发请求(列表停在全量)。
改为手动防抖 scheduleKeyword:组字中(composingRef)onChange 不排;onCompositionEnd
解锁后直接排一次(不依赖 setSearch 是否引起重渲染)。本地实测:输入"程"→ 请求
keyword=%E7%A8%8B 发出、列表 236→1(程浩)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
parent 09b9dbb2
Pipeline #3370 failed in 0 seconds
......@@ -67,13 +67,21 @@ export function PatientPickerRail({
const clinicDict = user?.dictionary?.clinics; // 显示 plan 诊所名用(字典查表,非 scope)
const clinicOptions = useMemo(() => visibleClinics(user), [user]);
useEffect(() => {
// IME 组字中(如拼音 "李石ming" 未上屏)不触发搜索 —— 否则会拿中间态去查 → 误报"没有匹配"。
// 组字完成由 onCompositionEnd 解锁并用最终中文重新触发本 effect。
if (composingRef.current) return;
const t = setTimeout(() => setKeyword(search.trim()), 300);
return () => clearTimeout(t);
}, [search]);
// 关键词防抖:手动排定,**不依赖 search 状态变化触发**。
// (若靠 useEffect([search]):组字结束时最终值"李石明"可能与组字中最后一次 onChange 同值 →
// React 不重渲染 → effect 不重跑 → 搜索永不发。这正是"中文搜不发请求"的坑。)
// 规则:组字中(composingRef)onChange 不排;组字结束由 onCompositionEnd 直接排一次。
const debounceRef = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
const scheduleKeyword = (value: string) => {
if (debounceRef.current) clearTimeout(debounceRef.current);
debounceRef.current = setTimeout(() => setKeyword(value.trim()), 300);
};
useEffect(
() => () => {
if (debounceRef.current) clearTimeout(debounceRef.current);
},
[],
);
const filters: PickerFilters = useMemo(
() => ({
......@@ -159,14 +167,22 @@ export function PatientPickerRail({
<input
type="search"
value={search}
onChange={(e) => setSearch(e.target.value)}
onChange={(e) => {
const v = e.target.value;
setSearch(v);
// 组字中(拼音中间态)不搜;非组字(英文/数字/粘贴/原生清空)正常排定
if (!composingRef.current) scheduleKeyword(v);
}}
onCompositionStart={() => {
composingRef.current = true;
}}
onCompositionEnd={(e) => {
// 组字完成(拼音→汉字上屏)→ 解锁,并用最终中文触发一次防抖搜索
// 组字完成(拼音→汉字上屏)→ 解锁,并用最终中文直接排一次搜索
// (直接调 scheduleKeyword,不依赖 setSearch 是否引起重渲染)
composingRef.current = false;
setSearch(e.currentTarget.value);
const v = e.currentTarget.value;
setSearch(v);
scheduleKeyword(v);
}}
placeholder="姓名 / 手机 / 病历号"
className="h-7 w-full rounded-md border border-slate-100 bg-slate-50 pl-7 pr-2 text-[12px] outline-none placeholder:text-slate-400 focus:border-teal-300 focus:bg-white"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment