Browse Source

图表、报表备注说明字段长度限制

zhuth 6 years ago
parent
commit
1906d5d3a3

+ 8 - 12
src/components/chartDesigner/content.jsx

@@ -59,31 +59,27 @@ class ChartDesignerContent extends React.Component {
         const { isOwner, animation, autoRefresh } = this.state;
         const { baseConfig } = chartDesigner;
         const { viewType } = baseConfig;
-        const formItemLayout = {
-            labelCol: { span: 8 },
-			wrapperCol: { span: 16 },
-        };
 
         let configForm, chartView;
 
         if(viewType === 'aggregateTable') {
-            configForm = (<AggregateTableConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<AggregateTableConfigForm autoRefresh={autoRefresh}/>);
             chartView = (<TableView />);
         }else if(viewType === 'dataView') {
-            configForm = (<DataViewConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<DataViewConfigForm autoRefresh={autoRefresh}/>);
             chartView = (<TableView inPage={true}/>);
         }else if(viewType === 'line') {
-            configForm = (<LineConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<LineConfigForm autoRefresh={autoRefresh}/>);
             // optionConfig 可以用来放替换属性(已做深拷贝替换)
             chartView = (<EchartsView optionConfig={{ animation }}/>);
         }else if(viewType === 'bar') {
-            configForm = (<BarConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<BarConfigForm autoRefresh={autoRefresh}/>);
             chartView = (<EchartsView optionConfig={{ animation, barMaxWidth: '50%' }}/>);
         }else if(viewType === 'pie') {
-            configForm = (<PieConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<PieConfigForm autoRefresh={autoRefresh}/>);
             chartView = (<EchartsView optionConfig={{ animation }}/>);
         }else if(viewType === 'scatter') {
-            configForm = (<ScatterConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
+            configForm = (<ScatterConfigForm autoRefresh={autoRefresh}/>);
             chartView = (<EchartsView optionConfig={{ animation }}/>);
         }else {
             chartView = <EmptyContent />
@@ -95,14 +91,14 @@ class ChartDesignerContent extends React.Component {
                     <Button className='collapse-toggle' style={{ display: isOwner? 'block' : 'none' }} shape='circle' size='small' icon={`${this.state.collapsed?'right':'left'}`} onClick={this.onCollapse} />
                     <Tabs className='sider-tabs'>
                         <TabPane className='chartconfig' tab='图表设置' key='1'>
-                            <BaseConfigForm formItemLayout={formItemLayout}/>
+                            <BaseConfigForm/>
                             { configForm }
                         </TabPane>
                         <TabPane className='styleconfig' tab='样式设置' key='2'>
                             <StyleConfigForm viewType={viewType}/>
                         </TabPane>
                         <TabPane className='otherconfig' tab='其他设置' key='3'>
-                            <OtherConfigForm formItemLayout={formItemLayout}/>
+                            <OtherConfigForm/>
                         </TabPane>
                     </Tabs>
                     {!this.state.collapsed && <Footer className='sider-footer'>

+ 7 - 3
src/components/chartDesigner/sections/aggregateTableConfigForm.jsx

@@ -14,7 +14,11 @@ class AggregateTableConfigForm extends React.Component {
 	constructor(props) {
 		super(props);
 		this.state = {
-			searchKey: ''
+			formItemLayout: {
+                labelCol: { span: 8 },
+                wrapperCol: { span: 16 },
+            },
+			searchKey: '',
 		};
 		
 	}
@@ -26,8 +30,8 @@ class AggregateTableConfigForm extends React.Component {
 	}
 	render() {
 		const props = this.props;
-		const { autoRefresh, formItemLayout, chartDesigner, dispatch } = props;
-		const{ searchKey } = this.state;
+		const { autoRefresh, chartDesigner, dispatch } = props;
+		const{ searchKey, formItemLayout } = this.state;
 		const { columns, aggregateTableConfig } = chartDesigner;
 		
 		let options = columns.filter(c => c.label.toLowerCase().indexOf(searchKey.toLowerCase()) !== -1);

+ 5 - 2
src/components/chartDesigner/sections/barConfigForm.jsx

@@ -5,8 +5,11 @@ import GAUGE from './gauge.json'
 import GRANULARITY from './granularity.json'
 const FormItem = Form.Item
 const { Option } = Select
-
-const BarConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
+const formItemLayout = {
+	labelCol: { span: 8 },
+	wrapperCol: { span: 16 },
+};
+const BarConfigForm = ({ autoRefresh, chartDesigner, dispatch }) => {
 	const columns = chartDesigner.columns;
 
 	return (

+ 8 - 1
src/components/chartDesigner/sections/baseConfigForm.jsx

@@ -7,12 +7,19 @@ const FormItem = Form.Item
 const { Option } = Select
 
 class baseConfigForm extends React.Component {
+	state =  {
+		formItemLayout: {
+			labelCol: { span: 8 },
+			wrapperCol: { span: 16 },
+		},
+	}
 	componentDidMount() {
 		this.props.dispatch({ type: 'dataSource/fetchList' });
 	}
 	render() {
 		const props = this.props;
-		const { formItemLayout, dataSource, chartDesigner } = props
+		const { formItemLayout } = this.state;
+		const { dataSource, chartDesigner } = props
 		const { baseConfig } = chartDesigner;
 
 		return (

+ 6 - 2
src/components/chartDesigner/sections/dataViewConfigForm.jsx

@@ -12,14 +12,18 @@ class DataViewConfigForm extends React.Component {
 	constructor(props) {
 		super(props);
 		this.state = {
+			formItemLayout: {
+                labelCol: { span: 8 },
+                wrapperCol: { span: 16 },
+            },
 			showBox: false,
 			visibleDisplayColumnBox: false
 		}
 	}
 	
 	render() {
-		const { autoRefresh, dispatch, chartDesigner, formItemLayout } = this.props;
-		const { visibleDisplayColumnBox } = this.state;
+		const { autoRefresh, dispatch, chartDesigner } = this.props;
+		const { formItemLayout, visibleDisplayColumnBox } = this.state;
 		return (
             <Form layout='horizontal'>
 				<FormItem label="展示列" {...formItemLayout}>

+ 5 - 2
src/components/chartDesigner/sections/lineConfigForm.jsx

@@ -5,8 +5,11 @@ import '../../../models/chartDesigner'
 import GAUGE from './gauge.json'
 const FormItem = Form.Item
 const { Option } = Select
-
-const LineConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
+const formItemLayout = {
+	labelCol: { span: 8 },
+	wrapperCol: { span: 16 },
+};
+const LineConfigForm = ({ autoRefresh, chartDesigner, dispatch }) => {
 	
 	const columns = chartDesigner.columns;
 

+ 118 - 55
src/components/chartDesigner/sections/otherConfigForm.jsx

@@ -1,68 +1,131 @@
 import React from 'react'
 import { Form, Input, Cascader } from 'antd'
 import { connect } from 'dva'
+import { arrayToTree } from '../../../utils/baseUtils'
 import './otherConfigForm.less'
 const FormItem = Form.Item
 const InputTextArea = Input.TextArea
 
-const OtherConfigForm = ({ chart, chartDesigner, dispatch, formItemLayout }) => {
-    let getGroup = () => {
-        const { group } = chartDesigner;
-        const { groupList } = chart;
-        let g1 = groupList.filter(g => g.code+'' === group+'')[0];
-        if(!g1) {
-            return ['-1']
-        }
-        if(g1.pcode === '-1') {
-            return [g1.code]
-        }else {
-            let g2 = groupList.filter(g => g.code+'' === g1.pcode+'')[0];
-            return [g2.code, g1.code]
+class OtherConfigForm extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            formItemLayout: {
+                labelCol: { span: 8 },
+                wrapperCol: { span: 16 },
+            },
+            description: props.chartDesigner.description,
+            validInfo: { description: { status: 'success', help: '' } }
+        };
+    }
+
+    generateGroupOptions = (treeData) => {
+        return treeData.map(t => {
+            t.children = t.children instanceof Array ? t.children : [];
+            return {
+                key: t.code,
+                value: t.code,
+                label: t.label,
+                children: this.generateGroupOptions(t.children)
+            }
+        })
+    }
+
+    getParents = (group) => {
+        const groupData = this.props.chart.groupList;
+        let pgroups = [group];
+        let fgroup = groupData.find(g => g.code === group.pcode);
+        if(fgroup) {
+            pgroups = this.getParents(fgroup).concat(pgroups);
         }
+        return pgroups;
     }
-    return (
-        <Form className='form-otherconfig'>
-            <FormItem label='所属分组' {...formItemLayout}>
-                <Cascader
-                    value={getGroup()}
-                    allowClear={true}
-                    changeOnSelect={true}
-                    expandTrigger='hover'
-					placeholder='未分组'
-					options={[{pcode: '-1', code: '-1', label: '未分组'}].concat(chart.groupList).filter(g => g.pcode === '-1').map((p, i)=>{
-						return {
-                            key: p.code,
-							value: p.code,
-							label: p.label,
-							children: chart.groupList.filter(g => g.pcode === p.code && p.code !== '-1').map(c => {
-                                return {
-                                    key: c.code,
-                                    value: c.code,
-                                    label: c.label
+
+    render() {
+        const { chart, chartDesigner, dispatch } = this.props;
+        const { description, formItemLayout, validInfo } = this.state;
+        const treeData = arrayToTree(chart.groupList, '-1', 'code', 'pcode', 'children');
+        let getGroup = () => {
+            const { group: key } = chartDesigner;
+            if(key === '-1') {
+                return ['-1'];
+            }else {
+                let group = chart.groupList.find(g => g.code === key);
+                if(group) {
+                    let groups = this.getParents(group);
+                    let val = groups.map(g => g.code);
+                    return val;
+                }else {
+                    return null;
+                }
+            }
+        }
+        return (
+            <Form className='form-otherconfig'>
+                <FormItem label='所属分组' {...formItemLayout}>
+                    <Cascader
+                        value={getGroup()}
+                        allowClear={true}
+                        changeOnSelect={true}
+                        expandTrigger='hover'
+                        placeholder='未分组'
+                        options={this.generateGroupOptions([{pcode: '-1', code: '-1', label: '未分组'}].concat(treeData))}
+                        onChange={(value, items) => {
+                            let v = value[value.length - 1];
+                            dispatch({ type: 'chartDesigner/setField', name: 'group', value: v });
+                        }}
+                        
+                    >
+                    </Cascader>
+                </FormItem>
+                <FormItem label='备注' {...formItemLayout} validateStatus={validInfo.description.status} help={validInfo.description.help}>
+                    <InputTextArea
+                        className='inputarea-description'
+                        value={description}
+                        autosize={{ minRows: 2, maxRows: 6 }}
+                        onChange={e => {
+                            let val = e.target.value;
+                            let status = 'success', help = '';
+                            if(val.length > 150) {
+                                status = 'error';
+                                help = '备注不能超过150个字符'
+                            }
+                            this.setState({
+                                description: val,
+                                validInfo: {
+                                    description: { status, help, }
                                 }
-                            })
-						}
-					})}
-					onChange={(value, items) => {
-                        let v = value[1] !== undefined ? value[1] : value[0];
-                        dispatch({ type: 'chartDesigner/setField', name: 'group', value: v });
-					}}
-					
-				>
-				</Cascader>
-            </FormItem>
-            <FormItem label='备注' {...formItemLayout}>
-                <InputTextArea
-                    className='inputarea-description'
-                    value={chartDesigner.description}
-                    autosize={{ minRows: 2, maxRows: 6 }}
-                    onChange={(e) => {
-                        dispatch({ type: 'chartDesigner/setField', name: 'description', value: e.target.value });
-                    }}
-                />
-            </FormItem>
-        </Form>
-    );
+                            });
+                            window.clearTimeout(this.descriptionKey);
+                            this.descriptionKey = window.setTimeout(() => {
+                                if(val.trim().length <= 150) {
+                                    dispatch({ type: 'chartDesigner/setField', name: 'description', value: val });
+                                }
+                            }, 200);
+                        }}
+                        onBlur={(e) => {
+                            if(validInfo.description.status === 'success') {
+                                dispatch({ type: 'chartDesigner/setField', name: 'description', value: e.target.value });
+                            }else {
+                                this.setState({
+                                    description: chartDesigner.description
+                                }, () => {
+                                    window.setTimeout(() => {
+                                        this.setState({
+                                            validInfo: {
+                                                description: { status: 'success', help: '', }
+                                            }
+                                        });
+                                    }, 500);
+                                })
+                            }
+                        }}
+                    />
+                </FormItem>
+            </Form>
+        );
+    }
 }
 
 function mapStateToProps({ present: {chart, chartDesigner}}) {

+ 5 - 2
src/components/chartDesigner/sections/pieConfigForm.jsx

@@ -5,8 +5,11 @@ import '../../../models/chartDesigner'
 import GAUGE from './gauge.json'
 import GRANULARITY from './granularity.json'
 const FormItem = Form.Item
-
-const PieConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
+const formItemLayout = {
+	labelCol: { span: 8 },
+	wrapperCol: { span: 16 },
+}
+const PieConfigForm = ({ autoRefresh, chartDesigner, dispatch }) => {
 	
 	const columns = chartDesigner.columns;
 

+ 5 - 1
src/components/chartDesigner/sections/scatterConfigForm.jsx

@@ -4,8 +4,12 @@ import { connect } from 'dva'
 import GAUGE from './gauge.json'
 const FormItem = Form.Item
 const { Option } = Select
+const formItemLayout = {
+	labelCol: { span: 8 },
+	wrapperCol: { span: 16 },
+};
 
-const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }) => {
+const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch }) => {
 	
 	const columns = chartDesigner.columns;
 

+ 42 - 6
src/components/dashboardDesigner/configSider.jsx

@@ -12,10 +12,12 @@ class ConfigSider extends React.Component {
     constructor(props) {
         super(props);
         this.state = {
+            description: props.dashboardDesigner.description,
             visibleChooseChartBox: false,
             visibleCusFilterBox: false,
             copyDisabled: false,
-            copyText: '复制'
+            copyText: '复制',
+            validInfo: { description: { status: 'success', help: '' } }
         };
     }
 
@@ -110,7 +112,7 @@ class ConfigSider extends React.Component {
 
     render() {
         const { dashboard, dashboardDesigner, dispatch } = this.props;
-        const { visibleCusFilterBox, copyDisabled, copyText } = this.state;
+        const { description, visibleCusFilterBox, copyDisabled, copyText, validInfo } = this.state;
         const { menuTree } = dashboard;
 
         return <Form className='form-config' layout={'vertical'}>
@@ -138,12 +140,46 @@ class ConfigSider extends React.Component {
                 >
                 </Cascader>
             </FormItem>
-            <FormItem label='备注'>
+            <FormItem label='备注' validateStatus={validInfo.description.status} help={validInfo.description.help}>
                 <Input.TextArea
                     autosize={{ minRows: 2, maxRows: 6 }}
-                    value={dashboardDesigner.description}
-                    onChange={(e) => {
-                        dispatch({ type: 'dashboardDesigner/setField', name: 'description', value: e.target.value });
+                    value={description}
+                    onChange={e => {
+                        let val = e.target.value;
+                        let status = 'success', help = '';
+                        if(val.length > 150) {
+                            status = 'error';
+                            help = '备注不能超过150个字符'
+                        }
+                        this.setState({
+                            description: val,
+                            validInfo: {
+                                description: { status, help, }
+                            }
+                        });
+                        window.clearTimeout(this.descriptionKey);
+                        this.descriptionKey = window.setTimeout(() => {
+                            if(val.trim().length <= 150) {
+                                dispatch({ type: 'dashboardDesigner/setField', name: 'description', value: val });
+                            }
+                        }, 200);
+                    }}
+                    onBlur={(e) => {
+                        if(validInfo.description.status === 'success') {
+                            dispatch({ type: 'dashboardDesigner/setField', name: 'description', value: e.target.value });
+                        }else {
+                            this.setState({
+                                description: dashboardDesigner.description
+                            }, () => {
+                                window.setTimeout(() => {
+                                    this.setState({
+                                        validInfo: {
+                                            description: { status: 'success', help: '', }
+                                        }
+                                    });
+                                }, 500);
+                            })
+                        }
                     }}
                 />
             </FormItem>

+ 3 - 3
src/components/dataSourceDetail/baseConfig.jsx

@@ -47,12 +47,12 @@ class DataSourceBaseConfig extends React.Component {
         })
     }
 
-    getParens = (group) => {
+    getParents = (group) => {
         const groupData = this.props.dataSource.groupList;
         let pgroups = [group];
         let fgroup = groupData.find(g => g.code === group.pcode);
         if(fgroup) {
-            pgroups = this.getParens(fgroup).concat(pgroups);
+            pgroups = this.getParents(fgroup).concat(pgroups);
         }
         return pgroups;
     }
@@ -73,7 +73,7 @@ class DataSourceBaseConfig extends React.Component {
             }else {
                 let group = dataSource.groupList.find(g => g.code === key);
                 if(group) {
-                    let groups = this.getParens(group);
+                    let groups = this.getParents(group);
                     let val = groups.map(g => g.code);
                     return val;
                 }else {