条件组合半成品
This commit is contained in:
parent
0f0f50358f
commit
0ba867b2fc
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import ConditionBuilder from '../../../src/components/condition-builder/ConditionBuilder';
|
||||
import ConditionBuilder from '../../../src/components/condition-builder';
|
||||
|
||||
const fields = [
|
||||
{
|
||||
|
@ -25,19 +25,38 @@ const fields = [
|
|||
children: [
|
||||
{
|
||||
label: '姓名',
|
||||
name: 'name',
|
||||
name: 'name2',
|
||||
type: 'text'
|
||||
},
|
||||
|
||||
{
|
||||
label: '年龄',
|
||||
name: 'age',
|
||||
name: 'age2',
|
||||
type: 'number'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
const funcs = [
|
||||
{
|
||||
label: '文本',
|
||||
children: [
|
||||
{
|
||||
type: 'LOWERCASE',
|
||||
label: '转小写',
|
||||
returnType: 'text',
|
||||
args: [
|
||||
{
|
||||
type: 'text',
|
||||
label: '文本'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
export default {
|
||||
type: 'page',
|
||||
title: '表单页面',
|
||||
|
@ -68,7 +87,12 @@ export default {
|
|||
{
|
||||
name: 'a',
|
||||
component: ({value, onChange}) => (
|
||||
<ConditionBuilder value={value} onChange={onChange} fields={fields} />
|
||||
<ConditionBuilder
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
fields={fields}
|
||||
funcs={funcs}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
|
|
@ -310,6 +310,7 @@
|
|||
padding: $Form-input-paddingY $Form-input-paddingX;
|
||||
font-size: $Form-input-fontSize;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
|
||||
input {
|
||||
flex-basis: px2rem(80px);
|
||||
|
@ -404,3 +405,11 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@mixin icon-color {
|
||||
color: $icon-color;
|
||||
|
||||
&:hover {
|
||||
color: $icon-onHover-color;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,4 +4,107 @@
|
|||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
&-field {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
min-width: px2rem(120px);
|
||||
}
|
||||
|
||||
&-fieldCaret {
|
||||
transition: transform 0.3s ease-out;
|
||||
margin: 0 $gap-xs;
|
||||
display: flex;
|
||||
color: $icon-color;
|
||||
&:hover {
|
||||
color: $icon-onHover-color;
|
||||
}
|
||||
|
||||
> svg {
|
||||
width: px2rem(12px);
|
||||
height: px2rem(12px);
|
||||
top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&-fieldInput.is-active &-fieldCaret {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}CBItem {
|
||||
display: flex;
|
||||
margin-top: px2rem(10px);
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: px2rem(30px);
|
||||
position: relative;
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
transition: all 0.3s ease-out;
|
||||
|
||||
&-dragbar {
|
||||
cursor: move;
|
||||
width: 20px;
|
||||
margin-left: -5px;
|
||||
opacity: 0;
|
||||
text-align: center;
|
||||
transition: opacity 0.3s ease-out;
|
||||
@include icon-color();
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background-color: rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
&:hover &-dragbar {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
&:before {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: -10px;
|
||||
left: -30px;
|
||||
width: 20px;
|
||||
border-left: solid 1px $borderColor;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&:after {
|
||||
position: absolute;
|
||||
content: '';
|
||||
top: 50%;
|
||||
width: 20px;
|
||||
left: -30px;
|
||||
border-top: solid 1px $borderColor;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
&:before {
|
||||
border-bottom-left-radius: 5px;
|
||||
border-bottom: solid 1px $borderColor;
|
||||
bottom: 50%;
|
||||
}
|
||||
|
||||
&:after {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.#{$ns}CBInputSwitch {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin: 0 5px;
|
||||
cursor: pointer;
|
||||
> a {
|
||||
@include icon-color();
|
||||
}
|
||||
|
||||
svg {
|
||||
width: px2rem(10px);
|
||||
height: px2rem(10px);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
}
|
||||
|
||||
&.is-focused,
|
||||
&.is-active,
|
||||
&:focus {
|
||||
outline: none;
|
||||
border-color: $Form-input-onFocused-borderColor;
|
||||
|
|
|
@ -21,6 +21,7 @@ export interface BaseRadiosProps extends ThemeProps, LocaleProps {
|
|||
disabled?: boolean;
|
||||
clearable?: boolean;
|
||||
showRadio?: boolean;
|
||||
onClick?: (e: React.MouseEvent) => void;
|
||||
}
|
||||
|
||||
export class BaseRadios<
|
||||
|
@ -119,7 +120,8 @@ export class BaseRadios<
|
|||
className,
|
||||
placeholder,
|
||||
classnames: cx,
|
||||
option2value
|
||||
option2value,
|
||||
onClick
|
||||
} = this.props;
|
||||
const __ = this.props.translate;
|
||||
|
||||
|
@ -131,7 +133,7 @@ export class BaseRadios<
|
|||
}
|
||||
|
||||
return (
|
||||
<div className={cx('ListRadios', className)}>
|
||||
<div className={cx('ListRadios', className)} onClick={onClick}>
|
||||
{body && body.length ? (
|
||||
body
|
||||
) : (
|
||||
|
|
|
@ -50,7 +50,7 @@ export class PopOverContainer extends React.Component<
|
|||
|
||||
@autobind
|
||||
getTarget() {
|
||||
return findDOMNode(this.target || this) as HTMLElement;
|
||||
return this.target || (findDOMNode(this) as HTMLElement);
|
||||
}
|
||||
|
||||
@autobind
|
||||
|
@ -82,7 +82,11 @@ export class PopOverContainer extends React.Component<
|
|||
<PopOver
|
||||
overlay
|
||||
className={popOverClassName}
|
||||
style={{minWidth: this.target ? this.target.offsetWidth : 'auto'}}
|
||||
style={{
|
||||
minWidth: this.target
|
||||
? Math.max(this.target.offsetWidth, 100)
|
||||
: 'auto'
|
||||
}}
|
||||
onHide={this.close}
|
||||
>
|
||||
{dropdownRender({onClose: this.close})}
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
import React from 'react';
|
||||
import {Fields, ConditionRule, ConditionGroupValue} from './types';
|
||||
import {ClassNamesFn} from '../../theme';
|
||||
import {Icon} from '../icons';
|
||||
import Select from '../Select';
|
||||
import {autobind} from '../../utils/helper';
|
||||
import PopOverContainer from '../PopOverContainer';
|
||||
import InputBox from '../InputBox';
|
||||
import ListRadios from '../ListRadios';
|
||||
import ResultBox from '../ResultBox';
|
||||
|
||||
export interface ConditionItemProps {
|
||||
fields: Fields;
|
||||
value: ConditionRule;
|
||||
classnames: ClassNamesFn;
|
||||
onChange: (value: ConditionRule) => void;
|
||||
}
|
||||
|
||||
export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
@autobind
|
||||
handleLeftSelect() {}
|
||||
|
||||
renderLeft() {
|
||||
const {value, fields} = this.props;
|
||||
|
||||
return (
|
||||
<PopOverContainer
|
||||
popOverRender={({onClose}) => (
|
||||
<ListRadios showRadio={false} options={fields} onChange={onClose} />
|
||||
)}
|
||||
>
|
||||
{({onClick, ref}) => (
|
||||
<ResultBox
|
||||
ref={ref}
|
||||
allowInput={false}
|
||||
onResultClick={onClick}
|
||||
placeholder="请选择"
|
||||
/>
|
||||
)}
|
||||
</PopOverContainer>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem() {
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('CBGroup-item')}>
|
||||
<a>
|
||||
<Icon icon="drag-bar" className="icon" />
|
||||
</a>
|
||||
|
||||
<div className={cx('CBGroup-itemBody')}>
|
||||
{this.renderLeft()}
|
||||
{this.renderItem()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
import {ExpressionComplex, Field, Funcs} from './types';
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* 支持4中表达式设置方式
|
||||
* 1. 直接就是值,由用户直接填写。
|
||||
* 2. 选择字段,让用户选一个字段。
|
||||
* 3. 选择一个函数,然后会参数里面的输入情况是个递归。
|
||||
* 4. 粗暴点,函数让用户自己书写。
|
||||
*/
|
||||
|
||||
export interface ExpressionProps {
|
||||
value: ExpressionComplex;
|
||||
onChange: (value: ExpressionComplex) => void;
|
||||
valueField?: Field;
|
||||
fields?: Field[];
|
||||
funcs?: Funcs;
|
||||
allowedTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
|
||||
}
|
||||
|
||||
export class Expression extends React.Component<ExpressionProps> {}
|
|
@ -0,0 +1,59 @@
|
|||
import React from 'react';
|
||||
import PopOverContainer from '../PopOverContainer';
|
||||
import ListRadios from '../ListRadios';
|
||||
import ResultBox from '../ResultBox';
|
||||
import {ClassNamesFn} from '../../theme';
|
||||
import {Icon} from '../icons';
|
||||
import {find} from 'lodash';
|
||||
import {findTree, noop} from '../../utils/helper';
|
||||
|
||||
export interface ConditionFieldProps {
|
||||
options: Array<any>;
|
||||
value: any;
|
||||
onChange: (value: any) => void;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
const option2value = (item: any) => item.name;
|
||||
|
||||
export default function ConditionField({
|
||||
options,
|
||||
onChange,
|
||||
value,
|
||||
classnames: cx
|
||||
}: ConditionFieldProps) {
|
||||
return (
|
||||
<PopOverContainer
|
||||
popOverRender={({onClose}) => (
|
||||
<ListRadios
|
||||
onClick={onClose}
|
||||
showRadio={false}
|
||||
options={options}
|
||||
value={value}
|
||||
option2value={option2value}
|
||||
onChange={onChange}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{({onClick, ref, isOpened}) => (
|
||||
<div className={cx('CBGroup-field')}>
|
||||
<ResultBox
|
||||
className={cx('CBGroup-fieldInput', isOpened ? 'is-active' : '')}
|
||||
ref={ref}
|
||||
allowInput={false}
|
||||
result={
|
||||
value ? findTree(options, item => item.name === value)?.label : ''
|
||||
}
|
||||
onResultChange={noop}
|
||||
onResultClick={onClick}
|
||||
placeholder="请选择字段"
|
||||
>
|
||||
<span className={cx('CBGroup-fieldCaret')}>
|
||||
<Icon icon="caret" className="icon" />
|
||||
</span>
|
||||
</ResultBox>
|
||||
</div>
|
||||
)}
|
||||
</PopOverContainer>
|
||||
);
|
||||
}
|
|
@ -1,14 +1,16 @@
|
|||
import React from 'react';
|
||||
import {Fields, ConditionGroupValue} from './types';
|
||||
import {Fields, ConditionGroupValue, Funcs} from './types';
|
||||
import {ClassNamesFn} from '../../theme';
|
||||
import Button from '../Button';
|
||||
import {ConditionItem} from './ConditionItem';
|
||||
import {ConditionItem} from './Item';
|
||||
import {autobind, guid} from '../../utils/helper';
|
||||
|
||||
export interface ConditionGroupProps {
|
||||
value?: ConditionGroupValue;
|
||||
fields: Fields;
|
||||
onChange: (value: ConditionGroupValue) => void;
|
||||
funcs?: Funcs;
|
||||
index?: number;
|
||||
onChange: (value: ConditionGroupValue, index?: number) => void;
|
||||
classnames: ClassNamesFn;
|
||||
removeable?: boolean;
|
||||
}
|
||||
|
@ -27,7 +29,7 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
|||
let value = this.getValue();
|
||||
value.not = !value.not;
|
||||
|
||||
onChange(value);
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
|
@ -35,7 +37,7 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
|||
const onChange = this.props.onChange;
|
||||
let value = this.getValue();
|
||||
value.conjunction = value.conjunction === 'and' ? 'or' : 'and';
|
||||
onChange(value);
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
|
@ -50,7 +52,7 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
|||
value.children.push({
|
||||
id: guid()
|
||||
});
|
||||
onChange(value);
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
|
@ -66,53 +68,70 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
|||
id: guid(),
|
||||
conjunction: 'and'
|
||||
});
|
||||
onChange(value);
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleItemChange(item: any, index?: number) {
|
||||
const onChange = this.props.onChange;
|
||||
let value = this.getValue();
|
||||
|
||||
value.children = Array.isArray(value.children)
|
||||
? value.children.concat()
|
||||
: [];
|
||||
|
||||
value.children.splice(index!, 1, item);
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx, value, fields, onChange} = this.props;
|
||||
const {classnames: cx, value, fields, funcs} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('CBGroup')}>
|
||||
<div className={cx('CBGroup-toolbar')}>
|
||||
<div className={cx('CBGroup-toolbarLeft')}>
|
||||
<Button onClick={this.handleNotClick} size="sm" active={value?.not}>
|
||||
取反
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction !== 'or'}
|
||||
>
|
||||
并且
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction === 'or'}
|
||||
>
|
||||
或者
|
||||
非
|
||||
</Button>
|
||||
<div className={cx('ButtonGroup m-l-xs')}>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction !== 'or'}
|
||||
>
|
||||
并且
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
onClick={this.handleConjunctionClick}
|
||||
active={value?.conjunction === 'or'}
|
||||
>
|
||||
或者
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className={cx('CBGroup-toolbarRight')}>
|
||||
<Button onClick={this.handleAdd} size="sm">
|
||||
添加条件
|
||||
</Button>
|
||||
<Button onClick={this.handleAddGroup} size="sm">
|
||||
<Button onClick={this.handleAddGroup} size="sm" className="m-l-xs">
|
||||
添加条件组
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{Array.isArray(value?.children)
|
||||
? value!.children.map(item =>
|
||||
? value!.children.map((item, index) =>
|
||||
(item as ConditionGroupValue).conjunction ? (
|
||||
<ConditionGroup
|
||||
key={item.id}
|
||||
fields={fields}
|
||||
value={item as ConditionGroupValue}
|
||||
classnames={cx}
|
||||
onChange={onChange}
|
||||
index={index}
|
||||
onChange={this.handleItemChange}
|
||||
funcs={funcs}
|
||||
/>
|
||||
) : (
|
||||
<ConditionItem
|
||||
|
@ -120,7 +139,9 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
|||
fields={fields}
|
||||
value={item}
|
||||
classnames={cx}
|
||||
onChange={onChange}
|
||||
index={index}
|
||||
onChange={this.handleItemChange}
|
||||
funcs={funcs}
|
||||
/>
|
||||
)
|
||||
)
|
|
@ -0,0 +1,44 @@
|
|||
import React from 'react';
|
||||
import PopOverContainer from '../PopOverContainer';
|
||||
import {Icon} from '../icons';
|
||||
import ListRadios from '../ListRadios';
|
||||
import {ClassNamesFn} from '../../theme';
|
||||
|
||||
export interface InputSwitchProps {
|
||||
options: Array<any>;
|
||||
value: any;
|
||||
onChange: (value: any) => void;
|
||||
classnames: ClassNamesFn;
|
||||
}
|
||||
|
||||
const option2value = (item: any) => item.value;
|
||||
|
||||
export default function InputSwitch({
|
||||
options,
|
||||
value,
|
||||
onChange,
|
||||
classnames: cx
|
||||
}: InputSwitchProps) {
|
||||
return (
|
||||
<PopOverContainer
|
||||
popOverRender={({onClose}) => (
|
||||
<ListRadios
|
||||
onClick={onClose}
|
||||
option2value={option2value}
|
||||
onChange={onChange}
|
||||
options={options}
|
||||
value={value}
|
||||
showRadio={false}
|
||||
/>
|
||||
)}
|
||||
>
|
||||
{({onClick, isOpened, ref}) => (
|
||||
<div className={cx('CBInputSwitch', isOpened ? 'is-active' : '')}>
|
||||
<a onClick={onClick} ref={ref}>
|
||||
<Icon icon="setting" />
|
||||
</a>
|
||||
</div>
|
||||
)}
|
||||
</PopOverContainer>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
import React from 'react';
|
||||
import {Fields, ConditionRule, ConditionGroupValue, Funcs} from './types';
|
||||
import {ClassNamesFn} from '../../theme';
|
||||
import {Icon} from '../icons';
|
||||
import Select from '../Select';
|
||||
import {autobind} from '../../utils/helper';
|
||||
import PopOverContainer from '../PopOverContainer';
|
||||
import InputBox from '../InputBox';
|
||||
import ListRadios from '../ListRadios';
|
||||
import ResultBox from '../ResultBox';
|
||||
import ConditionField from './Field';
|
||||
import InputSwitch from './InputSwitch';
|
||||
|
||||
export interface ConditionItemProps {
|
||||
fields: Fields;
|
||||
funcs?: Funcs;
|
||||
index?: number;
|
||||
value: ConditionRule;
|
||||
classnames: ClassNamesFn;
|
||||
onChange: (value: ConditionRule, index?: number) => void;
|
||||
}
|
||||
|
||||
const leftInputOptions = [
|
||||
{
|
||||
label: '字段',
|
||||
value: 'field'
|
||||
},
|
||||
{
|
||||
label: '函数',
|
||||
value: 'func'
|
||||
}
|
||||
];
|
||||
|
||||
export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
@autobind
|
||||
handleLeftFieldSelect(field: any) {
|
||||
const value = {...this.props.value};
|
||||
const onChange = this.props.onChange;
|
||||
value.left = field;
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
@autobind
|
||||
handleLeftInputTypeChange(type: 'func' | 'field') {
|
||||
const value = {...this.props.value};
|
||||
const onChange = this.props.onChange;
|
||||
|
||||
if (type === 'func') {
|
||||
value.left = {type: 'func'};
|
||||
} else {
|
||||
value.left = '';
|
||||
}
|
||||
|
||||
onChange(value, this.props.index);
|
||||
}
|
||||
|
||||
renderLeft() {
|
||||
const {value, fields, classnames: cx, funcs} = this.props;
|
||||
const inputType =
|
||||
value.left && (value.left as any).type === 'func' ? 'func' : 'field';
|
||||
|
||||
return (
|
||||
<>
|
||||
{Array.isArray(funcs) ? (
|
||||
<InputSwitch
|
||||
classnames={cx}
|
||||
onChange={this.handleLeftInputTypeChange}
|
||||
options={leftInputOptions}
|
||||
value={inputType}
|
||||
/>
|
||||
) : null}
|
||||
|
||||
{inputType === 'field' ? (
|
||||
<ConditionField
|
||||
classnames={cx}
|
||||
options={fields}
|
||||
value={value.left}
|
||||
onChange={this.handleLeftFieldSelect}
|
||||
/>
|
||||
) : null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
renderItem() {
|
||||
return null;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('CBItem')}>
|
||||
<a className={cx('CBItem-dragbar')}>
|
||||
<Icon icon="drag-bar" className="icon" />
|
||||
</a>
|
||||
|
||||
<div className={cx('CBItem-itemBody')}>
|
||||
{this.renderLeft()}
|
||||
{this.renderItem()}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,21 +2,23 @@ import React from 'react';
|
|||
import {ThemeProps, themeable} from '../../theme';
|
||||
import {LocaleProps, localeable} from '../../locale';
|
||||
import {uncontrollable} from 'uncontrollable';
|
||||
import {Fields, ConditionGroupValue} from './types';
|
||||
import {ConditionGroup} from './ConditionGroup';
|
||||
import {Fields, ConditionGroupValue, Funcs} from './types';
|
||||
import {ConditionGroup} from './Group';
|
||||
|
||||
export interface QueryBuilderProps extends ThemeProps, LocaleProps {
|
||||
fields: Fields;
|
||||
funcs?: Funcs;
|
||||
value?: ConditionGroupValue;
|
||||
onChange: (value: ConditionGroupValue) => void;
|
||||
}
|
||||
|
||||
export class QueryBuilder extends React.Component<QueryBuilderProps> {
|
||||
render() {
|
||||
const {classnames: cx, fields, onChange, value} = this.props;
|
||||
const {classnames: cx, fields, funcs, onChange, value} = this.props;
|
||||
|
||||
return (
|
||||
<ConditionGroup
|
||||
funcs={funcs}
|
||||
fields={fields}
|
||||
value={value}
|
||||
onChange={onChange}
|
|
@ -18,32 +18,32 @@ export type FieldItem = {
|
|||
operators: Array<OperatorType>;
|
||||
};
|
||||
|
||||
export type ConditionRightValueLiteral = string | number | object | undefined;
|
||||
export type ConditionRightValue =
|
||||
| ConditionRightValueLiteral
|
||||
export type ExpressionSimple = string | number | object | undefined;
|
||||
export type ExpressionComplex =
|
||||
| ExpressionSimple
|
||||
| {
|
||||
type: 'raw';
|
||||
value: ConditionRightValueLiteral;
|
||||
type: 'value';
|
||||
value: ExpressionSimple;
|
||||
}
|
||||
| {
|
||||
type: 'func';
|
||||
func: string;
|
||||
args: Array<ConditionRightValue>;
|
||||
args: Array<ExpressionComplex>;
|
||||
}
|
||||
| {
|
||||
type: 'field';
|
||||
field: string;
|
||||
}
|
||||
| {
|
||||
type: 'expression';
|
||||
type: 'raw';
|
||||
field: string;
|
||||
};
|
||||
|
||||
export interface ConditionRule {
|
||||
id: any;
|
||||
left?: string;
|
||||
left?: ExpressionComplex;
|
||||
op?: OperatorType;
|
||||
right?: ConditionRightValue | Array<ConditionRightValue>;
|
||||
right?: ExpressionComplex | Array<ExpressionComplex>;
|
||||
}
|
||||
|
||||
export interface ConditionGroupValue {
|
||||
|
@ -58,7 +58,7 @@ export interface ConditionValue extends ConditionGroupValue {}
|
|||
interface BaseField {
|
||||
type: FieldTypes;
|
||||
label: string;
|
||||
valueTypes?: Array<'raw' | 'field' | 'func' | 'expression'>;
|
||||
valueTypes?: Array<'value' | 'field' | 'func' | 'expression'>;
|
||||
|
||||
// valueTypes 里面配置 func 才有效。
|
||||
funcs?: Array<string>;
|
||||
|
@ -132,7 +132,7 @@ type FieldSimple =
|
|||
| SelectField
|
||||
| BooleanField;
|
||||
|
||||
type Field = FieldSimple | FieldGroup | GroupField;
|
||||
export type Field = FieldSimple | FieldGroup | GroupField;
|
||||
|
||||
interface FuncGroup {
|
||||
label: string;
|
||||
|
|
|
@ -128,6 +128,9 @@ import SortAscIcon from '../icons/sort-asc.svg';
|
|||
// @ts-ignore
|
||||
import SortDescIcon from '../icons/sort-desc.svg';
|
||||
|
||||
// @ts-ignore
|
||||
import SettingIcon from '../icons/setting.svg';
|
||||
|
||||
// 兼容原来的用法,后续不直接试用。
|
||||
// @ts-ignore
|
||||
export const closeIcon = <CloseIcon />;
|
||||
|
@ -213,6 +216,7 @@ registerIcon('folder', FolderIcon);
|
|||
registerIcon('sort-default', SortDefaultIcon);
|
||||
registerIcon('sort-asc', SortAscIcon);
|
||||
registerIcon('sort-desc', SortDescIcon);
|
||||
registerIcon('setting', SettingIcon);
|
||||
|
||||
export function Icon({
|
||||
icon,
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg viewBox="0 0 196 200" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(0.343750, 0.000000)" fill="currentColor" fill-rule="nonzero">
|
||||
<path d="M170.546281,170.220341 C167.664808,169.153129 165.637105,168.512801 163.716123,167.765753 C157.846456,165.524607 152.190232,162.963298 146.213844,160.935595 C144.506304,160.401989 142.051716,160.615431 140.450898,161.469201 C136.28877,163.496904 132.233364,165.844771 128.3914,168.512802 C127.110746,169.366571 126.043534,171.287553 125.72337,172.888371 C124.442715,179.931972 123.482224,187.082293 122.628455,194.232615 C122.094849,198.288021 120.173867,200.102282 116.011739,199.995561 C103.738799,199.888839 91.4658594,199.888839 79.1929195,199.995561 C75.1375133,199.995561 73.0030889,198.394742 72.4694828,194.339336 C71.5089918,187.189015 70.3350584,180.145414 69.4812887,172.995093 C69.161125,170.540505 68.3073553,169.046408 65.9594885,167.872474 C62.0108035,165.951493 58.4890033,163.283462 54.5403184,161.36248 C53.1529426,160.615432 51.0185182,160.295268 49.5244211,160.828874 C42.587542,163.283462 35.8641053,166.058214 29.0339475,168.726244 C24.1247715,170.647226 22.7373957,170.220341 19.9626439,165.524608 C13.8795346,155.17265 7.90314648,144.820692 1.9267582,134.468734 C-0.847993359,129.666279 -0.741272266,128.492346 3.63429766,125.077267 C9.39724336,120.488254 15.2669104,116.112685 20.9231348,111.416951 C21.9903469,110.563181 22.7373955,108.642199 22.7373955,107.254823 C22.9508379,103.306138 22.0970682,99.1440109 22.7373955,95.3020471 C23.4844439,91.1399195 21.7769045,89.0054953 18.7887105,86.7643498 C13.4526496,82.9223859 8.54347363,78.6535373 3.31413418,74.8115734 C0.219218945,72.4637066 -0.527829688,70.0091187 1.49987344,66.5940396 C8.00986758,55.6017543 14.4131406,44.5027479 20.8164137,33.4037412 C22.6306744,30.308826 24.9785412,29.6684986 28.2868988,30.9491533 C35.3304992,33.7239049 42.3740994,36.6053777 49.5244209,39.1666871 C51.018518,39.7002932 53.3663848,39.3801295 54.8604818,38.6330811 C58.9158881,36.6053779 62.5444094,33.9373475 66.5998156,31.9096443 C68.73424,30.8424322 69.4812885,29.5617775 69.6947309,27.4273533 C70.6552219,20.1703105 71.8291553,12.9132678 72.7896461,5.656225 C73.1098098,1.49409707 75.3509555,0 79.2996404,0 C91.5725803,0.106721289 103.84552,0.106721289 116.11846,0 C119.960424,0 122.094848,1.60081816 122.521733,5.44278203 C123.482224,12.5931035 124.656158,19.6367039 125.509927,26.7870254 C125.830091,29.4550559 126.790582,31.055874 129.351891,32.2298074 C133.087134,33.9373469 136.608934,36.0717713 140.024013,38.4196381 C142.265158,40.0204563 144.18614,40.0204563 146.640728,38.9532441 C153.257444,36.1784926 159.98088,33.7239045 166.704317,30.9491529 C170.43956,29.4550559 173.000869,30.2021045 175.028572,33.8306258 C181.111681,44.6094688 187.514954,55.2815904 193.704785,65.9537121 C196.159373,70.2225607 195.839209,71.6099365 191.890524,74.704852 C186.2343,79.0804219 180.578075,83.5627129 174.815129,87.9382828 C172.894148,89.4323799 172.360542,90.8197557 172.573984,93.2743437 C173.000869,97.7566348 172.467263,102.345647 172.680705,106.827938 C172.787427,108.428756 173.534475,110.349738 174.708408,111.310229 C180.364633,116.005963 186.2343,120.381533 191.997246,124.863824 C195.94593,127.958739 196.159373,129.346115 193.704785,133.614964 C187.408233,144.500528 181.111681,155.279371 174.708408,166.058214 C173.641196,167.979195 171.826935,169.046407 170.546281,170.220341 Z M97.335526,135.216323 C116.652066,135.322503 132.660249,119.634484 132.767515,100.531386 C132.873691,80.8946824 117.292394,64.9932211 97.869132,64.8859622 C78.4458705,64.7797785 62.4371504,80.5745187 62.4371504,99.9977801 C62.330967,119.207599 78.125707,135.109061 97.335526,135.216323 Z">
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
Loading…
Reference in New Issue