fix(linkageRules): fix autorun (#3105)
* fix(linkageRules): avoid accidentally triggering autorun * fix(linkageRules): fix the order of autorun triggers * fix: avoid crashing * fix: fix variable of expression * perf: use throttle to improve performance * chore: reduce wait time from 1000 to 500 * fix: fix init state * Revert "fix: fix init state" This reverts commit 3f469731770b7e1224ebbb63277ac86adc51b97d. * refactor: rename * fix: fix init state
This commit is contained in:
parent
79d2647c51
commit
357a081199
@ -75,7 +75,7 @@ export const Action: ComposedAction = observer(
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
field.linkageProperty = {};
|
||||
field.stateOfLinkageRules = {};
|
||||
linkageRules
|
||||
.filter((k) => !k.disabled)
|
||||
.forEach((v) => {
|
||||
|
@ -84,8 +84,8 @@ export const linkageAction = async ({
|
||||
variables: VariablesContextType;
|
||||
localVariables: VariableOption[];
|
||||
}) => {
|
||||
const disableResult = field?.linkageProperty?.disabled || [false];
|
||||
const displayResult = field?.linkageProperty?.display || ['visible'];
|
||||
const disableResult = field?.stateOfLinkageRules?.disabled || [false];
|
||||
const displayResult = field?.stateOfLinkageRules?.display || ['visible'];
|
||||
|
||||
switch (operator) {
|
||||
case ActionType.Visible:
|
||||
@ -94,8 +94,8 @@ export const linkageAction = async ({
|
||||
field.data = field.data || {};
|
||||
field.data.hidden = false;
|
||||
}
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
display: displayResult,
|
||||
};
|
||||
field.display = last(displayResult);
|
||||
@ -113,8 +113,8 @@ export const linkageAction = async ({
|
||||
if (await conditionAnalyses({ rules: condition, variables, localVariables })) {
|
||||
disableResult.push(true);
|
||||
}
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
disabled: disableResult,
|
||||
};
|
||||
field.disabled = last(disableResult);
|
||||
@ -124,8 +124,8 @@ export const linkageAction = async ({
|
||||
if (await conditionAnalyses({ rules: condition, variables, localVariables })) {
|
||||
disableResult.push(false);
|
||||
}
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
disabled: disableResult,
|
||||
};
|
||||
field.disabled = last(disableResult);
|
||||
|
@ -13,6 +13,7 @@ import { Collection, useCollection, useCollectionManager } from '../../../collec
|
||||
import { useRecord } from '../../../record-provider';
|
||||
import { GeneralSchemaItems } from '../../../schema-items/GeneralSchemaItems';
|
||||
import { GeneralSchemaDesigner, SchemaSettings, isPatternDisabled } from '../../../schema-settings';
|
||||
import { ActionType } from '../../../schema-settings/LinkageRules/type';
|
||||
import { VariableInput, getShouldChange } from '../../../schema-settings/VariableInput/VariableInput';
|
||||
import useIsAllowToSetDefaultValue from '../../../schema-settings/hooks/useIsAllowToSetDefaultValue';
|
||||
import { useIsShowMultipleSwitch } from '../../../schema-settings/hooks/useIsShowMultipleSwitch';
|
||||
@ -23,6 +24,7 @@ import { isSubMode } from '../association-field/util';
|
||||
import { BlockItem } from '../block-item';
|
||||
import { removeNullCondition } from '../filter';
|
||||
import { DynamicComponentProps } from '../filter/DynamicComponent';
|
||||
import { getTempFieldState } from '../form-v2/utils';
|
||||
import { HTMLEncode } from '../input/shared';
|
||||
import { useColorFields } from '../table-v2/Table.Column.Designer';
|
||||
import { FilterFormDesigner } from './FormItem.FilterFormDesigner';
|
||||
@ -128,12 +130,6 @@ FormItem.Designer = function Designer() {
|
||||
const isAssociationField = ['obo', 'oho', 'o2o', 'o2m', 'm2m', 'm2o'].includes(collectionField?.interface);
|
||||
const isTableField = fieldSchema['x-component'] === 'TableField';
|
||||
const isFileField = isFileCollection(targetCollection as any);
|
||||
const initialValue = {
|
||||
title: field.title === originalTitle ? undefined : field.title,
|
||||
};
|
||||
if (!field.readPretty) {
|
||||
initialValue['required'] = field.required;
|
||||
}
|
||||
const options = targetFields
|
||||
.filter((field) => {
|
||||
return isTitleField(field);
|
||||
@ -607,6 +603,7 @@ FormItem.Designer = function Designer() {
|
||||
schema['x-disabled'] = true;
|
||||
field.readPretty = false;
|
||||
field.disabled = true;
|
||||
_.set(field, 'initStateOfLinkageRules.pattern', getTempFieldState(true, ActionType.ReadOnly));
|
||||
break;
|
||||
}
|
||||
case 'read-pretty': {
|
||||
@ -615,6 +612,7 @@ FormItem.Designer = function Designer() {
|
||||
schema['x-read-pretty'] = true;
|
||||
schema['x-disabled'] = false;
|
||||
field.readPretty = true;
|
||||
_.set(field, 'initStateOfLinkageRules.pattern', getTempFieldState(true, ActionType.ReadPretty));
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@ -624,6 +622,7 @@ FormItem.Designer = function Designer() {
|
||||
schema['x-disabled'] = false;
|
||||
field.readPretty = false;
|
||||
field.disabled = false;
|
||||
_.set(field, 'initStateOfLinkageRules.pattern', getTempFieldState(true, ActionType.Editable));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,14 +2,21 @@ import { css } from '@emotion/css';
|
||||
import { FormLayout } from '@formily/antd-v5';
|
||||
import { createForm, Field, Form as FormilyForm, onFieldInit, onFormInputChange } from '@formily/core';
|
||||
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
|
||||
import { autorun, toJS } from '@formily/reactive';
|
||||
import { reaction } from '@formily/reactive';
|
||||
import { uid } from '@formily/shared';
|
||||
import { getValuesByPath } from '@nocobase/utils/client';
|
||||
import { ConfigProvider, Spin } from 'antd';
|
||||
import _ from 'lodash';
|
||||
import React, { useEffect, useMemo } from 'react';
|
||||
import { useActionContext } from '..';
|
||||
import { useAttach, useComponent } from '../..';
|
||||
import { ActionType } from '../../../schema-settings/LinkageRules/type';
|
||||
import { useLocalVariables, useVariables } from '../../../variables';
|
||||
import { VariableOption, VariablesContextType } from '../../../variables/types';
|
||||
import { getPath } from '../../../variables/utils/getPath';
|
||||
import { getVariableName } from '../../../variables/utils/getVariableName';
|
||||
import { isVariable, REGEX_OF_VARIABLE } from '../../../variables/utils/isVariable';
|
||||
import { getInnermostKeyAndValue, getTargetField } from '../../common/utils/uitls';
|
||||
import { useProps } from '../../hooks/useProps';
|
||||
import { collectFieldStateOfLinkageRules, getTempFieldState } from './utils';
|
||||
|
||||
@ -106,65 +113,46 @@ const WithForm = (props: WithFormProps) => {
|
||||
const disposes = [];
|
||||
|
||||
form.addEffects(id, () => {
|
||||
linkageRules.forEach((v) => {
|
||||
v.actions?.forEach((h) => {
|
||||
if (h.targetFields?.length) {
|
||||
const fields = h.targetFields.join(',');
|
||||
linkageRules.forEach((rule) => {
|
||||
rule.actions?.forEach((action) => {
|
||||
if (action.targetFields?.length) {
|
||||
const fields = action.targetFields.join(',');
|
||||
|
||||
// 之前使用的 `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 和 `reaction` 代替
|
||||
onFieldInit(`*(${fields})`, (field: any, form) => {
|
||||
field['initProperty'] = field?.['initProperty'] ?? {
|
||||
display: getTempFieldState(true, field.display),
|
||||
required: getTempFieldState(true, field.required),
|
||||
pattern: getTempFieldState(true, field.pattern),
|
||||
value: getTempFieldState(true, field.value || field.initialValue),
|
||||
field['initStateOfLinkageRules'] = {
|
||||
display: field.initStateOfLinkageRules?.display || getTempFieldState(true, field.display),
|
||||
required: field.initStateOfLinkageRules?.required || getTempFieldState(true, field.required || false),
|
||||
pattern: field.initStateOfLinkageRules?.pattern || getTempFieldState(true, field.pattern),
|
||||
value:
|
||||
field.initStateOfLinkageRules?.value || getTempFieldState(true, field.value || field.initialValue),
|
||||
};
|
||||
});
|
||||
|
||||
// 之前使用的 `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 和 `autorun` 代替
|
||||
onFieldInit(`*(${fields})`, (field: any, form) => {
|
||||
disposes.push(
|
||||
autorun(() => {
|
||||
// 当条件改变触发 autorun 时,会同步收集字段状态,并保存到 field.linkageProperty 中
|
||||
collectFieldStateOfLinkageRules({
|
||||
operator: h.operator,
|
||||
value: h.value,
|
||||
field,
|
||||
condition: v.condition,
|
||||
values: toJS(form?.values),
|
||||
variables,
|
||||
localVariables,
|
||||
});
|
||||
reaction(
|
||||
// 这里共依赖 3 部分,当这 3 部分中的任意一部分发生变更后,需要触发联动规则:
|
||||
// 1. 条件中的字段值;
|
||||
// 2. 条件中的变量值;
|
||||
// 3. value 表达式中的变量值;
|
||||
() => {
|
||||
// 获取条件中的字段值
|
||||
const fieldValuesInCondition = getFieldValuesInCondition({ linkageRules, formValues: form.values });
|
||||
|
||||
// 当条件改变时,有可能会触发多个 autorun,所以这里需要延迟一下,确保所有的 autorun 都执行完毕后,
|
||||
// 再从 field.linkageProperty 中取值,因为此时 field.linkageProperty 中的值才是全的。
|
||||
setTimeout(async () => {
|
||||
const fieldName = getFieldNameByOperator(h.operator);
|
||||
// 获取条件中的变量值
|
||||
const variableValuesInCondition = getVariableValuesInCondition({ linkageRules, localVariables });
|
||||
|
||||
// 防止重复赋值
|
||||
if (!field.linkageProperty[fieldName]) {
|
||||
return;
|
||||
}
|
||||
// 获取 value 表达式中的变量值
|
||||
const variableValuesInExpression = getVariableValuesInExpression({ action, localVariables });
|
||||
|
||||
let stateList = field.linkageProperty[fieldName];
|
||||
const result = [fieldValuesInCondition, variableValuesInCondition, variableValuesInExpression]
|
||||
.map((item) => JSON.stringify(item))
|
||||
.join(',');
|
||||
|
||||
stateList = await Promise.all(stateList);
|
||||
stateList = stateList.filter((v) => v.condition);
|
||||
|
||||
const lastState = stateList[stateList.length - 1];
|
||||
|
||||
if (fieldName === 'value') {
|
||||
// value 比较特殊,它只有在匹配条件时才需要赋值,当条件不匹配时,维持现在的值;
|
||||
// stateList 中肯定会有一个初始值,所以当 stateList.length > 1 时,就说明有匹配条件的情况;
|
||||
if (stateList.length > 1) {
|
||||
field.value = lastState.value;
|
||||
}
|
||||
} else {
|
||||
field[fieldName] = lastState?.value;
|
||||
}
|
||||
|
||||
// 在这里清空 field.linkageProperty,就可以保证:当条件再次改变时,如果该字段没有和任何条件匹配,则需要把对应的值恢复到初始值;
|
||||
field.linkageProperty[fieldName] = null;
|
||||
});
|
||||
}),
|
||||
return result;
|
||||
},
|
||||
getSubscriber(action, field, rule, form, variables, localVariables),
|
||||
{ fireImmediately: true },
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
@ -238,6 +226,59 @@ export const Form: React.FC<FormProps> & {
|
||||
{ displayName: 'Form' },
|
||||
);
|
||||
|
||||
function getSubscriber(
|
||||
action: any,
|
||||
field: any,
|
||||
rule: any,
|
||||
form: FormilyForm<any>,
|
||||
variables: VariablesContextType,
|
||||
localVariables: VariableOption[],
|
||||
): (value: string, oldValue: string) => void {
|
||||
return _.throttle(() => {
|
||||
// 当条件改变触发 reaction 时,会同步收集字段状态,并保存到 field.stateOfLinkageRules 中
|
||||
collectFieldStateOfLinkageRules({
|
||||
operator: action.operator,
|
||||
value: action.value,
|
||||
field,
|
||||
condition: rule.condition,
|
||||
values: form.values,
|
||||
variables,
|
||||
localVariables,
|
||||
});
|
||||
|
||||
// 当条件改变时,有可能会触发多个 reaction,所以这里需要延迟一下,确保所有的 reaction 都执行完毕后,
|
||||
// 再从 field.stateOfLinkageRules 中取值,因为此时 field.stateOfLinkageRules 中的值才是全的。
|
||||
setTimeout(async () => {
|
||||
const fieldName = getFieldNameByOperator(action.operator);
|
||||
|
||||
// 防止重复赋值
|
||||
if (!field.stateOfLinkageRules[fieldName]) {
|
||||
return;
|
||||
}
|
||||
|
||||
let stateList = field.stateOfLinkageRules[fieldName];
|
||||
|
||||
stateList = await Promise.all(stateList);
|
||||
stateList = stateList.filter((v) => v.condition);
|
||||
|
||||
const lastState = stateList[stateList.length - 1];
|
||||
|
||||
if (fieldName === 'value') {
|
||||
// value 比较特殊,它只有在匹配条件时才需要赋值,当条件不匹配时,维持现在的值;
|
||||
// stateList 中肯定会有一个初始值,所以当 stateList.length > 1 时,就说明有匹配条件的情况;
|
||||
if (stateList.length > 1) {
|
||||
field.value = lastState.value;
|
||||
}
|
||||
} else {
|
||||
field[fieldName] = lastState?.value;
|
||||
}
|
||||
|
||||
// 在这里清空 field.stateOfLinkageRules,就可以保证:当条件再次改变时,如果该字段没有和任何条件匹配,则需要把对应的值恢复到初始值;
|
||||
field.stateOfLinkageRules[fieldName] = null;
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
function getFieldNameByOperator(operator: ActionType) {
|
||||
switch (operator) {
|
||||
case ActionType.Required:
|
||||
@ -257,3 +298,78 @@ function getFieldNameByOperator(operator: ActionType) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getFieldValuesInCondition({ linkageRules, formValues }) {
|
||||
return linkageRules.map((rule) => {
|
||||
const type = Object.keys(rule.condition)[0] || '$and';
|
||||
const conditions = rule.condition[type];
|
||||
|
||||
return conditions
|
||||
.map((condition) => {
|
||||
const path = getTargetField(condition).join('.');
|
||||
return getValuesByPath(formValues, path);
|
||||
})
|
||||
.filter(Boolean);
|
||||
});
|
||||
}
|
||||
|
||||
function getVariableValuesInCondition({
|
||||
linkageRules,
|
||||
localVariables,
|
||||
}: {
|
||||
linkageRules: any[];
|
||||
localVariables: VariableOption[];
|
||||
}) {
|
||||
return linkageRules.map((rule) => {
|
||||
const type = Object.keys(rule.condition)[0] || '$and';
|
||||
const conditions = rule.condition[type];
|
||||
|
||||
return conditions
|
||||
.map((condition) => {
|
||||
const jsonlogic = getInnermostKeyAndValue(condition);
|
||||
if (!jsonlogic) {
|
||||
return null;
|
||||
}
|
||||
if (isVariable(jsonlogic.value)) {
|
||||
return getVariableValue(jsonlogic.value, localVariables);
|
||||
}
|
||||
|
||||
return jsonlogic.value;
|
||||
})
|
||||
.filter(Boolean);
|
||||
});
|
||||
}
|
||||
|
||||
function getVariableValuesInExpression({ action, localVariables }) {
|
||||
const actionValue = action.value;
|
||||
const mode = actionValue?.mode;
|
||||
const value = actionValue?.value || actionValue?.result;
|
||||
|
||||
if (mode !== 'express') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return value
|
||||
.match(REGEX_OF_VARIABLE)
|
||||
?.map((variableString: string) => {
|
||||
return getVariableValue(variableString, localVariables);
|
||||
})
|
||||
.filter(Boolean);
|
||||
}
|
||||
|
||||
function getVariableValue(variableString: string, localVariables: VariableOption[]) {
|
||||
if (!isVariable(variableString)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const variableName = getVariableName(variableString);
|
||||
const ctx = {
|
||||
[variableName]: localVariables.find((item) => item.name === variableName)?.ctx,
|
||||
};
|
||||
|
||||
return getValuesByPath(ctx, getPath(variableString));
|
||||
}
|
||||
|
@ -40,24 +40,24 @@ export const collectFieldStateOfLinkageRules = ({
|
||||
variables,
|
||||
localVariables,
|
||||
}: Props) => {
|
||||
const requiredResult = field?.linkageProperty?.required || [field?.initProperty?.required || false];
|
||||
const displayResult = field?.linkageProperty?.display || [field?.initProperty?.display];
|
||||
const patternResult = field?.linkageProperty?.pattern || [field?.initProperty?.pattern];
|
||||
const valueResult = field?.linkageProperty?.value || [field?.initProperty?.value];
|
||||
const requiredResult = field?.stateOfLinkageRules?.required || [field?.initStateOfLinkageRules?.required];
|
||||
const displayResult = field?.stateOfLinkageRules?.display || [field?.initStateOfLinkageRules?.display];
|
||||
const patternResult = field?.stateOfLinkageRules?.pattern || [field?.initStateOfLinkageRules?.pattern];
|
||||
const valueResult = field?.stateOfLinkageRules?.value || [field?.initStateOfLinkageRules?.value];
|
||||
const { evaluate } = evaluators.get('formula.js');
|
||||
|
||||
switch (operator) {
|
||||
case ActionType.Required:
|
||||
requiredResult.push(getTempFieldState(conditionAnalyses({ rules: condition, variables, localVariables }), true));
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
required: requiredResult,
|
||||
};
|
||||
break;
|
||||
case ActionType.InRequired:
|
||||
requiredResult.push(getTempFieldState(conditionAnalyses({ rules: condition, variables, localVariables }), false));
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
required: requiredResult,
|
||||
};
|
||||
break;
|
||||
@ -67,8 +67,8 @@ export const collectFieldStateOfLinkageRules = ({
|
||||
displayResult.push(
|
||||
getTempFieldState(conditionAnalyses({ rules: condition, variables, localVariables }), operator),
|
||||
);
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
display: displayResult,
|
||||
};
|
||||
break;
|
||||
@ -78,8 +78,8 @@ export const collectFieldStateOfLinkageRules = ({
|
||||
patternResult.push(
|
||||
getTempFieldState(conditionAnalyses({ rules: condition, variables, localVariables }), operator),
|
||||
);
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
pattern: patternResult,
|
||||
};
|
||||
break;
|
||||
@ -117,8 +117,8 @@ export const collectFieldStateOfLinkageRules = ({
|
||||
getTempFieldState(conditionAnalyses({ rules: condition, variables, localVariables }), getValue()),
|
||||
);
|
||||
}
|
||||
field.linkageProperty = {
|
||||
...field.linkageProperty,
|
||||
field.stateOfLinkageRules = {
|
||||
...field.stateOfLinkageRules,
|
||||
value: valueResult,
|
||||
};
|
||||
}
|
||||
|
@ -38,7 +38,7 @@ export function getInnermostKeyAndValue(obj) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const getTargetField = (obj) => {
|
||||
export const getTargetField = (obj) => {
|
||||
const keys = getAllKeys(obj);
|
||||
const index = findIndex(keys, (key, index, keys) => {
|
||||
if (key.includes('$') && index > 0) {
|
||||
@ -83,21 +83,20 @@ export const conditionAnalyses = async ({
|
||||
const type = Object.keys(rules)[0] || '$and';
|
||||
const conditions = rules[type];
|
||||
|
||||
let results = conditions.map(async (c) => {
|
||||
const jsonlogic = getInnermostKeyAndValue(c);
|
||||
let results = conditions.map(async (condition) => {
|
||||
const jsonlogic = getInnermostKeyAndValue(condition);
|
||||
const operator = jsonlogic?.key;
|
||||
|
||||
if (!operator) {
|
||||
return true;
|
||||
}
|
||||
|
||||
const targetVariableName = targetFieldToVariableString(getTargetField(c));
|
||||
const targetVariableName = targetFieldToVariableString(getTargetField(condition));
|
||||
const targetValue = variables.parseVariable(targetVariableName, localVariables);
|
||||
|
||||
const parsingResult = isVariable(jsonlogic?.value)
|
||||
? [
|
||||
variables.parseVariable(jsonlogic?.value, localVariables),
|
||||
variables.parseVariable(targetVariableName, localVariables),
|
||||
]
|
||||
: [jsonlogic?.value, variables.parseVariable(targetVariableName, localVariables)];
|
||||
? [variables.parseVariable(jsonlogic?.value, localVariables), targetValue]
|
||||
: [jsonlogic?.value, targetValue];
|
||||
|
||||
try {
|
||||
const jsonLogic = getJsonLogic();
|
||||
@ -127,7 +126,7 @@ export const conditionAnalyses = async ({
|
||||
* @param targetField
|
||||
* @returns
|
||||
*/
|
||||
function targetFieldToVariableString(targetField: string[]) {
|
||||
export function targetFieldToVariableString(targetField: string[]) {
|
||||
// Action 中的联动规则虽然没有 form 上下文但是在这里也使用的是 `$nForm` 变量,这样实现更简单
|
||||
return `{{ $nForm.${targetField.join('.')} }}`;
|
||||
}
|
||||
|
@ -97,7 +97,7 @@ export const CreateRecordAction = observer(
|
||||
const localVariables = useLocalVariables({ currentForm: { values } as any });
|
||||
|
||||
useEffect(() => {
|
||||
field.linkageProperty = {};
|
||||
field.stateOfLinkageRules = {};
|
||||
linkageRules
|
||||
.filter((k) => !k.disabled)
|
||||
.forEach((v) => {
|
||||
@ -201,7 +201,7 @@ export const CreateAction = observer(
|
||||
}, [menuItems]);
|
||||
|
||||
useEffect(() => {
|
||||
field.linkageProperty = {};
|
||||
field.stateOfLinkageRules = {};
|
||||
linkageRules
|
||||
.filter((k) => !k.disabled)
|
||||
.forEach((v) => {
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { Field } from '@formily/core';
|
||||
import { ISchema, observer, useField, useFieldSchema } from '@formily/react';
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useCollection, useCollectionManager } from '../collection-manager';
|
||||
import { useDesignable } from '../schema-component';
|
||||
import { getTempFieldState } from '../schema-component/antd/form-v2/utils';
|
||||
import { SchemaSettings } from '../schema-settings';
|
||||
|
||||
export const GeneralSchemaItems: React.FC<{
|
||||
@ -149,6 +151,7 @@ export const GeneralSchemaItems: React.FC<{
|
||||
['x-uid']: fieldSchema['x-uid'],
|
||||
};
|
||||
field.required = required;
|
||||
_.set(field, 'initStateOfLinkageRules.required', getTempFieldState(true, required));
|
||||
fieldSchema['required'] = required;
|
||||
schema['required'] = required;
|
||||
dn.emit('patch', {
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { untracked } from '@formily/reactive';
|
||||
import { getValuesByPath } from '@nocobase/utils/client';
|
||||
import _ from 'lodash';
|
||||
import React, { createContext, useCallback, useEffect, useMemo, useRef } from 'react';
|
||||
@ -278,11 +279,19 @@ VariablesProvider.displayName = 'VariablesProvider';
|
||||
export default VariablesProvider;
|
||||
|
||||
function shouldToRequest(value) {
|
||||
// fix https://nocobase.height.app/T-2502
|
||||
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
||||
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
|
||||
return true;
|
||||
}
|
||||
let result = false;
|
||||
|
||||
return _.isEmpty(value);
|
||||
// value 有可能是一个响应式对象,使用 untracked 可以避免意外触发 autorun
|
||||
untracked(() => {
|
||||
// fix https://nocobase.height.app/T-2502
|
||||
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
|
||||
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
|
||||
result = true;
|
||||
return;
|
||||
}
|
||||
|
||||
result = _.isEmpty(value);
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user