Browse Source

报表详情页结构样式调整

zhuth 6 years ago
parent
commit
3c7f24dc80

+ 0 - 7
src/components/common/dataPreview/dataPreview.less

@@ -9,13 +9,6 @@
         padding-top: 40px;
         padding-top: 40px;
         overflow: hidden;
         overflow: hidden;
         
         
-        .ant-modal-close {
-            .ant-modal-close-x {
-                width: 40px;
-                height: 40px;
-                line-height: 40px;
-            }
-        }
         .ant-modal-body {
         .ant-modal-body {
             height: 100%;
             height: 100%;
             padding: 0px 10px;
             padding: 0px 10px;

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

@@ -86,7 +86,7 @@ class ChartView extends React.Component {
             }
             }
         }else if(viewType === 'richText') { // 富文本类型
         }else if(viewType === 'richText') { // 富文本类型
             children = <RichTextEditor readOnly={!editMode} 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', item: { ...item, content } });
             }}/>
             }}/>
         }else {
         }else {
             children = <div className='mover'>错误类型</div>
             children = <div className='mover'>错误类型</div>

+ 83 - 68
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, message } from 'antd'
+import { Modal, Checkbox, Row, Col, Table, message } 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 ListFilter from '../common/listFilter/index'
 import ListFilter from '../common/listFilter/index'
 import './chooseChartBox.less'
 import './chooseChartBox.less'
+import CHART_TYPE from '../chartDesigner/sections/chartType'
 
 
 class ChooseChartBox extends React.Component {
 class ChooseChartBox extends React.Component {
 
 
@@ -15,6 +16,7 @@ class ChooseChartBox extends React.Component {
             filterLabel: '',
             filterLabel: '',
             filterItem: { name: 'name', label: '图表名称', type: 'string' },
             filterItem: { name: 'name', label: '图表名称', type: 'string' },
             selectedRecord: -1,
             selectedRecord: -1,
+            selectedRecords: [],
             screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
             screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
             screenHeight: document.documentElement.clientHeight || document.body.clientHeight
             screenHeight: document.documentElement.clientHeight || document.body.clientHeight
         };
         };
@@ -38,20 +40,36 @@ class ChooseChartBox extends React.Component {
     }
     }
 
 
     changeSelected = (record) => {
     changeSelected = (record) => {
-        this.setState({
-            selectedRecord: record
-        });
+        const { dashboardDesigner } = this.props;
+        const { selectedRecords } = this.state;
+        let idx = selectedRecords.findIndex(s => s.code === record.code);
+        if(dashboardDesigner.items.findIndex(i => i.chartCode===record.code) === -1) {
+            if(idx === -1) {
+                selectedRecords.push(record);
+            }else {
+                selectedRecords.splice(idx, 1);
+            }
+            this.setState({
+                selectedRecords: selectedRecords
+            });
+        }
     }
     }
 
 
-    okHandler = (model) => {
-        const { selectedRecord } = this.state;
+    okHandler = () => {
+        // const { selectedRecord } = this.state;
+        // const { dispatch, hideBox } = this.props;
+        // if(selectedRecord) {
+        //     dispatch({ type: 'dashboardDesigner/addChart', chart: selectedRecord });
+        //     hideBox();
+        // }else {
+        //     message.warning('未选中图表');
+        // }
+        const { selectedRecords } = this.state;
         const { dispatch, hideBox } = this.props;
         const { dispatch, hideBox } = this.props;
-        if(selectedRecord) {
-            dispatch({ type: 'dashboardDesigner/addChart', chart: selectedRecord });
-            hideBox();
-        }else {
-            message.warning('未选中图表');
+        if(selectedRecords.length > 0) {
+            dispatch({ type: 'dashboardDesigner/addCharts', charts: selectedRecords });
         }
         }
+        hideBox();
     }
     }
 
 
     onSearch = (list) => {
     onSearch = (list) => {
@@ -94,7 +112,7 @@ class ChooseChartBox extends React.Component {
 
 
     render() {
     render() {
         const { visibleBox, hideBox, dashboardDesigner, chart } = this.props;
         const { visibleBox, hideBox, dashboardDesigner, chart } = this.props;
-        const { selectedRecord, screenWidth, screenHeight, filterItem, filterLabel: stateFilterLabel } = this.state;
+        const { selectedRecords, selectedRecord, screenWidth, screenHeight, filterItem, filterLabel: stateFilterLabel } = 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;
@@ -106,16 +124,17 @@ class ChooseChartBox extends React.Component {
             width: 50,
             width: 50,
             render: (text, record) => {
             render: (text, record) => {
                 // return <Checkbox checked={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1 || selectedRecord.findIndex(s => s.code === record.code) !== -1 } disabled={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1}/>
                 // return <Checkbox checked={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1 || selectedRecord.findIndex(s => s.code === record.code) !== -1 } disabled={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1}/>
-                return <Radio
-                    checked={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1 || selectedRecord.code === record.code }
-                    disabled={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1}
-                />
+                return <Checkbox checked={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1 || selectedRecords.findIndex(s => s.code === record.code) !== -1 } disabled={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1}/>
+                // return <Radio
+                //     checked={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1 || selectedRecord.code === record.code }
+                //     disabled={dashboardDesigner.items.findIndex(i => i.chartCode===record.code)!==-1}
+                // />
             }
             }
         }, {
         }, {
             title: '名称',
             title: '名称',
             dataIndex: 'name',
             dataIndex: 'name',
             key: 'name',
             key: 'name',
-            width: 100,
+            width: 200,
             render: (text, record) => {
             render: (text, record) => {
                 return <div>
                 return <div>
                     <div>
                     <div>
@@ -134,11 +153,17 @@ class ChooseChartBox extends React.Component {
                     </div>
                     </div>
                 </div>
                 </div>
             }
             }
+        }, {
+            title: '图形类别',
+            dataIndex: 'type',
+            key: 'type',
+            width: 100,
+            render: text => text ? CHART_TYPE.find(t => t.type === text).label : '无'
         }, {
         }, {
             title: '数据源',
             title: '数据源',
             dataIndex: 'dataSourceName',
             dataIndex: 'dataSourceName',
             key: 'dataSourceName',
             key: 'dataSourceName',
-            width: 100,
+            width: 200,
         }, {
         }, {
             title: '创建人',
             title: '创建人',
             dataIndex: 'creatorName',
             dataIndex: 'creatorName',
@@ -172,7 +197,6 @@ class ChooseChartBox extends React.Component {
             title: '说明',
             title: '说明',
             dataIndex: 'description',
             dataIndex: 'description',
             key: 'description',
             key: 'description',
-            width: 200,
             render: (text, record) => {
             render: (text, record) => {
                 return (
                 return (
                     <span>
                     <span>
@@ -195,61 +219,52 @@ class ChooseChartBox extends React.Component {
                 className='choosechart-box'
                 className='choosechart-box'
                 width='80%'
                 width='80%'
                 height='80%'
                 height='80%'
-                title={
-                    <Row>
-                        <Row>
-                            <Col >选择图表</Col>
-                        </Row>
-                        <Row type='flex' justify='end'>
-                            <Col style={{ padding: '0 5px' }}>
-                                <ListFilter
-                                    modelName={null}
-                                    model={{
-                                        filterItems: chart.filterItems,
-                                        filterItem,
-                                        filterLabel: stateFilterLabel,
-                                    }}
-                                    onChangeFilterItem={(filterItem) => {
-                                        this.setState({
-                                            filterItem
-                                        });
-                                    }}
-                                    onChangeFilterValue={(filterLabel) => {
-                                        this.setState({
-                                            filterLabel
-                                        });
-                                    }}
-                                />
-                            </Col>
-                        </Row>
-                    </Row>
-                }
+                title='选择图表'
                 visible={visibleBox}
                 visible={visibleBox}
-                onOk={() => {this.setState({ filterLabel: '', selectedRecord: -1 });this.okHandler()}}
-                onCancel={() => {this.setState({ filterLabel: '', selectedRecord: -1 });hideBox()}}
+                onOk={this.okHandler}
+                onCancel={hideBox}
                 maskClosable={false}
                 maskClosable={false}
                 destroyOnClose={true}
                 destroyOnClose={true}
             >
             >
-                <Table
-                    className='choosechart-table'
-                    columns={columns.map(c => ({
-                        ...c,
-                        width: 100
-                    }))}
-                    dataSource={this.onSort(this.onSearch(chart.list))}
-                    size='small'
-                    scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
-                    pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
-                    onRow={(record) => {
-                        return {
-                            onClick: () => {
-                                if(dashboardDesigner.items.findIndex(i => i.chartCode===record.code)===-1) {
+                <div>
+                    <Row type='flex' justify='end'>
+                        <Col style={{ padding: '8px' }}>
+                            <ListFilter
+                                modelName={null}
+                                model={{
+                                    filterItems: chart.filterItems,
+                                    filterItem,
+                                    filterLabel: stateFilterLabel,
+                                }}
+                                onChangeFilterItem={(filterItem) => {
+                                    this.setState({
+                                        filterItem
+                                    });
+                                }}
+                                onChangeFilterValue={(filterLabel) => {
+                                    this.setState({
+                                        filterLabel
+                                    });
+                                }}
+                            />
+                        </Col>
+                    </Row>
+                    <Table
+                        className='choosechart-table'
+                        columns={columns}
+                        dataSource={this.onSort(this.onSearch(chart.list)).map((d, i) => ({ ...d, key: i }))}
+                        size='small'
+                        scroll={{ x: columns ? columns.length * 100 : tableBodyWidth, y: tableBodyHeight }}
+                        pagination={{ defaultPageSize: Math.floor(tableBodyHeight/tableRowHeight) || 10 }}
+                        onRow={(record) => {
+                            return {
+                                onClick: () => {
                                     this.changeSelected(record);
                                     this.changeSelected(record);
                                 }
                                 }
-                            }
-                        };
-                    }}
-                />
+                            };
+                        }}
+                    />
+                </div>
             </Modal>
             </Modal>
         )
         )
     } 
     } 

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

@@ -1,13 +1,17 @@
 .choosechart-box {
 .choosechart-box {
     .ant-modal-body {
     .ant-modal-body {
         padding: 0;
         padding: 0;
-        max-height: 50vh;
+        max-height: 60vh;
         overflow-y: auto;
         overflow-y: auto;
         .choosechart-table {
         .choosechart-table {
             .ant-table-header {
             .ant-table-header {
                 overflow-y: hidden;
                 overflow-y: hidden;
                 margin-right: 6px;
                 margin-right: 6px;
             }
             }
+            .ant-table-body {
+                overflow-x: hidden !important;
+                margin-top: 0;
+            }
         }
         }
     }
     }
 }
 }

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

@@ -70,7 +70,7 @@ class ConfigSider extends React.Component {
         const { dashboardDesigner, dispatch } = this.props;
         const { dashboardDesigner, dispatch } = this.props;
         const { visibleCusFilterBox, copyDisabled, copyText } = this.state;
         const { visibleCusFilterBox, copyDisabled, copyText } = this.state;
 
 
-        return <Form className='config-sider' layout={'vertical'}>
+        return <Form className='form-config' layout={'vertical'}>
             <Divider>报表制作</Divider>
             <Divider>报表制作</Divider>
             {this.generateViewTypes()}
             {this.generateViewTypes()}
             <Divider>字段过滤</Divider>
             <Divider>字段过滤</Divider>

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

@@ -1,4 +1,4 @@
-.config-sider {
+.form-config {
     .ant-divider {
     .ant-divider {
         margin: 10px 0;
         margin: 10px 0;
     }
     }

+ 33 - 21
src/components/dashboardDesigner/content.jsx

@@ -19,6 +19,7 @@ class DashboardDesignerContent extends React.Component {
                 height: 0,
                 height: 0,
             },
             },
             visibleFilterBox: false,
             visibleFilterBox: false,
+            closeFilters: false,
         };
         };
         this.contentRef=React.createRef();
         this.contentRef=React.createRef();
     }
     }
@@ -64,8 +65,10 @@ class DashboardDesignerContent extends React.Component {
             }; 
             }; 
         }
         }
         let _scroll = contentEl.scrollHeight > contentEl.clientHeight;
         let _scroll = contentEl.scrollHeight > contentEl.clientHeight;
+        let viewEl = contentEl.getElementsByClassName('dashboard-viewcontent')[0];
+        let padding = viewEl.getBoundingClientRect().left - contentEl.getBoundingClientRect().left;
 
 
-        let width = contentEl.offsetWidth - 10 - (_scroll ? 19 : 2) // 有滚动条时需要减去滚动条的宽度
+        let width = contentEl.offsetWidth - padding * 2 - (_scroll ? 10 : 2) // 有滚动条时需要减去滚动条的宽度
         if(width > 0 && width !== lastContentSize.width) {
         if(width > 0 && width !== lastContentSize.width) {
             this.setState({
             this.setState({
                 lastContentSize: {
                 lastContentSize: {
@@ -152,30 +155,11 @@ class DashboardDesignerContent extends React.Component {
     render() {
     render() {
         const { dashboardDesigner, isOwner, isShareView, isShareKeyView, isViewMode } = this.props;
         const { dashboardDesigner, isOwner, isShareView, isShareKeyView, isViewMode } = this.props;
         const { dataSources, editMode, filters, relationColumns } = dashboardDesigner;
         const { dataSources, editMode, filters, relationColumns } = dashboardDesigner;
-        const { visibleFilterBox, lastContentSize } = this.state;
+        const { visibleFilterBox, lastContentSize, closeFilters } = this.state;
 
 
         const contentSize = this.getContentSize();
         const contentSize = this.getContentSize();
 
 
         return <Layout className='content'>
         return <Layout className='content'>
-            <Header>
-                {/* <div className='toggle'><Icon type="caret-up" /></div> */}
-                <div className='filters'>
-                    {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Tag
-                        onClick={this.showFilterBox}
-                        className={`filter-tag filter-tag-add`}
-                    >
-                        <Icon type="filter" theme="outlined" />
-                    </Tag>}
-                    {filters.map(f => (
-                        <Filter
-                            key={f.key}
-                            filter={f}
-                            changeFilterValue={this.changeFilterValue}
-                        />
-                    ))}
-                </div>
-                {visibleFilterBox && <FilterBox key={Math.random()} dataSources={dataSources} relationColumns={relationColumns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
-            </Header>
             <Content className={`dashboard-content${(isShareView || isShareKeyView || isViewMode) ? ' nomargin' : ''}`}>
             <Content className={`dashboard-content${(isShareView || isShareKeyView || isViewMode) ? ' nomargin' : ''}`}>
                 <Layout className='content-layout'>
                 <Layout className='content-layout'>
                     {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Sider className={`config-sider${ (isOwner && editMode) ? '' : ' config-sider-closed' }`} width={(isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode) ? 200 : 0}>
                     {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Sider className={`config-sider${ (isOwner && editMode) ? '' : ' config-sider-closed' }`} width={(isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode) ? 200 : 0}>
@@ -185,6 +169,34 @@ class DashboardDesignerContent extends React.Component {
                         这里直接用main标签而不用antd的Header组件是为了让ref能够定位到对应的dom元素
                         这里直接用main标签而不用antd的Header组件是为了让ref能够定位到对应的dom元素
                     */}
                     */}
                     <main ref={this.contentRef} className='viewlayout ant-layout-content'>
                     <main ref={this.contentRef} className='viewlayout ant-layout-content'>
+                        <Header>
+                            {/* <div className='toggle'><Icon type="caret-up" /></div> */}
+                            <div className={`filters${closeFilters ? ' closed': ''}`}>
+                                <div className='content'>
+                                    {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Tag
+                                        onClick={this.showFilterBox}
+                                        className={`filter-tag filter-tag-add`}
+                                    >
+                                        <Icon type="filter" theme="outlined" />
+                                    </Tag>}
+                                    {filters.map(f => (
+                                        <Filter
+                                            key={f.key}
+                                            filter={f}
+                                            changeFilterValue={this.changeFilterValue}
+                                        />
+                                    ))}
+                                </div>
+                                <div className='right'>
+                                    <Icon title={closeFilters ? '展开' : '收起'} type={closeFilters ? 'caret-up' : 'caret-down'} onClick={() => {
+                                        this.setState({
+                                            closeFilters: !closeFilters
+                                        });
+                                    }}/>
+                                </div>
+                            </div>
+                            {visibleFilterBox && <FilterBox key={Math.random()} dataSources={dataSources} relationColumns={relationColumns} filterData={filters} visibleFilterBox={visibleFilterBox} showFilterBox={this.showFilterBox} hideFilterBox={this.hideFilterBox} createFilters={this.createFilters} />}
+                        </Header>
                         <ViewLayout isOwner={isOwner} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} contentSize={contentSize} lastContentSize={lastContentSize} editMode={editMode}/>
                         <ViewLayout isOwner={isOwner} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} contentSize={contentSize} lastContentSize={lastContentSize} editMode={editMode}/>
                     </main>
                     </main>
                 </Layout>
                 </Layout>

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

@@ -229,7 +229,7 @@ class CusFilterBox extends React.Component {
             height='80%'
             height='80%'
             title='自定义过滤条件'
             title='自定义过滤条件'
             visible={visibleBox}
             visible={visibleBox}
-            footer={<Button className='okbtn' onClick={() => {
+            footer={<Button className='okbtn' type='primary' onClick={() => {
                 let relationColumns = this.state.relationColumns;
                 let relationColumns = this.state.relationColumns;
                 let flag = true;
                 let flag = true;
                 for(let i = 0; i < relationColumns.length; i++) {
                 for(let i = 0; i < relationColumns.length; i++) {

+ 5 - 0
src/components/dashboardDesigner/cusFilterBox.less

@@ -131,4 +131,9 @@
             }
             }
         }
         }
     }
     }
+    .ant-modal-footer {
+        .okbtn {
+            width: 100%;
+        }
+    }
 }
 }

+ 7 - 7
src/components/dashboardDesigner/header.jsx

@@ -73,13 +73,6 @@ class Header extends React.Component {
                     }}>
                     }}>
                         <Icon type='left' />返回
                         <Icon type='left' />返回
                     </Button>}
                     </Button>}
-                    {this.isOwner() && <Button onClick={() => {
-                        if(dashboardDesigner.code && dashboardDesigner.code !== -1) {
-                            dispatch({ type: 'dashboard/remoteModify' });
-                        }else {
-                            dispatch({ type: 'dashboard/remoteAdd' });
-                        }
-                    }}><Icon type='save' />保存</Button>}
                 </div>
                 </div>
                 <div className='header-item toolbar-title'>
                 <div className='header-item toolbar-title'>
                     <Input
                     <Input
@@ -113,6 +106,13 @@ class Header extends React.Component {
                             }, 300);
                             }, 300);
                         }}
                         }}
                     />}
                     />}
+                    {this.isOwner() && <Button style={{ marginLeft: '8px' }} onClick={() => {
+                        if(dashboardDesigner.code && dashboardDesigner.code !== -1) {
+                            dispatch({ type: 'dashboard/remoteModify' });
+                        }else {
+                            dispatch({ type: 'dashboard/remoteAdd' });
+                        }
+                    }}><Icon type='save' />保存</Button>}
                 </div>
                 </div>
             </div>
             </div>
         );
         );

+ 2 - 2
src/components/dashboardDesigner/layout.jsx

@@ -50,9 +50,9 @@ class DashboardDesigner extends React.Component {
     render() {
     render() {
         const { dashboardDesigner, isShareView, isShareKeyView, isViewMode, afterRefresh } = this.props;
         const { dashboardDesigner, isShareView, isShareKeyView, isViewMode, afterRefresh } = this.props;
         const { loading } = dashboardDesigner;
         const { loading } = dashboardDesigner;
-        return <Layout className='dashboarddesigner-layout'>
+        return <Layout className='layout-dashboarddesigner'>
             {!isShareView && !isShareKeyView && !isViewMode && <Header>
             {!isShareView && !isShareKeyView && !isViewMode && <Header>
-                <DashboardDesignerHeader updateThumbnail={this.updateThumbnail} />
+                <DashboardDesignerHeader />
             </Header>}
             </Header>}
             <Content>
             <Content>
                 <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} afterRefresh={afterRefresh}/>
                 <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} afterRefresh={afterRefresh}/>

+ 41 - 21
src/components/dashboardDesigner/layout.less

@@ -1,4 +1,4 @@
-.dashboarddesigner-layout {
+.layout-dashboarddesigner {
     height: 100%;
     height: 100%;
     overflow: hidden;
     overflow: hidden;
     &>.ant-layout-header {
     &>.ant-layout-header {
@@ -15,7 +15,6 @@
         .content {
         .content {
             height: 100%;
             height: 100%;
             &>.dashboard-content {
             &>.dashboard-content {
-                height: calc(~"100% - 20px");
                 margin: 10px;
                 margin: 10px;
                 overflow: hidden;
                 overflow: hidden;
                 &.nomargin {
                 &.nomargin {
@@ -27,11 +26,16 @@
                     height: 100%;
                     height: 100%;
                     background: @content-background-color;
                     background: @content-background-color;
                     &>.viewlayout {
                     &>.viewlayout {
-                        padding: 5px 5px 50px 5px;
+                        display: flex;
+                        flex-direction: column;
+                        padding: 0;
                         overflow-x: hidden;
                         overflow-x: hidden;
-                        border: 1px solid @border-color-base;
+                        >.dashboard-viewcontent {
+                            flex: 1;
+                            margin: 8px;
+                        }
                     }
                     }
-                    .config-sider {
+                    >.config-sider {
                         border: none;
                         border: none;
                         .ant-layout-sider-children {
                         .ant-layout-sider-children {
                             margin: 0 10px 0 0;
                             margin: 0 10px 0 0;
@@ -65,26 +69,42 @@
                 .filters {
                 .filters {
                     display: flex;
                     display: flex;
                     width: 100%;
                     width: 100%;
-                    flex-wrap: wrap;
-                    border-top: 1px solid @border-color-base;
+                    justify-content: space-between;
+                    border-bottom: 1px solid @border-color-base;
                     padding-left: 8px;
                     padding-left: 8px;
-                    .filter-tag {
-                        max-width: 200px;
+                    transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
+                    &.closed {
+                        height: 39px;
                         overflow: hidden;
                         overflow: hidden;
-                        white-space: nowrap;
-                        text-overflow: ellipsis;
-                        border-style: dashed;
-                        margin: 8px 2px 8px 2px;
                     }
                     }
-                    .filter-tag-using {
-                        border-style: solid;
-                        border-color: #1890FF;
-                        background-color: #1890ff;
-                        color: white;
+                    .content {
+                        flex: 1;
+                        display: flex;
+                        flex-wrap: wrap;
+                        .filter-tag {
+                            max-width: 200px;
+                            overflow: hidden;
+                            white-space: nowrap;
+                            text-overflow: ellipsis;
+                            border-style: dashed;
+                            margin: 8px 2px 8px 2px;
+                        }
+                        .filter-tag-using {
+                            border-style: solid;
+                            border-color: #1890FF;
+                            background-color: #1890ff;
+                            color: white;
+                        }
+                        .filter-tag-add {
+                            background-color: white;
+                            border-style: solid;
+                        }
                     }
                     }
-                    .filter-tag-add {
-                        background-color: white;
-                        border-style: solid;
+                    .right {
+                        padding-right: 8px;
+                        .anticon {
+                            cursor: pointer;
+                        }
                     }
                     }
                 }
                 }
             }
             }

+ 38 - 5
src/components/dashboardDesigner/viewLayout.jsx

@@ -1,7 +1,7 @@
 import React from "react"
 import React from "react"
 import "./viewLayout.less"
 import "./viewLayout.less"
 import ReactGridLayout from 'react-grid-layout'
 import ReactGridLayout from 'react-grid-layout'
-import { Icon, Modal } from 'antd'
+import { Icon, Modal, Input } from 'antd'
 import { connect } from 'dva'
 import { connect } from 'dva'
 import ChartView from './chartView'
 import ChartView from './chartView'
 import EmptyContent from '../common/emptyContent/index'
 import EmptyContent from '../common/emptyContent/index'
@@ -13,7 +13,8 @@ class ViewLayout extends React.PureComponent {
             previewItem: null,
             previewItem: null,
             visiblePreviewBox: false,
             visiblePreviewBox: false,
             screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
             screenWidth: document.documentElement.clientWidth || document.body.clientWidth,
-            screenHeight: document.documentElement.clientHeight || document.body.clientHeight
+            screenHeight: document.documentElement.clientHeight || document.body.clientHeight,
+            editingKey: null,
         };
         };
     }
     }
 
 
@@ -32,8 +33,14 @@ class ViewLayout extends React.PureComponent {
         });
         });
     }
     }
 
 
+    modifyItem = (item) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboardDesigner/modifyItem', item });
+    }
+
     createElement = (item, isPreview, reload) => {
     createElement = (item, isPreview, reload) => {
         const { dispatch, main, dashboardDesigner } = this.props;
         const { dispatch, main, dashboardDesigner } = this.props;
+        const { editingKey } = this.state;
         const { currentUser } = main;
         const { currentUser } = main;
         const { editMode } = dashboardDesigner;
         const { editMode } = dashboardDesigner;
         const { code, name, viewType, layout, chartCode } = item;
         const { code, name, viewType, layout, chartCode } = item;
@@ -42,7 +49,32 @@ class ViewLayout extends React.PureComponent {
         return (
         return (
             <div className={`chartview${ isPreview ? ' chartview-preview' : (editMode ? ' chartview-edit' : '')}`} key={code} data-grid={layout}>
             <div className={`chartview${ isPreview ? ' chartview-preview' : (editMode ? ' chartview-edit' : '')}`} key={code} data-grid={layout}>
                 <div className='chartview-toolbar mover'>
                 <div className='chartview-toolbar mover'>
-                    <div className='chart-title'><span>{name}</span></div>
+                    <div className='chart-title'>
+                        {editingKey && editingKey === code ? <Input width={200} ref={node => this['inputRef-' + code] = node} defaultValue={name} onBlur={(e) => {
+                            let value = e.target.value
+                            this.setState({
+                                editingKey: null
+                            }, () => {
+                                !!value.trim() && this.modifyItem({ ...item, name: value });
+                            });
+                        }} onPressEnter={(e) => {
+                            let value = e.target.value
+                            this.setState({
+                                editingKey: null
+                            }, () => {
+                                !!value.trim() && this.modifyItem({ ...item, name: value });
+                            });
+                        }}/> : <span>{name}</span>}
+                        <div className='tools'>
+                            {editMode && (!editingKey || editingKey !== code) && <Icon type='edit' title='修改' style={{ cursor: 'pointer', marginLeft: '8px' }} onClick={() => {
+                                this.setState({
+                                    editingKey: code
+                                }, () => {
+                                    this['inputRef-' + code].focus();
+                                })
+                            }}/>}
+                        </div>
+                    </div>
                     <div className='chart-tools'>
                     <div className='chart-tools'>
                         {viewType !== 'richText' && <Icon className={iconCls} type="reload" theme="outlined" onClick={() => {
                         {viewType !== 'richText' && <Icon className={iconCls} type="reload" theme="outlined" onClick={() => {
                             dispatch({ type: 'dashboardDesigner/fetchChartData', item, mandatory: true });
                             dispatch({ type: 'dashboardDesigner/fetchChartData', item, mandatory: true });
@@ -85,6 +117,7 @@ class ViewLayout extends React.PureComponent {
 
 
     render() {
     render() {
         const { dashboardDesigner, contentSize, lastContentSize } = this.props;
         const { dashboardDesigner, contentSize, lastContentSize } = this.props;
+        const { editingKey } = this.state;
         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));
@@ -95,8 +128,8 @@ class ViewLayout extends React.PureComponent {
                 cols={12}
                 cols={12}
                 margin = {editMode ? [2, 2] : [0, 0]}
                 margin = {editMode ? [2, 2] : [0, 0]}
                 rowHeight = {50}
                 rowHeight = {50}
-                isDraggable={editMode}
-                isResizable={editMode}
+                isDraggable={editMode && !editingKey}
+                isResizable={editMode && !editingKey}
                 draggableHandle='.mover'
                 draggableHandle='.mover'
                 onLayoutChange={this.onLayoutChange}
                 onLayoutChange={this.onLayoutChange}
                 onBreakpointChange={this.onBreakpointChange}
                 onBreakpointChange={this.onBreakpointChange}

+ 3 - 1
src/components/dashboardDesigner/viewLayout.less

@@ -27,6 +27,8 @@
       .chart-title {
       .chart-title {
         font-size: 16px;
         font-size: 16px;
         line-height: 2;
         line-height: 2;
+        display: flex;
+        flex-wrap: nowrap;
       }
       }
       .chart-tools {
       .chart-tools {
         font-size: 20px;
         font-size: 20px;
@@ -90,8 +92,8 @@
           overflow: auto;
           overflow: auto;
           border: none !important;
           border: none !important;
           .w-e-text {
           .w-e-text {
-            // pointer-events: none;
             padding: 0 14px;
             padding: 0 14px;
+            overflow-y: auto;
             &>table {
             &>table {
               margin: 0;
               margin: 0;
             }
             }

+ 33 - 9
src/models/dashboardDesigner.js

@@ -237,20 +237,19 @@ export default {
             }
             }
             return Object.assign({}, state, {items, dirty});
             return Object.assign({}, state, {items, dirty});
         },
         },
-        // 富文本用
         modifyItem(state, action) {
         modifyItem(state, action) {
-            let { fields } = action;
+            let { item } = action;
             let { items } = state;
             let { items } = state;
             let dirty = false;
             let dirty = false;
-            for(let i = 0; i < items.length; i++) {
-                if(items[i].code === fields.code) {
-                    for(let k in fields) {
-                        items[i][k] = fields[k];
-                        dirty = true;
-                    }
-                }
+            let idx = items.findIndex(i => i.code === item.code);
+            if(idx > -1) {
+                let dirty = true;
+                items[idx] = { ...items[idx], ...item };
             }
             }
             return Object.assign({}, state, {items, dirty});
             return Object.assign({}, state, {items, dirty});
+
+
+            
         },
         },
         reset(state, action) {
         reset(state, action) {
             let newState = Object.assign({}, state, state.originData);
             let newState = Object.assign({}, state, state.originData);
@@ -321,6 +320,17 @@ export default {
     },
     },
 
 
     effects: {
     effects: {
+        *addCharts(action, { call, put, select }) {
+            const { charts } = action;
+
+            try{
+                for(let i = 0; i < charts.length; i++) {
+                    yield put({ type: 'addChart', chart: charts[i] });
+                }
+            }catch(e) {
+                message.error('添加图表错误: ' + e.message);
+            }
+        },
         /**
         /**
          * 刷新报表
          * 刷新报表
          */
          */
@@ -572,6 +582,20 @@ export default {
                 yield put({ type:'fetchChartData', item: targetItems[i], mandatory: true });
                 yield put({ type:'fetchChartData', item: targetItems[i], mandatory: true });
             }
             }
         },
         },
+        *modifyItem(action, { select, call, put }) {
+            try{
+                const { item } = action;
+                const dashboardDesigner = yield select(state => state.present.dashboardDesigner);
+                const { items } = dashboardDesigner;
+                let idx = items.findIndex(i => i.code === item.code);
+                if(idx > -1) {
+                    items[idx] = { ...items[idx], ...item };
+                    yield put({ type: 'setField', name: 'items', value: items });
+                }
+            }catch(e) {
+                message.error('修改失败: ' + e.message);
+            }
+        }
     },
     },
     subscriptions: {
     subscriptions: {
         setup({ dispatch, history}) {
         setup({ dispatch, history}) {

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

@@ -75,6 +75,13 @@
     border-radius: @checkbox-border-radius;
     border-radius: @checkbox-border-radius;
 }
 }
 
 
+// Modal
+.ant-modal-close-x {
+    height: 24px;
+    width: 24px;
+    line-height: 24px;
+}
+
 
 
 // 滚动条
 // 滚动条
 *::-webkit-scrollbar {
 *::-webkit-scrollbar {

+ 5 - 4
src/themes/default/chartdesigner.less

@@ -1,6 +1,7 @@
-@tab-bg-color-active: #727D99;
 
 
 .layout-chartdesigner {
 .layout-chartdesigner {
+    @tab-bg-color-active: #727D99;
+    @text-color: #D2E0F3;
     &> .layout-header {
     &> .layout-header {
         background: @content-background-color;
         background: @content-background-color;
     }
     }
@@ -22,7 +23,7 @@
                                     >.ant-tabs-nav-scroll {
                                     >.ant-tabs-nav-scroll {
                                         >.ant-tabs-nav {
                                         >.ant-tabs-nav {
                                             .ant-tabs-tab {
                                             .ant-tabs-tab {
-                                                color: #fff;
+                                                color: @text-color;
                                                 &.ant-tabs-tab-active {
                                                 &.ant-tabs-tab-active {
                                                     background: @tab-bg-color-active;
                                                     background: @tab-bg-color-active;
                                                 }
                                                 }
@@ -37,13 +38,13 @@
                         }
                         }
                         >.ant-tabs-content {
                         >.ant-tabs-content {
                             .ant-tabs-tabpane {
                             .ant-tabs-tabpane {
-                                color: #fff;
+                                color: @text-color;
                                 &.ant-tabs-tabpane-active {
                                 &.ant-tabs-tabpane-active {
                                     background: @tab-bg-color-active;
                                     background: @tab-bg-color-active;
                                 }
                                 }
                             }
                             }
                             .ant-form-item-label > label {
                             .ant-form-item-label > label {
-                                color: #fff;
+                                color: @text-color;
                             }
                             }
                         }
                         }
                     }
                     }

+ 0 - 0
src/themes/default/dashboard-detail.less


+ 63 - 0
src/themes/default/dashboarddesigner.less

@@ -0,0 +1,63 @@
+.layout-dashboarddesigner {
+    @text-color: #D2E0F3;
+    @text-color-active: #A7B1BE;
+    &>.ant-layout-header {
+        height: 46px;
+        line-height: 42px;
+    }
+    &>.ant-layout-content {
+        .content {
+            &>.dashboard-content {
+                margin: 0;
+                &.nomargin {
+                }
+                &>.content-layout {
+                    >.config-sider {
+                        background: @sider-background-color;
+                        >.ant-layout-sider-children {
+                            border-width: 0 1px 0 0;
+                            margin: 0;
+                            >.form-config {
+                                .ant-divider {
+                                    color: @text-color;
+                                    &:before, &:after {
+                                        border-color: @text-color;
+                                    }
+                                }
+                                .view-types {
+                                    .view-type-item {
+                                        border-color: @text-color-active;
+                                        i {
+                                            color: @text-color-active;
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                    &>.viewlayout {
+                    }
+                }
+            }
+            .ant-layout-header {
+                .filters {
+                    .filter-tag {
+                    }
+                    .filter-tag-using {
+                    }
+                    .filter-tag-add {
+                    }
+                }
+            }
+        }
+    }
+    .ant-layout-sider {
+        .ant-form-item {
+            >.ant-form-item-label{
+                >label {
+                    color: @text-color;
+                }
+            }
+        }
+    }
+}

+ 2 - 1
src/themes/default/frame.less

@@ -30,4 +30,5 @@
     @import "./setting.less";
     @import "./setting.less";
 }
 }
 
 
-@import "./chartdesigner.less";
+@import "./chartdesigner.less";
+@import "./dashboarddesigner.less";