Browse Source

看板组件布局调调整

zhuth 7 years ago
parent
commit
b646c354ba

+ 1 - 1
src/components/chartDesigner/sections/toolbar.jsx

@@ -129,7 +129,7 @@ class Toolbar extends React.Component {
                         })
                     }}>查看列</Button>
                 </div>
-                <FilterBox key={Math.random()} type='chart' code={code} columns={columns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />  
+                {visibleFilterBox && <FilterBox type='chart' code={code} columns={columns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
             </div>
         );
     }

+ 22 - 5
src/components/dashboardDesigner/chooseChartBox.jsx

@@ -13,7 +13,9 @@ class ChooseChartBox extends React.Component {
         super(props);
         this.state = {
             filterLabel: '',
-            selectedRecord: []
+            selectedRecord: [],
+            screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
+            screenHeight: document.documentElement.clientHeight || document.body.clientHeight
         };
     }
 
@@ -22,6 +24,13 @@ class ChooseChartBox extends React.Component {
         dispatch({ type: 'chart/fetchList' });
     }
 
+    onWindowResize = () => {
+        this.setState({
+            screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
+            screenHeight: document.documentElement.clientHeight || document.body.clientHeight
+        });
+    }
+
     changeSelected = (record) => {
         let arr = this.state.selectedRecord;
         let findIndex = arr.findIndex(a => a.code === record.code);
@@ -64,7 +73,10 @@ class ChooseChartBox extends React.Component {
 
     render() {
         const { visibleBox, hideBox, dashboardDesigner, chart } = this.props;
-        const { selectedRecord } = this.state;
+        const { selectedRecord, screenWidth, screenHeight } = this.state;
+        const tableBodyWidth = screenWidth * 0.8 - 10 - 10 - 18;
+        const tableBodyHeight = screenHeight * 0.8 - 65 - 53 - 38 - 130;
+        const tableRowHeight = 38;
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         let filterLabel = this.state.filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         const columns = [{
@@ -133,6 +145,8 @@ class ChooseChartBox extends React.Component {
         return (
             <Modal
                 className='choosechart-box'
+                width='80%'
+                height='80%'
                 title={
                     <Row>
                         <Col span={14}>选择图表</Col>
@@ -155,14 +169,17 @@ class ChooseChartBox extends React.Component {
             >
                 <Table
                     className='choosechart-table'
-                    columns={columns}
+                    columns={columns.map(c => ({
+                        ...c,
+                        width: 100
+                    }))}
                     dataSource={chart.list.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;
                     })}
                     size='small'
-                    scroll={{x: false, y: 471}}
-                    pagination={false}
+                    scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
+                    pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
                     onRow={(record) => {
                         return {
                             onClick: () => {

+ 0 - 1
src/components/dashboardDesigner/chooseChartBox.less

@@ -1,5 +1,4 @@
 .choosechart-box {
-    width: 600px !important;
     .ant-modal-body {
         padding: 0;
         max-height: 50vh;

+ 16 - 0
src/components/dashboardDesigner/configForm.jsx

@@ -0,0 +1,16 @@
+import { connect } from 'dva'
+import { Form, Input, Divider, Select, Checkbox } from 'antd'
+const { TextArea } = Input;
+
+const ConfigForm = ({ dashboardDesigner, dispatch }) => {
+
+    return <Form className='config-form'>
+        <Divider>基础设置</Divider>
+        <Form.Item label='备注'>
+            <TextArea placeholder="Autosize height with minimum and maximum number of lines" autosize={{ minRows: 2, maxRows: 6 }} />
+        </Form.Item>
+        <Divider>过滤字段设置</Divider>
+    </Form>
+}
+
+export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(ConfigForm);

+ 122 - 31
src/components/dashboardDesigner/content.jsx

@@ -1,10 +1,13 @@
 import React from 'react'
 import { findDOMNode } from 'react-dom'
-import { Layout, Button, Switch, Dropdown, Menu, Icon } from 'antd'
+import { Layout, Tooltip, Button, Tag, Dropdown, Menu, Icon } from 'antd'
 import { connect } from 'dva'
 import ViewLayout from './viewLayout'
 import ChooseChartBox from './chooseChartBox'
-const { Header, Content } = Layout
+import FilterBox from '../common/filterBox/filterBox'
+import ConfigForm from './configForm'
+import moment from 'moment'
+const { Header, Content, Sider } = Layout
 
 class DashboardDesignerContent extends React.Component {
     constructor(props) {
@@ -15,9 +18,8 @@ class DashboardDesignerContent extends React.Component {
                 width: 0,
                 height: 0,
             },
-            editMode: true,
-            operation: 'create',
-            visibleBox: false,
+            visibleChooseChartBox: false,
+            visibleFilterBox: false,
         };
     }
 
@@ -34,14 +36,25 @@ class DashboardDesignerContent extends React.Component {
 
     showBox = (o) => {
         this.setState({
-            operation: o,
-            visibleBox: true
+            visibleChooseChartBox: true
         });
     }
 
     hideBox = (o) => {
         this.setState({
-            visibleBox: false
+            visibleChooseChartBox: false
+        });
+    }
+
+    showFilterBox = (e) => {
+        this.setState({
+            visibleFilterBox: true
+        });
+    }
+
+    hideFilterBox = (e) => {
+        this.setState({
+            visibleFilterBox: false,
         });
     }
 
@@ -56,34 +69,95 @@ class DashboardDesignerContent extends React.Component {
         if(!flag && this.state.contentSize.scroll === _scroll) { // 如果滚动条没有变化则直接退出
             return;
         }
+        console.log(contentEl.offsetWidth);
         this.setState({
             contentSize: {
                 scroll: _scroll,
-                width: contentEl.offsetWidth - (_scroll ? 25 : 0), // 有滚动条时需要减去滚动条的宽度
+                width: contentEl.offsetWidth - (_scroll ? 28 : 10), // 有滚动条时需要减去滚动条的宽度
                 height: contentEl.clientHeight
             }
         });
     }
 
+    createFilterLabel = (filter) => {
+        let { label, operator, operatorLabel, type, value1, value2 } = filter;
+        let filterLabel;
+
+        if(type === 'string' || type === 'index') {
+            if(operator === 'null' || operator === 'notNull') {
+                filterLabel = `${label} ${operatorLabel}`;
+            }else {
+                filterLabel = `${label} ${operatorLabel} ${value1}`;
+            }
+        }else if(type === 'scale') {
+            if(operator === 'null' || operator === 'notNull') {
+                filterLabel = `${label} ${operatorLabel}`;
+            }else if(operator === 'between') {
+                filterLabel = `${label} ${operatorLabel} ${value1} ~ ${value2}`; 
+            }else {
+                filterLabel = `${label} ${operatorLabel} ${value1}`; 
+            }
+        }else if(type === 'time') {
+            value1 = moment(value1).format('YYYY/MM/DD');
+            value2 = moment(value2).format('YYYY/MM/DD');
+            
+            if(operator === 'null' || operator === 'notNull') {
+                filterLabel = `${label} ${operatorLabel}`;
+            }else if(operator === 'between') {
+                filterLabel = `${label} ${operatorLabel} ${value1} ~ ${value2}`;
+            }else {
+                filterLabel = `${label} ${operatorLabel} ${value1}`;
+            }
+        }else if(type === 'categorical') {
+            if(operator === 'null' || operator === 'notNull') {
+                filterLabel = `${label} ${operatorLabel}`;
+            }else {
+                filterLabel = `${label} ${operatorLabel} ${value1}`;
+            }
+        }else {
+            filterLabel = '错误条件';
+        }
+        return filterLabel;
+    }
+
     render() {
-        const { contentSize, editMode, operation, visibleBox } = this.state;
+        const { dashboardDesigner, dispatch } = this.props;
+        const { code, editMode, filterColumns, filters } = dashboardDesigner;
+        const { contentSize, visibleChooseChartBox, visibleFilterBox } = this.state;
+
+        let tags = filters.map((f, i)=>{
+            return {
+                key: f.key,
+                label: this.createFilterLabel(f),
+                using: f.type ? f.using : false
+            }
+        });
+
         return <Layout className='content'>
             <Header>
-                <div>
-                    <Switch
-                        className={`mode-switch ${editMode ? 'edit-mode-switch' : 'view-mode-switch'}`}
-                        checked={editMode}
-                        checkedChildren="编辑"
-                        unCheckedChildren="浏览"
-                        onChange={(checked) => {
-                            this.setState({
-                                editMode: checked
-                            })
-                        }}
-                    />
-                </div>
-                <div>
-                    {editMode && <Dropdown overlay={(
+                <div className='filters'>
+                    <div style={{ margin: '0 8px 0 10px' }}>筛选:</div>
+                        {tags.map(tag => (
+                            <Tag
+                                className={`filter-tag ${tag.using?'filter-tag-using':''}`}
+                                key={tag.key}
+                                closable={false}
+                                onClick={this.filterUsingChange}
+                                data-key={tag.key}
+                            >
+                                {tag.label}
+                            </Tag>
+                        ))}
+                        <Tag
+                            onClick={this.showFilterBox}
+                            className={`filter-tag filter-tag-add`}
+                        >
+                            <Icon type="filter" theme="outlined" />
+                        </Tag>
+                    </div>
+                    {visibleFilterBox && <FilterBox type='dashboard' code={code} columns={filterColumns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
+                <div className='viewtype'>
+                    {/* {editMode && <Dropdown overlay={(
                         <Menu onClick={(item) => {
                             const type = item.key;
                             if(type === 'chart') {
@@ -100,18 +174,35 @@ class DashboardDesignerContent extends React.Component {
                         <Button>
                             <Icon type="plus" />添加
                         </Button>
-                    </Dropdown>}
-                    <ChooseChartBox operation={operation} visibleBox={visibleBox} hideBox={this.hideBox} />
+                    </Dropdown>} */}
+                    <Tooltip title="图表">
+                        <Icon className='viewtype-icon' type="area-chart" theme="outlined" onClick={(item) => {
+                            this.showBox("create");
+                        }}/>
+                    </Tooltip >
+                    <Tooltip title="富文本">
+                        <Icon className='viewtype-icon' type="book" theme="outlined" onClick={() => {
+                            dispatch({ type: 'dashboardDesigner/addRichText' });
+                        }}/>
+                    </Tooltip>
+                    <ChooseChartBox visibleBox={visibleChooseChartBox} hideBox={this.hideBox} />
                 </div>
             </Header>
-            <Content ref='contentEl' className='dashboard-content'>
-                <ViewLayout contentSize={contentSize} reset={this.refreshContentSize} editMode={editMode}/>
+            <Content className='dashboard-content'>
+                <Layout className='content-layout'>
+                    <Content className='viewlayout' ref='contentEl'>
+                        <ViewLayout contentSize={contentSize} reset={this.refreshContentSize} editMode={editMode}/>
+                    </Content>
+                    <Sider className='config-sider' width={!!editMode ? 300 : 0}>
+                        <ConfigForm />
+                    </Sider>
+                </Layout>
             </Content>
         </Layout>
     }
 }
 function mapStateToProps(state) {
-    const DashboardDesigner = state.present.DashboardDesigner;
-    return { DashboardDesigner }
+    const dashboardDesigner = state.present.dashboardDesigner;
+    return { dashboardDesigner }
 }
 export default connect(mapStateToProps)(DashboardDesignerContent);

+ 18 - 6
src/components/dashboardDesigner/header.jsx

@@ -1,5 +1,5 @@
 import React from 'react'
-import { Input, Icon, Button, Popconfirm } from 'antd'
+import { Input, Icon, Button, Popconfirm, Switch } from 'antd'
 import { connect } from 'dva'
 import './header.less'
 import SettingBox from './settingBox';
@@ -19,6 +19,8 @@ class Header extends React.Component {
 
     render() {
         const { dashboardDesigner, dispatch } = this.props;
+        const { editMode } = dashboardDesigner;
+
         return (
             <div className='dashboarddesigner-header'>
                 <div className='header-item toolbar-back'>
@@ -79,11 +81,21 @@ class Header extends React.Component {
                         }}
                     />
                 </div>
-                <div className='header-item toolbar-buttons'>
-                    <Button onClick={() => this.setState({ visibleSettingBox: true})}>属性设置</Button>
-                    <SettingBox 
-                        visibleSettingBox={this.state.visibleSettingBox} 
-                        hideBox={() => this.setState({visibleSettingBox:false})}
+                <div className='header-item toolbar-viewswitch'>
+                    <Switch
+                        className={`mode-switch ${editMode ? 'edit-mode-switch' : 'view-mode-switch'}`}
+                        checked={editMode}
+                        checkedChildren="编辑"
+                        unCheckedChildren="浏览"
+                        onChange={(checked) => {
+                            dispatch({ type: 'dashboardDesigner/setEditMode', checked });
+                            // 主动触发一次window的resize事件
+                            window.setTimeout(() => {
+                                var e = document.createEvent("Event");
+                                e.initEvent("resize", true, true);
+                                window.dispatchEvent(e);
+                            }, 200);
+                        }}
                     />
                 </div>
             </div>

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

@@ -31,6 +31,14 @@
             }
         }
     }
+    .toolbar-viewswitch {
+        .edit-mode-switch {
+            background-color: #1890ff;
+        }
+        .view-mode-switch {
+            background-color: #51C319;
+        }
+    }
 }
 .ant-tooltip-arrow {
     border-bottom-color: rgba(255,255,255,.75) !important;

+ 57 - 7
src/components/dashboardDesigner/layout.less

@@ -14,10 +14,36 @@
         flex: 1;
         .content {
             height: 100%;
-            .ant-layout-content {
-                height: 100%;
+            &>.dashboard-content {
+                height: calc(~"100% - 20px");
                 margin: 10px;
-                overflow: auto;
+                overflow: hidden;
+                &>.content-layout {
+                    flex-direction: row;
+                    overflow: hidden;
+                    height: 100%;
+                    &>.viewlayout {
+                        padding: 5px;
+                        overflow: auto;
+                        border: 1px solid #CCCCCC;
+                    }
+                    .config-sider {
+                        border: none;
+                        .ant-layout-sider-children {
+                            margin: 0 0 0 10px;
+                            padding: 5px;
+                            border: 1px solid #CCCCCC;
+                            .config-form {
+                                .ant-divider {
+                                    margin: 10px 0;
+                                }
+                                .ant-form-item-label {
+                                    line-height: 24px;
+                                }
+                            }
+                        }
+                    }
+                }
             }
             .ant-layout-header {
                 background: none;
@@ -29,11 +55,35 @@
                 border-color: #CCCCCC;
                 display: flex;
                 justify-content: space-between;
-                .edit-mode-switch {
-                    background-color: #1890ff;
+                .filters {
+                    display: flex;
+                    .filter-tag {
+                        max-width: 400px;
+                        overflow: hidden;
+                        text-overflow: ellipsis;
+                        border-style: dashed;
+                        margin: 8px 2px 0 2px;
+                    }
+                    .filter-tag-using {
+                        border-style: solid;
+                        border-color: #1890FF;
+                        background-color: #1890ff;
+                        color: white;
+                    }
+                    .filter-tag-add {
+                        background-color: white;
+                        border-style: solid;
+                    }
                 }
-                .view-mode-switch {
-                    background-color: #51C319;
+                .viewtype {
+                    .viewtype-icon {
+                        font-size: 20px;
+                        cursor: pointer;
+                        margin-left: 5px;
+                        &:hover {
+                            color: #1890FF;
+                        }
+                    }
                 }
             }
         }

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

@@ -31,9 +31,9 @@ class ViewLayout extends React.PureComponent {
     }
 
     createElement = (item, isPreview) => {
-        const { dispatch, editMode } = this.props;
+        const { dispatch, dashboardDesigner } = this.props;
+        const { editMode } = dashboardDesigner;
         const { code, name, viewType, layout, chartCode } = item;
-        console.log(this.state.screenHeight);
         return (
             <div className={`chartview${editMode ? ' chartview-edit' : ''}`} key={code} data-grid={layout}>
                 <div className='chartview-toolbar mover'>
@@ -83,7 +83,8 @@ class ViewLayout extends React.PureComponent {
     }
 
     render() {
-        const { dashboardDesigner, contentSize, editMode } = this.props;
+        const { dashboardDesigner, contentSize } = this.props;
+        const { editMode } = dashboardDesigner;
         const { visiblePreviewBox, previewItem } = this.state;
         const children = dashboardDesigner.items.map((item) => this.createElement(item));
         return (<div>

+ 12 - 2
src/models/dashboardDesigner.js

@@ -11,7 +11,10 @@ export default {
             description: '',
             thumbnail: '',
             groupCode: '',
-            dirty: false
+            dirty: false,
+            editMode: true,
+            filterColumns: [],
+            filters: [],
         },
         name: '标题',
         defaultLayout: { x: 0, y: 50, w: 12, h: 6, minW: 2, maxW: 12, minH: 1 },
@@ -21,7 +24,10 @@ export default {
         description: '',
         thumbnail: '',
         groupCode: '',
-        dirty: false
+        dirty: false,
+        editMode: true,
+        filterColumns: [],
+        filters: []
     },
     
     reducers: {
@@ -117,6 +123,10 @@ export default {
         reset(state, action) {
             let newState = Object.assign({}, state, state.originData);
             return Object.assign({}, newState);
+        },
+        setEditMode(state, action) {
+            const { checked } = action;
+            return { ...state, editMode: checked };
         }
     },
 

+ 0 - 1
src/routes/privateRoute.jsx

@@ -2,7 +2,6 @@ import { Route } from 'dva/router'
 import RootLayout from '../components/common/rootLayout'
 import moment from 'moment'
 
-console.log(moment);
 export default ({ component: Component, ...rest }) => (
     <Route
         {...rest}