zhuth 6 лет назад
Родитель
Сommit
5c4008268b

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

@@ -465,7 +465,7 @@ class ChartList extends React.Component {
                 />}
                 {visibleDeleteBox && <DeleteBox
                     visibleBox={visibleDeleteBox}
-                    text={<div><span>确定要删除图表【{selectedRecord.name}】吗?</span><br/><span style={{ color: 'red' }}>(此操作将会影响使用到该图表的看板!)</span></div>}
+                    text={<div><span>确定要删除图表【{selectedRecord.name}】吗?</span><br/><span style={{ color: 'red' }}>(此操作将会影响使用到该图表的报表!)</span></div>}
                     hideBox={() => {
                         this.setState({
                             visibleDeleteBox: false

+ 1 - 1
src/components/common/CardList.jsx

@@ -10,7 +10,7 @@ const CardGrid = Card.Grid
 /**
  * 尝试抽出generateCard()作为一个公共模块
  * 需要指定以下props:
- * mode 模式,分为主页、看板、图表模式 (homepage, dashboard, chart)
+ * mode 模式,分为主页、报表、图表模式 (homepage, dashboard, chart)
  * list 数据所在的列表,存于models中
  * filterLabel 生成列表时使用的过滤器字段
  * onDistribute

+ 3 - 4
src/components/common/groupManageMentBox/box.jsx

@@ -26,7 +26,6 @@ class GroupBox extends React.Component {
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         const regLabel = filterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         let list = treeData.sort((a, b) => (a.index - b.index)).map(t => {
-
             const title = <span>{ (regLabel) ?
                 ((t.label || '').split(new RegExp(`(${regLabel})`, 'i')).map((fragment, i) => {
                     return (
@@ -86,10 +85,10 @@ class GroupBox extends React.Component {
 
     onExpand = (expandedKeys) => {
         this.setState({
-          expandedKeys,
-          autoExpandParent: false,
+            expandedKeys,
+            autoExpandParent: false,
         });
-      }
+    }
 
     onSearch = (e) => {
         const value = e.target.value;

+ 30 - 0
src/components/dashboard/layout.jsx

@@ -0,0 +1,30 @@
+import React from 'react'
+import { Layout } from 'antd'
+import DashboardMenu from './menu'
+import DashboardList from './list'
+import './layout.less'
+const { Sider, Content } = Layout
+
+class DashboardLayout extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+
+        }
+    }
+
+    render() {
+        return <Layout
+            className='layout-dashboard'
+        >
+            <Sider width={300}>
+                <DashboardMenu />
+            </Sider>
+            <Content>
+                <DashboardList />
+            </Content>
+        </Layout>
+    }
+}
+
+export default DashboardLayout

+ 11 - 0
src/components/dashboard/layout.less

@@ -0,0 +1,11 @@
+.layout-dashboard {
+    .ant-layout-sider {
+        border-width: 1px;
+        border-style: solid;
+        border-color: #CCCCCC;
+        background: #fff;
+        .ant-layout-sider-children {
+            height: 100%;
+        }
+    }
+}

+ 2 - 2
src/components/dashboard/list.jsx

@@ -321,7 +321,7 @@ class DashboardList extends React.Component {
                                     <Button onClick={() => {
                                         dispatch({ type: 'dashboard/remoteQucikAdd' });
                                     }}>
-                                        <Icon type="layout" />创建看板
+                                        <Icon type="layout" />创建报表
                                     </Button>
                                 </Col>
                             </Col>
@@ -376,7 +376,7 @@ class DashboardList extends React.Component {
                 />}
                 {visibleDeleteBox && <DeleteBox
                     visibleBox={visibleDeleteBox}
-                    text={`确定要删除看板【${selectedRecord.name}】吗?`}
+                    text={`确定要删除报表【${selectedRecord.name}】吗?`}
                     hideBox={() => {
                         this.setState({
                             visibleDeleteBox: false

+ 217 - 0
src/components/dashboard/menu.jsx

@@ -0,0 +1,217 @@
+import React from 'react'
+import { connect } from 'dva'
+import { Tree, Input, Button, Icon, Spin } from 'antd'
+import DeleteBox from '../common/deleteBox/deleteBox'
+import './menu.less'
+const { TreeNode } = Tree
+const { Search } = Input
+
+class DashboardMenu extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            editingKey: null,
+            selectedMenu: null,
+            visibleDeleteBox: false,
+        };
+    }
+
+    componentDidMount() {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboard/remoteMenuTree' });
+    }
+
+    generateMenu(tree, regLabel) {
+        const { dispatch } = this.props;
+        const { editingKey } = this.state;
+        return tree.filter(t => t.type === 'menu').sort((a, b) => a.index - b.index).map(t => {
+            let title = <div className='node-title'>
+                <span>{ (t.code !== editingKey) ?
+                   ( regLabel ? ((t.name || '').split(new RegExp(`(${regLabel})`, 'i')).map((fragment, i) => {
+                        return (
+                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'), '\\$1') === regLabel.toLowerCase() ?
+                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                            fragment
+                        )
+                    })) : <div className='label'>{t.name}</div> ) : ( <div className='input'>
+                    <Input
+                        size="small"
+                        defaultValue={t.name}
+                        addonAfter={<Icon style={{ cursor: 'pointer', color: '#52C41A' }} type="check-circle" onClick={() => {
+                            this.setState({ editingKey: false });
+                        }}/>}
+                        onBlur={(e) => {
+                            if(e.target.value !== t.name) {
+                                dispatch({ type: 'dashboard/remoteModifyMenu', menu: { ...t, name: e.target.value } });
+                            }
+                            this.setState({ editingKey: false });
+                        }} onPressEnter={(e) => {
+                            if(e.target.value !== t.name) {
+                                dispatch({ type: 'dashboard/remoteModifyMenu', menu: { ...t, name: e.target.value } });
+                            }
+                            this.setState({ editingKey: false });
+                        }}
+                    />
+                </div> )
+                }</span>
+                <div className='tools'>
+                    {t.code !== editingKey && <Icon type='edit' onClick={() => {
+                        this.setState({
+                            editingKey: t.code
+                        });
+                    }}/>}
+                    {!(t.children && t.children.length > 0) && <Icon type='delete' onClick={() => {
+                        this.setState({
+                            selectedMenu: t,
+                            visibleDeleteBox: true,
+                        });
+                    }}/>}
+                </div>
+            </div>
+
+            return <TreeNode title={title} key={t.code}>
+                { t.children && t.children.length > 0 && this.generateMenu(t.children, regLabel) }
+            </TreeNode>
+        });
+    }
+
+    onChange = (e) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboard/setField', name: 'menuFilterLabel', value: e.target.value })
+    }
+
+    onExpand = (keys) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboard/setFields', fields: [
+            { name: 'menuExpandedKeys', value: keys },
+            { name: 'menuAutoExpandParent', value: false },
+        ] });
+    }
+
+    onSelect = (selectedKeys, info) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'dashboard/setField', name: 'menuSelectedKeys', value: selectedKeys })
+    }
+
+    onSearch = (value) => {
+        const { dashboard, dispatch } = this.props;
+        const expandedKeys = this.findExpandedKeys(dashboard.menuTree, {code: '-1'}, value);
+        dispatch({ type: 'dashboard/setFields', fields: [
+            { name: 'menuExpandedKeys', value: expandedKeys },
+            { name: 'menuFilterLabel', value },
+            { name: 'autoExpandParent', value: true },
+        ] });
+    }
+
+    findExpandedKeys = (tree, parent, filterLabel) => {
+        let result = [];
+        if(tree && tree.length > 0) {
+            tree.forEach(t => {
+                if(t.name.toLowerCase().indexOf(filterLabel.toLowerCase()) > -1 && result.indexOf(parent.code) === -1) {
+                    result.push(parent.code);
+                }
+                result = result.concat(this.findExpandedKeys(t.children, t, filterLabel));
+            });
+        }
+        return result;
+    }
+
+    onAddClick = () => {
+        const { dashboard, dispatch } = this.props;
+        const { menuList, menuSelectedKeys, menuExpandedKeys } = dashboard;
+        const pmenu = menuList.find(l => l.code === menuSelectedKeys[0]);
+        const menu = {
+            index: pmenu.childrenCount,
+            name: '新目录',
+            pcode: pmenu.code
+        }
+        dispatch({ type: 'dashboard/remoteAddMenu', menu }).then(res => {
+            if(res) {
+                dispatch({ type: 'dashboard/setFields', fields: [
+                    { name: 'menuExpandedKeys', value: menuExpandedKeys.concat([pmenu.code]) },
+                    { name: 'autoExpandParent', value: true },
+                ] });
+            }
+        });
+    }
+
+    getParens = (menu) => {
+        const { menuList } = this.props.dashboard;
+        let pmenus = [menu];
+        let fmenu = menuList.find(l => l.code === menu.pcode);
+        if(fmenu) {
+            pmenus = pmenus.concat(this.getParens(fmenu));
+        }
+        return pmenus;
+    }
+
+    render() {
+        const { dashboard, dispatch, loading } = this.props;
+        const { visibleDeleteBox, selectedMenu } = this.state;
+        const { menuTree, menuFilterLabel, menuExpandedKeys, menuSelectedKeys, menuAutoExpandParent } = dashboard;
+        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+        const regLabel = menuFilterLabel.replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+
+        return <div className='menu-container'>
+            <div style={{ display: loading ? 'block' : 'none', position: 'absolute', height: '100%', width: '100%', zIndex: '4', background: 'rgba(51,51,51,.1)' }}>
+                <Spin style={{ display: 'inline-block', position: 'absolute', top: '50%', left: '50%', margin: '-10px' }} indicator={<Icon type="loading" style={{ fontSize: 24 }} spin />}/>
+            </div>
+            <div className='menu-buttons'>
+                <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onAddClick}>新增目录</Button>
+                {/* <Button disabled={menuSelectedKeys.length !== 1} onClick={this.onModifyClick}>修改目录</Button> */}
+            </div>
+            <div className='menu-search'>
+                <Search
+                    defaultValue={menuFilterLabel}
+                    placeholder='搜索'
+                    // onChange={this.onChange}
+                    onSearch={this.onSearch}
+                />
+                <Button onClick={() => {
+                    dispatch({ type: 'dashboard/remoteMenuTree', mandatory: true });
+                }}><Icon type='sync' /></Button>
+            </div>
+            <div className='menu-content'>
+                <Tree
+                    inlineIndent={8}
+                    expandedKeys={menuExpandedKeys}
+                    onExpand={this.onExpand}
+                    selectedKeys={menuSelectedKeys}
+                    onSelect={this.onSelect}
+                    autoExpandParent={menuAutoExpandParent}
+                >
+                    <TreeNode title='全部目录' key='-1'>
+                        { this.generateMenu(menuTree, regLabel) }
+                    </TreeNode>
+                </Tree>
+                {visibleDeleteBox && <DeleteBox
+                    visibleBox={visibleDeleteBox}
+                    text={`确定要删除目录【${selectedMenu.name}】吗?`}
+                    hideBox={() => {
+                        this.setState({
+                            visibleDeleteBox: false
+                        })
+                    }}
+                    okHandler={() => {
+                        dispatch({ type: 'dashboard/remoteDeleteMenu', menu: selectedMenu });
+                    }} 
+                />}
+            </div>
+        </div>
+    }
+}
+
+function mapStateToProps({ present: { loading, dashboard }}) {
+    let effectsArr = ['dashboard/remoteMenuTree', 'dashboard/remoteAddMenu', 'dashboard/remoteDeleteMenu'];
+    let flag = false;
+    for(let i = 0; i < effectsArr.length; i++) {
+        if(loading.effects[effectsArr[i]]) {
+            flag = true;
+            break;
+        }
+    }
+
+    return { dashboard, loading: flag }
+}
+export default connect(mapStateToProps)(DashboardMenu)

+ 50 - 0
src/components/dashboard/menu.less

@@ -0,0 +1,50 @@
+.menu-container {
+    height: 100%;
+    padding-top: 88px;
+    .menu-buttons {
+        height: 32px;
+        padding: 0 8px;
+        margin-top: -80px;
+        margin-bottom: 8px;
+        button {
+            margin-right: 8px;
+        }
+    }
+    .menu-search {
+        display: flex;
+        height: 32px;
+        padding: 0 8px;
+        margin-bottom: 8px;
+        .ant-input-search {
+            margin-right: 8px;
+        }
+    }
+    .menu-content {
+        height: 100%;
+        overflow: auto;
+        border-top: 1px solid #ccc;
+
+        .ant-tree li .ant-tree-node-content-wrapper {
+            width: ~'calc(100% - 32px)';
+            overflow: hidden;
+            text-overflow: ellipsis;
+
+            .node-title {
+                display: flex;
+                justify-content: space-between;
+                .tools {
+                    .anticon {
+                        display: none;
+                    }
+                }
+                &:hover {
+                    .tools {
+                        .anticon {
+                            display: inline-block;
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 3 - 3
src/components/dashboardDesigner/richTextEditor.jsx

@@ -29,14 +29,14 @@ class RichTextEditor extends Component {
             this.setState({
                 _html: editor.txt.html()
             });
-            let boardEl = document.getElementsByClassName('react-grid-layout')[0]; // 看板容器组件
+            let boardEl = document.getElementsByClassName('react-grid-layout')[0]; // 报表容器组件
             let viewEl = elem.parentElement.parentElement; // chart/richText组件
             let toolbarEl = elem.getElementsByClassName('w-e-toolbar')[0]; // 工具栏组件
 
             toolbarEl.style.display = 'flex';
             viewEl.style.zIndex = 2; // 使工具栏组件置于其他chat/richText组件上层
 
-            let boardElLayout = boardEl.getBoundingClientRect(); // 看板容器组件layout
+            let boardElLayout = boardEl.getBoundingClientRect(); // 报表容器组件layout
             let viewElLayout = viewEl.getBoundingClientRect(); // chart/richText组件layout
             let toolbarElLayout = toolbarEl.getBoundingClientRect(); // 工具栏组件layout
             
@@ -44,7 +44,7 @@ class RichTextEditor extends Component {
             console.log(toolbarEl);
             let viewElX = viewElLayout.left; // chart/richText组件左起位置
             let toolbarWidth = toolbarElLayout.width; // 工具栏组件宽度
-            let boardWidth = boardElLayout.width; // 看板容器宽度
+            let boardWidth = boardElLayout.width; // 报表容器宽度
 
             console.log(viewElX, toolbarWidth, boardWidth);
             if((viewElX + toolbarWidth) > boardWidth) { // 工具栏超出容器组件右边

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

@@ -105,7 +105,7 @@ class ViewLayout extends React.PureComponent {
                 {(children.length === 0) ? <div key='default-chartview' className='default-chartview' data-grid={{ x: 0, y: 0, w: 12, h: 2, minW: 12, maxW: 12, minH: 2, maxH: 2, static: true }}>
                     <div className='tip'>
                         <Icon type="message" theme="outlined" />
-                        {(isOwner && !isShareView && !isShareKeyView) ? <span>请从左侧选择图表/富文本添加到看板</span> : <span>无图表元素</span>}
+                        {(isOwner && !isShareView && !isShareKeyView) ? <span>请从左侧选择图表/富文本添加到报表</span> : <span>无图表元素</span>}
                     </div>
                 </div> : children}
             </ReactGridLayout>

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

@@ -32,7 +32,7 @@ class HomePage extends React.Component {
                             list={recentChart}
                         />
                     </Card>
-                    <Card className='recent-dashboard' title='最近访问看板'>
+                    <Card className='recent-dashboard' title='最近访问报表'>
                         <CardList
                             mode='homepage' 
                             type='dashboard' 

+ 1 - 1
src/components/workshop/index.jsx

@@ -6,7 +6,7 @@ import { connect } from 'dva'
 import Loading from '../../components/common/loading/loading'
 import DataConnect from '../../components/dataConnect/list'
 import DataSource from '../../components/dataSource/list'
-import Dashboard from '../../components/dashboard/list'
+import Dashboard from '../../components/dashboard/layout'
 import Chart from '../../components/chart/list'
 import DataSourceDetail from '../../components/dataSourceDetail/layout'
 import './index.less'

+ 1 - 0
src/components/workshop/index.less

@@ -1,6 +1,7 @@
 .layout-workshop {
     .sider-workshop {
         padding: 12px;
+        border: 1px solid #ccc;
         button {
             padding: 0 8px;
             margin: 0 0 12px 0;

+ 25 - 17
src/constants/url.js

@@ -159,47 +159,55 @@ const URLS = {
 
     GROUP_CHART_DELETE: BASE_URL + '/delChartsGroup', // 删除图表分组/子分组
 
-    /***************************************看板***************************************/
+    /***************************************报表***************************************/
 
-    DASHBOARD_LIST: BASE_URL + '/getListDashboards', // 获得看板列表
+    DASHBOARD_LIST: BASE_URL + '/getListDashboards', // 获得报表列表
 
-    DASHBOARD_DETAIL: BASE_URL + '/getDashboards', // 获得单个看板
+    DASHBOARD_DETAIL: BASE_URL + '/getDashboards', // 获得单个报表
     
-    DASHBOARD_ADD: BASE_URL + '/inputDashboards', // 新增看板
+    DASHBOARD_ADD: BASE_URL + '/inputDashboards', // 新增报表
 
-    DASHBOARD_DELETE: BASE_URL + '/delDashboards', // 删除看板
+    DASHBOARD_DELETE: BASE_URL + '/delDashboards', // 删除报表
 
-    DASHBOARD_UPDATE: BASE_URL + '/updateDashboards', // 更新看板
+    DASHBOARD_UPDATE: BASE_URL + '/updateDashboards', // 更新报表
 
-    DASHBOARD_SHARE_LIST: BASE_URL + '/getDashOrder', // 获得看板分发列表
+    DASHBOARD_SHARE_LIST: BASE_URL + '/getDashOrder', // 获得报表分发列表
 
-    DASHBOARD_SHARE: BASE_URL + '/addObject', // 看板分发
+    DASHBOARD_SHARE: BASE_URL + '/addObject', // 报表分发
 
-    DASHBOARD_TRANSFER: BASE_URL + '/changeDashOrder', // 看板移交
+    DASHBOARD_TRANSFER: BASE_URL + '/changeDashOrder', // 报表移交
 
-    DASHBOARD_COPY: BASE_URL + '/copyDashboard', // 看板复制
+    DASHBOARD_COPY: BASE_URL + '/copyDashboard', // 报表复制
 
-    DASHBOARD_GET_SHAREKEY: BASE_URL + '/share', // 生成看板分享链接
+    DASHBOARD_GET_SHAREKEY: BASE_URL + '/share', // 生成报表分享链接
     
-    DASHBOARD_SHARE_DETAIL_BY_KEY: BASE_URL + '/getSharedDashboard', // 通过看板分享链接获取看板数据
+    DASHBOARD_SHARE_DETAIL_BY_KEY: BASE_URL + '/getSharedDashboard', // 通过报表分享链接获取报表数据
 
-    DASHBOARD_ENCRYPT_CODE: BASE_URL + '/encryptCode', // 通过看板编号获得加密串
+    DASHBOARD_ENCRYPT_CODE: BASE_URL + '/encryptCode', // 通过报表编号获得加密串
 
-    DASHBOARD_SHARE_DETAIL_BY_CODE: BASE_URL + '/getDashboardByCode', // 通过看板编号获得看板数据
+    DASHBOARD_SHARE_DETAIL_BY_CODE: BASE_URL + '/getDashboardByCode', // 通过报表编号获得报表数据
+
+    DASHBOARD_MENU_TREE: BASE_URL + '/dashBoard/menu/list', // 获取报表目录树
+
+    DASHBOARD_MENU_ADD: BASE_URL + '/dashBoard/menu/save', // 添加报表目录
+
+    DASHBOARD_MENU_UPDATE: BASE_URL + '/dashBoard/menu/update', // 添加报表目录
+
+    DASHBOARD_MENU_DELETE: BASE_URL + '/dashBoard/menu/delete', // 删除报表目录
 
     /***************************************浏览记录***************************************/
     
-    HISTORY_ADD: BASE_URL + '/addRecord', // 添加图表、看板浏览记录 0 - 图表  1 - 看板
+    HISTORY_ADD: BASE_URL + '/addRecord', // 添加图表、报表浏览记录 0 - 图表  1 - 报表
     
     HISTORY_CHART_LIST: BASE_URL + '/getChartRecode', // 查询图表浏览记录列表
 
-    HISTORY_DASHBOARD_LIST: BASE_URL + '/getDashRecode', // 查询看板浏览记录列表
+    HISTORY_DASHBOARD_LIST: BASE_URL + '/getDashRecode', // 查询报表浏览记录列表
 
     /***************************************主页模块***************************************/
 
     HOMEPAGE_RECENT_CHART_GET: BASE_URL + "/getChartRecord", // 查询最近访问图表  //可能的错字
 
-    HOMEPAGE_RECENT_DASHBOARD_GET: BASE_URL + "/getDashRecord", //查询最近访问看板 //可能的错字
+    HOMEPAGE_RECENT_DASHBOARD_GET: BASE_URL + "/getDashRecord", //查询最近访问报表 //可能的错字
 
     HOMEPAGE_ADD_RECENT_RECORD: BASE_URL + "/addRecord", //添加最近访问记录 
 }

+ 2 - 2
src/index.js

@@ -41,8 +41,8 @@ app.model(dataSource); // 数据源
 app.model(dataSourceDetail); // 数据源详细数据
 app.model(chart);  // 图表
 app.model(chartDesigner); // 图表设计
-app.model(dashboard);  //报告与看板
-app.model(dashboardDesigner); // 看板设计
+app.model(dashboard);  //报告与报表
+app.model(dashboardDesigner); // 报表设计
 app.model(userGroup); // 用户组
 app.model(user); // 用户
 app.model(chartPolicy); // 图表策略

+ 0 - 2
src/models/chart.js

@@ -392,7 +392,6 @@ export default {
                     url: URLS.GROUP_CHART_LIST,
                 });
                 
-                console.log('请求图表分组列表', res);
                 if(!res.err && res.data.code > 0) {
                     const resData = res.data.data;
                     let data = resData.map(d => {
@@ -408,7 +407,6 @@ export default {
                     message.error('读取图表分组列表错误: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('读取图表分组列表错误: ' + e);
             }
         },

+ 124 - 14
src/models/dashboard.js

@@ -15,6 +15,12 @@ export default {
                 defaultSelectedGroups: [],
                 defaultSelectedUsers: []
             },
+            menuList: [],
+            menuTree: [],
+            menuExpandedKeys: ['-1'],
+            menuSelectedKeys: [],
+            menuFilterLabel: '',
+            menuAutoExpandParent: true,
             filterLabel: '',
             filterItems: [ // 可选过滤字段
                 { name: 'name', label: '报表名称', type: 'string' },
@@ -38,6 +44,18 @@ export default {
             let { label } = action;
             return Object.assign({}, state, {filterLabel: label});
         },
+        setField(state, action) {
+            const { name, value } = action;
+            let obj = {};
+            obj[name] = value;
+            return Object.assign({}, state, obj);
+        },
+        setFields(state, action) {
+            const { fields } = action;
+            let obj = {};
+            fields.map(f => (obj[f.name] = f.value));
+            return Object.assign({}, state, obj);
+        },
         reset(state, action) {
             let newState = Object.assign({}, state, state.originData);
             return Object.assign({}, newState);
@@ -102,11 +120,11 @@ export default {
                     })
                     yield put({ type: 'list', list: list });
                 }else {
-                    message.error('请求看板列表失败: ' + (res.err || res.data.msg));
+                    message.error('请求报表列表失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
                 console.log(body, e);
-                message.error('请求看板列表失败: ' + e)
+                message.error('请求报表列表失败: ' + e)
             }
         },
         *remoteDetail(action, { select, call, put }) {
@@ -175,10 +193,10 @@ export default {
                     }
                     yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                 }else {
-                    message.error('解析看板错误: ' + (res.err || res.data.msg));
+                    message.error('解析报表错误: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                message.error('解析看板错误: ' + e);
+                message.error('解析报表错误: ' + e);
             }finally {
                 yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
             }
@@ -293,6 +311,104 @@ export default {
                 message.error('删除失败: ' + e);
             }
         },
+        *remoteMenuTree(action, { put, call, select }) {
+            const dashboard = yield select(state => state.present.dashboard);
+            if(!action.mandatory && dashboard.menuTree.length > 0) {
+                return;
+            }
+            const res = yield call(service.fetch, {
+                url: URLS.DASHBOARD_MENU_TREE,
+                method: 'GET'
+            })
+            if(!res.err && res.data.code > 0) {
+                const resTree = res.data.data;
+                const list = [];
+                let fun = (tree, pcode) => {
+                    let newTree = tree.map((t, i) => {
+                        let ch = [];
+                        if(t.children && t.children.length > 0) {
+                            ch = fun(t.children, t.id);
+                        }
+                        let obj = {
+                            code: t.id + '',
+                            pcode: pcode + '',
+                            name: t.name,
+                            type: t.type,
+                            index: i,
+                            children: ch,
+                            childrenCount: ch.length
+                        }
+                        list.push(obj);
+                        return obj
+                    });
+                    return newTree;
+                }
+                let menuList = list;
+                let menuTree = fun(resTree, '-1');
+                yield put({ type: 'setFields', fields: [
+                    { name: 'menuList', value: menuList },
+                    { name: 'menuTree', value: menuTree },
+                ] });
+            }else {
+                message.error('获取报表目录失败: ' + (res.err || res.data.msg));
+            }
+        },
+        *remoteAddMenu(action, { put, call, select }) {
+            const { menu } = action;
+            const res = yield call(service.fetch, {
+                url: URLS.DASHBOARD_MENU_ADD,
+                method: 'POST',
+                body: {
+                    id: menu.code,
+                    index: menu.index,
+                    name: menu.name,
+                    parentId: menu.pcode
+                }
+            })
+
+            if(!res.err && res.data.code > 0) {
+                yield put({ type: 'remoteMenuTree', mandatory: true });
+                yield put({ type: 'setFields', fields: [
+                    { name: 'menuSelectedKeys', value: [] },
+                ] });
+                return true;
+            }else {
+                message.error('添加报表目录失败: ' + (res.err || res.data.msg));
+                return false;
+            }
+        },
+        *remoteModifyMenu(action, { put, call, select }) {
+            const { menu } = action;
+            const res = yield call(service.fetch, {
+                url: URLS.DASHBOARD_MENU_UPDATE,
+                body: {
+                    id: menu.code,
+                    index: menu.index,
+                    name: menu.name,
+                    parentId: menu.pcode
+                }
+            });
+            if(!res.err && res.data.code > 0) {
+                yield put({ type: 'remoteMenuTree', mandatory: true });
+                return true;
+            }else {
+                message.error('修改报表目录失败: ' + (res.err || res.data.msg));
+                return false;
+            }
+        },
+        *remoteDeleteMenu(action, { put, call, select }) {
+            const { menu } = action;
+            const res = yield call(service.fetch, {
+                url: URLS.DASHBOARD_MENU_DELETE + '/' + menu.code,
+            });
+            if(!res.err && res.data.code > 0) {
+                yield put({ type: 'remoteMenuTree', mandatory: true });
+                return true;
+            }else {
+                message.error('添加报表目录失败: ' + (res.err || res.data.msg));
+                return false;
+            }
+        },
         *share(action, { put, call, select }) {
             const { code, targets } = action;
             const body = {
@@ -308,14 +424,12 @@ export default {
                     url: URLS.DASHBOARD_SHARE,
                     body
                 });
-                console.log('看板分发', body, res);
                 if(!res.err && res.data.code > 0) {
                     message.success('设置分发对象成功');
                 }else {
                     message.error('设置分发对象失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('分发失败: ' + e);
             }
         },
@@ -326,7 +440,6 @@ export default {
                 url: URLS.DASHBOARD_SHARE_LIST,
                 body
             });
-            console.log('请求看板分发列表', body, res);
             return res;
         },
         *transfer(action, { put, call, select }) {
@@ -340,7 +453,6 @@ export default {
                     url: URLS.DASHBOARD_TRANSFER,
                     body
                 });
-                console.log('看板移交', body, res);
                 if(!res.err && res.data.code > 0) {
                     const dashboard = yield select(state => state.present.dashboard);
                     const list = dashboard.list;
@@ -353,11 +465,9 @@ export default {
                     yield put({ type: 'list', list });
                     message.success('移交成功');
                 }else {
-                    console.log(body, (res.err || res.data.msg));
                     message.error('移交失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('移交失败: ' + e);
             }
         },
@@ -428,10 +538,10 @@ export default {
                     }
                     yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                 }else {
-                    message.error('解析看板错误: ' + (res.err || res.data.msg));
+                    message.error('解析报表错误: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                message.error('解析看板错误: ' + e);
+                message.error('解析报表错误: ' + e);
             }finally {
                 yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
             }
@@ -528,10 +638,10 @@ export default {
                     }
                     yield put({ type: 'dashboardDesigner/silentSetFields', fields: fields });
                 }else {
-                    message.error('解析看板错误: ' + (res.err || res.data.msg));
+                    message.error('解析报表错误: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                message.error('解析看板错误: ' + e);
+                message.error('解析报表错误: ' + e);
             }finally {
                 yield put({ type: 'dashboardDesigner/silentSetField', name: 'loading', value: false });
             }

+ 1 - 1
src/models/dashboardDesigner.js

@@ -7,7 +7,7 @@ import URLS from '../constants/url'
 import CHART_TYPE from './chartType.json'
 
 /**
- * 获得看板中图表的真实过滤规则
+ * 获得报表中图表的真实过滤规则
  */
 function getTrueFilters(item, filters) {
     let trueFilters = [];

+ 1 - 1
src/models/main.js

@@ -122,7 +122,7 @@ export default {
                         code: user.id+'',
                         account: username,
                         phone: user.phone,
-                        password: user.passWord,
+                        password: password,
                         name: user.name,
                         role: user.role || 'default',
                         department: user.department,

+ 3 - 3
src/models/recent.js

@@ -74,7 +74,7 @@ export default {
                 const res = yield call(service.fetch, {
                     url: URLS.HOMEPAGE_RECENT_DASHBOARD_GET,
                 });
-                console.log('请求最近访问看板', res);
+                console.log('请求最近访问报表', res);
                 if(!res.err && res.data.code > 0) {
                     let recentDashboard = res.data.data.map((r, i) => {
                         return {
@@ -89,11 +89,11 @@ export default {
                     });
                     yield put({ type: 'listRecentDashboard', recentDashboard });
                 }else {
-                    message.error('读取最近访问看板列表错误: ' + (res.err || res.data.msg));
+                    message.error('读取最近访问报表列表错误: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
                 console.error(e);
-                message.error('读取最近访问看板列表错误: ' + e);
+                message.error('读取最近访问报表列表错误: ' + e);
             }
             
         },