diff --git a/packages/core/client/.dumirc.ts b/packages/core/client/.dumirc.ts
index 1debccd479..8389585d18 100644
--- a/packages/core/client/.dumirc.ts
+++ b/packages/core/client/.dumirc.ts
@@ -234,6 +234,10 @@ export default defineConfig({
"title": "Filter",
"link": "/components/filter"
},
+ {
+ "title": "LinkageFilter",
+ "link": "/components/linkage-filter"
+ },
]
},
{
diff --git a/packages/core/client/src/block-provider/hooks/index.ts b/packages/core/client/src/block-provider/hooks/index.ts
index ce2227b54e..d34a8d540e 100644
--- a/packages/core/client/src/block-provider/hooks/index.ts
+++ b/packages/core/client/src/block-provider/hooks/index.ts
@@ -1582,7 +1582,7 @@ export const getAppends = ({
const fieldNames = getTargetField(item);
// 只应该收集关系字段,只有大于 1 的时候才是关系字段
- if (fieldNames.length > 1) {
+ if (fieldNames.length > 1 && !item.op) {
appends.add(fieldNames.join('.'));
}
});
diff --git a/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx b/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
index f0e79b3eb7..9c4d55b34a 100644
--- a/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/add-new/addNewActionSettings.tsx
@@ -15,6 +15,8 @@ import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/actio
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsEnableChildCollections } from '../../../schema-settings/SchemaSettings';
import { useOpenModeContext } from '../../popup/OpenModeProvider';
+import { SchemaSettingsLinkageRules } from '../../../schema-settings';
+import { useDataBlockProps } from '../../../data-source';
export const addNewActionSettings = new SchemaSettings({
name: 'actionSettings:addNew',
@@ -27,6 +29,16 @@ export const addNewActionSettings = new SchemaSettings({
return buttonEditorProps;
},
},
+ {
+ name: 'linkageRules',
+ Component: SchemaSettingsLinkageRules,
+ useComponentProps() {
+ const { linkageRulesProps } = useSchemaToolbar();
+ return {
+ ...linkageRulesProps,
+ };
+ },
+ },
{
name: 'openMode',
Component: SchemaSettingOpenModeSchemaItems,
diff --git a/packages/core/client/src/modules/actions/bulk-destroy/bulkDeleteActionSettings.tsx b/packages/core/client/src/modules/actions/bulk-destroy/bulkDeleteActionSettings.tsx
index be35280a42..f5c2ab2409 100644
--- a/packages/core/client/src/modules/actions/bulk-destroy/bulkDeleteActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/bulk-destroy/bulkDeleteActionSettings.tsx
@@ -15,6 +15,7 @@ import {
SecondConFirm,
RefreshDataBlockRequest,
} from '../../../schema-component/antd/action/Action.Designer';
+import { SchemaSettingsLinkageRules } from '../../../schema-settings';
export const bulkDeleteActionSettings = new SchemaSettings({
name: 'actionSettings:bulkDelete',
@@ -27,6 +28,16 @@ export const bulkDeleteActionSettings = new SchemaSettings({
return buttonEditorProps;
},
},
+ {
+ name: 'linkageRules',
+ Component: SchemaSettingsLinkageRules,
+ useComponentProps() {
+ const { linkageRulesProps } = useSchemaToolbar();
+ return {
+ ...linkageRulesProps,
+ };
+ },
+ },
{
name: 'secondConFirm',
Component: SecondConFirm,
diff --git a/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx b/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx
index bfffdcbee2..1708fbc8ad 100644
--- a/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/disassociate/disassociateActionSettings.tsx
@@ -32,11 +32,9 @@ export const disassociateActionSettings = new SchemaSettings({
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useComponentProps() {
- const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
- collectionName: name,
};
},
},
diff --git a/packages/core/client/src/modules/actions/expand-collapse/expendableActionSettings.tsx b/packages/core/client/src/modules/actions/expand-collapse/expendableActionSettings.tsx
index be6e5a8c9d..d8b5f45f79 100644
--- a/packages/core/client/src/modules/actions/expand-collapse/expendableActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/expand-collapse/expendableActionSettings.tsx
@@ -14,7 +14,7 @@ import { useDesignable } from '../../..';
import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
-import { SchemaSettingsModalItem } from '../../../schema-settings';
+import { SchemaSettingsModalItem, SchemaSettingsLinkageRules } from '../../../schema-settings';
function ButtonEditor() {
const field = useField();
@@ -110,6 +110,17 @@ export const expendableActionSettings = new SchemaSettings({
return buttonEditorProps;
},
},
+ {
+ name: 'linkageRules',
+ Component: SchemaSettingsLinkageRules,
+ useComponentProps() {
+ const { linkageRulesProps } = useSchemaToolbar();
+
+ return {
+ ...linkageRulesProps,
+ };
+ },
+ },
{
name: 'remove',
sort: 100,
diff --git a/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx b/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
index c5a0cb87c8..34c51a0556 100644
--- a/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/link/customizeLinkActionSettings.tsx
@@ -11,10 +11,9 @@ import { useField, useFieldSchema } from '@formily/react';
import _ from 'lodash';
import React, { FC } from 'react';
import { useTranslation } from 'react-i18next';
-import { useCollectionRecord, useDesignable } from '../../../';
+import { useDesignable } from '../../../';
import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
-import { useCollection_deprecated } from '../../../collection-manager';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import {
SchemaSettingsLinkageRules,
@@ -22,6 +21,7 @@ import {
SchemaSettingAccessControl,
} from '../../../schema-settings';
import { useURLAndHTMLSchema } from './useURLAndHTMLSchema';
+import { useDataBlockProps } from '../../../data-source';
export const SchemaSettingsActionLinkItem: FC = () => {
const field = useField();
@@ -94,16 +94,10 @@ export const customizeLinkActionSettings = new SchemaSettings({
{
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
- useVisible() {
- const record = useCollectionRecord();
- return !_.isEmpty(record?.data);
- },
useComponentProps() {
- const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
- collectionName: name,
};
},
},
diff --git a/packages/core/client/src/modules/actions/refresh/refreshActionSettings.tsx b/packages/core/client/src/modules/actions/refresh/refreshActionSettings.tsx
index b8b31acada..cb7c94ecb7 100644
--- a/packages/core/client/src/modules/actions/refresh/refreshActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/refresh/refreshActionSettings.tsx
@@ -10,7 +10,7 @@
import { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
import { ButtonEditor, RemoveButton, SecondConFirm } from '../../../schema-component/antd/action/Action.Designer';
-
+import { SchemaSettingsLinkageRules } from '../../../schema-settings';
export const refreshActionSettings = new SchemaSettings({
name: 'actionSettings:refresh',
items: [
@@ -22,6 +22,17 @@ export const refreshActionSettings = new SchemaSettings({
return buttonEditorProps;
},
},
+ {
+ name: 'linkageRules',
+ Component: SchemaSettingsLinkageRules,
+ useComponentProps() {
+ const { linkageRulesProps } = useSchemaToolbar();
+
+ return {
+ ...linkageRulesProps,
+ };
+ },
+ },
{
name: 'secondConFirm',
Component: SecondConFirm,
diff --git a/packages/core/client/src/modules/actions/submit/createSubmitActionSettings.tsx b/packages/core/client/src/modules/actions/submit/createSubmitActionSettings.tsx
index 34bcb7cdef..0c48ebfc7d 100644
--- a/packages/core/client/src/modules/actions/submit/createSubmitActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/submit/createSubmitActionSettings.tsx
@@ -29,6 +29,7 @@ import { useCollectionState } from '../../../schema-settings/DataTemplates/hooks
import { SchemaSettingsModalItem } from '../../../schema-settings/SchemaSettings';
import { useParentPopupRecord } from '../../variable/variablesProvider/VariablePopupRecordProvider';
import { useDataBlockProps } from '../../../data-source';
+import { SchemaSettingsLinkageRules } from '../../../schema-settings';
const Tree = connect(
AntdTree,
@@ -149,6 +150,16 @@ export const createSubmitActionSettings = new SchemaSettings({
return buttonEditorProps;
},
},
+ {
+ name: 'linkageRules',
+ Component: SchemaSettingsLinkageRules,
+ useComponentProps() {
+ const { linkageRulesProps } = useSchemaToolbar();
+ return {
+ ...linkageRulesProps,
+ };
+ },
+ },
{
name: 'secondConfirmation',
Component: SecondConFirm,
diff --git a/packages/core/client/src/modules/actions/submit/updateSubmitActionSettings.tsx b/packages/core/client/src/modules/actions/submit/updateSubmitActionSettings.tsx
index 560785611e..f1441344b4 100644
--- a/packages/core/client/src/modules/actions/submit/updateSubmitActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/submit/updateSubmitActionSettings.tsx
@@ -46,10 +46,6 @@ export const updateSubmitActionSettings = new SchemaSettings({
collectionName: name,
};
},
- useVisible() {
- const fieldSchema = useFieldSchema();
- return !fieldSchema.parent['x-initializer'].includes('bulkEditForm');
- },
},
{
name: 'secondConfirmation',
diff --git a/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx b/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
index 4e86e008d8..dbec03441c 100644
--- a/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
+++ b/packages/core/client/src/modules/actions/view-edit-popup/customizePopupActionSettings.tsx
@@ -6,17 +6,12 @@
* 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 { useSchemaToolbar } from '../../../application';
import { SchemaSettings } from '../../../application/schema-settings/SchemaSettings';
-import { useCollection_deprecated } from '../../../collection-manager';
-import { useCollection } from '../../../data-source';
import { ButtonEditor, RemoveButton } from '../../../schema-component/antd/action/Action.Designer';
import { SchemaSettingOpenModeSchemaItems } from '../../../schema-items';
import { SchemaSettingsLinkageRules, SchemaSettingAccessControl } from '../../../schema-settings';
import { useOpenModeContext } from '../../popup/OpenModeProvider';
-import { useCurrentPopupRecord } from '../../variable/variablesProvider/VariablePopupRecordProvider';
export const customizePopupActionSettings = new SchemaSettings({
name: 'actionSettings:popup',
@@ -33,18 +28,11 @@ export const customizePopupActionSettings = new SchemaSettings({
name: 'linkageRules',
Component: SchemaSettingsLinkageRules,
useComponentProps() {
- const { name } = useCollection_deprecated();
const { linkageRulesProps } = useSchemaToolbar();
return {
...linkageRulesProps,
- collectionName: name,
};
},
- useVisible() {
- const { collection } = useCurrentPopupRecord() || {};
- const currentCollection = useCollection();
- return !collection || collection?.name === currentCollection?.name;
- },
},
{
name: 'openMode',
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
index 7550324146..bc0708f2b6 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings2.test.ts
@@ -35,11 +35,16 @@ test.describe('linkage rules', () => {
// 条件:singleLineText 字段的值包含 123 时
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add condition', { exact: true }).click();
- await page.getByTestId('select-filter-field').click();
- await page.getByRole('menuitemcheckbox', { name: 'singleLineText' }).click();
- await page.getByLabel('Linkage rules').getByRole('tabpanel').getByRole('textbox').click();
- await page.getByLabel('Linkage rules').getByRole('tabpanel').getByRole('textbox').fill('123');
+ await page.getByLabel('variable-button').first().click();
+ await page.getByText('Current form').last().click();
+ await page.getByText('Current form').last().click();
+ await page.getByRole('menuitemcheckbox', { name: 'singleLineText' }).locator('div').click();
+
+ // await page.getByRole('menuitemcheckbox', { name: 'singleLineText' }).click();
+ await page.getByTestId('right-filter-field').getByRole('textbox').click();
+ await page.getByTestId('right-filter-field').getByRole('textbox').fill('123');
+ await page.getByRole('tabpanel').getByRole('textbox').last().fill('123');
// action:禁用 longText 字段
await page.getByText('Add property').click();
await page.getByTestId('select-linkage-property-field').click();
@@ -81,7 +86,7 @@ test.describe('linkage rules', () => {
// 修改第一组规则,使其条件中包含一个变量 --------------------------------------------------------------------------
// 当 singleLineText 字段的值包含 longText 字段的值时,禁用 longText 字段
await openLinkageRules();
- await page.getByLabel('variable-button').click();
+ await page.getByLabel('variable-button').last().click();
await expectSupportedVariables(page, [
'Constant',
'Current user',
@@ -136,8 +141,13 @@ test.describe('linkage rules', () => {
.getByText('Add condition', { exact: true })
.last()
.click();
- await page.getByRole('button', { name: 'Select field' }).click();
- await page.getByRole('menuitemcheckbox', { name: 'number' }).click();
+ // await page.getByRole('button', { name: 'Select field' }).click();
+
+ await page.getByTestId('left-filter-field').getByLabel('variable-button').last().click();
+ await page.getByText('Current form').last().click();
+ await page.getByText('Current form').last().click();
+ await page.getByRole('menuitemcheckbox', { name: 'number' }).locator('div').click();
+
await page.getByLabel('Linkage rules').getByRole('spinbutton').click();
await page.getByLabel('Linkage rules').getByRole('spinbutton').fill('123');
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/deprecatedVariables.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/deprecatedVariables.test.ts
index 25c80340d2..1461e81c7e 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/deprecatedVariables.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/deprecatedVariables.test.ts
@@ -22,7 +22,7 @@ test.describe('deprecated variables', () => {
await expect(page.getByLabel('variable-tag').getByText('Current record / Nickname')).toBeVisible();
// 2. 但是变量列表中是禁用状态
- await page.locator('button').filter({ hasText: /^x$/ }).click();
+ await page.locator('button').filter({ hasText: /^x$/ }).last().click();
await page.getByRole('menuitemcheckbox', { name: 'Current record right' }).hover({ position: { x: 40, y: 12 } });
await expect(page.getByRole('tooltip', { name: 'This variable has been deprecated' })).toBeVisible();
await expect(page.getByRole('menuitemcheckbox', { name: 'Current record right' })).toHaveClass(
@@ -45,11 +45,11 @@ test.describe('deprecated variables', () => {
await page.getByLabel('Linkage rules').getByText('Linkage rules').click();
// 3. 当设置为其它变量后,再次打开,变量列表中的弃用变量不再显示
- await page.locator('button').filter({ hasText: /^x$/ }).click();
+ await page.locator('button').filter({ hasText: /^x$/ }).last().click();
await expect(page.getByRole('menuitemcheckbox', { name: 'Current form right' })).toHaveCount(1);
await page.getByRole('menuitemcheckbox', { name: 'Current form right' }).click();
await page.getByRole('menuitemcheckbox', { name: 'Nickname' }).click();
- await expect(page.getByLabel('variable-tag').getByText('Current form / Nickname')).toBeVisible();
+ await expect(page.getByLabel('variable-tag').getByText('Current form / Nickname').last()).toBeVisible();
// 清空表达式
await page.getByLabel('textbox').clear();
await page.getByRole('button', { name: 'OK', exact: true }).click();
@@ -58,7 +58,7 @@ test.describe('deprecated variables', () => {
await page.getByLabel('block-item-CardItem-users-form').hover();
await page.getByLabel('designer-schema-settings-CardItem-blockSettings:editForm-users').hover();
await page.getByRole('menuitem', { name: 'Linkage rules' }).click();
- await page.locator('button').filter({ hasText: /^x$/ }).click();
+ await page.locator('button').filter({ hasText: /^x$/ }).last().click();
await expect(page.getByRole('menuitemcheckbox', { name: 'Current record right' })).toBeHidden();
// 使下拉菜单消失
await page.getByLabel('Linkage rules').getByText('Linkage rules').click();
diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/schemaInitializer.test.ts
index 7db78e37dc..b137ecea4f 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/schemaInitializer.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-edit/schemaInitializer.test.ts
@@ -86,7 +86,6 @@ test.describe('configure fields', () => {
await page.getByRole('menuitem', { name: 'manyToOne3' }).click();
await page.mouse.move(600, 0);
await page.reload();
-
await expect(page.getByLabel('block-item-CollectionField-general-form-general.manyToOne1-manyToOne1')).toHaveText(
`manyToOne1:${record.manyToOne1.id}`,
);
diff --git a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts
index 506094cbc0..310774c18b 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/grid-card/__e2e__/schemaInitializer.test.ts
@@ -42,6 +42,7 @@ test.describe('where grid card block can be added', () => {
await page.getByLabel('schema-initializer-Grid-').nth(1).hover();
await page.getByRole('menuitem', { name: 'Role name' }).click();
await page.mouse.move(300, 0);
+ await page.reload();
await expect(page.getByText('Root')).toBeVisible();
await expect(page.getByText('Admin')).toBeVisible();
await expect(page.getByText('Member')).toBeVisible();
diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/actions/linkage.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/actions/linkage.test.ts
index 8c2a24c863..7ae4fa7a95 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/actions/linkage.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/actions/linkage.test.ts
@@ -30,7 +30,6 @@ test('action linkage by row data', async ({ page, mockPage }) => {
// 添加其他你需要的样式属性
};
});
-
expect(adminEditActionStyle.opacity).not.toBe('0.1');
expect(rootEditActionStyle.opacity).not.toBe('1');
});
diff --git a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts
index f51e03f878..ed1dda956b 100644
--- a/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts
+++ b/packages/core/client/src/modules/blocks/data-blocks/table/__e2e__/schemaSettings.test.ts
@@ -316,7 +316,8 @@ test.describe('actions schema settings', () => {
// 添加一个条件:ID 等于 1
await page.getByText('Add condition', { exact: true }).click();
- await page.getByTestId('select-filter-field').click();
+ await page.getByTestId('left-filter-field').getByLabel('variable-button').click();
+ await page.getByText('Current record').last().click();
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
await page.getByRole('spinbutton').click();
await page.getByRole('spinbutton').fill('1');
@@ -340,7 +341,8 @@ test.describe('actions schema settings', () => {
// 添加一个条件:ID 等于 1
await page.getByRole('tabpanel').getByText('Add condition', { exact: true }).last().click();
- await page.getByRole('button', { name: 'Select field' }).click();
+ await page.getByTestId('left-filter-field').getByLabel('variable-button').last().click();
+ await page.getByText('Current record').last().click();
await page.getByRole('menuitemcheckbox', { name: 'ID', exact: true }).click();
await page.getByRole('spinbutton').click();
await page.getByRole('spinbutton').fill('1');
@@ -902,7 +904,6 @@ test.describe('actions schema settings', () => {
await page.getByRole('menuitem', { name: 'Submit' }).click();
await page.mouse.move(300, 0);
await page.getByRole('button', { name: 'Submit' }).click();
-
await page.getByLabel('designer-schema-settings-CardItem-TableBlockDesigner-treeCollection').hover();
await page.getByRole('menuitem', { name: 'Tree table' }).click();
@@ -928,6 +929,7 @@ test.describe('actions schema settings', () => {
await page.getByLabel('schema-initializer-Grid-form:').hover();
await page.getByRole('menuitem', { name: 'Parent', exact: true }).click();
await page.mouse.move(300, 0);
+ await page.reload();
await expect(
page
.getByLabel('block-item-CollectionField-')
diff --git a/packages/core/client/src/modules/fields/component/Select/__e2e__/selectOptionsInLinkageRule.test.ts b/packages/core/client/src/modules/fields/component/Select/__e2e__/selectOptionsInLinkageRule.test.ts
index 0684ebf21a..5de86a8bd6 100644
--- a/packages/core/client/src/modules/fields/component/Select/__e2e__/selectOptionsInLinkageRule.test.ts
+++ b/packages/core/client/src/modules/fields/component/Select/__e2e__/selectOptionsInLinkageRule.test.ts
@@ -27,7 +27,8 @@ test.describe('options of Select field in linkage rule', () => {
await page.getByRole('switch', { name: 'On Off' }).click();
await page.getByRole('button', { name: 'OK' }).click();
await page.reload();
- await expect(page.getByRole('option', { name: 'option2' })).toBeVisible();
+ await page.getByLabel('block-item-CollectionField-').click();
+ await expect(page.getByRole('option', { name: 'option2' }).last()).toBeVisible();
await expect(page.getByRole('option', { name: 'option3' })).toBeVisible();
});
});
diff --git a/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts b/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts
index 5efa1553bc..01be31da31 100644
--- a/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts
+++ b/packages/core/client/src/modules/popup/__e2e__/schemaInitializer1.test.ts
@@ -215,7 +215,7 @@ test.describe('where to open a popup and what can be added to it', () => {
await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible();
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
- await page.getByRole('menuitem', { name: 'Table right' }).hover();
+ await page.getByRole('menuitem', { name: 'Table right' }).click();
await expect(page.getByRole('menuitem', { name: 'Associated records' })).toHaveCount(1);
await page.getByRole('menuitem', { name: 'Associated records' }).hover();
await page.getByRole('menuitem', { name: 'One to many' }).click();
@@ -282,7 +282,7 @@ test.describe('where to open a popup and what can be added to it', () => {
await expect(page.getByLabel('block-item-CardItem-users-')).toBeVisible();
await page.getByLabel('schema-initializer-Grid-popup:common:addBlock-general').hover();
- await page.getByRole('menuitem', { name: 'Table right' }).hover();
+ await page.getByRole('menuitem', { name: 'Table right' }).click();
await expect(page.getByRole('menuitem', { name: 'Associated records' })).toHaveCount(1);
await page.getByRole('menuitem', { name: 'Associated records' }).hover();
await page.getByRole('menuitem', { name: 'One to many' }).click();
diff --git a/packages/core/client/src/modules/variable/__e2e__/basic.test.ts b/packages/core/client/src/modules/variable/__e2e__/basic.test.ts
index 55d755cb8d..7768b268c0 100644
--- a/packages/core/client/src/modules/variable/__e2e__/basic.test.ts
+++ b/packages/core/client/src/modules/variable/__e2e__/basic.test.ts
@@ -18,7 +18,7 @@ test.describe('variables', () => {
await page.getByLabel('action-Action.Link-View-view-').hover();
await page.getByLabel('designer-schema-settings-Action.Link-actionSettings:view-users').hover();
await page.getByRole('menuitem', { name: 'Linkage rules' }).click();
- await page.getByLabel('variable-button').click();
+ await page.getByTestId('left-filter-field').getByLabel('variable-button').click();
// 2. 断言应该显示的变量
['Constant', 'Current user', 'Current role', 'API token', 'Date variables', 'Current record'].forEach(
diff --git a/packages/core/client/src/modules/variable/__e2e__/currentRecord.test.ts b/packages/core/client/src/modules/variable/__e2e__/currentRecord.test.ts
index 01a1256d2c..59f2f00f24 100644
--- a/packages/core/client/src/modules/variable/__e2e__/currentRecord.test.ts
+++ b/packages/core/client/src/modules/variable/__e2e__/currentRecord.test.ts
@@ -22,14 +22,14 @@ test.describe('variable: Current Record', () => {
await page.getByRole('menuitem', { name: 'Linkage rules' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add condition', { exact: true }).click();
- await page.getByLabel('variable-button').click();
+ await page.getByLabel('variable-button').first().click();
// 当前表单中应该包含 “Nickname” 字段
await page.getByRole('menuitemcheckbox', { name: 'Current form right' }).click();
await page.getByRole('menuitemcheckbox', { name: 'Nickname' }).click();
// 当前对象中应该包含 “Role UID” 字段
- await page.getByLabel('variable-button').click();
+ await page.getByLabel('variable-button').first().click();
await page.getByText('Current object').click();
await page.getByRole('menuitemcheckbox', { name: 'Current object right' }).click();
await page.getByRole('menuitemcheckbox', { name: 'Role UID' }).click();
@@ -43,12 +43,12 @@ test.describe('variable: Current Record', () => {
await page.getByRole('menuitem', { name: 'Linkage rules' }).click();
await page.getByRole('button', { name: 'plus Add linkage rule' }).click();
await page.getByText('Add condition', { exact: true }).click();
- await page.getByLabel('variable-button').click();
+ await page.getByLabel('variable-button').first().click();
// 当前记录中应该包含 “Nickname” 字段
await page.getByRole('menuitemcheckbox', { name: 'Current record right' }).click();
await page.getByRole('menuitemcheckbox', { name: 'Nickname' }).click();
- await page.getByLabel('variable-button').click();
+ await page.getByLabel('variable-button').first().click();
// 当前对象中应该包含 “Role UID” 字段
await page.getByRole('menuitemcheckbox', { name: 'Current object right' }).click();
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 53c0f11b22..38b6802b4d 100644
--- a/packages/core/client/src/schema-component/antd/action/Action.tsx
+++ b/packages/core/client/src/schema-component/antd/action/Action.tsx
@@ -49,6 +49,7 @@ import { useGetAriaLabelOfAction } from './hooks/useGetAriaLabelOfAction';
import { ActionContextProps, ActionProps, ComposedAction } from './types';
import { linkageAction, setInitialActionState } from './utils';
import { NAMESPACE_UI_SCHEMA } from '../../../i18n/constant';
+import { BlockContext } from '../../../block-provider/BlockProvider';
// 这个要放到最下面,否则会导致前端单测失败
import { useApp } from '../../../application';
@@ -96,7 +97,9 @@ export const Action: ComposedAction = withDynamicSchemaProps(
const { designable } = useDesignable();
const tarComponent = useComponent(component) || component;
const variables = useVariables();
- const localVariables = useLocalVariables({ currentForm: { values: recordData, readPretty: false } as any });
+ const localVariables = useLocalVariables({
+ currentForm: { values: recordData, readPretty: false } as any,
+ });
const { visibleWithURL, setVisibleWithURL } = usePopupUtils();
const { setSubmitted } = useActionContext();
const { getAriaLabel } = useGetAriaLabelOfAction(title);
@@ -120,6 +123,7 @@ export const Action: ComposedAction = withDynamicSchemaProps(
condition: v.condition,
variables,
localVariables,
+ conditionType: v.conditionType,
},
app.jsonLogic,
);
@@ -155,36 +159,38 @@ export const Action: ComposedAction = withDynamicSchemaProps(
}, [onClick, fieldSchema, getAllDataBlocks]);
return (
-
{JSON.stringify(field.value, null, 2)}+ {children} + > + ); +}); + +const useFilterActionProps = (): FilterActionProps => { + const field = useField
{JSON.stringify(field.value, null, 2)}+ {children} + > + ); +}); + +const useFilterActionProps = (): FilterActionProps => { + const field = useField
diff --git a/packages/core/client/src/schema-component/antd/linkageFilter/index.md b/packages/core/client/src/schema-component/antd/linkageFilter/index.md
new file mode 100644
index 0000000000..9cac8a16ed
--- /dev/null
+++ b/packages/core/client/src/schema-component/antd/linkageFilter/index.md
@@ -0,0 +1,18 @@
+# LinkageFilter
+
+用于前端联动规则中,用作条件配置
+
+```ts
+type FilterActionProps
+
diff --git a/packages/core/client/src/schema-component/antd/linkageFilter/index.ts b/packages/core/client/src/schema-component/antd/linkageFilter/index.ts
new file mode 100644
index 0000000000..650c85eb26
--- /dev/null
+++ b/packages/core/client/src/schema-component/antd/linkageFilter/index.ts
@@ -0,0 +1,10 @@
+/**
+ * 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 './LinkageFilter';
diff --git a/packages/core/client/src/schema-component/antd/linkageFilter/useOperators.ts b/packages/core/client/src/schema-component/antd/linkageFilter/useOperators.ts
new file mode 100644
index 0000000000..12a5e2328a
--- /dev/null
+++ b/packages/core/client/src/schema-component/antd/linkageFilter/useOperators.ts
@@ -0,0 +1,34 @@
+/**
+ * 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 { useCollection_deprecated, useCollectionManager_deprecated } from '../../../collection-manager';
+import { useMemo } from 'react';
+
+/**
+ * 获取当前字段所支持的操作符列表
+ * @returns
+ */
+export const useOperatorList = (): any[] => {
+ const schema = useFieldSchema();
+ const { name } = useCollection_deprecated();
+ const { getCollectionFields, getInterface } = useCollectionManager_deprecated();
+
+ const res = useMemo(() => {
+ const fieldInterface = schema['x-designer-props']?.interface;
+ const collectionFields = getCollectionFields(name);
+ if (fieldInterface) {
+ return getInterface(fieldInterface)?.filterable?.operators || [];
+ }
+ const field = collectionFields.find((item) => item.name === schema.name);
+ const ops = getInterface(field?.interface)?.filterable?.operators || [];
+ return ops.filter((o) => typeof o.visible !== 'function' || o.visible(field));
+ }, [schema.name]);
+ return res;
+};
diff --git a/packages/core/client/src/schema-component/antd/linkageFilter/useValues.ts b/packages/core/client/src/schema-component/antd/linkageFilter/useValues.ts
new file mode 100644
index 0000000000..6f2c5463ed
--- /dev/null
+++ b/packages/core/client/src/schema-component/antd/linkageFilter/useValues.ts
@@ -0,0 +1,141 @@
+/**
+ * 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 { useField } from '@formily/react';
+import { merge } from '@formily/shared';
+import { cloneDeep, last, uniqBy } from 'lodash';
+import { useCallback, useContext, useEffect } from 'react';
+import { FilterContext } from './context';
+
+interface UseValuesReturn {
+ fields: any[];
+ collectionField: any;
+ dataIndex: string[];
+ operators: any[];
+ operator: any;
+ schema: any;
+ value: any;
+ setDataIndex: (dataIndex: string[]) => void;
+ setOperator: (operatorValue: string) => void;
+ setRightValue: (value: any) => void;
+ setLeftValue: (value: any) => void;
+ leftVar: any;
+ rightVar: any;
+}
+
+const findOption = (str, options) => {
+ if (!str) return null;
+ const match = str.match(/\{\{\$(.*?)\}\}/);
+ if (!match) return null;
+
+ const [firstKey, ...subKeys] = match[1].split('.'); // 拆分层级
+ const keys = [`$${firstKey}`, ...subKeys]; // 第一层保留 `$`,后续不带 `$`
+
+ let currentOptions = options;
+ let option = null;
+ for (const key of keys) {
+ option = currentOptions.find((opt) => opt.value === key);
+ if (!option) return null;
+
+ // 进入下一层 children 查找
+ if (Array.isArray(option.children) || option.isLeaf === false) {
+ currentOptions = option.children;
+ } else {
+ return option; // 没有 children 直接返回
+ }
+ }
+
+ return option;
+};
+const operators = [
+ { label: '{{t("is empty")}}', value: '$empty', noValue: true },
+ { label: '{{t("is not empty")}}', value: '$notEmpty', noValue: true },
+];
+export const useValues = (): UseValuesReturn => {
+ const field = useField