diff --git a/packages/core/client/src/application/__tests__/hoc/withDynamicSchemaProps.test.tsx b/packages/core/client/src/application/__tests__/hoc/withDynamicSchemaProps.test.tsx
index 7652b77e68df1..fa76a42e15956 100644
--- a/packages/core/client/src/application/__tests__/hoc/withDynamicSchemaProps.test.tsx
+++ b/packages/core/client/src/application/__tests__/hoc/withDynamicSchemaProps.test.tsx
@@ -9,8 +9,8 @@
import { render } from '@nocobase/test/client';
import React from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { SchemaComponent, SchemaComponentProvider } from '../../../schema-component';
-import { withDynamicSchemaProps } from '../../hoc';
const HelloComponent = withDynamicSchemaProps((props: any) => (
{JSON.stringify(props)}
diff --git a/packages/core/client/src/application/__tests__/schema-settings/hooks/useSchemaSettingsRender.test.tsx b/packages/core/client/src/application/__tests__/schema-settings/hooks/useSchemaSettingsRender.test.tsx
index 630f29c163d04..3404d1d846724 100644
--- a/packages/core/client/src/application/__tests__/schema-settings/hooks/useSchemaSettingsRender.test.tsx
+++ b/packages/core/client/src/application/__tests__/schema-settings/hooks/useSchemaSettingsRender.test.tsx
@@ -7,9 +7,9 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-import React from 'react';
import { Application, SchemaSettings, useSchemaSettingsRender } from '@nocobase/client';
import { render, screen, waitFor } from '@nocobase/test/client';
+import React from 'react';
describe('useSchemaSettingsRender', () => {
async function createApp(DemoComponent: any) {
diff --git a/packages/core/client/src/application/index.ts b/packages/core/client/src/application/index.ts
index cac885b888f6d..63a51be8b8757 100644
--- a/packages/core/client/src/application/index.ts
+++ b/packages/core/client/src/application/index.ts
@@ -8,15 +8,16 @@
*/
export * from './Application';
-export * from './hooks';
export * from './Plugin';
+export * from './PluginSettingsManager';
export * from './RouterManager';
-export * from './utils';
export * from './components';
+export { ApplicationContext } from './context';
+export * from './globalType';
+export * from './hooks';
export * from './schema-initializer';
export * from './schema-settings';
+export * from './schema-settings/context/SchemaSettingItemContext';
+export * from './schema-settings/hooks/useSchemaSettingsRender';
export * from './schema-toolbar';
-export * from './PluginSettingsManager';
-export * from './hoc';
-export { ApplicationContext } from './context';
-export * from './globalType';
+export * from './utils';
diff --git a/packages/core/client/src/application/schema-settings/components/SchemaSettingsChildren.tsx b/packages/core/client/src/application/schema-settings/components/SchemaSettingsChildren.tsx
index 44e30815e367d..f80a135dcbfea 100644
--- a/packages/core/client/src/application/schema-settings/components/SchemaSettingsChildren.tsx
+++ b/packages/core/client/src/application/schema-settings/components/SchemaSettingsChildren.tsx
@@ -9,6 +9,7 @@
import React, { FC, memo, useEffect, useMemo, useRef } from 'react';
+import { useFieldComponentName } from '../../../common/useFieldComponentName';
import { useFindComponent } from '../../../schema-component';
import {
SchemaSettingsActionModalItem,
@@ -24,9 +25,8 @@ import {
SchemaSettingsSwitchItem,
useSchemaSettings,
} from '../../../schema-settings/SchemaSettings';
-import { SchemaSettingItemContext } from '../context';
+import { SchemaSettingItemContext } from '../context/SchemaSettingItemContext';
import { SchemaSettingsItemType } from '../types';
-import { useFieldComponentName } from '../../../common/useFieldComponentName';
export interface SchemaSettingsChildrenProps {
children: SchemaSettingsItemType[];
diff --git a/packages/core/client/src/application/schema-settings/context/index.ts b/packages/core/client/src/application/schema-settings/context/index.ts
deleted file mode 100644
index d7f8c7e5740dc..0000000000000
--- a/packages/core/client/src/application/schema-settings/context/index.ts
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * This file is part of the NocoBase (R) project.
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
- * Authors: NocoBase Team.
- *
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
- * For more information, please refer to: https://www.nocobase.com/agreement.
- */
-
-export * from './SchemaSettingItemContext';
diff --git a/packages/core/client/src/application/schema-settings/hooks/index.tsx b/packages/core/client/src/application/schema-settings/hooks/index.tsx
deleted file mode 100644
index 11fe3de33dac3..0000000000000
--- a/packages/core/client/src/application/schema-settings/hooks/index.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * This file is part of the NocoBase (R) project.
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
- * Authors: NocoBase Team.
- *
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
- * For more information, please refer to: https://www.nocobase.com/agreement.
- */
-
-export * from './useSchemaSettingsRender';
diff --git a/packages/core/client/src/application/schema-settings/index.ts b/packages/core/client/src/application/schema-settings/index.ts
index 30327ee6cf152..2b155a229d81c 100644
--- a/packages/core/client/src/application/schema-settings/index.ts
+++ b/packages/core/client/src/application/schema-settings/index.ts
@@ -9,7 +9,6 @@
export * from './SchemaSettings';
export * from './SchemaSettingsManager';
-export * from './hooks';
export * from './components';
-export * from './context';
+export * from './context/SchemaSettingItemContext';
export * from './types';
diff --git a/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx b/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
index 7e6b1c0665355..207dbd3f15fcb 100644
--- a/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
+++ b/packages/core/client/src/block-provider/BlockSchemaComponentProvider.tsx
@@ -31,6 +31,7 @@ import { CollapseItemSchemaToolbar } from '../modules/blocks/filter-blocks/colla
import { useCollapseBlockDecoratorProps } from '../modules/blocks/filter-blocks/collapse/hooks/useCollapseBlockDecoratorProps';
import { useFilterFormBlockDecoratorProps } from '../modules/blocks/filter-blocks/form/hooks/useFilterFormBlockDecoratorProps';
import { useFilterFormBlockProps } from '../modules/blocks/filter-blocks/form/hooks/useFilterFormBlockProps';
+import { useFormItemProps } from '../modules/blocks/filter-blocks/form/hooks/useFormItemProps';
import { SchemaComponentOptions } from '../schema-component';
import { RecordLink, useParamsFromRecord, useSourceIdFromParentRecord, useSourceIdFromRecord } from './BlockProvider';
import { DetailsBlockProvider, useDetailsBlockProps } from './DetailsBlockProvider';
@@ -83,6 +84,7 @@ export const BlockSchemaComponentProvider: React.FC = (props) => {
useFilterFormBlockProps,
useFilterFormBlockDecoratorProps,
useGridCardBlockDecoratorProps,
+ useFormItemProps,
}}
>
{props.children}
@@ -142,6 +144,7 @@ export class BlockSchemaComponentPlugin extends Plugin {
useFilterFormBlockProps,
useFilterFormBlockDecoratorProps,
useGridCardBlockDecoratorProps,
+ useFormItemProps,
});
}
}
diff --git a/packages/core/client/src/block-provider/CollectOperators.tsx b/packages/core/client/src/block-provider/CollectOperators.tsx
new file mode 100644
index 0000000000000..a3355286eed69
--- /dev/null
+++ b/packages/core/client/src/block-provider/CollectOperators.tsx
@@ -0,0 +1,71 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import React, { FC, createContext, useCallback, useRef } from 'react';
+
+const NOOP = () => {};
+
+const CollectOperatorsContext = createContext<{
+ /** 手机单个字段的操作符 */
+ collectOperator: (name: string | number, operator: string) => void;
+ /** 获取所有字段的操作符 */
+ getOperators: () => Record;
+ /** 获取单个字段的操作符 */
+ getOperator: (name: string | number) => string;
+ /** 移除单个字段的操作符 */
+ removeOperator: (name: string | number) => void;
+}>(null);
+
+export const CollectOperators: FC<{ defaultOperators: Record }> = (props) => {
+ const operators = useRef(props.defaultOperators || {});
+
+ const collectOperator = useCallback((name: string, operator: string) => {
+ operators.current[name] = operator;
+ }, []);
+
+ const getOperators = useCallback(() => {
+ return { ...operators.current };
+ }, []);
+
+ const getOperator = useCallback((name: string) => {
+ return operators.current[name];
+ }, []);
+
+ const removeOperator = useCallback((name: string) => {
+ delete operators.current[name];
+ }, []);
+
+ return (
+
+ {props.children}
+
+ );
+};
+
+export const useOperators = () => {
+ const {
+ getOperator = NOOP,
+ getOperators = NOOP,
+ collectOperator = NOOP,
+ removeOperator = NOOP,
+ } = React.useContext(CollectOperatorsContext) || {};
+ return {
+ getOperator,
+ getOperators: getOperators as () => Record | undefined,
+ collectOperator,
+ removeOperator,
+ };
+};
diff --git a/packages/core/client/src/block-provider/DetailsBlockProvider.tsx b/packages/core/client/src/block-provider/DetailsBlockProvider.tsx
index 9270a8b896112..55b44ce314d9b 100644
--- a/packages/core/client/src/block-provider/DetailsBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/DetailsBlockProvider.tsx
@@ -11,10 +11,10 @@ import { createForm } from '@formily/core';
import { useField, useFieldSchema } from '@formily/react';
import { Spin } from 'antd';
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
-import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../collection-manager';
import { useCollectionRecordData } from '../data-source';
import { useCollectionParentRecord } from '../data-source/collection-record/CollectionRecordProvider';
+import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { useDetailsWithPaginationBlockParams } from '../modules/blocks/data-blocks/details-multi/hooks/useDetailsWithPaginationBlockParams';
import { RecordProvider } from '../record-provider';
import { useDesignable } from '../schema-component';
diff --git a/packages/core/client/src/block-provider/FilterFormBlockProvider.tsx b/packages/core/client/src/block-provider/FilterFormBlockProvider.tsx
index 089267f642300..0c0bb304edb50 100644
--- a/packages/core/client/src/block-provider/FilterFormBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/FilterFormBlockProvider.tsx
@@ -7,18 +7,26 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import { useFieldSchema } from '@formily/react';
import React from 'react';
+import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { DatePickerProvider } from '../schema-component';
import { DefaultValueProvider } from '../schema-settings';
+import { CollectOperators } from './CollectOperators';
import { FormBlockProvider } from './FormBlockProvider';
-import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
export const FilterFormBlockProvider = withDynamicSchemaProps((props) => {
+ const filedSchema = useFieldSchema();
+ // 'x-filter-operators' 已被弃用,这里是为了兼容旧的配置
+ const deprecatedOperators = filedSchema['x-filter-operators'] || {};
+
return (
-
- false}>
-
-
-
+
+
+ false}>
+
+
+
+
);
});
diff --git a/packages/core/client/src/block-provider/FormBlockProvider.tsx b/packages/core/client/src/block-provider/FormBlockProvider.tsx
index a6fecd48b12b9..4b56b2e7278ea 100644
--- a/packages/core/client/src/block-provider/FormBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/FormBlockProvider.tsx
@@ -11,13 +11,13 @@ import { createForm } from '@formily/core';
import { Schema, useField } from '@formily/react';
import { Spin } from 'antd';
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
-import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import {
CollectionRecord,
useCollectionManager,
useCollectionParentRecordData,
useCollectionRecord,
} from '../data-source';
+import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { useTreeParentRecord } from '../modules/blocks/data-blocks/table/TreeRecordProvider';
import { RecordProvider } from '../record-provider';
import { useActionContext } from '../schema-component';
diff --git a/packages/core/client/src/block-provider/TableBlockProvider.tsx b/packages/core/client/src/block-provider/TableBlockProvider.tsx
index e5121a2653a2c..86432e8ae0234 100644
--- a/packages/core/client/src/block-provider/TableBlockProvider.tsx
+++ b/packages/core/client/src/block-provider/TableBlockProvider.tsx
@@ -10,8 +10,8 @@
import { createForm } from '@formily/core';
import { FormContext, useField, useFieldSchema } from '@formily/react';
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
-import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../collection-manager';
+import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { useTableBlockParams } from '../modules/blocks/data-blocks/table';
import { FixedBlockWrapper, SchemaComponentOptions } from '../schema-component';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
diff --git a/packages/core/client/src/block-provider/TableSelectorProvider.tsx b/packages/core/client/src/block-provider/TableSelectorProvider.tsx
index 7e6c38930e518..9732575cf1c4c 100644
--- a/packages/core/client/src/block-provider/TableSelectorProvider.tsx
+++ b/packages/core/client/src/block-provider/TableSelectorProvider.tsx
@@ -12,11 +12,11 @@ import { Schema, useField, useFieldSchema } from '@formily/react';
import _ from 'lodash';
import uniq from 'lodash/uniq';
import React, { createContext, useContext, useEffect, useState } from 'react';
-import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../collection-manager';
import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { isInFilterFormBlock } from '../filter-provider';
import { mergeFilter } from '../filter-provider/utils';
+import { withDynamicSchemaProps } from '../hoc/withDynamicSchemaProps';
import { RecordProvider, useRecord } from '../record-provider';
import { SchemaComponentOptions } from '../schema-component';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
diff --git a/packages/core/client/src/block-provider/__tests__/CollectOperators.test.tsx b/packages/core/client/src/block-provider/__tests__/CollectOperators.test.tsx
new file mode 100644
index 0000000000000..a3628fb19b597
--- /dev/null
+++ b/packages/core/client/src/block-provider/__tests__/CollectOperators.test.tsx
@@ -0,0 +1,52 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { render } from '@nocobase/test/client';
+import React from 'react';
+import { CollectOperators, useOperators } from '../CollectOperators';
+
+describe('CollectOperators', () => {
+ it('should collect and get operators correctly', () => {
+ const defaultOperators = {
+ field1: 'operator1',
+ field2: 'operator2',
+ };
+
+ const TestComponent = () => {
+ const { collectOperator, getOperators, getOperator } = useOperators();
+
+ collectOperator('field3', 'operator3');
+
+ const operators = getOperators();
+ const operator = getOperator('field1') as string;
+
+ return (
+
+ {JSON.stringify(operators)}
+ {operator}
+
+ );
+ };
+
+ const { getByTestId } = render(
+
+
+ ,
+ );
+
+ const operatorsElement = getByTestId('operators');
+ const operatorElement = getByTestId('operator');
+
+ expect(JSON.parse(operatorsElement.textContent)).toEqual({
+ ...defaultOperators,
+ field3: 'operator3',
+ });
+ expect(operatorElement.textContent).toBe('operator1');
+ });
+});
diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts
index 4e8c712034fa6..3e4fa92a77308 100644
--- a/packages/core/client/src/block-provider/hooks/index.ts
+++ b/packages/core/client/src/block-provider/hooks/index.ts
@@ -40,6 +40,7 @@ import { useLocalVariables, useVariables } from '../../variables';
import { isVariable } from '../../variables/utils/isVariable';
import { transformVariableValue } from '../../variables/utils/transformVariableValue';
import { useBlockRequestContext, useFilterByTk, useParamsFromRecord } from '../BlockProvider';
+import { useOperators } from '../CollectOperators';
import { useDetailsBlockContext } from '../DetailsBlockProvider';
import { TableFieldResource } from '../TableFieldProvider';
@@ -413,6 +414,7 @@ export const useFilterBlockActionProps = () => {
const { getDataBlocks } = useFilterBlock();
const { name } = useCollection_deprecated();
const { getCollectionJoinField } = useCollectionManager_deprecated();
+ const { getOperators } = useOperators();
actionField.data = actionField.data || {};
@@ -433,7 +435,7 @@ export const useFilterBlockActionProps = () => {
const storedFilter = block.service.params?.[1]?.filters || {};
storedFilter[uid] = removeNullCondition(
- transformToFilter(form.values, fieldSchema, getCollectionJoinField, name),
+ transformToFilter(form.values, getOperators(), getCollectionJoinField, name),
);
const mergedFilter = mergeFilter([
diff --git a/packages/core/client/src/data-source/collection-field/CollectionField.tsx b/packages/core/client/src/data-source/collection-field/CollectionField.tsx
index fe42188f22158..ee8193d86e50a 100644
--- a/packages/core/client/src/data-source/collection-field/CollectionField.tsx
+++ b/packages/core/client/src/data-source/collection-field/CollectionField.tsx
@@ -13,10 +13,10 @@ import { merge } from '@formily/shared';
import { concat } from 'lodash';
import React, { useCallback, useEffect, useMemo } from 'react';
import { useFormBlockContext } from '../../block-provider/FormBlockProvider';
+import { useDynamicComponentProps } from '../../hoc/withDynamicSchemaProps';
import { useCompile, useComponent } from '../../schema-component';
import { useIsAllowToSetDefaultValue } from '../../schema-settings/hooks/useIsAllowToSetDefaultValue';
import { CollectionFieldProvider, useCollectionField } from './CollectionFieldProvider';
-import { useDynamicComponentProps } from '../../application/hoc';
type Props = {
component: any;
diff --git a/packages/core/client/src/data-source/data-block/DataBlockProvider.tsx b/packages/core/client/src/data-source/data-block/DataBlockProvider.tsx
index 3d9735366178e..939c9bf217f2a 100644
--- a/packages/core/client/src/data-source/data-block/DataBlockProvider.tsx
+++ b/packages/core/client/src/data-source/data-block/DataBlockProvider.tsx
@@ -11,7 +11,7 @@ import React, { FC, ReactNode, createContext, useContext, useMemo } from 'react'
import { ACLCollectionProvider } from '../../acl/ACLProvider';
import { UseRequestOptions, UseRequestService } from '../../api-client';
-import { withDynamicSchemaProps } from '../../application/hoc';
+import { withDynamicSchemaProps } from '../../hoc/withDynamicSchemaProps';
import { Designable, useDesignable } from '../../schema-component';
import {
AssociationProvider,
diff --git a/packages/core/client/src/filter-provider/__tests__/transformToFilter.ts b/packages/core/client/src/filter-provider/__tests__/transformToFilter.ts
deleted file mode 100644
index 12d355e72a3d2..0000000000000
--- a/packages/core/client/src/filter-provider/__tests__/transformToFilter.ts
+++ /dev/null
@@ -1,67 +0,0 @@
-/**
- * This file is part of the NocoBase (R) project.
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
- * Authors: NocoBase Team.
- *
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
- * For more information, please refer to: https://www.nocobase.com/agreement.
- */
-
-import { transformToFilter } from '../utils';
-
-// TODO: 前端测试报错解决之后,把该文件重命名为 transformToFilter.test.ts
-describe('transformToFilter', () => {
- it('should transform to filter', () => {
- const values = {
- name: 'name',
- email: 'email',
- user: {
- name: 'name',
- },
- list: [{ name: 'name1' }, { name: 'name2' }, { name: 'name3' }],
- };
-
- const fieldSchema = {
- 'x-filter-operators': {
- name: '$eq',
- email: '$eq',
- },
- };
-
- const getField = (name: string) => {
- if (name === 'user' || name === 'list') {
- return {
- targetKey: 'name',
- };
- }
- return {
- targetKey: undefined,
- };
- };
-
- expect(transformToFilter(values, fieldSchema as any, getField)).toEqual({
- $and: [
- {
- name: {
- $eq: 'name',
- },
- },
- {
- email: {
- $eq: 'email',
- },
- },
- {
- 'user.name': {
- $eq: 'name',
- },
- },
- {
- 'list.name': {
- $eq: ['name1', 'name2', 'name3'],
- },
- },
- ],
- });
- });
-});
diff --git a/packages/core/client/src/filter-provider/__tests__/useFilter.tsx b/packages/core/client/src/filter-provider/__tests__/useFilter.tsx
deleted file mode 100644
index a1a25d9b9da1a..0000000000000
--- a/packages/core/client/src/filter-provider/__tests__/useFilter.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * This file is part of the NocoBase (R) project.
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
- * Authors: NocoBase Team.
- *
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
- * For more information, please refer to: https://www.nocobase.com/agreement.
- */
-
-import { render } from '@testing-library/react';
-import React from 'react';
-import { FilterBlockProvider, useFilterBlock } from '../FilterProvider';
-
-describe('useFilter', () => {
- test('should get a empty array', () => {
- let getDataBlocks = null;
- const Comp = () => {
- ({ getDataBlocks } = useFilterBlock());
- return null;
- };
- const App = () => {
- return (
-
-
-
- );
- };
- render();
- expect(getDataBlocks()).toEqual([]);
- });
-
- test('should not repeat', () => {
- let getDataBlocks = null,
- recordDataBlocks = null;
- const Comp = () => {
- ({ getDataBlocks, recordDataBlocks } = useFilterBlock());
- return null;
- };
- const App = () => {
- return (
-
-
-
- );
- };
- render();
-
- recordDataBlocks({
- name: 'test',
- collection: {},
- doFilter: () => {},
- });
- expect(getDataBlocks().length).toBe(1);
-
- // avoid repeat
- recordDataBlocks({
- name: 'test',
- collection: {},
- doFilter: () => {},
- });
- expect(getDataBlocks().length).toBe(1);
- });
-});
diff --git a/packages/core/client/src/filter-provider/utils.ts b/packages/core/client/src/filter-provider/utils.ts
index 397f3996edb8d..74f068a8e5186 100644
--- a/packages/core/client/src/filter-provider/utils.ts
+++ b/packages/core/client/src/filter-provider/utils.ts
@@ -13,14 +13,13 @@ import _ from 'lodash';
import { useCallback, useEffect, useState } from 'react';
import { FilterTarget, findFilterTargets } from '../block-provider/hooks';
import {
- Collection_deprecated,
CollectionFieldOptions_deprecated,
+ Collection_deprecated,
FieldOptions,
- useCollection_deprecated,
useCollectionManager_deprecated,
+ useCollection_deprecated,
} from '../collection-manager';
import { removeNullCondition } from '../schema-component';
-import { findFilterOperators } from '../schema-component/antd/form-item/SchemaSettingOptions';
import { DataBlock, useFilterBlock } from './FilterProvider';
export enum FilterBlockType {
@@ -99,12 +98,10 @@ export const useSupportedBlocks = (filterBlockType: FilterBlockType) => {
export const transformToFilter = (
values: Record,
- fieldSchema: Schema,
+ operators: Record,
getCollectionJoinField: (name: string) => CollectionFieldOptions_deprecated,
collectionName: string,
) => {
- const { operators } = findFilterOperators(fieldSchema);
-
values = flatten(values, {
breakOn({ value, path }) {
// 下面操作符的值是一个数组,需要特殊处理
diff --git a/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx b/packages/core/client/src/hoc/withDynamicSchemaProps.tsx
similarity index 98%
rename from packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx
rename to packages/core/client/src/hoc/withDynamicSchemaProps.tsx
index 635a3e9de9916..2bd0782dbc8c2 100644
--- a/packages/core/client/src/application/hoc/withDynamicSchemaProps.tsx
+++ b/packages/core/client/src/hoc/withDynamicSchemaProps.tsx
@@ -8,9 +8,9 @@
*/
import { useExpressionScope } from '@formily/react';
-import React, { ComponentType, useMemo } from 'react';
-import { useDesignable } from '../../schema-component';
import _ from 'lodash';
+import React, { ComponentType, useMemo } from 'react';
+import { useDesignable } from '../schema-component';
const useDefaultDynamicComponentProps = () => undefined;
diff --git a/packages/core/client/src/index.ts b/packages/core/client/src/index.ts
index b3c6b0c6682da..84e299b89fa09 100644
--- a/packages/core/client/src/index.ts
+++ b/packages/core/client/src/index.ts
@@ -60,13 +60,13 @@ export * from './testUtils';
export * from './user';
export * from './variables';
-export { withDynamicSchemaProps } from './application/hoc/withDynamicSchemaProps';
+export { withDynamicSchemaProps } from './hoc/withDynamicSchemaProps';
export * from './modules/blocks/BlockSchemaToolbar';
export * from './modules/blocks/data-blocks/form';
export * from './modules/blocks/data-blocks/table';
export * from './modules/blocks/data-blocks/table-selector';
-export * from './modules/blocks/useParentRecordCommon';
export * from './modules/blocks/index';
+export * from './modules/blocks/useParentRecordCommon';
export { DeclareVariable } from './modules/variable/DeclareVariable';
diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-multi/detailsWithPaginationSettings.tsx b/packages/core/client/src/modules/blocks/data-blocks/details-multi/detailsWithPaginationSettings.tsx
index 42b99ceed764b..85d77798dd784 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/details-multi/detailsWithPaginationSettings.tsx
+++ b/packages/core/client/src/modules/blocks/data-blocks/details-multi/detailsWithPaginationSettings.tsx
@@ -16,12 +16,10 @@ import { useFormBlockContext } from '../../../../block-provider';
import { useDetailsBlockContext } from '../../../../block-provider/DetailsBlockProvider';
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
import { removeNullCondition, useDesignable } from '../../../../schema-component';
-import {
- SchemaSettingsBlockTitleItem,
- SchemaSettingsTemplate,
- SchemaSettingsLinkageRules,
-} from '../../../../schema-settings';
+import { SchemaSettingsLinkageRules } from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../../schema-settings/SchemaSettingsTemplate';
import { setDataLoadingModeSettingsItem } from './setDataLoadingModeSettingsItem';
const commonItems: SchemaSettingsItemType[] = [
diff --git a/packages/core/client/src/modules/blocks/data-blocks/details-single/detailsBlockSettings.ts b/packages/core/client/src/modules/blocks/data-blocks/details-single/detailsBlockSettings.ts
index 42974fba615c2..61dbaf54e041a 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/details-single/detailsBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/details-single/detailsBlockSettings.ts
@@ -9,13 +9,10 @@
import { useFieldSchema } from '@formily/react';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
-import { useCollection_deprecated } from '../../../../collection-manager';
-import {
- SchemaSettingsBlockTitleItem,
- SchemaSettingsFormItemTemplate,
- SchemaSettingsLinkageRules,
-} from '../../../../schema-settings';
import { SchemaSettingsItemType } from '../../../../application/schema-settings/types';
+import { useCollection_deprecated } from '../../../../collection-manager';
+import { SchemaSettingsFormItemTemplate, SchemaSettingsLinkageRules } from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
const commonItems: SchemaSettingsItemType[] = [
{
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__tests__/fieldSettingsFormItem.test.tsx b/packages/core/client/src/modules/blocks/data-blocks/form/__tests__/fieldSettingsFormItem.test.tsx
index 11fb3eadc8949..40d86440fa603 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__tests__/fieldSettingsFormItem.test.tsx
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__tests__/fieldSettingsFormItem.test.tsx
@@ -7,20 +7,19 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import { useFieldSchema } from '@formily/react';
+import { observer } from '@formily/reactive-react';
+import { FilterFormBlockProvider, FormBlockProvider, FormItem, fieldSettingsFormItem } from '@nocobase/client';
import {
- screen,
+ checkFieldTitle,
checkSettings,
+ renderReadPrettySettings,
+ renderSettings,
renderSingleSettings,
- waitFor,
+ screen,
userEvent,
- renderReadPrettySingleSettings,
- renderSettings,
- renderReadPrettySettings,
- checkFieldTitle,
+ waitFor,
} from '@nocobase/test/client';
-import { FilterFormBlockProvider, FormBlockProvider, FormItem, fieldSettingsFormItem } from '@nocobase/client';
-import { useFieldSchema } from '@formily/react';
-import { observer } from '@formily/reactive-react';
import React from 'react';
describe('FieldSettingsFormItem', () => {
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/createFormBlockSettings.tsx b/packages/core/client/src/modules/blocks/data-blocks/form/createFormBlockSettings.tsx
index 27534d7601bfe..9a2b3b9cefaa6 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/createFormBlockSettings.tsx
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/createFormBlockSettings.tsx
@@ -12,11 +12,11 @@ import { SchemaSettings } from '../../../../application/schema-settings/SchemaSe
import { useFormBlockContext } from '../../../../block-provider';
import { useCollection_deprecated } from '../../../../collection-manager';
import {
- SchemaSettingsBlockTitleItem,
SchemaSettingsDataTemplates,
SchemaSettingsFormItemTemplate,
SchemaSettingsLinkageRules,
} from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
export const createFormBlockSettings = new SchemaSettings({
name: 'blockSettings:createForm',
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/editFormBlockSettings.ts b/packages/core/client/src/modules/blocks/data-blocks/form/editFormBlockSettings.ts
index 81c23db1faf1e..0b6e027e8cac9 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/editFormBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/editFormBlockSettings.ts
@@ -12,11 +12,11 @@ import { SchemaSettings } from '../../../../application/schema-settings/SchemaSe
import { useFormBlockContext } from '../../../../block-provider';
import { useCollection_deprecated } from '../../../../collection-manager';
import {
- SchemaSettingsBlockTitleItem,
SchemaSettingsDataTemplates,
SchemaSettingsFormItemTemplate,
SchemaSettingsLinkageRules,
} from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
export const editFormBlockSettings = new SchemaSettings({
name: 'blockSettings:editForm',
diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/gridCardBlockSettings.ts b/packages/core/client/src/modules/blocks/data-blocks/grid-card/gridCardBlockSettings.ts
index 3fed6d27adb9a..6b138b5b2976e 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/gridCardBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/gridCardBlockSettings.ts
@@ -17,8 +17,8 @@ import { useFormBlockContext } from '../../../../block-provider';
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
import { removeNullCondition, useDesignable } from '../../../../schema-component';
import { pageSizeOptions } from '../../../../schema-component/antd/grid-card/options';
-import { SchemaSettingsTemplate } from '../../../../schema-settings';
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../../schema-settings/SchemaSettingsTemplate';
import { setDataLoadingModeSettingsItem } from '../details-multi/setDataLoadingModeSettingsItem';
import { SetTheCountOfColumnsDisplayedInARow } from './SetTheCountOfColumnsDisplayedInARow';
diff --git a/packages/core/client/src/modules/blocks/data-blocks/list/listBlockSettings.ts b/packages/core/client/src/modules/blocks/data-blocks/list/listBlockSettings.ts
index fdc1bac618d58..2827b94f7a696 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/list/listBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/list/listBlockSettings.ts
@@ -15,8 +15,9 @@ import { SchemaSettings } from '../../../../application/schema-settings/SchemaSe
import { useFormBlockContext } from '../../../../block-provider';
import { useCollection_deprecated, useSortFields } from '../../../../collection-manager';
import { removeNullCondition, useDesignable } from '../../../../schema-component';
-import { SchemaSettingsBlockTitleItem, SchemaSettingsTemplate } from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../../schema-settings/SchemaSettingsTemplate';
import { setDataLoadingModeSettingsItem } from '../details-multi/setDataLoadingModeSettingsItem';
export const listBlockSettings = new SchemaSettings({
diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/tableBlockSettings.tsx b/packages/core/client/src/modules/blocks/data-blocks/table/tableBlockSettings.tsx
index ec8ee6d3d6743..9ed8c93bc87b7 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/table/tableBlockSettings.tsx
+++ b/packages/core/client/src/modules/blocks/data-blocks/table/tableBlockSettings.tsx
@@ -7,29 +7,27 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
+import { ArrayItems } from '@formily/antd-v5';
import { ISchema } from '@formily/json-schema';
import { useField, useFieldSchema } from '@formily/react';
+import { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
import { useAPIClient } from '../../../../api-client';
-import { useTableBlockContext, useFormBlockContext } from '../../../../block-provider';
+import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
+import { useFormBlockContext, useTableBlockContext } from '../../../../block-provider';
import {
useCollectionManager_deprecated,
useCollection_deprecated,
useSortFields,
} from '../../../../collection-manager';
import { FilterBlockType } from '../../../../filter-provider/utils';
-import { useDesignable, removeNullCondition } from '../../../../schema-component';
-import {
- SchemaSettingsBlockTitleItem,
- SchemaSettingsSortField,
- SchemaSettingsConnectDataBlocks,
- SchemaSettingsTemplate,
-} from '../../../../schema-settings/SchemaSettings';
-import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
-import { useCallback } from 'react';
-import { useTranslation } from 'react-i18next';
-import { ArrayItems } from '@formily/antd-v5';
+import { removeNullCondition, useDesignable } from '../../../../schema-component';
import { FixedBlockDesignerItem } from '../../../../schema-component/antd/page/FixedBlockDesignerItem';
-import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsConnectDataBlocks } from '../../../../schema-settings/SchemaSettingsConnectDataBlocks';
+import { SchemaSettingsDataScope } from '../../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsSortField } from '../../../../schema-settings/SchemaSettingsSortField';
+import { SchemaSettingsTemplate } from '../../../../schema-settings/SchemaSettingsTemplate';
import { setDataLoadingModeSettingsItem } from '../details-multi/setDataLoadingModeSettingsItem';
export const tableBlockSettings = new SchemaSettings({
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/collapse/filterCollapseBlockSettings.ts b/packages/core/client/src/modules/blocks/filter-blocks/collapse/filterCollapseBlockSettings.ts
index eeeb817dcf414..cd0aefa7578a9 100644
--- a/packages/core/client/src/modules/blocks/filter-blocks/collapse/filterCollapseBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/collapse/filterCollapseBlockSettings.ts
@@ -12,11 +12,9 @@ import { useTranslation } from 'react-i18next';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated } from '../../../../collection-manager';
import { FilterBlockType } from '../../../../filter-provider';
-import {
- SchemaSettingsBlockTitleItem,
- SchemaSettingsConnectDataBlocks,
- SchemaSettingsTemplate,
-} from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsConnectDataBlocks } from '../../../../schema-settings/SchemaSettingsConnectDataBlocks';
+import { SchemaSettingsTemplate } from '../../../../schema-settings/SchemaSettingsTemplate';
export const filterCollapseBlockSettings = new SchemaSettings({
name: 'blockSettings:filterCollapse',
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaSettings.test.ts
index 06b5a39e530f9..1ec219beb86f9 100644
--- a/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaSettings.test.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/__e2e__/schemaSettings.test.ts
@@ -36,7 +36,12 @@ test.describe('filter block schema settings', () => {
});
test.describe('connect data blocks', () => {
- test('connecting two blocks of the same collection', async ({ page, mockPage, mockRecords }) => {
+ test('connecting two blocks of the same collection', async ({
+ page,
+ mockPage,
+ mockRecords,
+ clearBlockTemplates,
+ }) => {
const nocoPage = await mockPage(oneFormAndOneTableWithSameCollection).waitForInit();
const records = await mockRecords('general', 3);
await nocoPage.goto();
@@ -81,6 +86,81 @@ test.describe('filter block schema settings', () => {
await expect(
page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[0].singleLineText }),
).toBeVisible();
+
+ // 更改操作符为 “is not”
+ await page.getByLabel('block-item-CollectionField-').hover();
+ await page.getByLabel('designer-schema-settings-CollectionField-FormItem.FilterFormDesigner-general-').hover();
+ await page.getByRole('menuitem', { name: 'Operator contains' }).click();
+ await page.getByRole('option', { name: 'is not', exact: true }).click();
+
+ // 输入值,点击筛选按钮
+ await page
+ .getByLabel('block-item-CollectionField-general-filter-form-general.singleLineText-singleLineText')
+ .getByRole('textbox')
+ .click();
+ await page
+ .getByLabel('block-item-CollectionField-general-filter-form-general.singleLineText-singleLineText')
+ .getByRole('textbox')
+ .fill(records[0].singleLineText);
+
+ // 点击筛选按钮
+ await page.getByLabel('action-Action-Filter records-submit-general-filter-form').click();
+
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[1].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[2].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[0].singleLineText }),
+ ).toBeHidden();
+
+ // 点击重置按钮
+ await page.getByLabel('action-Action-Reset records-general-filter-form').click();
+
+ // 将筛选表单区块保存为模板
+ await page.getByLabel('block-item-CardItem-general-filter-form').hover();
+ await page.getByLabel('designer-schema-settings-CardItem-FormV2.FilterDesigner-general').hover();
+ await page.getByRole('menuitem', { name: 'Save as block template' }).click();
+ await page.getByRole('button', { name: 'OK', exact: true }).click();
+
+ // 输入值,点击筛选按钮
+ await page
+ .getByLabel('block-item-CollectionField-general-filter-form-general.singleLineText-singleLineText')
+ .getByRole('textbox')
+ .click();
+ await page
+ .getByLabel('block-item-CollectionField-general-filter-form-general.singleLineText-singleLineText')
+ .getByRole('textbox')
+ .fill(records[0].singleLineText);
+
+ // 点击筛选按钮
+ await page.getByLabel('action-Action-Filter records-submit-general-filter-form').click();
+
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[1].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[2].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[0].singleLineText }),
+ ).toBeHidden();
+
+ // 点击重置按钮
+ await page.getByLabel('action-Action-Reset records-general-filter-form').click();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[1].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[2].singleLineText }),
+ ).toBeVisible();
+ await expect(
+ page.getByLabel('block-item-CardItem-general-table').getByRole('row', { name: records[0].singleLineText }),
+ ).toBeVisible();
+
+ await clearBlockTemplates();
});
});
});
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/__tests__/createFilterFormBlockSchema.test.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/__tests__/createFilterFormBlockSchema.test.ts
index dafcb383b7894..2b6ee20b5cea0 100644
--- a/packages/core/client/src/modules/blocks/filter-blocks/form/__tests__/createFilterFormBlockSchema.test.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/__tests__/createFilterFormBlockSchema.test.ts
@@ -55,7 +55,6 @@ describe('createFilterFormBlockSchema', () => {
"collection": "myCollection",
"dataSource": "myDataSource",
},
- "x-filter-operators": {},
"x-filter-targets": [],
"x-settings": "blockSettings:filterForm",
"x-toolbar": "BlockSchemaToolbar",
@@ -104,7 +103,6 @@ describe('createFilterFormBlockSchema', () => {
"collection": "myCollection",
"dataSource": "myDataSource",
},
- "x-filter-operators": {},
"x-filter-targets": [],
"x-settings": "blockSettings:filterForm",
"x-toolbar": "BlockSchemaToolbar",
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/createFilterFormBlockSchema.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/createFilterFormBlockSchema.ts
index 16924f5c20a87..4f67888d8387f 100644
--- a/packages/core/client/src/modules/blocks/filter-blocks/form/createFilterFormBlockSchema.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/createFilterFormBlockSchema.ts
@@ -34,8 +34,6 @@ export const createFilterFormBlockSchema = (options: {
'x-component': 'CardItem',
// 保存当前筛选区块所能过滤的数据区块
'x-filter-targets': [],
- // 用于存储用户设置的每个字段的运算符,目前仅筛选表单区块支持自定义
- 'x-filter-operators': {},
properties: {
[uid()]: {
type: 'void',
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormBlockSettings.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormBlockSettings.ts
index 9bda08eef0e91..68a8ed16f215f 100644
--- a/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormBlockSettings.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/filterFormBlockSettings.ts
@@ -12,12 +12,9 @@ import { useTranslation } from 'react-i18next';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useCollection_deprecated } from '../../../../collection-manager';
import { FilterBlockType } from '../../../../filter-provider';
-import {
- SchemaSettingsBlockTitleItem,
- SchemaSettingsConnectDataBlocks,
- SchemaSettingsFormItemTemplate,
- SchemaSettingsLinkageRules,
-} from '../../../../schema-settings';
+import { SchemaSettingsFormItemTemplate, SchemaSettingsLinkageRules } from '../../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsConnectDataBlocks } from '../../../../schema-settings/SchemaSettingsConnectDataBlocks';
export const filterFormBlockSettings = new SchemaSettings({
name: 'blockSettings:filterForm',
diff --git a/packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useCollectOperator.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useCollectOperator.ts
new file mode 100644
index 0000000000000..d38afd1787b18
--- /dev/null
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useCollectOperator.ts
@@ -0,0 +1,30 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { useFieldSchema } from '@formily/react';
+import { useEffect } from 'react';
+import { useOperators } from '../../../../../block-provider/CollectOperators';
+
+/**
+ * 用于将筛选表单中的字段操作符收集到一起
+ */
+export const useCollectOperator = () => {
+ const fieldSchema = useFieldSchema();
+ const { collectOperator, removeOperator } = useOperators();
+
+ useEffect(() => {
+ return () => {
+ removeOperator(fieldSchema.name);
+ };
+ }, [fieldSchema.name, removeOperator]);
+
+ if (fieldSchema['x-filter-operator']) {
+ collectOperator(fieldSchema.name, fieldSchema['x-filter-operator']);
+ }
+};
diff --git a/packages/core/client/src/application/hoc/index.ts b/packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useFormItemProps.ts
similarity index 69%
rename from packages/core/client/src/application/hoc/index.ts
rename to packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useFormItemProps.ts
index 7e0130d3cf645..eeaf65737835f 100644
--- a/packages/core/client/src/application/hoc/index.ts
+++ b/packages/core/client/src/modules/blocks/filter-blocks/form/hooks/useFormItemProps.ts
@@ -7,4 +7,8 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-export * from './withDynamicSchemaProps';
+import { useCollectOperator } from './useCollectOperator';
+
+export const useFormItemProps = () => {
+ useCollectOperator();
+};
diff --git a/packages/core/client/src/schema-component/antd/action/Action.Link.tsx b/packages/core/client/src/schema-component/antd/action/Action.Link.tsx
index 19178d1a5edc2..6c677828767a5 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.Link.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.Link.tsx
@@ -8,11 +8,11 @@
*/
import { observer } from '@formily/react';
-import React from 'react';
import classnames from 'classnames';
+import React from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import Action from './Action';
import { ComposedAction } from './types';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
export const ActionLink: ComposedAction = withDynamicSchemaProps(
observer((props: any) => {
diff --git a/packages/core/client/src/schema-component/antd/action/Action.tsx b/packages/core/client/src/schema-component/antd/action/Action.tsx
index 9d5ddc1814e70..c6c01278343bd 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.tsx
@@ -17,13 +17,13 @@ import { useTranslation } from 'react-i18next';
import { StablePopover, useActionContext } from '../..';
import { useDesignable } from '../../';
import { useACLActionParamsContext } from '../../../acl';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import {
useCollection,
useCollectionParentRecordData,
useCollectionRecordData,
useDataBlockRequest,
} from '../../../data-source';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { Icon } from '../../../icon';
import { TreeRecordProvider } from '../../../modules/blocks/data-blocks/table/TreeRecordProvider';
import { DeclareVariable } from '../../../modules/variable/DeclareVariable';
diff --git a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
index bf06ff2ba41a0..398b2ea43e750 100644
--- a/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
+++ b/packages/core/client/src/schema-component/antd/action/ActionBar.tsx
@@ -12,10 +12,10 @@ import { RecursionField, observer, useFieldSchema } from '@formily/react';
import { Space, SpaceProps } from 'antd';
import React, { CSSProperties, useContext } from 'react';
import { createPortal } from 'react-dom';
+import { useSchemaInitializerRender } from '../../../application';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { DndContext } from '../../common';
import { useDesignable, useProps } from '../../hooks';
-import { useSchemaInitializerRender } from '../../../application';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
export interface ActionBarProps {
layout?: 'one-column' | 'two-columns';
diff --git a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.BlockDesigner.tsx b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.BlockDesigner.tsx
index e19ba0011e22f..95df01c582890 100644
--- a/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.BlockDesigner.tsx
+++ b/packages/core/client/src/schema-component/antd/association-filter/AssociationFilter.BlockDesigner.tsx
@@ -12,14 +12,10 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { useCollection_deprecated } from '../../../collection-manager';
import { FilterBlockType } from '../../../filter-provider/utils';
-import {
- GeneralSchemaDesigner,
- SchemaSettingsBlockTitleItem,
- SchemaSettingsConnectDataBlocks,
- SchemaSettingsDivider,
- SchemaSettingsRemove,
- SchemaSettingsTemplate,
-} from '../../../schema-settings';
+import { GeneralSchemaDesigner, SchemaSettingsDivider, SchemaSettingsRemove } from '../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsConnectDataBlocks } from '../../../schema-settings/SchemaSettingsConnectDataBlocks';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
export const AssociationFilterBlockDesigner = () => {
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 6d6e816a7225d..4f2cb7a96b38b 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
@@ -12,6 +12,7 @@ import { useFieldSchema } from '@formily/react';
import { Col, Collapse, Input, Row, Tree } from 'antd';
import cls from 'classnames';
import React, { ChangeEvent, MouseEvent, useMemo, useState } from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { SortableItem } from '../../common';
import { useCompile, useDesigner, useProps } from '../../hooks';
import { useToken } from '../__builtins__';
@@ -19,7 +20,6 @@ import { EllipsisWithTooltip } from '../input';
import { getLabelFormatValue, useLabelUiSchema } from '../record-picker';
import { AssociationFilter } from './AssociationFilter';
import useStyles from './AssociationFilter.Item.style';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const { Panel } = Collapse;
diff --git a/packages/core/client/src/schema-component/antd/auto-complete/AutoComplete.tsx b/packages/core/client/src/schema-component/antd/auto-complete/AutoComplete.tsx
index f3737ae320cbd..59c18f580ba1f 100644
--- a/packages/core/client/src/schema-component/antd/auto-complete/AutoComplete.tsx
+++ b/packages/core/client/src/schema-component/antd/auto-complete/AutoComplete.tsx
@@ -9,8 +9,8 @@
import { connect, mapProps, mapReadPretty } from '@formily/react';
import { AutoComplete as AntdAutoComplete } from 'antd';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { ReadPretty } from '../input';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
export const AutoComplete = withDynamicSchemaProps(
connect(
diff --git a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
index 5c4c67b6e9452..acc5c305494e7 100644
--- a/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
+++ b/packages/core/client/src/schema-component/antd/block-item/BlockItem.tsx
@@ -10,7 +10,7 @@
import { useFieldSchema } from '@formily/react';
import cls from 'classnames';
import React, { useMemo } from 'react';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { CustomCreateStylesUtils, createStyles } from '../../../style';
import { SortableItem } from '../../common';
import { useDesigner, useProps } from '../../hooks';
diff --git a/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx b/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx
index 1af46216090e5..3de48cff1bd5e 100644
--- a/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx
+++ b/packages/core/client/src/schema-component/antd/cascader/Cascader.tsx
@@ -11,14 +11,14 @@ import { LoadingOutlined } from '@ant-design/icons';
import { ArrayField } from '@formily/core';
import { connect, mapProps, mapReadPretty, useField } from '@formily/react';
import { toArr } from '@formily/shared';
-import { Cascader as AntdCascader, Space, CascaderProps as AntdCascaderProps } from 'antd';
+import { Cascader as AntdCascader, CascaderProps as AntdCascaderProps, Space } from 'antd';
+import { BaseOptionType } from 'antd/es/select';
import { isBoolean, omit } from 'lodash';
import React from 'react';
import { UseRequestResult, useRequest } from '../../../api-client';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { ReadPretty } from './ReadPretty';
import { defaultFieldNames } from './defaultFieldNames';
-import { BaseOptionType } from 'antd/es/select';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const useDefDataSource = (options, props: any) => {
const field = useField();
diff --git a/packages/core/client/src/schema-component/antd/details/Details.tsx b/packages/core/client/src/schema-component/antd/details/Details.tsx
index aa607e3788222..13e09f5d29a49 100644
--- a/packages/core/client/src/schema-component/antd/details/Details.tsx
+++ b/packages/core/client/src/schema-component/antd/details/Details.tsx
@@ -7,12 +7,12 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
-import React from 'react';
-import { FormV2 } from '../form-v2';
-import _ from 'lodash';
import { Empty } from 'antd';
+import _ from 'lodash';
+import React from 'react';
import { useDataBlockRequest } from '../../../data-source';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
+import { FormV2 } from '../form-v2';
import { FormProps } from '../form-v2/Form';
export type DetailsProps = FormProps;
diff --git a/packages/core/client/src/schema-component/antd/filter/Filter.tsx b/packages/core/client/src/schema-component/antd/filter/Filter.tsx
index f754a96b8724f..89d6900348f43 100644
--- a/packages/core/client/src/schema-component/antd/filter/Filter.tsx
+++ b/packages/core/client/src/schema-component/antd/filter/Filter.tsx
@@ -11,13 +11,13 @@ import { ObjectField as ObjectFieldModel } from '@formily/core';
import { observer, useField, useFieldSchema } from '@formily/react';
import React, { useEffect } from 'react';
import { UseRequestOptions, useRequest } from '../../../api-client';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useProps } from '../../hooks/useProps';
import { FilterActionDesigner } from './Filter.Action.Designer';
import { FilterAction } from './FilterAction';
import { FilterGroup } from './FilterGroup';
import { SaveDefaultValue } from './SaveDefaultValue';
import { FilterContext, FilterContextProps } from './context';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const useDef = (options: UseRequestOptions) => {
const field = useField();
diff --git a/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx b/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx
index 418f11cd7ae65..487978f518d05 100644
--- a/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx
+++ b/packages/core/client/src/schema-component/antd/filter/FilterAction.tsx
@@ -14,12 +14,12 @@ import { flatten, unflatten } from '@nocobase/utils/client';
import { Button, Space } from 'antd';
import React, { createContext, useCallback, useContext, useMemo, useState } from 'react';
import { useTranslation } from 'react-i18next';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { FormProvider, SchemaComponent } from '../../core';
import { useDesignable } from '../../hooks';
import { useProps } from '../../hooks/useProps';
import { Action, ActionProps } from '../action';
import { StablePopover } from '../popover';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
export const FilterActionContext = createContext(null);
FilterActionContext.displayName = 'FilterActionContext';
diff --git a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx
index c72ad4563fef7..c4055e3221e55 100644
--- a/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx
+++ b/packages/core/client/src/schema-component/antd/form-item/FormItem.tsx
@@ -11,12 +11,13 @@ import { css, cx } from '@emotion/css';
import { IFormItemProps, FormItem as Item } from '@formily/antd-v5';
import { Field } from '@formily/core';
import { observer, useField, useFieldSchema } from '@formily/react';
-import React, { FC, useEffect, useMemo } from 'react';
+import React, { useEffect, useMemo } from 'react';
import { ACLCollectionFieldProvider } from '../../../acl/ACLProvider';
import { useApp } from '../../../application';
import { useFormActiveFields } from '../../../block-provider/hooks/useFormActiveFields';
import { Collection_deprecated } from '../../../collection-manager';
import { CollectionFieldProvider } from '../../../data-source/collection-field/CollectionFieldProvider';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { GeneralSchemaDesigner } from '../../../schema-settings';
import { useVariables } from '../../../variables';
import useContextVariable from '../../../variables/hooks/useContextVariable';
@@ -41,8 +42,8 @@ const formItemLabelCss = css`
}
`;
-export const FormItem: any = observer(
- (props: IFormItemProps) => {
+export const FormItem: any = withDynamicSchemaProps(
+ observer((props: IFormItemProps) => {
useEnsureOperatorsValid();
const field = useField();
const schema = useFieldSchema();
@@ -89,7 +90,7 @@ export const FormItem: any = observer(
);
- },
+ }),
{ displayName: 'FormItem' },
);
diff --git a/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx b/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx
index bc5a8999a5dee..a601e052247ca 100644
--- a/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx
+++ b/packages/core/client/src/schema-component/antd/form-item/SchemaSettingOptions.tsx
@@ -9,40 +9,18 @@
import { ArrayCollapse, FormLayout } from '@formily/antd-v5';
import { Field } from '@formily/core';
-import { ISchema, Schema, useField, useFieldSchema } from '@formily/react';
-import { uid } from '@formily/shared';
+import { ISchema, useField, useFieldSchema } from '@formily/react';
import _ from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useFormBlockContext } from '../../../block-provider';
-import { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
+import { useOperators } from '../../../block-provider/CollectOperators';
+import { useCollectionManager_deprecated, useCollection_deprecated } from '../../../collection-manager';
import { SchemaSettingsModalItem, SchemaSettingsSelectItem, SchemaSettingsSwitchItem } from '../../../schema-settings';
import { isPatternDisabled } from '../../../schema-settings/isPatternDisabled';
import { useCompile, useDesignable, useFieldModeOptions } from '../../hooks';
import { useOperatorList } from '../filter/useOperators';
import { isFileCollection } from './FormItem';
-export const findFilterOperators = (schema: Schema) => {
- while (schema) {
- if (schema['x-filter-operators']) {
- return {
- operators: schema['x-filter-operators'],
- uid: schema['x-uid'],
- };
- }
- schema = schema.parent;
- }
- return {};
-};
-
-const divWrap = (schema: ISchema) => {
- return {
- type: 'void',
- 'x-component': 'div',
- properties: {
- [schema.name || uid()]: schema,
- },
- };
-};
export const EditTitle = () => {
const { getCollectionJoinField } = useCollectionManager_deprecated();
@@ -496,10 +474,11 @@ export const EditPattern = () => {
export const useEnsureOperatorsValid = () => {
const fieldSchema = useFieldSchema();
const operatorList = useOperatorList();
- const { operators: storedOperators } = findFilterOperators(fieldSchema);
+ const { getOperators, collectOperator } = useOperators();
+ const storedOperators = getOperators();
if (storedOperators && operatorList.length && !storedOperators[fieldSchema.name]) {
- storedOperators[fieldSchema.name] = operatorList[0].value;
+ collectOperator(fieldSchema.name, operatorList[0].value);
}
};
@@ -510,61 +489,51 @@ export const EditOperator = () => {
const { t } = useTranslation();
const { dn } = useDesignable();
const operatorList = useOperatorList();
- const { operators: storedOperators = {}, uid } = findFilterOperators(fieldSchema);
+ const { getOperator, collectOperator } = useOperators();
- if (operatorList.length && !storedOperators[fieldSchema.name]) {
- storedOperators[fieldSchema.name] = operatorList[0].value;
+ if (operatorList.length && !getOperator(fieldSchema.name)) {
+ collectOperator(fieldSchema.name, operatorList[0].value);
}
return operatorList.length ? (
{
- storedOperators[fieldSchema.name] = v;
+ collectOperator(fieldSchema.name as string, v);
+ _.set(fieldSchema, 'x-filter-operator', v);
+
const operator = operatorList.find((item) => item.value === v);
- const schema: ISchema = {
- ['x-uid']: uid,
- ['x-filter-operators']: storedOperators,
- };
let componentProps = {};
// 根据操作符的配置,设置组件的属性
if (operator?.schema?.['x-component']) {
- _.set(fieldSchema, 'x-component-props.component', operator.schema['x-component']);
- _.set(field, 'componentProps.component', operator.schema['x-component']);
+ _.set(fieldSchema, 'x-component-props.component', operator.schema?.['x-component']);
+ _.set(field, 'componentProps.component', operator.schema?.['x-component']);
field.reset();
componentProps = {
component: operator.schema['x-component'],
- ...operator.schema['x-component-props'],
+ ...operator.schema?.['x-component-props'],
};
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- ['x-component-props']: componentProps,
- },
- });
} else if (fieldSchema['x-component-props']?.component) {
_.set(fieldSchema, 'x-component-props.component', null);
_.set(field, 'componentProps.component', null);
field.reset();
componentProps = {
component: null,
- ...operator.schema['x-component-props'],
+ ...operator.schema?.['x-component-props'],
};
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- ['x-component-props']: componentProps,
- },
- });
}
field.componentProps = componentProps;
dn.emit('patch', {
- schema,
+ schema: {
+ ['x-uid']: fieldSchema['x-uid'],
+ ['x-component-props']: componentProps,
+ ['x-filter-operator']: v,
+ },
});
dn.refresh();
}}
diff --git a/packages/core/client/src/schema-component/antd/form-v2/Form.Settings.tsx b/packages/core/client/src/schema-component/antd/form-v2/Form.Settings.tsx
index de1feb931d378..1ed14c659f164 100644
--- a/packages/core/client/src/schema-component/antd/form-v2/Form.Settings.tsx
+++ b/packages/core/client/src/schema-component/antd/form-v2/Form.Settings.tsx
@@ -15,17 +15,17 @@ import { useFormBlockContext } from '../../../block-provider';
import { useDetailsBlockContext } from '../../../block-provider/DetailsBlockProvider';
import { useCollection_deprecated } from '../../../collection-manager';
import { useSortFields } from '../../../collection-manager/action-hooks';
+import { setDataLoadingModeSettingsItem } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
import {
- SchemaSettingsBlockTitleItem,
SchemaSettingsDataTemplates,
SchemaSettingsFormItemTemplate,
SchemaSettingsLinkageRules,
- SchemaSettingsTemplate,
} from '../../../schema-settings/SchemaSettings';
+import { SchemaSettingsBlockTitleItem } from '../../../schema-settings/SchemaSettingsBlockTitleItem';
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useDesignable } from '../../hooks';
import { removeNullCondition } from '../filter';
-import { setDataLoadingModeSettingsItem } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
/**
* @deprecated
diff --git a/packages/core/client/src/schema-component/antd/form-v2/Form.tsx b/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
index ba19d2823e151..4c0052edf69bf 100644
--- a/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
+++ b/packages/core/client/src/schema-component/antd/form-v2/Form.tsx
@@ -18,8 +18,8 @@ import { ConfigProvider, Spin } from 'antd';
import React, { useEffect, useMemo } from 'react';
import { useActionContext } from '..';
import { useAttach, useComponent } from '../..';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { useToken } from '../../../style';
import { useLocalVariables, useVariables } from '../../../variables';
diff --git a/packages/core/client/src/schema-component/antd/form/Form.Settings.tsx b/packages/core/client/src/schema-component/antd/form/Form.Settings.tsx
index e5b07813f199d..6ac7cfedfd4db 100644
--- a/packages/core/client/src/schema-component/antd/form/Form.Settings.tsx
+++ b/packages/core/client/src/schema-component/antd/form/Form.Settings.tsx
@@ -9,7 +9,7 @@
import { SchemaSettings } from '../../../application/schema-settings';
import { useCollection_deprecated } from '../../../collection-manager';
-import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettings';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
/**
* @deprecated
diff --git a/packages/core/client/src/schema-component/antd/form/Form.tsx b/packages/core/client/src/schema-component/antd/form/Form.tsx
index d081243ddd4bf..f3d339f402b5c 100644
--- a/packages/core/client/src/schema-component/antd/form/Form.tsx
+++ b/packages/core/client/src/schema-component/antd/form/Form.tsx
@@ -16,12 +16,8 @@ import React, { createContext, useContext, useEffect, useMemo } from 'react';
import { useAttach, useComponent } from '../..';
import { useRequest } from '../../../api-client';
import { useCollection_deprecated } from '../../../collection-manager';
-import {
- GeneralSchemaDesigner,
- SchemaSettingsDivider,
- SchemaSettingsRemove,
- SchemaSettingsTemplate,
-} from '../../../schema-settings';
+import { GeneralSchemaDesigner, SchemaSettingsDivider, SchemaSettingsRemove } from '../../../schema-settings';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
type Opts = Options & { uid?: string };
diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.tsx
index 5492fe091cd44..94474550e25fb 100644
--- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.tsx
+++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Decorator.tsx
@@ -12,9 +12,9 @@ import { createForm } from '@formily/core';
import { FormContext, useField, useFieldSchema } from '@formily/react';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import { BlockProvider, useBlockRequestContext } from '../../../block-provider/BlockProvider';
-import useStyles from './GridCard.Decorator.style';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useGridCardBlockParams } from '../../../modules/blocks/data-blocks/grid-card/hooks/useGridCardBlockParams';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
+import useStyles from './GridCard.Decorator.style';
export const GridCardBlockContext = createContext({});
GridCardBlockContext.displayName = 'GridCardBlockContext';
diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Designer.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Designer.tsx
index 51bc4b815ed34..36effa6928bdc 100644
--- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Designer.tsx
+++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Designer.tsx
@@ -24,9 +24,9 @@ import {
SchemaSettingsModalItem,
SchemaSettingsRemove,
SchemaSettingsSelectItem,
- SchemaSettingsTemplate,
} from '../../../schema-settings';
import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
import { SchemaComponentOptions } from '../../core';
import { useDesignable } from '../../hooks';
diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx
index 856da986c96b7..b64f9a76cb66d 100644
--- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx
+++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.Item.tsx
@@ -12,8 +12,8 @@ import { ObjectField } from '@formily/core';
import { useField } from '@formily/react';
import { Card } from 'antd';
import React from 'react';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useCollectionParentRecordData } from '../../../data-source/collection-record/CollectionRecordProvider';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { RecordProvider } from '../../../record-provider';
const itemCss = css`
diff --git a/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx b/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx
index c86e6b040bfb4..0ddd24278bec1 100644
--- a/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx
+++ b/packages/core/client/src/schema-component/antd/grid-card/GridCard.tsx
@@ -12,6 +12,7 @@ import { ArrayField } from '@formily/core';
import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
import { List as AntdList, Col, PaginationProps } from 'antd';
import React, { useCallback, useState } from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { SortableItem } from '../../common';
import { SchemaComponentOptions } from '../../core';
import { useDesigner, useProps } from '../../hooks';
@@ -20,7 +21,6 @@ import { GridCardDesigner } from './GridCard.Designer';
import { GridCardItem } from './GridCard.Item';
import { useGridCardActionBarProps } from './hooks';
import { defaultColumnCount, pageSizeOptions } from './options';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const rowGutter = {
md: 12,
diff --git a/packages/core/client/src/schema-component/antd/list/List.Decorator.tsx b/packages/core/client/src/schema-component/antd/list/List.Decorator.tsx
index 425d6b6754fb5..0bd556350fd66 100644
--- a/packages/core/client/src/schema-component/antd/list/List.Decorator.tsx
+++ b/packages/core/client/src/schema-component/antd/list/List.Decorator.tsx
@@ -14,8 +14,8 @@ import { FormContext, useField } from '@formily/react';
import _ from 'lodash';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import { BlockProvider, useBlockRequestContext } from '../../../block-provider/BlockProvider';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useParsedFilter } from '../../../block-provider/hooks/useParsedFilter';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
export const ListBlockContext = createContext({});
ListBlockContext.displayName = 'ListBlockContext';
diff --git a/packages/core/client/src/schema-component/antd/list/List.Designer.tsx b/packages/core/client/src/schema-component/antd/list/List.Designer.tsx
index e5bf7b4108441..22d9aed535383 100644
--- a/packages/core/client/src/schema-component/antd/list/List.Designer.tsx
+++ b/packages/core/client/src/schema-component/antd/list/List.Designer.tsx
@@ -14,21 +14,21 @@ import React from 'react';
import { useTranslation } from 'react-i18next';
import { useFormBlockContext } from '../../../block-provider';
import { useCollection_deprecated, useSortFields } from '../../../collection-manager';
+import { SetDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
import { useRecord } from '../../../record-provider';
import {
GeneralSchemaDesigner,
- SchemaSettingsBlockTitleItem,
SchemaSettingsDivider,
SchemaSettingsModalItem,
SchemaSettingsRemove,
SchemaSettingsSelectItem,
- SchemaSettingsTemplate,
} from '../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
import { useDesignable } from '../../hooks';
import { removeNullCondition } from '../filter';
-import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
-import { SetDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
/**
* @deprecated - 已使用 SchemaSettings 替代
diff --git a/packages/core/client/src/schema-component/antd/list/List.Item.tsx b/packages/core/client/src/schema-component/antd/list/List.Item.tsx
index 24694b1be3f72..853feeeb2d8d4 100644
--- a/packages/core/client/src/schema-component/antd/list/List.Item.tsx
+++ b/packages/core/client/src/schema-component/antd/list/List.Item.tsx
@@ -14,8 +14,8 @@ import classnames from 'classnames';
import React from 'react';
import { useDesignable } from '../../hooks';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useCollectionParentRecordData } from '../../../data-source/collection-record/CollectionRecordProvider';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { RecordProvider } from '../../../record-provider';
export const ListItem = withDynamicSchemaProps((props) => {
diff --git a/packages/core/client/src/schema-component/antd/list/List.tsx b/packages/core/client/src/schema-component/antd/list/List.tsx
index 721832bd62a13..273cadab577a2 100644
--- a/packages/core/client/src/schema-component/antd/list/List.tsx
+++ b/packages/core/client/src/schema-component/antd/list/List.tsx
@@ -12,6 +12,7 @@ import { ArrayField } from '@formily/core';
import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react';
import { List as AntdList, PaginationProps } from 'antd';
import React, { useCallback, useState } from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { SortableItem } from '../../common';
import { SchemaComponentOptions } from '../../core';
import { useDesigner } from '../../hooks';
@@ -20,7 +21,6 @@ import { ListDesigner } from './List.Designer';
import { ListItem } from './List.Item';
import useStyles from './List.style';
import { useListActionBarProps } from './hooks';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
const InternalList = (props) => {
const { service } = useListBlockContext();
diff --git a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx
index e47589aa06b06..d52446b16760f 100644
--- a/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx
+++ b/packages/core/client/src/schema-component/antd/page/FixedBlock.tsx
@@ -10,7 +10,6 @@
import { css } from '@emotion/css';
import { useField, useFieldSchema } from '@formily/react';
import React, { useContext, useEffect, useRef, useState } from 'react';
-import { useRecord } from '../../../record-provider';
const FixedBlockContext = React.createContext<{
setFixedBlock: (value: string | false) => void;
diff --git a/packages/core/client/src/schema-component/antd/page/PageTabDesigner.tsx b/packages/core/client/src/schema-component/antd/page/PageTabDesigner.tsx
index a4c29f8d43181..78d8a11b812d5 100644
--- a/packages/core/client/src/schema-component/antd/page/PageTabDesigner.tsx
+++ b/packages/core/client/src/schema-component/antd/page/PageTabDesigner.tsx
@@ -12,7 +12,7 @@ import { useFieldSchema } from '@formily/react';
import { Space } from 'antd';
import React from 'react';
import { DragHandler, useDesignable } from '../..';
-import { useSchemaSettingsRender } from '../../../application/schema-settings/hooks';
+import { useSchemaSettingsRender } from '../../../application/schema-settings/hooks/useSchemaSettingsRender';
import { SchemaToolbarProvider } from '../../../application/schema-toolbar/context';
import { useGetAriaLabelOfDesigner } from '../../../schema-settings/hooks/useGetAriaLabelOfDesigner';
diff --git a/packages/core/client/src/schema-component/antd/pagination/index.tsx b/packages/core/client/src/schema-component/antd/pagination/index.tsx
index 5c520439c5b0d..dab98b1a51f5c 100644
--- a/packages/core/client/src/schema-component/antd/pagination/index.tsx
+++ b/packages/core/client/src/schema-component/antd/pagination/index.tsx
@@ -10,8 +10,8 @@
import { observer } from '@formily/react';
import { Pagination as AntdPagination, PaginationProps as AntdPaginationProps } from 'antd';
import React, { KeyboardEventHandler } from 'react';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useProps } from '../../hooks/useProps';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
export interface PaginationProps extends AntdPaginationProps {
hidden?: boolean;
diff --git a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
index 43f0b551be348..c34e0771bcee1 100644
--- a/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
+++ b/packages/core/client/src/schema-component/antd/table-v2/Table.tsx
@@ -35,8 +35,8 @@ import {
useTableSelectorContext,
} from '../../../';
import { useACLFieldWhitelist } from '../../../acl/ACLProvider';
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { isNewRecord } from '../../../data-source/collection-record/isNewRecord';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useToken } from '../__builtins__';
import { SubFormProvider } from '../association-field/hooks';
import { ColumnFieldProvider } from './components/ColumnFieldProvider';
diff --git a/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx b/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx
index 8a7b568873518..0e0e72ae8b2cd 100644
--- a/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx
+++ b/packages/core/client/src/schema-component/antd/table-v2/TableBlockDesigner.tsx
@@ -8,34 +8,33 @@
*/
import { ArrayItems } from '@formily/antd-v5';
-import { ISchema, useField, useFieldSchema } from '@formily/react';
import { Field } from '@formily/core';
+import { ISchema, useField, useFieldSchema } from '@formily/react';
import React, { useCallback } from 'react';
import { useTranslation } from 'react-i18next';
+import { useCompile } from '../../';
import { useAPIClient } from '../../../api-client';
import { useFormBlockContext, useTableBlockContext } from '../../../block-provider';
import { useCollectionManager_deprecated, useCollection_deprecated } from '../../../collection-manager';
import { useSortFields } from '../../../collection-manager/action-hooks';
import { FilterBlockType, mergeFilter } from '../../../filter-provider/utils';
-import { useRecord } from '../../../record-provider';
+import { SetDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
import {
GeneralSchemaDesigner,
- SchemaSettingsBlockTitleItem,
- SchemaSettingsConnectDataBlocks,
SchemaSettingsDivider,
SchemaSettingsModalItem,
SchemaSettingsRemove,
SchemaSettingsSelectItem,
SchemaSettingsSwitchItem,
- SchemaSettingsTemplate,
} from '../../../schema-settings';
+import { SchemaSettingsBlockTitleItem } from '../../../schema-settings/SchemaSettingsBlockTitleItem';
+import { SchemaSettingsConnectDataBlocks } from '../../../schema-settings/SchemaSettingsConnectDataBlocks';
+import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
import { useDesignable } from '../../hooks';
import { removeNullCondition } from '../filter';
-import { useCompile } from '../../';
-import { SchemaSettingsDataScope } from '../../../schema-settings/SchemaSettingsDataScope';
import { FixedBlockDesignerItem } from '../page/FixedBlockDesignerItem';
-import { SetDataLoadingMode } from '../../../modules/blocks/data-blocks/details-multi/setDataLoadingModeSettingsItem';
export const EditSortField = () => {
const { fields } = useCollection_deprecated();
diff --git a/packages/core/client/src/schema-component/antd/table-v2/__tests__/Table.settings.test.tsx b/packages/core/client/src/schema-component/antd/table-v2/__tests__/Table.settings.test.tsx
index ac32d8b0c79a3..fbf8aa62cfc1e 100644
--- a/packages/core/client/src/schema-component/antd/table-v2/__tests__/Table.settings.test.tsx
+++ b/packages/core/client/src/schema-component/antd/table-v2/__tests__/Table.settings.test.tsx
@@ -14,13 +14,13 @@ import {
useTableBlockDecoratorProps,
} from '@nocobase/client';
import {
+ CheckSettingsOptions,
+ checkSchema,
checkSettings,
renderSettings,
- checkSchema,
screen,
userEvent,
waitFor,
- CheckSettingsOptions,
} from '@nocobase/test/client';
import { withSchema } from '@nocobase/test/web';
diff --git a/packages/core/client/src/schema-component/antd/table/Table.Void.Designer.tsx b/packages/core/client/src/schema-component/antd/table/Table.Void.Designer.tsx
index 19d0d2932347e..61d4ab8d401bf 100644
--- a/packages/core/client/src/schema-component/antd/table/Table.Void.Designer.tsx
+++ b/packages/core/client/src/schema-component/antd/table/Table.Void.Designer.tsx
@@ -20,8 +20,8 @@ import {
SchemaSettingsRemove,
SchemaSettingsSelectItem,
SchemaSettingsSwitchItem,
- SchemaSettingsTemplate,
} from '../../../schema-settings';
+import { SchemaSettingsTemplate } from '../../../schema-settings/SchemaSettingsTemplate';
import { useSchemaTemplate } from '../../../schema-templates';
import { useDesignable } from '../../hooks';
diff --git a/packages/core/client/src/schema-component/antd/upload/Upload.tsx b/packages/core/client/src/schema-component/antd/upload/Upload.tsx
index 8e22fdfd7e2d7..2224989bed289 100644
--- a/packages/core/client/src/schema-component/antd/upload/Upload.tsx
+++ b/packages/core/client/src/schema-component/antd/upload/Upload.tsx
@@ -16,7 +16,7 @@ import React, { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import LightBox from 'react-image-lightbox';
import 'react-image-lightbox/style.css'; // This only needs to be imported once in your app
-import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
+import { withDynamicSchemaProps } from '../../../hoc/withDynamicSchemaProps';
import { useProps } from '../../hooks/useProps';
import { ReadPretty } from './ReadPretty';
import { isImage, isPdf, toArr, toFileList, toItem, toValue, useUploadProps } from './shared';
diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts
index 756a1483a45f1..e4f56a0fabf2a 100644
--- a/packages/core/client/src/schema-initializer/utils.ts
+++ b/packages/core/client/src/schema-initializer/utils.ts
@@ -382,6 +382,7 @@ export const useFilterFormItemInitializerFields = (options?: any) => {
'x-settings': 'fieldSettings:FilterFormItem',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
+ 'x-use-decorator-props': 'useFormItemProps',
'x-collection-field': `${name}.${field.name}`,
'x-component-props': {},
};
@@ -395,6 +396,7 @@ export const useFilterFormItemInitializerFields = (options?: any) => {
'x-settings': 'fieldSettings:FilterFormItem',
'x-component': 'CollectionField',
'x-decorator': 'FormItem',
+ 'x-use-decorator-props': 'useFormItemProps',
'x-collection-field': `${name}.${field.name}`,
'x-component-props': field.uiSchema?.['x-component-props'],
};
diff --git a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx
index 5f4ea8ee964fd..cade0cd743595 100644
--- a/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx
+++ b/packages/core/client/src/schema-settings/DataTemplates/FormDataTemplates.tsx
@@ -16,6 +16,7 @@ import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { useCollectionManager_deprecated } from '../../collection-manager';
import { mergeFilter } from '../../filter-provider/utils';
+import { withDynamicSchemaProps } from '../../hoc/withDynamicSchemaProps';
import { SchemaComponent, SchemaComponentContext, removeNullCondition, useProps } from '../../schema-component';
import { ITemplate } from '../../schema-component/antd/form-v2/Templates';
import { VariableInput } from '../VariableInput';
@@ -24,7 +25,6 @@ import { ArrayCollapse } from './components/DataTemplateTitle';
import { getSelectedIdFilter } from './components/Designer';
import { useCollectionState } from './hooks/useCollectionState';
import { useSyncFromForm } from './utils';
-import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
const Tree = connect(
AntdTree,
diff --git a/packages/core/client/src/schema-settings/EnableChildCollections/index.tsx b/packages/core/client/src/schema-settings/EnableChildCollections/index.tsx
index a4d9c315ee5e5..792097230dfd9 100644
--- a/packages/core/client/src/schema-settings/EnableChildCollections/index.tsx
+++ b/packages/core/client/src/schema-settings/EnableChildCollections/index.tsx
@@ -11,8 +11,8 @@ import { observer, useForm } from '@formily/react';
import { action } from '@formily/reactive';
import React from 'react';
import { useCollectionManager_deprecated } from '../../collection-manager';
+import { withDynamicSchemaProps } from '../../hoc/withDynamicSchemaProps';
import { SchemaComponent, useCompile, useProps } from '../../schema-component';
-import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
export const EnableChildCollections = withDynamicSchemaProps(
observer((props: any) => {
diff --git a/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx b/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx
index c87e5a5e7ba29..a4b6aeea3db01 100644
--- a/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx
+++ b/packages/core/client/src/schema-settings/GeneralSchemaDesigner.tsx
@@ -14,13 +14,8 @@ import { Space } from 'antd';
import classNames from 'classnames';
import React, { FC, useEffect, useMemo, useRef } from 'react';
import { useTranslation } from 'react-i18next';
-import {
- SchemaInitializer,
- SchemaSettings,
- SchemaToolbarProvider,
- useSchemaInitializerRender,
- useSchemaSettingsRender,
-} from '../application';
+import { SchemaInitializer, SchemaSettings, SchemaToolbarProvider, useSchemaInitializerRender } from '../application';
+import { useSchemaSettingsRender } from '../application/schema-settings/hooks/useSchemaSettingsRender';
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
import { useDataSource } from '../data-source/data-source/DataSourceProvider';
import { DragHandler, useCompile, useDesignable, useGridContext, useGridRowContext } from '../schema-component';
diff --git a/packages/core/client/src/schema-settings/LinkageRules/LinkageRuleActionGroup.tsx b/packages/core/client/src/schema-settings/LinkageRules/LinkageRuleActionGroup.tsx
index f427299e6ca98..2c7cf02931508 100644
--- a/packages/core/client/src/schema-settings/LinkageRules/LinkageRuleActionGroup.tsx
+++ b/packages/core/client/src/schema-settings/LinkageRules/LinkageRuleActionGroup.tsx
@@ -12,10 +12,10 @@ import { ArrayField, ObjectField, observer, useField } from '@formily/react';
import { Space } from 'antd';
import React, { useCallback, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
+import { withDynamicSchemaProps } from '../../hoc/withDynamicSchemaProps';
+import { useProps } from '../../schema-component/hooks/useProps';
import { FormButtonLinkageRuleAction, FormFieldLinkageRuleAction } from './LinkageRuleAction';
import { RemoveActionContext } from './context';
-import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
-import { useProps } from '../../schema-component/hooks/useProps';
export const LinkageRuleActions = observer(
(props: any): any => {
const { type, linkageOptions } = props;
diff --git a/packages/core/client/src/schema-settings/LinkageRules/index.tsx b/packages/core/client/src/schema-settings/LinkageRules/index.tsx
index 3f06124b5af92..cd538e530beb9 100644
--- a/packages/core/client/src/schema-settings/LinkageRules/index.tsx
+++ b/packages/core/client/src/schema-settings/LinkageRules/index.tsx
@@ -10,10 +10,10 @@
import { css } from '@emotion/css';
import { observer, useFieldSchema } from '@formily/react';
import React, { useMemo } from 'react';
-import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
import { FormBlockContext } from '../../block-provider';
import { useCollectionManager_deprecated } from '../../collection-manager';
import { useCollectionParentRecordData } from '../../data-source/collection-record/CollectionRecordProvider';
+import { withDynamicSchemaProps } from '../../hoc/withDynamicSchemaProps';
import { RecordProvider } from '../../record-provider';
import { SchemaComponent, useProps } from '../../schema-component';
import { DynamicComponentProps } from '../../schema-component/antd/filter/DynamicComponent';
diff --git a/packages/core/client/src/schema-settings/SchemaSettings.tsx b/packages/core/client/src/schema-settings/SchemaSettings.tsx
index 76f815750c8af..16296446bc2d0 100644
--- a/packages/core/client/src/schema-settings/SchemaSettings.tsx
+++ b/packages/core/client/src/schema-settings/SchemaSettings.tsx
@@ -12,7 +12,6 @@ import { ArrayCollapse, ArrayItems, FormItem, FormLayout, Input } from '@formily
import { Field, GeneralField, createForm } from '@formily/core';
import { ISchema, Schema, SchemaOptionsContext, useField, useFieldSchema, useForm } from '@formily/react';
import { uid } from '@formily/shared';
-import { error } from '@nocobase/utils/client';
import type { DropdownProps } from 'antd';
import {
Alert,
@@ -22,7 +21,6 @@ import {
CascaderProps,
ConfigProvider,
Dropdown,
- Empty,
MenuItemProps,
MenuProps,
Modal,
@@ -46,65 +44,47 @@ import React, {
import { createPortal } from 'react-dom';
import { useTranslation } from 'react-i18next';
import { Router } from 'react-router-dom';
+import { APIClientProvider } from '../api-client/APIClientProvider';
+import { useAPIClient } from '../api-client/hooks/useAPIClient';
+import { FormBlockContext, findFormBlock, useFormBlockContext, useFormBlockType } from '../block-provider';
import {
- APIClientProvider,
- ActionContextProvider,
- AssociationOrCollectionProvider,
- CollectionFieldOptions_deprecated,
- CollectionRecordProvider,
- DataSourceApplicationProvider,
- Designable,
- FormDialog,
- FormProvider,
- RemoteSchemaComponent,
- SchemaComponent,
- SchemaComponentContext,
- SchemaComponentOptions,
- createDesignable,
- findFormBlock,
- useAPIClient,
- useCollectionManager_deprecated,
- useCollectionRecord,
- useCollection_deprecated,
- useCompile,
- useDataBlockProps,
- useDesignable,
- useGlobalTheme,
- useLinkageCollectionFilterOptions,
- useRecord,
- useSortFields,
-} from '..';
-import { FormBlockContext, useFormBlockContext, useFormBlockType, useTableBlockContext } from '../block-provider';
-import {
- FormActiveFieldsProvider,
- findFilterTargets,
- updateFilterTargets,
- useFormActiveFields,
-} from '../block-provider/hooks';
-import {
- useBlockRequestContext,
+ BlockContext,
BlockRequestContext_deprecated,
useBlockContext,
- BlockContext,
+ useBlockRequestContext,
} from '../block-provider/BlockProvider';
+import { FormActiveFieldsProvider, useFormActiveFields } from '../block-provider/hooks';
+import { useLinkageCollectionFilterOptions, useSortFields } from '../collection-manager/action-hooks';
+import { useCollectionManager_deprecated } from '../collection-manager/hooks/useCollectionManager_deprecated';
+import { useCollection_deprecated } from '../collection-manager/hooks/useCollection_deprecated';
+import { CollectionFieldOptions_deprecated } from '../collection-manager/types';
import { SelectWithTitle, SelectWithTitleProps } from '../common/SelectWithTitle';
import { useNiceDropdownMaxHeight } from '../common/useNiceDropdownHeight';
+import {
+ CollectionRecordProvider,
+ useCollectionRecord,
+} from '../data-source/collection-record/CollectionRecordProvider';
+import { DataSourceApplicationProvider } from '../data-source/components/DataSourceApplicationProvider';
+import { AssociationOrCollectionProvider, useDataBlockProps } from '../data-source/data-block/DataBlockProvider';
import { useDataSourceManager } from '../data-source/data-source/DataSourceManagerProvider';
import { useDataSourceKey } from '../data-source/data-source/DataSourceProvider';
-import {
- FilterBlockType,
- getSupportFieldsByAssociation,
- getSupportFieldsByForeignKey,
- isSameCollection,
- useSupportedBlocks,
-} from '../filter-provider/utils';
import { useFilterBlock } from '../filter-provider/FilterProvider';
import { FlagProvider } from '../flag-provider';
+import { useGlobalTheme } from '../global-theme';
import { useCollectMenuItem, useCollectMenuItems, useMenuItem } from '../hooks/useMenuItem';
import { DeclareVariable } from '../modules/variable/DeclareVariable';
import { useVariable } from '../modules/variable/useVariable';
+import { useRecord } from '../record-provider';
+import { ActionContextProvider } from '../schema-component/antd/action/context';
import { SubFormProvider, useSubFormValue } from '../schema-component/antd/association-field/hooks';
-import { getTargetKey } from '../schema-component/antd/association-filter/utilts';
+import { FormDialog } from '../schema-component/antd/form-dialog';
+import { SchemaComponentContext } from '../schema-component/context';
+import { FormProvider } from '../schema-component/core/FormProvider';
+import { RemoteSchemaComponent } from '../schema-component/core/RemoteSchemaComponent';
+import { SchemaComponent } from '../schema-component/core/SchemaComponent';
+import { SchemaComponentOptions } from '../schema-component/core/SchemaComponentOptions';
+import { useCompile } from '../schema-component/hooks/useCompile';
+import { Designable, createDesignable, useDesignable } from '../schema-component/hooks/useDesignable';
import { useSchemaTemplateManager } from '../schema-templates';
import { useBlockTemplateContext } from '../schema-templates/BlockTemplate';
import { useLocalVariables, useVariables } from '../variables';
@@ -207,103 +187,6 @@ export const SchemaSettingsDropdown: React.FC = (props) =>
);
};
-export const SchemaSettingsTemplate = function Template(props) {
- const { componentName, collectionName, resourceName, needRender } = props;
- const { t } = useTranslation();
- const { getCollection } = useCollectionManager_deprecated();
- const { dn, setVisible, template, fieldSchema } = useSchemaSettings();
- const compile = useCompile();
- const api = useAPIClient();
- const { dn: tdn } = useBlockTemplateContext();
- const { saveAsTemplate, copyTemplateSchema } = useSchemaTemplateManager();
- const { theme } = useGlobalTheme();
-
- if (!collectionName && !needRender) {
- return null;
- }
- if (template) {
- return (
- {
- const schema = await copyTemplateSchema(template);
- const removed = tdn.removeWithoutEmit();
- tdn.insertAfterEnd(schema, {
- async onSuccess() {
- await api.request({
- url: `/uiSchemas:remove/${removed['x-uid']}`,
- });
- },
- });
- }}
- >
- {t('Convert reference to duplicate')}
-
- );
- }
- return (
- {
- setVisible(false);
- const collection = collectionName && getCollection(collectionName);
- const values = await FormDialog(
- t('Save as template'),
- () => {
- return (
-
-
-
- );
- },
- theme,
- ).open({});
- const sdn = createDesignable({
- t,
- api,
- refresh: dn.refresh.bind(dn),
- current: fieldSchema.parent,
- });
- sdn.loadAPIClientEvents();
- const { key } = await saveAsTemplate({
- collectionName,
- resourceName,
- componentName,
- dataSourceKey: collection.dataSource,
- name: values.name,
- uid: fieldSchema['x-uid'],
- });
- sdn.removeWithoutEmit(fieldSchema);
- sdn.insertBeforeEnd({
- type: 'void',
- 'x-component': 'BlockTemplate',
- 'x-component-props': {
- templateId: key,
- },
- });
- }}
- >
- {t('Save as template')}
-
- );
-};
-
const findGridSchema = (fieldSchema) => {
return fieldSchema.reduceProperties((buf, s) => {
if (s['x-component'] === 'FormV2' || s['x-component'] === 'Details') {
@@ -609,144 +492,6 @@ export const SchemaSettingsRemove: FC = (props) => {
);
};
-interface SchemaSettingsConnectDataBlocksProps {
- type: FilterBlockType;
- emptyDescription?: string;
-}
-
-export const SchemaSettingsConnectDataBlocks: FC = (props) => {
- const { type, emptyDescription } = props;
- const fieldSchema = useFieldSchema();
- const { dn } = useDesignable();
- const { t } = useTranslation();
- const collection = useCollection_deprecated();
- const { inProvider } = useFilterBlock();
- const dataBlocks = useSupportedBlocks(type);
- // eslint-disable-next-line prefer-const
- let { targets = [], uid } = findFilterTargets(fieldSchema);
- const compile = useCompile();
- const { getAllCollectionsInheritChain } = useCollectionManager_deprecated();
-
- if (!inProvider) {
- return null;
- }
-
- const Content = dataBlocks.map((block) => {
- const title = `${compile(block.collection.title)} #${block.uid.slice(0, 4)}`;
- const onHover = () => {
- const dom = block.dom;
- const designer = dom.querySelector('.general-schema-designer') as HTMLElement;
- if (designer) {
- designer.style.display = 'block';
- }
- dom.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';
- dom.scrollIntoView({
- behavior: 'smooth',
- block: 'center',
- });
- };
- const onLeave = () => {
- const dom = block.dom;
- const designer = dom.querySelector('.general-schema-designer') as HTMLElement;
- if (designer) {
- designer.style.display = null;
- }
- dom.style.boxShadow = 'none';
- };
- if (isSameCollection(block.collection, collection)) {
- return (
- target.uid === block.uid)}
- onChange={(checked) => {
- if (checked) {
- targets.push({ uid: block.uid });
- } else {
- targets = targets.filter((target) => target.uid !== block.uid);
- block.clearFilter(uid);
- }
-
- updateFilterTargets(fieldSchema, targets);
- dn.emit('patch', {
- schema: {
- ['x-uid']: uid,
- 'x-filter-targets': targets,
- },
- }).catch(error);
- dn.refresh();
- }}
- onMouseEnter={onHover}
- onMouseLeave={onLeave}
- />
- );
- }
-
- const target = targets.find((target) => target.uid === block.uid);
- // 与筛选区块的数据表具有关系的表
- return (
- {
- return {
- label: compile(field.uiSchema.title) || field.name,
- value: `${field.name}.${getTargetKey(field)}`,
- };
- }),
- ...getSupportFieldsByForeignKey(collection, block).map((field) => {
- return {
- label: `${compile(field.uiSchema.title) || field.name} [${t('Foreign key')}]`,
- value: field.name,
- };
- }),
- {
- label: t('Unconnected'),
- value: '',
- },
- ]}
- onChange={(value) => {
- if (value === '') {
- targets = targets.filter((target) => target.uid !== block.uid);
- block.clearFilter(uid);
- } else {
- targets = targets.filter((target) => target.uid !== block.uid);
- targets.push({ uid: block.uid, field: value });
- }
- updateFilterTargets(fieldSchema, targets);
- dn.emit('patch', {
- schema: {
- ['x-uid']: uid,
- 'x-filter-targets': targets,
- },
- });
- dn.refresh();
- }}
- onMouseEnter={onHover}
- onMouseLeave={onLeave}
- />
- );
- });
-
- return (
-
- {Content.length ? (
- Content
- ) : (
-
-
-
- )}
-
- );
-};
-
export interface SchemaSettingsSelectItemProps
extends Omit,
Omit {
@@ -1087,47 +832,6 @@ export const SchemaSettingsModalItem: FC = (props)
);
};
-export const SchemaSettingsBlockTitleItem = function BlockTitleItem() {
- const field = useField();
- const fieldSchema = useFieldSchema();
- const { dn } = useDesignable();
- const { t } = useTranslation();
-
- return (
- {
- const componentProps = fieldSchema['x-component-props'] || {};
- componentProps.title = title;
- fieldSchema['x-component-props'] = componentProps;
- field.componentProps.title = title;
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-component-props': fieldSchema['x-component-props'],
- },
- });
- dn.refresh();
- }}
- />
- );
-};
-
export const SchemaSettingsDefaultSortingRules = function DefaultSortingRules(props) {
const { path = 'x-component-props.params.sort' } = props;
const { t } = useTranslation();
@@ -1500,48 +1204,6 @@ export const findParentFieldSchema = (fieldSchema: Schema) => {
}
};
-export const SchemaSettingsSortField = () => {
- const { fields } = useCollection_deprecated();
- const field = useField();
- const fieldSchema = useFieldSchema();
- const { t } = useTranslation();
- const { dn } = useDesignable();
- const compile = useCompile();
- const { service, association } = useTableBlockContext();
- const { getCollectionJoinField } = useCollectionManager_deprecated();
- const collectionField = getCollectionJoinField(association);
- const options = fields
- .filter((field) => !field?.target && field.interface === 'sort')
- .map((field) => {
- return {
- value: field?.name,
- label: compile(field?.uiSchema?.title) || field?.name,
- disabled: field?.scopeKey && collectionField?.foreignKey !== field.scopeKey,
- };
- });
-
- return (
- {
- fieldSchema['x-decorator-props'].dragSortBy = dragSortBy;
- service.run({ ...service.params?.[0], sort: dragSortBy });
- field.decoratorProps.dragSortBy = dragSortBy;
- dn.emit('patch', {
- schema: {
- ['x-uid']: fieldSchema['x-uid'],
- 'x-decorator-props': fieldSchema['x-decorator-props'],
- },
- });
- dn.refresh();
- }}
- />
- );
-};
-
// 是否是系统字段
export const isSystemField = (collectionField: CollectionFieldOptions_deprecated, getInterface) => {
const i = getInterface?.(collectionField?.interface);
diff --git a/packages/core/client/src/schema-settings/SchemaSettingsBlockTitleItem.tsx b/packages/core/client/src/schema-settings/SchemaSettingsBlockTitleItem.tsx
new file mode 100644
index 0000000000000..e356366f34fbd
--- /dev/null
+++ b/packages/core/client/src/schema-settings/SchemaSettingsBlockTitleItem.tsx
@@ -0,0 +1,55 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { ISchema, useField, useFieldSchema } from '@formily/react';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useDesignable } from '../schema-component/hooks/useDesignable';
+import { SchemaSettingsModalItem } from './SchemaSettings';
+
+export function SchemaSettingsBlockTitleItem() {
+ const field = useField();
+ const fieldSchema = useFieldSchema();
+ const { dn } = useDesignable();
+ const { t } = useTranslation();
+
+ return (
+ {
+ const componentProps = fieldSchema['x-component-props'] || {};
+ componentProps.title = title;
+ fieldSchema['x-component-props'] = componentProps;
+ field.componentProps.title = title;
+ dn.emit('patch', {
+ schema: {
+ ['x-uid']: fieldSchema['x-uid'],
+ 'x-component-props': fieldSchema['x-component-props'],
+ },
+ });
+ dn.refresh();
+ }}
+ />
+ );
+}
diff --git a/packages/core/client/src/schema-settings/SchemaSettingsConnectDataBlocks.tsx b/packages/core/client/src/schema-settings/SchemaSettingsConnectDataBlocks.tsx
new file mode 100644
index 0000000000000..5600157c6df55
--- /dev/null
+++ b/packages/core/client/src/schema-settings/SchemaSettingsConnectDataBlocks.tsx
@@ -0,0 +1,166 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { useFieldSchema } from '@formily/react';
+import { error } from '@nocobase/utils/client';
+import { Empty } from 'antd';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { findFilterTargets, updateFilterTargets } from '../block-provider/hooks';
+import { useCollectionManager_deprecated } from '../collection-manager/hooks/useCollectionManager_deprecated';
+import { useCollection_deprecated } from '../collection-manager/hooks/useCollection_deprecated';
+import { useFilterBlock } from '../filter-provider/FilterProvider';
+import {
+ getSupportFieldsByAssociation,
+ getSupportFieldsByForeignKey,
+ isSameCollection,
+ useSupportedBlocks,
+} from '../filter-provider/utils';
+import { getTargetKey } from '../schema-component/antd/association-filter/utilts';
+import { useCompile } from '../schema-component/hooks/useCompile';
+import { useDesignable } from '../schema-component/hooks/useDesignable';
+import {
+ SchemaSettingsItem,
+ SchemaSettingsSelectItem,
+ SchemaSettingsSubMenu,
+ SchemaSettingsSwitchItem,
+} from './SchemaSettings';
+
+export function SchemaSettingsConnectDataBlocks(props) {
+ const { type, emptyDescription } = props;
+ const fieldSchema = useFieldSchema();
+ const { dn } = useDesignable();
+ const { t } = useTranslation();
+ const collection = useCollection_deprecated();
+ const { inProvider } = useFilterBlock();
+ const dataBlocks = useSupportedBlocks(type);
+ // eslint-disable-next-line prefer-const
+ let { targets = [], uid } = findFilterTargets(fieldSchema);
+ const compile = useCompile();
+ const { getAllCollectionsInheritChain } = useCollectionManager_deprecated();
+
+ if (!inProvider) {
+ return null;
+ }
+
+ const Content = dataBlocks.map((block) => {
+ const title = `${compile(block.collection.title)} #${block.uid.slice(0, 4)}`;
+ const onHover = () => {
+ const dom = block.dom;
+ const designer = dom.querySelector('.general-schema-designer') as HTMLElement;
+ if (designer) {
+ designer.style.display = 'block';
+ }
+ dom.style.boxShadow = '0 0 10px rgba(0, 0, 0, 0.2)';
+ dom.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ });
+ };
+ const onLeave = () => {
+ const dom = block.dom;
+ const designer = dom.querySelector('.general-schema-designer') as HTMLElement;
+ if (designer) {
+ designer.style.display = null;
+ }
+ dom.style.boxShadow = 'none';
+ };
+ if (isSameCollection(block.collection, collection)) {
+ return (
+ target.uid === block.uid)}
+ onChange={(checked) => {
+ if (checked) {
+ targets.push({ uid: block.uid });
+ } else {
+ targets = targets.filter((target) => target.uid !== block.uid);
+ block.clearFilter(uid);
+ }
+
+ updateFilterTargets(fieldSchema, targets);
+ dn.emit('patch', {
+ schema: {
+ ['x-uid']: uid,
+ 'x-filter-targets': targets,
+ },
+ }).catch(error);
+ dn.refresh();
+ }}
+ onMouseEnter={onHover}
+ onMouseLeave={onLeave}
+ />
+ );
+ }
+
+ const target = targets.find((target) => target.uid === block.uid);
+ // 与筛选区块的数据表具有关系的表
+ return (
+ {
+ return {
+ label: compile(field.uiSchema.title) || field.name,
+ value: `${field.name}.${getTargetKey(field)}`,
+ };
+ }),
+ ...getSupportFieldsByForeignKey(collection, block).map((field) => {
+ return {
+ label: `${compile(field.uiSchema.title) || field.name} [${t('Foreign key')}]`,
+ value: field.name,
+ };
+ }),
+ {
+ label: t('Unconnected'),
+ value: '',
+ },
+ ]}
+ onChange={(value) => {
+ if (value === '') {
+ targets = targets.filter((target) => target.uid !== block.uid);
+ block.clearFilter(uid);
+ } else {
+ targets = targets.filter((target) => target.uid !== block.uid);
+ targets.push({ uid: block.uid, field: value });
+ }
+ updateFilterTargets(fieldSchema, targets);
+ dn.emit('patch', {
+ schema: {
+ ['x-uid']: uid,
+ 'x-filter-targets': targets,
+ },
+ });
+ dn.refresh();
+ }}
+ onMouseEnter={onHover}
+ onMouseLeave={onLeave}
+ />
+ );
+ });
+
+ return (
+
+ {Content.length ? (
+ Content
+ ) : (
+
+
+
+ )}
+
+ );
+}
diff --git a/packages/core/client/src/schema-settings/SchemaSettingsSortField.tsx b/packages/core/client/src/schema-settings/SchemaSettingsSortField.tsx
new file mode 100644
index 0000000000000..0e724ea79010b
--- /dev/null
+++ b/packages/core/client/src/schema-settings/SchemaSettingsSortField.tsx
@@ -0,0 +1,61 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { Field } from '@formily/core';
+import { useField, useFieldSchema } from '@formily/react';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useTableBlockContext } from '../block-provider';
+import { useCollectionManager_deprecated } from '../collection-manager/hooks/useCollectionManager_deprecated';
+import { useCollection_deprecated } from '../collection-manager/hooks/useCollection_deprecated';
+import { useCompile } from '../schema-component/hooks/useCompile';
+import { useDesignable } from '../schema-component/hooks/useDesignable';
+import { SchemaSettingsSelectItem } from './SchemaSettings';
+
+export function SchemaSettingsSortField() {
+ const { fields } = useCollection_deprecated();
+ const field = useField();
+ const fieldSchema = useFieldSchema();
+ const { t } = useTranslation();
+ const { dn } = useDesignable();
+ const compile = useCompile();
+ const { service, association } = useTableBlockContext();
+ const { getCollectionJoinField } = useCollectionManager_deprecated();
+ const collectionField = getCollectionJoinField(association);
+ const options = fields
+ .filter((field) => !field?.target && field.interface === 'sort')
+ .map((field) => {
+ return {
+ value: field?.name,
+ label: compile(field?.uiSchema?.title) || field?.name,
+ disabled: field?.scopeKey && collectionField?.foreignKey !== field.scopeKey,
+ };
+ });
+
+ return (
+ {
+ fieldSchema['x-decorator-props'].dragSortBy = dragSortBy;
+ service.run({ ...service.params?.[0], sort: dragSortBy });
+ field.decoratorProps.dragSortBy = dragSortBy;
+ dn.emit('patch', {
+ schema: {
+ ['x-uid']: fieldSchema['x-uid'],
+ 'x-decorator-props': fieldSchema['x-decorator-props'],
+ },
+ });
+ dn.refresh();
+ }}
+ />
+ );
+}
diff --git a/packages/core/client/src/schema-settings/SchemaSettingsTemplate.tsx b/packages/core/client/src/schema-settings/SchemaSettingsTemplate.tsx
new file mode 100644
index 0000000000000..c0ff1716c3fb5
--- /dev/null
+++ b/packages/core/client/src/schema-settings/SchemaSettingsTemplate.tsx
@@ -0,0 +1,121 @@
+/**
+ * This file is part of the NocoBase (R) project.
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
+ * Authors: NocoBase Team.
+ *
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
+ * For more information, please refer to: https://www.nocobase.com/agreement.
+ */
+
+import { FormLayout } from '@formily/antd-v5';
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useAPIClient } from '../api-client/hooks/useAPIClient';
+import { useCollectionManager_deprecated } from '../collection-manager/hooks/useCollectionManager_deprecated';
+import { useGlobalTheme } from '../global-theme';
+import { FormDialog } from '../schema-component/antd/form-dialog';
+import { FormItem } from '../schema-component/antd/form-item/FormItem';
+import { Input } from '../schema-component/antd/input/Input';
+import { SchemaComponent } from '../schema-component/core/SchemaComponent';
+import { useCompile } from '../schema-component/hooks/useCompile';
+import { createDesignable } from '../schema-component/hooks/useDesignable';
+import { useSchemaTemplateManager } from '../schema-templates';
+import { useBlockTemplateContext } from '../schema-templates/BlockTemplate';
+import { SchemaSettingsItem, useSchemaSettings } from './SchemaSettings';
+
+export function SchemaSettingsTemplate(props) {
+ const { componentName, collectionName, resourceName, needRender } = props;
+ const { t } = useTranslation();
+ const { getCollection } = useCollectionManager_deprecated();
+ const { dn, setVisible, template, fieldSchema } = useSchemaSettings();
+ const compile = useCompile();
+ const api = useAPIClient();
+ const { dn: tdn } = useBlockTemplateContext();
+ const { saveAsTemplate, copyTemplateSchema } = useSchemaTemplateManager();
+ const { theme } = useGlobalTheme();
+
+ if (!collectionName && !needRender) {
+ return null;
+ }
+ if (template) {
+ return (
+ {
+ const schema = await copyTemplateSchema(template);
+ const removed = tdn.removeWithoutEmit();
+ tdn.insertAfterEnd(schema, {
+ async onSuccess() {
+ await api.request({
+ url: `/uiSchemas:remove/${removed['x-uid']}`,
+ });
+ },
+ });
+ }}
+ >
+ {t('Convert reference to duplicate')}
+
+ );
+ }
+ return (
+ {
+ setVisible(false);
+ const collection = collectionName && getCollection(collectionName);
+ const values = await FormDialog(
+ t('Save as template'),
+ () => {
+ return (
+
+
+
+ );
+ },
+ theme,
+ ).open({});
+ const sdn = createDesignable({
+ t,
+ api,
+ refresh: dn.refresh.bind(dn),
+ current: fieldSchema.parent,
+ });
+ sdn.loadAPIClientEvents();
+ const { key } = await saveAsTemplate({
+ collectionName,
+ resourceName,
+ componentName,
+ dataSourceKey: collection.dataSource,
+ name: values.name,
+ uid: fieldSchema['x-uid'],
+ });
+ sdn.removeWithoutEmit(fieldSchema);
+ sdn.insertBeforeEnd({
+ type: 'void',
+ 'x-component': 'BlockTemplate',
+ 'x-component-props': {
+ templateId: key,
+ },
+ });
+ }}
+ >
+ {t('Save as template')}
+
+ );
+}
diff --git a/packages/core/client/src/schema-settings/index.ts b/packages/core/client/src/schema-settings/index.ts
index f0178601b2450..0b153421d2076 100644
--- a/packages/core/client/src/schema-settings/index.ts
+++ b/packages/core/client/src/schema-settings/index.ts
@@ -11,15 +11,18 @@ export * from './DataTemplates/hooks/useCollectionState';
export * from './DataTemplates/utils';
export * from './GeneralSchemaDesigner';
export * from './SchemaSettings';
-export * from './hooks/useGetAriaLabelOfDesigner';
-export * from './hooks/useIsAllowToSetDefaultValue';
-export * from './isPatternDisabled';
+export * from './SchemaSettingsBlockTitleItem';
+export * from './SchemaSettingsConnectDataBlocks';
export * from './SchemaSettingsDataScope';
-export * from './SchemaSettingsDefaultValue';
export * from './SchemaSettingsDateFormat';
-export * from './SchemaSettingsSortingRule';
+export * from './SchemaSettingsDefaultValue';
export * from './SchemaSettingsNumberFormat';
+export * from './SchemaSettingsSortingRule';
+export * from './SchemaSettingsTemplate';
+export * from './hooks/useGetAriaLabelOfDesigner';
+export * from './hooks/useIsAllowToSetDefaultValue';
export { default as useParseDataScopeFilter } from './hooks/useParseDataScopeFilter';
+export * from './isPatternDisabled';
export { SchemaSettingsPlugin } from './SchemaSettingsPlugin';
export * from './VariableInput';
diff --git a/packages/plugins/@nocobase/plugin-map/src/client/block/MapBlock.Settings.tsx b/packages/plugins/@nocobase/plugin-map/src/client/block/MapBlock.Settings.tsx
index acc5b164ba788..b32b68eb1b463 100644
--- a/packages/plugins/@nocobase/plugin-map/src/client/block/MapBlock.Settings.tsx
+++ b/packages/plugins/@nocobase/plugin-map/src/client/block/MapBlock.Settings.tsx
@@ -11,6 +11,7 @@ import { ISchema, useField, useFieldSchema } from '@formily/react';
import {
FilterBlockType,
FixedBlockDesignerItem,
+ SchemaSettings,
SchemaSettingsBlockTitleItem,
SchemaSettingsCascaderItem,
SchemaSettingsConnectDataBlocks,
@@ -19,13 +20,11 @@ import {
SchemaSettingsModalItem,
SchemaSettingsSelectItem,
SchemaSettingsTemplate,
+ setDataLoadingModeSettingsItem,
useCollection,
+ useCollectionManager_deprecated,
useDesignable,
useFormBlockContext,
- SchemaSettings,
- useCollectionManager_deprecated,
- setDataLoadingModeSettingsItem,
- useDataLoadingMode,
} from '@nocobase/client';
import lodash from 'lodash';
import { useMapTranslation } from '../locale';