Browse Source

首页报表tab工具栏

zhuth 6 years ago
parent
commit
74e4e02f98

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

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

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

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

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

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

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

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

+ 18 - 2
src/components/dashboard/layout.jsx

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

+ 5 - 16
src/components/dashboard/menu.jsx

@@ -1,6 +1,6 @@
 import React from 'react'
 import { connect } from 'dva'
-import { Tree, Input, Button, Icon, Spin } from 'antd'
+import { Tree, Input, Button, Icon } from 'antd'
 import DeleteBox from '../common/deleteBox/deleteBox'
 import './menu.less'
 const { TreeNode } = Tree
@@ -181,7 +181,7 @@ class DashboardMenu extends React.Component {
     }
 
     render() {
-        const { mode, home, dashboard, dispatch, loading } = this.props;
+        const { mode, home, dashboard, dispatch } = this.props;
         const { visibleDeleteBox, selectedMenu } = this.state;
         const { menuTree } = dashboard;
         const { menuFilterLabel, menuExpandedKeys, menuSelectedKeys, menuAutoExpandParent } = mode === 'view' ? home : dashboard;
@@ -189,9 +189,7 @@ class DashboardMenu extends React.Component {
         const regLabel = menuFilterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
 
         return <div className='menu-container' style={ mode === 'view' ? { paddingTop: 0 } : { paddingTop: '88px' } }>
-            <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>
+            
             {mode !== 'view' && <div className='menu-buttons'>
                 <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onAddClick}>新增目录</Button>
                 {/* <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onModifyClick}>修改目录</Button> */}
@@ -237,16 +235,7 @@ class DashboardMenu extends React.Component {
     }
 }
 
-function mapStateToProps({ present: { loading, dashboard, home }}) {
-    let effectsArr = ['dashboard/remoteMenuTree', 'dashboard/remoteAddMenu', 'dashboard/remoteDeleteMenu'];
-    let flag = false;
-    for(let i = 0; i < effectsArr.length; i++) {
-        if(loading.effects[effectsArr[i]]) {
-            flag = true;
-            break;
-        }
-    }
-
-    return { dashboard, loading: flag, home }
+function mapStateToProps({ present: { dashboard, home }}) {
+    return { dashboard, home }
 }
 export default connect(mapStateToProps)(DashboardMenu)

+ 11 - 6
src/components/dashboardDesigner/content.jsx

@@ -54,9 +54,7 @@ class DashboardDesignerContent extends React.Component {
     }
 
     getContentSize = () => {
-        const { dashboardDesigner, isOwner, isShareView, isShareKeyView, isViewMode } = this.props;
         const { lastContentSize } = this.state;
-        const { editMode } = dashboardDesigner;
         let contentEl = this.contentRef.current;
         if(!contentEl) {
             return {
@@ -83,8 +81,10 @@ class DashboardDesignerContent extends React.Component {
     }
 
     createFilters = (filters) => {
-        const { dispatch } = this.props;
-        dispatch({ type: 'dashboardDesigner/changeFilters', filters });
+        const { dispatch, afterRefresh } = this.props;
+        dispatch({ type: 'dashboardDesigner/changeFilters', filters }).then(() => {
+            afterRefresh && typeof afterRefresh === 'function' && afterRefresh()
+        });
         this.hideFilterBox()
     }
 
@@ -134,10 +134,12 @@ class DashboardDesignerContent extends React.Component {
 
     filterUsingChange = (e) => {
         const key = e.target.dataset.key;
-        const { dashboardDesigner, dispatch } = this.props;
+        const { dashboardDesigner, dispatch, afterRefresh } = this.props;
         const filters = dashboardDesigner.filters;
         let filter = filters.find(f => +f.key === +key);
-        dispatch({ type: 'dashboardDesigner/changeFilter', filter: { ...filter, using: filter.type ? !filter.using : false} });
+        dispatch({ type: 'dashboardDesigner/changeFilter', filter: { ...filter, using: filter.type ? !filter.using : false} }).then(() => {
+            afterRefresh && typeof afterRefresh === 'function' && afterRefresh()
+        });
     }
 
     render() {
@@ -183,6 +185,9 @@ class DashboardDesignerContent extends React.Component {
                     {isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode && <Sider className={`config-sider${ (isOwner && editMode) ? '' : ' config-sider-closed' }`} width={(isOwner && editMode && !isShareView && !isShareKeyView && !isViewMode) ? 200 : 0}>
                         <ConfigSider/>
                     </Sider>}
+                    {/**
+                        这里直接用main标签而不用antd的Header组件是为了让ref能够定位到对应的dom元素
+                    */}
                     <main ref={this.contentRef} className='viewlayout ant-layout-content'>
                         <ViewLayout isOwner={isOwner} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} contentSize={contentSize} lastContentSize={lastContentSize} editMode={editMode}/>
                     </main>

+ 18 - 23
src/components/dashboardDesigner/layout.jsx

@@ -2,8 +2,6 @@ import React from 'react'
 import { connect } from 'dva'
 import { Icon, Layout, Spin } from 'antd'
 import './layout.less'
-import html2canvas from 'html2canvas'
-import jsPDF from 'jspdf'
 import DashboardDesignerHeader from './header'
 import DashboardDesignerContent from './content'
 const { Header, Content } = Layout
@@ -17,34 +15,31 @@ class DashboardDesigner extends React.Component {
     }
 
     componentDidMount() {
-        const { code, dispatch, isShareView, isShareKeyView, afterLoad } = this.props;
+        const { code, dispatch, isShareView, isShareKeyView, afterLoad, config } = this.props;
         
         let url;
         if (code !== 'create') {
             url = isShareView ? 'dashboard/remoteShareDetail' : ( isShareKeyView ? 'dashboard/remoteShareKeyDetail' : 'dashboard/remoteDetail');
         }
-        dispatch({ type: url, code: code }).then((data) => {
-            if(afterLoad && typeof afterLoad === 'function') {
-                afterLoad(data)
+        if(config) { // 首页打开的报表会保存报表配置,不需要后台再请求
+            let fields = [];
+            for(let key in config) {
+                fields.push({
+                    name: key,
+                    value: config[key]
+                })
             }
-        });
+            dispatch({ type: 'dashboardDesigner/silentSetFields', fields: fields });
+        }else {
+            dispatch({ type: url, code: code }).then((data) => {
+                if(afterLoad && typeof afterLoad === 'function') {
+                    afterLoad(data)
+                }
+            });
+        }
     }
 
 
-    saveToPNG = (element) => {
-        html2canvas(element).then(function (canvas) {
-            let pageData = canvas.toDataURL('image/png', 1.0);
-
-            //方向默认竖直,尺寸ponits,格式a4[595.28,841.89]
-            let pdf = new jsPDF('', 'pt', 'a4');
-
-            //addImage后两个参数控制添加图片的尺寸,此处将页面高度按照a4纸宽高比列进行压缩
-            pdf.addImage(pageData, 'PNG', 0, 0, 595.28, 592.28 / canvas.width * canvas.height);
-
-            pdf.save('stone.pdf');
-        });
-    }
-
     isOwner = () => {
         const { dashboardDesigner, main } = this.props;
         const { creatorCode } = dashboardDesigner;
@@ -53,14 +48,14 @@ class DashboardDesigner extends React.Component {
     }
 
     render() {
-        const { dashboardDesigner, isShareView, isShareKeyView, isViewMode } = this.props;
+        const { dashboardDesigner, isShareView, isShareKeyView, isViewMode, afterRefresh } = this.props;
         const { loading } = dashboardDesigner;
         return <Layout className='dashboarddesigner-layout'>
             {!isShareView && !isShareKeyView && !isViewMode && <Header>
                 <DashboardDesignerHeader updateThumbnail={this.updateThumbnail} />
             </Header>}
             <Content>
-                <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode}/>
+                <DashboardDesignerContent isOwner={this.isOwner()} isShareView={isShareView} isShareKeyView={isShareKeyView} isViewMode={isViewMode} afterRefresh={afterRefresh}/>
             </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 />} />

+ 3 - 8
src/components/homePage/index.jsx

@@ -1,20 +1,14 @@
 import React from 'react'
 import { Layout, Tabs } from 'antd'
 import { connect } from 'dva'
-import Loading from '../common/loading/loading'
 import MenuLayout from './sider'
+import DashboardViewToolbar from './toolbar'
 import DashboardView from './view'
 import './index.less'
 const { Sider, Content } = Layout
 const TabPane = Tabs.TabPane
 
 class Home extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-
-        }
-    }
 
     generateTabs() {
         const { home } = this.props;
@@ -22,7 +16,8 @@ class Home extends React.Component {
 
         return tabs.map(t => (
             <TabPane tab={t.title} key={t.code}>
-                <DashboardView code={t.code}/>
+                <DashboardViewToolbar />
+                <DashboardView code={t.code} config={t.config}/>
             </TabPane>
         ));
     }

+ 1 - 1
src/components/homePage/sider.jsx

@@ -10,7 +10,7 @@ const { Header, Content } = Layout
 class MenuLayout extends React.Component {
 
     onSearch = (value) => {
-        const { home, dashboard, dispatch } = this.props;
+        const { dashboard, dispatch } = this.props;
         const expandedKeys = this.findExpandedKeys(dashboard.menuTree, {code: '-1'}, value);
         dispatch({ type: 'home/setFields', fields: [
             { name: 'menuExpandedKeys', value: expandedKeys },

+ 65 - 0
src/components/homePage/toolbar.jsx

@@ -0,0 +1,65 @@
+import React from 'react'
+import { Icon, Modal } from 'antd'
+import { connect } from 'dva'
+import DashboardDesigner from '../dashboardDesigner/layout'
+import './toolbar.less'
+
+class Toolbar extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            visibleFullscreenBox: false,
+        }
+    }
+    fullscreen = () => {
+        this.setState({
+            visibleFullscreenBox: true,
+        });
+    }
+    refresh = () => {
+        this.props.dispatch({ type: 'dashboardDesigner/refresh' });
+    }
+    collect = () => {
+
+    }
+
+    afterRefresh = () => {
+        const { dispatch, home } = this.props;
+        dispatch({ type: 'home/saveCurrentTabDashboardConfig', code: home.selectedTabKey });
+    }
+    render() {
+        const { home } = this.props;
+        const { tabs, selectedTabKey } = home;
+        let { config } = tabs.find(t => t.code === selectedTabKey);
+        return <div className='dashboardview-toolbar'>
+            <div className='toos'>
+                <div className='tool'><span onClick={this.fullscreen}><Icon type="fullscreen" />全屏</span></div>
+                <div className='tool'><span onClick={this.refresh}><Icon type="sync" />刷新</span></div>
+                <div className='tool'><span onClick={this.collect}><Icon type="star" />收藏</span></div>
+            </div>
+            {this.state.visibleFullscreenBox && <Modal
+                className='modal-full'
+                width='100%'
+                height='100%'
+                visible={this.state.visibleFullscreenBox}
+                footer={null}
+                onCancel={() => {
+                    this.setState({
+                        visibleFullscreenBox: false
+                    })
+                }}
+            >
+                <DashboardDesigner
+                    dashboardDesigner={this.props.dashboardDesigner}
+                    code={selectedTabKey}
+                    isViewMode
+                    afterLoad={null}
+                    afterRefresh={this.afterRefresh}
+                    config={config}
+                />
+            </Modal>}
+        </div>
+    }
+}
+
+export default connect(({ present: { dashboardDesigner, home } }) => ({ dashboardDesigner, home }))(Toolbar)

+ 29 - 0
src/components/homePage/toolbar.less

@@ -0,0 +1,29 @@
+.dashboardview-toolbar {
+    display: flex;
+    justify-content: flex-end;
+    width: 100%;
+    border-top: 1px solid #ccc;
+    &>.toos {
+        display: flex;
+        margin-right: 16px;
+        &>.tool {
+            cursor: pointer;
+            margin-right: 8px;
+            i {
+                margin: 0 4px;
+            }
+        }
+    }
+}
+
+.modal-full {
+    top: 0;
+    padding: 0;
+    .ant-modal-content {
+        height: 100%;
+        .ant-modal-body {
+            padding: 0;
+            height: 100%;
+        }
+    }
+}

+ 12 - 1
src/components/homePage/view.jsx

@@ -11,8 +11,19 @@ class DashboardView extends React.Component {
         }
     }
 
+    afterRefresh = () => {
+        const { dispatch, code } = this.props;
+        dispatch({ type: 'home/saveCurrentTabDashboardConfig', code });
+    }
+
     render() {
-        return <DashboardDesigner dashboardDesigner={this.props.dashboardDesigner} code={this.props.code} isViewMode afterLoad={this.afterLoad}/>
+        return <DashboardDesigner
+            dashboardDesigner={this.props.dashboardDesigner}
+            code={this.props.code}
+            isViewMode
+            afterLoad={this.afterLoad}
+            afterRefresh={this.afterRefresh}
+            config={this.props.config}/>
     }
 }
 export default connect(({ present: { dashboardDesigner } }) => ({ dashboardDesigner }))(DashboardView)

+ 1 - 27
src/models/dashboard.js

@@ -206,33 +206,7 @@ export default {
             }
         },
         *remoteAdd(action, { select, call, put }) {
-            message.error('请先指定目录');
-            // try {
-            //     const dashboardDesigner = yield select(state => state.present.dashboardDesigner);
-            //     const { name, items, description, relationColumns, filters, shareCode, chartCodes } = dashboardDesigner;
-            //     let body = {
-            //         bdName: name,
-            //         bdNote: description,
-            //         bdConfiguration: JSON.stringify(items),
-            //         relationColumns: JSON.stringify(relationColumns),
-            //         filters: JSON.stringify(filters) || '',
-            //         bdCode: shareCode || generateShareCode(),
-            //         thumbnail: '',
-            //         chartIds: chartCodes.join(',')
-            //     }
-            //     const res = yield call(service.fetch, {
-            //         url: URLS.DASHBOARD_ADD,
-            //         body: body
-            //     });
-            //     if(!res.err && res.data.code > 0) {
-            //         yield put({ type: 'fetchList', mandatory: true });
-            //         message.success('保存成功');
-            //     }else {
-            //         message.error('保存失败: ' + (res.err || res.data.msg));
-            //     } 
-            // }catch(e) {
-            //     message.error('保存失败: ' + e.message);
-            // }
+            yield message.error('未指定目录');
         },
         *remoteQucikAdd(action, { select, call, put }) {
             const { menuCode } = action;

+ 11 - 0
src/models/dashboardDesigner.js

@@ -314,6 +314,17 @@ export default {
     },
 
     effects: {
+        /**
+         * 刷新报表
+         */
+        *refresh(action, { call, put, select }) {
+            const dashboardDesigner = yield select(state => state.present.dashboardDesigner);
+            const { items } = dashboardDesigner;
+
+            for(let i = 0; i < items.length; i++) {
+                yield put({ type:'fetchChartData', item: items[i], mandatory: true });
+            }
+        },
         *remoteGetColumns(action, { call, put, select }) {
             const { dataSourceCode, mandatory } = action;
             const dashboardDesigner = yield select(state => state.present.dashboardDesigner);

+ 0 - 14
src/models/home.js

@@ -7,20 +7,6 @@ import * as service from '../services/index'
 import URLS from '../constants/url'
 import moment from 'moment'
 
-const code = window.sessionStorage.getItem('usercode');
-const account = window.localStorage.getItem('account');
-const password = window.localStorage.getItem('password');
-const name = window.sessionStorage.getItem('username');
-const role = window.sessionStorage.getItem('userrole');
-const department = window.sessionStorage.getItem('department');
-const job = window.sessionStorage.getItem('job');
-const expireTime = window.sessionStorage.getItem('expireTime');
-const autoLogin = window.localStorage.getItem('autoLogin') ? window.localStorage.getItem('autoLogin') === 'true' : true;
-
-const t = moment(+expireTime);
-const isLogin = expireTime && t.isValid();
-const authenticated = t.isValid() && t.diff(moment()) > 0;
-
 export default {
     namespace: 'home',
     state: {