Browse Source

看板编辑界面初步设计/图表echarts视图解析逻辑调整

zhuth 7 years ago
parent
commit
a23c1ee501

+ 128 - 66
src/components/chart/resolveChartOption.js

@@ -1,28 +1,28 @@
-export default (config) => {
+export default (config, silent) => {
     const { viewType, option } = config;
     let o;
     switch(viewType) {
         case 'bar': {
-            o = barConfig(option);
+            o = barConfig(option, silent);
             break;
         }
         case 'pie': {
-            o = pieConfig(option);
+            o = pieConfig(option, silent);
             break;
         }
         case 'line': {
-            o = lineConfig(option);
+            o = lineConfig(option, silent);
             break;
         }
         case 'scatter': {
-            o = scatterConfig(option);
+            o = scatterConfig(option, silent);
             break;
         }
         case 'aggregateTable': {
-            o = tableConfig(option);
+            o = tableConfig(option, silent);
             break;
         }case 'dataView' : {
-            o = tableConfig(option);
+            o = tableConfig(option, silent);
             break;
         }
         default:{
@@ -33,51 +33,77 @@ export default (config) => {
     return o;
 }
 
-function barConfig(option) {
+function barConfig(option, silent) {
     const { xAxis, serieses, xTitle, yTitle } = option;
 
     let o = {
-        animation: false,
-        legend: {show: false},
+        animation: !silent,
+        tooltip : {
+            show: !silent,
+            trigger: "axis",
+            axisPointer: {
+                type: "cross",
+                label: {
+                    backgroundColor: "#6a7985"
+                }
+            }
+        },
+        legend: {
+            show: !silent
+        },
         grid: {
-            left: 0,
-            right: 0,
-            top: 0,
-            bottom: 0,
-            containLabel: false
+            left: silent ? 0 : '10%',
+            right: silent ? 0 : '10%',
+            top: silent ? 0 : 60,
+            bottom: silent ? 0 : 60,
+            containLabel: !silent
         },
         xAxis: [{
+            show: !silent,
             type: 'category',
-            boundaryGap: false,
             data: xAxis,
             name: xTitle || '横轴',
-            show: false
         }],
         yAxis: [{
+            show: !silent,
             name: yTitle || '纵轴',
-            type: 'value',
-            show: false
+            type: 'value'
         }],
         series: serieses.map(s => {
             return {
                 name: s.name,
                 type: 'bar',
                 data: s.value,
-                showSymbol: false,
-                silent: true
+                showSymbol: !silent,
+                silent,
             }
         }) 
     }
     return o;
 }
 
-function pieConfig(option) {
+function pieConfig(option, silent) {
 
     const { xAxis, columnName, serieses } = option;
 
     let o = {
-        animation: false,
-        legend: {show: false},
+        animation: !silent,
+        grid: {
+            left: silent ? 0 : '10%',
+            right: silent ? 0 : '10%',
+            top: silent ? 0 : 60,
+            bottom: silent ? 0 : 60,
+            containLabel: !silent
+        },
+        tooltip : {
+            show: !silent,
+            trigger: 'item',
+            formatter: "{a} <br/>{b} : {c} ({d}%)"
+        },
+        legend: {
+            show: !silent,
+            data: xAxis
+        },
         series : [
             {
                 name: columnName,
@@ -85,38 +111,55 @@ function pieConfig(option) {
                 // radius : '55%',
                 // center: ['50%', '60%'],
                 data: serieses[0].value,
-                label: { show: false },
-                labelLine: { show: false },
-                silent: true
+                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) {
+function lineConfig(option, silent) {
     const { serieses, xTitle, yTitle } = option;
 
     let o = {
-        animation: false,
+        animation: !silent,
         grid: {
-            left: 0,
-            right: 0,
-            top: 0,
-            bottom: 0,
-            containLabel: false
+            left: silent ? 0 : '10%',
+            right: silent ? 0 : '10%',
+            top: silent ? 0 : 60,
+            bottom: silent ? 0 : 60,
+            containLabel: !silent
+        },
+        tooltip: {
+            show: !silent,
+            trigger: 'axis',
+            axisPointer: {
+                type: 'cross'
+            }
+        },
+        legend: {
+            show: !silent
         },
-        legend: {show: false},
         xAxis:  {
+            show: !silent,
             name: xTitle,
-            type: 'time',
-            show: false
+            type: 'time'
         },
         yAxis: {
+            show: !silent,
             name: yTitle,
-            type: 'value',
-            show: false
+            type: 'value'
         },
+        
         series: serieses.map(s => {
             return {
                 name: s.name,
@@ -124,8 +167,8 @@ function lineConfig(option) {
                 data: s.mdata.map(m => {
                     return [m.date, m.value]
                 }),
-                showSymbol: false,
-                silent: true
+                showSymbol: !silent,
+                silent
             }
         })
     };
@@ -133,35 +176,54 @@ function lineConfig(option) {
     return o;
 }
 
-function scatterConfig(option) {
+function scatterConfig(option, silent) {
     const { serieses, xTitle, yTitle } = option;
     let o = {
-        animation: false,
+        animation: !silent,
         grid: {
-            left: 0,
-            right: 0,
-            top: 0,
-            bottom: 0,
-            containLabel: false
+            left: silent ? 10 : '10%',
+            right: silent ? 10 : '10%',
+            top: silent ? 10 : 60,
+            bottom: silent ? 10 : 60,
+            containLabel: !silent
         },
-        xAxis : {
-            type : 'value',
-            name: xTitle,
-            scale:true,
-            splitLine: {
-                show: false
-            },
-            show: false
+        tooltip : {
+            show: !silent,
+            showDelay : 0,
+            axisPointer:{
+                show: true,
+                type : 'cross',
+                lineStyle: {
+                    type : 'dashed',
+                    width : 1
+                }
+            }
         },
-        yAxis : {
-            type : 'value',
-            name: yTitle,
-            scale:true,
-            splitLine: {
-                show: false
-            },
-            show: false
+        legend: {
+            show: !silent
         },
+        xAxis : [
+            {
+                show: !silent,
+                type : 'value',
+                name: xTitle,
+                scale:true,
+                splitLine: {
+                    show: false
+                }
+            }
+        ],
+        yAxis : [
+            {
+                show: !silent,
+                type : 'value',
+                name: yTitle,
+                scale:true,
+                splitLine: {
+                    show: false
+                }
+            }
+        ],
         series : serieses.map(s => {
             return {
                 name: s.name,
@@ -169,14 +231,14 @@ function scatterConfig(option) {
                 data: s.mdata.map(m => {
                     return [m.date, m.value]
                 }),
-                silent: true
+                silent
             }
         })
     };
     return o;
 }
 
-function tableConfig(option) {
+function tableConfig(option, silent) {
     const { columns, data } = option;
     let o = {
         columns,

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

@@ -7,7 +7,7 @@ const Thumbnail = ({ code, option }) => {
         <div style={{ width: '100%', height: '100%' }}>
             <Echarts
                 key={code}
-                option={resolveChartOption(option || {})}
+                option={resolveChartOption(option || {}, true)}
                 className='rc-echarts'
                 style={{height: '100%'}}
             />

+ 1 - 1
src/components/chartDesigner/charts/echartsView.jsx

@@ -1,7 +1,7 @@
 import React from 'react'
 import Echarts from 'echarts-for-react'
 import { connect } from 'dva'
-import resolveChartOption from './resolveChartOption'
+import resolveChartOption from '../../chart/resolveChartOption'
 import { hashcode } from '../../../utils/baseUtils'
 
 const EchartsView = ({ chartDesigner, dispatch }) => {

+ 3 - 3
src/components/chartDesigner/charts/tableView.jsx

@@ -1,7 +1,7 @@
-import React from 'react';
-import { Table } from 'antd';
+import React from 'react'
+import { Table } from 'antd'
 import { connect } from 'dva'
-import resolveChartOption from './resolveChartOption'
+import resolveChartOption from '../../chart/resolveChartOption'
 
 const TableView = ({ chartDesigner, dispatch }) => {
     const option = resolveChartOption(chartDesigner.chartOption);

+ 1 - 6
src/components/common/login.jsx

@@ -4,7 +4,7 @@ import { Alert, Checkbox } from 'antd'
 import { Link, Redirect } from 'dva/router';
 import './login.less'
 
-const { Tab, UserName, Password, Mobile, Captcha, Submit } = Login;
+const { UserName, Password, Submit } = Login;
 
 function authenticate(cb) {
     window.localStorage.setItem("isAuthenticated", "true");
@@ -12,11 +12,6 @@ function authenticate(cb) {
     setTimeout(cb, 100); // fake async
 }
 
-function signout(cb) {
-    window.localStorage.setItem("isAuthenticated", "false");
-    setTimeout(cb, 100); // fake async
-}
-
 class LoginComponent extends React.Component {
     state = {
         notice: '',

+ 3 - 5
src/components/dashboard/dashboard.jsx

@@ -1,8 +1,7 @@
 import React from 'react'
 import { Tabs, Button, Icon, Input, Menu, Dropdown, Card, Avatar } from 'antd'
-import './dashboard.less'
-import '../../models/dashboard'
 import { connect } from 'dva'
+import './dashboard.less'
 const { Search } = Input
 const { TabPane } = Tabs
 const { Meta } = Card;
@@ -17,8 +16,8 @@ class Dashboard extends React.Component {
 
     generateCard(listType) { 
         let listTypeMapper = {
-            "Dynamic": this.props.dashboard.myDynamicDashboardList,
-            "Static": this.props.dashboard.myStaticDashboardList, 
+            "Dynamic": this.props.dashboard.dashboardList,
+            "Static": this.props.dashboard.dashboardList, 
         }
         const list = listTypeMapper[listType];
         return list.map(i => {
@@ -40,7 +39,6 @@ class Dashboard extends React.Component {
 
     render() {
         const { dispatch } = this.props;
-        return <div>null</div>
         return (
             <Tabs
                 className='dashboard-tabs'

+ 25 - 0
src/components/dashboardDesigner/chartView.jsx

@@ -0,0 +1,25 @@
+import React from 'react'
+import Echarts from 'echarts-for-react'
+import { connect } from 'dva'
+import resolveChartOption from '../chart/resolveChartOption.js'
+
+const ChartView = ({ chartCode, chart }) => {
+
+    let targetChart = chart.list.filter(c => c.code === chartCode)[0];
+
+
+    let option = resolveChartOption(targetChart ? targetChart.chartOption : {}, true);
+
+    return (
+        <div style={{ width: '100%', height: '100%' }}>
+            <Echarts
+                key={chartCode}
+                option={option}
+                className='rc-echarts'
+                style={{height: '100%'}}
+            />
+        </div>
+    );
+}
+
+export default connect(({ present: { chart } }) => ({ chart }))(ChartView);

+ 26 - 0
src/components/dashboardDesigner/content.jsx

@@ -0,0 +1,26 @@
+import React from 'react'
+import { Layout } from 'antd'
+import { connect } from 'dva'
+import ViewLayout from './viewLayout'
+const { Content } = Layout
+
+class DashboardDesignerContent extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+        };
+    }
+
+    render() {
+        return <Layout className='content'>
+            <Content>
+                <ViewLayout />
+            </Content>
+        </Layout>
+    }
+}
+function mapStateToProps(state) {
+    const DashboardDesigner = state.present.DashboardDesigner;
+    return { DashboardDesigner }
+}
+export default connect(mapStateToProps)(DashboardDesignerContent);

+ 99 - 0
src/components/dashboardDesigner/header.jsx

@@ -0,0 +1,99 @@
+import React from 'react'
+import { Input, Icon, Button, Popconfirm, Dropdown, Menu } from 'antd'
+import { connect } from 'dva'
+import './header.less'
+
+class Header extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            visibleConfirm: false,
+        }
+    }
+
+    handleVisibleChange = (visible) => {
+        this.setState({ visibleConfirm: visible });
+    }
+
+    render() {
+        const { dispatch } = this.props;
+        return (
+            <div className='dashboarddesigner-header'>
+                <div className='header-item toolbar-back'>
+                    <Popconfirm
+                        placement="bottomLeft"
+                        title="离开前保存修改吗?"
+                        visible={this.state.visibleConfirm}
+                        onVisibleChange={this.handleVisibleChange}
+                        onConfirm={() => {
+                            // this.setState({
+                            //     visibleConfirm: false
+                            // });
+                            // dispatch({ type: 'chart/remoteModify' });
+                            // dispatch({ type: 'main/redirect', path: '/chart' });
+                        }}
+                        onCancel={() => {
+                            this.setState({
+                                visibleConfirm: false
+                            });
+                            dispatch({ type: 'main/redirect', path: '/dashboard' });
+                        }}
+                        okText="保存"
+                        cancelText="不保存"
+                    >
+                        <Button onClick={() => {
+                            // if(!chartDesigner.dirty) {
+                            //     dispatch({ type: 'main/redirect', path: '/chart' });
+                            // }
+                        }}>
+                            <Icon type='left' />返回
+                        </Button>
+                    </Popconfirm>
+                    <Button onClick={() => {
+                        // if(chartDesigner.code && chartDesigner.code !== -1) {
+                        //     dispatch({ type: 'chart/remoteModify' });
+                        // }else {
+                        //     dispatch({ type: 'chart/remoteAdd' });
+                        // }
+                        // dispatch({ type: 'chartDesigner/setDirty', dirty: false });
+                    }}><Icon type='save' />保存</Button>
+                </div>
+                <div className='header-item toolbar-title'>
+                    <Input
+                        className='input-title' 
+                        addonAfter={<Icon type="edit" 
+                            onClick={(e) => {
+                                const input = e.currentTarget.parentElement.parentElement.getElementsByTagName('input')[0];
+                                input && input.focus()
+                            }}
+                        />}
+                        onChange={(e) => {
+                            // dispatch({ type: 'chartDesigner/setField', name: 'header', value: { label: e.target.value } });
+                        }}
+                    />
+                </div>
+                <div className='header-item toolbar-buttons'>
+                    <Dropdown overlay={(
+                        <Menu onClick={(item) => {
+                            const type = item.key;
+                            console.log(type);
+                        }}>
+                            <Menu.Item key='chart'>图表</Menu.Item>
+                            <Menu.Item key='richText'>富文本</Menu.Item>
+                        </Menu>
+                    )} trigger={['click']}>
+                        <Button>
+                            <Icon type="plus" />添加
+                        </Button>
+                    </Dropdown>
+                </div>
+            </div>
+        );
+    }
+}
+
+function mapStateToProps(state) {
+    const dashboardDesigner = state.present.dashboardDesigner;
+    return { dashboardDesigner }
+}
+export default connect(mapStateToProps)(Header);

+ 37 - 0
src/components/dashboardDesigner/header.less

@@ -0,0 +1,37 @@
+.dashboarddesigner-header {
+    display: flex;
+    justify-content: space-between;
+
+    .toolbar-title {
+        flex: 1;
+        text-align: center;
+        .ant-input-group-wrapper {
+            display: inline-block;
+            vertical-align: middle;
+            width: 200px;
+            margin-bottom: 5px;
+        }
+        .ant-input-group{
+            width: 300px;
+            .input-title {
+                text-align: center;
+                font-size: 18px;
+                border: none;
+                border-bottom-right-radius: 4px;
+                border-top-right-radius: 4px;
+                background-color: transparent;
+            }
+            .ant-input-group-addon {
+                cursor: pointer;
+                border: none;
+                background: transparent;
+                :hover {
+                    color: #40a9ff;
+                }
+            }
+        }
+    }
+}
+.ant-tooltip-arrow {
+    border-bottom-color: rgba(255,255,255,.75) !important;
+}

+ 35 - 69
src/components/dashboardDesigner/layout.jsx

@@ -1,30 +1,35 @@
 import React from 'react'
 import { connect } from 'dva'
-import ReactGridLayout from 'react-grid-layout'
-import '../../models/dashboard'
-import '../../../node_modules/react-grid-layout/css/styles.css'
-import '../../../node_modules/react-resizable/css/styles.css'
-import '../../models/dashboardDesigner'
-import { Icon, Menu, Layout, Switch, Row, Col, Button, Dropdown } from 'antd'
-import ElementConfig from './elementConfig'
+import { Icon, Menu, Layout, Dropdown, Spin } from 'antd'
 import './layout.less'
 import Element from './element'
-import '../../models/dataConnect'
 import html2canvas from 'html2canvas'
 import jsPDF from 'jspdf'
+import DashboardDesignerHeader from './header'
+import DashboardDesignerContent from './content'
+const { Header, Content } = Layout
 
 
 class DashboardDesigner extends React.Component {
 
-    constructor(props) {
-        super(props);
-        var layout = this.loadLayout()
-        this.state = {
-            editMode: true,
-            operation: 'create',
-            visibleBox: false,
-            layout: layout,
-        };
+    // constructor(props) {
+    //     super(props);
+    //     var layout = this.loadLayout()
+    //     this.state = {
+    //         editMode: true,
+    //         operation: 'create',
+    //         visibleBox: false,
+    //         layout: layout,
+    //     };
+    // }
+
+    componentDidMount() {
+        const { dispatch } = this.props;
+        const { code } = this.props.match.params;
+        dispatch({ type: 'chart/fetchList', code: code });
+        if(code !== 'create') {
+            dispatch({ type: 'chart/remoteGroupList', code: code });
+        }
     }
 
     saveToPNG = (element) => {
@@ -139,58 +144,19 @@ class DashboardDesigner extends React.Component {
     }
 
     render() {
-        const { operation, visibleBox, editMode } = this.state;
-        
-        return (
-            <Layout>
-                <Row 
-                    type='flex' 
-                    justify ='space-between'
-                    className='dashboard-header'
-                >
-                        <Col className='dashboard-header-title'                        >
-                            <div>{this.props.dashboardDesigner.basicConfig.title}</div>
-                        </Col>
-                        <Col className='dashboard-toolbar'>
-                            <div>
-                                <Button onClick={() => {
-                                    this.showElementConfigBox("create")
-                                }}>
-                                    添加元素
-                                </Button>
-                                <Button onClick={() => {
-                                    this.saveToPNG(document.body)
-                                }}>
-                                    保存为PNG
-                                </Button>
-                                <span>编辑模式</span>
-                                <Switch 
-                                    checkedChildren="开" 
-                                    unCheckedChildren="关" 
-                                    checked= {editMode}
-                                    
-                                />
-                            </div>
-                        </Col>
-                </Row>
-                <ReactGridLayout 
-                    className={`grid-layout${this.state.editMode ?' grid-layout-edit': ''}`}  
-                    cols={12}
-                    rowHeight={30} 
-                    width={1200}  //TODO: 宽度响应式设计?
-                    isDraggable={editMode}
-                    isResizable={editMode}
-                    compactType="horizontal"
-                >
-                {this.generateElement()}
-                
-                </ReactGridLayout>
-                <ElementConfig 
-                    operation={operation} 
-                    visibleBox={visibleBox}
-                    hideElementConfigBox={this.hideElementConfigBox} />
-            </Layout>
-        )
+        const { loading } = this.props;
+        // const { operation, visibleBox, editMode } = this.state;
+        return <Layout className='dashboarddesigner-layout'>
+            <Header>
+                <DashboardDesignerHeader />
+            </Header>
+            <Content style={{ height: 0 }}>
+                <DashboardDesignerContent />
+            </Content>
+            <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>
+        </Layout>
     }
 
 }

+ 51 - 35
src/components/dashboardDesigner/layout.less

@@ -1,36 +1,52 @@
-.dashboard-header {
-    height:64px;
-    line-height: 64px;
+.dashboarddesigner-layout {
+    height: 100%;
+    overflow: hidden;
+    .ant-layout-header {
+        background: none;
+        padding: 0 10px;
+        height: 40px;
+        line-height: 40px;
+        border-width: 1px 0;
+        border-style: solid;
+        border-color: #CCCCCC;
+    }
+    .ant-layout-content {
+        flex: 1;
+        .ant-layout {
+            height: 100%;
+            .content-header {
+                height: auto;
+                border-top: none;
+            }
+        }
+    }
+    .ant-layout-sider {
+        background: none;
+        border-width: 0 1px 0 1px;
+        border-style: solid;
+        border-color: #CCCCCC;
+        .ant-form-item {
+            margin-bottom: 0;
+        }
+    }
+    .ant-tabs {
+        .chartconfig {
+            .ant-cascader-picker {
+                .ant-cascader-picker-label {
+                    height: 100%;
+                    padding: 0 6px;
+                    .cascader-label {
+                        margin-left: 6px;
+                    }
+                    .empty-label {
+                        color: #bfbfbf;
+                    }
+                }
+            }
+        }
+    }
+    .ant-tabs-bar {
+        margin: 0;
+    }
 }
-.dashboard-header-title {
-    position: relative;
-    left: 5%;
-    top: 5%;
-
-}
-.dashboard-toolbar {
-    position: relative;
-    right: 5%;
-    top: 5%;
-}
-
-.grid-layout {
-    border: 1px solid transparent;
-    margin: 0 5% 0 5%;
-}
-.grid-layout-edit {
-    border: 1px dashed black;
-    
-}
-.grid-item {
-    border: 1px solid transparent;
-    background-color: aqua;
-}
-
-.grid-item-edit {
-    border: 1px dashed black;
-    background-color: pink;
-}
-
-
-
+  

+ 77 - 0
src/components/dashboardDesigner/viewLayout.jsx

@@ -0,0 +1,77 @@
+import React from "react"
+import "./viewLayout.less"
+import ReactGridLayout from 'react-grid-layout'
+import { connect } from 'dva'
+import ChartView from './chartView'
+
+class ViewLayout extends React.PureComponent {
+    constructor(props) {
+        super(props);
+        this.state = {
+            items: [0, 1, 2, 3, 4].map(function (i, key, list) {
+                return {
+                    i: i.toString(),
+                    x: i * 2,
+                    y: 0,
+                    w: i + 1,
+                    h: 2,
+                    add: i === (list.length - 1).toString()
+                };
+            }),
+            newCounter: 0,
+            width: 1100,
+            editMode: true
+        };
+    }
+
+    createElement = (item) => {
+        const { dispatch } = this.props;
+        const { code, layout, chartCode } = item;
+        const removeStyle = {
+            position: "absolute",
+            right: "2px",
+            top: 0,
+            cursor: "pointer"
+        };
+        return (
+            <div key={code} data-grid={{...layout, i: code}}>
+                <ChartView chartCode={chartCode}/>
+                <span className="remove" style={removeStyle} onClick={() => {
+                    dispatch({ type: 'dashboardDesigner/delete', item: item });
+                }}>x</span>
+            </div>
+        );
+    }
+
+    onLayoutChange = (layout) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboardDesigner/changeLayout', layout });
+    }
+
+    render() {
+        const { width, editMode } = this.state;
+        const { dashboardDesigner } = this.props;
+        const { items } = dashboardDesigner;
+        const children = items.map(item => this.createElement(item));
+        return (
+            <div>
+                <ReactGridLayout
+                    width={width}
+                    cols={12}
+                    margin = {editMode ? [2, 2] : [0, 0]}
+                    rowHeight = {100}
+                    isDraggable={editMode}
+                    isResizable={editMode}
+                    onLayoutChange={this.onLayoutChange}
+                    onBreakpointChange={this.onBreakpointChange}
+                    verticalCompact={true}
+                    compactType='vertical'
+                >
+                    {children}
+                </ReactGridLayout>
+            </div>
+        );
+    }
+}
+
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(ViewLayout);

+ 145 - 0
src/components/dashboardDesigner/viewLayout.less

@@ -0,0 +1,145 @@
+
+  .react-grid-layout {
+    background: #eee;
+  }
+  .layoutJSON {
+    background: #ddd;
+    border: 1px solid black;
+    margin-top: 10px;
+    padding: 10px;
+  }
+  .columns {
+    -moz-columns: 120px;
+    -webkit-columns: 120px;
+    columns: 120px;
+  }
+  .react-grid-item {
+    box-sizing: border-box;
+  }
+  .react-grid-item:not(.react-grid-placeholder) {
+    background: #ccc;
+    border: 1px solid black;
+  }
+  .react-grid-item.resizing {
+    opacity: 0.9;
+  }
+  .react-grid-item.static {
+    background: #cce;
+  }
+  .react-grid-item .text {
+    font-size: 24px;
+    text-align: center;
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+    margin: auto;
+  }
+  .react-grid-item .minMax {
+    font-size: 12px;
+  }
+  .react-grid-item .add {
+    cursor: pointer;
+  }
+  .react-grid-dragHandleExample {
+    cursor: move; /* fallback if grab cursor is unsupported */
+    cursor: grab;
+    cursor: -moz-grab;
+    cursor: -webkit-grab;
+  }
+  li b {
+    font-size: 19px;
+    line-height: 14px;
+  }
+  
+  .toolbox {
+    background-color: #dfd;
+    width: 100%;
+    height: 120px;
+    overflow: scroll;
+  }
+  
+  .hide-button {
+    cursor: pointer;
+    position: absolute;
+    font-size: 20px;
+    top: 0px;
+    right: 5px;
+  }
+  
+  .toolbox__title {
+    font-size: 24px;
+    margin-bottom: 5px;
+  }
+  .toolbox__items {
+    display: block;
+  }
+  .toolbox__items__item {
+    display: inline-block;
+    text-align: center;
+    line-height: 40px;
+    cursor: pointer;
+    width: 40px;
+    height: 40px;
+    padding: 10px;
+    margin: 5px;
+    border: 1px solid black;
+    background-color: #ddd;
+  }
+  
+
+.react-grid-layout {
+    position: relative;
+    transition: height 200ms ease;
+  }
+  .react-grid-item {
+    transition: all 200ms ease;
+    transition-property: left, top;
+  }
+  .react-grid-item.cssTransforms {
+    transition-property: transform;
+  }
+  .react-grid-item.resizing {
+    z-index: 1;
+    will-change: width, height;
+  }
+  
+  .react-grid-item.react-draggable-dragging {
+    transition: none;
+    z-index: 3;
+    will-change: transform;
+  }
+  
+  .react-grid-item.react-grid-placeholder {
+    background: red;
+    opacity: 0.2;
+    transition-duration: 100ms;
+    z-index: 2;
+    -webkit-user-select: none;
+    -moz-user-select: none;
+    -ms-user-select: none;
+    -o-user-select: none;
+    user-select: none;
+  }
+  
+  .react-grid-item > .react-resizable-handle {
+    position: absolute;
+    width: 20px;
+    height: 20px;
+    bottom: 0;
+    right: 0;
+    cursor: se-resize;
+  }
+  
+  .react-grid-item > .react-resizable-handle::after {
+    content: "";
+    position: absolute;
+    right: 3px;
+    bottom: 3px;
+    width: 5px;
+    height: 5px;
+    border-right: 2px solid rgba(0, 0, 0, 0.4);
+    border-bottom: 2px solid rgba(0, 0, 0, 0.4);
+  }
+  

+ 1 - 1
src/components/datasource/columnConfig.jsx

@@ -1,5 +1,5 @@
 import React from 'react'
-import { Form, Input, Button, Select, Table, Checkbox, Switch, Divider, Icon, Popconfirm } from 'antd'
+import { Form, Input, Button, Select, Table, Checkbox, Divider, Icon, Popconfirm } from 'antd'
 import { connect } from 'dva'
 import COLUMN_TYPE from './columnType.json'
 import { Resizable } from 'react-resizable';

+ 0 - 1
src/components/myPage/fav.jsx

@@ -1,5 +1,4 @@
 import React from 'react';
-import { Table } from 'antd';
 
 class Fav extends React.Component {
     constructor(props) {

+ 9 - 0
src/models/dashboard.js

@@ -4,6 +4,15 @@ import * as service from '../services/index'
 export default {
     namespace: 'dashboard',
     state: {
+        list: [],
+        filterLabel: '',
+        groupList: [],
+        currentGroup: [{
+            code: 'all',
+            label: '全部分组'
+        }],
+        groupDirty: false,
+        
         currentDashboard: {},
         dashboardList: [{            //Dynamic Dashboard指看板(动态) Static Dashboard指报告(静态)
             dashboardID: 1,

+ 40 - 9
src/models/dashboardDesigner.js

@@ -15,22 +15,53 @@ export default {
         },
         parameters: {
         },  //全局可用参数
-        elementList:[{
-            key:0,
-            type:'chart',  //基础元素simple vs 图表元素chart
-            layout:{},
-            content:{},            
+        items: [{
+            code: 'a001',
+            type: 'chart',
+            layout: { x: 0, y: 0, w: 4, h: 2},
+            content: 'jhadsasda',
+            chartCode: '372',
         }, {
-            key:1,
-            type:'simple',
-            layout: {},
-            content:{},
+            code: 'a002',
+            type: 'simple',
+            layout: { x: 2, y: 2, w: 2, h: 2},
+            content: 'hhhhhhhhh',
+            chartCode: '367'
         }],
         configBoxForm: {
         }
     },
     
     reducers: {
+        add(state, action) {
+            let { items } = state;
+            items.push({
+                code: (Math.random() * 1000)+'',
+                type: 'chart',
+                layout: { x: 0, y: 0, w: 2, h: 2},
+                content: new Date(), 
+            });
+            return Object.assign({}, state, {items});
+        },
+        delete(state, action) {
+            let { items } = state;
+            let { item } = action;
+            for(let i = 0; i < items.length; i++) {
+                if(items[i].code === item.code) {
+                    items.splice(i, 1);
+                    break;
+                }
+            }
+            return Object.assign({}, state, {items});
+        },
+        changeLayout(state, action) {
+            const { layout } = action;
+            let { items } = state;
+            for(let i = 0; i < items.length; i++) {
+                items[i].layout = layout;
+            }
+            return Object.assign({}, state, {items});
+        },
         handleFieldChange(state, action) {
             const { name, value } = action;
             let configBoxForm = state.configBoxForm;

+ 1 - 1
src/models/dataSource.js

@@ -318,7 +318,7 @@ export default {
                 const dataSource = yield select(state => state.present.dataSource);
                 const sqlStr = dataSource.newOne.target;
                 let body = {
-                    baseName: dataSource.newOne.userName,
+                    id: dataSource.newOne.code,
                     strSql: sqlStr
                 };
                 const res = yield call(service.fetch, {

+ 2 - 2
src/routes/router.js

@@ -8,7 +8,7 @@ import ChartDesigner from '../components/chartDesigner/layout'
 import DashboardDesigner from '../components/dashboardDesigner/layout'
 // 由于 antd 组件的默认文案是英文,所以需要修改为中文
 import zhCN from 'antd/lib/locale-provider/zh_CN'
-import Demo from '../demo';
+// import Demo from '../demo';
 
 if (!window.localStorage.getItem("isAuthenticated")) {
     window.localStorage.setItem("isAuthenticated", "false");
@@ -30,7 +30,7 @@ function RouterConfig({ history }) {
           <Route sensitive path='/login' component={Login}/>
           <Route sensitive path='/register' component={Register}/>
           <PrivateRoute sensitive path='/chart/:code' component={ChartDesigner}/>
-          <PrivateRoute sensitive path='/dashboard/:id/' component={DashboardDesigner}/>
+          <PrivateRoute sensitive path='/dashboard/:code/' component={DashboardDesigner}/>
           <PrivateRoute path='/' component={MainLayout}/>
         </Switch>
       </Router>