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 { reaction } from '@formily/reactive';
import _ from 'lodash';
import { useEffect, useRef } from 'react';
import { useEffect } from 'react';
import { useRecord, useRecordIndex } from '../../../../../src/record-provider';
import { useFormBlockType } from '../../../../block-provider/FormBlockProvider';
import { useCollection } from '../../../../collection-manager';
import { useFlag } from '../../../../flag-provider';
import { DEBOUNCE_WAIT, useLocalVariables, useVariables } from '../../../../variables';
@ -27,9 +28,7 @@ const useParseDefaultValue = () => {
const { getField } = useCollection();
const { isSpecialCase, setDefaultValue } = useSpecialCase();
const index = useRecordIndex();
// 需要保存 record 的初始值,因为设置默认值的时候 record 会被修改,导致初始值丢失
const recordRef = useRef(_.omit(record, '__parent'));
const { type: formBlockType } = useFormBlockType();
useEffect(() => {
if (
@ -37,8 +36,8 @@ const useParseDefaultValue = () => {
isInSetDefaultValueDialog ||
isInFormDataTemplate ||
isSubMode(fieldSchema) ||
// 根据 record 是否为空,判断当前是否是新建状态,编辑状态下不需要设置默认值,否则会覆盖用户输入的值,只有新建状态下才需要设置默认值
(!_.isEmpty(recordRef.current) && isFromDatabase(record) && !isInAssignFieldValues)
// 编辑状态下不需要设置默认值,否则会覆盖用户输入的值,只有新建状态下才需要设置默认值
(formBlockType === 'update' && isFromDatabase(record) && !isInAssignFieldValues)
) {
return;
}
@ -99,7 +98,16 @@ const useParseDefaultValue = () => {
if (variableValue) {
// 实现联动的效果,当依赖的变量变化时(如 `$nForm` 变量),重新解析默认值
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);
return dispose;

View File

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

View File

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

View File

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

View File

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