fix: should not display currentRecord in creation form block (#2814)

* fix: should not display currentRecord in creation form block

* fix: avoid crashing

* fix: fix T-2212
This commit is contained in:
被雨水过滤的空气-Rain 2023-10-16 18:23:41 +08:00 committed by GitHub
parent bb5093cfc2
commit e5cca1dcb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 37 additions and 19 deletions

View File

@ -2,8 +2,9 @@ import { Field } from '@formily/core';
import { useField, useFieldSchema } from '@formily/react'; import { useField, useFieldSchema } from '@formily/react';
import { reaction } from '@formily/reactive'; import { reaction } from '@formily/reactive';
import _ from 'lodash'; import _ from 'lodash';
import { useEffect, useRef } from 'react'; import { useEffect } from 'react';
import { useRecord, useRecordIndex } from '../../../../../src/record-provider'; import { useRecord, useRecordIndex } from '../../../../../src/record-provider';
import { useFormBlockType } from '../../../../block-provider/FormBlockProvider';
import { useCollection } from '../../../../collection-manager'; import { useCollection } from '../../../../collection-manager';
import { useFlag } from '../../../../flag-provider'; import { useFlag } from '../../../../flag-provider';
import { DEBOUNCE_WAIT, useLocalVariables, useVariables } from '../../../../variables'; import { DEBOUNCE_WAIT, useLocalVariables, useVariables } from '../../../../variables';
@ -27,9 +28,7 @@ const useParseDefaultValue = () => {
const { getField } = useCollection(); const { getField } = useCollection();
const { isSpecialCase, setDefaultValue } = useSpecialCase(); const { isSpecialCase, setDefaultValue } = useSpecialCase();
const index = useRecordIndex(); const index = useRecordIndex();
const { type: formBlockType } = useFormBlockType();
// 需要保存 record 的初始值,因为设置默认值的时候 record 会被修改,导致初始值丢失
const recordRef = useRef(_.omit(record, '__parent'));
useEffect(() => { useEffect(() => {
if ( if (
@ -37,8 +36,8 @@ const useParseDefaultValue = () => {
isInSetDefaultValueDialog || isInSetDefaultValueDialog ||
isInFormDataTemplate || isInFormDataTemplate ||
isSubMode(fieldSchema) || isSubMode(fieldSchema) ||
// 根据 record 是否为空,判断当前是否是新建状态,编辑状态下不需要设置默认值,否则会覆盖用户输入的值,只有新建状态下才需要设置默认值 // 编辑状态下不需要设置默认值,否则会覆盖用户输入的值,只有新建状态下才需要设置默认值
(!_.isEmpty(recordRef.current) && isFromDatabase(record) && !isInAssignFieldValues) (formBlockType === 'update' && isFromDatabase(record) && !isInAssignFieldValues)
) { ) {
return; return;
} }
@ -99,7 +98,16 @@ const useParseDefaultValue = () => {
if (variableValue) { if (variableValue) {
// 实现联动的效果,当依赖的变量变化时(如 `$nForm` 变量),重新解析默认值 // 实现联动的效果,当依赖的变量变化时(如 `$nForm` 变量),重新解析默认值
const dispose = reaction(() => { const dispose = reaction(() => {
return _.get({ [variableName]: variableValue?.ctx }, getPath(fieldSchema.default)); const obj = { [variableName]: variableValue?.ctx };
const path = getPath(fieldSchema.default);
// fix https://nocobase.height.app/T-2212
if (_.get(obj, path) === undefined) {
// 返回一个随机值,确保能触发 run 函数
return Math.random();
}
return _.get(obj, path);
}, run); }, run);
return dispose; return dispose;

View File

@ -70,6 +70,10 @@ export const linkageMergeAction = async ({
) { ) {
let result = null; let result = null;
if (value?.mode === 'express') { if (value?.mode === 'express') {
if ((value.value || value.result) == null) {
return;
}
const scope = cloneDeep(values); const scope = cloneDeep(values);
// 1. 解析如 `{{$user.name}}` 之类的变量 // 1. 解析如 `{{$user.name}}` 之类的变量
@ -113,6 +117,10 @@ async function replaceVariables(
const store = {}; const store = {};
const scope = {}; const scope = {};
if (value == null) {
return;
}
const waitForParsing = value.match(REGEX_OF_VARIABLE)?.map(async (item) => { const waitForParsing = value.match(REGEX_OF_VARIABLE)?.map(async (item) => {
const result = await variables.parseVariable(item, localVariables); const result = await variables.parseVariable(item, localVariables);

View File

@ -22,6 +22,10 @@ interface usePropsReturn {
variables: VariablesContextType; variables: VariablesContextType;
localVariables: VariableOption | VariableOption[]; localVariables: VariableOption | VariableOption[];
record: Record<string, any>; record: Record<string, any>;
/**
* create update
*/
formBlockType: 'create' | 'update';
} }
interface Props { interface Props {
@ -33,7 +37,8 @@ export const FormLinkageRules = observer(
(props: Props) => { (props: Props) => {
const fieldSchema = useFieldSchema(); const fieldSchema = useFieldSchema();
const { useProps, dynamicComponent } = props; const { useProps, dynamicComponent } = props;
const { options, defaultValues, collectionName, form, variables, localVariables, record } = useProps(); const { options, defaultValues, collectionName, form, formBlockType, variables, localVariables, record } =
useProps();
const { getAllCollectionsInheritChain } = useCollectionManager(); const { getAllCollectionsInheritChain } = useCollectionManager();
const components = useMemo(() => ({ ArrayCollapse }), []); const components = useMemo(() => ({ ArrayCollapse }), []);
@ -160,7 +165,7 @@ export const FormLinkageRules = observer(
); );
return ( return (
<FormBlockContext.Provider value={{ form }}> <FormBlockContext.Provider value={{ form, type: formBlockType }}>
<RecordProvider record={record}> <RecordProvider record={record}>
<FilterContext.Provider value={value}> <FilterContext.Provider value={value}>
<SchemaComponent components={components} schema={schema} /> <SchemaComponent components={components} schema={schema} />

View File

@ -64,7 +64,7 @@ import {
useRecord, useRecord,
useSortFields, useSortFields,
} from '..'; } from '..';
import { BlockRequestContext, useFormBlockContext, useTableBlockContext } from '../block-provider'; import { BlockRequestContext, useFormBlockContext, useFormBlockType, useTableBlockContext } from '../block-provider';
import { import {
FormActiveFieldsProvider, FormActiveFieldsProvider,
findFilterTargets, findFilterTargets,
@ -1154,6 +1154,7 @@ SchemaSettings.LinkageRules = function LinkageRules(props) {
const variables = useVariables(); const variables = useVariables();
const localVariables = useLocalVariables(); const localVariables = useLocalVariables();
const record = useRecord(); const record = useRecord();
const { type: formBlockType } = useFormBlockType();
const type = props?.type || ['Action', 'Action.Link'].includes(fieldSchema['x-component']) ? 'button' : 'field'; const type = props?.type || ['Action', 'Action.Link'].includes(fieldSchema['x-component']) ? 'button' : 'field';
const gridSchema = findGridSchema(fieldSchema) || fieldSchema; const gridSchema = findGridSchema(fieldSchema) || fieldSchema;
const schema = useMemo<ISchema>( const schema = useMemo<ISchema>(
@ -1176,6 +1177,7 @@ SchemaSettings.LinkageRules = function LinkageRules(props) {
variables, variables,
localVariables, localVariables,
record, record,
formBlockType,
}; };
}, },
}, },

View File

@ -1,7 +1,7 @@
import { Form } from '@formily/core'; import { Form } from '@formily/core';
import { ISchema, Schema } from '@formily/react'; import { ISchema, Schema } from '@formily/react';
import _ from 'lodash';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useFormBlockType } from '../../../block-provider/FormBlockProvider';
import { CollectionFieldOptions } from '../../../collection-manager'; import { CollectionFieldOptions } from '../../../collection-manager';
import { useFlag } from '../../../flag-provider'; import { useFlag } from '../../../flag-provider';
import { useBlockCollection } from './useBlockCollection'; import { useBlockCollection } from './useBlockCollection';
@ -20,7 +20,7 @@ interface Props {
/** /**
* `useRecord` * `useRecord`
*/ */
record: Record<string, any>; record?: Record<string, any>;
/** /**
* `Filter` `uiSchema` `数据范围` * `Filter` `uiSchema` `数据范围`
*/ */
@ -40,7 +40,6 @@ interface Props {
export const useVariableOptions = ({ export const useVariableOptions = ({
collectionField, collectionField,
form, form,
record,
uiSchema, uiSchema,
operator, operator,
noDisabled, noDisabled,
@ -48,6 +47,7 @@ export const useVariableOptions = ({
}: Props) => { }: Props) => {
const { name: blockCollectionName } = useBlockCollection(); const { name: blockCollectionName } = useBlockCollection();
const { isInSetDefaultValueDialog } = useFlag() || {}; const { isInSetDefaultValueDialog } = useFlag() || {};
const { type: formBlockType } = useFormBlockType();
const fieldCollectionName = collectionField?.collectionName; const fieldCollectionName = collectionField?.collectionName;
const userVariable = useUserVariable({ const userVariable = useUserVariable({
@ -80,10 +80,6 @@ export const useVariableOptions = ({
targetFieldSchema, targetFieldSchema,
}); });
// 保证下面的 `_.isEmpty(record)` 结果符合预期,如果存在 `__parent` 字段,需要删除
record = { ...record };
delete record.__parent;
return useMemo(() => { return useMemo(() => {
return [ return [
userVariable, userVariable,
@ -95,7 +91,7 @@ export const useVariableOptions = ({
fieldCollectionName !== blockCollectionName && fieldCollectionName !== blockCollectionName &&
isInSetDefaultValueDialog && isInSetDefaultValueDialog &&
iterationVariable, iterationVariable,
!_.isEmpty(record) && currentRecordVariable, formBlockType === 'update' && currentRecordVariable,
].filter(Boolean); ].filter(Boolean);
}, [ }, [
userVariable, userVariable,
@ -106,7 +102,6 @@ export const useVariableOptions = ({
blockCollectionName, blockCollectionName,
isInSetDefaultValueDialog, isInSetDefaultValueDialog,
iterationVariable, iterationVariable,
record,
currentRecordVariable, currentRecordVariable,
]); ]);
}; };