mirror of
https://gitee.com/baidu/amis.git
synced 2024-12-02 03:58:07 +08:00
添加条件组合示例
This commit is contained in:
parent
e3223fa7ab
commit
6efa44c11b
@ -15,6 +15,7 @@ import StaticFormSchema from './Form/Static';
|
||||
import HintFormSchema from './Form/Hint';
|
||||
import FieldSetInTabsFormSchema from './Form/FieldSetInTabs';
|
||||
import ComboFormSchema from './Form/Combo';
|
||||
import ConditionBuilderSchema from './Form/ConditionBuilder';
|
||||
import SubFormSchema from './Form/SubForm';
|
||||
import RichTextSchema from './Form/RichText';
|
||||
import EditorSchema from './Form/Editor';
|
||||
@ -226,6 +227,11 @@ export const examples = [
|
||||
path: '/examples/form/formula',
|
||||
component: makeSchemaRenderer(FormulaFormSchema)
|
||||
},
|
||||
{
|
||||
label: '条件组合',
|
||||
path: '/examples/form/condition-builder',
|
||||
component: makeSchemaRenderer(ConditionBuilderSchema)
|
||||
},
|
||||
|
||||
{
|
||||
label: '引用',
|
||||
|
99
examples/components/Form/ConditionBuilder.jsx
Normal file
99
examples/components/Form/ConditionBuilder.jsx
Normal file
@ -0,0 +1,99 @@
|
||||
export default {
|
||||
$schema: 'https://houtai.baidu.com/v2/schemas/page.json#',
|
||||
title: '条件生成器',
|
||||
body: [
|
||||
{
|
||||
type: 'form',
|
||||
api: '/api/mock2/saveForm?waitSeconds=2',
|
||||
title: '',
|
||||
mode: 'horizontal',
|
||||
horizontal: {
|
||||
leftFixed: true
|
||||
},
|
||||
actions: [
|
||||
{
|
||||
label: '查看数据',
|
||||
type: 'button',
|
||||
actionType: 'dialog',
|
||||
dialog: {
|
||||
title: '数据',
|
||||
body: '<pre>${conditions|json:2}</pre>'
|
||||
}
|
||||
}
|
||||
],
|
||||
controls: [
|
||||
{
|
||||
type: 'condition-builder',
|
||||
label: '条件组件',
|
||||
name: 'conditions',
|
||||
description:
|
||||
'适合让用户自己拼查询条件,然后后端根据数据生成 query where',
|
||||
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: 'D',
|
||||
value: 'd'
|
||||
},
|
||||
{
|
||||
label: 'E',
|
||||
value: 'e'
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
label: '日期',
|
||||
children: [
|
||||
{
|
||||
label: '日期',
|
||||
type: 'date',
|
||||
name: 'date'
|
||||
},
|
||||
{
|
||||
label: '时间',
|
||||
type: 'time',
|
||||
name: 'time'
|
||||
},
|
||||
{
|
||||
label: '日期时间',
|
||||
type: 'datetime',
|
||||
name: 'datetime'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
};
|
@ -137,6 +137,10 @@
|
||||
|
||||
background: rgba(0, 0, 0, 0.03);
|
||||
transition: all 0.3s ease-out;
|
||||
|
||||
> .#{$ns}CBGroup {
|
||||
margin: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
&-body:not(:hover) .#{$ns}CBDelete {
|
||||
|
@ -14,6 +14,7 @@ export interface ConditionGroupProps extends ThemeProps {
|
||||
value?: ConditionGroupValue;
|
||||
fields: Fields;
|
||||
funcs?: Funcs;
|
||||
showNot?: boolean;
|
||||
onChange: (value: ConditionGroupValue) => void;
|
||||
removeable?: boolean;
|
||||
onRemove?: (e: React.MouseEvent) => void;
|
||||
@ -117,13 +118,15 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
config,
|
||||
removeable,
|
||||
onRemove,
|
||||
onDragStart
|
||||
onDragStart,
|
||||
showNot
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx('CBGroup')} data-group-id={value?.id}>
|
||||
<div className={cx('CBGroup-toolbar')}>
|
||||
<div className={cx('CBGroup-toolbarLeft')}>
|
||||
{showNot ? (
|
||||
<Button
|
||||
onClick={this.handleNotClick}
|
||||
className="m-r-xs"
|
||||
@ -133,6 +136,7 @@ export class ConditionGroup extends React.Component<ConditionGroupProps> {
|
||||
>
|
||||
非
|
||||
</Button>
|
||||
) : null}
|
||||
<div className={cx('ButtonGroup')}>
|
||||
<Button
|
||||
size="xs"
|
||||
|
@ -251,7 +251,8 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
fields={fields}
|
||||
defaultType="value"
|
||||
allowedTypes={
|
||||
field?.valueTypes || ['value', 'field', 'func', 'raw']
|
||||
field?.valueTypes ||
|
||||
config.valueTypes || ['value', 'field', 'func', 'raw']
|
||||
}
|
||||
/>
|
||||
|
||||
@ -265,7 +266,8 @@ export class ConditionItem extends React.Component<ConditionItemProps> {
|
||||
fields={fields}
|
||||
defaultType="value"
|
||||
allowedTypes={
|
||||
field?.valueTypes || ['value', 'field', 'func', 'raw']
|
||||
field?.valueTypes ||
|
||||
config.valueTypes || ['value', 'field', 'func', 'raw']
|
||||
}
|
||||
/>
|
||||
</>
|
||||
|
@ -6,9 +6,9 @@ export interface BaseFieldConfig {
|
||||
|
||||
export interface Config {
|
||||
valueTypes?: Array<'value' | 'field' | 'func' | 'raw'>;
|
||||
fields: Fields;
|
||||
fields?: Fields;
|
||||
funcs?: Funcs;
|
||||
maxLevel?: number;
|
||||
maxLevel?: number; // 还没实现
|
||||
types: {
|
||||
[propName: string]: Type;
|
||||
};
|
||||
@ -124,40 +124,6 @@ const defaultConfig: Config = {
|
||||
boolean: {
|
||||
operators: ['equal', 'not_equal']
|
||||
}
|
||||
},
|
||||
|
||||
fields: [
|
||||
// {
|
||||
// type: 'text',
|
||||
// name: 'test',
|
||||
// label: 'Text'
|
||||
// },
|
||||
// {
|
||||
// label: 'Group',
|
||||
// children: [
|
||||
// ]
|
||||
// }
|
||||
],
|
||||
|
||||
// 函数配置示例
|
||||
funcs: [
|
||||
// {
|
||||
// label: '文本',
|
||||
// children: [
|
||||
// {
|
||||
// type: 'LOWERCASE',
|
||||
// label: '转小写',
|
||||
// returnType: 'text',
|
||||
// args: [
|
||||
// {
|
||||
// type: 'text',
|
||||
// label: '文本',
|
||||
// valueTypes: ['raw', 'field']
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
// ]
|
||||
// }
|
||||
]
|
||||
}
|
||||
};
|
||||
export default defaultConfig;
|
||||
|
@ -9,17 +9,19 @@ import {autobind, findTreeIndex, spliceTree, getTree} from '../../utils/helper';
|
||||
import {findDOMNode} from 'react-dom';
|
||||
import animtion from '../../utils/Animation';
|
||||
|
||||
export interface QueryBuilderProps extends ThemeProps, LocaleProps {
|
||||
export interface ConditionBuilderProps extends ThemeProps, LocaleProps {
|
||||
fields: Fields;
|
||||
funcs?: Funcs;
|
||||
showNot?: boolean;
|
||||
value?: ConditionGroupValue;
|
||||
onChange: (value: ConditionGroupValue) => void;
|
||||
}
|
||||
|
||||
export class QueryBuilder extends React.Component<QueryBuilderProps> {
|
||||
export class QueryBuilder extends React.Component<ConditionBuilderProps> {
|
||||
config = defaultConfig;
|
||||
|
||||
dragTarget: HTMLElement;
|
||||
// dragNextSibling: Element | null;
|
||||
ghost: HTMLElement;
|
||||
host: HTMLElement;
|
||||
lastX: number;
|
||||
@ -31,6 +33,7 @@ export class QueryBuilder extends React.Component<QueryBuilderProps> {
|
||||
const target = e.currentTarget;
|
||||
const item = target.closest('[data-id]') as HTMLElement;
|
||||
this.dragTarget = item;
|
||||
// this.dragNextSibling = item.nextElementSibling;
|
||||
this.host = item.closest('[data-group-id]') as HTMLElement;
|
||||
|
||||
const ghost = item.cloneNode(true) as HTMLElement;
|
||||
@ -48,10 +51,10 @@ export class QueryBuilder extends React.Component<QueryBuilderProps> {
|
||||
// 应该是 chrome 的一个bug,如果你马上修改,会马上执行 dragend
|
||||
setTimeout(() => {
|
||||
item.classList.add('is-dragging');
|
||||
item.parentElement!.insertBefore(
|
||||
item,
|
||||
item.parentElement!.firstElementChild
|
||||
); // 挪到第一个,主要是因为样式问题。
|
||||
// item.parentElement!.insertBefore(
|
||||
// item,
|
||||
// item.parentElement!.firstElementChild
|
||||
// ); // 挪到第一个,主要是因为样式问题。
|
||||
}, 5);
|
||||
}
|
||||
|
||||
@ -163,24 +166,41 @@ export class QueryBuilder extends React.Component<QueryBuilderProps> {
|
||||
document.body.removeEventListener('drop', this.handleDragDrop);
|
||||
|
||||
this.dragTarget.classList.remove('is-dragging');
|
||||
// if (this.dragNextSibling) {
|
||||
// this.dragTarget.parentElement!.insertBefore(
|
||||
// this.dragTarget,
|
||||
// this.dragNextSibling
|
||||
// );
|
||||
// } else {
|
||||
// this.dragTarget.parentElement!.appendChild(this.dragTarget);
|
||||
// }
|
||||
delete this.dragTarget;
|
||||
// delete this.dragNextSibling;
|
||||
this.ghost.parentElement?.removeChild(this.ghost);
|
||||
delete this.ghost;
|
||||
}
|
||||
|
||||
render() {
|
||||
const {classnames: cx, fields, funcs, onChange, value} = this.props;
|
||||
const {
|
||||
classnames: cx,
|
||||
fields,
|
||||
funcs,
|
||||
onChange,
|
||||
value,
|
||||
showNot
|
||||
} = this.props;
|
||||
|
||||
return (
|
||||
<ConditionGroup
|
||||
config={this.config}
|
||||
funcs={funcs}
|
||||
fields={fields}
|
||||
funcs={funcs || this.config.funcs}
|
||||
fields={fields || this.config.fields}
|
||||
value={value}
|
||||
onChange={onChange}
|
||||
classnames={cx}
|
||||
removeable={false}
|
||||
onDragStart={this.handleDragStart}
|
||||
showNot={showNot}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -83,6 +83,7 @@ import './renderers/Form/Matrix';
|
||||
import './renderers/Form/Range';
|
||||
import './renderers/Form/Array';
|
||||
import './renderers/Form/Combo';
|
||||
import './renderers/Form/ConditionBuilder';
|
||||
import './renderers/Form/Container';
|
||||
import './renderers/Form/SubForm';
|
||||
import './renderers/Form/RichText';
|
||||
|
31
src/renderers/Form/ConditionBuilder.tsx
Normal file
31
src/renderers/Form/ConditionBuilder.tsx
Normal file
@ -0,0 +1,31 @@
|
||||
import React from 'react';
|
||||
import {FormItem, FormControlProps} from './Item';
|
||||
import ColorPicker from '../../components/ColorPicker';
|
||||
import {Funcs, Fields} from '../../components/condition-builder/types';
|
||||
import {Config} from '../../components/condition-builder/config';
|
||||
import ConditionBuilder from '../../components/condition-builder/index';
|
||||
|
||||
export interface ConditionBuilderProps extends FormControlProps {
|
||||
funcs?: Funcs;
|
||||
fields: Fields;
|
||||
config?: Config;
|
||||
}
|
||||
|
||||
export default class ConditionBuilderControl extends React.PureComponent<
|
||||
ConditionBuilderProps
|
||||
> {
|
||||
render() {
|
||||
const {className, classnames: cx, ...rest} = this.props;
|
||||
|
||||
return (
|
||||
<div className={cx(`ConditionBuilderControl`, className)}>
|
||||
<ConditionBuilder {...rest} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@FormItem({
|
||||
type: 'condition-builder'
|
||||
})
|
||||
export class ConditionBuilderRenderer extends ConditionBuilderControl {}
|
@ -1,4 +1,8 @@
|
||||
// 基本上都是从 sortable 那抄的,让拖拽看起来更流畅。
|
||||
// 基本上都是从 sortable 那抄的,让拖拽切换有个动画,看起来更流畅。
|
||||
// 用法是移动前先 animat.capture(container) 把移动前的位置信息记住
|
||||
// 然后移动节点
|
||||
// 然后 animate.animateAll(); 计算移动后的位置,然后马上通过 css transform 到原来的位置
|
||||
// 然后开始动画到移动后的位置。
|
||||
|
||||
interface Rect {
|
||||
top: number;
|
||||
|
Loading…
Reference in New Issue
Block a user