mirror of
https://gitee.com/baidu/amis.git
synced 2024-11-29 18:39:05 +08:00
feat:ConditionBuilder支持自定义判断条件和右边渲染组件;优化ConditionBuilder样式 (#3887)
Co-authored-by: Qin,Haoyan <qinhaoyan@baidu.com>
This commit is contained in:
parent
42cbec8f44
commit
b2d2b27031
@ -73,55 +73,33 @@ exports[`Renderer:condition-builder 1`] = `
|
||||
class="cxd-CBGroup"
|
||||
>
|
||||
<div
|
||||
class="cxd-CBGroup-toolbar"
|
||||
class="cxd-CBGroup-toolbarCondition"
|
||||
>
|
||||
<div
|
||||
class="cxd-CBGroup-toolbarCondition"
|
||||
aria-expanded="false"
|
||||
aria-haspopup="listbox"
|
||||
aria-labelledby="downshift-0-label"
|
||||
class="cxd-Select"
|
||||
role="combobox"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="cxd-ButtonGroup"
|
||||
class="cxd-Select-valueWrap"
|
||||
>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--xs is-active"
|
||||
type="button"
|
||||
<div
|
||||
class="cxd-Select-value"
|
||||
>
|
||||
并且
|
||||
</button>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--xs"
|
||||
type="button"
|
||||
>
|
||||
或者
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-CBGroup-toolbarConditionAdd"
|
||||
>
|
||||
<div
|
||||
class="cxd-ButtonGroup"
|
||||
<span
|
||||
class="cxd-Select-arrow"
|
||||
>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--xs"
|
||||
type="button"
|
||||
>
|
||||
<icon-mock
|
||||
classname="icon icon-plus"
|
||||
icon="plus"
|
||||
/>
|
||||
添加条件
|
||||
</button>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--default cxd-Button--xs"
|
||||
type="button"
|
||||
>
|
||||
<icon-mock
|
||||
classname="icon icon-plus-cicle"
|
||||
icon="plus-cicle"
|
||||
/>
|
||||
添加条件组
|
||||
</button>
|
||||
</div>
|
||||
<icon-mock
|
||||
classname="icon icon-caret"
|
||||
icon="caret"
|
||||
/>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
@ -133,6 +111,30 @@ exports[`Renderer:condition-builder 1`] = `
|
||||
空
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="cxd-CBGroup-toolbar"
|
||||
>
|
||||
<div
|
||||
class="cxd-CBGroup-toolbarConditionAdd"
|
||||
>
|
||||
<div
|
||||
class="cxd-ButtonGroup"
|
||||
>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--link cxd-Button--xs"
|
||||
type="button"
|
||||
>
|
||||
添加条件
|
||||
</button>
|
||||
<button
|
||||
class="cxd-Button cxd-Button--link cxd-Button--xs"
|
||||
type="button"
|
||||
>
|
||||
添加条件组
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span
|
||||
|
@ -384,6 +384,97 @@ type Value = ValueGroup;
|
||||
}
|
||||
```
|
||||
|
||||
### 自定义
|
||||
|
||||
- `type` 字段配置中配置成 `"custom"`
|
||||
- `label` 字段名称
|
||||
- `placeholder` 占位符
|
||||
- `operators` 默认为空,需配置自定义判断条件,支持字符串或 key-value 格式
|
||||
- `value` 字段配置右边值需要渲染的组件,支持 amis 输入类组件或自定义输入类组件
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "condition-builder",
|
||||
"label": "条件组件",
|
||||
"name": "conditions",
|
||||
"description": "适合让用户自己拼查询条件,然后后端根据数据生成 query where",
|
||||
"fields": [
|
||||
{
|
||||
"label": "自定义",
|
||||
"type": "custom",
|
||||
"name": "a",
|
||||
"value": {
|
||||
"type": "input-color"
|
||||
},
|
||||
"operators": [
|
||||
"equal",
|
||||
{
|
||||
"label": "等于(自定义)",
|
||||
"value": "custom_equal"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
其中`operators`通过配置 values 还支持右边多个组件的渲染,`right`值格式为对象,`key`为组件的`name`
|
||||
|
||||
```schema: scope="body"
|
||||
{
|
||||
"type": "form",
|
||||
"debug": true,
|
||||
"body": [
|
||||
{
|
||||
"type": "condition-builder",
|
||||
"label": "条件组件",
|
||||
"name": "conditions",
|
||||
"description": "适合让用户自己拼查询条件,然后后端根据数据生成 query where",
|
||||
"fields": [
|
||||
{
|
||||
"label": "自定义",
|
||||
"type": "custom",
|
||||
"name": "a",
|
||||
"value": {
|
||||
"type": "input-color"
|
||||
},
|
||||
"operators": [
|
||||
{
|
||||
"label": "等于(自定义)",
|
||||
"value": "custom_equal"
|
||||
},
|
||||
{
|
||||
"label": "属于",
|
||||
"value": "belong",
|
||||
"values": [
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "color1"
|
||||
},
|
||||
{
|
||||
"type": "tpl",
|
||||
"tpl": "~"
|
||||
},
|
||||
{
|
||||
"type": "input-text",
|
||||
"name": "color2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
## 字段选项远程拉取
|
||||
|
||||
- 方式 1 配置 `source` 接口返回的数据对象 `data` 中存在 fields 变量即可。
|
||||
@ -593,4 +684,4 @@ type Value = ValueGroup;
|
||||
| fields | | | 字段配置 |
|
||||
| showANDOR | `boolean` | | 用于 simple 模式下显示切换按钮 |
|
||||
| showNot | `boolean` | | 是否显示「非」按钮 |
|
||||
| searchable | `boolean` | | 字段是否可搜索 |
|
||||
| searchable | `boolean` | | 字段是否可搜索 |
|
||||
|
@ -28,6 +28,46 @@ export default {
|
||||
description:
|
||||
'适合让用户自己拼查询条件,然后后端根据数据生成 query where',
|
||||
fields: [
|
||||
{
|
||||
name: 'switch',
|
||||
type: 'custom',
|
||||
label: '开关',
|
||||
value: {
|
||||
name: 'checkbox',
|
||||
type: 'checkbox',
|
||||
label: '勾选框',
|
||||
option: '选项说明'
|
||||
},
|
||||
operators: [
|
||||
'equal',
|
||||
{
|
||||
label: '属于',
|
||||
value: 'belong'
|
||||
},
|
||||
{
|
||||
label: '不属于',
|
||||
value: 'not_belong',
|
||||
values: [
|
||||
{
|
||||
type: 'input-date',
|
||||
name: 'date1',
|
||||
label: '日期',
|
||||
inputFormat: 'YYYY年MM月DD日'
|
||||
},
|
||||
{
|
||||
type: 'tpl',
|
||||
tpl: '~'
|
||||
},
|
||||
{
|
||||
type: 'input-date',
|
||||
name: 'date2',
|
||||
label: '日期',
|
||||
inputFormat: 'YYYY年MM月DD日'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '文本',
|
||||
type: 'text',
|
||||
|
@ -1,11 +1,36 @@
|
||||
.#{$ns}CBGroup {
|
||||
font-size: var(--fontSizeSm);
|
||||
position: relative;
|
||||
border: 1px solid #e8e9eb;
|
||||
border-radius: 4px;
|
||||
border-left: px2rem(3px) solid #e6f0ff;
|
||||
padding: px2rem(30px) px2rem(27px) px2rem(17px);
|
||||
margin-top: px2rem(30px);
|
||||
&-toolbarCondition {
|
||||
text-align: center;
|
||||
margin-top: px2rem(-44px);
|
||||
margin-bottom: px2rem(16px);
|
||||
.#{$ns}Select {
|
||||
font-size: 12px;
|
||||
height: px2rem(28px);
|
||||
width: px2rem(62px);
|
||||
background: #d4e5ff;
|
||||
border: none;
|
||||
color: #0832a6;
|
||||
font-weight: 500;
|
||||
padding: 0;
|
||||
padding-left: px2rem(8px);
|
||||
min-height: px2rem(28px);
|
||||
&:hover {
|
||||
background: #d4e5ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-toolbar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding-bottom: 10px;
|
||||
|
||||
margin-top: px2rem(8px);
|
||||
.#{$ns}Button {
|
||||
transition: padding var(--animation-duration);
|
||||
min-width: unset;
|
||||
@ -18,29 +43,22 @@
|
||||
}
|
||||
}
|
||||
|
||||
&:not(:hover)
|
||||
.#{$ns}CBGroup-toolbarCondition
|
||||
.#{$ns}Button:not(.is-active) {
|
||||
width: 0;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
opacity: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.#{$ns}CBGroup-toolbarConditionAdd {
|
||||
transition: opacity var(--animation-duration);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.#{$ns}ButtonGroup {
|
||||
& > .cxd-Button:first-child {
|
||||
margin-right: px2rem(24px);
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}CBDelete {
|
||||
margin-left: var(--gap-xs);
|
||||
}
|
||||
}
|
||||
&:not(:hover) .#{$ns}CBGroup-toolbarConditionAdd {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.#{$ns}ResultBox {
|
||||
padding-right: px2rem(3px);
|
||||
}
|
||||
|
||||
&-field,
|
||||
@ -76,92 +94,79 @@
|
||||
&-placeholder {
|
||||
color: var(--text--muted-color);
|
||||
position: relative;
|
||||
margin-left: 30px;
|
||||
padding: 10px;
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
border-radius: 5px;
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: -10px;
|
||||
left: -30px;
|
||||
width: var(--gap-md);
|
||||
border-left: solid 1px var(--borderColor);
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 50%;
|
||||
width: var(--gap-md);
|
||||
left: -30px;
|
||||
border-top: solid 1px var(--borderColor);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:before {
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom: solid 1px var(--borderColor);
|
||||
bottom: 50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.simple {
|
||||
margin-left: 0;
|
||||
&:before {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-toolbarCondition {
|
||||
margin-right: var(--gap-base);
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}CBDelete {
|
||||
@include icon-color();
|
||||
cursor: pointer;
|
||||
margin-left: auto;
|
||||
transition: opacity var(--animation-duration);
|
||||
}
|
||||
|
||||
.#{$ns}CBGroupOrItem-body-group--hover {
|
||||
& > .#{$ns}CBGroupOrItem-dragbar {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
& > .#{$ns}CBGroup {
|
||||
border-left-color: #2468f1;
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}CBGroupOrItem {
|
||||
position: relative;
|
||||
margin-left: px2rem(30px);
|
||||
|
||||
& + & {
|
||||
margin-top: px2rem(10px);
|
||||
}
|
||||
&-dragbar {
|
||||
cursor: move;
|
||||
width: 20px;
|
||||
margin-left: -5px;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
transition: opacity var(--animation-duration) ease-out;
|
||||
@include icon-color();
|
||||
}
|
||||
|
||||
&-body {
|
||||
display: flex;
|
||||
padding: 2px 7px;
|
||||
border-radius: 5px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
transition: all var(--animation-duration) ease-out;
|
||||
|
||||
> .#{$ns}CBGroup {
|
||||
margin: 3px;
|
||||
&-group {
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-top: px2rem(16px);
|
||||
> .#{$ns}CBGroupOrItem-dragbar {
|
||||
left: px2rem(-16px);
|
||||
position: absolute;
|
||||
}
|
||||
> .#{$ns}CBGroup {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&-body:not(:hover) .#{$ns}CBDelete {
|
||||
opacity: 0;
|
||||
&-item {
|
||||
background-color: #f7f7f9;
|
||||
width: 100%;
|
||||
padding: px2rem(12px);
|
||||
padding-left: px2rem(28px);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
> .#{$ns}CBGroupOrItem-dragbar {
|
||||
left: px2rem(10px);
|
||||
position: absolute;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.is-dragging {
|
||||
@ -179,59 +184,19 @@
|
||||
background: rgba($info, 0.2);
|
||||
}
|
||||
|
||||
&-dragbar {
|
||||
cursor: move;
|
||||
width: 20px;
|
||||
margin-left: -5px;
|
||||
opacity: 0.6;
|
||||
text-align: center;
|
||||
transition: opacity var(--animation-duration) ease-out;
|
||||
@include icon-color();
|
||||
}
|
||||
|
||||
.#{$ns}CBGroup {
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
&:hover > &-body {
|
||||
background: rgba(0, 0, 0, 0.05);
|
||||
& > &-body > &-body-group > &-dragbar,
|
||||
& > &-body > &-body-item > &-dragbar {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
&:hover > &-body > &-dragbar {
|
||||
&:hover > &-body > &-body-item > &-dragbar {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: -10px;
|
||||
left: -30px;
|
||||
width: 20px;
|
||||
border-left: solid 1px var(--borderColor);
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 50%;
|
||||
width: 20px;
|
||||
left: -30px;
|
||||
border-top: solid 1px var(--borderColor);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:before {
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom: solid 1px var(--borderColor);
|
||||
bottom: 50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
&-simple {
|
||||
margin-bottom: var(--gap-sm);
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import {Config} from './config';
|
||||
import InputBox from '../InputBox';
|
||||
import Formula from './Formula';
|
||||
import {FormulaPickerProps} from '../formula/Picker';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
|
||||
/**
|
||||
* 支持4中表达式设置方式
|
||||
@ -30,7 +31,7 @@ import {FormulaPickerProps} from '../formula/Picker';
|
||||
* 4. 粗暴点,函数让用户自己书写。
|
||||
*/
|
||||
|
||||
export interface ExpressionProps extends ThemeProps {
|
||||
export interface ExpressionProps extends ThemeProps, LocaleProps {
|
||||
value: ExpressionComplex;
|
||||
data?: any;
|
||||
index?: number;
|
||||
@ -46,6 +47,7 @@ export interface ExpressionProps extends ThemeProps {
|
||||
fieldClassName?: string;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
const fieldMap = {
|
||||
@ -137,7 +139,8 @@ export class Expression extends React.Component<ExpressionProps> {
|
||||
disabled,
|
||||
searchable,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
const inputType =
|
||||
((value as any)?.type === 'field'
|
||||
@ -169,6 +172,7 @@ export class Expression extends React.Component<ExpressionProps> {
|
||||
disabled={disabled}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
@ -231,4 +235,4 @@ export class Expression extends React.Component<ExpressionProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Expression);
|
||||
export default themeable(localeable(Expression));
|
||||
|
@ -1,8 +1,9 @@
|
||||
import React from 'react';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
import {ThemeProps, themeable} from '../../theme';
|
||||
import InputBox from '../InputBox';
|
||||
|
||||
export interface FormulaProps extends ThemeProps {
|
||||
export interface FormulaProps extends ThemeProps, LocaleProps {
|
||||
value: any;
|
||||
onChange: (value: any) => void;
|
||||
disabled?: boolean;
|
||||
@ -10,7 +11,13 @@ export interface FormulaProps extends ThemeProps {
|
||||
|
||||
export class Formula extends React.Component<FormulaProps> {
|
||||
render() {
|
||||
const {classnames: cx, value, onChange, disabled} = this.props;
|
||||
const {
|
||||
classnames: cx,
|
||||
value,
|
||||
onChange,
|
||||
disabled,
|
||||
translate: __
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('CBFormula')}>
|
||||
@ -18,12 +25,16 @@ export class Formula extends React.Component<FormulaProps> {
|
||||
disabled={disabled}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
placeholder="请输入公式"
|
||||
prefix={<span className={cx('CBFormula-label')}>表达式</span>}
|
||||
placeholder={__('Condition.formula_placeholder')}
|
||||
prefix={
|
||||
<span className={cx('CBFormula-label')}>
|
||||
{__('Condition.expression')}
|
||||
</span>
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(Formula);
|
||||
export default themeable(localeable(Formula));
|
||||
|
@ -8,8 +8,9 @@ import ResultBox from '../ResultBox';
|
||||
import {Icon} from '../icons';
|
||||
import Expression from './Expression';
|
||||
import {Config} from './config';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
|
||||
export interface ConditionFuncProps extends ThemeProps {
|
||||
export interface ConditionFuncProps extends ThemeProps, LocaleProps {
|
||||
value: ExpressionFunc;
|
||||
onChange: (value: ExpressionFunc) => void;
|
||||
disabled?: boolean;
|
||||
@ -68,7 +69,14 @@ export class ConditionFunc extends React.Component<ConditionFuncProps> {
|
||||
}
|
||||
|
||||
render() {
|
||||
const {value, classnames: cx, fieldClassName, funcs, disabled} = this.props;
|
||||
const {
|
||||
value,
|
||||
classnames: cx,
|
||||
fieldClassName,
|
||||
funcs,
|
||||
disabled,
|
||||
translate: __
|
||||
} = this.props;
|
||||
const func = value
|
||||
? findTree(funcs!, item => (item as Func).type === value.func)
|
||||
: null;
|
||||
@ -100,7 +108,7 @@ export class ConditionFunc extends React.Component<ConditionFuncProps> {
|
||||
result={func}
|
||||
onResultChange={noop}
|
||||
onResultClick={onClick}
|
||||
placeholder="请选择字段"
|
||||
placeholder={__('Condition.field_placeholder')}
|
||||
disabled={disabled}
|
||||
>
|
||||
<span className={cx('CBGroup-fieldCaret')}>
|
||||
@ -114,11 +122,13 @@ export class ConditionFunc extends React.Component<ConditionFuncProps> {
|
||||
{func ? (
|
||||
this.renderFunc(func as Func)
|
||||
) : (
|
||||
<span className={cx('CBFunc-error')}>方法未定义</span>
|
||||
<span className={cx('CBFunc-error')}>
|
||||
{__('Condition.fun_error')}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default themeable(ConditionFunc);
|
||||
export default themeable(localeable(ConditionFunc));
|
||||
|
@ -8,6 +8,7 @@ import {Config} from './config';
|
||||
import {Icon} from '../icons';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
import {FormulaPickerProps} from '../formula/Picker';
|
||||
import Select from '../Select';
|
||||
|
||||
export interface ConditionGroupProps extends ThemeProps, LocaleProps {
|
||||
builderMode?: 'simple' | 'full';
|
||||
@ -27,13 +28,14 @@ export interface ConditionGroupProps extends ThemeProps, LocaleProps {
|
||||
fieldClassName?: string;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
getValue() {
|
||||
return {
|
||||
id: guid(),
|
||||
conjunction: 'and' as 'and',
|
||||
conjunction: 'and',
|
||||
...this.props.value
|
||||
} as ConditionGroupValue;
|
||||
}
|
||||
@ -48,10 +50,10 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleConjunctionClick() {
|
||||
handleConjunctionChange(val: {value: 'or' | 'and'}) {
|
||||
const onChange = this.props.onChange;
|
||||
let value = this.getValue();
|
||||
value.conjunction = value.conjunction === 'and' ? 'or' : 'and';
|
||||
value.conjunction = val.value;
|
||||
onChange(value);
|
||||
}
|
||||
|
||||
@ -136,74 +138,42 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
searchable,
|
||||
translate: __,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
return (
|
||||
<div className={cx('CBGroup')} data-group-id={value?.id}>
|
||||
<div className={cx('CBGroup-toolbar')}>
|
||||
{builderMode === 'simple' && showANDOR === false ? null : (
|
||||
<div className={cx('CBGroup-toolbarCondition')}>
|
||||
{showNot ? (
|
||||
<Button
|
||||
onClick={this.handleNotClick}
|
||||
className="m-r-xs"
|
||||
size="xs"
|
||||
active={value?.not}
|
||||
disabled={disabled}
|
||||
>
|
||||
{__('Condition.not')}
|
||||
</Button>
|
||||
) : null}
|
||||
<div className={cx('ButtonGroup')}>
|
||||
<Button
|
||||
size="xs"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction !== 'or'}
|
||||
disabled={disabled}
|
||||
>
|
||||
{__('Condition.and')}
|
||||
</Button>
|
||||
<Button
|
||||
size="xs"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction === 'or'}
|
||||
disabled={disabled}
|
||||
>
|
||||
{__('Condition.or')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div
|
||||
className={cx(
|
||||
`CBGroup-toolbarConditionAdd${
|
||||
builderMode === 'simple' ? '-simple' : ''
|
||||
}`
|
||||
)}
|
||||
>
|
||||
<div className={cx('ButtonGroup')}>
|
||||
<Button onClick={this.handleAdd} size="xs" disabled={disabled}>
|
||||
<Icon icon="plus" className="icon" />
|
||||
{__('Condition.add_cond')}
|
||||
{builderMode === 'simple' && showANDOR === false ? null : (
|
||||
<div className={cx('CBGroup-toolbarCondition')}>
|
||||
{showNot ? (
|
||||
<Button
|
||||
onClick={this.handleNotClick}
|
||||
className="m-r-xs"
|
||||
size="xs"
|
||||
active={value?.not}
|
||||
disabled={disabled}
|
||||
>
|
||||
{__('Condition.not')}
|
||||
</Button>
|
||||
{builderMode === 'simple' ? null : (
|
||||
<Button
|
||||
onClick={this.handleAddGroup}
|
||||
size="xs"
|
||||
disabled={disabled}
|
||||
>
|
||||
<Icon icon="plus-cicle" className="icon" />
|
||||
{__('Condition.add_cond_group')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
<Select
|
||||
options={[
|
||||
{
|
||||
label: __('Condition.and'),
|
||||
value: 'and'
|
||||
},
|
||||
{
|
||||
label: __('Condition.or'),
|
||||
value: 'or'
|
||||
}
|
||||
]}
|
||||
value={value?.conjunction || 'and'}
|
||||
disabled={disabled}
|
||||
onChange={this.handleConjunctionChange}
|
||||
clearable={false}
|
||||
/>
|
||||
</div>
|
||||
{removeable ? (
|
||||
<a className={cx('CBDelete')} onClick={onRemove}>
|
||||
<Icon icon="close" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
)}
|
||||
<div className={cx('CBGroup-body')}>
|
||||
{Array.isArray(value?.children) && value!.children.length ? (
|
||||
value!.children.map((item, index) => (
|
||||
@ -225,6 +195,7 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
builderMode={builderMode}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
))
|
||||
) : (
|
||||
@ -239,6 +210,41 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className={cx('CBGroup-toolbar')}>
|
||||
<div
|
||||
className={cx(
|
||||
`CBGroup-toolbarConditionAdd${
|
||||
builderMode === 'simple' ? '-simple' : ''
|
||||
}`
|
||||
)}
|
||||
>
|
||||
<div className={cx('ButtonGroup')}>
|
||||
<Button
|
||||
level="link"
|
||||
onClick={this.handleAdd}
|
||||
size="xs"
|
||||
disabled={disabled}
|
||||
>
|
||||
{__('Condition.add_cond')}
|
||||
</Button>
|
||||
{builderMode === 'simple' ? null : (
|
||||
<Button
|
||||
onClick={this.handleAddGroup}
|
||||
size="xs"
|
||||
disabled={disabled}
|
||||
level="link"
|
||||
>
|
||||
{__('Condition.add_cond_group')}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
{removeable ? (
|
||||
<a className={cx('CBDelete')} onClick={onRemove}>
|
||||
{__('Condition.delete_cond_group')}
|
||||
</a>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import {autobind} from '../../utils/helper';
|
||||
import ConditionGroup from './Group';
|
||||
import ConditionItem from './Item';
|
||||
import {FormulaPickerProps} from '../formula/Picker';
|
||||
import Button from '../Button';
|
||||
|
||||
export interface CBGroupOrItemProps extends ThemeProps {
|
||||
builderMode?: 'simple' | 'full';
|
||||
@ -26,9 +27,13 @@ export interface CBGroupOrItemProps extends ThemeProps {
|
||||
fieldClassName?: string;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
export class CBGroupOrItem extends React.Component<CBGroupOrItemProps> {
|
||||
state = {
|
||||
hover: false
|
||||
};
|
||||
@autobind
|
||||
handleItemChange(value: any) {
|
||||
this.props.onChange(value, this.props.index);
|
||||
@ -39,6 +44,21 @@ export class CBGroupOrItem extends React.Component<CBGroupOrItemProps> {
|
||||
this.props.onRemove?.(this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handlerHoverIn(e: any) {
|
||||
e.stopPropagation();
|
||||
this.setState({
|
||||
hover: true
|
||||
});
|
||||
}
|
||||
|
||||
@autobind
|
||||
handlerHoverOut(e: any) {
|
||||
this.setState({
|
||||
hover: false
|
||||
});
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
builderMode,
|
||||
@ -54,7 +74,8 @@ export class CBGroupOrItem extends React.Component<CBGroupOrItemProps> {
|
||||
searchable,
|
||||
onDragStart,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
@ -65,33 +86,51 @@ export class CBGroupOrItem extends React.Component<CBGroupOrItemProps> {
|
||||
data-id={value?.id}
|
||||
>
|
||||
<div className={cx('CBGroupOrItem-body')}>
|
||||
{draggable ? (
|
||||
<a
|
||||
draggable
|
||||
onDragStart={onDragStart}
|
||||
className={cx('CBGroupOrItem-dragbar')}
|
||||
>
|
||||
<Icon icon="drag-bar" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
|
||||
{value?.conjunction ? (
|
||||
<ConditionGroup
|
||||
disabled={disabled}
|
||||
searchable={searchable}
|
||||
onDragStart={onDragStart}
|
||||
config={config}
|
||||
fields={fields}
|
||||
value={value as ConditionGroupValue}
|
||||
onChange={this.handleItemChange}
|
||||
fieldClassName={fieldClassName}
|
||||
funcs={funcs}
|
||||
removeable
|
||||
onRemove={this.handleItemRemove}
|
||||
data={data}
|
||||
/>
|
||||
<div
|
||||
className={cx(
|
||||
'CBGroupOrItem-body-group',
|
||||
this.state.hover && 'CBGroupOrItem-body-group--hover'
|
||||
)}
|
||||
onMouseOver={this.handlerHoverIn}
|
||||
onMouseOut={this.handlerHoverOut}
|
||||
>
|
||||
{draggable ? (
|
||||
<a
|
||||
draggable
|
||||
onDragStart={onDragStart}
|
||||
className={cx('CBGroupOrItem-dragbar')}
|
||||
>
|
||||
<Icon icon="drag-bar" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
<ConditionGroup
|
||||
disabled={disabled}
|
||||
searchable={searchable}
|
||||
onDragStart={onDragStart}
|
||||
config={config}
|
||||
fields={fields}
|
||||
value={value as ConditionGroupValue}
|
||||
onChange={this.handleItemChange}
|
||||
fieldClassName={fieldClassName}
|
||||
funcs={funcs}
|
||||
removeable
|
||||
onRemove={this.handleItemRemove}
|
||||
data={data}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
<div className={cx('CBGroupOrItem-body-item')}>
|
||||
{draggable ? (
|
||||
<a
|
||||
draggable
|
||||
onDragStart={onDragStart}
|
||||
className={cx('CBGroupOrItem-dragbar')}
|
||||
>
|
||||
<Icon icon="drag-bar" className="icon" />
|
||||
</a>
|
||||
) : null}
|
||||
<ConditionItem
|
||||
disabled={disabled}
|
||||
searchable={searchable}
|
||||
@ -104,11 +143,15 @@ export class CBGroupOrItem extends React.Component<CBGroupOrItemProps> {
|
||||
data={data}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
<a className={cx('CBDelete')} onClick={this.handleItemRemove}>
|
||||
<Icon icon="close" className="icon" />
|
||||
</a>
|
||||
</>
|
||||
<Button
|
||||
className={cx('CBDelete')}
|
||||
onClick={this.handleItemRemove}
|
||||
>
|
||||
<Icon icon="remove" className="icon" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -23,6 +23,7 @@ import GroupedSelection from '../GroupedSelection';
|
||||
import ResultBox from '../ResultBox';
|
||||
import {localeable, LocaleProps} from '../../locale';
|
||||
import {FormulaPickerProps} from '../formula/Picker';
|
||||
import {PlainObject} from '../../types';
|
||||
|
||||
const option2value = (item: any) => item.value;
|
||||
|
||||
@ -39,6 +40,7 @@ export interface ConditionItemProps extends ThemeProps, LocaleProps {
|
||||
fieldClassName?: string;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
@ -91,12 +93,22 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
handleRightSubChange(index: number, rightValue: any) {
|
||||
const origin = Array.isArray(this.props.value?.right)
|
||||
? this.props.value.right.concat()
|
||||
: [];
|
||||
handleRightSubChange(
|
||||
isCustom: boolean,
|
||||
index: number | string,
|
||||
rightValue: any
|
||||
) {
|
||||
let origin;
|
||||
if (isCustom) {
|
||||
origin = Object.assign({}, this.props.value?.right) as PlainObject;
|
||||
origin[index] = rightValue;
|
||||
} else {
|
||||
origin = Array.isArray(this.props.value?.right)
|
||||
? this.props.value.right.concat()
|
||||
: [];
|
||||
origin[index as number] = rightValue;
|
||||
}
|
||||
|
||||
origin[index] = rightValue;
|
||||
const value = {...this.props.value, right: origin};
|
||||
const onChange = this.props.onChange;
|
||||
|
||||
@ -145,7 +157,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
popOverContainer
|
||||
} = this.props;
|
||||
const left = value?.left;
|
||||
let operators: Array<string> = [];
|
||||
let operators: any[] = [];
|
||||
|
||||
if ((left as ExpressionFunc)?.type === 'func') {
|
||||
const func: Func = findTree(
|
||||
@ -169,6 +181,16 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
|
||||
if (Array.isArray(operators) && operators.length) {
|
||||
const __ = this.props.translate;
|
||||
const options = operators.map(operator => {
|
||||
if (typeof operator === 'string') {
|
||||
return {
|
||||
label: __(OperationMap[operator as keyof typeof OperationMap]),
|
||||
value: operator
|
||||
};
|
||||
} else {
|
||||
return operator;
|
||||
}
|
||||
});
|
||||
return (
|
||||
<PopOverContainer
|
||||
popOverContainer={popOverContainer || (() => findDOMNode(this))}
|
||||
@ -177,10 +199,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
onClick={onClose}
|
||||
option2value={option2value}
|
||||
onChange={this.handleOperatorChange}
|
||||
options={operators.map(operator => ({
|
||||
label: __(OperationMap[operator as keyof typeof OperationMap]),
|
||||
value: operator
|
||||
}))}
|
||||
options={options}
|
||||
value={value.op}
|
||||
multiple={false}
|
||||
/>
|
||||
@ -195,9 +214,10 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
)}
|
||||
ref={ref}
|
||||
allowInput={false}
|
||||
result={__(
|
||||
OperationMap[value?.op as keyof typeof OperationMap]
|
||||
)}
|
||||
result={
|
||||
__(OperationMap[value?.op as keyof typeof OperationMap]) ||
|
||||
options.find(option => option.value === value.op)?.label
|
||||
}
|
||||
onResultChange={noop}
|
||||
onResultClick={onClick}
|
||||
disabled={disabled}
|
||||
@ -263,13 +283,16 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
classnames: cx,
|
||||
disabled,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
let field = {
|
||||
...config.types[type],
|
||||
type
|
||||
} as FieldSimple;
|
||||
|
||||
let option;
|
||||
|
||||
if ((value?.left as ExpressionField)?.type === 'field') {
|
||||
const leftField: FieldSimple = findTree(
|
||||
fields,
|
||||
@ -281,6 +304,9 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
...field,
|
||||
...leftField
|
||||
};
|
||||
option = field.operators?.find(
|
||||
option => typeof option !== 'string' && option?.value === op
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -295,7 +321,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
valueField={field}
|
||||
value={(value.right as Array<ExpressionComplex>)?.[0]}
|
||||
data={data}
|
||||
onChange={this.handleRightSubChange.bind(this, 0)}
|
||||
onChange={this.handleRightSubChange.bind(this, false, 0)}
|
||||
fields={fields}
|
||||
allowedTypes={
|
||||
field?.valueTypes ||
|
||||
@ -304,6 +330,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
disabled={disabled}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
|
||||
<span className={cx('CBSeprator')}>~</span>
|
||||
@ -314,7 +341,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
valueField={field}
|
||||
value={(value.right as Array<ExpressionComplex>)?.[1]}
|
||||
data={data}
|
||||
onChange={this.handleRightSubChange.bind(this, 1)}
|
||||
onChange={this.handleRightSubChange.bind(this, false, 1)}
|
||||
fields={fields}
|
||||
allowedTypes={
|
||||
field?.valueTypes ||
|
||||
@ -323,11 +350,36 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
disabled={disabled}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
} else if (option && typeof option !== 'string' && option.values) {
|
||||
return option.values.map((schema, i) => {
|
||||
return (
|
||||
<span key={i}>
|
||||
<Expression
|
||||
config={config}
|
||||
op={op}
|
||||
funcs={funcs}
|
||||
valueField={schema}
|
||||
value={value.right}
|
||||
data={data}
|
||||
onChange={this.handleRightSubChange.bind(this, true, schema.name)}
|
||||
fields={fields}
|
||||
allowedTypes={
|
||||
field?.valueTypes ||
|
||||
config.valueTypes || ['value', 'field', 'func', 'formula']
|
||||
}
|
||||
disabled={disabled}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
</span>
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<Expression
|
||||
config={config}
|
||||
@ -345,6 +397,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
disabled={disabled}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ export interface ValueProps extends ThemeProps, LocaleProps {
|
||||
disabled?: boolean;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
export class Value extends React.Component<ValueProps> {
|
||||
@ -32,7 +33,8 @@ export class Value extends React.Component<ValueProps> {
|
||||
data,
|
||||
disabled,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
let input: JSX.Element | undefined = undefined;
|
||||
if (formula) {
|
||||
@ -85,7 +87,7 @@ export class Value extends React.Component<ValueProps> {
|
||||
input = (
|
||||
<DatePicker
|
||||
viewMode="time"
|
||||
placeholder={__(field.placeholder) || 'Time.placeholder'}
|
||||
placeholder={__(field.placeholder) || __('Time.placeholder')}
|
||||
format={field.format || 'HH:mm'}
|
||||
inputFormat={field.inputFormat || 'HH:mm'}
|
||||
value={value ?? field.defaultValue}
|
||||
@ -135,6 +137,23 @@ export class Value extends React.Component<ValueProps> {
|
||||
disabled={disabled}
|
||||
/>
|
||||
);
|
||||
} else if (field.type === 'custom') {
|
||||
input = renderEtrValue
|
||||
? renderEtrValue(field.value, {
|
||||
data,
|
||||
onChange,
|
||||
value: value ?? field.defaultValue
|
||||
})
|
||||
: null;
|
||||
} else {
|
||||
const res = value ?? (field as any).defaultValue;
|
||||
input = renderEtrValue
|
||||
? renderEtrValue(field, {
|
||||
data,
|
||||
onChange,
|
||||
value: res ? res[(field as any).name] : res
|
||||
})
|
||||
: null;
|
||||
}
|
||||
|
||||
return <div className={cx('CBValue')}>{input}</div>;
|
||||
|
@ -31,6 +31,7 @@ export interface ConditionBuilderProps extends ThemeProps, LocaleProps {
|
||||
fieldClassName?: string;
|
||||
formula?: FormulaPickerProps;
|
||||
popOverContainer?: any;
|
||||
renderEtrValue?: any;
|
||||
}
|
||||
|
||||
export class QueryBuilder extends React.Component<ConditionBuilderProps> {
|
||||
@ -211,7 +212,8 @@ export class QueryBuilder extends React.Component<ConditionBuilderProps> {
|
||||
searchable,
|
||||
builderMode,
|
||||
formula,
|
||||
popOverContainer
|
||||
popOverContainer,
|
||||
renderEtrValue
|
||||
} = this.props;
|
||||
|
||||
const normalizedValue = Array.isArray(value?.children)
|
||||
@ -249,6 +251,7 @@ export class QueryBuilder extends React.Component<ConditionBuilderProps> {
|
||||
searchable={searchable}
|
||||
formula={formula}
|
||||
popOverContainer={popOverContainer}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import {SchemaApi} from '../../Schema';
|
||||
import {BaseSchema, SchemaApi} from '../../Schema';
|
||||
import {Api} from '../../types';
|
||||
|
||||
export type FieldTypes =
|
||||
@ -8,7 +8,8 @@ export type FieldTypes =
|
||||
| 'date'
|
||||
| 'time'
|
||||
| 'datetime'
|
||||
| 'select';
|
||||
| 'select'
|
||||
| 'custom';
|
||||
|
||||
export type OperatorType =
|
||||
| 'equal'
|
||||
@ -28,7 +29,11 @@ export type OperatorType =
|
||||
| 'select_equals'
|
||||
| 'select_not_equals'
|
||||
| 'select_any_in'
|
||||
| 'select_not_any_in';
|
||||
| 'select_not_any_in'
|
||||
| {
|
||||
label: string;
|
||||
value: string;
|
||||
};
|
||||
|
||||
export type FieldItem = {
|
||||
type: 'text';
|
||||
@ -78,11 +83,17 @@ export interface ConditionGroupValue {
|
||||
|
||||
export interface ConditionValue extends ConditionGroupValue {}
|
||||
|
||||
interface customOperator {
|
||||
lable: string;
|
||||
value: string;
|
||||
values?: any[];
|
||||
}
|
||||
|
||||
interface BaseField {
|
||||
type: FieldTypes;
|
||||
label: string;
|
||||
valueTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
|
||||
operators?: Array<string>;
|
||||
operators?: Array<string | customOperator>;
|
||||
|
||||
// valueTypes 里面配置 func 才有效。
|
||||
funcs?: Array<string>;
|
||||
@ -158,6 +169,12 @@ interface BooleanField extends BaseField {
|
||||
name: string;
|
||||
}
|
||||
|
||||
interface CustomField extends BaseField {
|
||||
type: 'custom';
|
||||
name: string;
|
||||
value: BaseSchema;
|
||||
}
|
||||
|
||||
interface GroupField {
|
||||
type: 'group';
|
||||
label: string;
|
||||
@ -172,7 +189,8 @@ export type FieldSimple =
|
||||
| TimeField
|
||||
| DatetimeField
|
||||
| SelectField
|
||||
| BooleanField;
|
||||
| BooleanField
|
||||
| CustomField;
|
||||
|
||||
export type Field = FieldSimple | FieldGroup | GroupField;
|
||||
|
||||
|
@ -263,6 +263,7 @@ register('de-DE', {
|
||||
'Condition.or': 'oder',
|
||||
'Condition.add_cond': 'und Bedingung',
|
||||
'Condition.add_cond_group': 'Bedingungsgruppe hinzufügen',
|
||||
'Condition.delete_cond_group': 'Konditionsgruppe löschen',
|
||||
'Condition.equal': 'gleich',
|
||||
'Condition.not_equal': 'ungleich',
|
||||
'Condition.less': 'weniger',
|
||||
@ -285,6 +286,9 @@ register('de-DE', {
|
||||
'Condition.cond_placeholder': 'Bedingung auswählen',
|
||||
'Condition.field_placeholder': 'Feld auswählen',
|
||||
'Condition.blank': 'leer',
|
||||
'Condition.expression': 'Ausdruck',
|
||||
'Condition.formula_placeholder': 'Bitte geben Sie eine Formel ein',
|
||||
'Condition.fun_error': 'Funktion ist undefiniert',
|
||||
'InputTable.uniqueError': 'Column `{{label}}` unique validate failed',
|
||||
'Timeline.collapseText': 'Entfalten',
|
||||
'Timeline.expandText': 'Falten',
|
||||
|
@ -265,6 +265,7 @@ register('en-US', {
|
||||
'Condition.or': 'or',
|
||||
'Condition.add_cond': 'add condition',
|
||||
'Condition.add_cond_group': 'add condition group',
|
||||
'Condition.delete_cond_group': 'delete condition group',
|
||||
'Condition.equal': 'equal',
|
||||
'Condition.not_equal': 'not equal',
|
||||
'Condition.less': 'less',
|
||||
@ -287,6 +288,9 @@ register('en-US', {
|
||||
'Condition.cond_placeholder': 'select condition',
|
||||
'Condition.field_placeholder': 'select field',
|
||||
'Condition.blank': 'blank',
|
||||
'Condition.expression': 'expression',
|
||||
'Condition.formula_placeholder': 'Please enter a formula',
|
||||
'Condition.fun_error': 'Function is undefined',
|
||||
'InputTable.uniqueError': 'Column `{{label}}` unique validate failed',
|
||||
'Timeline.collapseText': 'Unfold',
|
||||
'Timeline.expandText': 'Fold',
|
||||
|
@ -272,6 +272,7 @@ register('zh-CN', {
|
||||
'Condition.or': '或者',
|
||||
'Condition.add_cond': '添加条件',
|
||||
'Condition.add_cond_group': '添加条件组',
|
||||
'Condition.delete_cond_group': '删除组',
|
||||
'Condition.equal': '等于',
|
||||
'Condition.not_equal': '不等于',
|
||||
'Condition.less': '小于',
|
||||
@ -294,6 +295,9 @@ register('zh-CN', {
|
||||
'Condition.cond_placeholder': '请选择操作',
|
||||
'Condition.field_placeholder': '请选择字段',
|
||||
'Condition.blank': '空',
|
||||
'Condition.expression': '表达式',
|
||||
'Condition.formula_placeholder': '请输入公式',
|
||||
'Condition.fun_error': '方法未定义',
|
||||
'InputTable.uniqueError': '列`{{label}}`没有通过唯一验证',
|
||||
'Timeline.collapseText': '展开',
|
||||
'Timeline.expandText': '折叠',
|
||||
|
@ -9,6 +9,8 @@ import {
|
||||
RemoteOptionsProps,
|
||||
withRemoteConfig
|
||||
} from '../../components/WithRemoteConfig';
|
||||
import {Schema} from '../../types';
|
||||
import {autobind} from '../../utils/helper';
|
||||
|
||||
/**
|
||||
* 条件组合控件
|
||||
@ -59,12 +61,23 @@ export interface ConditionBuilderProps
|
||||
> {}
|
||||
|
||||
export default class ConditionBuilderControl extends React.PureComponent<ConditionBuilderProps> {
|
||||
@autobind
|
||||
renderEtrValue(schema: Schema, data: any) {
|
||||
return this.props.render(
|
||||
'inline',
|
||||
Object.assign(schema, {label: false}),
|
||||
data
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const {className, classnames: cx, ...rest} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx(`ConditionBuilderControl`, className)}>
|
||||
<ConditionBuilderWithRemoteOptions {...rest} />
|
||||
<ConditionBuilderWithRemoteOptions
|
||||
renderEtrValue={this.renderEtrValue}
|
||||
{...rest}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
@ -77,12 +90,14 @@ const ConditionBuilderWithRemoteOptions = withRemoteConfig({
|
||||
RemoteOptionsProps & React.ComponentProps<typeof ConditionBuilder>
|
||||
> {
|
||||
render() {
|
||||
const {loading, config, deferLoad, disabled, ...rest} = this.props;
|
||||
const {loading, config, deferLoad, disabled, renderEtrValue, ...rest} =
|
||||
this.props;
|
||||
return (
|
||||
<ConditionBuilder
|
||||
{...rest}
|
||||
fields={config || rest.fields || []}
|
||||
disabled={disabled || loading}
|
||||
renderEtrValue={renderEtrValue}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user