|
|
@@ -1,14 +1,17 @@
|
|
|
import React from 'react';
|
|
|
-import { Form, Row, Col, Input, Icon, Button, Select } from 'antd';
|
|
|
+import { Form, Row, Col, Input, Icon, Button, Select, InputNumber, DatePicker } from 'antd';
|
|
|
const FormItem = Form.Item;
|
|
|
const SelectOption = Select.Option;
|
|
|
import emitter from '../../../eventManger/ev';
|
|
|
import { isEqual } from '../../../utils/baseUtils.js';
|
|
|
+import OPERATORS from './filterOperators.json';
|
|
|
import './filterBox.less';
|
|
|
|
|
|
let uuid = 0;
|
|
|
class FilterBox extends React.Component {
|
|
|
+
|
|
|
constructor(props) {
|
|
|
+ uuid = 0;
|
|
|
super(props);
|
|
|
this.state = {
|
|
|
columns: [{
|
|
|
@@ -33,127 +36,254 @@ class FilterBox extends React.Component {
|
|
|
name: 'zsf',
|
|
|
type: 'categorical'
|
|
|
}],
|
|
|
- filters: [{
|
|
|
- key: 'c1-1',
|
|
|
- name: 'c1',
|
|
|
- operator: 'like',
|
|
|
- value: '字符串'
|
|
|
- }]
|
|
|
+ filterData: props.filterData || []
|
|
|
}
|
|
|
}
|
|
|
- removeFilter(k) {
|
|
|
+
|
|
|
+ componentDidMount() {
|
|
|
+ // 将原本的过滤条件生成可视化组件
|
|
|
+ const { filterData } = this.state;
|
|
|
+ this.addFilter(filterData.map(f => {
|
|
|
+ return {
|
|
|
+ key: uuid++,
|
|
|
+ name: f.name,
|
|
|
+ label: f.label,
|
|
|
+ type: f.type,
|
|
|
+ operator: f.operator,
|
|
|
+ operatorLabel: f.operatorLabel,
|
|
|
+ value1: f.value1,
|
|
|
+ value2: f.value2,
|
|
|
+ using: f.using
|
|
|
+ }
|
|
|
+ }));
|
|
|
+ // 对外提供接口
|
|
|
+ // 在组件装载完成后发布事件
|
|
|
+ this.eventEmitter = emitter.addListener('getFilters', (callback)=>{
|
|
|
+ this.getFilters(callback)
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ componentWillUnmount() {
|
|
|
+ emitter.removeAllListeners('getFilters');
|
|
|
+ }
|
|
|
+
|
|
|
+ removeFilter = (key) => {
|
|
|
const { form } = this.props;
|
|
|
- // can use data-binding to get
|
|
|
- const keys = form.getFieldValue('keys');
|
|
|
-
|
|
|
- // can use data-binding to set
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+ form.setFieldsValue({
|
|
|
+ filters: filters.filter(filter => filter.key !== key),
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ addFilter = (filtes) => {
|
|
|
+ const { form } = this.props;
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+ const nextFilters = filters.concat(filtes || {
|
|
|
+ key: uuid++,
|
|
|
+ });
|
|
|
form.setFieldsValue({
|
|
|
- keys: keys.filter(key => key !== k),
|
|
|
+ filters: nextFilters,
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- addFilter() {
|
|
|
+ /**
|
|
|
+ * 改变过滤条件字段
|
|
|
+ */
|
|
|
+ changeFilterName = (filter, value) => {
|
|
|
const { form } = this.props;
|
|
|
- // can use data-binding to get
|
|
|
- const keys = form.getFieldValue('keys');
|
|
|
- const nextKeys = keys.concat(uuid);
|
|
|
- uuid++;
|
|
|
- // can use data-binding to set
|
|
|
- // important! notify form to detect changes
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+
|
|
|
form.setFieldsValue({
|
|
|
- keys: nextKeys,
|
|
|
+ filters: filters.map((f) => {
|
|
|
+ if (f.key == filter.key) {
|
|
|
+ f.key = uuid++; // 每次重设key值以保证界面重现渲染,解决Select数据残留的问题
|
|
|
+ f.name = value.key;
|
|
|
+ f.label = value.label;
|
|
|
+ f.type = this.getFilterType(value.key);
|
|
|
+ f.operator = OPERATORS[f.type][0].value;
|
|
|
+ f.operatorLabel = OPERATORS[f.type][0].label;
|
|
|
+ f.value1 = f.value2 = undefined;
|
|
|
+ }
|
|
|
+ return f;
|
|
|
+ })
|
|
|
});
|
|
|
}
|
|
|
|
|
|
- changeFilterName(value) {
|
|
|
- if(value == 'c1') {
|
|
|
+ /**
|
|
|
+ * 改变过滤条件连接符
|
|
|
+ */
|
|
|
+ changeFilterOperator = (filter, value) => {
|
|
|
+ const { form } = this.props;
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+
|
|
|
+ form.setFieldsValue({
|
|
|
+ filters: filters.map((f) => {
|
|
|
+ if (f.key == filter.key) {
|
|
|
+ f.key = uuid++;
|
|
|
+ f.operator = value.key;
|
|
|
+ f.operatorLabel = value.label;
|
|
|
+ }
|
|
|
+ return f;
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
|
|
|
+ /**
|
|
|
+ * 改变过滤条件的值
|
|
|
+ */
|
|
|
+ changeFilterValue = (filter, value, index) => {
|
|
|
+ const { form } = this.props;
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+
|
|
|
+ form.setFieldsValue({
|
|
|
+ filters: filters.map((f) => {
|
|
|
+ if (f.key == filter.key) {
|
|
|
+ f.key = uuid++;
|
|
|
+ f[`value${index}`] = value;
|
|
|
+ }
|
|
|
+ return f;
|
|
|
+ })
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通过列名从数据列中获得其类型
|
|
|
+ */
|
|
|
+ getFilterType = (name) => {
|
|
|
+ let {
|
|
|
+ columns
|
|
|
+ } = this.state, i = 0, type;
|
|
|
+ for (i; i < columns.length; i++) {
|
|
|
+ let column = columns[i];
|
|
|
+ if (column.name == name) {
|
|
|
+ type = column.type;
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
+ return type;
|
|
|
}
|
|
|
|
|
|
- componentDidMount() {
|
|
|
+ /**
|
|
|
+ * 获得设定的过滤条件规则
|
|
|
+ */
|
|
|
+ getFilters = (callback) => {
|
|
|
+ const { form } = this.props;
|
|
|
+ form.validateFields(function(err, values) {
|
|
|
+ if(!err && callback&&(typeof callback == 'function')) {
|
|
|
+ callback(values.filters);
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ getFilterValueField = (key, type, operator, index) => {
|
|
|
+ let field = <Input />, { columns } = this.state;
|
|
|
+ const { form } = this.props;
|
|
|
+ const filters = form.getFieldValue('filters');
|
|
|
+ let filter = filters.filter((f) => {return f.key == key})[0];
|
|
|
+ let column = columns.filter((c) => {return c.name == filter.name});
|
|
|
+ column = column.length>0?column[0]:{selection:[]};
|
|
|
+ column.selection = column.selection || []
|
|
|
+ if(type == 'string') {
|
|
|
+ field = <Input onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ }else if(type == 'number') {
|
|
|
+ field = <InputNumber onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ }else if(type == 'time') {
|
|
|
+ field = <DatePicker onChange={(value) => {this.changeFilterValue(filter, value, index)}}/>
|
|
|
+ }else if(type == 'categorical') {
|
|
|
+ field = <Select
|
|
|
+ mode={operator=='in'?'multiple':''}
|
|
|
+ onChange={(value) => {this.changeFilterValue(filter, value, index)}}
|
|
|
+ >
|
|
|
+ { column.selection.map((s, i) => {
|
|
|
+ return <SelectOption key={i} value={s}>{s}</SelectOption>
|
|
|
+ }) }
|
|
|
+ </Select>
|
|
|
+ }
|
|
|
+
|
|
|
+ return field;
|
|
|
}
|
|
|
|
|
|
getFilterItems() {
|
|
|
- const { columns } = this.state;
|
|
|
+ const { columns, filterData } = this.state;
|
|
|
const { getFieldDecorator, getFieldValue } = this.props.form;
|
|
|
- getFieldDecorator('keys', { initialValue: []});
|
|
|
- const keys = getFieldValue('keys');
|
|
|
- const filterItems = keys.map((k, index) => {
|
|
|
+ getFieldDecorator('filters', { initialValue: [] });
|
|
|
+ const filters = getFieldValue('filters');
|
|
|
+ const filterItems = filters.map((f, index) => {
|
|
|
+ let { key, name, type, operator, value1, value2 } = f;
|
|
|
return (
|
|
|
- <div key={`filterDiv[${k}]`}>
|
|
|
- <Row key={`filterRow[${k}]`}>
|
|
|
- <Col span={24}>
|
|
|
- <FormItem required={true} key={k}>
|
|
|
- {getFieldDecorator(`filterName[${k}]`, {
|
|
|
- validateTrigger: ['onChange', 'onBlur'],
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- whitespace: true,
|
|
|
- message: "请选择过滤字段",
|
|
|
- }],
|
|
|
- initialValue: ''
|
|
|
+ <Row key={`filterDiv[${key}]`}>
|
|
|
+ <Col span={22}>
|
|
|
+ {}
|
|
|
+ <Col span={6}>
|
|
|
+ <FormItem key={key}>
|
|
|
+ {getFieldDecorator(`filterName${key}`, {
|
|
|
+ initialValue: name?{key: name}:undefined
|
|
|
})(
|
|
|
<Select
|
|
|
showSearch={true}
|
|
|
- filterOption={function(inputValue, option){
|
|
|
- let { value, children } = option.props;
|
|
|
- return value.toLowerCase().indexOf(inputValue.toLowerCase()) != -1 ||
|
|
|
- children.toLowerCase().indexOf(inputValue.toLowerCase()) != -1;
|
|
|
- }}
|
|
|
- onChange={(value) => {this.changeFilterName(value)}}
|
|
|
+ labelInValue={true}
|
|
|
+ filterOption={
|
|
|
+ function (inputValue, option) {
|
|
|
+ let { value, children } = option.props;
|
|
|
+ return value.toLowerCase().indexOf(inputValue.toLowerCase()) != -1 ||
|
|
|
+ children.toLowerCase().indexOf(inputValue.toLowerCase()) != -1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ onChange={(value) => {this.changeFilterName(f, value)}}
|
|
|
>
|
|
|
- {columns.map((c, i) => { return (<SelectOption key={i} value={c.name}>{c.label}</SelectOption>) })}
|
|
|
- </Select>
|
|
|
- )}
|
|
|
+ {columns.map((c, i) => {
|
|
|
+ return (
|
|
|
+ <SelectOption key={i} value={c.name}>{c.label}</SelectOption>
|
|
|
+ )
|
|
|
+ })}
|
|
|
+ </Select>)}
|
|
|
</FormItem>
|
|
|
</Col>
|
|
|
- </Row>
|
|
|
- <Row>
|
|
|
- <Col span={10}>
|
|
|
- <FormItem required={true}>
|
|
|
- {getFieldDecorator(`filterOperator[${k}]`, {
|
|
|
- validateTrigger: ['onChange', 'onBlur'],
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- whitespace: true,
|
|
|
- message: "请选择过滤条件",
|
|
|
- }],
|
|
|
- initialValue: ''
|
|
|
+ <Col span={6}>
|
|
|
+ <FormItem key={key} className='filterOperator'>
|
|
|
+ {getFieldDecorator(`filterOperator${key}`, {
|
|
|
+ initialValue: operator?{key: operator}:undefined
|
|
|
})(
|
|
|
<Select
|
|
|
- onFocus={function(){debugger;}}
|
|
|
- onChange={(value) => { }}
|
|
|
+ labelInValue={true}
|
|
|
+ onChange={(value) => {this.changeFilterOperator(f, value)}}
|
|
|
>
|
|
|
- { this.getFilterOperator }
|
|
|
+ {OPERATORS[type].map((o, i) => {
|
|
|
+ return <SelectOption key={i} value={o.value}>{o.label}</SelectOption>;
|
|
|
+ })}
|
|
|
</Select>
|
|
|
)}
|
|
|
</FormItem>
|
|
|
</Col>
|
|
|
- <Col span={12}>
|
|
|
- <FormItem required={true}>
|
|
|
- {getFieldDecorator(`filterValue[${k}]`, {
|
|
|
- validateTrigger: ['onChange', 'onBlur'],
|
|
|
- rules: [{
|
|
|
- required: true,
|
|
|
- whitespace: true,
|
|
|
- message: "请输入条件值",
|
|
|
- }],
|
|
|
- initialValue: ''
|
|
|
- })(
|
|
|
- <Input />
|
|
|
- )}
|
|
|
+ <Col span={(operator&&operator!='null')?(operator=='between'?6:12):'0'}>
|
|
|
+ <FormItem
|
|
|
+ key={key}
|
|
|
+ className='filterValueOne'
|
|
|
+ >
|
|
|
+ {getFieldDecorator(`filterValueOne${key}`, {
|
|
|
+ initialValue: value1
|
|
|
+ })(this.getFilterValueField(key, type, operator, 1))}
|
|
|
</FormItem>
|
|
|
</Col>
|
|
|
- <Col span={2} className=''>
|
|
|
- <Icon
|
|
|
- className="dynamic-delete-button"
|
|
|
- type="close"
|
|
|
- onClick={() => { this.removeFilter(k) }}
|
|
|
- />
|
|
|
+ <Col span={operator=='between'?6:0}>
|
|
|
+ <FormItem
|
|
|
+ key={key}
|
|
|
+ className='filterValueTwo'
|
|
|
+ >
|
|
|
+ {getFieldDecorator(`filterValueTwo${key}`, {
|
|
|
+ initialValue: value2
|
|
|
+ })(this.getFilterValueField(key, type, operator, 2))}
|
|
|
+ </FormItem>
|
|
|
</Col>
|
|
|
- </Row>
|
|
|
- </div>
|
|
|
+ </Col>
|
|
|
+ <Col span={2} className='' >
|
|
|
+ <Icon
|
|
|
+ className="dynamic-delete-button"
|
|
|
+ type="close"
|
|
|
+ onClick={() => { this.removeFilter(key) }}
|
|
|
+ />
|
|
|
+ </Col>
|
|
|
+ </Row>
|
|
|
);
|
|
|
});
|
|
|
|
|
|
@@ -162,13 +292,18 @@ class FilterBox extends React.Component {
|
|
|
|
|
|
render() {
|
|
|
return (
|
|
|
- <Form>
|
|
|
- { this.getFilterItems()}
|
|
|
+ <Form size='small'>
|
|
|
+ {this.getFilterItems()}
|
|
|
<Row>
|
|
|
<Col>
|
|
|
<FormItem>
|
|
|
- <Button type="dashed" onClick={this.addFilter.bind(this)} style={{ width: '100%' }}>
|
|
|
- <Icon type="plus" /> 添加
|
|
|
+ <Button
|
|
|
+ className='filter-add-button'
|
|
|
+ type="dashed"
|
|
|
+ onClick={() => {this.addFilter()}}
|
|
|
+ >
|
|
|
+ <Icon type="plus" />
|
|
|
+ 添加
|
|
|
</Button>
|
|
|
</FormItem>
|
|
|
</Col>
|