mirror of
https://github.com/zuiidea/antd-admin
synced 2026-10-29 04:14:12 +00:00
layout
This commit is contained in:
+2
-1
@@ -5,6 +5,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"antd": "^2.0.1",
|
||||
"classnames": "^2.2.5",
|
||||
"dva": "1.0.0",
|
||||
"qs": "^6.2.0",
|
||||
"react": "^15.1.0",
|
||||
@@ -35,4 +36,4 @@
|
||||
"lint": "eslint --fix --ext .js,.jsx .",
|
||||
"build": "atool-build"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,36 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Menu, Icon } from 'antd';
|
||||
import { Link } from 'dva/router';
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import styles from './main.less'
|
||||
|
||||
const SubMenu = Menu.SubMenu
|
||||
|
||||
function getMenuKeyFromUrl(pathname) {
|
||||
let key = '';
|
||||
let key = ''
|
||||
try {
|
||||
key = pathname.match(/\/([^\/]*)/i)[1];
|
||||
key = pathname.match(/\/([^\/]*)/i)[1]
|
||||
/* eslint no-empty:0 */
|
||||
} catch (e) {}
|
||||
return key;
|
||||
return key
|
||||
}
|
||||
|
||||
function Header({ location }) {
|
||||
console.log(getMenuKeyFromUrl(location.pathname),location.pathname);
|
||||
return (
|
||||
<Menu
|
||||
selectedKeys={[getMenuKeyFromUrl(location.pathname)]}
|
||||
mode="horizontal"
|
||||
theme="dark"
|
||||
>
|
||||
<Menu.Item key="users">
|
||||
<Link to="/users"><Icon type="bars" />Users</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="home">
|
||||
<Link to="/"><Icon type="home" />Home</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="404">
|
||||
<Link to="/page-you-dont-know"><Icon type="frown-circle" />404</Link>
|
||||
</Menu.Item>
|
||||
<Menu.Item key="antd">
|
||||
<a href="https://github.com/dvajs/dva" target="_blank">dva</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
);
|
||||
<div className={styles.header}>
|
||||
<Menu className="header-menu" mode="horizontal">
|
||||
<SubMenu title={<span><Icon type="user" />吴彦祖</span>}>
|
||||
<Menu.Item key="signOut">
|
||||
<a>注销</a>
|
||||
</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
location: PropTypes.object,
|
||||
};
|
||||
}
|
||||
|
||||
export default Header;
|
||||
export default Header
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import styles from './MainLayout.less';
|
||||
import Header from './Header';
|
||||
|
||||
function MainLayout({ children, location }) {
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<Header location={location} />
|
||||
<div className={styles.content}>
|
||||
<div className={styles.main}>
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
MainLayout.propTypes = {
|
||||
children: PropTypes.element.isRequired,
|
||||
location: PropTypes.object,
|
||||
};
|
||||
|
||||
export default MainLayout;
|
||||
@@ -1,16 +0,0 @@
|
||||
|
||||
.normal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.main {
|
||||
padding: 0 8px;
|
||||
flex: 1 0 auto;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Breadcrumb, Icon} from 'antd'
|
||||
import styles from './main.less'
|
||||
|
||||
function Bread({location}) {
|
||||
return (
|
||||
<div className={styles.bread}>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item>Home</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>
|
||||
<a href="">Application Center</a>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>
|
||||
<a href="">Application List</a>
|
||||
</Breadcrumb.Item>
|
||||
<Breadcrumb.Item>An Application</Breadcrumb.Item>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Bread.propTypes = {
|
||||
location: PropTypes.object
|
||||
}
|
||||
|
||||
export default Bread
|
||||
@@ -0,0 +1,34 @@
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
// scrollbar
|
||||
::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-button {
|
||||
width: 0;
|
||||
height: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
width: 7px;
|
||||
background-color: #b4babf;
|
||||
border-radius: 7px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-track {
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar:hover {
|
||||
background-color: transparent;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import styles from './main.less'
|
||||
|
||||
function Footer({location}) {
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
底部
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Footer.propTypes = {
|
||||
location: PropTypes.object
|
||||
}
|
||||
|
||||
export default Footer
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import styles from './main.less'
|
||||
import classnames from 'classnames'
|
||||
import Header from './header'
|
||||
import Bread from './bread'
|
||||
import Footer from './footer'
|
||||
import Sider from './sider'
|
||||
import './common.less'
|
||||
|
||||
function Main({ children, location }) {
|
||||
return (
|
||||
<div className={styles.layout}>
|
||||
<aside className={styles.sider}>
|
||||
<Sider />
|
||||
</aside>
|
||||
<div className={styles.main}>
|
||||
<Header location={location} />
|
||||
<Bread location={location} />
|
||||
<div className={styles.container}>
|
||||
<div className={styles.content}>
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Main.propTypes = {
|
||||
children: PropTypes.element.isRequired,
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Main
|
||||
@@ -0,0 +1,77 @@
|
||||
.layout {
|
||||
position: relative;
|
||||
height: 100vh;
|
||||
|
||||
.sider {
|
||||
width: 224px;
|
||||
background: #404040;
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
padding-bottom: 24px;
|
||||
height: 100vh;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.logo {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
margin: 16px 0;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
:global(.ant-menu-horizontal) {
|
||||
border: none;
|
||||
}
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.bread {
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
padding: 0 16px;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.main {
|
||||
margin-left: 224px;
|
||||
transition: all 0.3s ease;
|
||||
overflow: auto;
|
||||
height: 100vh;
|
||||
|
||||
.container {
|
||||
margin: 24px 16px;
|
||||
|
||||
.content {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
min-height: e("calc(100vh - 168px)");
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.footer {
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #999;
|
||||
background: #fff;
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.05);
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import styles from './main.less'
|
||||
|
||||
const SubMenu = Menu.SubMenu;
|
||||
const MenuItemGroup = Menu.ItemGroup;
|
||||
|
||||
function Sider({ location }) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.logo}>
|
||||
<img src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg" />
|
||||
<span>Ant Design</span>
|
||||
</div>
|
||||
<Menu mode="inline" theme="dark" defaultSelectedKeys={['dashboard']}>
|
||||
<SubMenu key="sub1" title={<span><Icon type="mail" /><span>Navigation One</span></span>}>
|
||||
<MenuItemGroup title="Item 1">
|
||||
<Menu.Item key="1">Option 1</Menu.Item>
|
||||
<Menu.Item key="2">Option 2</Menu.Item>
|
||||
</MenuItemGroup>
|
||||
<MenuItemGroup title="Item 2">
|
||||
<Menu.Item key="3">Option 3</Menu.Item>
|
||||
<Menu.Item key="4">Option 4</Menu.Item>
|
||||
</MenuItemGroup>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub2" title={<span><Icon type="appstore" /><span>Navigation Two</span></span>}>
|
||||
<Menu.Item key="5">Option 5</Menu.Item>
|
||||
<Menu.Item key="6">Option 6</Menu.Item>
|
||||
<SubMenu key="sub3" title="Submenu">
|
||||
<Menu.Item key="7">Option 7</Menu.Item>
|
||||
<Menu.Item key="8">Option 8</Menu.Item>
|
||||
</SubMenu>
|
||||
</SubMenu>
|
||||
<SubMenu key="sub4" title={<span><Icon type="setting" /><span>Navigation Three</span></span>}>
|
||||
<Menu.Item key="9">Option 9</Menu.Item>
|
||||
<Menu.Item key="10">Option 10</Menu.Item>
|
||||
<Menu.Item key="11">Option 11</Menu.Item>
|
||||
<Menu.Item key="12">Option 12</Menu.Item>
|
||||
</SubMenu>
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Sider.propTypes = {
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Sider
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Form, Input, Button, Select} from 'antd'
|
||||
import styles from './UserSearch.less'
|
||||
import styles from './search.less'
|
||||
|
||||
const UserSearch = ({
|
||||
field,
|
||||
+7
-7
@@ -1,15 +1,15 @@
|
||||
import './index.html';
|
||||
import './index.less';
|
||||
import dva from 'dva';
|
||||
import './index.html'
|
||||
import './index.less'
|
||||
import dva from 'dva'
|
||||
|
||||
// 1. Initialize
|
||||
const app = dva();
|
||||
const app = dva()
|
||||
|
||||
// 2. Model
|
||||
app.model(require('./models/users'));
|
||||
app.model(require('./models/users'))
|
||||
|
||||
// 3. Router
|
||||
app.router(require('./router'));
|
||||
app.router(require('./router'))
|
||||
|
||||
// 4. Start
|
||||
app.start('#root');
|
||||
app.start('#root')
|
||||
|
||||
+3
-3
@@ -1,13 +1,13 @@
|
||||
import React from 'react'
|
||||
import { Router, Route } from 'dva/router'
|
||||
import HomePage from './routes/HomePage'
|
||||
import Index from './routes/index'
|
||||
import NotFound from './routes/NotFound'
|
||||
import Users from './routes/Users'
|
||||
import Users from './routes/users'
|
||||
|
||||
export default function ({ history }) {
|
||||
return (
|
||||
<Router history={history}>
|
||||
<Route path="/" component={HomePage} />
|
||||
<Route path="/" component={Index} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="*" component={NotFound} />
|
||||
</Router>
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import React, { Component, PropTypes } from 'react';
|
||||
import { connect } from 'dva';
|
||||
import { Link } from 'dva/router';
|
||||
import styles from './IndexPage.less';
|
||||
|
||||
function IndexPage() {
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<h1>Welcome to dva!</h1>
|
||||
<hr />
|
||||
<ul className={styles.list}>
|
||||
<li>To get started, edit <code>src/index.js</code> and save to reload.</li>
|
||||
<li><a href="https://github.com/sorrycc/blog/issues/8" target="_blank">Getting Started</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
IndexPage.propTypes = {
|
||||
};
|
||||
|
||||
export default connect()(IndexPage);
|
||||
@@ -1,8 +0,0 @@
|
||||
|
||||
.normal {
|
||||
margin: 100px;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
+29
-29
@@ -1,19 +1,19 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { routerRedux } from 'dva/router';
|
||||
import { connect } from 'dva';
|
||||
import MainLayout from '../components/Layout/MainLayout';
|
||||
import styles from './Users.less';
|
||||
import UserList from '../components/Users/UserList';
|
||||
import UserSearch from '../components/Users/UserSearch';
|
||||
import UserModal from '../components/Users/UserModal';
|
||||
import React, { PropTypes } from 'react'
|
||||
import { routerRedux } from 'dva/router'
|
||||
import { connect } from 'dva'
|
||||
import Main from '../components/layout/main'
|
||||
import styles from './users.less'
|
||||
import UserList from '../components/users/list'
|
||||
import UserSearch from '../components/users/search'
|
||||
import UserModal from '../components/users/modal'
|
||||
|
||||
function Users({ location, dispatch, users }) {
|
||||
const {
|
||||
loading, list, total, current,
|
||||
currentItem, modalVisible, modalType,
|
||||
} = users;
|
||||
} = users
|
||||
|
||||
const { field, keyword } = location.query;
|
||||
const { field, keyword } = location.query
|
||||
|
||||
const userModalProps = {
|
||||
item: modalType === 'create' ? {} : currentItem,
|
||||
@@ -23,14 +23,14 @@ function Users({ location, dispatch, users }) {
|
||||
dispatch({
|
||||
type: `users/${modalType}`,
|
||||
payload: data,
|
||||
});
|
||||
})
|
||||
},
|
||||
onCancel() {
|
||||
dispatch({
|
||||
type: 'users/hideModal',
|
||||
});
|
||||
})
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const userListProps = {
|
||||
dataSource: list,
|
||||
@@ -41,13 +41,13 @@ function Users({ location, dispatch, users }) {
|
||||
dispatch(routerRedux.push({
|
||||
pathname: '/users',
|
||||
query: { page },
|
||||
}));
|
||||
}))
|
||||
},
|
||||
onDeleteItem(id) {
|
||||
dispatch({
|
||||
type: 'users/delete',
|
||||
payload: id,
|
||||
});
|
||||
})
|
||||
},
|
||||
onEditItem(item) {
|
||||
dispatch({
|
||||
@@ -56,9 +56,9 @@ function Users({ location, dispatch, users }) {
|
||||
modalType: 'update',
|
||||
currentItem: item,
|
||||
},
|
||||
});
|
||||
})
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
const userSearchProps = {
|
||||
field,
|
||||
@@ -67,7 +67,7 @@ function Users({ location, dispatch, users }) {
|
||||
dispatch({
|
||||
type: 'users/query',
|
||||
payload: fieldsValue,
|
||||
});
|
||||
})
|
||||
},
|
||||
onAdd() {
|
||||
dispatch({
|
||||
@@ -75,35 +75,35 @@ function Users({ location, dispatch, users }) {
|
||||
payload: {
|
||||
modalType: 'create',
|
||||
},
|
||||
});
|
||||
})
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// 解决 Form.create initialValue 的问题
|
||||
// 每次创建一个全新的组件, 而不做diff
|
||||
// 如果你使用了redux, 请移步 http://react-component.github.io/form/examples/redux.html
|
||||
const UserModalGen = () =>
|
||||
<UserModal {...userModalProps} />;
|
||||
<UserModal {...userModalProps} />
|
||||
|
||||
return (
|
||||
<MainLayout location={location}>
|
||||
<Main location={location}>
|
||||
<div className={styles.normal}>
|
||||
<UserSearch {...userSearchProps} />
|
||||
<UserList {...userListProps} />
|
||||
<UserModalGen />
|
||||
</div>
|
||||
</MainLayout>
|
||||
);
|
||||
</Main>
|
||||
)
|
||||
}
|
||||
|
||||
Users.propTypes = {
|
||||
users: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
};
|
||||
|
||||
function mapStateToProps({ users }) {
|
||||
return { users };
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Users);
|
||||
function mapStateToProps({ users }) {
|
||||
return { users }
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Users)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'dva/router';
|
||||
import styles from './HomePage.less';
|
||||
import React from 'react'
|
||||
import { Link } from 'dva/router'
|
||||
import styles from './Index.less'
|
||||
|
||||
function HomePage() {
|
||||
return (
|
||||
@@ -11,10 +11,10 @@ function HomePage() {
|
||||
<li>You can go to <Link to="/users">/users</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
)
|
||||
}
|
||||
|
||||
HomePage.propTypes = {
|
||||
};
|
||||
}
|
||||
|
||||
export default HomePage;
|
||||
export default HomePage
|
||||
Reference in New Issue
Block a user