diff --git a/packages/core/client/src/block-provider/SharedFilterProvider.tsx b/packages/core/client/src/block-provider/SharedFilterProvider.tsx index a2b12cde3b..1d39998248 100644 --- a/packages/core/client/src/block-provider/SharedFilterProvider.tsx +++ b/packages/core/client/src/block-provider/SharedFilterProvider.tsx @@ -17,6 +17,17 @@ export type SharedFilterContextValue = { getFilterParams: (filterStore?: SharedFilterStore) => any; }; +export const mergeFilter = (filters: any[], op = '$and') => { + const items = filters.filter(Boolean); + if (items.length === 0) { + return {}; + } + if (items.length === 1) { + return items[0]; + } + return { [op]: items }; +}; + export const getFilterParams = (filterStore?: SharedFilterStore) => { const newAssociationFilterList = Object.entries(filterStore).map(([key, filter]) => filter); const newAssociationFilter = newAssociationFilterList.length @@ -35,8 +46,8 @@ export const SharedFilterContext = createContext({ }); export const concatFilter = (f1: SharedFilter, f2: SharedFilter): SharedFilter => { - const newAnd = [f1.$and, f2.$and].filter((i) => i).reduce((pre, cur) => pre.concat(cur), []); - const newOr = [f1.$or, f2.$or].filter((i) => i).reduce((pre, cur) => pre.concat(cur), []); + const newAnd = [f1?.$and, f2?.$and].filter((i) => i).reduce((pre, cur) => pre.concat(cur), []); + const newOr = [f1?.$or, f2?.$or].filter((i) => i).reduce((pre, cur) => pre.concat(cur), []); const newFilter: SharedFilter = {}; newAnd.length && (newFilter.$and = newAnd); newOr.length && (newFilter.$or = newOr); diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx index 012a3a6b71..f4b579d38d 100644 --- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx +++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.Item.tsx @@ -3,10 +3,10 @@ import { css } from '@emotion/css'; import { useFieldSchema } from '@formily/react'; import { Col, Collapse, Input, Row, Tree } from 'antd'; import cls from 'classnames'; -import React, { ChangeEvent, MouseEvent, useContext, useState } from 'react'; +import React, { ChangeEvent, MouseEvent, useState } from 'react'; import { useRequest } from '../../../api-client'; import { useBlockRequestContext } from '../../../block-provider'; -import { SharedFilterContext } from '../../../block-provider/SharedFilterProvider'; +import { mergeFilter } from '../../../block-provider/SharedFilterProvider'; import { SortableItem } from '../../common'; import { useCompile, useDesigner } from '../../hooks'; import { AssociationFilter } from './AssociationFilter'; @@ -24,7 +24,6 @@ export const AssociationFilterItem = (props) => { const Designer = useDesigner(); const compile = useCompile(); const { service } = useBlockRequestContext(); - const { setSharedFilterStore, sharedFilterStore, getFilterParams } = useContext(SharedFilterContext); const [searchVisible, setSearchVisible] = useState(false); const collectionFieldName = collectionField.name; @@ -67,31 +66,17 @@ export const AssociationFilterItem = (props) => { const onSelect = (selectedKeysValue: React.Key[]) => { setSelectedKeys(selectedKeysValue); - const orList = selectedKeysValue.map((item) => ({ - [collectionFieldName]: { - [valueKey]: { - $eq: item, - }, - }, - })); + const filters = service.params?.[1]?.filters || {}; - const newFilter = - orList.length > 0 - ? { - $or: orList, - } - : {}; + if (selectedKeysValue.length) { + filters[`af.${collectionFieldName}`] = { + [`${collectionFieldName}.${valueKey}.$in`]: selectedKeysValue, + }; + } else { + delete filters[`af.${collectionFieldName}`]; + } - const newAssociationFilterStore = { - ...sharedFilterStore, - [collectionFieldName]: newFilter, - }; - - setSharedFilterStore(newAssociationFilterStore); - - const paramFilter = getFilterParams(newAssociationFilterStore); - - service.run({ ...service.params?.[0], pageSize: 200, page: 1, filter: paramFilter }); + service.run({ ...service.params?.[0], pageSize: 200, page: 1, filter: mergeFilter(Object.values(filters)) }, { filters }); }; const handleSearchToggle = (e: MouseEvent) => { diff --git a/packages/core/client/src/schema-component/antd/filter/useFilterActionProps.ts b/packages/core/client/src/schema-component/antd/filter/useFilterActionProps.ts index a92a9e2696..bbd596645c 100644 --- a/packages/core/client/src/schema-component/antd/filter/useFilterActionProps.ts +++ b/packages/core/client/src/schema-component/antd/filter/useFilterActionProps.ts @@ -1,10 +1,9 @@ import { Field } from '@formily/core'; import { useField, useFieldSchema } from '@formily/react'; import flat from 'flat'; -import { useContext } from 'react'; import { useTranslation } from 'react-i18next'; import { useBlockRequestContext } from '../../../block-provider'; -import { concatFilter, SharedFilterContext } from '../../../block-provider/SharedFilterProvider'; +import { mergeFilter } from '../../../block-provider/SharedFilterProvider'; import { useCollection, useCollectionManager } from '../../../collection-manager'; export const useFilterOptions = (collectionName: string) => { @@ -99,7 +98,6 @@ export const useFilterActionProps = () => { export const useFilterFieldProps = ({ options, service, params }) => { const { t } = useTranslation(); const field = useField(); - const { sharedFilterStore, setSharedFilterStore, getFilterParams } = useContext(SharedFilterContext); return { options, onSubmit(values) { @@ -108,16 +106,10 @@ export const useFilterFieldProps = ({ options, service, params }) => { // filter parameter for the filter action const filter = removeNullCondition(values?.filter); - const newSharedFilterStore = { - ...sharedFilterStore, - ActionBar: concatFilter(defaultFilter, filter), - }; + const filters = service.params?.[1]?.filters || {}; + filters[`default`] = mergeFilter([defaultFilter, filter]); - setSharedFilterStore(newSharedFilterStore); - - const paramFilter = getFilterParams(newSharedFilterStore); - - service.run({ ...service.params?.[0], page: 1, filter: paramFilter }); + service.run({ ...service.params?.[0], page: 1, filter: mergeFilter(Object.values(filters)) }, { filters }); const items = filter?.$and || filter?.$or; if (items?.length) { field.title = t('{{count}} filter items', { count: items?.length || 0 });