Browse Source

操作日志/权限设置

zhuth 6 years ago
parent
commit
59bdcb3701
42 changed files with 877 additions and 504 deletions
  1. 0 9
      src/components/admin/userManagement.jsx
  2. 255 88
      src/components/authority/index.jsx
  3. 67 4
      src/components/authority/index.less
  4. 0 52
      src/components/authority/index1.jsx
  5. 3 0
      src/components/chart/list.less
  6. 0 1
      src/components/chartDesigner/charts/echartsView.jsx
  7. 0 2
      src/components/chartDesigner/sections/scatterConfigForm.jsx
  8. 0 1
      src/components/chartDesigner/sections/style/table.jsx
  9. 146 104
      src/components/common/accessObjectBox/accessObjectBox.jsx
  10. 62 22
      src/components/common/accessObjectBox/accessObjectBox.less
  11. 3 2
      src/components/common/cusIcon/index.jsx
  12. 0 3
      src/components/common/selectUserBox/selectUserBox.jsx
  13. 1 2
      src/components/dashboard/list.jsx
  14. 3 0
      src/components/dashboard/list.less
  15. 0 14
      src/components/dashboardDesigner/chartView.jsx
  16. 0 2
      src/components/dashboardDesigner/richTextEditor.jsx
  17. 3 0
      src/components/dataConnect/list.less
  18. 3 0
      src/components/dataSource/list.less
  19. 0 3
      src/components/dataSourceDetail/accessConfig.jsx
  20. 1 1
      src/components/dataSourceDetail/baseConfig.jsx
  21. 89 48
      src/components/dataSourceDetail/dataConnectBox.jsx
  22. 0 1
      src/components/dataSourceDetail/dataConnectConfig.jsx
  23. 3 1
      src/components/dataSourceDetail/header.jsx
  24. 51 17
      src/components/logs/logs.jsx
  25. 13 0
      src/components/logs/logs.less
  26. 1 1
      src/components/setting/index.jsx
  27. 19 1
      src/constants/url.js
  28. 115 7
      src/models/authority.js
  29. 0 31
      src/models/chart.js
  30. 0 12
      src/models/chartPolicy.js
  31. 2 1
      src/models/dashboard.js
  32. 0 3
      src/models/dashboardDesigner.js
  33. 2 28
      src/models/dataSource.js
  34. 0 8
      src/models/dataSourcePolicy.js
  35. 0 3
      src/models/home.js
  36. 17 5
      src/models/logs.js
  37. 0 1
      src/models/main.js
  38. 0 2
      src/models/parseChartOption.js
  39. 0 7
      src/models/recent.js
  40. 0 12
      src/models/userGroup.js
  41. 11 4
      src/themes/default/base.less
  42. 7 1
      src/utils/request.js

+ 0 - 9
src/components/admin/userManagement.jsx

@@ -36,13 +36,6 @@ class UserManagement extends React.Component {
             tableBodyHeight,
             pageSize: Math.ceil((tableBodyHeight) / 38)
         });
-
-        const tableEl = document.getElementsByClassName('usermanagement-table')[0];
-        const tableScrollEl = tableEl.getElementsByClassName('ant-table-scroll')[0];
-        this.setState({
-            tableBodyHeight: tableScrollEl.offsetHeight - 38,
-            pageSize: Math.ceil((tableScrollEl.offsetHeight - 38) / 38)
-        });
     }
 
     render() {
@@ -51,13 +44,11 @@ class UserManagement extends React.Component {
         const { newOne } = user;
         const { currentUser } = main;
 
-        console.log(newOne);
         const moreOperatingMenu = (
             <Menu className='operationmenu' visible={true}>
                 <Menu.Item
                     disabled={currentUser.code === newOne.code}
                     onClick={() => {
-                        // console.log();
                         dispatch({ type: 'user/remoteModify', fields: {
                             role: newOne.role === 'admin' ? 'normal' : 'admin'
                         } });

+ 255 - 88
src/components/authority/index.jsx

@@ -1,106 +1,273 @@
 import React from 'react'
-import { Layout, Input, Select, Spin } from 'antd'
+import { Tabs, Layout, Input, Menu, Table, Checkbox } from 'antd'
 import { connect } from 'dva'
-import * as service from '../../services/index'
-import URLS from '../../constants/url'
 import './index.less'
-const { Header, Content } = Layout
-const InputGroup = Input.Group
-const Option = Select.Option
+const { Sider, Content } = Layout
+const { Search } = Input
+const { TabPane } = Tabs
 
 class Authority extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {
-            dataList: [],
-            fetching: false,
-        };
+
+    componentDidMount() {
+        const { dispatch } = this.props;
+        dispatch({ type: 'userGroup/fetchList' });
+        dispatch({ type: 'user/fetchList' });
+        dispatch({ type: 'dashboard/remoteMenuTree' });
     }
 
-    fetchData = (keyword) => {
-        this.setState({ dataList: [], fetching: true }, () => {
-            let condition = keyword || '';
-            service.fetch({
-                url: URLS.USER_QUERY,
-                method: 'GET',
-                body: {
-                    condition
-                },
-            }).then(r => {
-                if(!r.err && r.data.code > 0) {
-                    return r;
-                }else {
-                    let obj = {};
-                    throw obj;
-                }
-            }).then(r => {
-                const resData = r.data.data || [];
-                this.setState({
-                    dataList: resData.map(d => ({
-                        code: d.id + '',
-                        name: d.name,
-                        account: d.userName + '',
-                        password: d.passWord,
-                        role: d.role,
-                        department: d.department,
-                        post: d.post,
-                    })),
-                    fetching: false
-                });
-            }).catch(ex => {
-                this.setState({
-                    dataList: [],
-                    fetching: false
-                });
-                console.error('fetch error', ex);
-            });
-        });
+    checkIndeterminate = (treeList) => {
+        const { authority } = this.props;
+        const { dashboardList } = authority;
+        let arr = treeList && treeList.length > 0 ? [ ...treeList ] : null;
+        for(let i = 0;arr && i < arr.length; i++) {
+            let l = arr[i];
+            if(l.type === 'menu') {
+                l.children = this.checkIndeterminate(l.children);
+                let checkedCount = l.children ? l.children.filter(c => c.type === 'dashboard').map(c => c.checked).filter(c => !!c).length : 0;
+                l.indeterminate = l.children ? (checkedCount > 0 && checkedCount < l.children.filter(c => c.type === 'dashboard').length) : false;
+                l.checked = l.children ? checkedCount !== 0 && checkedCount === l.children.filter(c => c.type === 'dashboard').length : false;
+            }else {
+                l.children = null;
+                l.indeterminate = false;
+                l.checked = dashboardList.findIndex(d => d === l.code) > -1;
+            }
+        }
+        return arr;
     }
 
-    generateOptions = () => {
-        const { dataList } = this.state;
-        let arr = dataList.filter(u => u.role !== 'super').map((s, i) => <Option key={s.code} value={s.code}>{s.name}</Option>)
-        console.log(arr);
-        return arr
+    changeTab = (key) => {
+        const { dispatch } = this.props;
+        dispatch({ type: 'authority/setFields', fields: [
+            { name: 'tabActiveKey', value: key },
+            { name: 'menuSelectedKeys', value: [] },
+            { name: 'dashboardList', value: [] },
+        ] });
     }
 
     render() {
-        // const { authority, dispatch } = this.props;
-        const { fetching } = this.state;
+        const { dashboard, authority, userGroup, user, dispatch } = this.props;
+        const { menuSelectedKeys, tabActiveKey, groupFilterLabel, userFilterLabel, groupLimit, userLimit } = authority;
+        const dashboardTreeList = this.checkIndeterminate(dashboard.menuTree);
         return <Layout className='layout-authority'>
-            <Header
-                theme='light'
-            >
-                <InputGroup compact>
-                    <Select
-                        defaultValue="group"
-                    >
-                        <Option value="group">用户组</Option>
-                        <Option value="user">用户</Option>
-                    </Select>
-                    <Select
-                        notFoundContent={fetching ? <Spin size="small" /> : '无'}
-                        showSearch
-                        filterOption={false} 
-                        onSearch={(value) => {
-                            const timeout = this.timeout;
-                            timeout && window.clearTimeout(timeout);
-                            this.timeout = window.setTimeout(() => {
-                                this.fetchData(value)
-                            }, 500)
-                        }}
-                        onFocus={() => {
-                            this.fetchData('');
-                        }}
-                    >
-                        { this.generateOptions() }
-                    </Select>
-                </InputGroup>
-            </Header>
+            <Sider>
+                <Tabs
+                    className='tabs-authority'
+                    type='card'
+                    tabPosition='top'
+                    defaultActiveKey="userGroup"
+                    activeKey={tabActiveKey}
+                    onChange={this.changeTab}
+                >
+                    <TabPane tab="用户组" key="userGroup" >
+                        <MenuList
+                            refName='group'
+                            selectedKeys={menuSelectedKeys}
+                            list={userGroup.list}
+                            filterLabel={groupFilterLabel}
+                            filterLabelChange={(val) => {
+                                dispatch({ type: 'authority/setFields', fields: [
+                                    { name: 'groupLimit', value: 30 },
+                                    { name: 'groupFilterLabel', value: val },
+                                ] })
+                            }}
+                            displayField='name'
+                            valueField='code'
+                            onItemClick={(item) => {
+                                dispatch({ type: 'authority/setFields', fields: [
+                                    { name: 'menuSelectedKeys', value: [item.code] },
+                                ] })
+                                dispatch({ type: 'authority/fetchDashboardTree', dtype: '0', code: item.code });
+                            }}
+                            limit={groupLimit}
+                            onScrollToBottom={() => {
+                                window.clearTimeout(this.groupLimitKey);
+                                this.groupLimitKey = window.setTimeout(() => {
+                                    dispatch({ type: 'authority/setFields', fields: [
+                                        { name: 'groupLimit', value: (groupLimit + 10 > userGroup.list.length ? userGroup.list.length : groupLimit + 10) },
+                                    ] })
+                                }, 500);
+                            }}
+                        />
+                    </TabPane>
+                    <TabPane tab="用户" key="user">
+                        <MenuList
+                            refName='user'
+                            selectedKeys={menuSelectedKeys}
+                            list={user.list}
+                            filterLabel={userFilterLabel}
+                            filterLabelChange={(val) => {
+                                dispatch({ type: 'authority/setFields', fields: [
+                                    { name: 'userLimit', value: 30 },
+                                    { name: 'userFilterLabel', value: val },
+                                ] })
+                            }}
+                            displayField='fullName'
+                            valueField='code'
+                            onItemClick={(item) => {
+                                dispatch({ type: 'authority/setFields', fields: [
+                                    { name: 'menuSelectedKeys', value: [item.code] },
+                                ] })
+                                dispatch({ type: 'authority/fetchDashboardTree', dtype: '1', code: item.code });
+                            }}
+                            limit={userLimit}
+                            onScrollToBottom={() => {
+                                window.clearTimeout(this.userLimitKey);
+                                this.userLimitKey = window.setTimeout(() => {
+                                    dispatch({ type: 'authority/setFields', fields: [
+                                        { name: 'userLimit', value: (userLimit + 10 > user.list.length ? user.list.length : userLimit + 10) },
+                                    ] })
+                                }, 500);
+                            }}
+                        />
+                    </TabPane>
+                </Tabs>
+            </Sider>
             <Content>
-                Content
+                <DashBoardTree dataSource={dashboardTreeList} onRowCheckChange={(record, checked) => {
+                    if(!!menuSelectedKeys[0]) {
+                        if(record.type === 'menu') {
+                            let dashboardCodes = record.children.filter(c => c.type === 'dashboard').map(c => c.code)
+                            dispatch({ type: 'authority/' + (checked ? 'addAll': 'removeAll'), dtype: tabActiveKey === 'user' ? 1 : 0, code: menuSelectedKeys[0], dashboardCodes });
+                        }else {
+                            dispatch({ type: 'authority/' + (checked ? 'add': 'remove'), dtype: tabActiveKey === 'user' ? 1 : 0, code: menuSelectedKeys[0], dashboardCode: record.code });
+                        }
+                    }
+                }}/>
             </Content>
         </Layout>
     }
 }
-export default connect(({ present: { authority } }) => ({ authority }))(Authority)
+
+class MenuList extends React.Component {
+    componentDidMount() {
+        this.addEvents();
+    }
+
+    addEvents = () => {
+        const { refName } = this.props;
+        let tabs = this['menuList-' + refName];
+        let menu = tabs.getElementsByClassName('ant-menu')[0];
+        menu.removeEventListener('scroll', this.onMenuScroll);
+        menu.addEventListener('scroll', this.onMenuScroll);
+    }
+
+    onMenuScroll = (e) => {
+        const { onScrollToBottom } = this.props;
+        let target = e.target;
+        if(target.scrollHeight - target.offsetHeight === target.scrollTop) { // 滚动到底了
+            typeof onScrollToBottom === 'function' && onScrollToBottom()
+        }
+    }
+
+    render() {
+        const { refName, selectedKeys, list, filterLabel: pFilterLabel, filterLabelChange, displayField, valueField, onItemClick, limit } = this.props;
+        const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
+        let filterLabel = (pFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+
+        return <div ref={node => this['menuList-' + refName] = node} className='menu-list'>
+            <div className='search-area'>
+                <Search
+                    value={pFilterLabel}
+                    placeholder="请输入关键字"
+                    onChange={e => {
+                        let val = e.target.value + '';
+                        typeof filterLabelChange === 'function' && filterLabelChange(val);
+                    }}
+                />
+            </div>
+            <Menu
+                selectedKeys={selectedKeys}
+            >
+                {list.filter(l => {
+                    let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
+                    return (l[displayField] || '').search(reg) !== -1;
+                }).slice(0, limit).map(l => (
+                    <Menu.Item key={l[valueField]+''} onClick={() => {
+                        typeof onItemClick === 'function' && onItemClick(l);
+                    }} >
+                        <div className='item-title'>
+                            <span className='label' title={l[displayField]}>
+                                { filterLabel ?
+                                    ((l[displayField] || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                                        return (
+                                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                                            fragment
+                                        )
+                                    }
+                                    )) : <span>{l[displayField]}</span>
+                                }
+                            </span>
+                        </div>
+                    </Menu.Item>
+                ))}
+            </Menu>
+        </div>
+    }
+}
+
+class DashBoardTree extends React.Component {
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            tableScrollHeight: 0,
+            pageSize: 0,
+        }
+    }
+
+    componentDidMount() {
+        this.tableSize();
+        window.addEventListener('resize', this.tableSize);
+    }
+
+    componentWillUnmount() {
+        window.removeEventListener('resize', this.tableSize);
+    }
+
+    tableSize = () => {
+        const tableWrapper = document.getElementsByClassName('ant-table-wrapper')[0];
+        const content = tableWrapper.getElementsByClassName('ant-spin-nested-loading')[0];
+        const tableHeader = content.querySelector('thead');
+        const padding = content.getBoundingClientRect().top - tableWrapper.getBoundingClientRect().top;
+        // 容器高度 - padding * 2 - 分页器高度 - 表头高度
+        let tableScrollHeight = tableWrapper.offsetHeight - padding * 2 - 42 - tableHeader.offsetHeight;
+        this.setState({
+            tableScrollHeight,
+            pageSize: Math.ceil((tableScrollHeight) / 38)
+        });
+    }
+
+    render() {
+        const { dataSource, onRowCheckChange } = this.props;
+        const { tableScrollHeight, pageSize } = this.state;
+
+        const columns = [{
+            title: '名称',
+            dataIndex: 'name',
+            key: 'name',
+            width: '80%',
+            render: (text, record, index) => <span style={{ fontWeight: record.type === 'dashboard' ? 'bold' : 'normal' }}>{text}</span>
+        }, {
+            title: '查看',
+            dataIndex: 'view',
+            key: 'view',
+            width: '20%',
+            render: (text, record, index) => {
+                return <Checkbox disabled={record.type === 'menu' && (!record.children || record.children.filter(c => c.type === 'dashboard').length === 0)} indeterminate={record.indeterminate} checked={record.checked} onChange={(e) => {
+                    let checked = e.target.checked;
+                    typeof onRowCheckChange === 'function' && onRowCheckChange(record, checked);
+                }} />
+            }
+        }];
+
+        return <Table columns={columns} dataSource={dataSource} scroll={{x: false, y: tableScrollHeight}}
+            size='small'    
+            pagination={{
+                pageSize: pageSize
+            }}
+        />
+    }
+}
+
+export default connect(({ present: { authority, userGroup, user, dashboard } }) => ({ authority, userGroup, user, dashboard }))(Authority)

+ 67 - 4
src/components/authority/index.less

@@ -1,8 +1,71 @@
 .layout-authority {
-    .ant-layout-header {
-        .ant-input-group {
-            .ant-select {
-                min-width: 150px;
+    flex-direction: row;
+    .ant-layout-sider {
+        .tabs-authority {
+            height: 100%;
+            padding: 12px 0 12px 12px;
+            display: flex;
+            flex-direction: column;
+            background: #fff;
+            > .ant-tabs-bar {
+                border: none;
+                margin: 0 0 12px 0;
+                &> .ant-tabs-nav-container {
+                    .ant-tabs-nav-wrap {
+                        .ant-tabs-tab {
+                            color: @tab-color;
+                            background: @tab-background;
+                            border-color: @tab-background-active;
+                            border-radius: 0;
+                            border-right-width: 0;
+                            margin: 0;
+                            text-align: center;
+                            &.ant-tabs-tab-active {
+                                color: @tab-color-active;
+                                background: @tab-background-active;
+                            }
+                            &:last-child {
+                                border-right-width: 1px;
+                            }
+                        }
+                    }
+                }
+            }
+            > .ant-tabs-content {
+                flex: auto;
+                overflow: hidden;
+                background:  #FAFAFA;
+                padding: 8px;
+                border: 1px solid rgba(0,0,0,0.10);
+                >.ant-tabs-tabpane {
+                    height: 100%;
+                    > .menu-list {
+                        height: 100%;
+                        display: flex;
+                        flex-direction: column;
+                        &.ant-tabs-tabpane-inactive {
+                            display: none;
+                        }
+                        >.ant-menu {
+                            overflow: auto;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    .ant-layout-content {
+        .ant-table-wrapper {
+            background: #fafafa;
+            margin: 12px;
+            height: calc(~'100% - 24px');
+            padding: 8px;
+            border: 1px solid rgba(0, 0, 0, 0.1);
+            .ant-table-body {
+                margin-top: 0;
+            }
+            .ant-pagination {
+                margin: 8px 0;
             }
         }
     }

+ 0 - 52
src/components/authority/index1.jsx

@@ -1,52 +0,0 @@
-import React from 'react'
-import { Layout } from 'antd'
-import { connect } from 'dva'
-import DashboardMenu from '../dashboard/menu'
-const { Sider, Content } = Layout
-
-class Authority extends React.Component {
-    constructor(props) {
-        super(props);
-        this.state = {};
-    }
-
-    render() {
-        const { authority, dispatch } = this.props;
-        console.log(authority);
-        return <Layout>
-            <Sider
-                theme='light'
-                width={300}
-            >
-                <DashboardMenu
-                    model={authority}
-                    editable={false}
-                    searchMenu={true}
-                    onlyMenu={false}
-                    hideHeader={false}
-                    hideEmptyMenu={true}
-                    onExpand={menus => {
-                        dispatch({ type: 'authority/setFields', fields: [
-                            { name: 'menuExpandedKeys', value: menus.map(m => m.code) },
-                            { name: 'menuAutoExpandParent', value: false },
-                        ] });
-                    }}
-                    onSelect={selectedMenu => {
-                        dispatch({ type: 'authority/setField', name: 'menuSelectedKeys', value: selectedMenu && selectedMenu.type === 'dashboard' ? [selectedMenu.code] : [] })
-                    }}
-                    onSearch={(keyword, expandedMenus) => {
-                        dispatch({ type: 'authority/setFields', fields: [
-                            { name: 'menuExpandedKeys', value: expandedMenus.map(m => m.code) },
-                            { name: 'menuFilterLabel', value: keyword },
-                            { name: 'menuAutoExpandParent', value: true },
-                        ] });
-                    }}
-                />
-            </Sider>
-            <Content>
-                
-            </Content>
-        </Layout>
-    }
-}
-export default connect(({ present: { authority } }) => ({ authority }))(Authority)

+ 3 - 0
src/components/chart/list.less

@@ -42,6 +42,9 @@
                         .btn-refresh {
                             border: none;
                             font-size: 18px;
+                            &:after {
+                                content: none;
+                            }
                         }
                     } 
                 }

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

@@ -7,7 +7,6 @@ import EmptyContent from '../../common/emptyContent'
 const EchartsView = ({ chartDesigner, dispatch, optionConfig }) => {
     const { chartOption } = chartDesigner;
     const option = deepAssign(chartOption, optionConfig);
-    // console.log(deepAssign({a: {b: 10}}, {b: 20}, {a: {c: 30}}, { a: { b: 20 }}));
     if(!option.series) {
         return <EmptyContent />
     }else {

+ 0 - 2
src/components/chartDesigner/sections/scatterConfigForm.jsx

@@ -47,8 +47,6 @@ const ScatterConfigForm = ({ autoRefresh, chartDesigner, dispatch, formItemLayou
 					onChange={(value, items) => {
 						let column = {};
 						let granularity = {};
-						console.log('items', items)
-						console.log('value', value)
 						if(items.length > 0) {
 							column = { type: items[0].type, value: items[0].value, label: items[0].label };
 						}

+ 0 - 1
src/components/chartDesigner/sections/style/table.jsx

@@ -64,7 +64,6 @@ class TableStyle extends React.Component {
             return;
         }else {
             let idx = thousandsSeparatorColumns.findIndex(s => s === formatColumn.name);
-            console.log(idx);
             checked ? (idx !== -1 ? (void 0) : thousandsSeparatorColumns.push(formatColumn.name)) : thousandsSeparatorColumns.splice(idx, 1);
         }
         dispatch({ type: 'chartDesigner/setField', name: 'styleConfig', value: { ...styleConfig, table: { ...table, thousandsSeparatorColumns }} });

+ 146 - 104
src/components/common/accessObjectBox/accessObjectBox.jsx

@@ -11,11 +11,15 @@ class AccessObjectBox extends React.Component {
     constructor(props) {
         super(props);
         this.state = {
+            groupFilterLabel: '',
+            userFilterLabel: '',
             selectedGroups: props.defaultSelectedGroups && props.defaultSelectedGroups.length >= 0 ? props.defaultSelectedGroups : [],
             selectedUsers: props.defaultSelectedUsers && props.defaultSelectedUsers.length >= 0 ? props.defaultSelectedUsers : [],
             columnWidth: 100,
             boxHeight: 0,
             tableHeaderHeight: 60,
+            groupLimit: 30,
+            userLimit: 30,
         }
     }
 
@@ -23,29 +27,8 @@ class AccessObjectBox extends React.Component {
         const { dispatch } = this.props;
         new Promise(() => {
             dispatch({ type: 'userGroup/fetchList' });
-            dispatch({ type: 'user/fetchList' }).then(() => {
-                window.setTimeout(() => {
-                    var e = document.createEvent("Event");
-                    e.initEvent("resize", true, true);
-                    window.dispatchEvent(e);
-                }, 20);
-            });
+            dispatch({ type: 'user/fetchList' })
         })
-        window.addEventListener('resize', this.onWindowResize);
-    }
-
-    componentWillUnmount() {
-        window.removeEventListener('resize', this.onWindowResize);
-    }
-
-    onWindowResize = () => {
-        const boxEl = document.getElementsByClassName('accessobject-box')[0].getElementsByClassName('ant-modal-content')[0];
-        const tableHeaderEl = boxEl.getElementsByTagName('thead')[0];
-
-        this.setState({
-            boxHeight: boxEl.offsetHeight,
-            tableHeaderHeight: tableHeaderEl.offsetHeight + 2, // 表头高度(含边框)
-        });
     }
     
     getAccessObject = () => {
@@ -57,15 +40,14 @@ class AccessObjectBox extends React.Component {
 
     render() {
         const { visibleBox, hideBox, userGroup, user, defaultSelectedGroups: _defaultSelectedGroups, defaultSelectedUsers: _defaultSelectedUsers } = this.props;
-        const { selectedGroups, selectedUsers, columnWidth, boxHeight } = this.state;
+        const { selectedGroups, selectedUsers, columnWidth, groupLimit, userLimit } = this.state;
 
         const defaultSelectedGroups = _defaultSelectedGroups && _defaultSelectedGroups.length >= 0 ? _defaultSelectedGroups : [];
         const defaultSelectedUsers = _defaultSelectedUsers && _defaultSelectedUsers.length >= 0 ? _defaultSelectedUsers : [];
 
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
-        let filterLabel = (this.state.filterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
-
-        const tableBodyHeight = boxHeight - 50 - 45 - 37 - 53 - 2;
+        let groupFilterLabel = (this.state.groupFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
+        let userFilterLabel = (this.state.userFilterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
 
         const userGroupColumns = [{
             key: 'check',
@@ -97,10 +79,10 @@ class AccessObjectBox extends React.Component {
             dataIndex: 'name',
             width: 400,
             render: value => <span>
-                { filterLabel ?
-                    ((value || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                { groupFilterLabel ?
+                    ((value || '').split(new RegExp(`(${groupFilterLabel})`, 'i')).map((fragment, i) => {
                         return (
-                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === groupFilterLabel.toLowerCase() ?
                             <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                             fragment
                         )
@@ -123,10 +105,10 @@ class AccessObjectBox extends React.Component {
             dataIndex: 'fullName',
             width: 400,
             render: value => <span>
-                { filterLabel ?
-                    ((value || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                { userFilterLabel ?
+                    ((value || '').split(new RegExp(`(${userFilterLabel})`, 'i')).map((fragment, i) => {
                         return (
-                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === userFilterLabel.toLowerCase() ?
                             <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
                             fragment
                         )
@@ -141,109 +123,88 @@ class AccessObjectBox extends React.Component {
                 className='accessobject-box'
                 width='60%'
                 height='80%'
-                title={
-                    <Row>
-                        <Col span={14}>选择用户组或用户</Col>
-                        <Col span={8}><Search 
-                            placeholder="请输入关键字"
-                            value={this.state.filterLabel}
-                            onChange={e => {
-                                this.setState({
-                                    filterLabel: e.target.value
-                                });
-                            }}
-                        /></Col>
-                    </Row>
-                }
+                title='选择用户组或用户'
                 visible={visibleBox}
                 onCancel={hideBox}
                 onOk={this.getAccessObject}
                 maskClosable={false}
                 destroyOnClose={true}
             >
-                <Tabs 
+                <Tabs
+                    type='card'
                     className='accessobject-tabs'
                     defaultActiveKey="userGroup"
                 >
                     <TabPane tab="用户组" key="userGroup" >
-                        <Table
-                            className='object-table usergroup-table'
+                        <TableList
+                            refName='grouptable'
+                            filterLabel={this.state.groupFilterLabel}
+                            onFilterLabelChange={(val) => {
+                                this.setState({
+                                    groupFilterLabel: val
+                                });
+                            }}
                             columns={userGroupColumns.map(c => ({
                                 ...c, width: columnWidth
                             }))}
                             dataSource={userGroup.list.filter(l => {
-                                let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
+                                let reg = new RegExp('(' + groupFilterLabel + '){1}', 'ig');
                                 return (l.name || '').search(reg) !== -1;
-                             }).map((l, i) => ({
+                            }).slice(0, groupLimit).map((l, i) => ({
                                 ...l,
                                 key: i
                             }))}
-                            size='small'
-                            pagination={false}
-                            scroll={{
-                                x: userColumns.length * columnWidth,
-                                y: tableBodyHeight
-                            }}
-                            onRow={(record) => {
-                                return {
-                                    onClick: () => {
-                                        console.log(record);
-                                        const idx = selectedGroups.findIndex(i => i.code === record.code);
-                                        if(idx === -1) {
-                                            selectedGroups.push({
-                                                code: record.code,
-                                                name: record.name,
-                                                isGroup: true
-                                            });
-                                        }else {
-                                            selectedGroups.splice(idx, 1);
-                                        }
-                                        this.setState({
-                                            selectedGroups: selectedGroups
-                                        })
-                                    }
-                                };
+                            onRowClick={(record) => {
+                                const idx = selectedGroups.findIndex(i => i.code === record.code);
+                                if(idx === -1) {
+                                    selectedGroups.push({
+                                        code: record.code,
+                                        name: record.name,
+                                        isGroup: true
+                                    });
+                                }else {
+                                    selectedGroups.splice(idx, 1);
+                                }
+                                this.setState({
+                                    selectedGroups: selectedGroups
+                                })
                             }}
                         />
                     </TabPane>
                     <TabPane tab="用户" key="user" >
-                        <Table
-                            className='object-table user-table'
+                        <TableList
+                            refName='usertable'
+                            filterLabel={this.state.userFilterLabel}
+                            onFilterLabelChange={(val) => {
+                                this.setState({
+                                    userFilterLabel: val
+                                });
+                            }}
                             columns={userColumns.map(c => ({
                                 ...c,
                                 width: columnWidth
                             }))}
                             dataSource={user.list.filter(l => {
-                                let reg = new RegExp('(' + filterLabel + '){1}', 'ig');
+                                let reg = new RegExp('(' + userFilterLabel + '){1}', 'ig');
                                 return (l.fullName || '').search(reg) !== -1;
-                             }).map((l, i) => ({
+                            }).slice(0, userLimit).map((l, i) => ({
                                 ...l,
                                 key: i
                             }))}
-                            size='small'
-                            pagination={false}
-                            scroll={{
-                                x: userColumns.length * columnWidth,
-                                y: tableBodyHeight
-                            }}
-                            onRow={(record) => {
-                                return {
-                                    onClick: () => {
-                                        const idx = selectedUsers.findIndex(i => i.code === record.code);
-                                        if(idx === -1) {
-                                            selectedUsers.push({
-                                                code: record.code,
-                                                name: record.fullName,
-                                                isGroup: false
-                                            });
-                                        }else {
-                                            selectedUsers.splice(idx, 1);
-                                        }
-                                        this.setState({
-                                            selectedUsers: selectedUsers
-                                        })
-                                    }
-                                };
+                            onRowClick={(record) => {
+                                const idx = selectedUsers.findIndex(i => i.code === record.code);
+                                if(idx === -1) {
+                                    selectedUsers.push({
+                                        code: record.code,
+                                        name: record.fullName,
+                                        isGroup: false
+                                    });
+                                }else {
+                                    selectedUsers.splice(idx, 1);
+                                }
+                                this.setState({
+                                    selectedUsers: selectedUsers
+                                })
                             }}
                         />
                     </TabPane>
@@ -253,4 +214,85 @@ class AccessObjectBox extends React.Component {
     }
 }
 
+class TableList extends React.Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            pageSize: 0,
+            tableScrollHeight: 0,
+            currentPage: 1,
+        };
+    }
+
+    componentDidMount() {
+        this.resetTableScrollSize();
+        window.addEventListener('resize', this.resetTableScrollSize);
+    }
+
+    componentWillUnmount() {
+        window.removeEventListener('resize', this.resetTableScrollSize);
+    }
+
+    resetTableScrollSize = () => {
+        const { refName } = this.props;
+        const tableWrapper = this[refName].getElementsByClassName('object-table')[0];
+        const content = tableWrapper.getElementsByClassName('ant-spin-nested-loading')[0];
+        const tableHeader = content.querySelector('thead');
+        // 容器高度 - 分页器高度 - 表头高度
+        let tableScrollHeight = tableWrapper.offsetHeight - 42 - tableHeader.offsetHeight - 10;
+        this.setState({
+            tableScrollHeight,
+            pageSize: Math.ceil((tableScrollHeight) / 38)
+        });
+    }
+
+    onPageChange = page => {
+        this.setState({
+            currentPage: page
+        });
+    }
+    
+    render() {
+        const { refName, filterLabel, onFilterLabelChange, columns, dataSource, onRowClick } = this.props;
+        const { tableScrollHeight, pageSize, currentPage } = this.state;
+
+        return <div ref={node => this[refName] = node} className='table-list'>
+            <Row type='flex' justify='end' style={{ position: 'absolute', right: 0, top: 0 }}>
+                <Col style={{ padding: '8px' }}><Search 
+                    placeholder="请输入关键字"
+                    value={filterLabel}
+                    onChange={e => {
+                        this.setState({
+                            currentPage: 1,
+                        });
+                        onFilterLabelChange && onFilterLabelChange(e.target.value + '');
+                    }}
+                /></Col>
+            </Row>
+            <Table
+                className='object-table'
+                columns={columns}
+                dataSource={dataSource}
+                size='small'
+                pagination={{
+                    pageSize: pageSize,
+                    current: currentPage,
+                    onChange: this.onPageChange
+                }}
+                scroll={{
+                    x: false,
+                    y: tableScrollHeight
+                }}
+                onRow={(record) => {
+                    return {
+                        onClick: () => {
+                            onRowClick && onRowClick(record)
+                        }
+                    };
+                }}
+            />
+        </div>
+    }
+}
+
 export default connect(({ present: { userGroup, user } }) => ({ userGroup, user }))(AccessObjectBox);

+ 62 - 22
src/components/common/accessObjectBox/accessObjectBox.less

@@ -1,33 +1,73 @@
 .accessobject-box {
-    top: 10%;
+    top: 50px;
     &>.ant-modal-content {
+        display: flex;
+        flex-direction: column;
         max-height: 100%;
         height: 100%;
-        padding-top: 50px;
         overflow: hidden;
-        &>.ant-modal-header {
-            margin-top: -50px;
-            height: 50px;
-            line-height: 50px;
-            padding: 12px 24px;
-        }
-    }
-    .ant-modal-body {
-        padding: 0;
-        &>.accessobject-tabs {
-            margin: 0;
-            &>.ant-tabs-bar {
+        .ant-modal-body {
+            flex: 1;
+            overflow: hidden;
+            padding: 0 12px 0 12px;
+            &>.accessobject-tabs {
+                display: flex;
+                flex-direction: column;
+                height: 100%;
                 margin: 0;
+                &> .ant-tabs-bar {
+                    border: none;
+                    margin: 0 0 12px 0;
+                    &> .ant-tabs-nav-container {
+                        .ant-tabs-nav-wrap {
+                            .ant-tabs-tab {
+                                color: @tab-color;
+                                background: @tab-background;
+                                border-color: @tab-background-active;
+                                border-radius: 0;
+                                border-right-width: 0;
+                                margin: 0;
+                                text-align: center;
+                                &.ant-tabs-tab-active {
+                                    color: @tab-color-active;
+                                    background: @tab-background-active;
+                                }
+                                &:last-child {
+                                    border-right-width: 1px;
+                                }
+                            }
+                        }
+                    }
+                }
+                &>.ant-tabs-content {
+                    flex: 1;
+                    overflow: hidden;
+                    &>.ant-tabs-tabpane {
+                        height: 100%;
+                        .table-list {
+                            height: 100%;
+                            display: flex;
+                            flex-direction: column;
+                            .object-table {
+                                flex: 1;
+                                overflow: hidden;
+                            }
+                        }
+                    }
+                }
             }
-        }
-        .object-table {
-            .ant-table-header {
-                overflow-y: hidden;
-                margin-right: 6px;
-            }
-            .ant-table-body {
-                height: 999px; // 最终高度等于max-height
+            .object-table {
+                .ant-table-header {
+                    overflow-y: hidden;
+                    margin-right: 6px;
+                }
+                .ant-table-body {
+                    margin-top: 0;
+                }
             }
         }
+        .ant-modal-footer {
+            border: none;
+        }
     }
 }

+ 3 - 2
src/components/common/cusIcon/index.jsx

@@ -1,5 +1,6 @@
 import { Icon } from 'antd'
-
+import scriptUrl from '../../../../static/iconfont/iconfont.js'
+ 
 export default Icon.createFromIconfontCN({
-    scriptUrl: '../../../../static/iconfont/iconfont.js'
+    scriptUrl
 });

+ 0 - 3
src/components/common/selectUserBox/selectUserBox.jsx

@@ -114,9 +114,6 @@ class AddGroupMemberBox extends React.Component {
                                     }
                                 });
                             }}
-                            onKeyPress={() => {
-                                console.log(112131231);
-                            }}
                         >
                             { userData.filter(u => !!onlyAdmin ? (u.role === 'admin') : ( true )).map((s, i) => {
                                 return <SelectOption key={i} value={s.code} disabled={!!selectedUsers && selectedUsers.length > 0 && selectedUsers.findIndex(u => u.code === s.code) !== -1}>{s.name}</SelectOption>

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

@@ -37,7 +37,6 @@ class DashboardList extends React.Component {
         const { dashboard, dispatch } = this.props;
         const { currentMenu } = dashboard;
         this.setScrollTableHeight();
-        console.log(currentMenu);
         if(currentMenu && currentMenu.code !== '-1') {
             dispatch({ type: 'dashboard/remoteMenuDashboardList', menuCode: currentMenu.code });
         }else {
@@ -90,7 +89,7 @@ class DashboardList extends React.Component {
                     });
                 }
             ).catch(reject => {
-                console.log(reject);
+                console.error(reject);
             });
         });
     }

+ 3 - 0
src/components/dashboard/list.less

@@ -38,6 +38,9 @@
                     .btn-refresh {
                         border: none;
                         font-size: 18px;
+                        &:after {
+                            content: none;
+                        }
                     }
                 }
             }

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

@@ -11,7 +11,6 @@ class ChartView extends React.Component {
     
     constructor(props) {
         super(props);
-        console.log('init');
         this.state = {
             tableScrollHeight: 0,
             layout: { ...props.item.layout },
@@ -35,18 +34,7 @@ class ChartView extends React.Component {
         window.removeEventListener('resize', this.setTableSize);
     }
 
-    // static getDerivedStateFromProps = (props, state) => {
-    //     console.log(props.item.layout, state.layout);
-    //     if(!isEqual(props.item.layout, state.layout)) {
-    //         return {
-    //             tableScrollHeight: ChartView.getTableScrollSize()
-    //         }
-    //     }else {
-    //         return null;
-    //     }
-    // }
     componentDidUpdate(preProps) {
-        console.log(preProps.item.layout, this.state.layout);
         if(!isEqual(preProps.item.layout, this.state.layout)) {
             this.setState({
                 layout: { ...preProps.item.layout },
@@ -71,9 +59,7 @@ class ChartView extends React.Component {
         const { item, editMode, dispatch, readOnly, chartRef } = this.props;
         const { tableScrollHeight } = this.state;
         const { viewType, chartType, content, chartOption, fetching } = item;
-        // let children = <div className='chart-default mover'></div>;
         let children = <EmptyContent/>;
-        console.log(tableScrollHeight);
         
         if(viewType === 'chart') { // 图表类型
             if(chartOption) {

+ 0 - 2
src/components/dashboardDesigner/richTextEditor.jsx

@@ -45,12 +45,10 @@ class RichTextEditor extends Component {
             let toolbarElLayout = toolbarEl.getBoundingClientRect(); // 工具栏组件layout
             
             
-            console.log(toolbarEl);
             let viewElX = viewElLayout.left; // chart/richText组件左起位置
             let toolbarWidth = toolbarElLayout.width; // 工具栏组件宽度
             let boardWidth = boardElLayout.width; // 报表容器宽度
 
-            console.log(viewElX, toolbarWidth, boardWidth);
             if((viewElX + toolbarWidth) > boardWidth) { // 工具栏超出容器组件右边
                 toolbarEl.style.left = -(viewElX + toolbarWidth - boardWidth + 62) + 'px';
             }else {

+ 3 - 0
src/components/dataConnect/list.less

@@ -16,6 +16,9 @@
                         .btn-refresh {
                             border: none;
                             font-size: 18px;
+                            &:after {
+                                content: none;
+                            }
                         }
                     } 
                 }

+ 3 - 0
src/components/dataSource/list.less

@@ -42,6 +42,9 @@
                     .btn-refresh {
                         border: none;
                         font-size: 18px;
+                        &:after {
+                            content: none;
+                        }
                     }
                 }
             }

+ 0 - 3
src/components/dataSourceDetail/accessConfig.jsx

@@ -121,8 +121,6 @@ class DataSourceAccessConfig extends React.Component{
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
         let filterLabel = (this.state.filterLabel || '').replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1'); // 添加转义符号
         
-        // let owner = user.list.find(l => l.code === dataSourceDetail.creator); // 数据源拥有者
-        // console.log(owner);
         const columnData = dataSourceDetail.columns ? dataSourceDetail.columns.filter(c => c.using).map(c => ({
             key: c.key,
             label: c.alias,
@@ -144,7 +142,6 @@ class DataSourceAccessConfig extends React.Component{
                         ...r,
                         enabled: e.target.checked
                     }
-                    console.log(policy);
                     dispatch({ type: 'dataSourcePolicy/remoteModify', policy });
                 }}
                 checked={v}

+ 1 - 1
src/components/dataSourceDetail/baseConfig.jsx

@@ -128,7 +128,7 @@ class DataSourceBaseConfig extends React.Component {
                             {/* <div style={{ textAlign: 'end', color: '#F5222D' }}>*若只修改数据链接,请确认不同数据库取数逻辑一致</div> */}
                             <FormItem label='数据链接' {...formItemLayout}>
                                 <Select
-                                    disabled
+                                    // disabled
                                     value={dataSourceDetail.connectCode}
                                     onChange={(value) => {
                                         let selectedDataConnect = dataConnect.list.filter((l) => l.code === value)[0];

+ 89 - 48
src/components/dataSourceDetail/dataConnectBox.jsx

@@ -11,7 +11,6 @@ class DataConnectBox extends React.Component {
         super(props);
         this.state = {
             password: '',
-            passwordEditing: false,
             validInfo: {
                 name: { status: 'success', help: '' },
                 dbType: { status: 'success', help: '' },
@@ -33,21 +32,68 @@ class DataConnectBox extends React.Component {
     okHandler() {
         const { dispatch, dataConnect} = this.props;
         const operation = dataConnect.newOne.boxOperation;
-        if(operation === 'create') {
+        this.validAll();
+        if(operation === 'create' && this.checkValid()) {
             dispatch({ type: 'dataConnect/remoteAdd' }).then((success) => {
                 success && this.hideBox()
             });
-        }else if(operation === 'modify') {
+        }else if(operation === 'modify' && this.checkValid()) {
             dispatch({ type: 'dataConnect/remoteModify', code: dataConnect.newOne.code }).then((success) => {
                 success && this.hideBox();
             });
         }
     }
 
-    checkValid() {
-        const { dataConnect } = this.props;
+    validAll = () => {
+        const { boxOperation } = this.props.dataConnect.newOne;
+        const arr = [
+            { name: 'name', label: '数据链接名称', rule: { required: true, maxLength: 50 } },
+            { name: 'dbType', label: '数据库类型', rule: { required: true } },
+            { name: 'address', label: '数据库地址', rule: { required: true } },
+            { name: 'port', label: '端口', rule: { required: true } },
+            { name: 'dbName', label: '数据库名', rule: { required: true } },
+            { name: 'userName', label: '用户名', rule: { required: true } },
+            { name: 'password', label: '密码', rule: { required: boxOperation === 'create' } },
+            { name: 'description', label: '说明', rule: { maxLength: 150 } },
+        ]
+        for(let i = 0; i < arr.length; i++) {
+            let a = arr[i];
+            this.valid(a.name, undefined, a.label, a.rule);
+        }
+    }
+
+    // // 执行校验并生成错误提示
+    valid = (fieldName, nowValue, fieldLabel, rule) => {
         const { validInfo } = this.state;
+        const { dataConnect } = this.props;
         const { newOne } = dataConnect;
+        const { required, maxLength, minLength, reg } = rule;
+
+        let value = nowValue === undefined  ? newOne[fieldName] : nowValue;
+        let status = 'success';
+        let help = '';
+        if(required !== undefined && required) {
+            status = (value === undefined || value === null) ? 'error' : ((value + '').trim().length === 0 ? 'error' : 'success');
+            help = (value === undefined || value === null) ? fieldLabel + '不能为空' : ((value + '').trim().length === 0 ? fieldLabel + '不能为空' : '');
+        }else if(minLength !== undefined && minLength > 0) {
+            status = !!value && (value + '').length < minLength ? 'error' : 'success'
+            help = !!value && (value + '').length < minLength ? fieldLabel + '长度不能小于' + minLength + '个字符' : ''
+        }else if(maxLength !== undefined && maxLength > 0) {
+            status = !!value && (value + '').length > maxLength ? 'error' : 'success'
+            help = !!value && (value + '').length > maxLength ? fieldLabel + '长度不能大于' + maxLength + '个字符' : ''
+        }else if(reg !== undefined) {
+            status = !!value.match(new RegExp(reg)) ? 'success' : 'error'
+            help = !!value.match(new RegExp(reg)) ? '' : fieldLabel + '格式有误'
+        }
+        validInfo[fieldName] = { status, help }
+        this.setState({
+            validInfo
+        });
+    }
+
+    // 检查错误提示
+    checkValid = () => {
+        const { validInfo } = this.state;
         let flag = true;
 
         for(let k in validInfo) {
@@ -56,13 +102,12 @@ class DataConnectBox extends React.Component {
             }
         }
 
-        return flag && !!newOne && !!newOne.name && (newOne.name + '').length <= 50 && !!newOne.dbType && !!newOne.address && !!newOne.port &&
-            !!newOne.dbName && !!newOne.userName && (newOne.description + '').length <= 150 && (newOne.boxOperation === 'create' ? !!newOne.password : true);
+        return flag;
     }
 
     render() {
         const { dispatch, dataConnect } = this.props;
-        const { password, passwordEditing, validInfo } = this.state;
+        const { password, validInfo } = this.state;
         const operation = dataConnect.newOne.boxOperation;
         const disabled = operation === 'view';
 
@@ -82,13 +127,7 @@ class DataConnectBox extends React.Component {
                 footer={
                     operation === 'view' ? null : (
                         <Row>
-                            <Col className='validatemessage' span={12}>
-                                {/* {dataConnect.newOne.invalid !== undefined ? (dataConnect.newOne.invalid ? <span style={{ color: '#F5222D' }}>{dataConnect.newOne.invalidText}</span> : <span style={{ color: '#52C41A' }}>测试通过</span>) : ''} */}
-                            </Col>
-                            <Col span={12}>
-                                {/* <Button disabled={dataConnect.newOne.validating || dataConnect.newOne.saving} onClick={() => dispatch({ type:'dataConnect/remoteValidate'})}>
-                                {dataConnect.newOne.validating ? (<Icon type='loading' />) : ''}{dataConnect.newOne.validating ? '测试中' : '测试'}
-                                </Button> */}
+                            <Col>
                                 <Button type='danger' disabled={dataConnect.newOne.validating || dataConnect.newOne.saving} onClick={() => {
                                     dispatch({ type:'dataConnect/resetNewModel'});
                                     this.setState({
@@ -122,9 +161,7 @@ class DataConnectBox extends React.Component {
                                 let val = e.target.value+'';
                                 window.clearTimeout(this.nameTimeout);
                                 this.nameTimeout = window.setTimeout(() => {
-                                    this.setState({
-                                        validInfo: { ...validInfo, name: { status: (!val || val.length > 50 || val.length === 0) ? 'error' : 'success', help: val.length > 50 ? '链接名不能超过50个字符' : ((val+'').trim().length === 0 ? '链接名不能为空' : '') } }
-                                    });
+                                    this.valid('name', val, '数据链接名称', { required: true, maxLength: 50 });
                                 }, 100);
                             }}
                             onBlur={(e) => { dispatch({ type: 'dataConnect/setNewModelField', name: 'name', value: e.target.value+'' }) }}
@@ -132,8 +169,8 @@ class DataConnectBox extends React.Component {
                         </Input>
                     </FormItem>
                     <FormItem className='required' label='数据库类型' {...formItemLayout}
-                        validateStatus={(dataConnect.newOne.dbType === undefined || dataConnect.newOne.dbType) ? 'success' : 'error'}
-                        help={(dataConnect.newOne.dbType === undefined || dataConnect.newOne.dbType) ? '' : '数据库类型不能为空'}
+                        validateStatus={validInfo.dbType.status}
+                        help={validInfo.dbType.help}
                     >
                         <Select
                             key={dataConnect.newOne.dbType}
@@ -143,19 +180,20 @@ class DataConnectBox extends React.Component {
                             value={dataConnect.newOne.dbType}
                             onChange={(value) => {
                                 dispatch({ type: 'dataConnect/setNewModelField', name: 'dbType', value: value} );
+                                this.valid('dbType', value, '数据库类型', { required: true });
                             }}
                         >
                             <SelectOption value='oracle'>
-                                ORACLE
+                                Oracle
                             </SelectOption>
                             <SelectOption value='mysql'>
-                                MYSQL
+                                MySql
                             </SelectOption>
                             <SelectOption value='sqlserver'>
-                                SQLSERVER
+                                SQLServer
                             </SelectOption>
                             <SelectOption value='sqlite'>
-                                SQLITE
+                                SQLite
                             </SelectOption>
                         </Select>
                     </FormItem>
@@ -180,9 +218,7 @@ class DataConnectBox extends React.Component {
                                         let val = e.target.value+'';
                                         window.clearTimeout(this.addressTimeout);
                                         this.addressTimeout = window.setTimeout(() => {
-                                            this.setState({
-                                                validInfo: { ...validInfo, address: { status: (val.length === 0) ? 'error' : 'success', help: val.length === 0 ? '数据库地址不能为空' : '' } }
-                                            });
+                                            this.valid('address', val, '数据库地址', { required: true });
                                         }, 100);
                                     }}
                                 />
@@ -193,15 +229,14 @@ class DataConnectBox extends React.Component {
                                 labelCol: { span: 12 },
                                 wrapperCol: { span: 12 }
                             }}
-                            validateStatus={(dataConnect.newOne.port === undefined || dataConnect.newOne.port) ? 'success' : 'error'}
-                            help={(dataConnect.newOne.port === undefined || dataConnect.newOne.port) ? '' : '端口不能为空'}
+                            validateStatus={validInfo.port.status}
+                            help={validInfo.port.help}
                             >
                                 <InputNumber
-                                    // key={dataConnect.newOne.port}
                                     disabled={disabled}
-                                    // defaultValue={dataConnect.newOne.port}
                                     value={dataConnect.newOne.port}
                                     onChange={(value) => {
+                                        this.valid('port', value, '端口', { required: true });
                                         dispatch({ type: 'dataConnect/setNewModelField', name: 'port', value: value });
                                     }}
                                 />
@@ -209,17 +244,19 @@ class DataConnectBox extends React.Component {
                         </Col>
                     </Row>
                     <FormItem className='required' label='数据库名' {...formItemLayout}
-                        validateStatus={(dataConnect.newOne.dbName === undefined || dataConnect.newOne.dbName) ? 'success' : 'error'}
-                        help={(dataConnect.newOne.dbName === undefined || dataConnect.newOne.dbName) ? '' : '数据库名不能为空'}
+                        validateStatus={validInfo.dbName.status}
+                        help={validInfo.dbName.help}
                     >
                         <Input
                             key={dataConnect.newOne.dbName}
                             disabled={disabled}
-                            // defaultValue='orcl'
                             defaultValue={dataConnect.newOne.dbName}
                             onBlur={(e) => {
                                 dispatch({ type: 'dataConnect/setNewModelField', name: 'dbName', value: e.target.value+'' });
                             }}
+                            onChange={(e) => {
+                                this.valid('dbName', e.target.value+'', '数据库名', { required: true })
+                            }}
                         />
                     </FormItem>
                     <Row>
@@ -228,8 +265,8 @@ class DataConnectBox extends React.Component {
                                 labelCol: { span: 8 },
                                 wrapperCol: { span: 16 }
                             }}
-                            validateStatus={(dataConnect.newOne.userName === undefined || dataConnect.newOne.userName) ? 'success' : 'error'}
-                            help={(dataConnect.newOne.userName === undefined || dataConnect.newOne.userName) ? '' : '用户名不能为空'}
+                            validateStatus={validInfo.userName.status}
+                            help={validInfo.userName.help}
                             >
                                 <Input
                                     key={dataConnect.newOne.userName}
@@ -238,6 +275,9 @@ class DataConnectBox extends React.Component {
                                     onBlur={(e) => {
                                         dispatch({ type: 'dataConnect/setNewModelField', name: 'userName', value: e.target.value+'' });
                                     }}
+                                    onChange={(e) => {
+                                        this.valid('userName', e.target.value+'', '用户名', { required: true });
+                                    }}
                                 />
                             </FormItem>
                         </Col>
@@ -246,8 +286,8 @@ class DataConnectBox extends React.Component {
                                 labelCol: { span: 8 },
                                 wrapperCol: { span: 16 }
                             }}
-                            validateStatus={operation === 'create' ? ((dataConnect.newOne.password === undefined || dataConnect.newOne.password) ? 'success' : 'error') : 'success'}
-                            help={operation === 'create' ? ((passwordEditing || dataConnect.newOne.password === undefined || dataConnect.newOne.password) ? '' : '密码不能为空') : ''}
+                            validateStatus={validInfo.password.status}
+                            help={validInfo.password.help}
                             >
                                 <Input
                                     disabled={disabled}
@@ -255,20 +295,16 @@ class DataConnectBox extends React.Component {
                                     type='password'
                                     value={password}
                                     placeholder={operation === 'create' ? '' : '******'}
-                                    onFocus={e => {
-                                        this.setState({
-                                            passwordEditing: true
-                                        });
-                                    }}
                                     onChange={(e) => {
+                                        let val = e.target.value+'';
                                         this.setState({
-                                            password: e.target.value+''
+                                            password: val
                                         });
+                                        if(operation === 'create') {
+                                            this.valid('password', val, '密码', { required: true });
+                                        }
                                     }}
                                     onBlur={(e) => {
-                                        this.setState({
-                                            passwordEditing: false
-                                        });
                                         dispatch({ type: 'dataConnect/setNewModelField', name: 'password', value: e.target.value+'' });
                                     }}
                                 />
@@ -279,7 +315,12 @@ class DataConnectBox extends React.Component {
                                 <Button
                                     style={{ marginLeft: '10px' }}
                                     disabled={dataConnect.newOne.validating || dataConnect.newOne.saving}
-                                    onClick={() => dispatch({ type:'dataConnect/remoteValidate'})}
+                                    onClick={() => {
+                                        this.validAll();
+                                        if(this.checkValid()) {
+                                            dispatch({ type:'dataConnect/remoteValidate'})
+                                        }
+                                    }}
                                     className={`valid-btn ${dataConnect.newOne.invalid === undefined ? 'valid-default' : ( dataConnect.newOne.invalid ? 'valid-failure' : 'valid-success' )}`}
                                 >
                                     {dataConnect.newOne.validating ? (<Icon type='loading' />) : ( dataConnect.newOne.invalid === undefined ? <Icon type='question-circle' /> : ( dataConnect.newOne.invalid ? <Icon type="exclamation-circle" /> : <Icon type="check-circle" /> ) ) }

+ 0 - 1
src/components/dataSourceDetail/dataConnectConfig.jsx

@@ -160,7 +160,6 @@ class DataConnectConfig extends React.Component {
                                     let fileList = info.fileList;
                                     fileList = fileList.slice(-1); // 只保留最后一个
                                     if (info.file.status !== 'uploading') {
-                                        console.log(file, info.fileList);
                                         const trueType = file.type === 'application/vnd.ms-excel';
                                         const trueSize = file.size / 1024 / 1024 < 30;
                                         if(!trueType || !trueSize) {

+ 3 - 1
src/components/dataSourceDetail/header.jsx

@@ -18,7 +18,9 @@ class DataSourceDetailHeader extends React.Component {
     }
 
     handleVisibleSaveConfirmChange = (visible) => {
-        this.setState({ visibleSaveConfirm: visible });
+        if(this.isValid()) {
+            this.setState({ visibleSaveConfirm: visible });
+        }
     }
 
     isValid = () => {

+ 51 - 17
src/components/logs/logs.jsx

@@ -1,8 +1,10 @@
 import React from 'react'
-import { Layout, Row, Col, Table, Card } from 'antd'
+import { Layout, Row, Col, Table, Card, Button } from 'antd'
 import { connect } from 'dva'
 import './logs.less'
-import ListFilter from '../common/listFilter/index';
+import ListFilter from '../common/listFilter/index'
+import EllipsisTooltip from '../common/ellipsisTooltip/index'
+import CusIcon from '../common/cusIcon/index'
 const { Content } = Layout
 
 class Logs extends React.Component {
@@ -74,10 +76,14 @@ class Logs extends React.Component {
         return dataList;
     }
 
+    onPageChange = page => {
+        this.props.dispatch({ type: 'logs/setField', name: 'currentPage', value: page });
+    };
+
     render() {
-        const { logs } = this.props;
+        const { logs, dispatch } = this.props;
         const { pageSize, tableBodyHeight } = this.state;
-        const { filterItem, filterLabel } = logs;
+        const { filterItem, filterLabel, currentPage } = logs;
 
         let dataList = this.onSort(this.onSearch());
         let total = dataList.length;
@@ -105,17 +111,41 @@ class Logs extends React.Component {
             dataIndex: 'name',
             key: 'name',
             width: 200,
-            render: text => {
-                return (filterItem.name === 'name' && filterLabel) ?
-                ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
-                    return (
-                        fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
-                        <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
-                        fragment
-                    )
+            onCell: () => {
+                return {
+                    style: {
+                        whiteSpace: 'nowrap',
+                        maxWidth: 200,
+                    }
                 }
-                )) : text
+            },
+            render: text => {
+                return <EllipsisTooltip title={text}>{
+                    (filterItem.name === 'name' && filterLabel) ?
+                    ((text || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
+                        return (
+                            fragment.toLowerCase().replace(new RegExp('(\\\\)', 'g'), '\\$1').replace(reg, '\\$1') === filterLabel.toLowerCase() ?
+                            <span key={i} style={{fontWeight: 'bold', color: 'red'}} className="highlight">{fragment}</span> :
+                            fragment
+                        )
+                    }
+                    )) : text
+                }</EllipsisTooltip>
             }
+        }, {
+            title: '操作',
+            dataIndex: 'operation',
+            key: 'operation',
+            width: 200,
+            onCell: () => {
+                return {
+                    style: {
+                        whiteSpace: 'nowrap',
+                        maxWidth: 200,
+                    }
+                }
+            },
+            render: text => <EllipsisTooltip title={text}>{text}</EllipsisTooltip>
         }, {
             title: '操作人',
             dataIndex: 'operator',
@@ -143,8 +173,13 @@ class Logs extends React.Component {
             <Layout className='layout-logs'>
                 <Content>
                     <Card bordered={false} className='logs-body' title={
-                        <Row className='logs-tools' type='flex' justify='space-between'>
+                        <Row className='logs-tools' type='flex' justify='end'>
                             <Col className='search'>
+                                <Button className='btn-refresh' onClick={() => {
+                                    dispatch({ type: 'logs/fetchList', mandatory: true });
+                                }}>
+                                    <CusIcon type='bi-refresh'/>
+                                </Button>
                                 <ListFilter modelName='logs' model={logs} />
                             </Col>
                         </Row>
@@ -158,13 +193,12 @@ class Logs extends React.Component {
                             pagination={{
                                 pageSize,
                                 total,
+                                current: currentPage,
                                 // simple: true,
                                 showTotal: (total, range) => {
                                     return `第${range[0]}到第${range[1]}条数据,共${total}条数据`;
                                 },
-                                // onChange: (page, pageSize) => {
-                                //     typeof fetchFunction === 'function' && fetchFunction(page, pageSize);
-                                // }
+                                onChange: this.onPageChange
                             }}
                             scroll={{ x: false, y: tableBodyHeight }}
                         />

+ 13 - 0
src/components/logs/logs.less

@@ -18,6 +18,19 @@
                 >.ant-card-head-wrapper {
                     >.ant-card-head-title {
                         padding: 0;
+                        .search {
+                            display: flex;
+                            >div {
+                                margin-left: 8px;
+                            }
+                            .btn-refresh {
+                                border: none;
+                                font-size: 18px;
+                                &:after {
+                                    content: none;
+                                }
+                            }
+                        } 
                     }
                 }
             }

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

@@ -33,7 +33,7 @@ class Setting extends React.Component {
                 className='sider-setting'
             >
                 <Link to='/setting/admin'><div className={`link-btn${(paths[1] === 'admin' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={(paths[1] === 'admin' || !paths[1]) ? 'primary' : 'default'} >用户管理</Button></div></Link>
-                <Link to='/setting/authority'><div className={`link-btn${(paths[1] === 'authority' || !paths[1]) ? ' selected' : ''}`}><Button disabled className='ant-btn-block' type={paths[1] === 'authority' ? 'primary' : 'default'} >权限管理</Button></div></Link>
+                <Link to='/setting/authority'><div className={`link-btn${(paths[1] === 'authority' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={paths[1] === 'authority' ? 'primary' : 'default'} >权限管理</Button></div></Link>
                 <Link to='/setting/logs'><div className={`link-btn${(paths[1] === 'logs' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={paths[1] === 'logs' ? 'primary' : 'default'} >操作日志</Button></div></Link>
             </Sider>
             <Content className='content-setting'>

+ 19 - 1
src/constants/url.js

@@ -1,4 +1,6 @@
 // const BASE_URL = 'http://10.1.1.168:8081/BI/';
+// const BASE_URL = 'http://10.1.81.2:24000/BI_DEV/';
+// const BASE_URL = 'http://10.1.80.78:8097/BI_DEV/';
 const BASE_URL = ''
 
 /**后台接口地址 */
@@ -220,7 +222,23 @@ const URLS = {
 
     HOMEPAGE_RECENT_DASHBOARD_GET: BASE_URL + 'getDashRecord', //查询最近访问报表 //可能的错字
 
-    HOMEPAGE_ADD_RECENT_RECORD: BASE_URL + 'addRecord', //添加最近访问记录 
+    HOMEPAGE_ADD_RECENT_RECORD: BASE_URL + 'addRecord', //添加最近访问记录
+
+    /***************************************操作日志***************************************/
+
+    MESSAGELOG_LIST: BASE_URL + 'messageLog/list', // 获得操作日志列表
+
+    /***************************************权限设置***************************************/
+
+    ACCESS_DASHBOARD_TREE: BASE_URL + 'user/power/read', // 获得用户/用户组的权限报表目录
+
+    ACCESS_ADD: BASE_URL + 'user/power/save', // 为用户/用户组添加报表权限
+
+    ACCESS_ADD_ALL: BASE_URL + 'user/power/batchAdd', // 批量为用户/用户组添加报表权限
+
+    ACCESS_REMOVE: BASE_URL + 'user/power/delete', // 删除用户/用户组报表权限
+    
+    ACCESS_REMOVE_ALL: BASE_URL + 'user/power/batchDelete', // 批量删除用户/用户组报表权限
 }
 
 export default URLS

+ 115 - 7
src/models/authority.js

@@ -1,15 +1,18 @@
-// import { message } from 'antd'
-// import * as service from '../services/index'
-// import URLS from '../constants/url'
+import { message } from 'antd'
+import * as service from '../services/index'
+import URLS from '../constants/url'
 
 export default {
     namespace: 'authority',
     state: {
         originData: {
-            menuExpandedKeys: ['-1'],
+            tabActiveKey: 'userGroup',
             menuSelectedKeys: [],
-            menuFilterLabel: '',
-            menuAutoExpandParent: true,
+            groupFilterLabel: '',
+            userFilterLabel: '',
+            groupLimit: 30,
+            userLimit: 30,
+            dashboardList: [],
         },
     },
     reducers: {
@@ -30,7 +33,112 @@ export default {
         },
     },
     effects: {
-
+        *fetchDashboardTree(action, { put, call, select }) {
+            try{
+                const { dtype, code } = action;
+                const res = yield call(service.fetch, {
+                    url: URLS.ACCESS_DASHBOARD_TREE + '/' + dtype + '/' + code,
+                    method: 'GET'
+                })
+                if(!res.err && res.data.code > 0) {
+                    const list = res.data.data || [];
+                    const dashboardList = list.map(l => l.id + '');
+                    yield put({ type: 'setFields', fields: [
+                        { name: 'dashboardList', value: dashboardList },
+                    ] });
+                }else {
+                    message.error('获取报表目录失败: ' + (res.err || res.data.msg));
+                    return false;
+                }
+            }catch(e) {
+                message.error('获取报表目录失败: ' + e.message);
+                return false;
+            }
+        },
+        *add(action, { select, put, call }) {
+            try {
+                const { dtype, code, dashboardCode } = action;
+                const res = yield call(service.fetch, {
+                    url: URLS.ACCESS_ADD,
+                    method: 'POST',
+                    body: {
+                        bizId: code,
+                        dashboardId: dashboardCode,
+                        type: dtype
+                    }
+                });
+                if(!res.err && res.data.code > 0) {
+                    yield put({ type: 'fetchDashboardTree', dtype, code });
+                }else {
+                    message.error('设置权限失败: ' + (res.err || res.data.msg));
+                }
+            }catch(e) {
+                message.error('设置权限失败: ' + e.message);
+            }
+        },
+        *addAll(action, { select, put, call }) {
+            try {
+                const { dtype, code, dashboardCodes } = action;
+                const res = yield call(service.fetch, {
+                    url: URLS.ACCESS_ADD_ALL,
+                    method: 'POST',
+                    body: {
+                        bizId: code,
+                        dashboardIds: dashboardCodes.join(','),
+                        type: dtype
+                    }
+                });
+                if(!res.err && res.data.code > 0) {
+                    yield put({ type: 'fetchDashboardTree', dtype, code });
+                }else {
+                    message.error('设置权限失败: ' + (res.err || res.data.msg));
+                }
+            }catch(e) {
+                message.error('设置权限失败: ' + e.message);
+            }
+        },
+        *remove(action, { select, put, call }) {
+            try {
+                const { dtype, code, dashboardCode } = action;
+                const res = yield call(service.fetch, {
+                    url: URLS.ACCESS_REMOVE,
+                    method: 'POST',
+                    body: {
+                        bizId: code,
+                        dashboardId: dashboardCode,
+                        type: dtype
+                    }
+                });
+                if(!res.err && res.data.code > 0) {
+                    yield put({ type: 'fetchDashboardTree', dtype, code });
+                }else {
+                    message.error('设置权限失败: ' + (res.err || res.data.msg));
+                }
+            }catch(e) {
+                message.error('设置权限失败: ' + e.message);
+            }
+        },
+        *removeAll(action, { select, put, call }) {
+            try {
+                const { dtype, code, dashboardCodes } = action;
+                const res = yield call(service.fetch, {
+                    url: URLS.ACCESS_REMOVE_ALL,
+                    method: 'POST',
+                    body: {
+                        bizId: code,
+                        dashboardIds: dashboardCodes.join(','),
+                        type: dtype
+                    }
+                });
+                if(!res.err && res.data.code > 0) {
+                    yield put({ type: 'fetchDashboardTree', dtype, code });
+                }else {
+                    message.error('设置权限失败: ' + (res.err || res.data.msg));
+                }
+            }catch(e) {
+                message.error('设置权限失败: ' + e.message);
+            }
+        }
     },
     subscriptions: {
         setup({ dispatch, history }) {

+ 0 - 31
src/models/chart.js

@@ -344,7 +344,6 @@ export default {
                     url: URLS.CHART_ADD,
                     body: body
                 })
-                console.log('新增图表', body, res);
                 if(!res.err && res.data.code > 0) {
                     message.success('新增成功');
                     yield put({ type: 'fetchList', mandatory: true });
@@ -416,7 +415,6 @@ export default {
                     url: URLS.CHART_DELETE,
                     body: code
                 });
-                console.log('删除图表', code, res);
                 if(!res.err && res.data.code > 0) {
                     for(let i = 0; i < list.length; i++) {
                         if(list[i].code === code) {
@@ -430,7 +428,6 @@ export default {
                     message.error('删除失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('删除失败: ' + e.message);
             }
         },
@@ -553,14 +550,12 @@ export default {
                     url: URLS.GROUP_CHART_UPDATE,
                     body: body
                 });
-                console.log('修改图表分组', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'setGroupDirty', dirty: false });
                 }else {
                     message.error('修改分组失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('修改分组失败: ' + e.message);
             }
         },
@@ -583,14 +578,12 @@ export default {
                     url: URLS.GROUP_CHART_LIST_UPDATE,
                     body: body
                 });
-                console.log('批量修改图表分组', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'modifyGroups', groups: groups });
                 }else {
                     message.error('修改分组失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('修改分组失败: ' + e.message);
             }
         },
@@ -633,14 +626,11 @@ export default {
 
                 let modifyGroups = [];
                 if((dragGroup.pcode === '-1' || dropGroup.pcode === '-1') && (dragGroup.pcode !== dropGroup.pcode)) { // 跨级
-                    console.log('跨级');
                     if(dropGroup.pcode !== '-1') { // 从父级到子级
-                        console.log('error');
                         return; // 不允许
                     }else { // 从子级到父级
                         if(dragGroup.pcode === dropGroup.code) { // 不跨组
                             if(dropPosition === -1) { // 目标前
-                                console.log('before');
                                 let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                 let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                 dragGroups.splice(dragGroup.index, 1);
@@ -653,10 +643,8 @@ export default {
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                             }else if(dropPosition === 0) { // 目标内
-                                console.log('nothing');
                                 return; // 无变化
                             }else if(dropPosition === 1) { // 目标后
-                                console.log('after');
                                 let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                 let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                 dragGroups.splice(dragGroup.index, 1);
@@ -679,14 +667,12 @@ export default {
                                 return { ...g, index: i }
                             });
                             if(dropPosition === -1) { // 目标前
-                                console.log('before');
                                 dropGroups.splice(dropGroup.index, 0, dragGroup);
                                 dropGroups = dropGroups.map((g, i) => {
                                     return { ...g, index: i, pcode: dropGroup.pcode }
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                             }else if(dropPosition === 0) { // 目标内
-                                console.log('in');
                                 dropChildrenGroups.push({
                                     ...dragGroup,
                                     index: dropChildrenGroups.length,
@@ -694,7 +680,6 @@ export default {
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropChildrenGroups);
                             }else if(dropPosition === 1) { // 目标后
-                                console.log('after');
                                 dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
                                 dropGroups = dropGroups.map((g, i) => {
                                     return { ...g, index: i, pcode: dropGroup.pcode }
@@ -704,23 +689,18 @@ export default {
                         }
                     }
                 }else { // 不跨级
-                    console.log('不跨级');
                     if(dragGroup.pcode === dropGroup.pcode) { // 不跨组
-                        console.log('不跨组');
                         let dGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                         dGroups.splice(dragGroup.index, 1, {code: 'temp', index: dragGroup.index});
                         if(dropPosition === -1) { // 目标前
-                            console.log('before');
                             dGroups.splice(dropGroup.index, 0, dragGroup);
                             dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                 return { ...g, index: i }
                             });
                             modifyGroups = modifyGroups.concat(dGroups);
                         }else if(dropPosition === 0) { // 目标内
-                            console.log('in');
                             return;
                         }else if(dropPosition === 1) { // 目标后
-                            console.log('after');
                             dGroups.splice(dropGroup.index + 1, 0, dragGroup);
                             dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                 return { ...g, index: i }
@@ -728,7 +708,6 @@ export default {
                             modifyGroups = modifyGroups.concat(dGroups);
                         }
                     }else { // 跨组
-                        console.log('跨组');
                         let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                         let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                         
@@ -739,17 +718,14 @@ export default {
                         for(let i = 0; i < dropGroups.length; i++) {
                             if(dropGroups[i].code === dropGroup.code) {
                                 if(dropPosition === -1) { // 目标前
-                                    console.log('before');
                                     dropGroups.splice(i, 0, dragGroup);
                                     dropGroups = dropGroups.map((g, i) => {
                                         return { ...g, index: i, pcode: dropGroup.pcode }
                                     });
                                     modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                                 }else if(dropPosition === 0) { // 目标内
-                                    console.log('in');
                                     return; // 不允许
                                 }else if(dropPosition === 1) { // 目标后
-                                    console.log('after');
                                     dropGroups.splice(i + 1, 0, dragGroup);
                                     dropGroups = dropGroups.map((g, i) => {
                                         return { ...g, index: i, pcode: dropGroup.pcode }
@@ -761,10 +737,8 @@ export default {
                         }
                     }
                 }
-                console.log(dragGroup, dropGroup, modifyGroups);
                 yield put({ type: 'remoteModifyGroups', groups: modifyGroups });
             }catch(e) {
-                console.log(e);
                 message.error('位置调整失败: ' + e.message);
             }
         },
@@ -784,14 +758,12 @@ export default {
                     url: URLS.GROUP_CHART_SET_GROUP,
                     body: body
                 });
-                console.log('设置图表所属分组', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'setChartGroup', chartCode, groupCode });
                 }else {
                     message.error('设置分组失败: ' + (res.err || res.data.msg));
                 }
             } catch(e) {
-                console.log(e);
                 message.error('设置分组失败: ' + e.message);
             }
         },
@@ -806,7 +778,6 @@ export default {
                     url: URLS.CHART_TRANSFER,
                     body
                 });
-                console.log('图表移交', body, res);
                 if(!res.err && res.data.code > 0) {
                     const chart = yield select(state => state.present.chart);
                     const list = chart.list;
@@ -819,11 +790,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.message);
             }
         },

+ 0 - 12
src/models/chartPolicy.js

@@ -102,7 +102,6 @@ export default {
                     url: URLS.CHART_POLICY_LIST,
                     body
                 });
-                console.log('请求图表策略列表', body, res);
                 if(!res.err && res.data.code > 0) {
                     let list = (res.data.data && res.data.data.length > 0) ? res.data.data.sort((a, b) => new Date(a.createDate) - new Date(b.createDate)).map(d => ({
                         code: d.strategies.id,
@@ -124,7 +123,6 @@ export default {
                     message.error('请求图表策略列表失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('读取图表策略列表错误: ' + e.message);
             }
         },
@@ -143,7 +141,6 @@ export default {
                     url: URLS.CHART_POLICY_ADD,
                     body,
                 });
-                console.log('添加策略', body, res);
                 if(!res.err && res.data.code > 0) {
                     let { list } = chartPolicy;
                     list.push({
@@ -155,7 +152,6 @@ export default {
                     message.error('添加失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('添加失败: ' + e.message);
             }
         },
@@ -174,14 +170,12 @@ export default {
                     url: URLS.CHART_POLICY_UPDATE,
                     body
                 });
-                console.log('修改图表策略', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'modify', policy });
                 }else {
                     message.error('修改失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('修改失败: ' + e.message);
             }
         },
@@ -194,7 +188,6 @@ export default {
                     url: URLS.CHART_POLICY_DELETE,
                     body
                 });
-                console.log('删除策略', body, res);
                 if(!res.err && res.data.code > 0) {
                     let { list } = chartPolicy;
                     for(let i = 0; i < list.length; i++) {
@@ -208,7 +201,6 @@ export default {
                     message.error('删除失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('删除失败: ' + e.message);
             }
         },
@@ -227,7 +219,6 @@ export default {
                     url: URLS.CHART_POLICY_TARGET_UPDATE,
                     body
                 });
-                console.log('设置策略对象', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'modify', policy: {
                         ...policy,
@@ -237,7 +228,6 @@ export default {
                     message.error('设置对象失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('设置对象失败: ' + e.message);
             }
         },
@@ -251,7 +241,6 @@ export default {
                     url: URLS.CHART_QUERY_DATACOLUMNS,
                     body
                 });
-                console.log('获得图表列数据', body, res);
                 if(!res.err && res.data.code > 0) {
                     let columnData = res.data.data.map(d => ({
                         name: d.columnName,
@@ -263,7 +252,6 @@ export default {
                     message.error('获得图表列数据失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('获得图表列数据失败: ' + e.message);
             }
         }

+ 2 - 1
src/models/dashboard.js

@@ -299,7 +299,7 @@ export default {
         *remoteMenuTree(action, { put, call, select }) {
             const dashboard = yield select(state => state.present.dashboard);
             if(!action.mandatory && dashboard.menuTree.length > 0) {
-                return;
+                return {menuList: dashboard.menuList, menuTree: dashboard.menuTree};
             }
             try{
                 const res = yield call(service.fetch, {
@@ -316,6 +316,7 @@ export default {
                                 ch = fun(t.children, t.id);
                             }
                             let obj = {
+                                key: t.id + '-' + i,
                                 code: t.id + '',
                                 pcode: pcode + '',
                                 name: t.name,

+ 0 - 3
src/models/dashboardDesigner.js

@@ -355,7 +355,6 @@ export default {
                     url: URLS.DATASOURCE_QUERY_DATACOLUMNS,
                     body: body
                 });
-                console.log('获得列数据', body, res);
                 if(!res.err && res.data.code > 0) {
                     let resData = res.data.data;
                     
@@ -379,7 +378,6 @@ export default {
                     yield put({ type: 'silentSetField', name: 'dataSources', value: [] });
                 }
             }catch(e) {
-                console.log(e, body);
                 message.error('请求列数据失败: ' + e.message);
             }
         },
@@ -505,7 +503,6 @@ export default {
                 yield put({ type: 'dashboard/remoteModify' });
                 yield put({ type: 'silentSetField', name: 'loading', value: false });
             }catch(e) {
-                console.log(e);
                 message.error('生成缩略图失败: ' + e.message);
             }
         },

+ 2 - 28
src/models/dataSource.js

@@ -177,7 +177,7 @@ export default {
                 if(!res.err && res.data.code > 0) {
                     let list = res.data.data.list.map((r, i) => {
                         let dbConfig = {
-                            code: r.dbConfig.id,
+                            code: r.dbConfig.id + '',
                             name: r.dbConfig.name,
                             dbName: r.dbConfig.dataName,
                             dbType: r.dbConfig.databaseType,
@@ -245,7 +245,6 @@ export default {
                     url: URLS.DATASOURCE_ADD,
                     body: data
                 });
-                console.log('新增数据源', data, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'fetchList', mandatory: true });
                     yield put({ type: 'main/redirect', path: { pathname: '/workshop/datasource' } });
@@ -278,7 +277,7 @@ export default {
                         code: resData.dataId + '',
                         name: resData.dataName,
                         type: resData.type,
-                        connectCode: dbConfig.id,
+                        connectCode: dbConfig.id + '',
                         dbType: dbConfig.databaseType,
                         dbName: dbConfig.dataName,
                         address: dbConfig.addrass,
@@ -346,7 +345,6 @@ export default {
                     message.error('删除失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('删除失败: ' + e.message);
             }
         },
@@ -384,7 +382,6 @@ export default {
                     url: URLS.DATASOURCE_UPDATE,
                     body: data
                 });
-                console.log('修改数据源', data, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'fetchList', mandatory: true });
                     message.success('保存成功');
@@ -393,7 +390,6 @@ export default {
     
                 }
             }catch(e) {
-                console.log(e);
                 message.error('保存失败: ' + e.message);
             }
         },
@@ -589,14 +585,11 @@ export default {
 
                 let modifyGroups = [];
                 if((dragGroup.pcode === '-1' || dropGroup.pcode === '-1') && (dragGroup.pcode !== dropGroup.pcode)) { // 跨级
-                    console.log('跨级');
                     if(dropGroup.pcode !== '-1') { // 从父级到子级
-                        console.log('error');
                         return; // 不允许
                     }else { // 从子级到父级
                         if(dragGroup.pcode === dropGroup.code) { // 不跨组
                             if(dropPosition === -1) { // 目标前
-                                console.log('before');
                                 let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                 let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                 dragGroups.splice(dragGroup.index, 1);
@@ -609,10 +602,8 @@ export default {
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                             }else if(dropPosition === 0) { // 目标内
-                                console.log('nothing');
                                 return; // 无变化
                             }else if(dropPosition === 1) { // 目标后
-                                console.log('after');
                                 let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                                 let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                                 dragGroups.splice(dragGroup.index, 1);
@@ -635,14 +626,12 @@ export default {
                                 return { ...g, index: i }
                             });
                             if(dropPosition === -1) { // 目标前
-                                console.log('before');
                                 dropGroups.splice(dropGroup.index, 0, dragGroup);
                                 dropGroups = dropGroups.map((g, i) => {
                                     return { ...g, index: i, pcode: dropGroup.pcode }
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                             }else if(dropPosition === 0) { // 目标内
-                                console.log('in');
                                 dropChildrenGroups.push({
                                     ...dragGroup,
                                     index: dropChildrenGroups.length,
@@ -650,7 +639,6 @@ export default {
                                 });
                                 modifyGroups = modifyGroups.concat(dragGroups, dropChildrenGroups);
                             }else if(dropPosition === 1) { // 目标后
-                                console.log('after');
                                 dropGroups.splice(dropGroup.index + 1, 0, dragGroup);
                                 dropGroups = dropGroups.map((g, i) => {
                                     return { ...g, index: i, pcode: dropGroup.pcode }
@@ -660,23 +648,18 @@ export default {
                         }
                     }
                 }else { // 不跨级
-                    console.log('不跨级');
                     if(dragGroup.pcode === dropGroup.pcode) { // 不跨组
-                        console.log('不跨组');
                         let dGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                         dGroups.splice(dragGroup.index, 1, {code: 'temp', index: dragGroup.index});
                         if(dropPosition === -1) { // 目标前
-                            console.log('before');
                             dGroups.splice(dropGroup.index, 0, dragGroup);
                             dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                 return { ...g, index: i }
                             });
                             modifyGroups = modifyGroups.concat(dGroups);
                         }else if(dropPosition === 0) { // 目标内
-                            console.log('in');
                             return;
                         }else if(dropPosition === 1) { // 目标后
-                            console.log('after');
                             dGroups.splice(dropGroup.index + 1, 0, dragGroup);
                             dGroups = dGroups.filter(g => g.code !== 'temp').map((g, i) => {
                                 return { ...g, index: i }
@@ -684,7 +667,6 @@ export default {
                             modifyGroups = modifyGroups.concat(dGroups);
                         }
                     }else { // 跨组
-                        console.log('跨组');
                         let dragGroups = group.filter(g => g.pcode === dragGroup.pcode).sort((a, b) => a.index - b.index);
                         let dropGroups = group.filter(g => g.pcode === dropGroup.pcode).sort((a, b) => a.index - b.index);
                         
@@ -695,17 +677,14 @@ export default {
                         for(let i = 0; i < dropGroups.length; i++) {
                             if(dropGroups[i].code === dropGroup.code) {
                                 if(dropPosition === -1) { // 目标前
-                                    console.log('before');
                                     dropGroups.splice(i, 0, dragGroup);
                                     dropGroups = dropGroups.map((g, i) => {
                                         return { ...g, index: i, pcode: dropGroup.pcode }
                                     });
                                     modifyGroups = modifyGroups.concat(dragGroups, dropGroups);
                                 }else if(dropPosition === 0) { // 目标内
-                                    console.log('in');
                                     return; // 不允许
                                 }else if(dropPosition === 1) { // 目标后
-                                    console.log('after');
                                     dropGroups.splice(i + 1, 0, dragGroup);
                                     dropGroups = dropGroups.map((g, i) => {
                                         return { ...g, index: i, pcode: dropGroup.pcode }
@@ -717,10 +696,8 @@ export default {
                         }
                     }
                 }
-                console.log(dragGroup, dropGroup, modifyGroups);
                 yield put({ type: 'remoteModifyGroups', groups: modifyGroups });
             }catch(e) {
-                console.log(e);
                 message.error('位置调整失败: ' + e.message);
             }
         },
@@ -761,7 +738,6 @@ export default {
                     url: URLS.DATASOURCE_TRANSFER,
                     body
                 });
-                console.log('数据源移交', body, res);
                 if(!res.err && res.data.code > 0) {
                     const dataSource = yield select(state => state.present.dataSource);
                     const list = dataSource.list;
@@ -775,11 +751,9 @@ export default {
                     yield put({ type: 'chart/fetchList', mandatory: true });
                     message.success('移交成功');
                 }else {
-                    console.log(body, (res.err || res.data.msg));
                     message.error('移交失败');
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('移交失败: ' + e.message);
             }
         },

+ 0 - 8
src/models/dataSourcePolicy.js

@@ -92,7 +92,6 @@ export default {
                     url: URLS.DATASOURCE_POLICY_LIST,
                     body
                 });
-                console.log('请求数据源策略列表', body, res);
                 if(!res.err && res.data.code > 0) {
                     let list = (res.data.data && res.data.data.length > 0) ? res.data.data.sort((a, b) => new Date(a.createDate) - new Date(b.createDate)).map(d => ({
                         code: d.strategies.id,
@@ -114,7 +113,6 @@ export default {
                     message.error('请求数据源策略列表失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('读取数据源策略列表错误: ' + e.message);
             }
         },
@@ -134,7 +132,6 @@ export default {
                     url: URLS.DATASOURCE_POLICY_ADD,
                     body,
                 });
-                console.log('添加策略', body, res);
                 if(!res.err && res.data.code > 0) {
                     let { list } = dataSourcePolicy;
                     list.push({
@@ -146,7 +143,6 @@ export default {
                     message.error('添加失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('添加失败: ' + e.message);
             }
         },
@@ -166,14 +162,12 @@ export default {
                     url: URLS.DATASOURCE_POLICY_UPDATE,
                     body
                 });
-                console.log('修改数据源策略', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'modify', policy });
                 }else {
                     message.error('修改失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('修改失败: ' + e.message);
             }
         },
@@ -217,7 +211,6 @@ export default {
                     url: URLS.DATASOURCE_POLICY_TARGET_UPDATE,
                     body
                 });
-                console.log('设置策略对象', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'modify', policy: {
                         ...policy,
@@ -227,7 +220,6 @@ export default {
                     message.error('设置对象失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('设置对象失败: ' + e.message);
             }
         }

+ 0 - 3
src/models/home.js

@@ -83,7 +83,6 @@ export default {
 
             yield put({ type: 'setSelectedTab', tab });
             let fTab = tabs.find(t => t.code === tab.code);
-            console.log(fTab);
             if(!fTab) {
                 return false;
             }else {
@@ -136,7 +135,6 @@ export default {
                 const home = yield select(state => state.present.home);
                 const { collectionDashboards } = home;
                 const { mandatory } = action;
-                console.log(collectionDashboards);
                 if(collectionDashboards.length > 0 && !mandatory) {
                     return;
                 }
@@ -149,7 +147,6 @@ export default {
                         code: d.ID + '',
                         name: d.NAME
                     }));
-                    console.log(list);
                     yield put({ type: 'setField', name: 'collectionDashboards', value: list });
                 }else {
                     message.error('获取收藏列表失败: ' + (res.err || res.data.msg));

+ 17 - 5
src/models/logs.js

@@ -15,15 +15,27 @@ export default {
                     { name: '数据源', label: '数据源' },
                     { name: '图表', label: '图表' },
                     { name: '报表', label: '报表' },
-                    { name: '数据源分组', label: '数据源分组' },
-                    { name: '图表分组', label: '图表分组' },
+                    // { name: '数据源分组', label: '数据源分组' },
+                    // { name: '图表分组', label: '图表分组' },
+                    { name: '权限管理', label: '权限管理' },
+                    { name: '用户管理', label: '用户管理' },
                 ] },
                 { name: 'name', label: '名称', type: 'string' },
                 { name: 'operator', label: '操作人', type: 'string' },
                 { name: 'date', label: '操作时间', type: 'date' },
             ], // 可选过滤字段
-            filterItem: { name: 'name', label: '名称', type: 'string' }, // 已选过滤字段
+            filterItem: { name: 'module', label: '模块', type: 'enum', options: [
+                { name: '数据链接', label: '数据链接' },
+                { name: '数据源', label: '数据源' },
+                { name: '图表', label: '图表' },
+                { name: '报表', label: '报表' },
+                // { name: '数据源分组', label: '数据源分组' },
+                // { name: '图表分组', label: '图表分组' },
+                { name: '权限管理', label: '权限管理' },
+                { name: '用户管理', label: '用户管理' },
+            ] }, // 已选过滤字段
             listScrollTop: 0, // 记录列表界面滚动条位置
+            currentPage: 1, // 记录分页器当前所在页数
         },
     },
     reducers: {
@@ -45,7 +57,7 @@ export default {
         },
         setFilterLabel(state, action) {
             const { label } = action;
-            return Object.assign({}, state, {filterLabel: label});
+            return Object.assign({}, state, {filterLabel: label, currentPage: 1});
         },
         reset(state, action) {
             return Object.assign({}, state, state.originData);
@@ -74,7 +86,7 @@ export default {
                         return {
                             code: d.id + '',
                             date: d.date,
-                            content: d.content,
+                            operation: d.content,
                             module: d.module,
                             name: d.order,
                             result: d.result,

+ 0 - 1
src/models/main.js

@@ -185,7 +185,6 @@ export default {
                 yield put({ type: 'recent/reset' });
                 yield put({ type: 'reset' });
             }catch(e) {
-                console.log(e);
                 message.error('注销失败: ' + e.message);
             }
         },

+ 0 - 2
src/models/parseChartOption.js

@@ -112,7 +112,6 @@ function barOption(data, barConfig) {
 function pieOption(data, pieConfig) {
     let columnName = pieConfig.xAxis.column.label + (pieConfig.xAxis.granularity.value ? '('+pieConfig.xAxis.granularity.label+')' : '');
       
-    console.log(pieConfig);
     let option = {
         tooltip : {
             trigger: 'item',
@@ -146,7 +145,6 @@ function pieOption(data, pieConfig) {
         ]
     };
 
-    console.log(option);
     return option;
 }
 

+ 0 - 7
src/models/recent.js

@@ -32,16 +32,10 @@ export default {
     effects: {
         *fetchRecentChart(action, { select, call, put }) {
             try {
-                // const recent = yield select(state => state.present.recent);
-                // if(!action.mandatory && recent.recentChart.length > 0) {
-                //     return;
-                // }
                 const res = yield call(service.fetch, {
                     url: URLS.HOMEPAGE_RECENT_CHART_GET,
                 });
                 
-                console.log('请求最近访问图表', res);
-                
                 if(!res.err && res.data.code > 0) {
                     let recentChart = res.data.data.map((r, i) => {
                         return {
@@ -74,7 +68,6 @@ export default {
                 const res = yield call(service.fetch, {
                     url: URLS.HOMEPAGE_RECENT_DASHBOARD_GET,
                 });
-                console.log('请求最近访问报表', res);
                 if(!res.err && res.data.code > 0) {
                     let recentDashboard = res.data.data.map((r, i) => {
                         return {

+ 0 - 12
src/models/userGroup.js

@@ -108,7 +108,6 @@ export default {
                 const res = yield call(service.fetch, {
                     url: URLS.USERGROUP_LIST,
                 });
-                console.log('请求用户组列表', res);
                 if(!res.err && res.data.code > 0) {
                     const list = res.data.data.map(d => ({
                         code: d.id + '',
@@ -120,11 +119,9 @@ export default {
                     yield put({ type: 'list', list: list.sort((a, b) => a.createTime - b.createTime) });
                     yield autoSelect && put({ type: 'changeSelectedGroup', group: list[0] });
                 }else {
-                    console.log(res.err || res.data.msg);
                     message.error('请求用户组列表失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('请求用户组列表失败: ' + e.message);
             }
         },
@@ -154,7 +151,6 @@ export default {
                     message.error('新增失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(e);
                 message.error('新增失败: ' + e.message);
             }
         },
@@ -179,7 +175,6 @@ export default {
                     message.error('修改失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('修改失败: ' + e.message);
             }
         },
@@ -200,7 +195,6 @@ export default {
                     message.error('删除失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log([group.code], e);
                 message.error('删除失败: ' + e.message);
             }
         },
@@ -228,7 +222,6 @@ export default {
                     url: URLS.USERGROUP_MEMBER_LIST,
                     body: groupCode
                 });
-                console.log('请求用户组成员列表', groupCode, res);
                 if(!res.err && res.data.code > 0) {
                     const memberList = res.data.data.map(d => ({
                         code: d.id + '',
@@ -240,7 +233,6 @@ export default {
                     message.error('请求用户组成员列表失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(groupCode, e);
                 message.error('请求用户组成员列表失败: ' + e.message);
             }
         },
@@ -255,7 +247,6 @@ export default {
                     url: URLS.USERGROUP_MEMBER_ADD,
                     body
                 });
-                console.log('添加用户组成员', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'remoteMemberList', groupCode: group.code, mandatory: true });
                     yield put({ type: 'setNewModelField', name: 'visibleAddMemberBox', value: false });
@@ -263,7 +254,6 @@ export default {
                     message.error('添加失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('添加失败: ' + e.message);
             }
         },
@@ -278,14 +268,12 @@ export default {
                     url: URLS.USERGROUP_MEMBER_DELETE,
                     body
                 });
-                console.log('删除用户组成员', body, res);
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'remoteMemberList', groupCode, mandatory: true });
                 }else {
                     message.error('删除失败: ' + (res.err || res.data.msg));
                 }
             }catch(e) {
-                console.log(body, e);
                 message.error('删除失败: ' + e.message);
             }
         },

+ 11 - 4
src/themes/default/base.less

@@ -79,6 +79,7 @@
 .ant-modal-header {
     display: table;
     width: 100%;
+    padding: 42px 24px 0;
     border-bottom: none;
     &:before, &:after {
         content: "";
@@ -92,10 +93,16 @@
         text-align: center;
     }
 }
-.ant-modal-close-x {
-    height: 24px;
-    width: 24px;
-    line-height: 24px;
+.ant-modal-close {
+    position: absolute;
+    top: 8px;
+    right: 8px;
+    .ant-modal-close-x {
+        height: 32px;
+        width: 32px;
+        line-height: 32px;
+        font-size: 18px;
+    }
 }
 
 

+ 7 - 1
src/utils/request.js

@@ -5,7 +5,10 @@ function parseJSON(response) {
 }
 
 function checkStatus(response) {
-  if (response && (response.status >= 200 && response.status < 300)) {
+  if(!response) {
+    throw new Error('无法访问服务器');
+  }
+  if (response.status >= 200 && response.status < 300) {
     return response;
   }
 
@@ -15,6 +18,9 @@ function checkStatus(response) {
   if (response.status === 404) {
     throw new Error('请求未找到');
   }
+  if (response.status === 405) {
+    throw new Error('无法访问服务器');
+  }
 }
 
 /**