fix: revert linkage rules (#2821)

* fix: revert linkage rules

* fix: move fields
This commit is contained in:
被雨水过滤的空气-Rain 2023-10-16 18:28:10 +08:00 committed by GitHub
parent e5cca1dcb1
commit 24d914b0ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 92 additions and 63 deletions

View File

@ -66,6 +66,7 @@ export const Action: ComposedAction = observer(
let actionTitle = title || compile(fieldSchema.title); let actionTitle = title || compile(fieldSchema.title);
actionTitle = lodash.isString(actionTitle) ? t(actionTitle) : actionTitle; actionTitle = lodash.isString(actionTitle) ? t(actionTitle) : actionTitle;
useEffect(() => { useEffect(() => {
field.linkageProperty = {};
linkageRules linkageRules
.filter((k) => !k.disabled) .filter((k) => !k.disabled)
.forEach((v) => { .forEach((v) => {

View File

@ -1,7 +1,9 @@
import type { ISchema } from '@formily/react'; import type { ISchema } from '@formily/react';
import { last } from 'lodash';
import { ActionType } from '../../../schema-settings/LinkageRules/type'; import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { VariableOption, VariablesContextType } from '../../../variables/types'; import { VariableOption, VariablesContextType } from '../../../variables/types';
import { conditionAnalyses } from '../../common/utils/uitls'; import { conditionAnalyses } from '../../common/utils/uitls';
const validateJSON = { const validateJSON = {
validator: `{{(value, rule)=> { validator: `{{(value, rule)=> {
if (!value) { if (!value) {
@ -84,54 +86,52 @@ export const linkageAction = async ({
variables: VariablesContextType; variables: VariablesContextType;
localVariables: VariableOption[]; localVariables: VariableOption[];
}) => { }) => {
field.data = field.data || {}; const disableResult = field?.linkageProperty?.disabled || [false];
const displayResult = field?.linkageProperty?.display || ['visible'];
switch (operator) { switch (operator) {
case ActionType.Visible: case ActionType.Visible:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._display = '_display' in field ? field._display : field.display; displayResult.push(operator);
field.display = operator; field.data = field.data || {};
} else { field.data.hidden = false;
field.display = field._display;
} }
field.linkageProperty = {
...field.linkageProperty,
display: displayResult,
};
field.display = last(displayResult);
break; break;
case ActionType.Hidden: case ActionType.Hidden:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data = field.data || {};
field.data.hidden = true; field.data.hidden = true;
} else { } else {
field.data = field.data || {};
field.data.hidden = false; field.data.hidden = false;
} }
break; break;
case ActionType.Disabled: case ActionType.Disabled:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data.disabled = true; disableResult.push(true);
field.disabled = true;
} else {
field.data.disabled = false;
field.disabled = false;
} }
field.linkageProperty = {
...field.linkageProperty,
disabled: disableResult,
};
field.disabled = last(disableResult);
break; break;
case ActionType.Active: case ActionType.Active:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data.disabled = false; disableResult.push(false);
field.disabled = false;
} else {
field.data.disabled = true;
field.disabled = true;
} }
field.linkageProperty = {
...field.linkageProperty,
disabled: disableResult,
};
field.disabled = last(disableResult);
break; break;
default: default:
return null; return null;
} }
}; };
function reset(field: any) {
field.display = field._display;
field.data.hidden = false;
field.data.disabled = false;
field.disabled = false;
}

View File

@ -1,6 +1,6 @@
import { css } from '@emotion/css'; import { css } from '@emotion/css';
import { FormLayout } from '@formily/antd-v5'; import { FormLayout } from '@formily/antd-v5';
import { createForm, Field, Form as FormilyForm, onFieldInit, onFormInputChange } from '@formily/core'; import { createForm, Field, Form as FormilyForm, onFieldChange, onFieldInit, onFormInputChange } from '@formily/core';
import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react'; import { FieldContext, FormContext, observer, RecursionField, useField, useFieldSchema } from '@formily/react';
import { autorun } from '@formily/reactive'; import { autorun } from '@formily/reactive';
import { uid } from '@formily/shared'; import { uid } from '@formily/shared';
@ -103,31 +103,32 @@ const WithForm = (props: WithFormProps) => {
useEffect(() => { useEffect(() => {
const id = uid(); const id = uid();
const disposes = []; const disposes = [];
const linkagefields = [];
form.addEffects(id, () => { form.addEffects(id, () => {
linkageRules.forEach((v) => { linkageRules.forEach((v, index) => {
v.actions?.forEach((h) => { v.actions?.forEach((h) => {
if (h.targetFields?.length) { if (h.targetFields?.length) {
const fields = h.targetFields.join(','); const fields = h.targetFields.join(',');
onFieldInit(`*(${fields})`, (field: any, form) => {
// 当 `linkageRules` 变更时,需要把 `field` 上之前已设置的值还原成初始值,以防止下面所述的情况: field['initProperty'] = {
// display: field.display,
// 1. 更改 `linkageRules`,使 a 字段满足条件时被隐藏 required: field.required,
// 2. 设置表单,使其满足条件,进而隐藏 a 字段 pattern: field.pattern,
// 3. 再次更改 `linkageRules`,使 a 字段满足条件时被禁用 value: field.value || field.initialValue,
// 4. 设置表单,使其满足条件,会发现 a 字段还是隐藏状态,这里期望的是只显示禁用状态 };
onFieldInit(`*(${fields})`, (field: any) => { });
Object.keys(field).forEach((key) => { onFieldChange(`*(${fields})`, ['value', 'required', 'pattern', 'display'], (field: any) => {
if (key.startsWith('_') && field[key] !== undefined) { field.linkageProperty = {
field[key.slice(1)] = field[key]; display: field.linkageProperty?.display,
} };
});
}); });
// `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 代替 // `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 代替
onFieldInit(`*(${fields})`, (field: any, form) => { onFieldInit(`*(${fields})`, (field: any, form) => {
disposes.push( disposes.push(
autorun(() => { autorun(() => {
linkagefields.push(field);
linkageMergeAction({ linkageMergeAction({
operator: h.operator, operator: h.operator,
value: h.value, value: h.value,
@ -137,6 +138,13 @@ const WithForm = (props: WithFormProps) => {
variables, variables,
localVariables, localVariables,
}); });
if (index === linkageRules.length - 1) {
setTimeout(() =>
linkagefields.map((v) => {
v.linkageProperty = {};
}),
);
}
}), }),
); );
}); });
@ -151,7 +159,7 @@ const WithForm = (props: WithFormProps) => {
dispose(); dispose();
}); });
}; };
}, [JSON.stringify(linkageRules)]); }, [linkageRules]);
return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />; return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />;
}; };

View File

@ -1,7 +1,7 @@
import { Field } from '@formily/core'; import { Field } from '@formily/core';
import { evaluators } from '@nocobase/evaluators/client'; import { evaluators } from '@nocobase/evaluators/client';
import { uid } from '@nocobase/utils'; import { uid } from '@nocobase/utils';
import _, { cloneDeep } from 'lodash'; import _, { cloneDeep, last } from 'lodash';
import { ActionType } from '../../../schema-settings/LinkageRules/type'; import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { VariableOption, VariablesContextType } from '../../../variables/types'; import { VariableOption, VariablesContextType } from '../../../variables/types';
import { REGEX_OF_VARIABLE } from '../../../variables/utils/isVariable'; import { REGEX_OF_VARIABLE } from '../../../variables/utils/isVariable';
@ -28,47 +28,62 @@ export const linkageMergeAction = async ({
variables, variables,
localVariables, localVariables,
}: Props) => { }: 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.value || field?.initProperty?.value];
const { evaluate } = evaluators.get('formula.js'); const { evaluate } = evaluators.get('formula.js');
switch (operator) { switch (operator) {
case ActionType.Required: case ActionType.Required:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.required = true; requiredResult.push(true);
} else {
field.required = false;
} }
field.linkageProperty = {
...field.linkageProperty,
required: requiredResult,
};
field.required = last(field.linkageProperty?.required);
break; break;
case ActionType.InRequired: case ActionType.InRequired:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.required = false; requiredResult.push(false);
} else {
field.required = true;
} }
field.linkageProperty = {
...field.linkageProperty,
required: requiredResult,
};
field.required = last(field.linkageProperty?.required);
break; break;
case ActionType.Visible: case ActionType.Visible:
case ActionType.None: case ActionType.None:
case ActionType.Hidden: case ActionType.Hidden:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._display = '_display' in field ? field._display : field.display; displayResult.push(operator);
field.display = operator;
} }
field.linkageProperty = {
...field.linkageProperty,
display: displayResult,
};
field.display = last(field.linkageProperty?.display);
break; break;
case ActionType.Editable: case ActionType.Editable:
case ActionType.ReadOnly: case ActionType.ReadOnly:
case ActionType.ReadPretty: case ActionType.ReadPretty:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) { if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._pattern = '_pattern' in field ? field._pattern : field.pattern; patternResult.push(operator);
field.pattern = operator;
} else {
field.pattern = field._pattern;
} }
field.linkageProperty = {
...field.linkageProperty,
pattern: patternResult,
};
field.pattern = last(field.linkageProperty.pattern);
break; break;
case ActionType.Value: case ActionType.Value:
if ( if (
isConditionEmpty(condition) || isConditionEmpty(condition) ||
(await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables }))
) { ) {
let result = null;
if (value?.mode === 'express') { if (value?.mode === 'express') {
if ((value.value || value.result) == null) { if ((value.value || value.result) == null) {
return; return;
@ -84,19 +99,22 @@ export const linkageMergeAction = async ({
try { try {
// 2. TODO: 需要把里面解析变量的逻辑删除,因为在上一步已经解析过了 // 2. TODO: 需要把里面解析变量的逻辑删除,因为在上一步已经解析过了
result = evaluate(exp, { ...scope, now: () => new Date().toString(), ...expScope }); const result = evaluate(exp, { ...scope, now: () => new Date().toString(), ...expScope });
valueResult.push(result);
} catch (error) { } catch (error) {
console.error(error); console.error(error);
} }
} else if (value?.mode === 'constant') { } else if (value?.mode === 'constant') {
result = value?.value || value; valueResult.push(value?.value || value);
} else { } else {
result = null; valueResult.push(null);
} }
field._value = '_value' in field ? field._value : field.value;
field.value = result === undefined ? field.value : result; field.linkageProperty = {
} else { ...field.linkageProperty,
field.value = field._value; value: valueResult,
};
field.value = last(valueResult) === undefined ? field.value : last(valueResult);
} }
break; break;
default: default:

View File

@ -97,6 +97,7 @@ export const CreateRecordAction = observer(
const localVariables = useLocalVariables({ currentForm: { values } as any }); const localVariables = useLocalVariables({ currentForm: { values } as any });
useEffect(() => { useEffect(() => {
field.linkageProperty = {};
linkageRules linkageRules
.filter((k) => !k.disabled) .filter((k) => !k.disabled)
.forEach((v) => { .forEach((v) => {
@ -201,6 +202,7 @@ export const CreateAction = observer(
}, [menuItems]); }, [menuItems]);
useEffect(() => { useEffect(() => {
field.linkageProperty = {};
linkageRules linkageRules
.filter((k) => !k.disabled) .filter((k) => !k.disabled)
.forEach((v) => { .forEach((v) => {