mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:48:13 +08:00
fix: ConditionBuilder使用公式编辑器切换类型异常问题
This commit is contained in:
parent
f210a93d9a
commit
a02a2e3c3e
@ -96,7 +96,9 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
|||||||
|
|
||||||
@autobind
|
@autobind
|
||||||
handleOperatorChange(op: OperatorType) {
|
handleOperatorChange(op: OperatorType) {
|
||||||
const {fields, value, index, onChange} = this.props;
|
const {fields, value, index, onChange, formula} = this.props;
|
||||||
|
const useFormulaInput =
|
||||||
|
formula?.mode === 'input-group' && formula?.inputSettings;
|
||||||
const leftFieldSchema: FieldSimple = findTree(
|
const leftFieldSchema: FieldSimple = findTree(
|
||||||
fields,
|
fields,
|
||||||
(i: FieldSimple) => i.name === (value?.left as ExpressionField)?.field
|
(i: FieldSimple) => i.name === (value?.left as ExpressionField)?.field
|
||||||
@ -104,7 +106,10 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
|||||||
const result = {
|
const result = {
|
||||||
...value,
|
...value,
|
||||||
op: op,
|
op: op,
|
||||||
right: value.right ?? leftFieldSchema?.defaultValue
|
/** 使用公式编辑器模式时,因为不同条件下值格式不一致(比如select类型下包含和等于对应的multiple会变化),所以变化条件时需要清空right值 */
|
||||||
|
right: useFormulaInput
|
||||||
|
? leftFieldSchema?.defaultValue
|
||||||
|
: value.right ?? leftFieldSchema?.defaultValue
|
||||||
};
|
};
|
||||||
|
|
||||||
onChange(result, index);
|
onChange(result, index);
|
||||||
|
@ -191,6 +191,15 @@ export class FormulaEditor extends React.Component<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof value !== 'string') {
|
||||||
|
try {
|
||||||
|
value = JSON.stringify(value);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[amis][formula] given value is not a string');
|
||||||
|
value = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const varMap: {
|
const varMap: {
|
||||||
[propname: string]: string;
|
[propname: string]: string;
|
||||||
} = {};
|
} = {};
|
||||||
|
@ -9,7 +9,8 @@ import {
|
|||||||
LocaleProps,
|
LocaleProps,
|
||||||
uncontrollable,
|
uncontrollable,
|
||||||
findTree,
|
findTree,
|
||||||
isExpression
|
isExpression,
|
||||||
|
isObject
|
||||||
} from 'amis-core';
|
} from 'amis-core';
|
||||||
|
|
||||||
import {FormulaEditor, VariableItem} from './Editor';
|
import {FormulaEditor, VariableItem} from './Editor';
|
||||||
@ -96,9 +97,35 @@ const FormulaInput: React.FC<FormulaInputProps> = props => {
|
|||||||
if (schemaType === 'boolean') {
|
if (schemaType === 'boolean') {
|
||||||
result = origin.value;
|
result = origin.value;
|
||||||
} else if (schemaType === 'select') {
|
} else if (schemaType === 'select') {
|
||||||
result = Array.isArray(origin)
|
const {
|
||||||
? origin.map(item => item.value)
|
joinValues,
|
||||||
: origin.value;
|
extractValue,
|
||||||
|
delimiter,
|
||||||
|
multiple,
|
||||||
|
valueField = 'value'
|
||||||
|
} = inputSettings;
|
||||||
|
|
||||||
|
if (joinValues) {
|
||||||
|
if (multiple) {
|
||||||
|
result = Array.isArray(origin)
|
||||||
|
? (origin.map(item => item[valueField]).join(delimiter) as string)
|
||||||
|
: origin
|
||||||
|
? origin[valueField]
|
||||||
|
: '';
|
||||||
|
} else {
|
||||||
|
result = origin ? origin[valueField] : '';
|
||||||
|
}
|
||||||
|
} else if (extractValue) {
|
||||||
|
if (multiple) {
|
||||||
|
result = Array.isArray(origin)
|
||||||
|
? origin.map(item => item[valueField])
|
||||||
|
: origin
|
||||||
|
? [origin[valueField || 'value']]
|
||||||
|
: [];
|
||||||
|
} else {
|
||||||
|
result = origin ? origin[valueField] : '';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
onChange?.(result);
|
onChange?.(result);
|
||||||
},
|
},
|
||||||
@ -123,26 +150,58 @@ const FormulaInput: React.FC<FormulaInputProps> = props => {
|
|||||||
: cmptValue === item?.value;
|
: cmptValue === item?.value;
|
||||||
})
|
})
|
||||||
: null;
|
: null;
|
||||||
|
let useVariable = !!(isExpression(cmptValue) || targetVariable);
|
||||||
|
|
||||||
if (
|
/** 判断value是否为变量,如果是变量,使用ResultBox渲染 */
|
||||||
isExpression(cmptValue) ||
|
if (!useVariable) {
|
||||||
targetVariable ||
|
if (schemaType === 'number') {
|
||||||
(schemaType === 'number' &&
|
useVariable = cmptValue != null && typeof cmptValue !== 'number';
|
||||||
cmptValue != null &&
|
} else if (['date', 'time', 'datetime'].includes(schemaType)) {
|
||||||
typeof cmptValue !== 'number') ||
|
useVariable = !moment(cmptValue).isValid();
|
||||||
(['date', 'time', 'datetime'].includes(schemaType) &&
|
} else if (schemaType === 'select') {
|
||||||
!moment(cmptValue).isValid()) ||
|
const {
|
||||||
(schemaType === 'select' &&
|
options,
|
||||||
cmptValue != null &&
|
joinValues,
|
||||||
!(inputSettings?.options ?? []).some(
|
extractValue,
|
||||||
(item: any) => item?.value === cmptValue
|
delimiter,
|
||||||
)) ||
|
multiple,
|
||||||
(schemaType === 'boolean' &&
|
valueField = 'value'
|
||||||
cmptValue != null &&
|
} = inputSettings;
|
||||||
typeof cmptValue !== 'boolean')
|
let selctedValue: any[] = [];
|
||||||
) {
|
|
||||||
|
if (multiple) {
|
||||||
|
if (joinValues) {
|
||||||
|
selctedValue =
|
||||||
|
typeof cmptValue === 'string' ? cmptValue.split(delimiter) : [];
|
||||||
|
} else {
|
||||||
|
selctedValue = Array.isArray(cmptValue)
|
||||||
|
? extractValue
|
||||||
|
? cmptValue
|
||||||
|
: cmptValue.map(i => i?.[valueField])
|
||||||
|
: [];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (joinValues) {
|
||||||
|
selctedValue = typeof cmptValue === 'string' ? [cmptValue] : [];
|
||||||
|
} else {
|
||||||
|
selctedValue = isObject(cmptValue) ? [cmptValue?.[valueField]] : [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 选项类型清空后是空字符串, */
|
||||||
|
useVariable =
|
||||||
|
cmptValue &&
|
||||||
|
!(options ?? []).some((item: any) =>
|
||||||
|
selctedValue.includes(item?.value)
|
||||||
|
);
|
||||||
|
} else if (schemaType === 'boolean') {
|
||||||
|
useVariable = cmptValue != null && typeof cmptValue !== 'boolean';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useVariable) {
|
||||||
const varName =
|
const varName =
|
||||||
cmptValue && mixedMode
|
typeof cmptValue === 'string' && cmptValue && mixedMode
|
||||||
? cmptValue.replace(/^\$\{/, '').replace(/\}$/, '')
|
? cmptValue.replace(/^\$\{/, '').replace(/\}$/, '')
|
||||||
: cmptValue;
|
: cmptValue;
|
||||||
const resultValue = targetVariable?.value ?? varName;
|
const resultValue = targetVariable?.value ?? varName;
|
||||||
|
@ -14,10 +14,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {fireEvent, render, screen, waitFor} from '@testing-library/react';
|
import {fireEvent, render, screen, cleanup, waitFor} from '@testing-library/react';
|
||||||
import '../../../src';
|
import '../../../src';
|
||||||
import {render as amisRender} from '../../../src';
|
import {render as amisRender, clearStoresCache} from '../../../src';
|
||||||
import {makeEnv, replaceReactAriaIds, wait} from '../../helper';
|
import {makeEnv, replaceReactAriaIds, wait} from '../../helper';
|
||||||
|
import { Select } from 'packages/amis-ui/lib/components/Select';
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
cleanup();
|
||||||
|
clearStoresCache();
|
||||||
|
jest.useRealTimers();
|
||||||
|
});
|
||||||
|
|
||||||
const testSchema = {
|
const testSchema = {
|
||||||
type: 'page',
|
type: 'page',
|
||||||
@ -801,3 +808,341 @@ test('Renderer:condition-builder with not embed', async () => {
|
|||||||
baseElement.querySelector('.cxd-Modal .cxd-CBGroup')
|
baseElement.querySelector('.cxd-Modal .cxd-CBGroup')
|
||||||
).toBeInTheDocument();
|
).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 组合条件使用公式编辑器
|
||||||
|
* 1. 7种类型的公式编辑器正常渲染
|
||||||
|
* 2. 选项类型(select)字段,切换操作符(包含 -> 等于),字段值清空且正常渲染(等于和包含对应的multiple不一样,所以值格式不一样)
|
||||||
|
* 3. 先使用其他类型字段,再切换到select类型,条件选择包含,值正常渲染
|
||||||
|
*/
|
||||||
|
describe.only('Renderer: condition-builder with formula', () => {
|
||||||
|
const onSubmit = jest.fn();
|
||||||
|
test('condition-builder with different fields', async () => {
|
||||||
|
const {container} = render(amisRender({
|
||||||
|
"type": "form",
|
||||||
|
"data": {
|
||||||
|
"conditions": {
|
||||||
|
"id": "68bddc1495e9",
|
||||||
|
"conjunction": "and",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "b9cc34dae93a",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "text"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "4c718986c321",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "number"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "7ee79c416422",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "boolean"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "9cd76d8a6522",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "select"
|
||||||
|
},
|
||||||
|
"op": "select_equals"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "20a65e9df546",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "date"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "e729b32ea9e8",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "time"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "a5f48e000557",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "datetime"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "condition-builder",
|
||||||
|
"label": "条件组件",
|
||||||
|
"name": "conditions",
|
||||||
|
"searchable": true,
|
||||||
|
"formula": {
|
||||||
|
"mode": "input-group",
|
||||||
|
"inputSettings": {},
|
||||||
|
"allowInput": true,
|
||||||
|
"mixedMode": true,
|
||||||
|
"variables": []
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"label": "文本",
|
||||||
|
"type": "text",
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "数字",
|
||||||
|
"type": "number",
|
||||||
|
"name": "number"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "布尔",
|
||||||
|
"type": "boolean",
|
||||||
|
"name": "boolean"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "选项",
|
||||||
|
"type": "select",
|
||||||
|
"name": "select",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "A",
|
||||||
|
"value": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "B",
|
||||||
|
"value": "b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "C",
|
||||||
|
"value": "c"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "日期",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"label": "日期",
|
||||||
|
"type": "date",
|
||||||
|
"name": "date"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "时间",
|
||||||
|
"type": "time",
|
||||||
|
"name": "time"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "日期时间",
|
||||||
|
"type": "datetime",
|
||||||
|
"name": "datetime"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {onSubmit}, makeEnv({})));
|
||||||
|
|
||||||
|
replaceReactAriaIds(container);
|
||||||
|
// 7种类型都存在
|
||||||
|
expect(container.querySelectorAll('.cxd-FormulaPicker-input')?.length).toEqual(7);
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker--text')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-number')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-boolean')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-select')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-date')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-time')).toBeInTheDocument();
|
||||||
|
expect(container.querySelector('.cxd-FormulaPicker-input-datetime')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('condition-builder with select field and change operator', async () => {
|
||||||
|
const {container, findByText} = render(amisRender({
|
||||||
|
"type": "form",
|
||||||
|
"data": {
|
||||||
|
"conditions": {
|
||||||
|
"id": "68bddc1495e9",
|
||||||
|
"conjunction": "and",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "9cd76d8a6522",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "select"
|
||||||
|
},
|
||||||
|
"op": "select_equals"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "condition-builder",
|
||||||
|
"label": "条件组件",
|
||||||
|
"name": "conditions",
|
||||||
|
"searchable": true,
|
||||||
|
"formula": {
|
||||||
|
"mode": "input-group",
|
||||||
|
"inputSettings": {},
|
||||||
|
"allowInput": true,
|
||||||
|
"mixedMode": true,
|
||||||
|
"variables": []
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"label": "选项",
|
||||||
|
"type": "select",
|
||||||
|
"name": "select",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "A",
|
||||||
|
"value": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "B",
|
||||||
|
"value": "b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "C",
|
||||||
|
"value": "c"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {}, makeEnv({})));
|
||||||
|
|
||||||
|
replaceReactAriaIds(container);
|
||||||
|
|
||||||
|
// 选中第一个选项(Form中默认值是等于操作)
|
||||||
|
let fieldValueControl = container.querySelector('.cxd-FormulaPicker-input-select')!;
|
||||||
|
fireEvent.click(fieldValueControl);
|
||||||
|
await wait(100);
|
||||||
|
fireEvent.click(await findByText('A'));
|
||||||
|
expect(container.querySelector('.cxd-Tag-text')?.innerHTML).toEqual('A');
|
||||||
|
|
||||||
|
// 切换操作符,字段值清空,需要重新选择,且下拉选项变成多选
|
||||||
|
const opControl = container.querySelector('.cxd-CBGroup-operatorInput')!;
|
||||||
|
fireEvent.click(opControl);
|
||||||
|
await wait(100);
|
||||||
|
fireEvent.click(await findByText('包含'));
|
||||||
|
await wait(100);
|
||||||
|
expect(container.querySelector('.cxd-Select-placeholder')).toBeInTheDocument();
|
||||||
|
fieldValueControl = container.querySelector('.cxd-FormulaPicker-input-select')!;
|
||||||
|
fireEvent.click(fieldValueControl);
|
||||||
|
await wait(100);
|
||||||
|
expect(container.querySelectorAll('.cxd-Select-option-checkbox').length).toEqual(3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('condition-builder with field type change', async () => {
|
||||||
|
const onSubmit = jest.fn();
|
||||||
|
const {container, findByText, findByPlaceholderText} = render(amisRender({
|
||||||
|
"type": "form",
|
||||||
|
"data": {
|
||||||
|
"conditions": {
|
||||||
|
"id": "68bddc1495e9",
|
||||||
|
"conjunction": "and",
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"id": "b9cc34dae93a",
|
||||||
|
"left": {
|
||||||
|
"type": "field",
|
||||||
|
"field": "text"
|
||||||
|
},
|
||||||
|
"op": "equal"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"body": [
|
||||||
|
{
|
||||||
|
"type": "condition-builder",
|
||||||
|
"label": "条件组件",
|
||||||
|
"name": "conditions",
|
||||||
|
"searchable": true,
|
||||||
|
"formula": {
|
||||||
|
"mode": "input-group",
|
||||||
|
"inputSettings": {},
|
||||||
|
"allowInput": true,
|
||||||
|
"mixedMode": true,
|
||||||
|
"variables": []
|
||||||
|
},
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"label": "文本",
|
||||||
|
"type": "text",
|
||||||
|
"name": "text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "选项",
|
||||||
|
"type": "select",
|
||||||
|
"name": "select",
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"label": "A",
|
||||||
|
"value": "a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "B",
|
||||||
|
"value": "b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "C",
|
||||||
|
"value": "c"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {onSubmit}, makeEnv({})));
|
||||||
|
|
||||||
|
replaceReactAriaIds(container);
|
||||||
|
|
||||||
|
// 切换字段类型,对应字段值控件更新
|
||||||
|
const fieldControl = container.querySelector('.cxd-DropDownSelection-input')!;
|
||||||
|
fireEvent.click(fieldControl);
|
||||||
|
await wait(100);
|
||||||
|
fireEvent.click(await findByText('选项'));
|
||||||
|
await wait(100);
|
||||||
|
let selectValueControl = container.querySelector('.cxd-FormulaPicker-input-select')!;
|
||||||
|
expect(selectValueControl).toBeInTheDocument();
|
||||||
|
|
||||||
|
// 切换操作符,下拉选项变成多选
|
||||||
|
const opControl = container.querySelector('.cxd-CBGroup-operatorInput')!;
|
||||||
|
fireEvent.click(opControl);
|
||||||
|
await wait(100);
|
||||||
|
fireEvent.click(await findByText('包含'));
|
||||||
|
await wait(100);
|
||||||
|
expect(container.querySelector('.cxd-Select-placeholder')).toBeInTheDocument();
|
||||||
|
selectValueControl = container.querySelector('.cxd-FormulaPicker-input-select')!;
|
||||||
|
fireEvent.click(selectValueControl);
|
||||||
|
await wait(100);
|
||||||
|
expect(container.querySelectorAll('.cxd-Select-option-checkbox').length).toEqual(3);
|
||||||
|
|
||||||
|
// 选择2个选项,绑定值变化
|
||||||
|
fireEvent.click(await findByText('A'));
|
||||||
|
fireEvent.click(await findByText('C'));
|
||||||
|
const selectedValues = [];
|
||||||
|
const nodes = container.querySelectorAll('.cxd-Select-valueLabel');
|
||||||
|
for (const el of nodes.values()) {
|
||||||
|
selectedValues.push(el?.innerHTML);
|
||||||
|
}
|
||||||
|
expect(selectedValues.length).toEqual(2);
|
||||||
|
expect(selectedValues.join(',')).toEqual('A,C');
|
||||||
|
});
|
||||||
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user