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);
actionTitle = lodash.isString(actionTitle) ? t(actionTitle) : actionTitle;
useEffect(() => {
field.linkageProperty = {};
linkageRules
.filter((k) => !k.disabled)
.forEach((v) => {

View File

@ -1,7 +1,9 @@
import type { ISchema } from '@formily/react';
import { last } from 'lodash';
import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { VariableOption, VariablesContextType } from '../../../variables/types';
import { conditionAnalyses } from '../../common/utils/uitls';
const validateJSON = {
validator: `{{(value, rule)=> {
if (!value) {
@ -84,54 +86,52 @@ export const linkageAction = async ({
variables: VariablesContextType;
localVariables: VariableOption[];
}) => {
field.data = field.data || {};
const disableResult = field?.linkageProperty?.disabled || [false];
const displayResult = field?.linkageProperty?.display || ['visible'];
switch (operator) {
case ActionType.Visible:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._display = '_display' in field ? field._display : field.display;
field.display = operator;
} else {
field.display = field._display;
displayResult.push(operator);
field.data = field.data || {};
field.data.hidden = false;
}
field.linkageProperty = {
...field.linkageProperty,
display: displayResult,
};
field.display = last(displayResult);
break;
case ActionType.Hidden:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data = field.data || {};
field.data.hidden = true;
} else {
field.data = field.data || {};
field.data.hidden = false;
}
break;
case ActionType.Disabled:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data.disabled = true;
field.disabled = true;
} else {
field.data.disabled = false;
field.disabled = false;
disableResult.push(true);
}
field.linkageProperty = {
...field.linkageProperty,
disabled: disableResult,
};
field.disabled = last(disableResult);
break;
case ActionType.Active:
reset(field);
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.data.disabled = false;
field.disabled = false;
} else {
field.data.disabled = true;
field.disabled = true;
disableResult.push(false);
}
field.linkageProperty = {
...field.linkageProperty,
disabled: disableResult,
};
field.disabled = last(disableResult);
break;
default:
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 { 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 { autorun } from '@formily/reactive';
import { uid } from '@formily/shared';
@ -103,31 +103,32 @@ const WithForm = (props: WithFormProps) => {
useEffect(() => {
const id = uid();
const disposes = [];
const linkagefields = [];
form.addEffects(id, () => {
linkageRules.forEach((v) => {
linkageRules.forEach((v, index) => {
v.actions?.forEach((h) => {
if (h.targetFields?.length) {
const fields = h.targetFields.join(',');
// 当 `linkageRules` 变更时,需要把 `field` 上之前已设置的值还原成初始值,以防止下面所述的情况:
//
// 1. 更改 `linkageRules`,使 a 字段满足条件时被隐藏
// 2. 设置表单,使其满足条件,进而隐藏 a 字段
// 3. 再次更改 `linkageRules`,使 a 字段满足条件时被禁用
// 4. 设置表单,使其满足条件,会发现 a 字段还是隐藏状态,这里期望的是只显示禁用状态
onFieldInit(`*(${fields})`, (field: any) => {
Object.keys(field).forEach((key) => {
if (key.startsWith('_') && field[key] !== undefined) {
field[key.slice(1)] = field[key];
}
onFieldInit(`*(${fields})`, (field: any, form) => {
field['initProperty'] = {
display: field.display,
required: field.required,
pattern: field.pattern,
value: field.value || field.initialValue,
};
});
onFieldChange(`*(${fields})`, ['value', 'required', 'pattern', 'display'], (field: any) => {
field.linkageProperty = {
display: field.linkageProperty?.display,
};
});
// `onFieldReact` 有问题,没有办法被取消监听,所以这里用 `onFieldInit` 代替
onFieldInit(`*(${fields})`, (field: any, form) => {
disposes.push(
autorun(() => {
linkagefields.push(field);
linkageMergeAction({
operator: h.operator,
value: h.value,
@ -137,6 +138,13 @@ const WithForm = (props: WithFormProps) => {
variables,
localVariables,
});
if (index === linkageRules.length - 1) {
setTimeout(() =>
linkagefields.map((v) => {
v.linkageProperty = {};
}),
);
}
}),
);
});
@ -151,7 +159,7 @@ const WithForm = (props: WithFormProps) => {
dispose();
});
};
}, [JSON.stringify(linkageRules)]);
}, [linkageRules]);
return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />;
};

View File

@ -1,7 +1,7 @@
import { Field } from '@formily/core';
import { evaluators } from '@nocobase/evaluators/client';
import { uid } from '@nocobase/utils';
import _, { cloneDeep } from 'lodash';
import _, { cloneDeep, last } from 'lodash';
import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { VariableOption, VariablesContextType } from '../../../variables/types';
import { REGEX_OF_VARIABLE } from '../../../variables/utils/isVariable';
@ -28,47 +28,62 @@ export const linkageMergeAction = async ({
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.value || field?.initProperty?.value];
const { evaluate } = evaluators.get('formula.js');
switch (operator) {
case ActionType.Required:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.required = true;
} else {
field.required = false;
requiredResult.push(true);
}
field.linkageProperty = {
...field.linkageProperty,
required: requiredResult,
};
field.required = last(field.linkageProperty?.required);
break;
case ActionType.InRequired:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field.required = false;
} else {
field.required = true;
requiredResult.push(false);
}
field.linkageProperty = {
...field.linkageProperty,
required: requiredResult,
};
field.required = last(field.linkageProperty?.required);
break;
case ActionType.Visible:
case ActionType.None:
case ActionType.Hidden:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._display = '_display' in field ? field._display : field.display;
field.display = operator;
displayResult.push(operator);
}
field.linkageProperty = {
...field.linkageProperty,
display: displayResult,
};
field.display = last(field.linkageProperty?.display);
break;
case ActionType.Editable:
case ActionType.ReadOnly:
case ActionType.ReadPretty:
if (await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables })) {
field._pattern = '_pattern' in field ? field._pattern : field.pattern;
field.pattern = operator;
} else {
field.pattern = field._pattern;
patternResult.push(operator);
}
field.linkageProperty = {
...field.linkageProperty,
pattern: patternResult,
};
field.pattern = last(field.linkageProperty.pattern);
break;
case ActionType.Value:
if (
isConditionEmpty(condition) ||
(await conditionAnalyses({ rules: condition, formValues: values, variables, localVariables }))
) {
let result = null;
if (value?.mode === 'express') {
if ((value.value || value.result) == null) {
return;
@ -84,19 +99,22 @@ export const linkageMergeAction = async ({
try {
// 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) {
console.error(error);
}
} else if (value?.mode === 'constant') {
result = value?.value || value;
valueResult.push(value?.value || value);
} else {
result = null;
valueResult.push(null);
}
field._value = '_value' in field ? field._value : field.value;
field.value = result === undefined ? field.value : result;
} else {
field.value = field._value;
field.linkageProperty = {
...field.linkageProperty,
value: valueResult,
};
field.value = last(valueResult) === undefined ? field.value : last(valueResult);
}
break;
default:

View File

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