diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts index 738b7d6a1..836d3847a 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/schemaSettings.test.ts @@ -9,7 +9,7 @@ import { oneTableBlockWithAddNewAndViewAndEditAndBasicFields, test, } from '@nocobase/test/e2e'; -import { T2165, T2174, T3251 } from './templatesOfBug'; +import { T2165, T2174, T3251, T3806 } from './templatesOfBug'; const clickOption = async (page: Page, optionName: string) => { await page.getByLabel('block-item-CardItem-general-form').hover(); @@ -254,6 +254,47 @@ test.describe('creation form block schema settings', () => { page.getByLabel('block-item-CollectionField-users-form-users.email-Email').getByRole('textbox'), ).toBeEditable(); }); + + // https://nocobase.height.app/T-3806 + test('after save as block template', async ({ page, mockPage }) => { + await mockPage(T3806).goto(); + + // 1. 一开始联动规则应该正常 + await page + .getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname') + .getByRole('textbox') + .fill('123'); + await expect( + page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'), + ).toHaveValue('123'); + + try { + // 2. 将表单区块保存为模板后 + await page.getByLabel('block-item-CardItem-users-form').hover(); + await page.getByLabel('designer-schema-settings-CardItem-blockSettings:createForm-users').hover(); + await page.getByRole('menuitem', { name: 'Save as block template' }).click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await page.waitForTimeout(1000); + + // 3. 联动规则应该依然是正常的 + await page + .getByLabel('block-item-CollectionField-users-form-users.nickname-Nickname') + .getByRole('textbox') + .fill('456'); + await expect( + page.getByLabel('block-item-CollectionField-users-form-users.username-Username').getByRole('textbox'), + ).toHaveValue('456'); + } catch (err) { + throw err; + } finally { + // 4. 把创建的模板删除 + await page.goto('/admin/settings/ui-schema-storage'); + await page.getByLabel('Select all').check(); + await page.getByLabel('action-Action-Delete-destroy-').click(); + await page.getByRole('button', { name: 'OK', exact: true }).click(); + await expect(page.getByRole('row', { name: 'Users_Form' }).first()).toBeHidden(); + } + }); }); test('Save as block template & convert reference to duplicate', async ({ page, mockPage }) => { diff --git a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts index adf352e49..2f6ed4d94 100644 --- a/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts +++ b/packages/core/client/src/modules/blocks/data-blocks/form/__e2e__/form-create/templatesOfBug.ts @@ -6066,3 +6066,204 @@ export const T3529: PageConfig = { 'x-index': 1, }, }; + +export const T3806: PageConfig = { + pageSchema: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Page', + properties: { + '6w8tkq3665g': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'page:addBlock', + properties: { + '0k0yifwylj8': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + v5cdqnvyh3z: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + p9pszqbz1n5: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-acl-action-props': { + skipScopeCheck: true, + }, + 'x-acl-action': 'users:create', + 'x-decorator': 'FormBlockProvider', + 'x-use-decorator-props': 'useCreateFormBlockDecoratorProps', + 'x-decorator-props': { + dataSource: 'main', + collection: 'users', + }, + 'x-toolbar': 'BlockSchemaToolbar', + 'x-settings': 'blockSettings:createForm', + 'x-component': 'CardItem', + properties: { + '578cg3ao40s': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'FormV2', + 'x-use-component-props': 'useCreateFormBlockProps', + properties: { + grid: { + 'x-uid': 'xpdqjz634mt', + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid', + 'x-initializer': 'form:configureFields', + 'x-linkage-rules': [ + { + condition: { + $and: [], + }, + actions: [ + { + targetFields: ['username'], + operator: 'value', + value: { + mode: 'express', + value: '{{$nForm.nickname}}', + result: '{{$nForm.nickname}}', + }, + }, + ], + }, + ], + properties: { + gjck905cyws: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + i041myizzph: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + nickname: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'users.nickname', + 'x-component-props': {}, + 'x-uid': 'afnfoxl5cbi', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'a3o7l08zz6e', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'zoakp82dymw', + 'x-async': false, + 'x-index': 1, + }, + qffoo7lqua1: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Row', + properties: { + nq0rbuti1d9: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-component': 'Grid.Col', + properties: { + username: { + _isJSONSchemaObject: true, + version: '2.0', + type: 'string', + 'x-toolbar': 'FormItemSchemaToolbar', + 'x-settings': 'fieldSettings:FormItem', + 'x-component': 'CollectionField', + 'x-decorator': 'FormItem', + 'x-collection-field': 'users.username', + 'x-component-props': {}, + 'x-uid': 'mq80n8nyuq8', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'hf9bq4vjm80', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'ua08izsl514', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-async': false, + 'x-index': 1, + }, + '006ip4mnr75': { + _isJSONSchemaObject: true, + version: '2.0', + type: 'void', + 'x-initializer': 'createForm:configureActions', + 'x-component': 'ActionBar', + 'x-component-props': { + layout: 'one-column', + style: { + marginTop: 24, + }, + }, + 'x-uid': 'u6d026lia1x', + 'x-async': false, + 'x-index': 2, + }, + }, + 'x-uid': 'p7ucl8ixcx4', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'hz9xoui3o9d', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'j1q201o2wju', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 't0olm6ygvas', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'aq4i1y0nf00', + 'x-async': false, + 'x-index': 1, + }, + }, + 'x-uid': 'px8uapyslvw', + 'x-async': true, + 'x-index': 1, + }, +}; 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 4c707ba6e..176fdd7da 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 @@ -19,6 +19,7 @@ import { getInnermostKeyAndValue, getTargetField } from '../../common/utils/uitl import { useProps } from '../../hooks/useProps'; import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils'; import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps'; +import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider'; export interface FormProps { [key: string]: any; @@ -87,6 +88,7 @@ const WithForm = (props: WithFormProps) => { const { setFormValueChanged } = useActionContext(); const variables = useVariables(); const localVariables = useLocalVariables({ currentForm: form }); + const { templateFinshed } = useTemplateBlockContext(); const linkageRules: any[] = (getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || []; @@ -166,7 +168,7 @@ const WithForm = (props: WithFormProps) => { dispose(); }); }; - }, [linkageRules]); + }, [linkageRules, templateFinshed]); return fieldSchema['x-decorator'] === 'FormV2' ? : ; };