Browse Source

大量细节优化

zhuth 6 years ago
parent
commit
575eb91915
35 changed files with 416 additions and 265 deletions
  1. 3 3
      src/components/admin/userGroupDetailBox.jsx
  2. 8 5
      src/components/admin/userGroupManagement.jsx
  3. 5 8
      src/components/admin/userGroupManagement.less
  4. 12 1
      src/components/admin/userManagement.jsx
  5. 1 9
      src/components/admin/userManagement.less
  6. 40 35
      src/components/chart/chooseDataSourceBox.jsx
  7. 4 1
      src/components/chart/chooseDataSourceBox.less
  8. 25 24
      src/components/chart/list.jsx
  9. 25 11
      src/components/chartDesigner/header.jsx
  10. 4 0
      src/components/chartDesigner/sections/aggregateTableConfigForm.jsx
  11. 7 1
      src/components/common/filterBox/filterBox.jsx
  12. 7 1
      src/components/common/filterBox/filterBox2.jsx
  13. 2 2
      src/components/common/groupManageMentBox/box.jsx
  14. 1 1
      src/components/common/groupSelector/popover.jsx
  15. 6 0
      src/components/common/listFilter/index.jsx
  16. 2 2
      src/components/dashboard/copyBox.jsx
  17. 3 3
      src/components/dashboardDesigner/chartView.jsx
  18. 8 2
      src/components/dashboardDesigner/chooseChartBox.jsx
  19. 5 0
      src/components/dashboardDesigner/configSider.jsx
  20. 1 1
      src/components/dashboardDesigner/content.jsx
  21. 1 1
      src/components/dashboardDesigner/cusFilterBox.less
  22. 17 3
      src/components/dashboardDesigner/header.jsx
  23. 1 1
      src/components/dashboardDesigner/richTextEditor.jsx
  24. 16 11
      src/components/dashboardDesigner/viewLayout.jsx
  25. 28 24
      src/components/dataSource/list.jsx
  26. 51 0
      src/components/dataSourceDetail/columnConfig.md
  27. 3 3
      src/components/dataSourceDetail/columnType.json
  28. 2 7
      src/components/dataSourceDetail/dataConnectBox.jsx
  29. 1 0
      src/components/homePage/index.less
  30. 1 0
      src/components/setting/index.less
  31. 101 100
      src/constants/url.js
  32. 1 4
      src/models/dashboardDesigner.js
  33. 1 1
      src/models/defaultColumnType.json
  34. 16 0
      src/themes/default/base.less
  35. 7 0
      src/themes/default/chartdesigner.less

+ 3 - 3
src/components/admin/userGroupDetailBox.jsx

@@ -62,9 +62,9 @@ class DetailBox extends React.Component {
                                 rules: [
                                     { validator(rule, value, callback, source, options) {
                                         let msg;
-                                        if(value.trim().length === 0) {
+                                        if((value+'').trim().length === 0) {
                                             msg = '用户组名不能为空'
-                                        }else if(value.length > 20) {
+                                        }else if((value+'').length > 20) {
                                             msg = '用户组名长度不能大于20个字符'
                                         }
                                         me.setState({
@@ -97,7 +97,7 @@ class DetailBox extends React.Component {
                                 rules: [
                                     { validator(rule, value, callback, source, options) {
                                         let msg;
-                                        if(value.length > 500) {
+                                        if((value+'').length > 500) {
                                             msg = '用户组描述不能大于500个字符'
                                         }
                                         me.setState({

+ 8 - 5
src/components/admin/userGroupManagement.jsx

@@ -34,11 +34,14 @@ class UserGroupManagement extends React.Component {
     }
 
     tableSize = () => {
-        const tableEl = document.getElementsByClassName('member-table')[0];
-        const tableScrollEl = tableEl.getElementsByClassName('ant-table-scroll')[0];
+        const layoutGroup = document.getElementsByClassName('layout-group')[0];
+        const content = layoutGroup.getElementsByClassName('ant-layout-content')[0];
+        const groupname = content.getElementsByClassName('groupname')[0];
+        // 容器高度 - 搜索栏 - 表头高度 - 分页器高度 - padding
+        let tableBodyHeight = content.offsetHeight - groupname.offsetHeight - 42 - 26 - 10;
         this.setState({
-            tableBodyHeight: tableScrollEl.offsetHeight - 38,
-            pageSize: Math.ceil((tableScrollEl.offsetHeight - 38) / 38)
+            tableBodyHeight,
+            pageSize: Math.ceil((tableBodyHeight) / 38)
         });
     }
 
@@ -107,7 +110,7 @@ class UserGroupManagement extends React.Component {
         }]
         const selectedKeys = selectedGroup ? [selectedGroup.code] : [];
         return (
-            <Layout className='group-layout'>
+            <Layout className='layout-group'>
                 <Sider>
                     <div className='search-area'>
                         <Search

+ 5 - 8
src/components/admin/userGroupManagement.less

@@ -1,4 +1,4 @@
-.group-layout {
+.layout-group {
     height: 100%;
     background: #FAFAFA;
     border: none;
@@ -70,22 +70,19 @@
             }
         }
         .member-table {
-            height: 100%;
             .ant-spin-nested-loading {
-                height: 100%;
                 .ant-spin-container {
-                    height: 100%;
                     .ant-table {
-                        height: 100%;
                         .ant-table-content {
-                            height: 100%;
                             .ant-table-scroll {
-                                height: 100%;
+                                .ant-table-header {
+                                    margin-bottom: -20px !important;
+                                }
                                 .ant-table-body {
                                     overflow-x: hidden !important;
                                 }
                                 .ant-table-placeholder {
-                                    height: calc(~'100% - 38px');
+                                    height: calc(~'100% - 51px');
                                 }
                             }
                         }

+ 12 - 1
src/components/admin/userManagement.jsx

@@ -26,6 +26,17 @@ class UserManagement extends React.Component {
     }
 
     tableSize = () => {
+
+        const layoutGroup = document.getElementsByClassName('layout-usermanagement')[0];
+        const content = layoutGroup.getElementsByClassName('ant-layout-content')[0];
+        const header = content.getElementsByClassName('ant-card-head')[0];
+        // 容器高度 - 搜索栏 - 表头高度 - 分页器高度 - padding
+        let tableBodyHeight = content.offsetHeight - header.offsetHeight - 42 - 26 - 10;
+        this.setState({
+            tableBodyHeight,
+            pageSize: Math.ceil((tableBodyHeight) / 38)
+        });
+
         const tableEl = document.getElementsByClassName('usermanagement-table')[0];
         const tableScrollEl = tableEl.getElementsByClassName('ant-table-scroll')[0];
         this.setState({
@@ -94,7 +105,7 @@ class UserManagement extends React.Component {
         }];
 
         return (
-            <Layout className='usermanagement-view'>
+            <Layout className='layout-usermanagement'>
                 <Content>
                     <Card className='usermanagement-body' title={
                         <Row className='usermanagement-tools' type='flex' justify='space-between'>

+ 1 - 9
src/components/admin/userManagement.less

@@ -1,4 +1,4 @@
-.usermanagement-view {
+.layout-usermanagement {
     height: 100%;
     .ant-layout-content {
         height: 100%;
@@ -34,22 +34,14 @@
             }
             .ant-card-body {
                 padding: 0;
-                height: 100%;
                 .usermanagement-table {
-                    height: 100%;
                     .ant-spin-nested-loading {
-                        height: 100%;
                         .ant-spin-container {
-                            height: 100%;
                             padding-bottom: 50px;
                             .ant-table {
-                                height: 100%;
                                 .ant-table-content {
-                                    height: 100%;
                                     .ant-table-scroll {
-                                        height: 100%;
                                         .ant-table-body {
-                                            height: 100%;
                                             overflow-x: hidden !important;
                                         }
                                     }

+ 40 - 35
src/components/chart/chooseDataSourceBox.jsx

@@ -186,47 +186,52 @@ class ChooseDataSourceBox extends React.Component {
         return (
             <Modal
                 className='choosedatasource-box'
-                title={<Row><Col>选择数据源</Col><Col>
-                    <ListFilter
-                        modelName={null}
-                        model={{
-                            filterItems: dataSource.filterItems,
-                            filterItem, // 已选过滤字段
-                            filterLabel: stateFilterLabel,
-                        }}
-                        onChangeFilterItem={(filterItem) => {
-                            this.setState({
-                                filterItem
-                            });
-                        }}
-                        onChangeFilterValue={(filterLabel) => {
-                            this.setState({
-                                filterLabel
-                            });
-                        }}
-                    />
-                </Col></Row>}
+                title='选择数据源'
                 visible={visibleChooseDataSourceBox}
                 onOk={this.okHandler}
                 onCancel={hideBox}
                 maskClosable={false}
                 destroyOnClose={true}
             >
-                <Table
-                    className='choosedatasource-table'
-                    columns={columns}
-                    dataSource={this.onSearch(dataSource.list)}
-                    size='small'
-                    scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
-                    pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
-                    onRow={(record) => {
-                        return {
-                            onClick: () => {
-                                this.changeSelected(record);
-                            }
-                        };
-                    }}
-                />
+                <div>
+                    <Row type='flex' justify='end'>
+                        <Col style={{ padding: '8px' }}>
+                            <ListFilter
+                                modelName={null}
+                                model={{
+                                    filterItems: dataSource.filterItems,
+                                    filterItem, // 已选过滤字段
+                                    filterLabel: stateFilterLabel,
+                                }}
+                                onChangeFilterItem={(filterItem) => {
+                                    this.setState({
+                                        filterItem
+                                    });
+                                }}
+                                onChangeFilterValue={(filterLabel) => {
+                                    this.setState({
+                                        filterLabel
+                                    });
+                                }}
+                            />
+                        </Col>
+                    </Row>
+                    <Table
+                        className='choosedatasource-table'
+                        columns={columns}
+                        dataSource={this.onSearch(dataSource.list)}
+                        size='small'
+                        scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
+                        pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
+                        onRow={(record) => {
+                            return {
+                                onClick: () => {
+                                    this.changeSelected(record);
+                                }
+                            };
+                        }}
+                    />
+                </div>
             </Modal>
         )
     }

+ 4 - 1
src/components/chart/chooseDataSourceBox.less

@@ -7,13 +7,16 @@
     }
     .ant-modal-body {
         padding: 0;
-        max-height: 50vh;
+        max-height: 60vh;
         overflow-y: auto;
         .choosedatasource-table {
             .ant-table-header {
                 overflow-y: hidden;
                 margin-right: 6px;
             }
+            .ant-table-body {
+                margin-top: 0;
+            }
         }
     }
 }

+ 25 - 24
src/components/chart/list.jsx

@@ -105,26 +105,30 @@ class ChartList extends React.Component {
         return <Breadcrumb className={`group${noGroup ? ' nogroup' : ''}`} separator=">">
             { pGroups.map(g => (
                 <Breadcrumb.Item key={g.code}>
-                    <GroupSelector
-                        visible={this.state['visibleGroupSelector' + g.code]}
-                        handleVisibleChange={(visible) => {
-                            let obj = {};
-                            obj['visibleGroupSelector' + g.code] = visible
-                            this.setState(obj);
-                        }}
-                        pGroup={g}
-                        groupList={chart.groupList}
-                        selectGroup={(group) => {
-                            let obj = {};
-                            obj['visibleGroupSelector' + g.code] = false;
-                            this.setState(obj);
-                            dispatch({ type: 'chart/setCurrentGroup', group });
-                        }}
-                    >
-                        <Tag color={'blue'} >
-                            {g.label}
-                        </Tag>
-                    </GroupSelector>
+                    <Tag color={'blue'} >
+                        <span onClick={() => {
+                            let group = chart.groupList.find(group => group.code === g.code);
+                            dispatch({ type: 'chart/setCurrentGroup', group: group });
+                        }}>{g.label}</span>
+                        <GroupSelector
+                            visible={this.state['visibleGroupSelector' + g.code]}
+                            handleVisibleChange={(visible) => {
+                                let obj = {};
+                                obj['visibleGroupSelector' + g.code] = visible
+                                this.setState(obj);
+                            }}
+                            pGroup={g}
+                            groupList={chart.groupList}
+                            selectGroup={(group) => {
+                                let obj = {};
+                                obj['visibleGroupSelector' + g.code] = false;
+                                this.setState(obj);
+                                dispatch({ type: 'chart/setCurrentGroup', group });
+                            }}
+                        >
+                            <Icon style={{ marginLeft: '8px', fontSize: '12px' }} type="down" />
+                        </GroupSelector>
+                    </Tag>
                 </Breadcrumb.Item>
             )) }
         </Breadcrumb>
@@ -216,7 +220,7 @@ class ChartList extends React.Component {
                 <Card
                     title={
                         <Row type='flex' justify='space-between'>
-                            <Col className='label' span={21} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} >
+                            <Col className='label' style={{ overflow: 'hidden', textOverflow: 'ellipsis', padding: '0 16px' }} >
                                 { (filterItem.name === 'name' && filterLabel) ?
                                     ((l.name || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                         return (
@@ -228,9 +232,6 @@ class ChartList extends React.Component {
                                     )) : l.name
                                 }
                             </Col>
-                            <Col style={{ textAlign: 'right' }} span={3} >
-                                {/* <Icon type='star-o'/> */}
-                            </Col>
                         </Row>
                     }
                     cover={

+ 25 - 11
src/components/chartDesigner/header.jsx

@@ -78,21 +78,43 @@ class Header extends React.Component {
                 </div>
                 <div className='header-item toolbar-title'>
                     <Input
+                        key={chartDesigner.header.label}
                         className='input-title'
                         readOnly={!this.isOwner()}
+                        defaultValue={chartDesigner.header.label}
                         addonAfter={this.isOwner() ? <Icon type="edit" 
                             onClick={(e) => {
                                 const input = e.currentTarget.parentElement.parentElement.getElementsByTagName('input')[0];
                                 input && input.focus()
                             }}
                         /> : ''}
-                        onChange={(e) => {
-                            dispatch({ type: 'chartDesigner/setField', name: 'header', value: { label: e.target.value } });
+                        onBlur={(e) => {
+                            let value = e.target.value;
+                            if(!!value.trim()) {
+                                dispatch({ type: 'chartDesigner/setField', name: 'header', value: { label: e.target.value } });
+                            }else {
+                                e.target.value = chartDesigner.header.label;
+                            }
+                        }}
+                        onPressEnter={(e) => {
+                            let value = e.target.value;
+                            if(!!value.trim()) {
+                                dispatch({ type: 'chartDesigner/setField', name: 'header', value: { label: e.target.value } });
+                            }else {
+                                e.target.value = chartDesigner.header.label;
+                            }
                         }}
-                        value={chartDesigner.header.label}
                     />
                 </div>
                 <div className='header-item toolbar-buttons'>
+                    {this.isOwner() && <Button onClick={() => {
+                        if(chartDesigner.code && chartDesigner.code !== -1) {
+                            dispatch({ type: 'chart/remoteModify' });
+                        }else {
+                            dispatch({ type: 'chart/remoteAdd' });
+                        }
+                        dispatch({ type: 'chartDesigner/setDirty', dirty: false });
+                    }}><Icon type='save' />保存</Button>}
                     {this.isOwner() && <Tooltip title='复制新增'>
                         <Button className='tools-btn' icon='copy' onClick={() => {
                             this.setState({
@@ -134,14 +156,6 @@ class Header extends React.Component {
                             dispatch({ type: 'chart/remoteDelete', code: chartDesigner.code });
                             dispatch({ type: 'main/goBack', path: '/workshop/chart' });
                     }} />}
-                    {this.isOwner() && <Button onClick={() => {
-                        if(chartDesigner.code && chartDesigner.code !== -1) {
-                            dispatch({ type: 'chart/remoteModify' });
-                        }else {
-                            dispatch({ type: 'chart/remoteAdd' });
-                        }
-                        dispatch({ type: 'chartDesigner/setDirty', dirty: false });
-                    }}><Icon type='save' />保存</Button>}
                 </div>
             </div>
         );

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

@@ -1,3 +1,6 @@
+/**
+ * 总体统计数据表
+ */
 import React from 'react';
 import { Form, Select, Checkbox, Row, Col } from 'antd';
 import { connect } from 'dva';
@@ -48,6 +51,7 @@ class AggregateTableConfigForm extends React.Component {
 				</FormItem>
 				<FormItem label='显示总体数据' {...formItemLayout}>
 					<CheckboxGroup
+						className='checkbox-group-statistics'
 						value={aggregateTableConfig.statistics}
 						onChange={(value) => {
 							dispatch({ type: 'chartDesigner/changeField', name: 'aggregateTableConfig', value: { ...props.chartDesigner.aggregateTableConfig, statistics: value }, autoRefresh });

+ 7 - 1
src/components/common/filterBox/filterBox.jsx

@@ -509,8 +509,14 @@ class FilterBox extends React.Component {
         return (
             <Modal
                 className='filter-box'
-                title={<div>筛选条件<div className='clear' onClick={()=>{this.removeAllFilters()}}>清空条件<Icon type='delete'/></div></div>}
+                title='筛选条件'
                 visible={visibleFilterBox}
+                footer={<div>
+                    <Button type='danger' onClick={this.removeAllFilters}>清空条件</Button>
+                    <Button onClick={hideFilterBox}>取消</Button>
+                    <Button type='primary' onClick={this.getFilters}>确定</Button>
+                    </div>
+                }
                 onOk={this.getFilters}
                 onCancel={hideFilterBox}
                 maskClosable={false}

+ 7 - 1
src/components/common/filterBox/filterBox2.jsx

@@ -556,8 +556,14 @@ class FilterBox extends React.Component {
         return (
             <Modal
                 className='filter-box'
-                title={<div>筛选条件<div className='clear' onClick={()=>{this.removeAllFilters()}}>清空条件<Icon type='delete'/></div></div>}
+                title='筛选条件'
                 visible={visibleFilterBox}
+                footer={<div>
+                    <Button type='danger' onClick={this.removeAllFilters}>清空条件</Button>
+                    <Button onClick={hideFilterBox}>取消</Button>
+                    <Button type='primary' onClick={this.getFilters}>确定</Button>
+                    </div>
+                }
                 onOk={this.getFilters}
                 onCancel={hideFilterBox}
                 maskClosable={false}

+ 2 - 2
src/components/common/groupManageMentBox/box.jsx

@@ -98,7 +98,7 @@ class GroupBox extends React.Component {
                                 this['inputRef-' + t.code].focus();
                             });
                         }}/>}
-                        {!t.children && <Icon type='delete' onClick={() => {
+                        {(!t.children || t.children.length === 0) && <Icon type='delete' onClick={() => {
                             if(t.code.startsWith('new-')) {
                                 this.deleteGroup(t);
                             }else {
@@ -312,7 +312,7 @@ class GroupBox extends React.Component {
             </Row>
             {visibleDeleteGroupBox && <DeleteBox
                 visibleBox={visibleDeleteGroupBox}
-                text={<div><span>确定要删除图表【{willDeleteGroup.label}】吗?</span><br/><span style={{ color: 'red' }}>*该组所有数据源将移动到未分组</span></div>}
+                text={<div><span>确定要删除分组【{willDeleteGroup.label}】吗?</span><br/><span style={{ color: 'red' }}>*该组所有数据源将移动到未分组</span></div>}
                 hideBox={() => {
                     this.setState({
                         visibleDeleteGroupBox: false

+ 1 - 1
src/components/common/groupSelector/popover.jsx

@@ -66,7 +66,7 @@ class PopTree extends React.Component {
                             });
                         }}
                         onSelect={(selectedKeys) => {
-                            let group = groupList.filter(g => g.code === selectedKeys[0])[0];
+                            let group = groupList.find(g => g.code === selectedKeys[0]);
                             selectGroup(group);
                         }}
                     >

+ 6 - 0
src/components/common/listFilter/index.jsx

@@ -15,6 +15,12 @@ class ListFilter extends React.Component {
         }
     }
 
+    componentDidMount() {
+        const { model } = this.props;
+        const { filterItem } = model;
+        filterItem.type === 'enum' && this.fetchData(filterItem);
+    }
+
     generateFilterItem = () => {
         const { modelName, model, dispatch, onChangeFilterItem, onChangeFilterValue } = this.props;
         const { filterItems, filterItem } = model;

+ 2 - 2
src/components/dashboard/copyBox.jsx

@@ -49,12 +49,12 @@ class CopyBox extends React.Component {
             <div>复制对象包括报表和报表包含的图表</div>
             <Form>
                 <FormItem
-                    label='切换数据'
+                    label='切换数据链接'
                     {...formItemLayout}
                 >
                     <Select
                         disabled={!currentDataConnectCode}
-                        placeholder={currentDataConnectCode ? '不切换...' : '无需选择数据'}
+                        placeholder={currentDataConnectCode ? '不切换...' : '无需选择数据链接'}
                         onChange={(value) => {
                             this.setState({
                                 currentDataConnectCode: value

+ 3 - 3
src/components/dashboardDesigner/chartView.jsx

@@ -26,7 +26,7 @@ class ChartView extends React.Component {
     }
 
     render() {
-        const { item, tableBodyHeight, editMode, dispatch } = this.props;
+        const { item, tableBodyHeight, editMode, dispatch, readOnly } = this.props;
         const { viewType, chartType, content, chartOption, fetching } = item;
         let children = <div className='chart-default mover'></div>;
         
@@ -85,8 +85,8 @@ class ChartView extends React.Component {
                 }
             }
         }else if(viewType === 'richText') { // 富文本类型
-            children = <RichTextEditor readOnly={!editMode} content={content} onContentChange={(content) => {
-                dispatch({ type: 'dashboardDesigner/modifyItem', item: { ...item, content } });
+            children = <RichTextEditor readOnly={readOnly || !editMode} content={content} onContentChange={(content) => {
+                !readOnly && dispatch({ type: 'dashboardDesigner/modifyItem', item: { ...item, content } });
             }}/>
         }else {
             children = <div className='mover'>错误类型</div>

+ 8 - 2
src/components/dashboardDesigner/chooseChartBox.jsx

@@ -1,6 +1,6 @@
 import React from 'react'
 import '../../models/dashboardDesigner'
-import { Modal, Checkbox, Row, Col, Table, message } from 'antd'
+import { Modal, Checkbox, Row, Col, Table } from 'antd'
 import { connect } from 'dva'
 import moment from 'moment'
 import 'braft-editor/dist/braft.css'
@@ -70,6 +70,12 @@ class ChooseChartBox extends React.Component {
             dispatch({ type: 'dashboardDesigner/addCharts', charts: selectedRecords });
         }
         hideBox();
+
+        setTimeout(() => {
+            // 滚动到最底部
+            let viewScrollContent = document.querySelector('.viewlayout');
+            viewScrollContent.scrollTo(0, viewScrollContent.scrollHeight - viewScrollContent.clientHeight);
+        }, 500);
     }
 
     onSearch = (list) => {
@@ -112,7 +118,7 @@ class ChooseChartBox extends React.Component {
 
     render() {
         const { visibleBox, hideBox, dashboardDesigner, chart } = this.props;
-        const { selectedRecords, selectedRecord, screenWidth, screenHeight, filterItem, filterLabel: stateFilterLabel } = this.state;
+        const { selectedRecords, screenWidth, screenHeight, filterItem, filterLabel: stateFilterLabel } = this.state;
         const tableBodyWidth = screenWidth * 0.8 - 10 - 10 - 18;
         const tableBodyHeight = screenHeight * 0.8 - 65 - 53 - 38 - 130;
         const tableRowHeight = 38;

+ 5 - 0
src/components/dashboardDesigner/configSider.jsx

@@ -59,6 +59,11 @@ class ConfigSider extends React.Component {
                 <div className="view-type-item">
                     <Icon className='viewtype-icon' type="book" theme="outlined" onClick={() => {
                         dispatch({ type: 'dashboardDesigner/addRichText' });
+                        setTimeout(() => {
+                            // 滚动到最底部
+                            let viewScrollContent = document.querySelector('.viewlayout');
+                            viewScrollContent.scrollTo(0, viewScrollContent.scrollHeight - viewScrollContent.clientHeight);
+                        }, 500);
                     }}/>
                 </div>
             </Tooltip>

+ 1 - 1
src/components/dashboardDesigner/content.jsx

@@ -187,7 +187,7 @@ class DashboardDesignerContent extends React.Component {
                                         />
                                     ))}
                                 </div>
-                                <div className='right'>
+                                <div className='right' style={{ display: filters.length > 0 ? 'block' : 'none' }}>
                                     <Icon title={closeFilters ? '展开' : '收起'} type={closeFilters ? 'caret-up' : 'caret-down'} onClick={() => {
                                         this.setState({
                                             closeFilters: !closeFilters

+ 1 - 1
src/components/dashboardDesigner/cusFilterBox.less

@@ -2,7 +2,7 @@
     top: 50px;
     .ant-modal-body {
         padding: 10px;
-        max-height: 80vh;
+        max-height: 60vh;
         overflow-y: auto;
         .config-form {
             .ant-divider {

+ 17 - 3
src/components/dashboardDesigner/header.jsx

@@ -76,8 +76,9 @@ class Header extends React.Component {
                 </div>
                 <div className='header-item toolbar-title'>
                     <Input
+                        key={dashboardDesigner.name}
                         className='input-title'
-                        value={dashboardDesigner.name}
+                        defaultValue={dashboardDesigner.name}
                         disabled={!this.isOwner()}
                         addonAfter={this.isOwner() ? <Icon type="edit" 
                             onClick={(e) => {
@@ -85,8 +86,21 @@ class Header extends React.Component {
                                 input && input.focus()
                             }}
                         /> : null}
-                        onChange={(e) => {
-                            dispatch({ type: 'dashboardDesigner/setField', name: 'name', value: e.target.value });
+                        onBlur={(e) => {
+                            let value = e.target.value;
+                            if(!!value.trim()) {
+                                dispatch({ type: 'dashboardDesigner/setField', name: 'name', value: e.target.value });
+                            }else {
+                                e.target.value = dashboardDesigner.name;
+                            }
+                        }}
+                        onPressEnter={(e) => {
+                            let value = e.target.value;
+                            if(!!value.trim()) {
+                                dispatch({ type: 'dashboardDesigner/setField', name: 'name', value: e.target.value });
+                            }else {
+                                e.target.value = dashboardDesigner.name;
+                            }
                         }}
                     />
                 </div>

+ 1 - 1
src/components/dashboardDesigner/richTextEditor.jsx

@@ -8,6 +8,7 @@ class RichTextEditor extends Component {
         this.state = ({
             _html: props.content
         });
+        this.editorElem = React.createRef();
     }
 
     render() {
@@ -65,7 +66,6 @@ class RichTextEditor extends Component {
         }
         editor.customConfig.uploadImgShowBase64 = true; // 上传图片(base64)
         editor.create()
-        // editor.blur();
         editor.txt.html(content);
 
         editor.$textElem.attr('contenteditable', !readOnly)

+ 16 - 11
src/components/dashboardDesigner/viewLayout.jsx

@@ -15,6 +15,7 @@ class ViewLayout extends React.PureComponent {
             screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
             screenHeight: document.documentElement.clientHeight || document.body.clientHeight,
             editingKey: null,
+            richTextReadOnly: false,
         };
     }
 
@@ -40,7 +41,7 @@ class ViewLayout extends React.PureComponent {
 
     createElement = (item, isPreview, reload) => {
         const { dispatch, main, dashboardDesigner } = this.props;
-        const { editingKey } = this.state;
+        const { editingKey, richTextReadOnly } = this.state;
         const { currentUser } = main;
         const { editMode } = dashboardDesigner;
         const { code, name, viewType, layout, chartCode } = item;
@@ -53,22 +54,26 @@ class ViewLayout extends React.PureComponent {
                         {editingKey && editingKey === code ? <Input width={200} ref={node => this['inputRef-' + code] = node} defaultValue={name} onBlur={(e) => {
                             let value = e.target.value
                             this.setState({
-                                editingKey: null
-                            }, () => {
-                                !!value.trim() && this.modifyItem({ ...item, name: value });
-                            });
-                        }} onPressEnter={(e) => {
-                            let value = e.target.value
-                            this.setState({
-                                editingKey: null
+                                editingKey: null,
+                                richTextReadOnly: false,
                             }, () => {
                                 !!value.trim() && this.modifyItem({ ...item, name: value });
                             });
+                        // TODO 这里使用onPressEnter在存在富文本类型时会出问题
+                        // }} onPressEnter={(e) => {
+                        //     let value = e.target.value
+                        //     this.setState({
+                        //         editingKey: null,
+                        //         // richTextReadOnly: false,
+                        //     }, () => {
+                        //         !!value.trim() && this.modifyItem({ ...item, name: value });
+                        //     });
                         }}/> : <span>{name}</span>}
                         <div className='tools'>
                             {editMode && (!editingKey || editingKey !== code) && <Icon type='edit' title='修改' style={{ cursor: 'pointer', marginLeft: '8px' }} onClick={() => {
                                 this.setState({
-                                    editingKey: code
+                                    editingKey: code,
+                                    richTextReadOnly: true,
                                 }, () => {
                                     this['inputRef-' + code].focus();
                                 })
@@ -91,7 +96,7 @@ class ViewLayout extends React.PureComponent {
                         {isPreview && <Icon className={iconCls} type="close" onClick={this.hidePreviewBox}/>}
                     </div>
                 </div>
-                <ChartView tableBodyHeight={isPreview ? (this.state.screenHeight * 0.8 - 24 - 40 - 50 - 38) : 50 * layout.h - 30 - 50 -38} editMode={isPreview ? false : editMode} item={{...item}} reload={reload}/>
+                <ChartView readOnly={richTextReadOnly} tableBodyHeight={isPreview ? (this.state.screenHeight * 0.8 - 24 - 40 - 50 - 38) : 50 * layout.h - 30 - 50 -38} editMode={isPreview ? false : editMode} item={{...item}} reload={reload}/>
             </div>
         )
     }

+ 28 - 24
src/components/dataSource/list.jsx

@@ -131,30 +131,34 @@ class DataSource extends React.Component {
         const { dataSource, dispatch } = this.props;
         const { noGroup } = this.state;
         const { currentGroup } = dataSource;
-        const pGroups = currentGroup ? [{ code: '-1', label: '全部分组' }].concat(this.getParens(currentGroup)) : [{ code: '-1', label: '全部分组' }];
+        const pGroups = (currentGroup) ? [{ code: '-1', label: '全部分组' }].concat(this.getParens(currentGroup)) : [{ code: '-1', label: '全部分组' }];
         return <Breadcrumb className={`group${noGroup ? ' nogroup' : ''}`} separator=">">
             { pGroups.map(g => (
                 <Breadcrumb.Item key={g.code}>
-                    <GroupSelector
-                        visible={this.state['visibleGroupSelector' + g.code]}
-                        handleVisibleChange={(visible) => {
-                            let obj = {};
-                            obj['visibleGroupSelector' + g.code] = visible
-                            this.setState(obj);
-                        }}
-                        pGroup={g}
-                        groupList={dataSource.groupList}
-                        selectGroup={(group) => {
-                            let obj = {};
-                            obj['visibleGroupSelector' + g.code] = false;
-                            this.setState(obj);
-                            dispatch({ type: 'dataSource/setCurrentGroup', group });
-                        }}
-                    >
-                        <Tag color={'blue'} >
-                            {g.label}
-                        </Tag>
-                    </GroupSelector>
+                    <Tag color={'blue'} >
+                        <span onClick={() => {
+                            let group = dataSource.groupList.find(group => group.code === g.code);
+                            dispatch({ type: 'dataSource/setCurrentGroup', group: group });
+                        }}>{g.label}</span>
+                        <GroupSelector
+                            visible={this.state['visibleGroupSelector' + g.code]}
+                            handleVisibleChange={(visible) => {
+                                let obj = {};
+                                obj['visibleGroupSelector' + g.code] = visible
+                                this.setState(obj);
+                            }}
+                            pGroup={g}
+                            groupList={dataSource.groupList}
+                            selectGroup={(group) => {
+                                let obj = {};
+                                obj['visibleGroupSelector' + g.code] = false;
+                                this.setState(obj);
+                                dispatch({ type: 'dataSource/setCurrentGroup', group });
+                            }}
+                        >
+                            <Icon style={{ marginLeft: '8px', fontSize: '12px' }} type="down" />
+                        </GroupSelector>
+                    </Tag>
                 </Breadcrumb.Item>
             )) }
         </Breadcrumb>
@@ -354,14 +358,14 @@ class DataSource extends React.Component {
                     <Card className='datasource-body' title={
                         <Row className='datasource-tools' type='flex' justify='space-between'>
                             <Col style={{ display: 'flex', width: 'calc(100% - 324px)', overflow: 'hidden' }}>
+                                <Checkbox style={{ marginTop: '4px' }} value={noGroup} onChange={(e) => {
+                                    this.setState({noGroup: e.target.checked})
+                                }}>未分组</Checkbox>
                                 <Icon type="bars" onClick={() => {
                                     this.setState({
                                         visibleGroupManageMentBox: true
                                     });
                                 }}/>
-                                <Checkbox style={{ marginTop: '4px' }} value={noGroup} onChange={(e) => {
-                                    this.setState({noGroup: e.target.checked})
-                                }}>未分组</Checkbox>
                                 { this.generateGroupTags() }
                             </Col>
                             <Col className='search'>

+ 51 - 0
src/components/dataSourceDetail/columnConfig.md

@@ -0,0 +1,51 @@
+## 数据类型与分析类型说明
+
+#### 数据类型与分析类型的对应关系
+| 数据类型 | 名称 | 可选分析类型 | 默认分析类型 |
+|-|-|-|-|
+| String | 字符串 | [ 索引 , 类别, 文本 ] | 类别 |
+| Date | 时间 | [ 时间 ] | 时间 |
+| Timestamp | 时间 | [ 时间 ] | 时间 |
+| BigDecimal | 大数字 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Double | 双精度浮点型 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Long | 长整型 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Float | 浮点型 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Int | 整型 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Short | 短整型 | [ 索引 , 类别, 标量, 序值 , 文本 ] | 标量 |
+| Boolean | 布尔型 | [ 类别, 文本 ] | 类别 |
+| Byte | 字节型 | [ 类别, 文本 ] | 类别 |
+
+#### 分析类型说明
+| 数据类型 | 名称 | 说明 |
+|-|-|-|
+| index | 索引 | 目前没有明显用途, |
+| time | 时间 ||
+| categorical | 类别 ||
+| scale | 标量 ||
+| ordinal | 序值 ||
+| String | 文本 ||
+
+#### 图表设计与分析类型的逻辑关系
+##### 总体统计数据表
+
+| 属性 | 与分析类型逻辑 | 其他说明 |
+|-|-|-|
+| 分析目标 | 可以选全部分析类型列 ||
+| 显示总体数据 | 只有当分许目标选中列的分析类型等于标量时才允许选中百分比、平均数等计算属性,否则只允许选条数和百分比 ||
+| 分组 | 可以选全部分析类型列 | 需要数据源列设置中“允许分组”勾选 |
+
+##### 数据视图
+
+| 属性 | 与分析类型逻辑 | 其他说明 |
+|-|-|-|
+| 展示列 | 可以选全部分析类型列 ||
+| 排序列 | 可以选全部分析类型列 | 只能从已加入展示列的数据中选 |
+| 排序方式 | 无 ||
+
+##### 折线图
+
+| 属性 | 与分析类型逻辑 | 其他说明 |
+|-|-|-|
+| 展示列 | 可以选全部分析类型列 ||
+| 排序列 | 可以选全部分析类型列 | 只能从已加入展示列的数据中选 |
+| 排序方式 | 无 ||

+ 3 - 3
src/components/dataSourceDetail/columnType.json

@@ -1,5 +1,5 @@
 [{
-    "dataType": ["String", "BigDecimal", "Double", "long", "float", "int"],
+    "dataType": ["String", "BigDecimal", "Double", "long", "float", "int", "Short"],
     "columnType": "index",
     "label": "索引"
 }, {
@@ -11,11 +11,11 @@
     "columnType": "categorical",
     "label": "类别"
 }, {
-    "dataType": ["BigDecimal", "Double", "Long", "Float", "Int"],
+    "dataType": ["BigDecimal", "Double", "Long", "Float", "Int", "Short"],
     "columnType": "scale",
     "label": "标量"
 }, {
-    "dataType": ["BigDecimal", "Double", "Long", "Float", "Int"],
+    "dataType": ["BigDecimal", "Double", "Long", "Float", "Int", "Short"],
     "columnType": "ordinal",
     "label": "序值"
 }, {

+ 2 - 7
src/components/dataSourceDetail/dataConnectBox.jsx

@@ -56,13 +56,7 @@ class DataConnectBox extends React.Component {
         return (
             <Modal
                 className='dataconnect-box'
-                title={<Row type='flex' justify='space-between'><Col>{`${operation === 'create'?'新建':(operation === 'modify' ? '修改' : '查看')}数据链接`}</Col><Col style={{ marginRight: '35px', fontSize: '14px', cursor: 'pointer', color: 'red' }} onClick={() => {
-                    // 密码input特殊处理
-                    document.getElementsByClassName('password')[0].value = '';
-                    dispatch({ type:'dataConnect/resetNewModel'})
-                }}>
-                    {/* <Icon type='delete' />清空 */}
-                </Col></Row>}
+                title={`${operation === 'create'?'新建':(operation === 'modify' ? '修改' : '查看')}数据链接`}
                 visible={dataConnect.newOne.visibleBox}
                 onCancel={() => { this.hideBox() }}
                 maskClosable={false}
@@ -218,6 +212,7 @@ class DataConnectBox extends React.Component {
                                     className='password'
                                     type='password'
                                     value={password}
+                                    placeholder={operation === 'create' ? '' : '******'}
                                     onFocus={e => {
                                         this.setState({
                                             passwordEditing: true

+ 1 - 0
src/components/homePage/index.less

@@ -1,4 +1,5 @@
 .layout-home {
+    flex-direction: row;
     .sider-home {
         padding: 0;
         border-right: 1px solid @border-color-base;

+ 1 - 0
src/components/setting/index.less

@@ -1,4 +1,5 @@
 .layout-setting {
+    flex-direction: row;
     .sider-setting {
         padding: 12px;
         border-right: 1px solid @border-color-base;

+ 101 - 100
src/constants/url.js

@@ -1,227 +1,228 @@
-// const BASE_URL = 'http://10.1.1.168:8094/BI';
-// const BASE_URL = 'http://10.1.80.78:8011';
-const BASE_URL = 'http://218.18.115.198:8888/BI'
+// const BASE_URL = 'http://10.1.1.168:8094/BI/';
+// const BASE_URL = 'http://10.1.80.78:8011/';
+const BASE_URL = 'http://218.18.115.198:8888/BI/'
+// const BASE_URL = ''
 
 /**后台接口地址 */
 const URLS = {
 
     /***************************************当前用户***************************************/
     
-    LOGIN: BASE_URL + '/login', // 登录
+    LOGIN: BASE_URL + 'login', // 登录
 
-    LOGOUT: BASE_URL + '/logout', // 登出
+    LOGOUT: BASE_URL + 'logout', // 登出
 
     /***************************************用户组***************************************/
     
-    USERGROUP_LIST: BASE_URL + '/getUserGroupList', // 获得用户组列表
+    USERGROUP_LIST: BASE_URL + 'getUserGroupList', // 获得用户组列表
 
-    USERGROUP_ADD: BASE_URL + '/createUserGroup', // 添加用户组
+    USERGROUP_ADD: BASE_URL + 'createUserGroup', // 添加用户组
 
-    USERGROUP_DELETE: BASE_URL + '/delUserGroup', // 删除用户组
+    USERGROUP_DELETE: BASE_URL + 'delUserGroup', // 删除用户组
 
-    USERGROUP_UPDATE: BASE_URL + '/updateUserGroup', // 修改用户组
+    USERGROUP_UPDATE: BASE_URL + 'updateUserGroup', // 修改用户组
 
-    USERGROUP_MEMBER_LIST: BASE_URL + '/getUserInGroup', // 获得用户组成员列表
+    USERGROUP_MEMBER_LIST: BASE_URL + 'getUserInGroup', // 获得用户组成员列表
 
-    USERGROUP_MEMBER_ADD: BASE_URL + '/setUserInto', // 添加用户组成员
+    USERGROUP_MEMBER_ADD: BASE_URL + 'setUserInto', // 添加用户组成员
 
-    USERGROUP_MEMBER_DELETE: BASE_URL + '/delUserInGroup', // 删除用户组成员
+    USERGROUP_MEMBER_DELETE: BASE_URL + 'delUserInGroup', // 删除用户组成员
     
     /***************************************用户***************************************/
 
-    USER_LIST: BASE_URL + '/getUserList', // 获取用户列表
+    USER_LIST: BASE_URL + 'getUserList', // 获取用户列表
 
-    USER_UPDATE: BASE_URL + '/updateUser', // 设置用户角色
+    USER_UPDATE: BASE_URL + 'updateUser', // 设置用户角色
 
-    USER_QUERY: BASE_URL + '/getNameList', // 关键字查询
+    USER_QUERY: BASE_URL + 'getNameList', // 关键字查询
 
     /***************************************数据源***************************************/
 
-    DATASOURCE_ADD: BASE_URL + '/Connector/inputDataConnector', // 新增数据源
+    DATASOURCE_ADD: BASE_URL + 'Connector/inputDataConnector', // 新增数据源
 
-    DATASOURCE_UPDATE: BASE_URL + '/Connector/updateData', // 修改数据源
+    DATASOURCE_UPDATE: BASE_URL + 'Connector/updateData', // 修改数据源
 
-    DATASOURCE_DELETE: BASE_URL + '/Connector/delDataConnector', // 删除数据源
+    DATASOURCE_DELETE: BASE_URL + 'Connector/delDataConnector', // 删除数据源
 
-    DATASOURCE_LIST: BASE_URL + '/Connector/getListDataConnector', // 获得数据源列表
+    DATASOURCE_LIST: BASE_URL + 'Connector/getListDataConnector', // 获得数据源列表
 
-    DATASOURCE_DETAIL: BASE_URL + '/Connector/getDataConnector', // 获得单个数据源详细数据
+    DATASOURCE_DETAIL: BASE_URL + 'Connector/getDataConnector', // 获得单个数据源详细数据
 
-    DATASOURCE_QUERY_SQLCOLUMNS: BASE_URL + '/Connector/implementSql', // 根据sql请求列数据信息
+    DATASOURCE_QUERY_SQLCOLUMNS: BASE_URL + 'Connector/implementSql', // 根据sql请求列数据信息
     
-    DATASOURCE_QUERY_DATACOLUMNS: BASE_URL + '/DataBase/getColumnData', // 获得数据源下的列
+    DATASOURCE_QUERY_DATACOLUMNS: BASE_URL + 'DataBase/getColumnData', // 获得数据源下的列
 
-    DATASOURCE_QUERY_COLUMNDATA: BASE_URL + '/getScreenByBaseId', // 数据源关键字查询获得列去重之后的数据(20条)
+    DATASOURCE_QUERY_COLUMNDATA: BASE_URL + 'getScreenByBaseId', // 数据源关键字查询获得列去重之后的数据(20条)
 
-    DATASOURCE_QUERY_COLUMNDATA_MUL: BASE_URL + '/getScreenByBaseIds', // 数据源关键字查询获得列去重之后的数据(多个数据源)(20条)
+    DATASOURCE_QUERY_COLUMNDATA_MUL: BASE_URL + 'getScreenByBaseIds', // 数据源关键字查询获得列去重之后的数据(多个数据源)(20条)
 
-    DATASOURCE_POLICY_LIST: BASE_URL + '/getDbStrategys', // 获得数据源的策略
+    DATASOURCE_POLICY_LIST: BASE_URL + 'getDbStrategys', // 获得数据源的策略
 
-    DATASOURCE_POLICY_ADD: BASE_URL + '/addStrategys', // 添加策略
+    DATASOURCE_POLICY_ADD: BASE_URL + 'addStrategys', // 添加策略
 
-    DATASOURCE_POLICY_UPDATE: BASE_URL + '/updateStrategys', // 修改策略
+    DATASOURCE_POLICY_UPDATE: BASE_URL + 'updateStrategys', // 修改策略
 
-    DATASOURCE_POLICY_DELETE: BASE_URL + '/delDbStrategys', // 删除策略
+    DATASOURCE_POLICY_DELETE: BASE_URL + 'delDbStrategys', // 删除策略
 
-    DATASOURCE_POLICY_TARGET_UPDATE: BASE_URL + '/addObject', // 设置策略对象
+    DATASOURCE_POLICY_TARGET_UPDATE: BASE_URL + 'addObject', // 设置策略对象
 
-    DATASOURCE_TRANSFER: BASE_URL + '/Connector/changeDbOrder', // 数据源移交
+    DATASOURCE_TRANSFER: BASE_URL + 'Connector/changeDbOrder', // 数据源移交
 
-    DATASOURCE_COPY: BASE_URL + '/Connector/copyDataSource', // 数据源复制
+    DATASOURCE_COPY: BASE_URL + 'Connector/copyDataSource', // 数据源复制
 
-    DATASOURCE_DATA_LIST: BASE_URL + '/Connector/getConnectorData', // 获取数据列表
+    DATASOURCE_DATA_LIST: BASE_URL + 'Connector/getConnectorData', // 获取数据列表
 
-    DATASOURCE_DATA_LIST_BY_CHART: BASE_URL + '/getChartsData', // 通过图表code获取数据列表
+    DATASOURCE_DATA_LIST_BY_CHART: BASE_URL + 'getChartsData', // 通过图表code获取数据列表
 
     /***************************************数据链接配置***************************************/
 
-    DATACONNECT_ADD: BASE_URL + '/DataBase/inputDatabases', // 新增数据链接配置
+    DATACONNECT_ADD: BASE_URL + 'DataBase/inputDatabases', // 新增数据链接配置
 
-    DATACONNECT_UPDATE: BASE_URL + '/DataBase/updatabases', // 修改数据链接配置
+    DATACONNECT_UPDATE: BASE_URL + 'DataBase/updatabases', // 修改数据链接配置
 
-    DATACONNECT_DELETE: BASE_URL + '/DataBase/delDatabases', // 删除数据链接配置
+    DATACONNECT_DELETE: BASE_URL + 'DataBase/delDatabases', // 删除数据链接配置
 
-    DATACONNECT_LIST: BASE_URL + '/DataBase/getDatabases', // 获得数据链接列表
+    DATACONNECT_LIST: BASE_URL + 'DataBase/getDatabases', // 获得数据链接列表
 
-    DATACONNECT_VALIDATE: BASE_URL + '/DataBase/testConnect', // 校验数据库连接是否合法
+    DATACONNECT_VALIDATE: BASE_URL + 'DataBase/testConnect', // 校验数据库连接是否合法
 
     /***************************************图表***************************************/
 
-    CHART_ADD: BASE_URL + '/inputCharts', // 新增图表
+    CHART_ADD: BASE_URL + 'inputCharts', // 新增图表
 
-    CHART_UPDATE: BASE_URL + '/updateCharts', // 修改图表
+    CHART_UPDATE: BASE_URL + 'updateCharts', // 修改图表
 
-    CHART_DELETE: BASE_URL + '/delChartsConfig', // 删除图表
+    CHART_DELETE: BASE_URL + 'delChartsConfig', // 删除图表
 
-    CHART_LIST: BASE_URL + '/getListCharts', // 获得图表列表
+    CHART_LIST: BASE_URL + 'getListCharts', // 获得图表列表
 
-    CHART_QUERY_COLUMNDATA: BASE_URL + '/showScreenData', // 图表获得关键字查询过滤列去重之后的数据(20条)
+    CHART_QUERY_COLUMNDATA: BASE_URL + 'showScreenData', // 图表获得关键字查询过滤列去重之后的数据(20条)
 
-    CHART_DETAIL: BASE_URL + '/getChartsConfig', // 获得单个图表详细数据
+    CHART_DETAIL: BASE_URL + 'getChartsConfig', // 获得单个图表详细数据
 
-    CHART_OPTION: BASE_URL + '/showChartsInDash', // 请求图表展示数据(已定义好的图表)
+    CHART_OPTION: BASE_URL + 'showChartsInDash', // 请求图表展示数据(已定义好的图表)
 
-    CHART_BAR_OPTION: BASE_URL + '/showHistogram', // 请求柱状图展示数据
+    CHART_BAR_OPTION: BASE_URL + 'showHistogram', // 请求柱状图展示数据
 
-    CHART_PIE_OPTION: BASE_URL + '/showPie', // 请求饼图展示数据
+    CHART_PIE_OPTION: BASE_URL + 'showPie', // 请求饼图展示数据
 
-    CHART_LINE_OPTION: BASE_URL + '/showLine', // 请求折线图展示数据
+    CHART_LINE_OPTION: BASE_URL + 'showLine', // 请求折线图展示数据
 
-    CHART_SCATTER_OPTION: BASE_URL + '/showScatter', // 请求散点图展示数据
+    CHART_SCATTER_OPTION: BASE_URL + 'showScatter', // 请求散点图展示数据
 
-    CHART_DATAVIEW_OPTION: BASE_URL + '/showIndividual', // 请求个体统计数据
+    CHART_DATAVIEW_OPTION: BASE_URL + 'showIndividual', // 请求个体统计数据
 
-    CHART_AGGREGATETABLE_OPTION: BASE_URL + '/showPopulation', // 请求总体统计数据
+    CHART_AGGREGATETABLE_OPTION: BASE_URL + 'showPopulation', // 请求总体统计数据
 
-    CHART_QUERY_DATACOLUMNS: BASE_URL + '/DataBase/getColumnByChartId', // 通过图表id获得列数据
+    CHART_QUERY_DATACOLUMNS: BASE_URL + 'DataBase/getColumnByChartId', // 通过图表id获得列数据
 
-    CHART_POLICY_LIST: BASE_URL + '/getChartStrategys', // 获得图表的策略
+    CHART_POLICY_LIST: BASE_URL + 'getChartStrategys', // 获得图表的策略
 
-    CHART_POLICY_ADD: BASE_URL + '/addStrategys', // 添加策略
+    CHART_POLICY_ADD: BASE_URL + 'addStrategys', // 添加策略
 
-    CHART_POLICY_UPDATE: BASE_URL + '/updateStrategys', // 修改策略
+    CHART_POLICY_UPDATE: BASE_URL + 'updateStrategys', // 修改策略
 
-    CHART_POLICY_DELETE: BASE_URL + '/delChartStrategys', // 删除策略
+    CHART_POLICY_DELETE: BASE_URL + 'delChartStrategys', // 删除策略
 
-    CHART_POLICY_TARGET_UPDATE: BASE_URL + '/addObject', // 设置策略对象
+    CHART_POLICY_TARGET_UPDATE: BASE_URL + 'addObject', // 设置策略对象
 
-    CHART_TRANSFER: BASE_URL + '/changeChartOrder', // 图表移交
+    CHART_TRANSFER: BASE_URL + 'changeChartOrder', // 图表移交
 
     /***************************************数据源分组***************************************/
 
-    GROUP_DATASOURCE_LIST: BASE_URL + '/Connector/getConnectorGroup', // 获得数据源所有分组/子分组
+    GROUP_DATASOURCE_LIST: BASE_URL + 'Connector/getConnectorGroup', // 获得数据源所有分组/子分组
 
-    GROUP_DATASOURCE_BATCH_SET: BASE_URL + '/Connector/batchUpdateConnectorGroup', // 数据源分组批量设置
+    GROUP_DATASOURCE_BATCH_SET: BASE_URL + 'Connector/batchUpdateConnectorGroup', // 数据源分组批量设置
 
-    GROUP_DATASOURCE_ADD: BASE_URL + '/Connector/setConnectorGroup', // 新增数据源分组/子分组(已废弃)
+    GROUP_DATASOURCE_ADD: BASE_URL + 'Connector/setConnectorGroup', // 新增数据源分组/子分组(已废弃)
 
-    GROUP_DATASOURCE_UPDATE: BASE_URL + '/Connector/updataDataConnectorGroup', // 修改数据源分组信息(已废弃)
+    GROUP_DATASOURCE_UPDATE: BASE_URL + 'Connector/updataDataConnectorGroup', // 修改数据源分组信息(已废弃)
 
-    GROUP_DATASOURCE_SET_GROUP: BASE_URL + '/Connector/updateConnectConfigGroup', // 设置数据源所属分组
+    GROUP_DATASOURCE_SET_GROUP: BASE_URL + 'Connector/updateConnectConfigGroup', // 设置数据源所属分组
 
-    GROUP_DATASOURCE_LIST_UPDATE: BASE_URL + '/Connector/updataConnectorGroup', // 批量修改数据源分组信息(已废弃)
+    GROUP_DATASOURCE_LIST_UPDATE: BASE_URL + 'Connector/updataConnectorGroup', // 批量修改数据源分组信息(已废弃)
 
-    GROUP_DATASOURCE_DELETE: BASE_URL + '/Connector/delDataConnectorGroup', // 删除数据源分组/子分组(已废弃)
+    GROUP_DATASOURCE_DELETE: BASE_URL + 'Connector/delDataConnectorGroup', // 删除数据源分组/子分组(已废弃)
 
     /***************************************图表分组***************************************/
 
-    GROUP_CHART_LIST: BASE_URL + '/getChartsGroup', // 获得图表所有分组/子分组
+    GROUP_CHART_LIST: BASE_URL + 'getChartsGroup', // 获得图表所有分组/子分组
 
-    GROUP_CHART_BATCH_SET: BASE_URL + '/batchUpdateChartsGroup', // 图表分组批量设置
+    GROUP_CHART_BATCH_SET: BASE_URL + 'batchUpdateChartsGroup', // 图表分组批量设置
 
-    GROUP_CHART_ADD: BASE_URL + '/setChartsGroup', // 新增图表分组/子分组
+    GROUP_CHART_ADD: BASE_URL + 'setChartsGroup', // 新增图表分组/子分组
 
-    GROUP_CHART_UPDATE: BASE_URL + '/updataChartsGroup', // 修改图表分组信息
+    GROUP_CHART_UPDATE: BASE_URL + 'updataChartsGroup', // 修改图表分组信息
 
-    GROUP_CHART_SET_GROUP: BASE_URL + '/updateChartConfigGroup', // 设置图表所属分组
+    GROUP_CHART_SET_GROUP: BASE_URL + 'updateChartConfigGroup', // 设置图表所属分组
 
-    GROUP_CHART_LIST_UPDATE: BASE_URL + '/updataListGroup', // 批量修改图表分组信息
+    GROUP_CHART_LIST_UPDATE: BASE_URL + 'updataListGroup', // 批量修改图表分组信息
 
-    GROUP_CHART_DELETE: BASE_URL + '/delChartsGroup', // 删除图表分组/子分组
+    GROUP_CHART_DELETE: BASE_URL + 'delChartsGroup', // 删除图表分组/子分组
 
     /***************************************报表***************************************/
 
-    DASHBOARD_LIST: BASE_URL + '/getListDashboards', // 获得报表列表
+    DASHBOARD_LIST: BASE_URL + 'getListDashboards', // 获得报表列表
 
-    DASHBOARD_DETAIL: BASE_URL + '/getDashboards', // 获得单个报表
+    DASHBOARD_DETAIL: BASE_URL + 'getDashboards', // 获得单个报表
     
-    DASHBOARD_ADD: BASE_URL + '/inputDashboards', // 新增报表
+    DASHBOARD_ADD: BASE_URL + 'inputDashboards', // 新增报表
 
-    DASHBOARD_DELETE: BASE_URL + '/delDashboards', // 删除报表
+    DASHBOARD_DELETE: BASE_URL + 'delDashboards', // 删除报表
 
-    DASHBOARD_UPDATE: BASE_URL + '/updateDashboards', // 更新报表
+    DASHBOARD_UPDATE: BASE_URL + 'updateDashboards', // 更新报表
 
-    DASHBOARD_SHARE_LIST: BASE_URL + '/getDashOrder', // 获得报表分发列表
+    DASHBOARD_SHARE_LIST: BASE_URL + 'getDashOrder', // 获得报表分发列表
 
-    DASHBOARD_SHARE: BASE_URL + '/addObject', // 报表分发
+    DASHBOARD_SHARE: BASE_URL + 'addObject', // 报表分发
 
-    DASHBOARD_TRANSFER: BASE_URL + '/changeDashOrder', // 报表移交
+    DASHBOARD_TRANSFER: BASE_URL + 'changeDashOrder', // 报表移交
 
-    DASHBOARD_COPY: BASE_URL + '/copyDashboard', // 报表复制
+    DASHBOARD_COPY: BASE_URL + 'copyDashboard', // 报表复制
 
-    DASHBOARD_GET_SHAREKEY: BASE_URL + '/share', // 生成报表分享链接
+    DASHBOARD_GET_SHAREKEY: BASE_URL + 'share', // 生成报表分享链接
     
-    DASHBOARD_SHARE_DETAIL_BY_KEY: BASE_URL + '/getSharedDashboard', // 通过报表分享链接获取报表数据
+    DASHBOARD_SHARE_DETAIL_BY_KEY: BASE_URL + 'getSharedDashboard', // 通过报表分享链接获取报表数据
 
-    DASHBOARD_ENCRYPT_CODE: BASE_URL + '/encryptCode', // 通过报表编号获得加密串
+    DASHBOARD_ENCRYPT_CODE: BASE_URL + 'encryptCode', // 通过报表编号获得加密串
 
-    DASHBOARD_SHARE_DETAIL_BY_CODE: BASE_URL + '/getDashboardByCode', // 通过报表编号获得报表数据
+    DASHBOARD_SHARE_DETAIL_BY_CODE: BASE_URL + 'getDashboardByCode', // 通过报表编号获得报表数据
 
-    DASHBOARD_COLLECT_LIST: BASE_URL + '/dashboard/favorite/list', // 报表收藏列表
+    DASHBOARD_COLLECT_LIST: BASE_URL + 'dashboard/favorite/list', // 报表收藏列表
 
-    DASHBOARD_COLLECT_ADD: BASE_URL + '/dashboard/favorite/save', // 添加报表到收藏
+    DASHBOARD_COLLECT_ADD: BASE_URL + 'dashboard/favorite/save', // 添加报表到收藏
 
-    DASHBOARD_COLLECT_REMOVE: BASE_URL + '/dashboard/favorite/delete', // 报表取消收藏
+    DASHBOARD_COLLECT_REMOVE: BASE_URL + 'dashboard/favorite/delete', // 报表取消收藏
 
     /***************************************报表目录***************************************/
 
-    DASHBOARD_MENU_TREE: BASE_URL + '/dashboard/menu/list', // 获取报表目录树
+    DASHBOARD_MENU_TREE: BASE_URL + 'dashboard/menu/list', // 获取报表目录树
 
-    DASHBOARD_MENU_ADD: BASE_URL + '/dashboard/menu/save', // 添加报表目录
+    DASHBOARD_MENU_ADD: BASE_URL + 'dashboard/menu/save', // 添加报表目录
 
-    DASHBOARD_MENU_UPDATE: BASE_URL + '/dashboard/menu/update', // 添加报表目录
+    DASHBOARD_MENU_UPDATE: BASE_URL + 'dashboard/menu/update', // 添加报表目录
 
-    DASHBOARD_MENU_DELETE: BASE_URL + '/dashboard/menu/delete', // 删除报表目录
+    DASHBOARD_MENU_DELETE: BASE_URL + 'dashboard/menu/delete', // 删除报表目录
 
-    DASHBOARD_MENU_DASHBOARD_LIST: BASE_URL + '/dashboard/menu/list', // 获得目录下的所有报表
+    DASHBOARD_MENU_DASHBOARD_LIST: BASE_URL + 'dashboard/menu/list', // 获得目录下的所有报表
 
-    DASHBOARD_SET_MENU: BASE_URL + '/dashboard/menu/update/dashboard', // 设置报表所属目录
+    DASHBOARD_SET_MENU: BASE_URL + 'dashboard/menu/update/dashboard', // 设置报表所属目录
 
     /***************************************浏览记录***************************************/
     
-    HISTORY_ADD: BASE_URL + '/addRecord', // 添加图表、报表浏览记录 0 - 图表  1 - 报表
+    HISTORY_ADD: BASE_URL + 'addRecord', // 添加图表、报表浏览记录 0 - 图表  1 - 报表
     
-    HISTORY_CHART_LIST: BASE_URL + '/getChartRecode', // 查询图表浏览记录列表
+    HISTORY_CHART_LIST: BASE_URL + 'getChartRecode', // 查询图表浏览记录列表
 
-    HISTORY_DASHBOARD_LIST: BASE_URL + '/getDashRecode', // 查询报表浏览记录列表
+    HISTORY_DASHBOARD_LIST: BASE_URL + 'getDashRecode', // 查询报表浏览记录列表
 
     /***************************************主页模块***************************************/
 
-    HOMEPAGE_RECENT_CHART_GET: BASE_URL + "/getChartRecord", // 查询最近访问图表  //可能的错字
+    HOMEPAGE_RECENT_CHART_GET: BASE_URL + 'getChartRecord', // 查询最近访问图表  //可能的错字
 
-    HOMEPAGE_RECENT_DASHBOARD_GET: BASE_URL + "/getDashRecord", //查询最近访问报表 //可能的错字
+    HOMEPAGE_RECENT_DASHBOARD_GET: BASE_URL + 'getDashRecord', //查询最近访问报表 //可能的错字
 
-    HOMEPAGE_ADD_RECENT_RECORD: BASE_URL + "/addRecord", //添加最近访问记录 
+    HOMEPAGE_ADD_RECENT_RECORD: BASE_URL + 'addRecord', //添加最近访问记录 
 }
 
 export default URLS

+ 1 - 4
src/models/dashboardDesigner.js

@@ -212,7 +212,7 @@ export default {
         addRichText(state, action) {
             let { items, defaultLayout } = state;
             items.push({
-                code: Math.random(),
+                code: Math.random() + '',
                 viewType: 'richText',
                 name: '',
                 layout: defaultLayout
@@ -247,9 +247,6 @@ export default {
                 items[idx] = { ...items[idx], ...item };
             }
             return Object.assign({}, state, {items, dirty});
-
-
-            
         },
         reset(state, action) {
             let newState = Object.assign({}, state, state.originData);

+ 1 - 1
src/models/defaultColumnType.json

@@ -9,5 +9,5 @@
     "Int": "scale",
     "Boolean": "categorical",
     "Byte": "string",
-    "Short": "string"
+    "Short": "scale"
 }

+ 16 - 0
src/themes/default/base.less

@@ -76,6 +76,22 @@
 }
 
 // Modal
+.ant-modal-header {
+    display: table;
+    width: 100%;
+    border-bottom: none;
+    &:before, &:after {
+        content: "";
+        position: relative;
+        width: 33%;
+        border-top: 1px solid #e8e8e8;
+        display: table-cell;
+        transform: translateY(50%);
+    }
+    .ant-modal-title {
+        text-align: center;
+    }
+}
 .ant-modal-close-x {
     height: 24px;
     width: 24px;

+ 7 - 0
src/themes/default/chartdesigner.less

@@ -46,6 +46,13 @@
                             .ant-form-item-label > label {
                                 color: @text-color;
                             }
+                            .checkbox-group-statistics {
+                                >.ant-row {
+                                    >div>label {
+                                        color: @text-color;
+                                    }
+                                }
+                            }
                         }
                     }
                     >.sider-footer {