hy 6 years ago
parent
commit
fb1b8fc337
41 changed files with 482 additions and 954 deletions
  1. 5 4
      src/components/admin/admin.jsx
  2. 6 1
      src/components/admin/admin.less
  3. 21 19
      src/components/admin/userGroupManagement.jsx
  4. 13 13
      src/components/admin/userGroupManagement.less
  5. 9 8
      src/components/chart/list.jsx
  6. 5 0
      src/components/chart/list.less
  7. 34 311
      src/components/chart/resolveChartOption.js
  8. 3 29
      src/components/chartDesigner/content.jsx
  9. 1 8
      src/components/chartDesigner/sections/barConfigForm.jsx
  10. 1 8
      src/components/chartDesigner/sections/lineConfigForm.jsx
  11. 1 8
      src/components/chartDesigner/sections/pieConfigForm.jsx
  12. 1 8
      src/components/chartDesigner/sections/scatterConfigForm.jsx
  13. 0 120
      src/components/common/CardList.jsx
  14. 0 146
      src/components/common/CardList.less
  15. 7 0
      src/components/common/emptyContent/index.jsx
  16. 5 3
      src/components/common/selectUserBox/selectUserBox.jsx
  17. 19 3
      src/components/dashboard/layout.jsx
  18. 8 1
      src/components/dashboard/list.less
  19. 63 46
      src/components/dashboard/menu.jsx
  20. 1 1
      src/components/dashboard/menu.less
  21. 6 5
      src/components/dashboard/shareKeyView.jsx
  22. 6 5
      src/components/dashboard/shareView.jsx
  23. 12 0
      src/components/dashboard/view.jsx
  24. 1 1
      src/components/dashboardDesigner/chartView.jsx
  25. 110 19
      src/components/dashboardDesigner/chooseChartBox.jsx
  26. 12 14
      src/components/dashboardDesigner/configSider.jsx
  27. 35 29
      src/components/dashboardDesigner/content.jsx
  28. 29 2
      src/components/dashboardDesigner/cusFilterBox.jsx
  29. 24 25
      src/components/dashboardDesigner/layout.jsx
  30. 9 2
      src/components/dashboardDesigner/layout.less
  31. 6 1
      src/components/dashboardDesigner/richTextEditor.jsx
  32. 0 0
      src/components/dashboardDesigner/viewBox.jsx
  33. 4 6
      src/components/dashboardDesigner/viewLayout.jsx
  34. 2 2
      src/components/dashboardDesigner/viewLayout.less
  35. 3 2
      src/components/dataConnect/list.jsx
  36. 8 0
      src/components/dataConnect/list.less
  37. 8 1
      src/components/dataSource/list.less
  38. 2 0
      src/components/dataSourceDetail/dataConnectBox.jsx
  39. 2 1
      src/components/dataSourceDetail/dataConnectConfig.jsx
  40. 0 53
      src/components/homePage/homePage.jsx
  41. 0 49
      src/components/homePage/homePage.less

+ 5 - 4
src/components/admin/admin.jsx

@@ -24,16 +24,17 @@ class Admin extends React.Component {
 
 
     render() {
     render() {
         return (      
         return (      
-            <Tabs 
+            <Tabs
+                type='card'
                 className='admin-tabs'
                 className='admin-tabs'
-                tabPosition='left'
+                tabPosition='top'
                 defaultActiveKey="userGroup"
                 defaultActiveKey="userGroup"
                 onChange={this.changeTab}
                 onChange={this.changeTab}
             >
             >
-                <TabPane tab="用户组" key="userGroup" >
+                <TabPane tab="用户组" key="userGroup" >
                     <UserGroupManagement />
                     <UserGroupManagement />
                 </TabPane>
                 </TabPane>
-                <TabPane tab="用户管理" key="user" >
+                <TabPane tab="用户" key="user" >
                     <UserManagement/>
                     <UserManagement/>
                 </TabPane>
                 </TabPane>
             </Tabs>
             </Tabs>

+ 6 - 1
src/components/admin/admin.less

@@ -1,10 +1,15 @@
 .admin-tabs {
 .admin-tabs {
     height: 100%;
     height: 100%;
+    display: flex;
+    flex-direction: column;
+    background: #fff;
+    padding: 12px;
     .ant-tabs-bar {
     .ant-tabs-bar {
         margin: 0;
         margin: 0;
     }
     }
     .ant-tabs-content {
     .ant-tabs-content {
-        height: 100%;
+        flex: auto;
+        overflow: hidden;
         border: none !important;
         border: none !important;
         .ant-tabs-tabpane {
         .ant-tabs-tabpane {
             height: 100%;
             height: 100%;

+ 21 - 19
src/components/admin/userGroupManagement.jsx

@@ -140,27 +140,29 @@ class UserGroupManagement extends React.Component {
                 <Content>
                 <Content>
                     <div className='groupname'>
                     <div className='groupname'>
                         <span>{selectedGroup ? selectedGroup.name : ''}</span>
                         <span>{selectedGroup ? selectedGroup.name : ''}</span>
-                        {selectedGroup && <Button className='delete-btn' onClick={() => {
-                            this.setState({
-                                visibleDeleteBox: true
-                            })
-                        }}>
-                            <Icon type="delete" />删除用户组
-                        </Button>}
-                        {visibleDeleteBox && <DeleteBox
-                            visibleBox={visibleDeleteBox}
-                            text={`确定要删除用户组【${selectedGroup.name}】吗?`}
-                            hideBox={() => {
+                        <div className='buttons'>
+                            {selectedGroup && <Button className='button delete-button' onClick={() => {
                                 this.setState({
                                 this.setState({
-                                    visibleDeleteBox: false
+                                    visibleDeleteBox: true
                                 })
                                 })
-                            }}
-                            okHandler={() =>{
-                                dispatch({ type: 'userGroup/remoteDelete', group: selectedGroup });
-                        }} />}
-                        {selectedGroup && <Button className='edit-btn' onClick={() => {this.showDetailBox('modify')}}>
-                            <Icon type="edit" />编辑用户组
-                        </Button>}
+                            }}>
+                                <Icon type="delete" />删除用户组
+                            </Button>}
+                            {visibleDeleteBox && <DeleteBox
+                                visibleBox={visibleDeleteBox}
+                                text={`确定要删除用户组【${selectedGroup.name}】吗?`}
+                                hideBox={() => {
+                                    this.setState({
+                                        visibleDeleteBox: false
+                                    })
+                                }}
+                                okHandler={() =>{
+                                    dispatch({ type: 'userGroup/remoteDelete', group: selectedGroup });
+                            }} />}
+                            {selectedGroup && <Button className='button edit-button' onClick={() => {this.showDetailBox('modify')}}>
+                                <Icon type="edit" />编辑用户组
+                            </Button>}
+                        </div>
                     </div>
                     </div>
                     <Table
                     <Table
                         className='member-table'
                         className='member-table'

+ 13 - 13
src/components/admin/userGroupManagement.less

@@ -1,15 +1,14 @@
 .group-layout {
 .group-layout {
     height: 100%;
     height: 100%;
     background: white;
     background: white;
-    padding: 5px;
-    border: 1px solid #e8e8e8;
+    border: 1px solid #ccc;
     flex-direction: row;
     flex-direction: row;
     .ant-layout-sider {
     .ant-layout-sider {
         height: 100%;
         height: 100%;
         background: white;
         background: white;
         .ant-layout-sider-children {
         .ant-layout-sider-children {
             height: 100%;
             height: 100%;
-            border-right: 1px solid #e8e8e8;
+            border-right: 1px solid #ccc;
             padding: 37px 5px;
             padding: 37px 5px;
             .search-area {
             .search-area {
                 margin-top: -32px;
                 margin-top: -32px;
@@ -23,18 +22,19 @@
         }
         }
     }
     }
     .ant-layout-content {
     .ant-layout-content {
-        padding: 40px 5px 37px 5px;
+        padding: 56px 5px 37px 5px;
         overflow: hidden;
         overflow: hidden;
         .groupname {
         .groupname {
-            height: 40px;
-            margin-top: -40px;
-            line-height: 35px;
-            padding-left: 20px;
-            .edit-btn {
-                float: right;
-            }
-            .delete-btn {
-                float: right;
+            height: 56px;
+            display: flex;
+            justify-content: space-between;
+            margin-top: -56px;
+            line-height: 40px;
+            padding: 8px 8px 8px 5px;
+            .buttons {
+                .button {
+                    margin-left: 8px;
+                }
             }
             }
         }
         }
         .member-table {
         .member-table {

+ 9 - 8
src/components/chart/list.jsx

@@ -6,6 +6,7 @@ import { Layout, Button, Icon, Input, Menu, Dropdown, Card, Col, Row, Breadcrumb
 import { connect } from 'dva'
 import { connect } from 'dva'
 import ChooseDataSourceBox from './chooseDataSourceBox'
 import ChooseDataSourceBox from './chooseDataSourceBox'
 import GroupManagementBox from '../common/groupManageMentBox/box'
 import GroupManagementBox from '../common/groupManageMentBox/box'
+import EmptyContent from '../common/emptyContent/index'
 import moment from 'moment'
 import moment from 'moment'
 import Ellipsis from 'ant-design-pro/lib/Ellipsis'
 import Ellipsis from 'ant-design-pro/lib/Ellipsis'
 import 'ant-design-pro/dist/ant-design-pro.css'
 import 'ant-design-pro/dist/ant-design-pro.css'
@@ -188,25 +189,25 @@ class ChartList extends React.Component {
         let cards = this.onGroup().map(l => {
         let cards = this.onGroup().map(l => {
             if(filterItem.type === 'date') {
             if(filterItem.type === 'date') {
                 if(filterLabel===""){
                 if(filterLabel===""){
-                    return { ...l, bf: false };
+                    return { ...l };
                 }else if(filterLabel.indexOf('#')>-1){
                 }else if(filterLabel.indexOf('#')>-1){
                     let start = filterLabel.split('#')[0]
                     let start = filterLabel.split('#')[0]
                     let end = filterLabel.split('#')[1]
                     let end = filterLabel.split('#')[1]
                     let nowTime = new Date(l[filterItem.name]).getTime();
                     let nowTime = new Date(l[filterItem.name]).getTime();
                     if(nowTime>=start && nowTime<=end){
                     if(nowTime>=start && nowTime<=end){
-                        return { ...l, bf: false };
+                        return { ...l };
                     }
                     }
-                    return { ...l, bf: true };
+                    return null;
                 }else{
                 }else{
-                    return { ...l, bf: true };
+                    return null;
                 }
                 }
             }else {
             }else {
-                return ((l[filterItem.name] + '').search(filterReg) > -1) ? { ...l, bf: false } : { ...l, bf: true }
+                return ((l[filterItem.name] + '').search(filterReg) > -1) ? { ...l } : null
             }
             }
-        }).sort((a, b) => {
+        }).filter(l => l !== null).sort((a, b) => {
             return new Date(b.createTime) - new Date(a.createTime)
             return new Date(b.createTime) - new Date(a.createTime)
         }).map( (l, i) => (
         }).map( (l, i) => (
-            <CardGrid className={`chart-card${l.bf?' chart-card-hide':''}`} key={i} onClick={() => {
+            <CardGrid className={`chart-card`} key={i} onClick={() => {
                 this.setState({ selectedRecord: l })
                 this.setState({ selectedRecord: l })
             }}>
             }}>
                 <Card
                 <Card
@@ -286,7 +287,7 @@ class ChartList extends React.Component {
             </CardGrid>
             </CardGrid>
         ));
         ));
         if(cards.length === 0) {
         if(cards.length === 0) {
-            return (<div className="ant-empty ant-empty-normal"><div className="ant-empty-image"><img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K"/></div><p className="ant-empty-description">暂无数据</p></div>)
+            return <EmptyContent />
         }
         }
         return cards;
         return cards;
     }
     }

+ 5 - 0
src/components/chart/list.less

@@ -1,6 +1,9 @@
 .chart-list {
 .chart-list {
     &>.ant-layout-content {
     &>.ant-layout-content {
         &>.ant-card {
         &>.ant-card {
+            height: 100%;
+            display: flex;
+            flex-direction: column;
             &>.ant-card-head {
             &>.ant-card-head {
                 padding: 0 10px;
                 padding: 0 10px;
                 .tools {
                 .tools {
@@ -40,10 +43,12 @@
                 }
                 }
             }
             }
             &>.ant-card-body {
             &>.ant-card-body {
+                flex: 1;
                 padding: 10px;
                 padding: 10px;
                 display: flex;
                 display: flex;
                 flex-wrap: wrap;
                 flex-wrap: wrap;
                 justify-content: center;
                 justify-content: center;
+                overflow: auto;
                 &>.chart-body {
                 &>.chart-body {
                     .chart-card {
                     .chart-card {
                         width: 207px;
                         width: 207px;

+ 34 - 311
src/components/chart/resolveChartOption.js

@@ -50,329 +50,52 @@ export default (option, silent, thumbnail) => {
         bottom: thumbnail ? 10 : 60,
         bottom: thumbnail ? 10 : 60,
         containLabel: !thumbnail
         containLabel: !thumbnail
     }
     }
-    // x轴
-    _option.xAxis ? _option.xAxis[0] = {
-        ..._option.xAxis[0],
-        // show: !thumbnail
-    } : void 0;
-    // y轴
-    _option.yAxis ? _option.yAxis[0] = {
-        ..._option.yAxis[0],
-        // show: !thumbnail
-    } : void 0;
     // 图形
     // 图形
-    if(viewType ==='bar' ) { // 柱状图
+    if(viewType ==='bar' || viewType === 'line') { // 柱状图
         _option.series = _option.series.map(s => ({
         _option.series = _option.series.map(s => ({
             ...s, showSymbol: !thumbnail, silent
             ...s, showSymbol: !thumbnail, silent
         }));
         }));
+        // x轴
+        _option.xAxis ? (_option.xAxis.length > 0 ? (
+            _option.xAxis[0].axisLabel = {
+                ..._option.xAxis[0].axisLabel,
+                show: !thumbnail,
+            }
+        ) : (
+            _option.xAxis.axisLabel = {
+                ..._option.xAxis.axisLabel,
+                show: !thumbnail,
+            }
+        )) : _option.xAxis = {
+            axisLabel: {
+                show: !thumbnail,
+            } 
+        };
+        // y轴
+        _option.yAxis ? (_option.yAxis.length > 0 ? (
+            _option.yAxis[0].axisLabel = {
+                ..._option.yAxis[0].axisLabel,
+                show: !thumbnail,
+            }
+        ) : (
+            _option.yAxis.axisLabel = {
+                ..._option.yAxis.axisLabel,
+                show: !thumbnail,
+            }
+        )) : _option.yAxis = {
+            axisLabel: {
+                show: !thumbnail,
+            } 
+        };
     }else if(viewType === 'pie') { // 饼图
     }else if(viewType === 'pie') { // 饼图
         _option.series = _option.series.map(s => ({
         _option.series = _option.series.map(s => ({
             ...s, label: { show: !silent }, labelLine: { show: !silent }, silent
             ...s, label: { show: !silent }, labelLine: { show: !silent }, silent
         }));
         }));
-    }else if(viewType === 'line') { // 折线图
-        _option.series = _option.series.map(s => ({
-            ...s, showSymbol: !thumbnail, silent
-        }));
     }else if(viewType === 'scatter') { // 散点图
     }else if(viewType === 'scatter') { // 散点图
         _option.series = _option.series.map(s => ({
         _option.series = _option.series.map(s => ({
             ...s, silent
             ...s, silent
         }));
         }));
     }
     }
     
     
-    
     return _option;
     return _option;
-}
-
-// function barConfig(chartConfig, option, styleConfig, silent, thumbnail) {
-//     const { xAxis, serieses, xTitle, yTitle } = option;
-//     const { bar } = styleConfig;
-//     const { stack, visibleToolTip } = (bar || { stack: false, visibleToolTip: true });
-//     let o = {
-//         animation: !thumbnail,
-//         tooltip : {
-//             show: visibleToolTip && !silent && !thumbnail,
-//             trigger: "axis",
-//             axisPointer: {
-//                 type: "cross",
-//                 label: {
-//                     backgroundColor: "#6a7985"
-//                 }
-//             }
-//         },
-//         legend: {
-//             show: !thumbnail,
-//             selectedMode: !silent
-//         },
-//         grid: {
-//             left: thumbnail ? 10 : '10%',
-//             right: thumbnail ? 10 : '10%',
-//             top: thumbnail ? 10 : 60,
-//             bottom: thumbnail ? 10 : 60,
-//             containLabel: !thumbnail
-//         },
-//         xAxis: [{
-//             show: !thumbnail,
-//             type: 'category',
-//             data: barXAxis(chartConfig, xAxis),
-//             name: xTitle || '横轴',
-//         }],
-//         yAxis: [{
-//             show: !thumbnail,
-//             name: yTitle || '纵轴',
-//             type: 'value'
-//         }],
-//         series: serieses.map(s => {
-//             return {
-//                 name: s.name,
-//                 type: 'bar',
-//                 data: s.value,
-//                 stack: stack ? '1' : null,
-//                 showSymbol: !thumbnail,
-//                 silent,
-//             }
-//         }) 
-//     }
-//     return o;
-// }
-
-// function pieConfig(option, styleConfig, silent, thumbnail) {
-
-//     const { xAxis, columnName, serieses } = option;
-
-//     let o = {
-//         animation: !thumbnail,
-//         grid: {
-//             left: thumbnail ? 10 : '10%',
-//             right: thumbnail ? 10 : '10%',
-//             top: thumbnail ? 10 : 60,
-//             bottom: thumbnail ? 10 : 60,
-//             containLabel: !thumbnail
-//         },
-//         tooltip : {
-//             show: !silent && !thumbnail,
-//             trigger: 'item',
-//             formatter: "{a} <br/>{b} : {c} ({d}%)"
-//         },
-//         legend: {
-//             show: !thumbnail,
-//             data: xAxis,
-//             selectedMode: !silent
-//         },
-//         series : [
-//             {
-//                 name: columnName,
-//                 type: 'pie',
-//                 // radius : '55%',
-//                 // center: ['50%', '60%'],
-//                 data: serieses[0].value,
-//                 label: { show: !silent },
-//                 labelLine: { show: !silent },
-//                 itemStyle: {
-//                     emphasis: {
-//                         shadowBlur: 10,
-//                         shadowOffsetX: 0,
-//                         shadowColor: 'rgba(0, 0, 0, 0.5)'
-//                     }
-//                 },
-//                 silent
-//             }
-//         ]
-//     };
-//     return o;
-// }
-
-// function lineConfig(option, styleConfig, silent, thumbnail) {
-//     const { serieses, xTitle, yTitle } = option;
-
-//     let o = {
-//         animation: !thumbnail,
-//         grid: {
-//             left: thumbnail ? 10 : '10%',
-//             right: thumbnail ? 10 : '10%',
-//             top: thumbnail ? 10 : 60,
-//             bottom: thumbnail ? 10 : 60,
-//             containLabel: !thumbnail
-//         },
-//         tooltip: {
-//             show: !silent && !thumbnail,
-//             trigger: 'axis',
-//             axisPointer: {
-//                 type: 'cross'
-//             }
-//         },
-//         legend: {
-//             show: !thumbnail,
-//             selectedMode: !silent
-//         },
-//         xAxis:  {
-//             show: !thumbnail,
-//             name: xTitle,
-//             type: 'time'
-//         },
-//         yAxis: {
-//             show: !thumbnail,
-//             name: yTitle,
-//             type: 'value'
-//         },
-        
-//         series: serieses.map(s => {
-//             return {
-//                 name: s.name,
-//                 type: 'line',
-//                 data: s.mdata.map(m => {
-//                     return [m.date, m.value]
-//                 }),
-//                 showSymbol: !thumbnail,
-//                 silent
-//             }
-//         })
-//     };
-
-//     return o;
-// }
-
-// function scatterConfig(option, styleConfig, silent, thumbnail) {
-//     const { serieses, xTitle, yTitle } = option;
-//     let o = {
-//         animation: !thumbnail,
-//         grid: {
-//             left: thumbnail ? 10 : '10%',
-//             right: thumbnail ? 10 : '10%',
-//             top: thumbnail ? 10 : 60,
-//             bottom: thumbnail ? 10 : 60,
-//             containLabel: !thumbnail
-//         },
-//         tooltip : {
-//             show: !silent && !thumbnail,
-//             showDelay : 0,
-//             axisPointer:{
-//                 show: true,
-//                 type : 'cross',
-//                 lineStyle: {
-//                     type : 'dashed',
-//                     width : 1
-//                 }
-//             }
-//         },
-//         legend: {
-//             show: !thumbnail,
-//             selectedMode: !silent
-//         },
-//         xAxis : [
-//             {
-//                 show: !thumbnail,
-//                 type : 'value',
-//                 name: xTitle,
-//                 scale:true,
-//                 splitLine: {
-//                     show: false
-//                 }
-//             }
-//         ],
-//         yAxis : [
-//             {
-//                 show: !thumbnail,
-//                 type : 'value',
-//                 name: yTitle,
-//                 scale:true,
-//                 splitLine: {
-//                     show: false
-//                 }
-//             }
-//         ],
-//         series : serieses.map(s => {
-//             return {
-//                 name: s.name,
-//                 type: 'scatter',
-//                 data: s.mdata.map(m => {
-//                     return [m.date, m.value]
-//                 }),
-//                 silent
-//             }
-//         })
-//     };
-//     return o;
-// }
-
-// function aggregateTableConfig(option, styleConfig, silent, thumbnail) {
-//     const { columns, data } = option;
-//     let c = columns.map(_c => {
-//         if(_c.dataIndex === 'percent') {
-//             return { ..._c, render: (value, record, index) => ((+value*100).toFixed(2)) + '%'};
-//         }else {
-//             return {..._c, width: 100};
-//         }
-//     });
-//     let o = {
-//         columns: c,
-//         data: data.map((d, i) => {
-//             return { ...d, key: i}
-//         })
-//     };
-//     return o;
-// }
-
-// function tableViewConfig(option, styleConfig, silent, thumbnail) {
-//     const { columns, data } = option;
-//     const { table } = styleConfig || {};
-//     const {
-//         visibleIndex,
-//         aligns,
-//         widths,
-//         thousandsSeparatorColumns,
-//     } = table || {
-//         visibleIndex: false,
-//         aligns: {},
-//         widths: {},
-//         thousandsSeparatorColumns: [],
-//     };
-//     console.log(styleConfig);
-//     let c = columns.map(c => {
-//         let o = {
-//             key: c.name,
-//             title: c.label,
-//             dataIndex: c.name,
-//             width: widths? (widths[c.name] ? ( +widths[c.name] ) : 100 ) : 100,
-//             align: aligns ? (aligns[c.name] || 'left') : 'left',
-//         };
-//         if(c.type === 'time') {
-//             o.render = v => moment(v).format('YYYY-MM-DD');
-//         }
-//         return o;
-//     });
-//     if(visibleIndex) {
-//         c.unshift({
-//             key: '_index',
-//             title: '序号',
-//             render: (v, r, i) => i+1,
-//             width: 50,
-//             align: 'center'
-//         });
-//     }
-//     let o = {
-//         columns: c,
-//         data: data.map((d, i) => {
-//             return { ...d, key: i}
-//         })
-//     };
-//     return o;
-// }
-
-// function barXAxis(chartConfig, xAxis) {
-//     let data = xAxis;
-    
-//     if(chartConfig) {
-//         const { xAxis: cx } = chartConfig;
-//         const { column, granularity } = cx;
-//         const { label: cLabel, type: cType, value: cValue } = column;
-//         const { label: gLabel, value: gValue } = granularity;
-
-//         if(cType === 'time') {
-//             let s = GRANULARITY['time'];
-//             let g = s.find(d => d.value === gValue);
-//             data = xAxis.map(x => (g.replaceFunction && typeof g.replaceFunction === 'function') ? g.replaceFunction(x) : x);
-//         }
-//     }
-    
-//     return data;
-// }
+}

+ 3 - 29
src/components/chartDesigner/content.jsx

@@ -13,6 +13,7 @@ import OtherConfigForm from './sections/otherConfigForm'
 import EchartsView from './charts/echartsView'
 import EchartsView from './charts/echartsView'
 import ToolBar from './sections/toolbar'
 import ToolBar from './sections/toolbar'
 import { connect } from 'dva'
 import { connect } from 'dva'
+import EmptyContent from '../common/emptyContent/index'
 import './content.less'
 import './content.less'
 const { Header, Sider, Content, Footer } = Layout
 const { Header, Sider, Content, Footer } = Layout
 const { TabPane } = Tabs
 const { TabPane } = Tabs
@@ -33,20 +34,6 @@ class ChartDesignerContent extends React.Component {
         }
         }
     }
     }
 
 
-    // componentDidMount() {
-    //     window.setTimeout(() => {
-    //         this.setState({
-    //             animation: true
-    //         });
-    //     }, 2000);
-    //     this.refreshContentSize();
-    //     window.addEventListener('resize', this.refreshContentSize);
-    // }
-
-    // componentWillUnmount() {
-    //     window.removeEventListener('resize', this.refreshContentSize);
-    // }
-
     static getDerivedStateFromProps(nextProps, nextState) {
     static getDerivedStateFromProps(nextProps, nextState) {
         const { chartDesigner, main } = nextProps;
         const { chartDesigner, main } = nextProps;
         const isOwner = chartDesigner.creatorCode === main.currentUser.code;
         const isOwner = chartDesigner.creatorCode === main.currentUser.code;
@@ -61,21 +48,6 @@ class ChartDesignerContent extends React.Component {
         }
         }
     }
     }
 
 
-    // /**
-    //  * 设置图表区域大小
-    //  */
-    // refreshContentSize = () => {
-    //     let contentEl = findDOMNode(this.refs.contentEl);
-    //     if(!contentEl) { return; }
-    //     let contentLayout = contentEl.getBoundingClientRect();
-    //     this.setState({
-    //         contentSize: {
-    //             width: contentLayout.width,
-    //             height: contentLayout.height
-    //         }
-    //     });
-    // }
-
     onCollapse = () => {
     onCollapse = () => {
         this.setState({
         this.setState({
             collapsed: !this.state.collapsed,
             collapsed: !this.state.collapsed,
@@ -112,6 +84,8 @@ class ChartDesignerContent extends React.Component {
         }else if(viewType === 'scatter') {
         }else if(viewType === 'scatter') {
             configForm = (<ScatterConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             configForm = (<ScatterConfigForm autoRefresh={autoRefresh} formItemLayout={formItemLayout}/>);
             chartView = (<EchartsView optionConfig={{ animation }}/>);
             chartView = (<EchartsView optionConfig={{ animation }}/>);
+        }else {
+            chartView = <EmptyContent />
         }
         }
 
 
         return (
         return (

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

@@ -1,5 +1,5 @@
 import React from 'react'
 import React from 'react'
-import { Form, Select, Tag, Cascader, Dropdown, Menu, InputNumber } from 'antd'
+import { Form, Select, Tag, Cascader, Dropdown, Menu } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import GAUGE from './gauge.json'
 import GAUGE from './gauge.json'
 import GRANULARITY from './granularity.json'
 import GRANULARITY from './granularity.json'
@@ -181,13 +181,6 @@ const BarConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout })
 					})}
 					})}
 				</Select>
 				</Select>
 			</FormItem>
 			</FormItem>
-			<FormItem label='阈值' {...formItemLayout}>
-				<InputNumber min={0} defaultValue={chartDesigner.barConfig.threshold} onBlur={(e) => {
-					if(chartDesigner.barConfig.threshold !== e.target.value) {
-						dispatch({ type: 'chartDesigner/changeField', name: 'barConfig', value: { ...chartDesigner.barConfig, threshold: e.target.value }, autoRefresh });
-					}
-				}}/>
-			</FormItem>
 		</Form>
 		</Form>
 	);
 	);
 }
 }

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

@@ -1,5 +1,5 @@
 import React from 'react'
 import React from 'react'
-import { Form, Select, Tag, Cascader, Dropdown, Menu, InputNumber  } from 'antd'
+import { Form, Select, Tag, Cascader, Dropdown, Menu } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import '../../../models/chartDesigner'
 import '../../../models/chartDesigner'
 import GAUGE from './gauge.json'
 import GAUGE from './gauge.json'
@@ -180,13 +180,6 @@ const LineConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout }
 					})}
 					})}
 				</Select>
 				</Select>
 			</FormItem>
 			</FormItem>
-			<FormItem label='阈值' {...formItemLayout}>
-				<InputNumber min={0} defaultValue={chartDesigner.lineConfig.threshold} onBlur={(e) => {
-					if(chartDesigner.lineConfig.threshold !== e.target.value) {
-						dispatch({ type: 'chartDesigner/changeField', name: 'lineConfig', value: { ...chartDesigner.lineConfig, threshold: e.target.value }, autoRefresh });
-					}
-				}}/>
-			</FormItem>
 		</Form>
 		</Form>
 	);
 	);
 }
 }

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

@@ -1,5 +1,5 @@
 import React from 'react'
 import React from 'react'
-import { Form, Tag, Cascader, Dropdown, Menu, InputNumber } from 'antd'
+import { Form, Tag, Cascader, Dropdown, Menu } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import '../../../models/chartDesigner'
 import '../../../models/chartDesigner'
 import GAUGE from './gauge.json'
 import GAUGE from './gauge.json'
@@ -162,13 +162,6 @@ const PieConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayout })
 				>
 				>
 				</Cascader>
 				</Cascader>
 			</FormItem>
 			</FormItem>
-			<FormItem label='阈值' {...formItemLayout}>
-				<InputNumber min={0} defaultValue={chartDesigner.pieConfig.threshold} onBlur={(e) => {
-					if(chartDesigner.pieConfig.threshold !== e.target.value) {
-						dispatch({ type: 'chartDesigner/changeField', name: 'pieConfig', value: { ...chartDesigner.pieConfig, threshold: e.target.value }, autoRefresh });
-					}
-				}}/>
-			</FormItem>
 		</Form>
 		</Form>
 	);
 	);
 }
 }

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

@@ -1,5 +1,5 @@
 import React from 'react'
 import React from 'react'
-import { Form, Select, Tag, Cascader, Dropdown, Menu, InputNumber } from 'antd'
+import { Form, Select, Tag, Cascader, Dropdown, Menu } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import GAUGE from './gauge.json'
 import GAUGE from './gauge.json'
 const FormItem = Form.Item
 const FormItem = Form.Item
@@ -181,13 +181,6 @@ const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayou
 					})}
 					})}
 				</Select>
 				</Select>
 			</FormItem>
 			</FormItem>
-			<FormItem label='阈值' {...formItemLayout}>
-				<InputNumber min={0} defaultValue={chartDesigner.scatterConfig.threshold} onBlur={(e) => {
-					if(chartDesigner.scatterConfig.threshold !== e.target.value) {
-						dispatch({ type: 'chartDesigner/changeField', name: 'scatterConfig', value: { ...chartDesigner.scatterConfig, threshold: e.target.value }, autoRefresh });
-					}
-				}}/>
-			</FormItem>
 		</Form>
 		</Form>
 	);
 	);
 }
 }

+ 0 - 120
src/components/common/CardList.jsx

@@ -1,120 +0,0 @@
-import React from 'react'
-import { Card, Row, Col } from 'antd'
-import { connect } from 'dva'
-import Ellipsis from 'ant-design-pro/lib/Ellipsis'
-import moment from 'moment'
-import Thumbnail from './thumbnail'
-import './CardList.less'
-const CardGrid = Card.Grid
-
-/**
- * 尝试抽出generateCard()作为一个公共模块
- * 需要指定以下props:
- * mode 模式,分为主页、报表、图表模式 (homepage, dashboard, chart)
- * list 数据所在的列表,存于models中
- * filterLabel 生成列表时使用的过滤器字段
- * onDistribute
- * onTransfer
- * onDelete
- * 
- * 备注: chart和dashboard的thumbnail部分需要抽取出来形成公用的
- * 
- * @class CardList
- * @extends {React.Component}
- */
-
-class CardList extends React.Component {
-    
-    generateCard() {
-        const { mode, dispatch, list, type } = this.props;
-        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
-        let filterLabel = (mode !== 'homepage') ? list.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') : ""; // 添加转义符号
-
-        let cards = list.filter(l => {
-            let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
-            return (l.name || '').search(reg) !== -1 || (l.description || '').search(reg) !== -1;
-        }).sort((a, b) => {
-            return new Date(b.recentTime) - new Date(a.recentTime)
-        }).map( (l, i) => (
-            <CardGrid className={(type === 'dashboard')? 'recent-dashboard-card' : 'recent-chart-card'} key={i} onClick={() => {
-                this.setState({ selectedRecord: l })
-            }}>
-                <Card
-                    title={
-                        <Row type='flex' justify='space-between'>
-                            <Col span={21} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} >
-                                { filterLabel ?
-                                    ((l.name || '').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
-                                        )
-                                    }
-                                    )) : l.name
-                                }
-                            </Col>
-                            <Col style={{ textAlign: 'right' }} span={3} >
-                                {/* {<Icon type='star-o'/>} */}
-                            </Col>
-                        </Row>
-                    }
-                    cover={
-                        <Col className='cover-body'>
-                            <Row className='thumb' onClick={() => {
-                                if(type === 'dashboard') {
-                                    dispatch({ type: 'dashboardDesigner/reset' });
-                                    dispatch({ type: 'main/redirect', path: '/dashboard/' + l.code });
-                                }else {
-                                    dispatch({ type: 'chartDesigner/reset' });
-                                    dispatch({ type: 'main/redirect', path: '/chart/' + l.code });
-                                }
-                            }}>
-                                <Thumbnail mode={type} type={l.type} code={l.code} option={l.chartOption} thumbnail={l.thumbnail}/> 
-                            </Row>
-                            {type === 'chart' && <Row className='desc'>
-                                <Ellipsis tooltip={l.description.length > 16} lines={2}>{
-                                    <span>
-                                    { filterLabel ?
-                                        ((l.description || '').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
-                                            )
-                                        }
-                                        )) : l.description
-                                    }
-                                </span>
-                                }</Ellipsis>
-                            </Row>}
-                            <Row className='footer' type='flex' justify='end' align='bottom'>
-                                <Col style={{ textAlign: 'left', lineHeight: '30px' }} span={22}>
-                                    <Row>{l.createBy} {moment(l.createTime).format('YYYY-MM-DD')}</Row>
-                                </Col>
-                                <Col span={2} style={{ textAlign: 'right' }}>
-                                    {/* <Dropdown overlay={operationMenu} trigger={['click']}>
-                                        <Icon type="ellipsis" />
-                                    </Dropdown> */}
-                                </Col>
-                            </Row>
-                        </Col>
-                    }
-                >
-                </Card>
-            </CardGrid>
-        ));
-        if(cards.length === 0) {
-            cards = <div style={{ padding: '7px', textAlign: 'center', fontSize: '14px', color: 'rgba(0, 0, 0, 0.45)' }}>暂无数据</div>
-            return cards
-        }
-        
-        return cards.slice(0,3); //此处为了开发方便,限制了只显示前3个,之后可能要做成分页
-    }
-
-    render() {
-        return this.generateCard()
-    }
-}
-
-export default connect(({ present: { dashboard, homepage, chart } }) =>  { return { homepage, dashboard, chart }})(CardList)

+ 0 - 146
src/components/common/CardList.less

@@ -1,146 +0,0 @@
-.recent-chart-card {
-    width: 207px;
-    text-align: center;
-    margin: 5px;
-    padding: 0;
-
-    .ant-card-head {
-        min-height: 20px;
-        cursor: default;
-        .ant-card-head-title {
-            font-size: 14px;
-            padding: 6px 0;
-            .ant-row-flex {
-                flex: 1;
-            }
-            .anticon {
-                cursor: pointer;
-            }
-        }
-    }
-
-    .ant-card-cover {
-        height: 200px;
-        .cover-body {
-            padding: 10px;
-            .thumb {
-                height: 132px;
-                .deny-body {
-                    height: 100%;
-                    width: 100%;
-                    display: flex;
-                    position: absolute;
-                    text-align: center;
-                    justify-content: center;
-                    flex-direction: column;
-                    z-index: 1;
-                    .deny-tip {
-                        height: 40px;
-                        line-height: 40px;
-                        background: rgba(218, 218, 218, 0.5);
-                        border: 2px solid #aaaaaa;
-                        font-weight: bold;
-                    }
-                }
-                cursor: pointer;
-                canvas {
-                    cursor: pointer;
-                }
-                .table-default {
-                    background-image: url(../../../static/images/table-default.png);
-                    width: 100%;
-                    height: 100%;
-                    background-position: center;
-                    background-size: contain;
-                    background-repeat: no-repeat;
-                    cursor: pointer;
-                }
-                .chart-default {
-                    background-image: url(../../../static/images/chart-default.png);
-                    width: 100%;
-                    height: 100%;
-                    background-position: center;
-                    background-size: contain;
-                    background-repeat: no-repeat;
-                    cursor: pointer;
-                    opacity: .3;
-                }
-            }
-            .desc {
-                text-align: left;
-                height: 41px;
-            }
-            .footer {
-                margin-top: 6px;
-                .anticon {
-                    font-size: 24px;
-                }
-            }
-        }
-    }
-}
-
-.recent-dashboard-card {
-    width: 507px;
-    text-align: center;
-    margin: 5px;
-    padding: 0;
-
-    .ant-card-head {
-        min-height: 20px;
-        cursor: default;
-        .ant-card-head-title {
-            font-size: 14px;
-            padding: 6px 0;
-            .ant-row-flex {
-                flex: 1;
-            }
-            .anticon {
-                cursor: pointer;
-            }
-        }
-    }
-
-    .ant-card-cover {
-        height: 247px;
-        .cover-body {
-            padding: 10px;
-            .thumb {
-                height: 222px;
-                cursor: pointer;
-                canvas {
-                    cursor: pointer;
-                }
-                .table-default {
-                    background-image: url(../../../static/images/table-default.png);
-                    width: 100%;
-                    height: 100%;
-                    background-position: center;
-                    background-size: contain;
-                    background-repeat: no-repeat;
-                    cursor: pointer;
-                }
-                .dashboard-default {
-                    background-image: url(../../../static/images/dashboard-default.png);
-                    width: 100%;
-                    height: 100%;
-                    background-position: center;
-                    background-size: contain;
-                    background-repeat: no-repeat;
-                    cursor: pointer;
-                    opacity: .3;
-                }
-            }
-            .desc {
-                text-align: left;
-                height: 41px;
-            }
-            .footer {
-                margin-top: 6px;
-                .anticon {
-                    font-size: 24px;
-                }
-            }
-        }
-    }
-}

+ 7 - 0
src/components/common/emptyContent/index.jsx

@@ -0,0 +1,7 @@
+import React from 'react'
+
+const Content = () => {
+    return (<div className="ant-empty ant-empty-normal"><div className="ant-empty-image"><img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K"/></div><p className="ant-empty-description">暂无数据</p></div>) 
+}
+
+export default Content

+ 5 - 3
src/components/common/selectUserBox/selectUserBox.jsx

@@ -20,10 +20,13 @@ class AddGroupMemberBox extends React.Component {
 
 
     fetchUserData = (keyword) => {
     fetchUserData = (keyword) => {
         this.setState({ userData: [], fetching: true }, () => {
         this.setState({ userData: [], fetching: true }, () => {
-            const body = keyword || '';
+            let condition = keyword || '';
             service.fetch({
             service.fetch({
                 url: URLS.USER_QUERY,
                 url: URLS.USER_QUERY,
-                body: body,
+                method: 'GET',
+                body: {
+                    condition
+                },
             }).then(r => {
             }).then(r => {
                 if(!r.err && r.data.code > 0) {
                 if(!r.err && r.data.code > 0) {
                     return r;
                     return r;
@@ -32,7 +35,6 @@ class AddGroupMemberBox extends React.Component {
                     throw obj;
                     throw obj;
                 }
                 }
             }).then(r => {
             }).then(r => {
-                console.log('获得用户数据', body, r);
                 const resData = r.data.data || [];
                 const resData = r.data.data || [];
                 this.setState({
                 this.setState({
                     userData: resData.map(d => ({
                     userData: resData.map(d => ({

+ 19 - 3
src/components/dashboard/layout.jsx

@@ -1,5 +1,6 @@
 import React from 'react'
 import React from 'react'
-import { Layout } from 'antd'
+import { connect } from 'dva'
+import { Layout, Spin, Icon } from 'antd'
 import DashboardMenu from './menu'
 import DashboardMenu from './menu'
 import DashboardList from './list'
 import DashboardList from './list'
 import './layout.less'
 import './layout.less'
@@ -14,11 +15,15 @@ class DashboardLayout extends React.Component {
     }
     }
 
 
     render() {
     render() {
+        const { loading } = this.props;
         return <Layout
         return <Layout
             className='layout-dashboard'
             className='layout-dashboard'
         >
         >
             <Sider width={300}>
             <Sider width={300}>
-                <DashboardMenu />
+                <DashboardMenu mode='manage'/>
+                <div style={{ display: loading ? 'block' : 'none', position: 'absolute', height: '100%', width: '100%', top: '0px', zIndex: '4', background: 'rgba(51,51,51,.1)' }}>
+                    <Spin style={{ display: 'inline-block', position: 'absolute', top: '50%', left: '50%', margin: '-10px' }} indicator={<Icon type="loading" style={{ fontSize: 24 }} spin />}/>
+                </div>
             </Sider>
             </Sider>
             <Content>
             <Content>
                 <DashboardList />
                 <DashboardList />
@@ -26,5 +31,16 @@ class DashboardLayout extends React.Component {
         </Layout>
         </Layout>
     }
     }
 }
 }
+function mapStateToProps({ present: { loading }}) {
+    let effectsArr = ['dashboard/remoteMenuTree', 'dashboard/remoteAddMenu', 'dashboard/remoteDeleteMenu'];
+    let flag = false;
+    for(let i = 0; i < effectsArr.length; i++) {
+        if(loading.effects[effectsArr[i]]) {
+            flag = true;
+            break;
+        }
+    }
 
 
-export default DashboardLayout
+    return { loading: flag }
+}
+export default connect(mapStateToProps)(DashboardLayout)

+ 8 - 1
src/components/dashboard/list.less

@@ -1,7 +1,10 @@
 .dashboard-view {
 .dashboard-view {
     .dashboard-body {
     .dashboard-body {
         padding: 0;
         padding: 0;
-        .ant-card-head {
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        &>.ant-card-head {
             padding: 0 10px;
             padding: 0 10px;
             .dashboard-tools {
             .dashboard-tools {
                 flex: 1;
                 flex: 1;
@@ -30,6 +33,10 @@
                 }
                 }
             }
             }
         }
         }
+        &>.ant-card-body {
+            flex: 1;
+            overflow: auto;
+        }
     }
     }
     .ant-card-body {
     .ant-card-body {
         padding: 0;
         padding: 0;

+ 63 - 46
src/components/dashboard/menu.jsx

@@ -1,6 +1,6 @@
 import React from 'react'
 import React from 'react'
 import { connect } from 'dva'
 import { connect } from 'dva'
-import { Tree, Input, Button, Icon, Spin } from 'antd'
+import { Tree, Input, Button, Icon } from 'antd'
 import DeleteBox from '../common/deleteBox/deleteBox'
 import DeleteBox from '../common/deleteBox/deleteBox'
 import './menu.less'
 import './menu.less'
 const { TreeNode } = Tree
 const { TreeNode } = Tree
@@ -23,18 +23,26 @@ class DashboardMenu extends React.Component {
     }
     }
 
 
     generateMenu(tree, regLabel) {
     generateMenu(tree, regLabel) {
-        const { dispatch } = this.props;
+        const { mode, dispatch } = this.props;
         const { editingKey } = this.state;
         const { editingKey } = this.state;
-        return tree.filter(t => t.type === 'menu').sort((a, b) => a.index - b.index).map(t => {
+        return tree.filter(t => (mode === 'view' || t.type === 'menu')).sort((a, b) => a.index - b.index).map(t => {
             let title = <div className='node-title'>
             let title = <div className='node-title'>
                 <span>{ (t.code !== editingKey) ?
                 <span>{ (t.code !== editingKey) ?
-                   ( regLabel ? ((t.name || '').split(new RegExp(`(${regLabel})`, 'i')).map((fragment, i) => {
-                        return (
-                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'), '\\$1') === regLabel.toLowerCase() ?
-                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
-                            fragment
-                        )
-                    })) : <div className='label'>{t.name}</div> ) : ( <div className='input'>
+                   ( regLabel ? ( <span style={{ fontWeight: t.type === 'dashboard' ? 'bold' : 'normal' }}>
+                        { t.type === 'dashboard' && <Icon style={{ marginRight: '8px' }} type="pushpin" /> }
+                        { (t.name || '').split(new RegExp(`(${regLabel})`, 'i')).map((fragment, i) => {
+                            return (
+                                fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'), '\\$1') === regLabel.toLowerCase() ?
+                                <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                                fragment
+                            )
+                        }) }                       
+                   </span> ) : <div className='label'>
+                        <span style={{ fontWeight: t.type === 'dashboard' ? 'bold' : 'normal' }}>
+                            { t.type === 'dashboard' && <Icon style={{ marginRight: '8px' }} type="pushpin" /> }
+                            { t.name }
+                        </span>
+                    </div> ) : ( <div className='input'>
                     <Input
                     <Input
                         size="small"
                         size="small"
                         defaultValue={t.name}
                         defaultValue={t.name}
@@ -55,7 +63,7 @@ class DashboardMenu extends React.Component {
                     />
                     />
                 </div> )
                 </div> )
                 }</span>
                 }</span>
-                <div className='tools'>
+                {mode !== 'view' && <div className='tools'>
                     {t.code !== editingKey && <Icon type='edit' onClick={() => {
                     {t.code !== editingKey && <Icon type='edit' onClick={() => {
                         this.setState({
                         this.setState({
                             editingKey: t.code
                             editingKey: t.code
@@ -67,7 +75,7 @@ class DashboardMenu extends React.Component {
                             visibleDeleteBox: true,
                             visibleDeleteBox: true,
                         });
                         });
                     }}/>}
                     }}/>}
-                </div>
+                </div>}
             </div>
             </div>
 
 
             return <TreeNode title={title} key={t.code}>
             return <TreeNode title={title} key={t.code}>
@@ -82,21 +90,40 @@ class DashboardMenu extends React.Component {
     }
     }
 
 
     onExpand = (keys) => {
     onExpand = (keys) => {
-        const { dispatch } = this.props;
-        dispatch({ type: 'dashboard/setFields', fields: [
-            { name: 'menuExpandedKeys', value: keys },
-            { name: 'menuAutoExpandParent', value: false },
-        ] });
+        const { mode, dispatch } = this.props;
+        if(mode === 'view') {
+            dispatch({ type: 'home/setFields', fields: [
+                { name: 'menuExpandedKeys', value: keys },
+                { name: 'menuAutoExpandParent', value: false },
+            ] });
+        }else {
+            dispatch({ type: 'dashboard/setFields', fields: [
+                { name: 'menuExpandedKeys', value: keys },
+                { name: 'menuAutoExpandParent', value: false },
+            ] });
+        }
     }
     }
 
 
     onSelect = (selectedKeys, info) => {
     onSelect = (selectedKeys, info) => {
-        const { dispatch } = this.props;
-        dispatch({ type: 'dashboard/setField', name: 'menuSelectedKeys', value: selectedKeys })
-        if(selectedKeys.length === 1) {
-            if(selectedKeys[0] === '-1') {
-                dispatch({ type: 'dashboard/fetchList', mandatory: true });
-            }else {
-                dispatch({ type: 'dashboard/remoteMenuDashboardList', menuCode: selectedKeys[0] });
+        const { mode, dashboard, dispatch } = this.props;
+        const { menuList } = dashboard;
+        if(mode === 'view') {
+            // dispatch({ type: 'home/setField', name: 'menuSelectedKeys', value: selectedKeys })
+            let selectedMenu = menuList.find(l => l.code === selectedKeys[0]);
+            if(selectedMenu && selectedMenu.type === 'dashboard') {
+                dispatch({ type: 'home/openTab', tab: {
+                    code: selectedMenu.code,
+                    name: selectedMenu.name
+                } })
+            }
+        }else {
+            dispatch({ type: 'dashboard/setField', name: 'menuSelectedKeys', value: selectedKeys })
+            if(selectedKeys.length === 1) {
+                if(selectedKeys[0] === '-1') {
+                    dispatch({ type: 'dashboard/fetchList', mandatory: true });
+                }else {
+                    dispatch({ type: 'dashboard/remoteMenuDashboardList', menuCode: selectedKeys[0] });
+                }
             }
             }
         }
         }
     }
     }
@@ -107,7 +134,7 @@ class DashboardMenu extends React.Component {
         dispatch({ type: 'dashboard/setFields', fields: [
         dispatch({ type: 'dashboard/setFields', fields: [
             { name: 'menuExpandedKeys', value: expandedKeys },
             { name: 'menuExpandedKeys', value: expandedKeys },
             { name: 'menuFilterLabel', value },
             { name: 'menuFilterLabel', value },
-            { name: 'autoExpandParent', value: true },
+            { name: 'menuAutoExpandParent', value: true },
         ] });
         ] });
     }
     }
 
 
@@ -154,21 +181,20 @@ class DashboardMenu extends React.Component {
     }
     }
 
 
     render() {
     render() {
-        const { dashboard, dispatch, loading } = this.props;
+        const { mode, home, dashboard, dispatch } = this.props;
         const { visibleDeleteBox, selectedMenu } = this.state;
         const { visibleDeleteBox, selectedMenu } = this.state;
-        const { menuTree, menuFilterLabel, menuExpandedKeys, menuSelectedKeys, menuAutoExpandParent } = dashboard;
+        const { menuTree } = dashboard;
+        const { menuFilterLabel, menuExpandedKeys, menuSelectedKeys, menuAutoExpandParent } = mode === 'view' ? home : dashboard;
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         const regLabel = menuFilterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         const regLabel = menuFilterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
 
 
-        return <div className='menu-container'>
-            <div style={{ display: loading ? 'block' : 'none', position: 'absolute', height: '100%', width: '100%', zIndex: '4', background: 'rgba(51,51,51,.1)' }}>
-                <Spin style={{ display: 'inline-block', position: 'absolute', top: '50%', left: '50%', margin: '-10px' }} indicator={<Icon type="loading" style={{ fontSize: 24 }} spin />}/>
-            </div>
-            <div className='menu-buttons'>
+        return <div className='menu-container' style={ mode === 'view' ? { paddingTop: 0 } : { paddingTop: '88px' } }>
+            
+            {mode !== 'view' && <div className='menu-buttons'>
                 <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onAddClick}>新增目录</Button>
                 <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onAddClick}>新增目录</Button>
                 {/* <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onModifyClick}>修改目录</Button> */}
                 {/* <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onModifyClick}>修改目录</Button> */}
-            </div>
-            <div className='menu-search'>
+            </div>}
+            {mode !== 'view' && <div className='menu-search'>
                 <Search
                 <Search
                     defaultValue={menuFilterLabel}
                     defaultValue={menuFilterLabel}
                     placeholder='搜索'
                     placeholder='搜索'
@@ -178,7 +204,7 @@ class DashboardMenu extends React.Component {
                 <Button onClick={() => {
                 <Button onClick={() => {
                     dispatch({ type: 'dashboard/remoteMenuTree', mandatory: true });
                     dispatch({ type: 'dashboard/remoteMenuTree', mandatory: true });
                 }}><Icon type='sync' /></Button>
                 }}><Icon type='sync' /></Button>
-            </div>
+            </div>}
             <div className='menu-content'>
             <div className='menu-content'>
                 <Tree
                 <Tree
                     inlineIndent={8}
                     inlineIndent={8}
@@ -209,16 +235,7 @@ class DashboardMenu extends React.Component {
     }
     }
 }
 }
 
 
-function mapStateToProps({ present: { loading, dashboard }}) {
-    let effectsArr = ['dashboard/remoteMenuTree', 'dashboard/remoteAddMenu', 'dashboard/remoteDeleteMenu'];
-    let flag = false;
-    for(let i = 0; i < effectsArr.length; i++) {
-        if(loading.effects[effectsArr[i]]) {
-            flag = true;
-            break;
-        }
-    }
-
-    return { dashboard, loading: flag }
+function mapStateToProps({ present: { dashboard, home }}) {
+    return { dashboard, home }
 }
 }
 export default connect(mapStateToProps)(DashboardMenu)
 export default connect(mapStateToProps)(DashboardMenu)

+ 1 - 1
src/components/dashboard/menu.less

@@ -1,6 +1,6 @@
 .menu-container {
 .menu-container {
     height: 100%;
     height: 100%;
-    padding-top: 88px;
+    // padding-top: 88px;
     .menu-buttons {
     .menu-buttons {
         height: 32px;
         height: 32px;
         padding: 0 8px;
         padding: 0 8px;

+ 6 - 5
src/components/dashboard/shareKeyView.jsx

@@ -1,10 +1,11 @@
 import React from 'react'
 import React from 'react'
-import Layout from '../dashboardDesigner/layout'
+import { connect } from 'dva'
+import DashboardDesigner from '../dashboardDesigner/layout'
 
 
-class View extends React.Component {
+class DashboardView extends React.Component {
     render() {
     render() {
-        return <Layout { ...this.props } isShareKeyView={true} ></Layout>
+        const { code } = this.props.match.params;
+        return <DashboardDesigner dashboardDesigner={this.props.dashboardDesigner} code={code} isShareKeyView={true}/>
     }
     }
 }
 }
-
-export default View
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(DashboardView)

+ 6 - 5
src/components/dashboard/shareView.jsx

@@ -1,10 +1,11 @@
 import React from 'react'
 import React from 'react'
-import Layout from '../dashboardDesigner/layout'
+import { connect } from 'dva'
+import DashboardDesigner from '../dashboardDesigner/layout'
 
 
-class DashboardShareView extends React.Component {
+class DashboardView extends React.Component {
     render() {
     render() {
-        return <Layout { ...this.props } isShareView={true} ></Layout>
+        const { code } = this.props.match.params;
+        return <DashboardDesigner dashboardDesigner={this.props.dashboardDesigner} code={code} isShareView={true}/>
     }
     }
 }
 }
-
-export default DashboardShareView
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(DashboardView)

+ 12 - 0
src/components/dashboard/view.jsx

@@ -0,0 +1,12 @@
+import React from 'react'
+import { connect } from 'dva'
+import DashboardDesigner from '../dashboardDesigner/layout'
+
+class DashboardView extends React.Component {
+    render() {
+        const { code } = this.props.match.params;
+        console.log(code);
+        return <DashboardDesigner dashboardDesigner={this.props.dashboardDesigner} code={code}/>
+    }
+}
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(DashboardView)

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

@@ -85,7 +85,7 @@ class ChartView extends React.Component {
                 }
                 }
             }
             }
         }else if(viewType === 'richText') { // 富文本类型
         }else if(viewType === 'richText') { // 富文本类型
-            children = <RichTextEditor content={content} onContentChange={(content) => {
+            children = <RichTextEditor readOnly={!editMode} content={content} onContentChange={(content) => {
                 dispatch({ type: 'dashboardDesigner/modifyItem', fields: { code: item.code, content } });
                 dispatch({ type: 'dashboardDesigner/modifyItem', fields: { code: item.code, content } });
             }}/>
             }}/>
         }else {
         }else {

+ 110 - 19
src/components/dashboardDesigner/chooseChartBox.jsx

@@ -1,11 +1,12 @@
 import React from 'react'
 import React from 'react'
 import '../../models/dashboardDesigner'
 import '../../models/dashboardDesigner'
-import { Modal, Radio, Row, Col, Table, Input, message } from 'antd'
+import { Modal, Radio, Row, Col, Table, Input, Select, message, DatePicker } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import moment from 'moment'
 import moment from 'moment'
 import 'braft-editor/dist/braft.css'
 import 'braft-editor/dist/braft.css'
 import './chooseChartBox.less'
 import './chooseChartBox.less'
 const { Search } = Input
 const { Search } = Input
+const { RangePicker } = DatePicker
 
 
 class ChooseChartBox extends React.Component {
 class ChooseChartBox extends React.Component {
 
 
@@ -53,12 +54,18 @@ class ChooseChartBox extends React.Component {
         }
         }
     }
     }
 
 
+    generateFilterItems = () => {
+        const { filterItems } = this.props.chart;
+        return filterItems.map(t => <Select.Option key={t.name}  value={t.name}>{t.label}</Select.Option>);
+    }
+
     render() {
     render() {
-        const { main, visibleBox, hideBox, dashboardDesigner, chart } = this.props;
+        const { main, visibleBox, hideBox, dashboardDesigner, chart, dispatch } = this.props;
         const { selectedRecord, screenWidth, screenHeight } = this.state;
         const { selectedRecord, screenWidth, screenHeight } = this.state;
         const tableBodyWidth = screenWidth * 0.8 - 10 - 10 - 18;
         const tableBodyWidth = screenWidth * 0.8 - 10 - 10 - 18;
         const tableBodyHeight = screenHeight * 0.8 - 65 - 53 - 38 - 130;
         const tableBodyHeight = screenHeight * 0.8 - 65 - 53 - 38 - 130;
         const tableRowHeight = 38;
         const tableRowHeight = 38;
+        const { filterItem } = dashboardDesigner;
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         let filterLabel = this.state.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         let filterLabel = this.state.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         const columns = [{
         const columns = [{
@@ -81,7 +88,7 @@ class ChooseChartBox extends React.Component {
                 return <div>
                 return <div>
                     <div>
                     <div>
                         <span>
                         <span>
-                            { filterLabel ?
+                            { filterLabel && filterItem.name === 'name' ?
                                 (text.split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                 (text.split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                     return (
                                     return (
                                         fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
                                         fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
@@ -99,7 +106,25 @@ class ChooseChartBox extends React.Component {
             title: '创建人',
             title: '创建人',
             dataIndex: 'creatorName',
             dataIndex: 'creatorName',
             key: 'creatorName',
             key: 'creatorName',
-            width: 100
+            width: 100,
+            render: (text, record) => {
+                return <div>
+                    <div>
+                        <span>
+                            { filterLabel && filterItem.name === 'creatorName' ?
+                                (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>
+            }
         }, {
         }, {
             title: '创建时间',
             title: '创建时间',
             dataIndex: 'createTime',
             dataIndex: 'createTime',
@@ -114,7 +139,7 @@ class ChooseChartBox extends React.Component {
             render: (text, record) => {
             render: (text, record) => {
                 return (
                 return (
                     <span>
                     <span>
-                        { filterLabel ?
+                        { filterLabel && filterItem.name === 'description' ?
                             ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                             ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                 return (
                                 return (
                                     fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
                                     fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
@@ -135,16 +160,66 @@ class ChooseChartBox extends React.Component {
                 height='80%'
                 height='80%'
                 title={
                 title={
                     <Row>
                     <Row>
-                        <Col span={14}>选择图表</Col>
-                        <Col span={8}><Search 
-                            placeholder="请输入关键字"
-                            value={this.state.filterLabel}
-                            onChange={e => {
-                                this.setState({
-                                    filterLabel: e.target.value
-                                });
-                            }}
-                        /></Col>
+                        <Row>
+                            <Col >选择图表</Col>
+                        </Row>
+                        <Row type='flex' justify='end'>
+                            <Col style={{ padding: '0 1px', margin: '0 -5px' }}>
+                                <Select 
+                                    value={filterItem.name}
+                                    style={{ width: 120 }}
+                                    onChange={value => {
+                                        let item = chart.filterItems.find(i => i.name === value);
+                                        dispatch({ type: 'dashboardDesigner/setFilterItem', item });
+                                    }}
+                                >
+                                    {this.generateFilterItems()}
+                                </Select>
+                            </Col>
+                            <Col style={{ padding: '0 5px' }}>
+                                {filterItem.type === 'date' ? 
+                                    <RangePicker  
+                                        ranges={{
+                                            '今天': [moment().startOf('day'), moment().endOf('day')], 
+                                            '昨天': [moment().startOf('day').add(-1,'days'), moment().endOf('day')],
+                                            '近七天': [moment().startOf('day'),moment().endOf('day').add(6,'days')],
+                                            '本月': [moment().startOf('month'), moment().endOf('month')],
+                                            '本年': [moment().startOf('year'), moment().endOf('year')] 
+                                        }}
+                                        showTime={{ format: 'HH:mm' }}
+                                        format="YYYY-MM-DD HH:mm:ss"
+                                        onChange={e => {
+                                            //清空时间时
+                                            if(e.length === 0){
+                                                this.setState({
+                                                    filterLabel: ''
+                                                });
+                                            }
+                                        }}
+                                        onOk={e => {
+                                            //解析时间格式
+                                            let start = e[0]
+                                            let end = e[1]
+                                            let time = start._d.getTime() + "#" + end._d.getTime()
+                                            this.setState({
+                                                filterLabel: time
+                                            });
+                                        }}
+                                    >
+                                    </RangePicker> 
+                                    : 
+                                    <Search
+                                        placeholder="请输入关键字"
+                                        value={this.state.filterLabel}
+                                        onChange={e => {
+                                            this.setState({
+                                                filterLabel: e.target.value
+                                            });
+                                        }}
+                                    />
+                                }
+                            </Col>
+                        </Row>
                     </Row>
                     </Row>
                 }
                 }
                 visible={visibleBox}
                 visible={visibleBox}
@@ -159,10 +234,26 @@ class ChooseChartBox extends React.Component {
                         ...c,
                         ...c,
                         width: 100
                         width: 100
                     }))}
                     }))}
-                    dataSource={chart.list.filter(l => l.creatorCode === main.currentUser.code).map((l, i) => ({ ...l, key: i})).filter(l => {
-                        let regLabel = new RegExp('(' + filterLabel + '){1}', 'ig');
-                        return (l.name || '').search(regLabel) !== -1 || (l.description || '').search(regLabel) !== -1;
-                    })}
+                    dataSource={chart.list.map((l, i) => {
+                        let o = Object.assign({}, l);
+                        if(filterItem.type === 'date') {
+                            if(filterLabel===""){
+                                return { ...o, key: i };
+                            }else if(filterLabel.indexOf('#')>-1){
+                                let start = filterLabel.split('#')[0]
+                                let end = filterLabel.split('#')[1]
+                                let nowTime = new Date(o[filterItem.name]).getTime();
+                                if(nowTime>=start && nowTime<=end){
+                                    return { ...o, key: i};
+                                }
+                                return null 
+                            }else{
+                                return null 
+                            }
+                        }else {
+                            return ((o[filterItem.name] + '').search(new RegExp('(' + filterLabel + '){1}', 'ig')) > -1) ? { ...o, key: i } : null
+                        }
+                    }).filter(a => a!==null && a.creatorCode === main.currentUser.code)}
                     size='small'
                     size='small'
                     scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
                     scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
                     pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
                     pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}

+ 12 - 14
src/components/dashboardDesigner/configSider.jsx

@@ -15,7 +15,7 @@ class ConfigSider extends React.Component {
             visibleChooseChartBox: false,
             visibleChooseChartBox: false,
             visibleCusFilterBox: false,
             visibleCusFilterBox: false,
             copyDisabled: false,
             copyDisabled: false,
-            copyText: '生成链接'
+            copyText: '复制'
         };
         };
     }
     }
 
 
@@ -98,19 +98,17 @@ class ConfigSider extends React.Component {
                         if(copyDisabled || !dashboardDesigner.shareCode) {
                         if(copyDisabled || !dashboardDesigner.shareCode) {
                             return;
                             return;
                         }
                         }
-                        dispatch({ type: 'dashboardDesigner/encryptCode', shareCode: dashboardDesigner.shareCode }).then(key => {
-                            copy(window.location.origin + '/#/dashboard/share/' + key);
-                            this.setState({
-                                copyDisabled: true,
-                                copyText: '已复制到剪贴板'
-                            }, () => {
-                                setTimeout(() => {
-                                    this.setState({
-                                        copyDisabled: false,
-                                        copyText: '生成链接'
-                                    });
-                                }, 3000)
-                            });
+                        copy(dashboardDesigner.shareCode);
+                        this.setState({
+                            copyDisabled: true,
+                            copyText: '已复制'
+                        }, () => {
+                            setTimeout(() => {
+                                this.setState({
+                                    copyDisabled: false,
+                                    copyText: '复制'
+                                });
+                            }, 3000)
                         });
                         });
                     }}>{copyText}</span>}
                     }}>{copyText}</span>}
                 />
                 />

+ 35 - 29
src/components/dashboardDesigner/content.jsx

@@ -12,13 +12,14 @@ class DashboardDesignerContent extends React.Component {
     constructor(props) {
     constructor(props) {
         super(props);
         super(props);
         this.state = {
         this.state = {
-            contentSize: {
+            lastContentSize: {
                 scroll: false,
                 scroll: false,
                 width: 0,
                 width: 0,
                 height: 0,
                 height: 0,
             },
             },
             visibleFilterBox: false,
             visibleFilterBox: false,
         };
         };
+        this.contentRef=React.createRef();
     }
     }
 
 
     componentDidMount() {
     componentDidMount() {
@@ -53,9 +54,8 @@ class DashboardDesignerContent extends React.Component {
     }
     }
 
 
     getContentSize = () => {
     getContentSize = () => {
-        const { dashboardDesigner, isOwner, isShareView, isShareKeyView } = this.props;
-        const { editMode } = dashboardDesigner;
-        let contentEl = document.getElementsByClassName('viewlayout')[0];
+        const { lastContentSize } = this.state;
+        let contentEl = this.contentRef.current;
         if(!contentEl) {
         if(!contentEl) {
             return {
             return {
                 width: 0,
                 width: 0,
@@ -64,27 +64,27 @@ class DashboardDesignerContent extends React.Component {
         }
         }
         let _scroll = contentEl.scrollHeight > contentEl.clientHeight;
         let _scroll = contentEl.scrollHeight > contentEl.clientHeight;
 
 
+        let width = contentEl.offsetWidth - 10 - (_scroll ? 19 : 2) // 有滚动条时需要减去滚动条的宽度
+        if(width > 0 && width !== lastContentSize.width) {
+            this.setState({
+                lastContentSize: {
+                    width,
+                    height: contentEl.clientHeight,
+                    scroll: _scroll
+                }
+            });
+        }
         return {
         return {
-            width: document.body.offsetWidth - 20 - ((isOwner && editMode && !isShareView && !isShareKeyView) ? 200 : 0) - 10 - (_scroll ? 17 : 2), // 有滚动条时需要减去滚动条的宽度
+            width: width,
             height: contentEl.clientHeight
             height: contentEl.clientHeight
         }
         }
     }
     }
 
 
-    // getRelationFilterColumns = () => {
-    //     const { dashboardDesigner } = this.props;
-    //     const { relationColumns } = dashboardDesigner;
-    //     let arr = relationColumns.filter(r => r.relations.length > 0).map(r => ({
-    //         name: r.relations[0].column.name + (r.relations[1] ? (',' + r.relations[1].column.name) : ''),
-    //         label: r.name,
-    //         type: r.relations[0].column.type + (r.relations[1] ? (',' + r.relations[1].column.type) : ''),
-    //         dataSource: r.relations[0].dataSource + (r.relations[1] ? (',' + r.relations[1].dataSource) : ''),
-    //     }));
-    //     return arr;
-    // }
-
     createFilters = (filters) => {
     createFilters = (filters) => {
-        const { dispatch } = this.props;
-        dispatch({ type: 'dashboardDesigner/changeFilters', filters });
+        const { dispatch, afterRefresh } = this.props;
+        dispatch({ type: 'dashboardDesigner/changeFilters', filters }).then(() => {
+            afterRefresh && typeof afterRefresh === 'function' && afterRefresh()
+        });
         this.hideFilterBox()
         this.hideFilterBox()
     }
     }
 
 
@@ -134,16 +134,18 @@ class DashboardDesignerContent extends React.Component {
 
 
     filterUsingChange = (e) => {
     filterUsingChange = (e) => {
         const key = e.target.dataset.key;
         const key = e.target.dataset.key;
-        const { dashboardDesigner, dispatch } = this.props;
+        const { dashboardDesigner, dispatch, afterRefresh } = this.props;
         const filters = dashboardDesigner.filters;
         const filters = dashboardDesigner.filters;
         let filter = filters.find(f => +f.key === +key);
         let filter = filters.find(f => +f.key === +key);
-        dispatch({ type: 'dashboardDesigner/changeFilter', filter: { ...filter, using: filter.type ? !filter.using : false} });
+        dispatch({ type: 'dashboardDesigner/changeFilter', filter: { ...filter, using: filter.type ? !filter.using : false} }).then(() => {
+            afterRefresh && typeof afterRefresh === 'function' && afterRefresh()
+        });
     }
     }
 
 
     render() {
     render() {
-        const { dashboardDesigner, isOwner, isShareView, isShareKeyView } = this.props;
+        const { dashboardDesigner, isOwner, isShareView, isShareKeyView, isViewMode } = this.props;
         const { dataSources, editMode, filters, relationColumns } = dashboardDesigner;
         const { dataSources, editMode, filters, relationColumns } = dashboardDesigner;
-        const { visibleFilterBox } = this.state;
+        const { visibleFilterBox, lastContentSize } = this.state;
 
 
         const contentSize = this.getContentSize();
         const contentSize = this.getContentSize();
         let tags = filters.map((f, i)=>{
         let tags = filters.map((f, i)=>{
@@ -165,6 +167,7 @@ class DashboardDesignerContent extends React.Component {
                             closable={false}
                             closable={false}
                             onClick={this.filterUsingChange}
                             onClick={this.filterUsingChange}
                             data-key={tag.key}
                             data-key={tag.key}
+                            title={tag.label}
                         >
                         >
                             {tag.label}
                             {tag.label}
                         </Tag>
                         </Tag>
@@ -178,14 +181,17 @@ class DashboardDesignerContent extends React.Component {
                 </div>
                 </div>
                 {visibleFilterBox && <FilterBox dataSources={dataSources} relationColumns={relationColumns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
                 {visibleFilterBox && <FilterBox dataSources={dataSources} relationColumns={relationColumns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
             </Header>
             </Header>
-            <Content className='dashboard-content'>
+            <Content className={`dashboard-content${(isShareView || isShareKeyView || isViewMode) ? ' nomargin' : ''}`}>
                 <Layout className='content-layout'>
                 <Layout className='content-layout'>
-                    <Sider className={`config-sider${ (isOwner && editMode) ? '' : ' config-sider-closed' }`} width={(isOwner && editMode && !isShareView && !isShareKeyView) ? 200 : 0}>
+                    {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Sider className={`config-sider${ (isOwner && editMode) ? '' : ' config-sider-closed' }`} width={(isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode) ? 200 : 0}>
                         <ConfigSider/>
                         <ConfigSider/>
-                    </Sider>
-                    <Content className='viewlayout'>
-                        <ViewLayout isOwner={isOwner} isShareView={isShareView} isShareKeyView={isShareKeyView} contentSize={contentSize} editMode={editMode}/>
-                    </Content>
+                    </Sider>}
+                    {/**
+                        这里直接用main标签而不用antd的Header组件是为了让ref能够定位到对应的dom元素
+                    */}
+                    <main ref={this.contentRef} className='viewlayout ant-layout-content'>
+                        <ViewLayout isOwner={isOwner} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} contentSize={contentSize} lastContentSize={lastContentSize} editMode={editMode}/>
+                    </main>
                 </Layout>
                 </Layout>
             </Content>
             </Content>
         </Layout>
         </Layout>

+ 29 - 2
src/components/dashboardDesigner/cusFilterBox.jsx

@@ -34,7 +34,7 @@ class CusFilterBox extends React.Component {
                 header={<Form.Item className='filtercolumn-name' label='名称' labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
                 header={<Form.Item className='filtercolumn-name' label='名称' labelCol={{ span: 6 }} wrapperCol={{ span: 18 }}>
                     <Input size='small' value={r.name}
                     <Input size='small' value={r.name}
                     onChange={(e) => {
                     onChange={(e) => {
-                        dispatch({ type: 'dashboardDesigner/setRelationColumn', code: r.code, relationColumn: { ...r, name: e.target.value, cusName: true } });
+                        dispatch({ type: 'dashboardDesigner/setRelationColumn', code: r.code, relationColumn: { ...r, name: e.target.value } });
                     }} onFocus={() => {
                     }} onFocus={() => {
                         this.setState({
                         this.setState({
                             editing: true,
                             editing: true,
@@ -129,6 +129,7 @@ class CusFilterBox extends React.Component {
         const { dashboardDesigner, dispatch } = this.props;
         const { dashboardDesigner, dispatch } = this.props;
         const { selectedDataSource } = this.state;
         const { selectedDataSource } = this.state;
         const { relationColumns } = dashboardDesigner;
         const { relationColumns } = dashboardDesigner;
+        let setFlag, cusName;
 
 
         this.setState({
         this.setState({
             selectedColumn: {
             selectedColumn: {
@@ -140,6 +141,8 @@ class CusFilterBox extends React.Component {
             const { relations } = r;
             const { relations } = r;
             let idx = relations.findIndex(r => r.dataSource.code === selectedDataSource.code);
             let idx = relations.findIndex(r => r.dataSource.code === selectedDataSource.code);
             if(idx === -1){
             if(idx === -1){
+                setFlag = relations.length === 0; // 当添加第一个数据源列时
+                cusName = c.label;
                 relations.push({
                 relations.push({
                     dataSource: {
                     dataSource: {
                         code: selectedDataSource.code,
                         code: selectedDataSource.code,
@@ -151,6 +154,26 @@ class CusFilterBox extends React.Component {
                         type: c.type
                         type: c.type
                     }
                     }
                 });
                 });
+            }else if(idx === 0) { // 如果是第一个则需要重新设置关联
+                let cr = relations[idx];
+                setFlag = true;
+                cusName = c.label;
+                
+                if(cr.column.name === selectedColumn.name) {
+                    relations.splice(0, relations.length); // 第一个取消勾选后全部清空
+                }else {
+                    relations[idx] = {
+                        dataSource: {
+                            code: selectedDataSource.code,
+                            name: selectedDataSource.name
+                        },
+                        column: {
+                            name: c.name,
+                            label: c.label,
+                            type: c.type
+                        }
+                    };
+                }
             }else {
             }else {
                 let cr = relations[idx];
                 let cr = relations[idx];
                 if(cr.column.name === selectedColumn.name) {
                 if(cr.column.name === selectedColumn.name) {
@@ -170,7 +193,11 @@ class CusFilterBox extends React.Component {
                 }
                 }
             }
             }
             let index = relationColumns.findIndex(rc => rc.code === r.code);
             let index = relationColumns.findIndex(rc => rc.code === r.code);
-            relationColumns[index] = { ...r, name: relationColumns[index].cusName ? relationColumns[index].name : c.label, cusName: true, relations };
+            if(setFlag) {
+                relationColumns[index] = { ...r, name: cusName, relations };
+            }else {
+                relationColumns[index] = { ...r, relations }; 
+            }
             dispatch({ type: 'dashboardDesigner/setField', name: 'relationColumns', value: relationColumns });
             dispatch({ type: 'dashboardDesigner/setField', name: 'relationColumns', value: relationColumns });
         });
         });
     }
     }

+ 24 - 25
src/components/dashboardDesigner/layout.jsx

@@ -2,8 +2,6 @@ import React from 'react'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import { Icon, Layout, Spin } from 'antd'
 import { Icon, Layout, Spin } from 'antd'
 import './layout.less'
 import './layout.less'
-import html2canvas from 'html2canvas'
-import jsPDF from 'jspdf'
 import DashboardDesignerHeader from './header'
 import DashboardDesignerHeader from './header'
 import DashboardDesignerContent from './content'
 import DashboardDesignerContent from './content'
 const { Header, Content } = Layout
 const { Header, Content } = Layout
@@ -17,30 +15,31 @@ class DashboardDesigner extends React.Component {
     }
     }
 
 
     componentDidMount() {
     componentDidMount() {
-        const { dispatch, isShareView, isShareKeyView } = this.props;
-        const { code } = this.props.match.params;
+        const { code, dispatch, isShareView, isShareKeyView, afterLoad, config } = this.props;
+        
         let url;
         let url;
         if (code !== 'create') {
         if (code !== 'create') {
             url = isShareView ? 'dashboard/remoteShareDetail' : ( isShareKeyView ? 'dashboard/remoteShareKeyDetail' : 'dashboard/remoteDetail');
             url = isShareView ? 'dashboard/remoteShareDetail' : ( isShareKeyView ? 'dashboard/remoteShareKeyDetail' : 'dashboard/remoteDetail');
         }
         }
-        dispatch({ type: url, code: code });
+        if(config) { // 首页打开的报表会保存报表配置,不需要后台再请求
+            let fields = [];
+            for(let key in config) {
+                fields.push({
+                    name: key,
+                    value: config[key]
+                })
+            }
+            dispatch({ type: 'dashboardDesigner/silentSetFields', fields: fields });
+        }else {
+            dispatch({ type: url, code: code }).then((data) => {
+                if(afterLoad && typeof afterLoad === 'function') {
+                    afterLoad(data)
+                }
+            });
+        }
     }
     }
 
 
 
 
-    saveToPNG = (element) => {
-        html2canvas(element).then(function (canvas) {
-            let pageData = canvas.toDataURL('image/png', 1.0);
-
-            //方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
-            let pdf = new jsPDF('', 'pt', 'a4');
-
-            //addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
-            pdf.addImage(pageData, 'PNG', 0, 0, 595.28, 592.28 / canvas.width * canvas.height);
-
-            pdf.save('stone.pdf');
-        });
-    }
-
     isOwner = () => {
     isOwner = () => {
         const { dashboardDesigner, main } = this.props;
         const { dashboardDesigner, main } = this.props;
         const { creatorCode } = dashboardDesigner;
         const { creatorCode } = dashboardDesigner;
@@ -49,14 +48,14 @@ class DashboardDesigner extends React.Component {
     }
     }
 
 
     render() {
     render() {
-        const { dashboardDesigner, isShareView, isShareKeyView } = this.props;
+        const { dashboardDesigner, isShareView, isShareKeyView, isViewMode, afterRefresh } = this.props;
         const { loading } = dashboardDesigner;
         const { loading } = dashboardDesigner;
         return <Layout className='dashboarddesigner-layout'>
         return <Layout className='dashboarddesigner-layout'>
-            {!isShareView && !isShareKeyView && <Header>
+            {!isShareView && !isShareKeyView && !isViewMode && <Header>
                 <DashboardDesignerHeader updateThumbnail={this.updateThumbnail} />
                 <DashboardDesignerHeader updateThumbnail={this.updateThumbnail} />
             </Header>}
             </Header>}
-            <Content style={{ height: 0 }}>
-                <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView}/>
+            <Content>
+                <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} afterRefresh={afterRefresh}/>
             </Content>
             </Content>
             <div style={{ display: loading ? 'block' : 'none', position: 'absolute', height: '100%', width: '100%', zIndex: '4', background: 'rgba(51,51,51,.1)' }}>
             <div style={{ display: loading ? 'block' : 'none', position: 'absolute', height: '100%', width: '100%', zIndex: '4', background: 'rgba(51,51,51,.1)' }}>
                 <Spin style={{ display: 'inline-block', position: 'absolute', top: '50%', left: '50%', margin: '-10px' }} indicator={<Icon type="loading" style={{ fontSize: 24 }} spin />} />
                 <Spin style={{ display: 'inline-block', position: 'absolute', top: '50%', left: '50%', margin: '-10px' }} indicator={<Icon type="loading" style={{ fontSize: 24 }} spin />} />
@@ -67,8 +66,8 @@ class DashboardDesigner extends React.Component {
 }
 }
 
 
 function mapStateToProps(state) {
 function mapStateToProps(state) {
-    const { main, dashboardDesigner } = state.present;
-    return { main, dashboardDesigner }
+    const { main } = state.present;
+    return { main }
 }
 }
 
 
 export default connect(mapStateToProps)(DashboardDesigner)
 export default connect(mapStateToProps)(DashboardDesigner)

+ 9 - 2
src/components/dashboardDesigner/layout.less

@@ -18,6 +18,9 @@
                 height: calc(~"100% - 20px");
                 height: calc(~"100% - 20px");
                 margin: 10px;
                 margin: 10px;
                 overflow: hidden;
                 overflow: hidden;
+                &.nomargin {
+                    margin: 0;
+                }
                 &>.content-layout {
                 &>.content-layout {
                     flex-direction: row;
                     flex-direction: row;
                     overflow: hidden;
                     overflow: hidden;
@@ -49,7 +52,8 @@
             .ant-layout-header {
             .ant-layout-header {
                 background: none;
                 background: none;
                 padding: 0 10px;
                 padding: 0 10px;
-                height: 40px;
+                height: auto;
+                min-height: 40px;
                 line-height: 37px;
                 line-height: 37px;
                 border-width: 1px 0;
                 border-width: 1px 0;
                 border-style: solid;
                 border-style: solid;
@@ -58,9 +62,12 @@
                 justify-content: space-between;
                 justify-content: space-between;
                 .filters {
                 .filters {
                     display: flex;
                     display: flex;
+                    width: 100%;
+                    flex-wrap: wrap;
                     .filter-tag {
                     .filter-tag {
-                        max-width: 400px;
+                        max-width: 200px;
                         overflow: hidden;
                         overflow: hidden;
+                        white-space: nowrap;
                         text-overflow: ellipsis;
                         text-overflow: ellipsis;
                         border-style: dashed;
                         border-style: dashed;
                         margin: 8px 2px 8px 2px;
                         margin: 8px 2px 8px 2px;

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

@@ -16,7 +16,7 @@ class RichTextEditor extends Component {
         );
         );
     }
     }
     componentDidMount() {
     componentDidMount() {
-        const { content, onContentChange } = this.props;
+        const { content, onContentChange, readOnly } = this.props;
         const elem = this.refs.editorElem;
         const elem = this.refs.editorElem;
         const editor = new E(elem);
         const editor = new E(elem);
         editor.customConfig.onchange = (html) => {
         editor.customConfig.onchange = (html) => {
@@ -26,6 +26,9 @@ class RichTextEditor extends Component {
             }
             }
         }; // 使用 onchange 函数监听内容的变化
         }; // 使用 onchange 函数监听内容的变化
         editor.customConfig.onfocus = () => {
         editor.customConfig.onfocus = () => {
+            if(readOnly) {
+                return;
+            }
             this.setState({
             this.setState({
                 _html: editor.txt.html()
                 _html: editor.txt.html()
             });
             });
@@ -64,6 +67,8 @@ class RichTextEditor extends Component {
         editor.create()
         editor.create()
         // editor.blur();
         // editor.blur();
         editor.txt.html(content);
         editor.txt.html(content);
+
+        editor.$textElem.attr('contenteditable', !readOnly)
     }
     }
 }
 }
 
 

+ 0 - 0
src/components/dashboardDesigner/viewBox.jsx


+ 4 - 6
src/components/dashboardDesigner/viewLayout.jsx

@@ -4,6 +4,7 @@ import ReactGridLayout from 'react-grid-layout'
 import { Icon, Modal } from 'antd'
 import { Icon, Modal } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import ChartView from './chartView'
 import ChartView from './chartView'
+import EmptyContent from '../common/emptyContent/index'
 
 
 class ViewLayout extends React.PureComponent {
 class ViewLayout extends React.PureComponent {
     constructor(props) {
     constructor(props) {
@@ -83,13 +84,13 @@ class ViewLayout extends React.PureComponent {
     }
     }
 
 
     render() {
     render() {
-        const { isOwner, isShareView, isShareKeyView, dashboardDesigner, contentSize } = this.props;
+        const { dashboardDesigner, contentSize, lastContentSize } = this.props;
         const { editMode } = dashboardDesigner;
         const { editMode } = dashboardDesigner;
         const { visiblePreviewBox, previewItem } = this.state;
         const { visiblePreviewBox, previewItem } = this.state;
         const children = dashboardDesigner.items.map((item) => this.createElement(item, false, !item.chartOption));
         const children = dashboardDesigner.items.map((item) => this.createElement(item, false, !item.chartOption));
         return (<div className='dashboard-viewcontent'>
         return (<div className='dashboard-viewcontent'>
             <ReactGridLayout
             <ReactGridLayout
-                width={contentSize.width}
+                width={ contentSize.width ? contentSize.width : lastContentSize.width }
                 autoSize={true}
                 autoSize={true}
                 cols={12}
                 cols={12}
                 margin = {editMode ? [2, 2] : [0, 0]}
                 margin = {editMode ? [2, 2] : [0, 0]}
@@ -103,10 +104,7 @@ class ViewLayout extends React.PureComponent {
                 compactType='vertical'
                 compactType='vertical'
             >
             >
                 {(children.length === 0) ? <div key='default-chartview' className='default-chartview' data-grid={{ x: 0, y: 0, w: 12, h: 2, minW: 12, maxW: 12, minH: 2, maxH: 2, static: true }}>
                 {(children.length === 0) ? <div key='default-chartview' className='default-chartview' data-grid={{ x: 0, y: 0, w: 12, h: 2, minW: 12, maxW: 12, minH: 2, maxH: 2, static: true }}>
-                    <div className='tip'>
-                        <Icon type="message" theme="outlined" />
-                        {(isOwner && !isShareView && !isShareKeyView) ? <span>请从左侧选择图表/富文本添加到报表</span> : <span>无图表元素</span>}
-                    </div>
+                    <EmptyContent />
                 </div> : children}
                 </div> : children}
             </ReactGridLayout>
             </ReactGridLayout>
             <Modal
             <Modal

+ 2 - 2
src/components/dashboardDesigner/viewLayout.less

@@ -90,7 +90,7 @@
           overflow: auto;
           overflow: auto;
           border: none !important;
           border: none !important;
           .w-e-text {
           .w-e-text {
-            pointer-events: none;
+            // pointer-events: none;
             padding: 0 14px;
             padding: 0 14px;
             &>table {
             &>table {
               margin: 0;
               margin: 0;
@@ -129,7 +129,7 @@
     }
     }
   }
   }
   .react-grid-layout {
   .react-grid-layout {
-    background: #eee;
+    // background: #eee;
   }
   }
   .layoutJSON {
   .layoutJSON {
     background: #ddd;
     background: #ddd;

+ 3 - 2
src/components/dataConnect/list.jsx

@@ -3,6 +3,7 @@ import { Layout, Row, Col, Input, Button, Icon, Card, Tooltip, Select, DatePicke
 import { connect } from 'dva'
 import { connect } from 'dva'
 import moment from 'moment'
 import moment from 'moment'
 import DeleteBox from '../common/deleteBox/deleteBox'
 import DeleteBox from '../common/deleteBox/deleteBox'
+import EmptyContent from '../common/emptyContent/index'
 import DataConnectBox from '../dataSourceDetail/dataConnectBox'
 import DataConnectBox from '../dataSourceDetail/dataConnectBox'
 import './list.less'
 import './list.less'
 const CardGrid = Card.Grid
 const CardGrid = Card.Grid
@@ -190,7 +191,7 @@ class DataConnect extends React.Component {
         ))
         ))
 
 
         if(cards.length === 0) {
         if(cards.length === 0) {
-            return (<div className="ant-empty ant-empty-normal"><div className="ant-empty-image"><img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K"/></div><p className="ant-empty-description">暂无数据</p></div>)
+            return <EmptyContent />
         }
         }
         
         
         return cards;
         return cards;
@@ -294,7 +295,7 @@ class DataConnect extends React.Component {
                         dispatch({ type: 'dataConnect/remoteDelete', code: selected.code })
                         dispatch({ type: 'dataConnect/remoteDelete', code: selected.code })
                     }} 
                     }} 
                 />}
                 />}
-                <DataConnectBox />
+                {dataConnect.newOne.visibleBox && <DataConnectBox />}
             </Layout>
             </Layout>
         )
         )
     }
     }

+ 8 - 0
src/components/dataConnect/list.less

@@ -1,6 +1,9 @@
 .layout-dataconnect {
 .layout-dataconnect {
     &>.ant-layout-content {
     &>.ant-layout-content {
         &>.ant-card {
         &>.ant-card {
+            height: 100%;
+            display: flex;
+            flex-direction: column;
             &>.ant-card-head {
             &>.ant-card-head {
                 padding: 0 10px;
                 padding: 0 10px;
                 .tools {
                 .tools {
@@ -14,10 +17,15 @@
                 }
                 }
             }
             }
             &>.ant-card-body {
             &>.ant-card-body {
+                flex: 1;
+                overflow: auto;
                 padding: 16px;
                 padding: 16px;
                 display: flex;
                 display: flex;
                 flex-wrap: wrap;
                 flex-wrap: wrap;
                 justify-content: center;
                 justify-content: center;
+                &:before {
+                    content: none;
+                }
                 .dataconnect-card {
                 .dataconnect-card {
                     width: 160px;
                     width: 160px;
                     height: 160px;
                     height: 160px;

+ 8 - 1
src/components/dataSource/list.less

@@ -1,7 +1,10 @@
 .datasource-view {
 .datasource-view {
     .datasource-body {
     .datasource-body {
         padding: 0;
         padding: 0;
-        .ant-card-head {
+        height: 100%;
+        display: flex;
+        flex-direction: column;
+        &>.ant-card-head {
             padding: 0 10px;
             padding: 0 10px;
             .datasource-tools {
             .datasource-tools {
                 flex: 1;
                 flex: 1;
@@ -39,6 +42,10 @@
                 }
                 }
             }
             }
         }
         }
+        &>.ant-card-body {
+            flex: 1;
+            overflow: auto;
+        }
     }
     }
     .ant-card-body {
     .ant-card-body {
         padding: 0;
         padding: 0;

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

@@ -163,6 +163,7 @@ class DataConnectBox extends React.Component {
                             >
                             >
                                 <InputNumber
                                 <InputNumber
                                     disabled={disabled}
                                     disabled={disabled}
+                                    defaultValue={1521}
                                     value={dataConnect.newOne.port}
                                     value={dataConnect.newOne.port}
                                     onChange={(value) => {
                                     onChange={(value) => {
                                         dispatch({ type: 'dataConnect/setNewModelField', name: 'port', value: value });
                                         dispatch({ type: 'dataConnect/setNewModelField', name: 'port', value: value });
@@ -177,6 +178,7 @@ class DataConnectBox extends React.Component {
                     >
                     >
                         <Input
                         <Input
                             disabled={disabled}
                             disabled={disabled}
+                            defaultValue='orcl'
                             value={dataConnect.newOne.dbName}
                             value={dataConnect.newOne.dbName}
                             onChange={(e) => {
                             onChange={(e) => {
                                 dispatch({ type: 'dataConnect/setNewModelField', name: 'dbName', value: e.target.value });
                                 dispatch({ type: 'dataConnect/setNewModelField', name: 'dbName', value: e.target.value });

+ 2 - 1
src/components/dataSourceDetail/dataConnectConfig.jsx

@@ -3,6 +3,7 @@ import { Layout, Form, Row, Col, Input, Icon, Menu, Dropdown, Divider, Upload, m
 import { connect } from 'dva'
 import { connect } from 'dva'
 import DataConnectBox from './dataConnectBox'
 import DataConnectBox from './dataConnectBox'
 import Ellipsis from 'ant-design-pro/lib/Ellipsis'
 import Ellipsis from 'ant-design-pro/lib/Ellipsis'
+import EmptyContent from '../common/emptyContent/index'
 const { Content } = Layout
 const { Content } = Layout
 const CardGrid = Card.Grid
 const CardGrid = Card.Grid
 const UploadDragger = Upload.Dragger
 const UploadDragger = Upload.Dragger
@@ -118,7 +119,7 @@ class DataConnectConfig extends React.Component {
             // );
             // );
 
 
             if(cards.length === 0) {
             if(cards.length === 0) {
-                return (<div className="ant-empty ant-empty-normal"><div className="ant-empty-image"><img alt="暂无数据" src="data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNjQiIGhlaWdodD0iNDEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMCAxKSIgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgIDxlbGxpcHNlIGZpbGw9IiNGNUY1RjUiIGN4PSIzMiIgY3k9IjMzIiByeD0iMzIiIHJ5PSI3Ii8+CiAgICA8ZyBmaWxsLXJ1bGU9Im5vbnplcm8iIHN0cm9rZT0iI0Q5RDlEOSI+CiAgICAgIDxwYXRoIGQ9Ik01NSAxMi43Nkw0NC44NTQgMS4yNThDNDQuMzY3LjQ3NCA0My42NTYgMCA0Mi45MDcgMEgyMS4wOTNjLS43NDkgMC0xLjQ2LjQ3NC0xLjk0NyAxLjI1N0w5IDEyLjc2MVYyMmg0NnYtOS4yNHoiLz4KICAgICAgPHBhdGggZD0iTTQxLjYxMyAxNS45MzFjMC0xLjYwNS45OTQtMi45MyAyLjIyNy0yLjkzMUg1NXYxOC4xMzdDNTUgMzMuMjYgNTMuNjggMzUgNTIuMDUgMzVoLTQwLjFDMTAuMzIgMzUgOSAzMy4yNTkgOSAzMS4xMzdWMTNoMTEuMTZjMS4yMzMgMCAyLjIyNyAxLjMyMyAyLjIyNyAyLjkyOHYuMDIyYzAgMS42MDUgMS4wMDUgMi45MDEgMi4yMzcgMi45MDFoMTQuNzUyYzEuMjMyIDAgMi4yMzctMS4zMDggMi4yMzctMi45MTN2LS4wMDd6IiBmaWxsPSIjRkFGQUZBIi8+CiAgICA8L2c+CiAgPC9nPgo8L3N2Zz4K"/></div><p className="ant-empty-description">暂无数据</p></div>)
+                return <EmptyContent />
             }
             }
             
             
             return cards;
             return cards;

+ 0 - 53
src/components/homePage/homePage.jsx

@@ -1,53 +0,0 @@
-import React from 'react';
-import { Layout, Card } from 'antd'
-import CardList from '../common/CardList'
-import { connect } from 'dva'
-import './homePage.less'
-const { Content, Sider } = Layout
-
-class HomePage extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-        }
-    }
-
-    componentDidMount() {
-        const { dispatch } = this.props;
-        dispatch({ type: 'recent/fetchRecentChart' });
-        dispatch({ type: 'recent/fetchRecentDashboard' });
-    }
-
-    render() {
-        const { recent } = this.props;
-        const { recentChart, recentDashboard } = recent;
-
-        return (
-            <Layout className='homepage'>
-                <Content>
-                    <Card className='recent-chart' title='最近访问图表' >
-                        <CardList
-                            mode='homepage' 
-                            type='chart' 
-                            list={recentChart}
-                        />
-                    </Card>
-                    <Card className='recent-dashboard' title='最近访问报表'>
-                        <CardList
-                            mode='homepage' 
-                            type='dashboard' 
-                            list={recentDashboard}
-                        />
-                    </Card>
-                </Content>
-                <Sider width={280}> 
-                    <Card>
-                        <div><h1>快速上手</h1><p>点击访问<a href="http://192.168.253.189:82" target="_blank" rel="noopener noreferrer">产品文档</a></p></div>
-                    </Card>
-                </Sider>
-            </Layout>
-        );
-    }
-}
-
-export default connect(({ present: { recent } }) =>  { return { recent }})(HomePage)

+ 0 - 49
src/components/homePage/homePage.less

@@ -1,49 +0,0 @@
-.homepage {
-    &>.ant-layout-content {
-        padding: 20px;
-        &>.ant-card {
-            &>.ant-card-head {
-                padding: 0;
-                height: 42px;
-                min-height: 42px;
-                &>.ant-card-head-wrapper {
-                    &>.ant-card-head-title {
-                        padding: 8px 10px;
-                    }
-                }
-            }
-            &>.ant-card-body {
-                padding: 10px;
-                &>.ant-card-grid {
-                    &>.ant-card {
-                        border: 2px solid #CCCCCC;
-                        &>.ant-card-head {
-                            border-bottom: 2px solid #CCCCCC;
-                            min-height: 20px;
-                            cursor: default;
-                            padding: 0 10px;
-                        }
-                        &>.ant-card-body {
-                            padding: 10px;
-                        }
-                    }
-                }
-            }
-        }
-        &>.recent-chart {
-            margin-bottom: 20px;
-        }
-        &>.recent-dashboard {
-
-        }
-    }
-    .ant-layout-sider {
-        padding: 20px 20px 20px 0;
-        background: transparent;
-        &>.ant-layout-sider-children {
-            &>.ant-card {
-                height: 100%;
-            }
-        }
-    }
-}