diff --git a/packages/core/client/src/block-provider/FormBlockProvider.tsx b/packages/core/client/src/block-provider/FormBlockProvider.tsx index 9c101c144..7ac794662 100644 --- a/packages/core/client/src/block-provider/FormBlockProvider.tsx +++ b/packages/core/client/src/block-provider/FormBlockProvider.tsx @@ -3,7 +3,7 @@ import { RecursionField, Schema, useField, useFieldSchema } from '@formily/react import { Spin } from 'antd'; import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react'; import { useCollection_deprecated } from '../collection-manager'; -import { useCollectionParentRecordData, useCollectionRecord } from '../data-source'; +import { CollectionRecord, useCollectionParentRecordData, useCollectionRecord } from '../data-source'; import { RecordProvider, useRecord } from '../record-provider'; import { useActionContext, useDesignable } from '../schema-component'; import { Templates as DataTemplateSelect } from '../schema-component/antd/form-v2/Templates'; @@ -11,7 +11,20 @@ import { BlockProvider, useBlockRequestContext } from './BlockProvider'; import { TemplateBlockProvider } from './TemplateBlockProvider'; import { FormActiveFieldsProvider } from './hooks/useFormActiveFields'; -export const FormBlockContext = createContext({}); +export const FormBlockContext = createContext<{ + form?: any; + type?: 'update' | 'create'; + action?: string; + field?: any; + service?: any; + resource?: any; + updateAssociationValues?: any; + formBlockRef?: any; + collectionName?: string; + params?: any; + formRecord?: CollectionRecord; + [key: string]: any; +}>({}); FormBlockContext.displayName = 'FormBlockContext'; const InternalFormBlockProvider = (props) => { @@ -28,7 +41,7 @@ const InternalFormBlockProvider = (props) => { const { resource, service, updateAssociationValues } = useBlockRequestContext(); const formBlockRef = useRef(); const record = useCollectionRecord(); - const formBlockValue = useMemo(() => { + const formBlockValue: any = useMemo(() => { return { ...ctx, params, @@ -42,8 +55,9 @@ const InternalFormBlockProvider = (props) => { updateAssociationValues, formBlockRef, collectionName: collection, + formRecord: record, }; - }, [action, field, form, params, resource, service, updateAssociationValues]); + }, [action, collection, ctx, field, form, params, record, resource, service, updateAssociationValues]); if (service.loading && Object.keys(form?.initialValues)?.length === 0 && action) { return ; diff --git a/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/schemaSettings.test.ts index 140f6c45f..b43b71dcb 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/schemaSettings.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/schemaSettings.test.ts @@ -1,5 +1,6 @@ -import { expectSettingsMenu, test } from '@nocobase/test/e2e'; +import { expectSettingsMenu, test, expect } from '@nocobase/test/e2e'; import { createTable } from './utils'; +import { tableSelectorDataScopeVariable } from './templatesOfBug'; test.describe('table data selector schema settings', () => { test('supported options', async ({ page, mockPage }) => { @@ -11,6 +12,126 @@ test.describe('table data selector schema settings', () => { supportedOptions: ['Set the data scope', 'Set default sorting rules', 'Records per page', 'Delete'], }); }); + + test('should have a current form variable', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(tableSelectorDataScopeVariable).waitForInit(); + const record = await mockRecord('table-selector-data-scope-variable'); + await nocoPage.goto(); + + await page.getByLabel('action-Action.Link-View-view-table-selector-data-scope-variable-table-0').click(); + await page.getByTestId('select-data-picker').click(); + await page + .getByTestId('drawer-AssociationField.Selector-table-selector-data-scope-variable-Select record') + .getByLabel('block-item-CardItem-table-') + .hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:tableSelector-table-selector-').hover(); + await page.getByRole('menuitem', { name: 'Set the data scope' }).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.getByTestId('select-filter-operator').click(); + await page.getByRole('option', { name: 'is', exact: true }).click(); + await page.getByLabel('variable-button').click(); + await page.getByRole('menuitemcheckbox', { name: 'Current form right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'singleLineText' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // 保存数据范围之后,表格选择器中应该只显示一条数据,且该数据与页面表格的第一行数据相同 + await expect( + page + .getByTestId('drawer-AssociationField.Selector-table-selector-data-scope-variable-Select record') + .getByLabel('block-item-CardItem-table-') + .getByRole('row'), + ).toHaveCount(2); // 这里之所以是 2,是因为表头也是一个 row + await expect( + page + .getByTestId('drawer-AssociationField.Selector-table-selector-data-scope-variable-Select record') + .getByLabel('block-item-CardItem-table-') + .getByText(record['singleLineText']), + ).toBeVisible(); + }); + + test('should have a current object variable', async ({ page, mockPage, mockRecord }) => { + const nocoPage = await mockPage(tableSelectorDataScopeVariable).waitForInit(); + const record = await mockRecord('table-selector-data-scope-variable'); + await nocoPage.goto(); + + await page.getByLabel('action-Action.Link-View-view-table-selector-data-scope-variable-table-0').click(); + + // 1. 将一个关系字段的 Select 组件改为子表单 + await page + .getByLabel( + 'block-item-CollectionField-table-selector-data-scope-variable-form-table-selector-data-scope-variable.manyToMany-manyToMany', + { exact: true }, + ) + .hover(); + await page + .getByLabel( + 'designer-schema-settings-CollectionField-fieldSettings:FormItem-table-selector-data-scope-variable-table-selector-data-scope-variable.manyToMany', + { exact: true }, + ) + .hover(); + await page.getByText('Field componentRecord picker').click(); + await page.getByRole('option', { name: 'Sub-form', exact: true }).click(); + // 使菜单消失 + await page.getByRole('menuitem', { name: 'Delete' }).hover(); + await page.mouse.move(-300, 0); + + // 2. 在子表单中创建一个关系字段,并切换成数据选择器组件 + await page.getByLabel('schema-initializer-Grid-form:').first().hover(); + await page.getByRole('menuitem', { name: 'manyToMany' }).click(); + await page.getByRole('menuitem', { name: 'singleLineText' }).click(); + await page.getByLabel('block-item-CollectionField-').nth(1).hover(); + await page + .getByLabel('designer-schema-settings-CollectionField-fieldSettings:FormItem-table-selector-') + .nth(1) + .hover(); + await page.getByRole('menuitem', { name: 'Field component Select' }).click(); + await page.getByRole('option', { name: 'Record picker' }).click(); + // 使菜单消失 + await page.getByRole('menuitem', { name: 'Delete' }).hover(); + await page.mouse.move(-300, 0); + + await page.getByLabel('block-item-CollectionField-').nth(1).click(); + + // 3. 创建 Table 区块 + await page.getByLabel('schema-initializer-Grid-popup').hover(); + await page.getByRole('menuitem', { name: 'form Table' }).click(); + + // 4. 设置数据范围 + await page.getByLabel('block-item-CardItem-table-selector-data-scope-variable-table-selector').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:tableSelector-table-selector-').hover(); + await page.getByRole('menuitem', { name: 'Set the data scope' }).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.getByTestId('select-filter-operator').click(); + await page.getByRole('option', { name: 'is', exact: true }).click(); + await page.getByLabel('variable-button').click(); + await page.getByRole('menuitemcheckbox', { name: 'Current object right' }).click(); + await page.getByRole('menuitemcheckbox', { name: 'singleLineText' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + + // Table 中显示 singleLineText 字段 + await page.getByLabel('schema-initializer-TableV2.').hover(); + await page.getByRole('menuitem', { name: 'singleLineText' }).click(); + await page.mouse.move(300, 0); + + // 保存数据范围之后,表格选择器中应该只显示一条数据,且该数据与页面表格的第一行数据相同 + await expect( + page.getByLabel('block-item-CardItem-table-selector-data-scope-variable-table-selector').getByRole('row'), + ).toHaveCount(2); // 这里之所以是 2,是因为表头也是一个 row + await expect( + page + .getByLabel('block-item-CardItem-table-selector-data-scope-variable-table-selector') + .getByRole('row') + .getByText(record['manyToMany'][0]['singleLineText']), + ).toBeVisible(); + }); }); async function showSettingsMenu(page) { diff --git a/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/templatesOfBug.ts index e69de29bb..c649e89e5 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/templatesOfBug.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/table-selector/__e2e__/templatesOfBug.ts @@ -0,0 +1,851 @@ +import { PageConfig } from '@nocobase/test/e2e'; + +const commonCollections = [ + { + name: 'table-selector-data-scope-variable', + fields: [ + { + name: 'manyToMany', + interface: 'm2m', + target: 'table-selector-data-scope-variable', + }, + { + name: 'singleLineText', + interface: 'input', + }, + ], + }, +]; + +export const tableSelectorDataScopeVariable: PageConfig = { + collections: commonCollections, + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + ij2wf9hi0si: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'BlockInitializers', + properties: { + jdz50aeuduh: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + ij66b8u5o5m: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + '5j0kimft2lz': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'TableBlockProvider', + 'x-acl-action': 'table-selector-data-scope-variable:list', + 'x-decorator-props': { + collection: 'table-selector-data-scope-variable', + dataSource: 'main', + resource: 'table-selector-data-scope-variable', + action: 'list', + params: { + pageSize: 20, + }, + rowKey: 'id', + showIndex: true, + dragSort: false, + disableTemplate: false, + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:table', + 'x-component': 'CardItem', + 'x-filter-targets': [], + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'TableActionInitializers', + 'x-component': 'ActionBar', + 'x-component-props': { + style: { + marginBottom: 'var(--nb-spacing)', + }, + }, + 'x-uid': 'vdvzzbfp53e', + 'x-async': false, + 'x-index': 1, + }, + ttcsp9slh2z: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'array', + 'x-initializer': 'TableColumnInitializers', + 'x-component': 'TableV2', + 'x-component-props': { + rowKey: 'id', + rowSelection: { + type: 'checkbox', + }, + useProps: '{{ useTableBlockProps }}', + }, + properties: { + actions: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("Actions") }}', + 'x-action-column': 'actions', + 'x-decorator': 'TableV2.Column.ActionBar', + 'x-component': 'TableV2.Column', + 'x-designer': 'TableV2.ActionColumnDesigner', + 'x-initializer': 'TableActionColumnInitializers', + properties: { + f1gruzhfm8r: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-decorator': 'DndContext', + 'x-component': 'Space', + 'x-component-props': { + split: '|', + }, + properties: { + esrrc38rvqe: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View") }}', + 'x-action': 'view', + 'x-toolbar': 'ActionSchemaToolbar', + 'x-settings': 'actionSettings:view', + 'x-component': 'Action.Link', + 'x-component-props': { + openMode: 'drawer', + }, + 'x-decorator': 'ACLActionProvider', + 'x-designer-props': { + linkageAction: true, + }, + properties: { + drawer: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{ t("View record") }}', + 'x-component': 'Action.Container', + 'x-component-props': { + className: 'nb-action-popup', + }, + properties: { + tabs: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Tabs', + 'x-component-props': {}, + 'x-initializer': 'TabPaneInitializers', + properties: { + tab1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + title: '{{t("Details")}}', + 'x-component': 'Tabs.TabPane', + 'x-designer': 'Tabs.Designer', + 'x-component-props': {}, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'RecordBlockInitializers', + properties: { + zhykdvqpa7k: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + luhz7fq6529: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + gecihd85864: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: false, + }, + 'x-acl-action': + 'table-selector-data-scope-variable:update', + 'x-decorator': 'FormBlockProvider', + 'x-decorator-props': { + useSourceId: '{{ useSourceIdFromParentRecord }}', + useParams: '{{ useParamsFromRecord }}', + action: 'get', + dataSource: 'main', + resource: 'table-selector-data-scope-variable', + collection: 'table-selector-data-scope-variable', + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:editForm', + 'x-component': 'CardItem', + 'x-component-props': {}, + properties: { + '3h121b8k9ey': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'FormV2', + 'x-component-props': { + useProps: '{{ useFormBlockProps }}', + }, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'FormItemInitializers', + properties: { + t4tin6z9nq1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + xb7fdug52ex: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + manyToMany: { + 'x-uid': 'p0km7m8dnj4', + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': + 'FormItemSchemaToolbar', + 'x-settings': + 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': + 'table-selector-data-scope-variable.manyToMany', + 'x-component-props': { + fieldNames: { + label: 'id', + value: 'id', + }, + mode: 'Picker', + }, + properties: { + guunasm2a3h: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': + 'AssociationField.Selector', + title: + '{{ t("Select record") }}', + 'x-component-props': { + className: + 'nb-record-picker-selector', + }, + 'x-index': 1, + properties: { + grid: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': + 'TableSelectorInitializers', + properties: { + '0uui41pxdye': { + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-component': + 'Grid.Row', + properties: { + '476w75depv3': { + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-component': + 'Grid.Col', + properties: { + alibfkv2g0v: { + 'x-uid': + 'y8f4lswt52q', + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-acl-action': + 'table-selector-data-scope-variable:list', + 'x-decorator': + 'TableSelectorProvider', + 'x-decorator-props': + { + collection: + 'table-selector-data-scope-variable', + resource: + 'table-selector-data-scope-variable', + dataSource: + 'main', + action: + 'list', + params: { + pageSize: 20, + filter: + {}, + }, + rowKey: + 'id', + }, + 'x-toolbar': + 'BlockSchemaToolbar', + 'x-settings': + 'blockSettings:tableSelector', + 'x-component': + 'CardItem', + properties: { + rblwp47r7fz: { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + 'x-initializer': + 'TableActionInitializers', + 'x-component': + 'ActionBar', + 'x-component-props': + { + style: { + marginBottom: + 'var(--nb-spacing)', + }, + }, + 'x-uid': + 'ubog2cks3ay', + 'x-async': + false, + 'x-index': 1, + }, + value: { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'array', + 'x-initializer': + 'TableColumnInitializers', + 'x-component': + 'TableV2.Selector', + 'x-component-props': + { + rowSelection: + { + type: 'checkbox', + }, + useProps: + '{{ useTableSelectorProps }}', + }, + properties: + { + jryz1oqazsj: + { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + title: + '{{ t("Actions") }}', + 'x-decorator': + 'TableV2.Column.ActionBar', + 'x-component': + 'TableV2.Column', + 'x-designer': + 'TableV2.ActionColumnDesigner', + 'x-initializer': + 'TableActionColumnInitializers', + 'x-action-column': + 'actions', + properties: + { + pkzvqfi6lr5: + { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + 'x-decorator': + 'DndContext', + 'x-component': + 'Space', + 'x-component-props': + { + split: + '|', + }, + properties: + { + xffx2jx6u7q: + { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + title: + '{{ t("View") }}', + 'x-action': + 'view', + 'x-toolbar': + 'ActionSchemaToolbar', + 'x-settings': + 'actionSettings:view', + 'x-component': + 'Action.Link', + 'x-component-props': + { + openMode: + 'drawer', + }, + 'x-decorator': + 'ACLActionProvider', + 'x-designer-props': + { + linkageAction: + true, + }, + properties: + { + drawer: + { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + title: + '{{ t("View record") }}', + 'x-component': + 'Action.Container', + 'x-component-props': + { + className: + 'nb-action-popup', + }, + properties: + { + tabs: { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + 'x-component': + 'Tabs', + 'x-component-props': + {}, + 'x-initializer': + 'TabPaneInitializers', + properties: + { + tab1: { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + title: + '{{t("Details")}}', + 'x-component': + 'Tabs.TabPane', + 'x-designer': + 'Tabs.Designer', + 'x-component-props': + {}, + properties: + { + grid: { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + 'x-component': + 'Grid', + 'x-initializer': + 'RecordBlockInitializers', + 'x-uid': + 'wkqrpvcqiih', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + '2lzui9z88st', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + 'ee4zj3qx2ip', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + 'l5ew3g2ka6s', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + '0m2i5xxfw1k', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + 'zm42p4adruu', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + '4ybzswir3zr', + 'x-async': + false, + 'x-index': 2, + }, + d51klxxphw4: + { + _isJSONSchemaObject: + true, + version: + '2.0', + type: 'void', + 'x-decorator': + 'TableV2.Column.Decorator', + 'x-toolbar': + 'TableColumnSchemaToolbar', + 'x-settings': + 'fieldSettings:TableColumn', + 'x-component': + 'TableV2.Column', + properties: + { + singleLineText: + { + _isJSONSchemaObject: + true, + version: + '2.0', + 'x-collection-field': + 'table-selector-data-scope-variable.singleLineText', + 'x-component': + 'CollectionField', + 'x-component-props': + { + ellipsis: + true, + }, + 'x-read-pretty': + true, + 'x-decorator': + null, + 'x-decorator-props': + { + labelStyle: + { + display: + 'none', + }, + }, + 'x-uid': + 'n069twt8nsc', + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + '51p2r7zlo9k', + 'x-async': + false, + 'x-index': 3, + }, + }, + 'x-uid': + 'gkbturli19t', + 'x-async': + false, + 'x-index': 2, + }, + }, + 'x-async': + false, + 'x-index': 1, + }, + }, + 'x-uid': + 't45on50ncwe', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9hzvnye1ntr', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'k2bdu4w8zz2', + 'x-async': false, + 'x-index': 1, + }, + footer: { + _isJSONSchemaObject: true, + version: '2.0', + 'x-component': + 'Action.Container.Footer', + 'x-component-props': {}, + properties: { + actions: { + _isJSONSchemaObject: + true, + version: '2.0', + type: 'void', + 'x-component': + 'ActionBar', + 'x-component-props': {}, + properties: { + submit: { + _isJSONSchemaObject: + true, + version: '2.0', + title: + '{{ t("Submit") }}', + 'x-action': + 'submit', + 'x-component': + 'Action', + 'x-toolbar': + 'ActionSchemaToolbar', + 'x-settings': + 'actionSettings:updateSubmit', + 'x-component-props': + { + type: 'primary', + htmlType: + 'submit', + useProps: + '{{ usePickActionProps }}', + }, + 'x-uid': + 'n6qpnb48sbd', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '92iud7xsva7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '3c8prk8jgoh', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '41hvryuv2jy', + 'x-async': false, + }, + }, + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'qbnfti92f1t', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4dx0hfhj9mj', + 'x-async': false, + 'x-index': 1, + }, + '23d5tg85dmy': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + wwivbgmqgly: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + singleLineText: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': + 'FormItemSchemaToolbar', + 'x-settings': + 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': + 'table-selector-data-scope-variable.singleLineText', + 'x-component-props': {}, + 'x-uid': 'sj6aet9kqxc', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '9cj7a3ivw6b', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '5w0lqwa932g', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'gmbrw8r2h2s', + 'x-async': false, + 'x-index': 1, + }, + gi40rgo7rbw: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'UpdateFormActionInitializers', + 'x-component': 'ActionBar', + 'x-component-props': { + layout: 'one-column', + style: { + marginTop: 24, + }, + }, + 'x-uid': 'go3p2x3eo9j', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '5wir035vnz7', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'r82q143nugf', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'rqwpj88fpss', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4yfu43yq0ff', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '1xvy1k1xpig', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ip9pwu9kuf0', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'h9iowhtt6mu', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'so8ptulb3b0', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'lcy4ohio47t', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'oh16739fgf8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ut6738nt9in', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '4e89got7e7b', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': '5yt30cpknsy', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '0s3jvo8y7y3', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'irunx7mpta6', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': '8es0fh04717', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'hwlep783jqy', + 'x-async': true, + 'x-index': 1, + }, +}; diff --git a/packages/core/client/src/schema-component/antd/association-field/Nester.tsx b/packages/core/client/src/schema-component/antd/association-field/Nester.tsx index af8fc1287..960c069d3 100644 --- a/packages/core/client/src/schema-component/antd/association-field/Nester.tsx +++ b/packages/core/client/src/schema-component/antd/association-field/Nester.tsx @@ -25,6 +25,7 @@ import { import { AssociationFieldContext } from './context'; import { SubFormProvider, useAssociationFieldContext } from './hooks'; import { isNewRecord, markRecordAsNew } from '../../../data-source/collection-record/isNewRecord'; +import { useCollection } from '../../../data-source'; export const Nester = (props) => { const { options } = useContext(AssociationFieldContext); @@ -48,6 +49,7 @@ export const Nester = (props) => { const ToOneNester = (props) => { const { field } = useAssociationFieldContext(); const recordV2 = useCollectionRecord(); + const collection = useCollection(); const isAllowToSetDefaultValue = useCallback( ({ form, fieldSchema, collectionField, getInterface, formBlockType }: IsAllowToSetDefaultValueParams) => { @@ -84,7 +86,7 @@ const ToOneNester = (props) => { return ( - + {props.children} @@ -101,6 +103,7 @@ const ToManyNester = observer( const { options, field, allowMultiple, allowDissociate } = useAssociationFieldContext(); const { t } = useTranslation(); const recordData = useCollectionRecordData(); + const collection = useCollection(); if (!Array.isArray(field.value)) { field.value = []; @@ -193,7 +196,7 @@ const ToManyNester = observer( )} - + diff --git a/packages/core/client/src/schema-component/antd/association-field/hooks.ts b/packages/core/client/src/schema-component/antd/association-field/hooks.ts index 0dda6bbec..cd15de8c7 100644 --- a/packages/core/client/src/schema-component/antd/association-field/hooks.ts +++ b/packages/core/client/src/schema-component/antd/association-field/hooks.ts @@ -16,6 +16,7 @@ import { getVariableName } from '../../../variables/utils/getVariableName'; import { isVariable } from '../../../variables/utils/isVariable'; import { useDesignable } from '../../hooks'; import { AssociationFieldContext } from './context'; +import { Collection } from '../../../data-source'; export const useInsertSchema = (component) => { const fieldSchema = useFieldSchema(); @@ -178,7 +179,10 @@ export const useFieldNames = (props) => { return { label: 'label', value: 'value', ...fieldNames }; }; -const SubFormContext = createContext>(null); +const SubFormContext = createContext<{ + value: any; + collection: Collection; +}>(null); SubFormContext.displayName = 'SubFormContext'; export const SubFormProvider = SubFormContext.Provider; @@ -192,8 +196,9 @@ export const SubFormProvider = SubFormContext.Provider; * @returns */ export const useSubFormValue = () => { - const context = useContext(SubFormContext); + const { value, collection } = useContext(SubFormContext) || {}; return { - formValue: context, + formValue: value, + collection, }; }; 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 645631bae..0b2f4accb 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 @@ -18,6 +18,7 @@ import { DndContext, useDesignable, useTableSize } from '../..'; import { RecordIndexProvider, RecordProvider, + useCollection, useCollection_deprecated, useCollectionParentRecordData, useSchemaInitializerRender, @@ -44,6 +45,8 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) => const { designable } = useDesignable(); const { exists, render } = useSchemaInitializerRender(schema['x-initializer'], schema['x-initializer-props']); const parentRecordData = useCollectionParentRecordData(); + const collection = useCollection(); + const columns = schema .reduceProperties((buf, s) => { if (isColumnComponent(s) && schemaInWhitelist(Object.values(s.properties || {}).pop())) { @@ -68,7 +71,7 @@ const useTableColumns = (props: { showDel?: boolean; isSubTable?: boolean }) => render: (v, record) => { const index = field.value?.indexOf(record); return ( - + diff --git a/packages/core/client/src/schema-initializer/utils.ts b/packages/core/client/src/schema-initializer/utils.ts index 9f020252e..36ec4d353 100644 --- a/packages/core/client/src/schema-initializer/utils.ts +++ b/packages/core/client/src/schema-initializer/utils.ts @@ -734,7 +734,7 @@ const recursiveParent = (schema: Schema) => { export const useCurrentSchema = (action: string, key: string, find = findSchema, rm = removeSchema) => { const { removeActiveFieldName } = useFormActiveFields() || {}; - const { form }: { form: Form } = useFormBlockContext(); + const { form }: { form?: Form } = useFormBlockContext(); let fieldSchema = useFieldSchema(); if (!fieldSchema?.['x-initializer'] && fieldSchema?.['x-decorator'] === 'FormItem') { const recursiveInitializerSchema = recursiveParent(fieldSchema); diff --git a/packages/core/client/src/schema-settings/EnableChildCollections/DynamicComponent.tsx b/packages/core/client/src/schema-settings/EnableChildCollections/DynamicComponent.tsx index 1f280b034..c1825e9d0 100644 --- a/packages/core/client/src/schema-settings/EnableChildCollections/DynamicComponent.tsx +++ b/packages/core/client/src/schema-settings/EnableChildCollections/DynamicComponent.tsx @@ -15,7 +15,6 @@ export const ChildDynamicComponent = observer( collectionField, }); const { currentObjectSettings } = useCurrentObjectVariable({ - currentCollection: collectionField?.collectionName, schema: collectionField?.uiSchema, collectionField, }); diff --git a/packages/core/client/src/schema-settings/LinkageRules/index.tsx b/packages/core/client/src/schema-settings/LinkageRules/index.tsx index 8ebf4f373..a44fbad76 100644 --- a/packages/core/client/src/schema-settings/LinkageRules/index.tsx +++ b/packages/core/client/src/schema-settings/LinkageRules/index.tsx @@ -167,7 +167,7 @@ export const FormLinkageRules = observer( ); return ( - + diff --git a/packages/core/client/src/schema-settings/SchemaSettings.tsx b/packages/core/client/src/schema-settings/SchemaSettings.tsx index 223007b7a..cbea0aee2 100644 --- a/packages/core/client/src/schema-settings/SchemaSettings.tsx +++ b/packages/core/client/src/schema-settings/SchemaSettings.tsx @@ -70,6 +70,7 @@ import { } from '..'; import { BlockRequestContext_deprecated, + FormBlockContext, useFormBlockContext, useFormBlockType, useTableBlockContext, @@ -968,9 +969,10 @@ export const SchemaSettingsModalItem: FC = (props) const dataSourceKey = useDataSourceKey(); const record = useCollectionRecord(); const { association } = useDataBlockProps() || {}; + const formCtx = useFormBlockContext(); // 解决变量`当前对象`值在弹窗中丢失的问题 - const { formValue: subFormValue } = useSubFormValue(); + const { formValue: subFormValue, collection: subFormCollection } = useSubFormValue(); if (hidden) { return null; @@ -987,44 +989,49 @@ export const SchemaSettingsModalItem: FC = (props) () => { return ( - - - - - - - - 576px - @media (min-width: 576px) { - min-width: 520px; - } + + + + + + + + + 576px + @media (min-width: 576px) { + min-width: 520px; + } - // screen <= 576px - @media (max-width: 576px) { - min-width: 320px; - } - `} - > - - - - - - - - - - - - - + // screen <= 576px + @media (max-width: 576px) { + min-width: 320px; + } + `} + > + + + + + + + + + + + + + + ); }, diff --git a/packages/core/client/src/schema-settings/VariableInput/VariableInput.tsx b/packages/core/client/src/schema-settings/VariableInput/VariableInput.tsx index 10020e01a..647eb1655 100644 --- a/packages/core/client/src/schema-settings/VariableInput/VariableInput.tsx +++ b/packages/core/client/src/schema-settings/VariableInput/VariableInput.tsx @@ -41,10 +41,6 @@ type Props = { style?: React.CSSProperties; collectionField: CollectionFieldOptions_deprecated; contextCollectionName?: string; - /**指定当前表单数据表 */ - currentFormCollectionName?: string; - /**指定当前对象数据表 */ - currentIterationCollectionName?: string; /** * 根据 `onChange` 的第一个参数,判断是否需要触发 `onChange` * @param value `onChange` 的第一个参数 @@ -86,8 +82,6 @@ export const VariableInput = (props: Props) => { record, returnScope = _.identity, targetFieldSchema, - currentFormCollectionName, - currentIterationCollectionName, } = props; const { name: blockCollectionName } = useBlockCollection(); const scope = useVariableScope(); @@ -100,8 +94,6 @@ export const VariableInput = (props: Props) => { operator, uiSchema, targetFieldSchema, - currentFormCollectionName, - currentIterationCollectionName, }); const contextVariable = useContextAssociationFields({ schema, maxDepth: 2, contextCollectionName, collectionField }); const { compatOldVariables } = useCompatOldVariables({ @@ -245,7 +237,6 @@ export function useCompatOldVariables(props: { }); const { currentRecordSettings } = useCurrentRecordVariable({ schema: uiSchema, - collectionName: blockCollectionName, collectionField, noDisabled, targetFieldSchema, diff --git a/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts b/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts index aeabcaa45..a053d6208 100644 --- a/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts +++ b/packages/core/client/src/schema-settings/VariableInput/hooks/useFormVariable.ts @@ -57,7 +57,6 @@ export const useFormVariable = ({ collectionName, collectionField, schema, noDis * @returns */ export const useCurrentFormVariable = ({ - collectionName, collectionField, schema, noDisabled, @@ -66,7 +65,7 @@ export const useCurrentFormVariable = ({ }: Props = {}) => { // const { getActiveFieldsName } = useFormActiveFields() || {}; const { t } = useTranslation(); - const { form } = useFormBlockContext(); + const { form, collectionName } = useFormBlockContext(); const currentFormSettings = useBaseVariable({ collectionField, uiSchema: schema, @@ -97,6 +96,6 @@ export const useCurrentFormVariable = ({ /** 变量值 */ currentFormCtx: formInstance?.values, /** 用来判断是否可以显示`当前表单`变量 */ - shouldDisplayCurrentForm: !!formInstance && !formInstance.readPretty, + shouldDisplayCurrentForm: formInstance && !formInstance.readPretty, }; }; diff --git a/packages/core/client/src/schema-settings/VariableInput/hooks/useIterationVariable.ts b/packages/core/client/src/schema-settings/VariableInput/hooks/useIterationVariable.ts index 8834af4cf..2808c97b8 100644 --- a/packages/core/client/src/schema-settings/VariableInput/hooks/useIterationVariable.ts +++ b/packages/core/client/src/schema-settings/VariableInput/hooks/useIterationVariable.ts @@ -5,6 +5,7 @@ import { CollectionFieldOptions } from '../../../data-source/collection/Collecti import { useFlag } from '../../../flag-provider'; import { useSubFormValue } from '../../../schema-component/antd/association-field/hooks'; import { useBaseVariable } from './useBaseVariable'; +import { useCollection } from '../../../data-source'; /** * @deprecated @@ -61,13 +62,11 @@ export const useIterationVariable = ({ * @returns */ export const useCurrentObjectVariable = ({ - currentCollection, collectionField, schema, noDisabled, targetFieldSchema, }: { - currentCollection?: string; collectionField?: CollectionFieldOptions; schema?: any; noDisabled?: boolean; @@ -75,7 +74,8 @@ export const useCurrentObjectVariable = ({ targetFieldSchema?: Schema; } = {}) => { // const { getActiveFieldsName } = useFormActiveFields() || {}; - const { formValue: currentObjectCtx } = useSubFormValue(); + const collection = useCollection(); + const { formValue: currentObjectCtx, collection: collectionOfCurrentObject } = useSubFormValue(); const { isInSubForm, isInSubTable } = useFlag() || {}; const { t } = useTranslation(); const currentObjectSettings = useBaseVariable({ @@ -85,7 +85,7 @@ export const useCurrentObjectVariable = ({ maxDepth: 4, name: '$iteration', title: t('Current object'), - collectionName: currentCollection, + collectionName: collectionOfCurrentObject?.name || collection?.name, noDisabled, returnFields: (fields, option) => { // fix https://nocobase.height.app/T-2277 diff --git a/packages/core/client/src/schema-settings/VariableInput/hooks/useRecordVariable.ts b/packages/core/client/src/schema-settings/VariableInput/hooks/useRecordVariable.ts index dfa733c2d..5078217f7 100644 --- a/packages/core/client/src/schema-settings/VariableInput/hooks/useRecordVariable.ts +++ b/packages/core/client/src/schema-settings/VariableInput/hooks/useRecordVariable.ts @@ -2,10 +2,8 @@ import { Schema } from '@formily/json-schema'; import _ from 'lodash'; import { useTranslation } from 'react-i18next'; import { CollectionFieldOptions_deprecated } from '../../../collection-manager'; -import { useCollection } from '../../../data-source/collection/CollectionProvider'; -import { useCollectionRecord } from '../../../data-source/collection-record/CollectionRecordProvider'; -import { useFlag } from '../../../flag-provider/hooks/useFlag'; import { useBaseVariable } from './useBaseVariable'; +import { useFormBlockContext } from '../../../block-provider/FormBlockProvider'; interface Props { collectionField?: CollectionFieldOptions_deprecated; @@ -47,16 +45,13 @@ export const useRecordVariable = (props: Props) => { */ export const useCurrentRecordVariable = (props: Props = {}) => { const { t } = useTranslation(); - const { isInSubForm, isInSubTable } = useFlag() || {}; - const record = useCollectionRecord(); - const recordData = isInSubForm || isInSubTable ? record?.parentRecord?.data : record?.data; - const { name: collectionName } = useCollection() || {}; + const { formRecord, collectionName } = useFormBlockContext(); const currentRecordSettings = useBaseVariable({ collectionField: props.collectionField, uiSchema: props.schema, name: '$nRecord', title: t('Current record'), - collectionName: props.collectionName || collectionName, + collectionName: collectionName, noDisabled: props.noDisabled, targetFieldSchema: props.targetFieldSchema, }); @@ -65,9 +60,9 @@ export const useCurrentRecordVariable = (props: Props = {}) => { /** 变量配置 */ currentRecordSettings, /** 变量值 */ - currentRecordCtx: recordData, + currentRecordCtx: formRecord?.data, /** 用于判断是否需要显示配置项 */ - shouldDisplayCurrentRecord: !_.isEmpty(recordData), + shouldDisplayCurrentRecord: !formRecord?.isNew && !_.isEmpty(formRecord?.data), /** 当前记录对应的 collection name */ collectionName, }; diff --git a/packages/core/client/src/schema-settings/VariableInput/hooks/useVariableOptions.ts b/packages/core/client/src/schema-settings/VariableInput/hooks/useVariableOptions.ts index c7c5a182d..d2aaa1ae0 100644 --- a/packages/core/client/src/schema-settings/VariableInput/hooks/useVariableOptions.ts +++ b/packages/core/client/src/schema-settings/VariableInput/hooks/useVariableOptions.ts @@ -35,10 +35,6 @@ interface Props { noDisabled?: boolean; /** 消费变量值的字段 */ targetFieldSchema?: Schema; - /**指定当前表单数据表 */ - currentFormCollectionName?: string; - /**指定当前对象数据表 */ - currentIterationCollectionName?: string; } export const useVariableOptions = ({ @@ -49,11 +45,8 @@ export const useVariableOptions = ({ noDisabled, targetFieldSchema, record, - currentFormCollectionName, - currentIterationCollectionName, }: Props) => { const { name: blockCollectionName = record?.__collectionName } = useBlockCollection(); - const { name } = useCollection_deprecated(); const blockParentCollectionName = record?.__parent?.__collectionName; const { currentUserSettings } = useCurrentUserVariable({ maxDepth: 3, @@ -71,14 +64,12 @@ export const useVariableOptions = ({ const { datetimeSettings } = useDatetimeVariable({ operator, schema: uiSchema, noDisabled }); const { currentFormSettings, shouldDisplayCurrentForm } = useCurrentFormVariable({ schema: uiSchema, - collectionName: currentFormCollectionName || blockCollectionName, collectionField, noDisabled, targetFieldSchema, form, }); const { currentObjectSettings, shouldDisplayCurrentObject } = useCurrentObjectVariable({ - currentCollection: currentIterationCollectionName || name, collectionField, schema: uiSchema, noDisabled, @@ -86,7 +77,6 @@ export const useVariableOptions = ({ }); const { currentRecordSettings, shouldDisplayCurrentRecord } = useCurrentRecordVariable({ schema: uiSchema, - collectionName: blockCollectionName, collectionField, noDisabled, targetFieldSchema,