Browse Source

搜索报错调整/图表自动刷新参数设为组件state而非model字段/针对调整撤销重做图表loading显示逻辑

zhuth 7 years ago
parent
commit
7201541d7e

+ 52 - 4
src/components/chart/chooseDataSourceBox.jsx

@@ -9,6 +9,7 @@ class ChooseDataSourceBox extends React.Component {
     constructor(props) {
         super(props);
         this.state = {
+            filterLabel: '',
             selectedRecord: null
         }
     }
@@ -34,6 +35,9 @@ class ChooseDataSourceBox extends React.Component {
         const { selectedRecord } = this.state;
         const { dataSource, visibleBox, hideBox } = this.props
 
+        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+        let filterLabel = this.state.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+        
         const columns = [{
             title: '选择',
             key: 'selected',
@@ -49,7 +53,20 @@ class ChooseDataSourceBox extends React.Component {
             render: (text, record) => {
                 return <div className='datasource-name'>
                     <div className={`datasource-type type-${record.type.key}`}></div>
-                    <div>{text}</div>
+                    <div>
+                        <span>
+                            { filterLabel ?
+                                (text.split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                                    return (
+                                        fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                                        <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                                        fragment
+                                    )
+                                }
+                                )) : text
+                            }
+                        </span>
+                    </div>
                 </div>
             }
         }, {
@@ -67,7 +84,23 @@ class ChooseDataSourceBox extends React.Component {
             title: '说明',
             dataIndex: 'description',
             key: 'description',
-            width: 200
+            width: 200,
+            render: (text, record) => {
+                return (
+                    <span>
+                        { filterLabel ?
+                            (text.split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                                return (
+                                    fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                                    <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                                    fragment
+                                )
+                            }
+                            )) : text
+                        }
+                    </span>
+                )
+            }
         }];
 
         return (
@@ -76,7 +109,14 @@ class ChooseDataSourceBox extends React.Component {
                 title={
                     <Row>
                         <Col span={14}>选择数据源</Col>
-                        <Col span={8}><Search /></Col>
+                        <Col span={8}><Search 
+                            placeholder="请输入关键字"
+                            onChange={e => {
+                                this.setState({
+                                    filterLabel: e.target.value
+                                });
+                            }}
+                        /></Col>
                     </Row>
                 }
                 visible={visibleBox}
@@ -88,7 +128,15 @@ class ChooseDataSourceBox extends React.Component {
                 <Table
                     className='choosedatasource-table'
                     columns={columns}
-                    dataSource={dataSource.list}
+                    dataSource={dataSource.list.filter(l => {
+                        try{
+                            let regLabel = new RegExp('(' + filterLabel + '){1}', 'ig');
+                            return (l.name || '').search(regLabel) !== -1 || (l.description || '').search(regLabel) !== -1;
+                        }catch(e) {
+                            console.log(e);
+                            return true;
+                        }
+                    })}
                     size='small'
                     scroll={{x: false, y: 471}}
                     pagination={false}

+ 1 - 1
src/components/chart/list.jsx

@@ -88,7 +88,7 @@ class ChartList extends React.Component {
 
         let cards = list.filter(l => groupFilter.indexOf(l.groupCode+'') !== -1).filter(l => {
             let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
-            return l.name.search(reg) !== -1 || l.description.search(reg) !== -1;
+            return (l.name || '').search(reg) !== -1 || (l.description || '').search(reg) !== -1;
         }).sort((a, b) => {
             return new Date(b.createTime) - new Date(a.createTime)
         }).map( (l, i) => (

+ 22 - 9
src/components/chartDesigner/content.jsx

@@ -18,9 +18,18 @@ const { Header, Sider, Content, Footer } = Layout
 const { TabPane } = Tabs
 
 class ChartDesignerContent extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            autoRefresh: true
+        }
+    }
+
     render() {
         const { chartDesigner, dispatch } = this.props;
-        const { baseConfig, autoRefresh } = chartDesigner;
+        const { autoRefresh } = this.state;
+        const { baseConfig } = chartDesigner;
         const { viewType } = baseConfig;
         const formItemLayout = {
             labelCol: { span: 8 },
@@ -30,25 +39,26 @@ class ChartDesignerContent extends React.Component {
         let configForm, chartView;
 
         if(viewType === 'aggregateTable') {
-            configForm = (<AggregateTableConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<AggregateTableConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<TableView />);
         }else if(viewType === 'dataView') {
-            configForm = (<DataViewConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<DataViewConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<TableView />);
         }else if(viewType === 'line') {
-            configForm = (<LineConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<LineConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<EchartsView />);
         }else if(viewType === 'bar') {
-            configForm = (<BarConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<BarConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<EchartsView />);
         }else if(viewType === 'pie') {
-            configForm = (<PieConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<PieConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<EchartsView />);
         }else if(viewType === 'scatter') {
-            configForm = (<ScatterConfigForm formItemLayout={formItemLayout}/>);
+            configForm = (<ScatterConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<EchartsView />);
         }
 
+        console.log(autoRefresh);
         return (
             <Layout className='chartdesigner'>
                 <Sider className='sider-left' width={300}>
@@ -71,9 +81,12 @@ class ChartDesignerContent extends React.Component {
                                 if(checked) {
                                     dispatch({ type: 'chartDesigner/fetchChartData' });
                                 }
-                                dispatch({ type: 'chartDesigner/silentSetField', name: 'autoRefresh', value: checked })
+                                this.setState({
+                                    autoRefresh: checked
+                                });
+                                // dispatch({ type: 'chartDesigner/silentSetField', name: 'autoRefresh', value: checked })
                             }}/>
-                            <Button hidden={autoRefresh} size='small' onClick={() => { dispatch({ type: 'chartDesigner/fetchChartData'}) }}
+                            <Button style={{ display: autoRefresh ? 'none' : 'block' }} size='small' onClick={() => { dispatch({ type: 'chartDesigner/fetchChartData'}) }}
                             >立即刷新</Button>
                         </div>
                     </Footer> 

+ 8 - 0
src/components/chartDesigner/content.less

@@ -29,4 +29,12 @@
             font-size: 12px;
         }
     }
+    .ant-cascader-picker-focused {
+        color: rgba(0, 0, 0, .65);
+    }
+    .ant-cascader-picker-with-value {
+        .ant-tag,.empty-label,.ant-cascader-picker-label {
+            display: none;
+        }
+    }
 }

+ 12 - 1
src/components/chartDesigner/layout.jsx

@@ -31,7 +31,18 @@ class ChartDesigner extends React.Component {
     }
 }
 function mapStateToProps(state) {
-    const loading = state.present.loading.models.chartDesigner;
+    let effectsArr = ['chart/remoteDetail', 'chart/remoteGroupList', 'chartDesigner/remoteDataColumn', 'chartDesigner/fetchLineData',
+        'chartDesigner/fetchBarData', 'chartDesigner/fetchPieData', 'chartDesigner/fetchScatterData', 'chartDesigner/fetchDataViewData', 'chartDesigner/fetchAggregateTableData'];
+    let loading = false;
+    effectsArr.map(e => {
+        return state.present.loading.effects['chart/remoteDetail'];
+    });
+    for(let i = 0; i < effectsArr.length; i++) {
+        if(state.present.loading.effects[effectsArr[i]]) {
+            loading = true;
+            break;
+        }
+    }
 
     return { loading }
 }

+ 49 - 9
src/components/chartDesigner/sections/ScatterConfigForm.jsx

@@ -5,7 +5,7 @@ import GAUGE from './gauge.json'
 const FormItem = Form.Item
 const { Option } = Select
 
-const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
+const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
 	
 	const columns = chartDesigner.columns;
 
@@ -15,8 +15,28 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 				<Cascader
 					value={[chartDesigner.scatterConfig.xAxis.column.value, chartDesigner.scatterConfig.xAxis.granularity.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.filter(c =>['scale', 'ordinal'].indexOf(c.type) !== -1).map((c, i)=>{
 						return {
 							type: c.type,
@@ -35,7 +55,7 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 						if(items.length > 1) {
 							granularity = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, xAxis: { column, granularity } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, xAxis: { column, granularity } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let text = '';
@@ -60,8 +80,28 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					className='gauge-item'
 					value={[chartDesigner.scatterConfig.yAxis.column.value, chartDesigner.scatterConfig.yAxis.gauge.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.map((c, i)=>{
 						return {
 							value: c.name,
@@ -82,7 +122,7 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 							column = { type: items[0].type, value: items[0].value, label: items[0].label };
 							gauge = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, yAxis: { column, gauge } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, yAxis: { column, gauge } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let menu = selectedOptions.length > 0 ? <Menu
@@ -99,7 +139,7 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 											column: chartDesigner.scatterConfig.yAxis.column,
 											gauge: { value, label }
 										}
-									}});
+									}, autoRefresh });
 									e.domEvent.stopPropagation();
 								}}>{c.label}</Menu.Item>
 							})}
@@ -130,7 +170,7 @@ const ScatterConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					placeholder='请选择...'
 					onChange={(value) => {
 						// value = value.splice(-1);
-						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, groupBy: value } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, groupBy: value }, autoRefresh });
 					}}
 					value={chartDesigner.scatterConfig.groupBy}
 				>

+ 4 - 4
src/components/chartDesigner/sections/aggregateTableConfigForm.jsx

@@ -23,7 +23,7 @@ class AggregateTableConfigForm extends React.Component {
 	}
 	render() {
 		const props = this.props;
-		const { formItemLayout, chartDesigner, dispatch } = props;
+		const { autoRefresh, formItemLayout, chartDesigner, dispatch } = props;
 		const{ searchKey } = this.state;
 		const { columns, aggregateTableConfig } = chartDesigner;
 		
@@ -38,7 +38,7 @@ class AggregateTableConfigForm extends React.Component {
 						filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
 						onChange={(value) => {
 							let column = columns.filter(c => c.name === value)[0];
-							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...chartDesigner.aggregateTableConfig, targetColumn: column, statistics: [] } });
+							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...chartDesigner.aggregateTableConfig, targetColumn: column, statistics: [] }, autoRefresh });
 						}}
 					>
 						{options.map((c, i)=>{
@@ -50,7 +50,7 @@ class AggregateTableConfigForm extends React.Component {
 					<CheckboxGroup
 						value={aggregateTableConfig.statistics}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...props.chartDesigner.aggregateTableConfig, statistics: value } });
+							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...props.chartDesigner.aggregateTableConfig, statistics: value }, autoRefresh });
 						}}
 					>
 						<Row>
@@ -69,7 +69,7 @@ class AggregateTableConfigForm extends React.Component {
 						showSearch
 						filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...props.chartDesigner.aggregateTableConfig, groupBy: value } });
+							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...props.chartDesigner.aggregateTableConfig, groupBy: value }, autoRefresh });
 						}}
 						value={chartDesigner.aggregateTableConfig.groupBy}
 					>

+ 55 - 17
src/components/chartDesigner/sections/barConfigForm.jsx

@@ -6,8 +6,7 @@ import GRANULARITY from './granularity.json'
 const FormItem = Form.Item
 const { Option } = Select
 
-const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
-	
+const BarConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
 	const columns = chartDesigner.columns;
 
 	return (
@@ -17,8 +16,28 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					className='barconfig-yaxis'
 					value={[chartDesigner.barConfig.xAxis.column.value, chartDesigner.barConfig.xAxis.granularity.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.filter(c =>['ordinal', 'categorical', 'time'].indexOf(c.type) !== -1).map((c, i)=>{
 						
 						return {
@@ -37,7 +56,7 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 						if(items.length > 1) {
 							granularity = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, xAxis: { column, granularity } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, xAxis: { column, granularity } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let text = '';
@@ -62,19 +81,39 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					className='gauge-item'
 					value={[chartDesigner.barConfig.yAxis.column.value, chartDesigner.barConfig.yAxis.gauge.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.map((c, i)=>{
 						return {
 							value: c.name,
 							label: c.label,
 							children: GAUGE[chartDesigner.baseConfig.viewType].map(g => {
-                                if(g.columnType.indexOf(c.type) !== -1) {
-                                    return g;
-                                }else {
-                                    return null;
-                                }
-                            }).filter( g => g!==null)
+								if(g.columnType.indexOf(c.type) !== -1) {
+									return g;
+								}else {
+									return null;
+								}
+							}).filter( g => g!==null)
 						}
 					})}
 					onChange={(value, items) => {
@@ -84,7 +123,7 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 							column = { type: items[0].type, value: items[0].value, label: items[0].label };
 							gauge = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, yAxis: { column, gauge } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, yAxis: { column, gauge } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let menu = selectedOptions.length > 0 ? <Menu
@@ -101,7 +140,7 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 											column: chartDesigner.barConfig.yAxis.column,
 											gauge: { value, label }
 										}
-									}});
+									}, autoRefresh });
 									e.domEvent.stopPropagation();
 								}}>{c.label}</Menu.Item>
 							})}
@@ -130,8 +169,7 @@ const BarConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
 					allowClear={true}
 					onChange={(value) => {
-						// value = value.splice(-1);
-						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, groupBy: value } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, groupBy: value }, autoRefresh });
 					}}
 					value={chartDesigner.barConfig.groupBy}
 				>

+ 0 - 2
src/components/chartDesigner/sections/baseConfigForm.jsx

@@ -45,9 +45,7 @@ class baseConfigForm extends React.Component {
 						CHART_TYPE.map( c => (
 							<Option key={c.type} value={c.type} title={c.label}>
 								<div className='viewtype-box'>
-									{/* <div className={`viewtype-icon viewtype-${c.type}`}> */}
 									<Icon className='viewtype-icon' type={c.icon} />
-									{/* </div> */}
 									<div className='viewtype-text'>
 										{c.label}
 									</div>

+ 13 - 7
src/components/chartDesigner/sections/dataViewConfigForm.jsx

@@ -1,12 +1,18 @@
 import React from 'react'
-import { Form, Select, InputNumber  } from 'antd'
+import { Form, Select, InputNumber } from 'antd'
 import { connect } from 'dva'
 const FormItem = Form.Item
 const { Option } = Select
 
 class DataViewConfigForm extends React.Component {
+	constructor(props) {
+		super(props);
+		this.state = {
+			showBox: false
+		}
+	}
 	render() {
-		const { dispatch, chartDesigner, formItemLayout } = this.props;
+		const { autoRefresh, dispatch, chartDesigner, formItemLayout } = this.props;
 		const columns = chartDesigner.columns;
         console.log(chartDesigner.dataViewConfig);
 		return (
@@ -15,12 +21,12 @@ class DataViewConfigForm extends React.Component {
 					<Select
 						mode='multiple'
 						allowClear
+						showArrow={true}
 						value={chartDesigner.dataViewConfig.viewColumns}
 						showSearch
-						filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
 						labelInValue={true}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, viewColumns: value }});
+							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, viewColumns: value }, autoRefresh });
 						}}
 					>
 						{columns.map((c, i)=>{
@@ -36,7 +42,7 @@ class DataViewConfigForm extends React.Component {
 						showSearch
 						filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, sortColumn: value }});
+							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, sortColumn: value }, autoRefresh });
 						}}
 					>
 						{columns.filter(c => chartDesigner.dataViewConfig.viewColumns.map(c => c.key).indexOf(c.name) !== -1 ).map((c, i)=>{
@@ -49,7 +55,7 @@ class DataViewConfigForm extends React.Component {
 						defaultValue='asc'
 						value={chartDesigner.dataViewConfig.sortType}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, sortType: value }});
+							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, sortType: value }, autoRefresh });
 						}}
 					>
 						<Option value="asc">升序</Option>
@@ -61,7 +67,7 @@ class DataViewConfigForm extends React.Component {
 						min={0}
 						defaultValue={chartDesigner.dataViewConfig.count}
 						onChange={(value) => {
-							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, count: value }});
+							dispatch({ type: 'chartDesigner/changeField', name: 'dataViewConfig', value: { ...chartDesigner.dataViewConfig, count: value }, autoRefresh });
 						}}
 					>
 					</InputNumber>

+ 49 - 9
src/components/chartDesigner/sections/lineConfigForm.jsx

@@ -6,7 +6,7 @@ import GAUGE from './gauge.json'
 const FormItem = Form.Item
 const { Option } = Select
 
-const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
+const LineConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
 	
 	const columns = chartDesigner.columns;
 
@@ -16,8 +16,28 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 				<Cascader
 					value={[chartDesigner.lineConfig.xAxis.column.value, chartDesigner.lineConfig.xAxis.granularity.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.filter(c =>['time'].indexOf(c.type) !== -1).map((c, i)=>{
 						return {
 							type: c.type,
@@ -34,7 +54,7 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 						if(items.length > 1) {
 							granularity = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, xAxis: { column, granularity } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, xAxis: { column, granularity } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let text = '';
@@ -59,8 +79,28 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					className='gauge-item'
 					value={[chartDesigner.lineConfig.yAxis.column.value, chartDesigner.lineConfig.yAxis.gauge.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.map((c, i)=>{
 						return {
 							value: c.name,
@@ -81,7 +121,7 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 							column = { type: items[0].type, value: items[0].value, label: items[0].label };
 							gauge = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, yAxis: { column, gauge } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, yAxis: { column, gauge } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let menu = selectedOptions.length > 0 ? <Menu
@@ -98,7 +138,7 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 											column: chartDesigner.lineConfig.yAxis.column,
 											gauge: { value, label }
 										}
-									}});
+									}, autoRefresh });
 									e.domEvent.stopPropagation();
 								}}>{c.label}</Menu.Item>
 							})}
@@ -129,7 +169,7 @@ const LineConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					placeholder='请选择...'
 					onChange={(value) => {
 						// value = value.splice(-1);
-						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, groupBy: value } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, groupBy: value }, autoRefresh });
 					}}
 					value={chartDesigner.lineConfig.groupBy}
 				>

+ 48 - 8
src/components/chartDesigner/sections/pieConfigForm.jsx

@@ -6,7 +6,7 @@ import GAUGE from './gauge.json'
 import GRANULARITY from './granularity.json'
 const FormItem = Form.Item
 
-const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
+const PieConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
 	
 	const columns = chartDesigner.columns;
 
@@ -16,8 +16,28 @@ const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 				<Cascader
 					value={[chartDesigner.pieConfig.xAxis.column.value, chartDesigner.pieConfig.xAxis.granularity.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.filter(c =>['ordinal', 'categorical', 'time'].indexOf(c.type) !== -1).map((c, i)=>{
 						
 						return {
@@ -36,7 +56,7 @@ const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 						if(items.length > 1) {
 							granularity = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'pieConfig', value: { ...chartDesigner.pieConfig, xAxis: { column, granularity } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'pieConfig', value: { ...chartDesigner.pieConfig, xAxis: { column, granularity } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let text = '';
@@ -61,8 +81,28 @@ const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 					className='gauge-item'
 					value={[chartDesigner.pieConfig.yAxis.column.value, chartDesigner.pieConfig.yAxis.gauge.value]}
 					allowClear={true}
-					showSearch
-					filterOption={(input, option) => option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0}
+					showSearch={{
+						filter: (inputValue, path) => {
+							let p0 = path[0].label.toLowerCase();
+							let v = inputValue.toLowerCase();
+							return p0.indexOf(v) !== -1;
+						},
+						sort: (a, b, inputValue) => {
+							return a[0].label.localeCompare(b[0].label,"zh");
+						},
+						render: (inputValue, path) => {
+							const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+							let v = inputValue.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+							let label0 = (path[0].label.split(new RegExp(`(${v})`, 'i')).map((fragment, i) => {
+								return (
+									fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === v.toLowerCase() ?
+									<span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+									fragment
+								)
+							}))
+							return <div>{label0}>{path[1].label}</div>
+						}
+					}}
 					options={columns.map((c, i)=>{
 						return {
 							value: c.name,
@@ -83,7 +123,7 @@ const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 							column = { type: items[0].type, value: items[0].value, label: items[0].label };
 							gauge = { value: items[1].value, label: items[1].label };
 						}
-						dispatch({ type: 'chartDesigner/changeField', name: 'pieConfig', value: { ...chartDesigner.pieConfig, yAxis: { column, gauge } } });
+						dispatch({ type: 'chartDesigner/changeField', name: 'pieConfig', value: { ...chartDesigner.pieConfig, yAxis: { column, gauge } }, autoRefresh });
 					}}
 					displayRender={(label, selectedOptions) => {
 						let menu = selectedOptions.length > 0 ? <Menu
@@ -100,7 +140,7 @@ const PieConfigForm = ({ chartDesigner, dispatch, formItemLayout }) => {
 											column: chartDesigner.pieConfig.yAxis.column,
 											gauge: { value, label }
 										}
-									}});
+									}, autoRefresh });
 									e.domEvent.stopPropagation();
 								}}>{c.label}</Menu.Item>
 							})}

+ 0 - 16
src/components/datasource/columnConfig.jsx

@@ -98,22 +98,6 @@ class DataSourceColumnConfig extends React.Component {
             dataIndex: 'description',
             key: 'description',
             width: widths[2],
-            render: (text, record) => {
-                return <Input
-                    value={text}
-                    onChange={(e) => {
-                        let columns = dataSource.newOne.columns.map(c => {
-                            if(c.key === record.key) {
-                                c['description'] = e.target.value;
-                            }
-                            return c;
-                        });
-                        
-                        dispatch({ type: 'dataSource/setNewModelField', name: 'columns', value: columns });
-                    }}
-                >
-                </Input>
-            }
         }, {
             title: '数据类型',
             dataIndex: 'dataType',

+ 5 - 2
src/components/datasource/dataConnectConfig.jsx

@@ -17,7 +17,9 @@ class DataConnectConfig extends React.Component {
 
     render() {
         const { dataSource, dataConnect, dispatch } = this.props;
-        const filterLabel = dataConnect.filterLabel;
+        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+        let filterLabel = dataConnect.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+        
         const generateCard = () => {
             const operationMenu = (
                 <Menu className='menu-operation'>
@@ -39,7 +41,8 @@ class DataConnectConfig extends React.Component {
             )
 
             let cards = dataConnect.list.filter(l => {
-                return l.name.search(new RegExp('(' + filterLabel + '){1}', 'ig')) !== -1;
+                return ((l.name || '').search(new RegExp('(' + filterLabel + '){1}', 'ig')) !== -1) ||
+                    ((l.description || '').search(new RegExp('(' + filterLabel + '){1}', 'ig')) !== -1);
             }).map( (l, i) => (
                 <CardGrid className='dataconnect-card' key={i}>
                     <Card

+ 9 - 4
src/components/datasource/dataSource.jsx

@@ -63,9 +63,9 @@ class DataSource extends React.Component {
         return list.map(l => {
             let o = Object.assign({}, l);
             let reg = new RegExp('('+ text +'){1}', 'ig');
-            if(o.name.search(reg) !== -1) {
+            if(o.name && o.name.search(reg) !== -1) {
                 return o;
-            }else if(o.description.search(reg) !== -1) {
+            }else if(o.description && o.description.search(reg) !== -1) {
                 return o;
             }else {
                 return null
@@ -90,9 +90,11 @@ class DataSource extends React.Component {
         const pGroups = groupList.filter(d => d.pcode === '-1').sort((a, b) => a.index - b.index);
         const cGroups = groupList.filter(d => d.pcode !== '-1');
 
-        let allGroups = selectedRecord ? pGroups : [
+        let allGroups = selectedRecord ? [
+            { code: '-1', label: '未分组' }
+        ].concat(pGroups) : [
             { code: 'all', label: '全部分组' },
-            { code: 'nogroup', label: '未分组' }
+            { code: '-1', label: '未分组' }
         ].concat(pGroups);
 
         return allGroups.map(p => {
@@ -123,6 +125,9 @@ class DataSource extends React.Component {
             ) : (
                 <Menu.Item key={p.code} onClick={() => {
                     dispatch({ type: 'dataSource/setCurrentGroup', group1: p });
+                    if(selectedRecord) {
+                        dispatch({ type: 'dataSource/remoteSetDataSourceGroup', dataSource: selectedRecord, group: p });
+                    }
                     this.hideGroupMenu();
                 }}><span className={selectedRecord ? (
                     selectedRecord.groupCode+'' === p.code+'' ? 'selected' : ''

+ 8 - 14
src/models/chartDesigner.js

@@ -52,7 +52,7 @@ export default {
             header: { label: '标题' },
             baseConfig: { dataSource: '', viewType: '' },
             aggregateTableConfig: { targetColumn: {}, statistics: [], groupBy: [] },
-            dataViewConfig: { viewColumns: [], sortColumn: {}, sortType: 'asc' },
+            dataViewConfig: { viewColumns: [], sortColumn: {key: ''}, sortType: 'asc', count: 25 },
             barConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''} },
             lineConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''} },
             pieConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
@@ -60,7 +60,6 @@ export default {
             style: {},
             filters: [],
             chartOption: {},
-            autoRefresh: true
         },
         columns: [],
         allPermission: [
@@ -73,7 +72,7 @@ export default {
             viewType: ''
         },
         aggregateTableConfig: { targetColumn: {}, statistics: [], groupBy: [] },
-        dataViewConfig: { viewColumns: [], sortColumn: {}, sortType: 'asc' },
+        dataViewConfig: { viewColumns: [], sortColumn: {key: ''}, sortType: 'asc', count: 25 },
         barConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''} },
         lineConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} }, groupBy: {key:''} },
         pieConfig: { xAxis: { column: {}, granularity: {} }, yAxis: { column: {}, gauge: {} } },
@@ -83,7 +82,6 @@ export default {
         description: '',
         filters: [],
         chartOption: {},
-        autoRefresh: true,
         dirty: false
     },
     reducers: {
@@ -151,9 +149,8 @@ export default {
             const { fields } = action;
             yield put({ type: 'silentSetFields', fields });
 
-            const chartDesigner = yield select(state => state.present.chartDesigner);
-            const { autoRefresh } = chartDesigner;
-            if(autoRefresh) {
+            const { autoRefresh } = action;
+            if(autoRefresh === undefined ? true : autoRefresh) {
                 yield put({ type: 'fetchChartData' });
             }
         },
@@ -165,10 +162,8 @@ export default {
             const { name, value } = action;
             yield put({ type: 'setField', name, value });
 
-            const chartDesigner = yield select(state => state.present.chartDesigner);
-            const { autoRefresh } = chartDesigner;
-            
-            if(autoRefresh) {
+            const { autoRefresh } = action;
+            if(autoRefresh === undefined ? true : autoRefresh) {
                 yield put({ type: 'fetchChartData' });
             }
         },
@@ -179,9 +174,8 @@ export default {
             const { fields } = action;
             yield put({ type: 'setFields', fields });
 
-            const chartDesigner = yield select(state => state.present.chartDesigner);
-            const { autoRefresh } = chartDesigner;
-            if(autoRefresh) {
+            const { autoRefresh } = action;
+            if(autoRefresh === undefined ? true : autoRefresh) {
                 yield put({ type: 'fetchChartData' });
             }
         },