fix: issue when adding a one-to-one relationship field in the form (#5975)

This commit is contained in:
Katherine 2024-12-31 14:17:53 +08:00 committed by GitHub
parent 3ed00a2ebf
commit 81ada5022a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -9,7 +9,7 @@
import { uid } from '@formily/shared';
import { Divider, Empty, Input, MenuProps } from 'antd';
import React, { useEffect, useMemo, useState, useRef } from 'react';
import React, { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useCompile } from '../../../';
@ -36,10 +36,11 @@ export const SearchFields = ({ value: outValue, onChange, name }) => {
useEffect(() => {
const focusInput = () => {
if (
inputRef.current &&
document.activeElement?.id !== inputRef.current.input.id &&
getPrefixAndCompare(document.activeElement?.id, inputRef.current.input.id)
) {
inputRef.current?.focus();
inputRef.current.focus();
}
};
@ -96,20 +97,18 @@ export const SearchFields = ({ value: outValue, onChange, name }) => {
</div>
);
};
let currentName = null;
export const useMenuSearch = (props: { children: any[]; showType?: boolean; hideSearch?: boolean; name?: string }) => {
const { children, showType, hideSearch, name } = props;
const items = children?.concat?.() || [];
const [searchValue, setSearchValue] = useState(null);
const compile = useCompile();
const [searchValue, setSearchValue] = useState(null);
// 处理搜索逻辑
const limitedSearchedItems = useMemo(() => {
if (!searchValue || searchValue === '') {
return items;
const filteredItems = (data, name) => {
if (!searchValue || searchValue === '' || (currentName && currentName !== name)) {
return data;
}
const lowerSearchValue = searchValue.toLocaleLowerCase();
return items.filter((item) => {
return data.filter((item) => {
return (
(item.title || item.label) &&
String(compile(item.title || item.label))
@ -117,64 +116,72 @@ export const useMenuSearch = (props: { children: any[]; showType?: boolean; hide
.includes(lowerSearchValue)
);
});
}, [searchValue, items]);
};
// 最终结果项
const resultItems = useMemo<MenuProps['items']>(() => {
// 递归处理菜单项传递每一层的filteredItems
const generateResultItems = (items: any[], name, parentItems: Set<any> = new Set()): MenuProps['items'] => {
const res = [];
try {
// 如果满足条件则显示搜索框
if (!hideSearch && (items.length > 10 || searchValue)) {
res.push({
key: `search-${uid()}`,
Component: () => (
<SearchFields name={name} value={searchValue} onChange={(val: string) => setSearchValue(val)} />
),
onClick({ domEvent }) {
domEvent.stopPropagation();
},
...(showType ? { isMenuType: true } : {}),
});
}
// 如果有匹配的项目,渲染过滤后的项
if (limitedSearchedItems.length > 0) {
limitedSearchedItems.forEach((item) => {
// 如果是子菜单或分组项,递归处理
if (['subMenu', 'itemGroup'].includes(item.type)) {
// 避免动态渲染hooks
const childItems = item.children
? // eslint-disable-next-line react-hooks/rules-of-hooks
useMenuSearch({
children: item.children,
showType,
hideSearch,
name: item.name,
})
: [];
res.push({ ...item, children: childItems });
} else {
res.push(item);
}
});
} else {
// 没有匹配项时显示空状态
res.push({
key: 'empty',
style: { height: 150 },
Component: () => (
<div onClick={(e) => e.stopPropagation()}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</div>
),
...(showType ? { isMenuType: true } : {}),
});
}
} catch (error) {
res.push(...limitedSearchedItems);
// 如果满足条件则显示搜索框
if (!hideSearch && (items.length > 10 || searchValue) && !['subMenu', 'itemGroup'].includes(items[0]?.type)) {
res.push({
key: `search-${uid()}`,
Component: () => {
return (
<SearchFields
name={name}
value={!currentName || currentName === name ? searchValue : ''}
onChange={(val: string) => {
currentName = name;
setSearchValue(val);
}}
/>
);
},
onClick({ domEvent }) {
domEvent.stopPropagation();
},
...(showType ? { isMenuType: true } : {}),
});
}
// 递归处理所有项,包含子菜单
items.forEach((item) => {
if (parentItems.has(item)) return;
parentItems.add(item);
// 过滤当前项是否匹配搜索条件
if (['subMenu', 'itemGroup'].includes(item.type)) {
// 对子菜单项进行递归处理
const result =
!currentName || currentName === item.name ? filteredItems(item.children.concat(), item.name) : item.children;
const filteredChildren = generateResultItems(result, item.name, parentItems);
res.push({ ...item, children: filteredChildren });
} else {
// 处理非子菜单项
res.push(item);
}
});
// 如果没有匹配项时显示空状态
if (items.length === 0) {
res.push({
key: 'empty',
style: { height: 150 },
Component: () => (
<div onClick={(e) => e.stopPropagation()}>
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
</div>
),
...(showType ? { isMenuType: true } : {}),
});
}
return res;
}, [hideSearch, limitedSearchedItems, searchValue, showType]);
};
// 获取最终的结果项,处理根级菜单项
const resultItems = generateResultItems(filteredItems(children?.concat() || [], name), name);
return children ? resultItems : undefined;
};