Browse Source

列表界面样式调整

zhuth 6 years ago
parent
commit
467270bc81

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

@@ -60,11 +60,11 @@ class ChartList extends React.Component {
         const pWidth = parent.offsetWidth; // 父级容器宽度
         const pPadding = 10 + 10; // 父级容器左右padding
         const cWidth = 207; // 每个卡片宽度
-        const cMargin = 5 + 5; // 每个卡片左右margin
+        const cMargin = 8 + 8; // 每个卡片左右margin
         const pTrueWidth = pWidth - pPadding; // 父容器实际可用宽度
         const cTrueWidth = cWidth + cMargin; // 卡片实际占用宽度
-        const count = Math.floor(pTrueWidth/cTrueWidth); // 每行最大卡片数量
-        const cardBodyWidth = count * cTrueWidth;
+        const count = Math.ceil(pTrueWidth/cTrueWidth); // 每行最大卡片数量
+        const cardBodyWidth = (count - 1) * cTrueWidth; // 考虑到滚动条,减少一个
 
         cardBodyWidth > 0 ? cardBody.style.width = cardBodyWidth + 'px' : void(0);
     }
@@ -212,7 +212,7 @@ class ChartList extends React.Component {
                 <Card
                     title={
                         <Row type='flex' justify='space-between'>
-                            <Col span={21} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} >
+                            <Col className='label' span={21} style={{ overflow: 'hidden', textOverflow: 'ellipsis' }} >
                                 { (filterItem.name === 'name' && filterLabel) ?
                                     ((l.name || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {
                                         return (
@@ -298,7 +298,7 @@ class ChartList extends React.Component {
             if(t.children && t.children.length > 0) {
                 return <Menu.SubMenu
                     key={t.code}
-                    title={selectedRecord.groupCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.label}</span> : t.label}
+                    title={selectedRecord.groupCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.label}</span> : t.label}
                     onTitleClick={() => {
                         dispatch({ type: 'chart/remoteSetGroup', chart: selectedRecord, group: t });
                         dispatch({ type: 'chart/setCurrentGroup', group: t });
@@ -310,7 +310,7 @@ class ChartList extends React.Component {
                 return <Menu.Item key={t.code} onClick={() => {
                     dispatch({ type: 'chart/remoteSetGroup', chart: selectedRecord, group: t });
                     dispatch({ type: 'chart/setCurrentGroup', group: t });
-                }}>{selectedRecord.groupCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.label}</span> : t.label}</Menu.Item>
+                }}>{selectedRecord.groupCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.label}</span> : t.label}</Menu.Item>
             }
         })
     }
@@ -339,7 +339,7 @@ class ChartList extends React.Component {
         const { dispatch, chart } = this.props;
         const { visibleChooseDataSourceBox, visibleDistributeBox, visibleGroupManageMentBox, visibleTransferBox, visibleDeleteBox, selectedRecord, noGroup } = this.state;
         return (
-            <Layout className='chart-list'>
+            <Layout className='layout-chart'>
                 <Content>
                     <Card title={
                         <Row className='tools' type='flex' justify='space-between'>

+ 5 - 5
src/components/chart/list.less

@@ -1,4 +1,4 @@
-.chart-list {
+.layout-chart {
     &>.ant-layout-content {
         &>.ant-card {
             height: 100%;
@@ -56,15 +56,15 @@
                     .chart-card {
                         width: 207px;
                         text-align: center;
-                        margin: 5px;
+                        margin: 8px;
                         padding: 0;
                         &>.ant-card {
-                            border: 2px solid #CCCCCC;
+                            // border: 2px solid @border-color-base;
                             &>.ant-card-head {
-                                border-bottom: 2px solid #CCCCCC;
+                                // border-bottom: 2px solid @border-color-base;
                                 min-height: 20px;
                                 cursor: default;
-                                padding: 0 10px;
+                                padding: 0;
                                 &>.ant-card-head-wrapper {
                                     &>.ant-card-head-title {
                                         font-size: 14px;

+ 2 - 2
src/components/common/listFilter/index.less

@@ -2,10 +2,10 @@
     .ant-select:first-child {
         .ant-select-selection.ant-select-selection--single {
             border-right: none;
-            border-radius: 4px 0 0 4px;
+            border-radius: @border-radius-base 0 0 @border-radius-base;
         }
     }
     .ant-select:last-child .ant-select-selection.ant-select-selection--single, .ant-input-search.ant-input-affix-wrapper>input, .ant-calendar-picker-input.ant-input {
-        border-radius: 0 4px 4px 0;
+        border-radius: 0 @border-radius-base @border-radius-base 0;
     }
 }

+ 2 - 1
src/components/common/navigator.jsx

@@ -43,7 +43,8 @@ class Navigator extends React.Component {
 
         return <div className='navigator'>
             <div className='navigator-left'>
-                <img src='../../../static/images/uas.png' alt='LOGO'/>
+                {/* <img src='../../../static/images/uas.png' alt='LOGO'/> */}
+                <div className='logo'></div>
             </div>
             <div className='navigator-content'>
                 {currentUser.role === 'admin' && <Menu

+ 10 - 0
src/components/common/navigator.less

@@ -3,6 +3,16 @@
     justify-content: space-between;
     height: 100%;
     padding: 0 24px;
+    .navigator-left {
+        .logo {
+            height: 100%;
+            width: 84px;
+            margin-top: 3px;
+            background-image: url(../../../static/images/uas.png);
+            background-repeat: no-repeat;
+            background-position: center;
+        }
+    }
     .navigator-menu {
         border-bottom: none;
         .nav-page {

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

@@ -134,7 +134,7 @@ class DashboardList extends React.Component {
             if(t.children && t.children.length > 0) {
                 return <Menu.SubMenu
                     key={t.code}
-                    title={selectedRecord.menuCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.name}</span> : t.name}
+                    title={selectedRecord.menuCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.name}</span> : t.name}
                     onTitleClick={() => {
                         dispatch({ type: 'dashboard/remoteSetMenu', dashboard: selectedRecord, menu: t });
                         let obj = {selectedRecord: null};
@@ -150,7 +150,7 @@ class DashboardList extends React.Component {
                     let obj = {selectedRecord: null};
                     obj['visibleOperatingMenu' + selectedRecord.code] = false;
                     this.setState(obj);
-                }}>{selectedRecord.menuCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.name}</span> : t.name}</Menu.Item>
+                }}>{selectedRecord.menuCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.name}</span> : t.name}</Menu.Item>
             }
         })
     }

+ 1 - 1
src/components/dashboard/list.less

@@ -67,7 +67,7 @@
                         }
                     }
                     .ant-table-body {
-                        margin-top: 17px;
+                        margin-top: 10px;
                         overflow-y: auto !important;
                         table {
                             padding: 0;

+ 47 - 32
src/components/dataConnect/list.jsx

@@ -1,5 +1,5 @@
 import React from 'react'
-import { Layout, Row, Col, Button, Icon, Card, Tooltip, Select } from 'antd'
+import { Layout, Row, Col, Button, Icon, Card, Tooltip, Select, Menu, Dropdown } from 'antd'
 import { connect } from 'dva'
 import DeleteBox from '../common/deleteBox/deleteBox'
 import EmptyContent from '../common/emptyContent/index'
@@ -38,11 +38,11 @@ class DataConnect extends React.Component {
         const pWidth = parent.offsetWidth; // 父级容器宽度
         const pPadding = 10 + 10; // 父级容器左右padding
         const cWidth = 160; // 每个卡片宽度
-        const cMargin = 5 + 5; // 每个卡片左右margin
+        const cMargin = 8 + 8; // 每个卡片左右margin
         const pTrueWidth = pWidth - pPadding; // 父容器实际可用宽度
         const cTrueWidth = cWidth + cMargin; // 卡片实际占用宽度
         const count = Math.floor(pTrueWidth/cTrueWidth); // 每行最大卡片数量
-        const cardBodyWidth = count * cTrueWidth;
+        const cardBodyWidth = (count - 1) * cTrueWidth; // 可能有滚动条,减少一个
 
         cardBodyWidth > 0 ? cardBody.style.width = cardBodyWidth + 'px' : void(0);
     }
@@ -73,6 +73,43 @@ class DataConnect extends React.Component {
         this.setState({ visibleGroupMenu: flag });
     }
 
+    generateOperationMenu = (l) => {
+        const { dispatch } = this.props;
+
+        return (
+            <Menu className='menu-operation'>
+                <Menu.Item onClick={()=>{
+                    dispatch({ type: 'dataConnect/setSelected', selected: l });
+                    dispatch({ type: 'dataConnect/setNewModel', model: l });
+                    dispatch({ type: 'dataConnect/setNewModelFields', fields: [
+                        { name: 'visibleBox', value: true },
+                        { name: 'boxOperation', value: 'modify' }
+                    ] });
+                }}>
+                    <Icon type="info-circle-o" />属性设置
+                </Menu.Item>
+                <Menu.Item onClick={(e) => {
+                    dispatch({ type: 'dataConnect/setSelected', selected: l });
+                    dispatch({ type: 'dataConnect/setNewModel', model: { ...l, code: null } });
+                    dispatch({ type: 'dataConnect/setNewModelFields', fields: [
+                        { name: 'visibleBox', value: true },
+                        { name: 'boxOperation', value: 'create' }
+                    ] });
+                }}>
+                    <Icon type="copy" />复制新增
+                    
+                </Menu.Item>
+                <Menu.Item onClick={(e) => {
+                    dispatch({ type: 'dataConnect/setSelected', selected: l });
+                    this.setState({ visibleDeleteBox: true})
+                }}>
+                    <Icon type="delete" />删除
+                    
+                </Menu.Item>
+            </Menu>
+        )
+    }
+
     generateCard() {
         const { dataConnect, dispatch } = this.props;
         const reg = new RegExp('([+ \\- & | ! ( ) { } \\[ \\] ^ \" ~ * ? : ( ) \/])', 'g'); // 需要转义的字符
@@ -130,35 +167,12 @@ class DataConnect extends React.Component {
                         </Row>
                     }
                     actions={[
-                        <Tooltip placement='bottom' title="属性设置">
-                            <Icon type="info-circle-o" onClick={() => {
-                                // 选中项设置
-                                dispatch({ type: 'dataConnect/setSelected', selected: l });
-                                dispatch({ type: 'dataConnect/setNewModel', model: l });
-                                dispatch({ type: 'dataConnect/setNewModelFields', fields: [
-                                    { name: 'visibleBox', value: true },
-                                    { name: 'boxOperation', value: 'modify' }
-                                ] });
-                            }}/>
-                        </Tooltip>,
-                        <Tooltip placement='bottom' title="复制新增">
-                            <Icon type="copy" onClick={() => {
-                                // 选中项设置
-                                dispatch({ type: 'dataConnect/setSelected', selected: l });
-                                dispatch({ type: 'dataConnect/setNewModel', model: { ...l, code: null } });
-                                dispatch({ type: 'dataConnect/setNewModelFields', fields: [
-                                    { name: 'visibleBox', value: true },
-                                    { name: 'boxOperation', value: 'create' }
-                                ] });
-                            }}/>
-                        </Tooltip>,
-                        <Tooltip placement='bottom' title="删除">
-                            <Icon type="delete" onClick={() => {
-                                // 选中项设置
-                                dispatch({ type: 'dataConnect/setSelected', selected: l });
-                                this.setState({ visibleDeleteBox: true})
-                            }}/>
-                        </Tooltip>,
+                        <div>
+                            {l.dbType === 'file' ? <Icon type='file' /> : <div><Icon type='database' />{l.dbType[0].toUpperCase() + l.dbType.slice(1)}</div>}
+                        </div>,
+                        <Dropdown overlay={this.generateOperationMenu(l)} trigger={['click']}>
+                            <Icon style={{ fontSize: '24px' }} type="ellipsis" theme="outlined" />
+                        </Dropdown>
                     ]}
                 >
                     <div className='content'
@@ -172,6 +186,7 @@ class DataConnect extends React.Component {
                             ] });
                         }}
                     >
+                        { /** TODO 这里只考虑了数据库的展示情况,需要兼容展示文件类型的数据链接 */ }
                         <Row className='address'>
                             { filterLabel && filterItem.name === 'address' ?
                                 ((l.address || '').split(new RegExp(`(${filterLabel})`, 'i')).map((fragment, i) => {

+ 4 - 2
src/components/dataConnect/list.less

@@ -30,7 +30,7 @@
                     width: 160px;
                     height: 160px;
                     padding: 0;
-                    margin: 5px;
+                    margin: 8px;
                     cursor: pointer;
                     .ant-card {
                         height: 100%;
@@ -68,8 +68,10 @@
                             }
                         }
                         .ant-card-actions {
+                            height: 32px;
+                            background: #fff;
                             li {
-                                margin: 8px 0;
+                                margin: 4px 0;
                             }
                         }
                     }

+ 5 - 5
src/components/dataSource/list.jsx

@@ -157,7 +157,7 @@ class DataSource extends React.Component {
             if(t.children && t.children.length > 0) {
                 return <Menu.SubMenu
                     key={t.code}
-                    title={selectedRecord.groupCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.label}</span> : t.label}
+                    title={selectedRecord.groupCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.label}</span> : t.label}
                     onTitleClick={() => {
                         dispatch({ type: 'dataSource/remoteSetGroup', dataSource: selectedRecord, group: t });
                         dispatch({ type: 'dataSource/setCurrentGroup', group: t });
@@ -170,7 +170,7 @@ class DataSource extends React.Component {
                     dispatch({ type: 'dataSource/remoteSetGroup', dataSource: selectedRecord, group: t });
                     dispatch({ type: 'dataSource/setCurrentGroup', group: t });
                 }}>
-                    {selectedRecord.groupCode === t.code ? <span style={{ color: '#1890ff', fontWeight: 'bold' }}>{t.label}</span> : t.label}
+                    {selectedRecord.groupCode === t.code ? <span className='current' style={{ fontWeight: 'bold' }}>{t.label}</span> : t.label}
                 </Menu.Item>
             }
         })
@@ -239,13 +239,13 @@ class DataSource extends React.Component {
                     <Icon type="swap" />移交
                 </Menu.Item>}
                 <Menu.Divider />
-                { selectedRecord && <Menu.Item
+                {/* { selectedRecord && <Menu.Item
                     onClick={()=>{
                         this.setState({ visibleCopyBox: true})
                     }}
                 >
                     <Icon type="copy" />复制
-                </Menu.Item>}
+                </Menu.Item>} */}
                 { selectedRecord && currentUser.code === selectedRecord.creatorCode && <Menu.Item
                     onClick={(e) => {
                         this.setState({ visibleDeleteBox: true})
@@ -350,7 +350,7 @@ class DataSource extends React.Component {
         }];
 
         return ( 
-            <Layout className='datasource-view'>
+            <Layout className='layout-datasource'>
                 <Content>
                     <Card className='datasource-body' title={
                         <Row className='datasource-tools' type='flex' justify='space-between'>

+ 1 - 1
src/components/dataSource/list.less

@@ -1,4 +1,4 @@
-.datasource-view {
+.layout-datasource {
     .datasource-body {
         padding: 0;
         height: 100%;

+ 40 - 26
src/components/dataSourceDetail/baseConfig.jsx

@@ -1,5 +1,6 @@
 import React from 'react'
 import { Form, Row, Col, Input, InputNumber, Select, Divider, Cascader } from 'antd'
+import { arrayToTree } from '../../utils/baseUtils'
 import { connect } from 'dva'
 const FormItem = Form.Item
 const SelectOption = Select.Option
@@ -23,26 +24,52 @@ class DataSourceBaseConfig extends React.Component {
         dispatch({ type: 'dataConnect/fetchList' });
     }
 
+    generateGroupOptions = (treeData) => {
+        return treeData.map(t => {
+            t.children = t.children instanceof Array ? t.children : [];
+            return {
+                key: t.code,
+                value: t.code,
+                label: t.label,
+                children: this.generateGroupOptions(t.children)
+            }
+        })
+    }
+
+    getParens = (group) => {
+        const groupData = this.props.dataSource.groupList;
+        let pgroups = [group];
+        let fgroup = groupData.find(g => g.code === group.pcode);
+        if(fgroup) {
+            pgroups = this.getParens(fgroup).concat(pgroups);
+        }
+        return pgroups;
+    }
+
     render() {
         const { dataConnect, dataSource, dataSourceDetail, dispatch } = this.props;
-
+        const treeData = arrayToTree(dataSource.groupList, '-1', 'code', 'pcode', 'children');
         const formItemLayout = {
             labelCol: { span: 4 },
             wrapperCol: { span: 20 },
         };
     
         let getGroup = () => {
-            const { groupList } = dataSource;
-            const { group } = dataSourceDetail;
-            let g1 = groupList.filter(g => g.code+'' === group+'')[0];
-            if(!g1) {
-                return ['-1']
-            }
-            if(g1.pcode === '-1') {
-                return [g1.code]
+            const { group: key } = dataSourceDetail;
+            if(key === '-1') {
+                return ['-1'];
             }else {
-                let g2 = groupList.filter(g => g.code+'' === g1.pcode+'')[0];
-                return [g2.code, g1.code]
+                console.log(key);
+                let group = dataSource.groupList.find(g => g.code === key);
+                if(group) {
+                    console.log(group);
+                    let groups = this.getParens(group);
+                    let val = groups.map(g => g.code);
+                    console.log(group, val);
+                    return val;
+                }else {
+                    return null;
+                }
             }
         }
     
@@ -194,22 +221,9 @@ class DataSourceBaseConfig extends React.Component {
                         changeOnSelect={true}
                         expandTrigger='hover'
                         placeholder='未分组'
-                        options={[{pcode: '-1', code: '-1', label: '未分组'}].concat(dataSource.groupList).filter(g => g.pcode === '-1').map((p, i)=>{
-                            return {
-                                key: p.code,
-                                value: p.code,
-                                label: p.label,
-                                children: dataSource.groupList.filter(g => g.pcode === p.code && p.code !== '-1').map(c => {
-                                    return {
-                                        key: c.code,
-                                        value: c.code,
-                                        label: c.label
-                                    }
-                                })
-                            }
-                        })}
+                        options={this.generateGroupOptions([{pcode: '-1', code: '-1', label: '未分组'}].concat(treeData))}
                         onChange={(value, items) => {
-                            let v = value[1] !== undefined ? value[1] : value[0];
+                            let v = value[value.length - 1];
                             dispatch({ type: 'dataSourceDetail/setField', name: 'group', value: v });
                         }}
                         

+ 4 - 4
src/components/dataSourceDetail/dataConnectBox.jsx

@@ -56,7 +56,7 @@ class DataConnectBox extends React.Component {
         return (
             <Modal
                 className='dataconnect-box'
-                title={<Row type='flex' justify='space-between'><Col>{`${operation === 'create'?'新建':(operation === 'modify' ? '修改' : '查看')}数据库连接`}</Col><Col style={{ marginRight: '35px', fontSize: '14px', cursor: 'pointer', color: 'red' }} onClick={() => {
+                title={<Row type='flex' justify='space-between'><Col>{`${operation === 'create'?'新建':(operation === 'modify' ? '修改' : '查看')}数据接`}</Col><Col style={{ marginRight: '35px', fontSize: '14px', cursor: 'pointer', color: 'red' }} onClick={() => {
                     // 密码input特殊处理
                     document.getElementsByClassName('password')[0].value = '';
                     dispatch({ type:'dataConnect/resetNewModel'})
@@ -95,14 +95,14 @@ class DataConnectBox extends React.Component {
             >
                 <Form size='small'>
                     <FormItem
-                        label='接名'
+                        label='接名'
                         {...formItemLayout}
                         validateStatus={(dataConnect.newOne.name === undefined || dataConnect.newOne.name) ? 'success' : 'error'}
-                        help={dataConnect.newOne.name === undefined || dataConnect.newOne.name ? '' : '接名不能为空'}
+                        help={dataConnect.newOne.name === undefined || dataConnect.newOne.name ? '' : '接名不能为空'}
                     >
                         <Input
                             disabled={disabled}
-                            placeholder="输入数据库连接名称"
+                            placeholder="输入数据接名称"
                             value={dataConnect.newOne.name}
                             onChange={(e) => { dispatch({ type: 'dataConnect/setNewModelField', name: 'name', value: e.target.value }) }}
                         >

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

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

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

@@ -27,17 +27,17 @@ class Workshop extends React.Component {
 
         return <Layout className='layout-workshop'>
             <Sider
-                width={100}
+                width={160}
                 collapsible
                 collapsedWidth={0}
                 trigger={null}
                 theme='light'
                 className='sider-workshop'
             >
-                <Link to='/workshop/dataconnect'><Button className='ant-btn-block' type={(paths[1] === 'dataconnect' || !paths[1]) ? 'primary' : 'default'} >数据链接</Button></Link>
-                <Link to='/workshop/datasource'><Button className='ant-btn-block' type={paths[1] === 'datasource' ? 'primary' : 'default'} >数据源</Button></Link>
-                <Link to='/workshop/chart'><Button className='ant-btn-block' type={paths[1] === 'chart' ? 'primary' : 'default'} >图表</Button></Link>
-                <Link to='/workshop/dashboard'><Button className='ant-btn-block' type={paths[1] === 'dashboard' ? 'primary' : 'default'} >报表</Button></Link>
+                <Link to='/workshop/dataconnect'><div className={`link-btn${(paths[1] === 'dataconnect' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={(paths[1] === 'dataconnect' || !paths[1]) ? 'primary' : 'default'} >数据链接</Button></div></Link>
+                <Link to='/workshop/datasource'><div className={`link-btn${(paths[1] === 'datasource' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={paths[1] === 'datasource' ? 'primary' : 'default'} >数据源</Button></div></Link>
+                <Link to='/workshop/chart'><div className={`link-btn${(paths[1] === 'chart' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={paths[1] === 'chart' ? 'primary' : 'default'} >图表</Button></div></Link>
+                <Link to='/workshop/dashboard'><div className={`link-btn${(paths[1] === 'dashboard' || !paths[1]) ? ' selected' : ''}`}><Button className='ant-btn-block' type={paths[1] === 'dashboard' ? 'primary' : 'default'} >报表</Button></div></Link>
             </Sider>
             <Content className='content-workshop'>
                 <Switch>

+ 2 - 2
src/constants/url.js

@@ -1,5 +1,5 @@
 // const BASE_URL = 'http://10.1.1.168:8094/BI';
-// const BASE_URL = 'http://10.1.80.74:8011';
+// const BASE_URL = 'http://10.1.80.78:8011';
 const BASE_URL = 'http://218.18.115.198:8888/BI'
 
 /**后台接口地址 */
@@ -17,7 +17,7 @@ const URLS = {
 
     USERGROUP_ADD: BASE_URL + '/createUserGroup', // 添加用户组
 
-    USERGROUP_DELETE: BASE_URL + '/delUserGroup ', // 删除用户组
+    USERGROUP_DELETE: BASE_URL + '/delUserGroup', // 删除用户组
 
     USERGROUP_UPDATE: BASE_URL + '/updateUserGroup', // 修改用户组
 

+ 2 - 0
src/models/dashboard.js

@@ -735,6 +735,8 @@ export default {
             if(!res.err && res.data.code > 0) {
                 message.success('复制成功');
                 yield put({ type: 'fetchList', mandatory: true });
+                yield put({ type: 'dataSource/fetchList', mandatory: true });
+                yield put({ type: 'chart/fetchList', mandatory: true });
                 return true;
             }else {
                 message.error('复制失败: ' + (res.err || res.data.msg));

+ 2 - 4
src/models/userGroup.js

@@ -187,10 +187,8 @@ export default {
             const { group } = action;
             try {
                 const res = yield call(service.fetch, {
-                    url: URLS.USERGROUP_DELETE,
-                    body: {
-                        id: group.code
-                    }
+                    url: URLS.USERGROUP_DELETE + '/' + group.code,
+                    
                 });
                 if(!res.err && res.data.code > 0) {
                     yield put({ type: 'delete', group });

+ 10 - 1
src/theme.js

@@ -1,16 +1,25 @@
 // https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less
 module.exports = {
     /** override */
+    // Base Scaffolding Variables
+    'border-radius-base': '2px',
+
     // Layout
     'layout-body-background': '#fff',
+
     // Border
     'border-color-base': '#ccc',
 
+
+    
     /** custom */
+    'item-active-bg-color': '#2C82BE',
+    'item-active-color': '#fff',
     // Layout
     'sider-background-color': '#485465',
     'content-background-color': '#F6F6F7',
+
     // Tabs
     'tab-background': '#F5FBFE',
-    'tab-background-active': '#2C82BE',
+    'tab-background-active': 'item-active-bg-color',
 };

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

@@ -20,6 +20,35 @@
     color: rgba(0, 0, 0, 0.5);
 }
 
+// Table
+.ant-table-thead > tr,.ant-table-thead > tr:hover {
+    background: #D6EEFE;
+}
+.ant-table-thead > tr.ant-table-row-hover:not(.ant-table-expanded-row) > td, .ant-table-tbody > tr.ant-table-row-hover:not(.ant-table-expanded-row) > td, .ant-table-thead > tr:hover:not(.ant-table-expanded-row) > td, .ant-table-tbody > tr:hover:not(.ant-table-expanded-row) > td {
+    background: #F2F7FF;
+}
+.layout-datasource .ant-card-body .datasource-table .ant-table .ant-table-scroll .ant-table-body {
+    margin-top: 10px;
+}
+
+// ListFilter
+.list-filter .ant-select:first-child .ant-select-selection.ant-select-selection--single {
+    background: #F5FBFE;
+}
+
+// Dropdown Menu
+.ant-dropdown-menu {
+    border: 1px solid #408DC6;
+    .ant-dropdown-menu-item:hover, .ant-dropdown-menu-submenu-title:hover {
+        color: @item-active-color;
+        background-color: @item-active-bg-color;
+    }
+    .ant-dropdown-menu-item-disabled:hover, .ant-dropdown-menu-submenu-title-disabled:hover {
+        color: rgba(0, 0, 0, 0.25);
+        background-color: #fff;
+    }
+}
+
 
 // 滚动条
 *::-webkit-scrollbar {

+ 30 - 0
src/themes/default/chart.less

@@ -0,0 +1,30 @@
+.layout-chart {
+    &> .ant-layout-content {
+        &> .ant-card {
+            &> .ant-card-head {
+                .search {
+                    button {
+                        background: #F5FBFE;
+                        border: 1px solid #408DC6;
+                    }
+                }
+            }
+            &> .ant-card-body {
+                background: @content-background-color;
+                .chart-card {
+                    .ant-card {
+                        .ant-card-head {
+                            .ant-card-head-wrapper {
+                                background: #D6EEFE;
+                                .label {
+                                    font-size: 14px;
+                                    color: #2C82BE;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

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

@@ -0,0 +1,64 @@
+.layout-dashboard {
+    &> .ant-layout-sider {
+        border: none;
+        &> .ant-layout-sider-children {
+            &> .menu-container {
+                background: #727D99;
+                &> .menu-search {
+                    button {
+                        font-size: 18px;
+                        color: @menu-item-color;
+                        background: transparent;
+                        border: none;
+                        top: 1px;
+                        &:after {
+                            content: none;
+                        }
+                        &:hover {
+                            color: @menu-item-color-hover;
+                        }
+                    }
+                }
+                &> .menu-content {
+                    border: none;
+                    .ant-tree li {
+                        color: #E7F3FC;
+                        .ant-tree-node-content-wrapper {
+                            color: #E7F3FC;
+                            &.ant-tree-node-selected {
+                                background-color: #52637b;
+                            }
+                            &:hover {
+                                background-color: #52637b;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+    &> .ant-layout-content {
+        .dashboard-view {
+            &> .ant-layout-content {
+                &> .dashboard-body {
+                    &> .ant-card-head {
+                        .search {
+                            button {
+                                background: #F5FBFE;
+                                border: 1px solid #408DC6;
+                            }
+                            .ant-btn-disabled, .ant-btn.disabled, .ant-btn[disabled], .ant-btn-disabled:hover, .ant-btn.disabled:hover, .ant-btn[disabled]:hover, .ant-btn-disabled:focus, .ant-btn.disabled:focus, .ant-btn[disabled]:focus, .ant-btn-disabled:active, .ant-btn.disabled:active, .ant-btn[disabled]:active, .ant-btn-disabled.active, .ant-btn.disabled.active, .ant-btn[disabled].active {
+                                background-color: #f5f5f5;
+                                border-color: #ccc;
+                            }
+                        }
+                    }
+                    &> .ant-card-body {
+                        background: #F6F6F7;
+                        padding: 12px;
+                    }
+                }
+            }
+        }
+    }
+}

+ 30 - 0
src/themes/default/dataconnect.less

@@ -0,0 +1,30 @@
+.layout-dataconnect {
+    &> .ant-layout-content {
+        &> .ant-card {
+            &> .ant-card-head {
+                .search {
+                    button {
+                        background: #F5FBFE;
+                        border: 1px solid #408DC6;
+                    }
+                }
+            }
+            &> .ant-card-body {
+                background: @content-background-color;
+                .dataconnect-card {
+                    .ant-card {
+                        .ant-card-head {
+                            .ant-card-head-wrapper {
+                                background: #D6EEFE;
+                                .label {
+                                    font-size: 14px;
+                                    color: #2C82BE;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 18 - 0
src/themes/default/datasource.less

@@ -0,0 +1,18 @@
+.layout-datasource {
+    &> .ant-layout-content {
+        &> .datasource-body {
+            &> .ant-card-head {
+                .search {
+                    button {
+                        background: #F5FBFE;
+                        border: 1px solid #408DC6;
+                    }
+                }
+            }
+            &> .ant-card-body {
+                background: @content-background-color;
+                padding: 12px;
+            }
+        }
+    }
+}

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

@@ -26,5 +26,6 @@
 .main-content {
     background: @content-background-color;
     @import "./home.less";
+    @import "./workshop.less";
     @import "./setting.less";
 }

+ 3 - 3
src/themes/default/home.less

@@ -73,6 +73,7 @@
     }
     .content-home {
         &>.ant-tabs {
+            // background: #fff;
             &>.ant-tabs-bar {
                 .ant-tabs-nav-wrap {
                     .ant-tabs-tab {
@@ -99,9 +100,8 @@
                 }
             }
             &>.ant-tabs-content {
-                &>.ant-tabs-tabpane.ant-tabs-   -active {
-                    &>.dashboarddesigner-layout {
-                    }
+                .dashboardview-toolbar {
+                    // background: @content-background-color;
                 }
             }
         }

+ 23 - 10
src/themes/default/setting.less

@@ -5,18 +5,31 @@
         padding: 12px 0 0;
         .ant-layout-sider-children {
             a {
-                button {
-                    background: transparent;
-                    border: none;
-                    font-size: 16px;
-                    color: #A4AEBB;
-                    border-radius: 0;
-                    &[disabled] {
-                        opacity: 0.5;
+                .link-btn {
+                    button {
+                        height: 40px;
+                        background: transparent;
+                        border: none;
+                        font-size: 16px;
+                        color: #A4AEBB;
+                        border-radius: 0;
+                        &[disabled] {
+                            opacity: 0.5;
+                        }
                     }
                     &.selected {
-                        background: #727D99;
-                        color: #fff;
+                        button {
+                            background: #727D99;
+                            color: #fff;
+                        }
+                        &::before {
+                            content: ' ';
+                            position: absolute;
+                            height: 40px;
+                            width: 8px;
+                            background: #C8D1E9;
+                            z-index: 1;
+                        }
                     }
                 }
             }

+ 45 - 0
src/themes/default/workshop.less

@@ -0,0 +1,45 @@
+.layout-workshop {
+    .sider-workshop {
+        background: @sider-background-color;
+        border: none;
+        padding: 12px 0 0;
+        .ant-layout-sider-children {
+            a {
+                .link-btn {
+                    button {
+                        height: 40px;
+                        background: transparent;
+                        border: none;
+                        font-size: 16px;
+                        color: #A4AEBB;
+                        border-radius: 0;
+                        &[disabled] {
+                            opacity: 0.5;
+                        }
+                    }
+                    &.selected {
+                        button {
+                            background: #727D99;
+                            color: #fff;
+                        }
+                        &::before {
+                            content: ' ';
+                            position: absolute;
+                            height: 40px;
+                            width: 8px;
+                            background: #C8D1E9;
+                            z-index: 1;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    .content-workshop {
+        background: @content-background-color;
+        @import "./dataconnect.less";
+        @import "./datasource.less";
+        @import "./chart.less";
+        @import "./dashboard.less";
+    }
+}