|
|
@@ -3,12 +3,12 @@
|
|
|
*/
|
|
|
import React from 'react'
|
|
|
import PropTypes from 'prop-types'
|
|
|
-import { Modal, Form, Row, Col, Input, Icon, Button, Cascader, Select, InputNumber, DatePicker, Spin } from 'antd'
|
|
|
-import OPERATORS from './filterOperators.js';
|
|
|
+import { Modal, Form, Row, Col, Input, Icon, Button, Cascader, Select, InputNumber, DatePicker, Spin, Divider } from 'antd'
|
|
|
+import OPERATORS from './filterOperators.js'
|
|
|
import './filterBox.less'
|
|
|
import * as service from '../../../services/index'
|
|
|
import URLS from '../../../constants/url'
|
|
|
-import moment from 'moment';
|
|
|
+import moment from 'moment'
|
|
|
const FormItem = Form.Item
|
|
|
const SelectOption = Select.Option
|
|
|
|
|
|
@@ -23,7 +23,6 @@ class FilterBox extends React.Component {
|
|
|
relationColumns: props.relationColumns || [],
|
|
|
filterData: props.filterData || [],
|
|
|
fetching: false, // 请求列数据状态
|
|
|
- columnData: [], // 列数据
|
|
|
fieldOptions: props.dataSources.map(d => {
|
|
|
return {
|
|
|
name: d.code,
|
|
|
@@ -51,9 +50,9 @@ class FilterBox extends React.Component {
|
|
|
}
|
|
|
|
|
|
componentDidMount() {
|
|
|
- // 将原本的过滤条件生成可视化组件
|
|
|
this.loadColumnDatas();
|
|
|
const { filterData } = this.state;
|
|
|
+ // 将原本的过滤条件生成可视化组件
|
|
|
this.addFilter(filterData.map(f => {
|
|
|
return {
|
|
|
...f,
|
|
|
@@ -104,7 +103,9 @@ class FilterBox extends React.Component {
|
|
|
const { form } = this.props;
|
|
|
const filters = form.getFieldValue('filters');
|
|
|
|
|
|
- this.setState({ columnData: [] });
|
|
|
+ let obj = {};
|
|
|
+ obj['columnData-' + value[0].name + '-' + value[1].name] = [];
|
|
|
+ this.setState(obj);
|
|
|
form.setFieldsValue({
|
|
|
filters: filters.map((f) => {
|
|
|
if (f.key === filter.key) {
|
|
|
@@ -132,7 +133,7 @@ class FilterBox extends React.Component {
|
|
|
form.setFieldsValue({
|
|
|
filters: filters.map((f) => {
|
|
|
if (f.key === filter.key) {
|
|
|
- f.key = uuid++;
|
|
|
+ // f.key = uuid++;
|
|
|
f.operator = value.key;
|
|
|
f.operatorLabel = value.label;
|
|
|
f.value1 = f.value2 = (f.type === 'time' ? moment() : undefined);
|
|
|
@@ -152,7 +153,7 @@ class FilterBox extends React.Component {
|
|
|
form.setFieldsValue({
|
|
|
filters: filters.map((f) => {
|
|
|
if (f.key === filter.key) {
|
|
|
- f.key = uuid++;
|
|
|
+ // f.key = uuid++;
|
|
|
f[`value${index}`] = value;
|
|
|
}
|
|
|
return f;
|
|
|
@@ -178,7 +179,6 @@ class FilterBox extends React.Component {
|
|
|
}
|
|
|
|
|
|
fetchColumnData = (filter, options) => {
|
|
|
- const { columnData } = this.state;
|
|
|
const { keyword, mandatory } = options || {};
|
|
|
const { dataSource } = filter;
|
|
|
const isCusMode = dataSource.name === 'cus';
|
|
|
@@ -186,8 +186,11 @@ class FilterBox extends React.Component {
|
|
|
if(isCusMode) {
|
|
|
column = dataSource.columns.find(c => c.name === filter.name)
|
|
|
}
|
|
|
+ let columnData = this.state['columnData-' + filter.dataSource.name + '-' + filter.name]
|
|
|
if(!columnData || columnData.length === 0 || mandatory) {
|
|
|
- this.setState({ columnData: [], fetching: true }, () => {
|
|
|
+ let obj = {fetching: true};
|
|
|
+ obj['columnData-' + filter.dataSource.name + '-' + filter.name] = []
|
|
|
+ this.setState(obj, () => {
|
|
|
const body = isCusMode ? column.relations.map(r => ({
|
|
|
id: r.dataSource.code,
|
|
|
columnName: r.column.name,
|
|
|
@@ -210,15 +213,13 @@ class FilterBox extends React.Component {
|
|
|
}
|
|
|
}).then(r => {
|
|
|
const resData = r.data.data || [];
|
|
|
- this.setState({
|
|
|
- columnData: resData.map(d => d || 'null'),
|
|
|
- fetching: false
|
|
|
- });
|
|
|
+ let obj = {fetching: false};
|
|
|
+ obj['columnData-' + filter.dataSource.name + '-' + filter.name] = resData.map(d => d || 'null')
|
|
|
+ this.setState(obj);
|
|
|
}).catch(ex => {
|
|
|
- this.setState({
|
|
|
- columnData: [],
|
|
|
- fetching: false
|
|
|
- });
|
|
|
+ let obj = {fetching: false};
|
|
|
+ obj['columnData-' + filter.dataSource.name + '-' + filter.name] = [];
|
|
|
+ this.setState(obj);
|
|
|
console.error('fetch error', ex);
|
|
|
});
|
|
|
});
|
|
|
@@ -298,28 +299,26 @@ class FilterBox extends React.Component {
|
|
|
)}
|
|
|
</FormItem>
|
|
|
</Col>
|
|
|
- <Col span={(operator&&operator!=='null'&&operator!=='notNull')?(operator==='between'?6:12):'0'}>
|
|
|
+ <Col span={(operator&&operator!=='null'&&operator!=='notNull')?(operator==='between'?6:12):0}>
|
|
|
<FormItem
|
|
|
key={key}
|
|
|
className='filterValueOne'
|
|
|
>
|
|
|
{getFieldDecorator(`filterValueOne${key}`, {
|
|
|
initialValue: type==='time' ? ( value1 ? moment(value1) : null) : value1,
|
|
|
- rules: operator&&operator!=='null'&&operator!=='notNull' ? [{ required: true, message: '该值不能为空' }] : null
|
|
|
- })(this.generateValueItem(key, type, operator, 1))}
|
|
|
+ })(this.generateValueItem(f, 1))}
|
|
|
</FormItem>
|
|
|
</Col>
|
|
|
- <Col span={operator==='between'?6:0}>
|
|
|
+ {operator==='between' && <Col span={6}>
|
|
|
<FormItem
|
|
|
key={key}
|
|
|
className='filterValueTwo'
|
|
|
>
|
|
|
{getFieldDecorator(`filterValueTwo${key}`, {
|
|
|
initialValue: type==='time' ? ( value2 ? moment(value2) : null) : value2,
|
|
|
- rules: [{ required: operator==='between', message: '该值不能为空' }]
|
|
|
- })(this.generateValueItem(key, type, operator, 2))}
|
|
|
+ })(this.generateValueItem(f, 2))}
|
|
|
</FormItem>
|
|
|
- </Col>
|
|
|
+ </Col>}
|
|
|
</Col>
|
|
|
<Col span={2} className='filter-remove-col' >
|
|
|
<Icon
|
|
|
@@ -339,6 +338,7 @@ class FilterBox extends React.Component {
|
|
|
const { fieldOptions } = this.state;
|
|
|
|
|
|
return <Cascader
|
|
|
+ allowClear={false}
|
|
|
fieldNames={{ label: 'label', value: 'name', children: 'columns' }}
|
|
|
options={fieldOptions}
|
|
|
loadData={this.loadColumnData}
|
|
|
@@ -362,40 +362,69 @@ class FilterBox extends React.Component {
|
|
|
</Select>)
|
|
|
}
|
|
|
|
|
|
- generateValueItem = (key, type, operator, index) => {
|
|
|
- const { fetching, columnData } = this.state;
|
|
|
+ generateValueItem = (filter, index) => {
|
|
|
+ const { fetching } = this.state;
|
|
|
+ const dropdownOpen = filter.key ? (this.state['dropdownOpen-' + filter.key] || false) : false;
|
|
|
+ const columnData = filter.name ? (this.state['columnData-' + filter.dataSource.name + '-' + filter.name] || []) : [];
|
|
|
let field;
|
|
|
- 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 || [];
|
|
|
+ const { key, type, operator } = filter;
|
|
|
+
|
|
|
+ const commonProps = { placeholder: '无默认值' }
|
|
|
+
|
|
|
if(['index', 'string'].indexOf(type) !== -1) {
|
|
|
- field = <Input onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ field = <Input { ...commonProps } onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
}else if(['scale', 'ordinal'].indexOf(type) !== -1) {
|
|
|
- field = <InputNumber onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ field = <InputNumber { ...commonProps } onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
}else if(type === 'time') {
|
|
|
- field = <DatePicker onChange={(value) => {this.changeFilterValue(filter, value, index)}}/>
|
|
|
+ field = <DatePicker { ...commonProps } onChange={(value) => {this.changeFilterValue(filter, value, index)}}/>
|
|
|
}else if(type === 'categorical') { // 类别
|
|
|
if(operator === 'include' || operator==='notInclude') { // 包含/不包含
|
|
|
- field = <Input onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ field = <Input { ...commonProps } onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
}else if(operator === 'contain' || operator === 'notContain') { // 包括/不包括
|
|
|
field = (<Select
|
|
|
+ { ...commonProps }
|
|
|
+ allowClear
|
|
|
mode='multiple'
|
|
|
showSearch
|
|
|
+ open={dropdownOpen}
|
|
|
+ onDropdownVisibleChange={(open) => {
|
|
|
+ this.onDropdownVisibleChange(filter, open);
|
|
|
+ }}
|
|
|
dropdownMatchSelectWidth={false}
|
|
|
notFoundContent={fetching ? <Spin size="small" /> : '无'}
|
|
|
onSearch={(value) => {this.fetchColumnData(filter, { keyword: value, mandatory: true })}}
|
|
|
onFocus={() => {this.fetchColumnData(filter)}}
|
|
|
onChange={(value) => {this.changeFilterValue(filter, value, index)}}
|
|
|
+ // dropdownRender={menu => (
|
|
|
+ // <div>
|
|
|
+ // {menu}
|
|
|
+ // {columnData.length > 0 && <Divider style={{ margin: '4px 0' }} />}
|
|
|
+ // {columnData.length > 0 && <div style={{ padding: '8px', cursor: 'pointer' }}>
|
|
|
+ // {/** https://github.com/ant-design/ant-design/issues/13448 */}
|
|
|
+ // <span onMouseDown={this.lockClose} onMouseUp={this.lockClose} onClick={() => {
|
|
|
+ // if(commonProps.defaultValue && commonProps.defaultValue.length === columnData.length) {
|
|
|
+ // this.changeFilterValue(filter, [], index)
|
|
|
+ // }else {
|
|
|
+ // this.changeFilterValue(filter, columnData, index)
|
|
|
+ // }
|
|
|
+ // let obj = {};
|
|
|
+ // obj['dropdownOpen-' + filter.key] = false;
|
|
|
+ // this.setState(obj);
|
|
|
+ // }}>
|
|
|
+ // <Icon type={ commonProps.defaultValue && commonProps.defaultValue.length === columnData.length ? 'check-square' : 'border' } /> { commonProps.defaultValue && commonProps.defaultValue.length === columnData.length ? '取消全选' : '全选' }
|
|
|
+ // </span>
|
|
|
+ // </div>}
|
|
|
+ // </div>
|
|
|
+ // )}
|
|
|
>
|
|
|
{ columnData.map((s, i) => {
|
|
|
return <SelectOption key={i} value={s}>{s}</SelectOption>
|
|
|
}) }
|
|
|
</Select>)
|
|
|
}else { // 等于/不等于
|
|
|
- field = (<Select
|
|
|
+ field = (<Select
|
|
|
+ { ...commonProps }
|
|
|
+ allowClear
|
|
|
mode='single'
|
|
|
showSearch
|
|
|
dropdownMatchSelectWidth={false}
|
|
|
@@ -410,12 +439,26 @@ class FilterBox extends React.Component {
|
|
|
</Select>)
|
|
|
}
|
|
|
}else {
|
|
|
- field = <Input onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
+ field = <Input { ...commonProps } onBlur={(e) => {this.changeFilterValue(filter, e.target.value, index)}}/>
|
|
|
}
|
|
|
|
|
|
return field;
|
|
|
}
|
|
|
|
|
|
+ lockClose = e => {
|
|
|
+ clearTimeout(this.lock);
|
|
|
+ this.lock = setTimeout(() => {
|
|
|
+ this.lock = null;
|
|
|
+ }, 100);
|
|
|
+ };
|
|
|
+
|
|
|
+ onDropdownVisibleChange = (filter, open) => {
|
|
|
+ if (this.lock) return;
|
|
|
+ let obj = {};
|
|
|
+ obj['dropdownOpen-' + filter.key] = open;
|
|
|
+ this.setState(obj);
|
|
|
+ };
|
|
|
+
|
|
|
loadColumnDatas() {
|
|
|
let { fieldOptions } = this.state;
|
|
|
fieldOptions.forEach(f => {
|