还原 text 的 creatable 逻辑

Change-Id: Ibb1421e7016678636a581bf0ed1ea903fa1d8135
This commit is contained in:
2betop 2020-11-02 19:17:56 +08:00
parent 8da0be9128
commit 1cdaa6b763
9 changed files with 105 additions and 30 deletions

View File

@ -52,16 +52,16 @@
&-fieldCaret,
&-operatorCaret {
transition: transform 0.3s ease-out;
margin: 3px;
margin: 5px;
display: flex;
color: $icon-color;
color: $Form-select-caret-iconColor;
&:hover {
color: $icon-onHover-color;
color: $Form-select-caret-onHover-iconColor;
}
> svg {
width: px2rem(12px);
height: px2rem(12px);
width: px2rem(10px);
height: px2rem(10px);
top: 0;
}
}
@ -267,6 +267,25 @@
margin: px2rem(3px);
}
.#{$ns}CBFormula {
position: relative;
display: inline-block;
vertical-align: middle;
margin: px2rem(3px);
&-label {
background: $ResultBox-value-bg;
color: $text--muted-color;
display: block;
font-size: $fontSizeSm;
align-self: center;
margin: -5px 0 -5px -8px;
padding: 5px;
border-radius: 5px;
user-select: none;
}
}
.#{$ns}CBSeprator {
width: 20px;
text-align: center;

View File

@ -16,6 +16,9 @@ import Value from './Value';
import InputSwitch from './InputSwitch';
import ConditionFunc from './Func';
import {ThemeProps, themeable} from '../../theme';
import {Config} from './config';
import InputBox from '../InputBox';
import Formula from './Formula';
/**
* 4
@ -33,21 +36,22 @@ export interface ExpressionProps extends ThemeProps {
valueField?: FieldSimple;
fields?: Field[];
funcs?: Funcs;
defaultType?: 'value' | 'field' | 'func' | 'raw';
allowedTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
defaultType?: 'value' | 'field' | 'func' | 'formula';
allowedTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
op?: OperatorType;
config: Config;
}
const fieldMap = {
value: '值',
field: '字段',
func: '函数',
raw: '公式'
formula: '公式'
};
export class Expression extends React.Component<ExpressionProps> {
@autobind
handleInputTypeChange(type: 'value' | 'field' | 'func' | 'raw') {
handleInputTypeChange(type: 'value' | 'field' | 'func' | 'formula') {
let value = this.props.value;
const onChange = this.props.onChange;
@ -65,9 +69,9 @@ export class Expression extends React.Component<ExpressionProps> {
type: 'field',
field: ''
};
} else if (type === 'raw') {
} else if (type === 'formula') {
value = {
type: 'raw',
type: 'formula',
value: ''
};
}
@ -102,7 +106,15 @@ export class Expression extends React.Component<ExpressionProps> {
}
@autobind
handleRawChange() {}
handleFormulaChange(formula: string) {
let value = this.props.value;
const onChange = this.props.onChange;
value = {
type: 'formula',
value: formula
};
onChange(value, this.props.index);
}
render() {
const {
@ -112,15 +124,16 @@ export class Expression extends React.Component<ExpressionProps> {
allowedTypes,
funcs,
fields,
op
op,
classnames: cx
} = this.props;
const inputType =
((value as any)?.type === 'field'
? 'field'
: (value as any)?.type === 'func'
? 'func'
: (value as any)?.type === 'raw'
? 'raw'
: (value as any)?.type === 'formula'
? 'formula'
: value !== undefined
? 'value'
: undefined) ||
@ -173,6 +186,13 @@ export class Expression extends React.Component<ExpressionProps> {
/>
) : null}
{inputType === 'formula' ? (
<Formula
value={(value as any).value}
onChange={this.handleFormulaChange}
/>
) : null}
{types.length > 1 ? (
<InputSwitch
value={inputType}

View File

@ -0,0 +1,27 @@
import React from 'react';
import {ThemeProps, themeable} from '../../theme';
import InputBox from '../InputBox';
export interface FormulaProps extends ThemeProps {
value: any;
onChange: (value: any) => void;
}
export class Formula extends React.Component<FormulaProps> {
render() {
const {classnames: cx, value, onChange} = this.props;
return (
<div className={cx('CBFormula')}>
<InputBox
value={(value as any).value}
onChange={onChange}
placeholder="请输入公式"
prefix={<span className={cx('CBFormula-label')}></span>}
/>
</div>
);
}
}
export default themeable(Formula);

View File

@ -13,8 +13,8 @@ export interface ConditionFuncProps extends ThemeProps {
onChange: (value: ExpressionFunc) => void;
fields?: Field[];
funcs?: Funcs;
defaultType?: 'value' | 'field' | 'func' | 'raw';
allowedTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
defaultType?: 'value' | 'field' | 'func' | 'formula';
allowedTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
}
const option2value = (item: Func) => item.type;

View File

@ -99,6 +99,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
return (
<Expression
config={config}
funcs={funcs}
value={value.left}
onChange={this.handleLeftChange}
@ -244,6 +245,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
return (
<>
<Expression
config={config}
funcs={funcs}
valueField={field}
value={(value.right as Array<ExpressionComplex>)?.[0]}
@ -252,13 +254,14 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
defaultType="value"
allowedTypes={
field?.valueTypes ||
config.valueTypes || ['value', 'field', 'func', 'raw']
config.valueTypes || ['value', 'field', 'func', 'formula']
}
/>
<span className={cx('CBSeprator')}>~</span>
<Expression
config={config}
funcs={funcs}
valueField={field}
value={(value.right as Array<ExpressionComplex>)?.[1]}
@ -267,7 +270,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
defaultType="value"
allowedTypes={
field?.valueTypes ||
config.valueTypes || ['value', 'field', 'func', 'raw']
config.valueTypes || ['value', 'field', 'func', 'formula']
}
/>
</>
@ -276,6 +279,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
return (
<Expression
config={config}
op={op}
funcs={funcs}
valueField={field}
@ -285,7 +289,7 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
defaultType="value"
allowedTypes={
field?.valueTypes ||
config.valueTypes || ['value', 'field', 'func', 'raw']
config.valueTypes || ['value', 'field', 'func', 'formula']
}
/>
);

View File

@ -5,10 +5,14 @@ export interface BaseFieldConfig {
}
export interface Config {
valueTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
valueTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
fields?: Fields;
funcs?: Funcs;
maxLevel?: number; // 还没实现
// todo 起码需要支持 formula 组件可以自定义。
// todo 很多还不能配置。
types: {
[propName: string]: Type;
};

View File

@ -4,7 +4,7 @@ import {LocaleProps, localeable} from '../../locale';
import {uncontrollable} from 'uncontrollable';
import {Fields, ConditionGroupValue, Funcs} from './types';
import ConditionGroup from './Group';
import defaultConfig from './config';
import defaultConfig, {Config} from './config';
import {autobind, findTreeIndex, spliceTree, getTree} from '../../utils/helper';
import {findDOMNode} from 'react-dom';
import animtion from '../../utils/Animation';
@ -15,10 +15,11 @@ export interface ConditionBuilderProps extends ThemeProps, LocaleProps {
showNot?: boolean;
value?: ConditionGroupValue;
onChange: (value: ConditionGroupValue) => void;
config?: Config;
}
export class QueryBuilder extends React.Component<ConditionBuilderProps> {
config = defaultConfig;
config = {...defaultConfig, ...this.props.config};
dragTarget?: HTMLElement;
// dragNextSibling: Element | null;

View File

@ -48,8 +48,8 @@ export type ExpressionField = {
type: 'field';
field: string;
};
export type ExpressionRaw = {
type: 'raw';
export type ExpressionFormula = {
type: 'formula';
value: string;
};
@ -57,7 +57,7 @@ export type ExpressionComplex =
| ExpressionValue
| ExpressionFunc
| ExpressionField
| ExpressionRaw;
| ExpressionFormula;
export interface ConditionRule {
id: any;
@ -78,7 +78,7 @@ export interface ConditionValue extends ConditionGroupValue {}
interface BaseField {
type: FieldTypes;
label: string;
valueTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
valueTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
operators?: Array<string>;
// valueTypes 里面配置 func 才有效。
@ -184,5 +184,5 @@ export type Type = {
defaultOp?: OperatorType;
operators: Array<OperatorType>;
placeholder?: string;
valueTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
valueTypes?: Array<'value' | 'field' | 'func' | 'formula'>;
};

View File

@ -483,7 +483,7 @@ export default class TextControl extends React.PureComponent<
(option: any) => !~selectedItem.indexOf(option.value)
);
if (creatable !== false && this.state.inputValue) {
if (!filtedOptions.length && this.state.inputValue) {
filtedOptions.push({
[labelField || 'label']: this.state.inputValue,
[valueField || 'value']: this.state.inputValue,
@ -578,7 +578,7 @@ export default class TextControl extends React.PureComponent<
'is-disabled': option.disabled
})
})}
key={option.value}
key={`${option.label}-${option.value}`}
>
{option.isNew ? (
<span>