mirror of
https://github.com/zuiidea/antd-admin
synced 2026-10-28 20:03:57 +00:00
dashbord
This commit is contained in:
+1
-1
@@ -38,7 +38,7 @@
|
||||
"scripts": {
|
||||
"start": "dora --plugins \"proxy,webpack,webpack-hmr\"",
|
||||
"dev": "dora --plugins \"webpack,webpack-hmr\"",
|
||||
"lint": "eslint --fix --ext .js,.jsx .",
|
||||
"lint": "eslint --fix --ext .js,.jsx src/components/layout",
|
||||
"build": "atool-build"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
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 Header({location,user,logout}) {
|
||||
function handleClickMenu(item){
|
||||
if(item.key=='logout'){
|
||||
function Header({ location, user, logout }) {
|
||||
function handleClickMenu(item) {
|
||||
if (item.key === 'logout') {
|
||||
logout()
|
||||
}
|
||||
}
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
<Menu className="header-menu" mode="horizontal" onClick={handleClickMenu}>
|
||||
<SubMenu style={{
|
||||
float: 'right'
|
||||
}} title={< span > <Icon type="user"/>{user.name}< /span>}>
|
||||
<Menu className="header-menu" mode="horizontal" onClick={handleClickMenu}>
|
||||
<SubMenu style={{ float: 'right' }}
|
||||
title={<span><Icon type="user" />{user.name}</span>}
|
||||
>
|
||||
<Menu.Item key="logout">
|
||||
<a>注销</a>
|
||||
</Menu.Item>
|
||||
@@ -27,7 +27,7 @@ function Header({location,user,logout}) {
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
location: PropTypes.object
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Header
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Icon} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Icon } from 'antd'
|
||||
import styles from './numberCard.less'
|
||||
|
||||
function NumberCard(props) {
|
||||
const {icon, color, title, number} = props
|
||||
const { icon, color, title, number } = props
|
||||
return (
|
||||
<div className={styles.numberCard}>
|
||||
<Icon className={styles.iconWarp} style={{color}} type={icon}/>
|
||||
<Icon className={styles.iconWarp} style={{ color }} type={icon} />
|
||||
<div className={styles.content}>
|
||||
<p className={styles.title}>{title||'No Title'}</p>
|
||||
<p className={styles.number}>{number||'10,000'}</p>
|
||||
<p className={styles.title}>{title || 'No Title'}</p>
|
||||
<p className={styles.number}>{number || '10,000'}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
.numberCard{
|
||||
box-shadow: 2px 2px 10px 0 rgba(0,0,0,0.05);
|
||||
box-shadow: 2px 2px 10px 0 rgba(0,0,0,0.01);
|
||||
padding: 32px;
|
||||
font-family: monospace;
|
||||
background-color: #fff;
|
||||
margin-bottom: 24px;
|
||||
.iconWarp{
|
||||
font-size: 54px;
|
||||
float: left;
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Breadcrumb, Icon} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Breadcrumb, Icon } from 'antd'
|
||||
import styles from './main.less'
|
||||
import {config, menu} from '../../utils'
|
||||
import { config, menu } from '../../utils'
|
||||
|
||||
let pathSet = []
|
||||
const getPathSet = function (menuArray, parentPath) {
|
||||
parentPath = parentPath || '/'
|
||||
menuArray.map(item => {
|
||||
pathSet[(parentPath + item.key).replace(/\//g, "-").hyphenToHump()] = {
|
||||
pathSet[(parentPath + item.key).replace(/\//g, '-').hyphenToHump()] = {
|
||||
path: parentPath + item.key,
|
||||
name: item.name,
|
||||
icon: item.icon || ''
|
||||
icon: item.icon || '',
|
||||
}
|
||||
if (!!item.child) {
|
||||
getPathSet(item.child, parentPath + item.key + '/')
|
||||
@@ -19,20 +19,20 @@ const getPathSet = function (menuArray, parentPath) {
|
||||
}
|
||||
getPathSet(menu)
|
||||
|
||||
function Bread({location}) {
|
||||
function Bread({ location }) {
|
||||
let pathNames = []
|
||||
location.pathname.substr(1).split('/').map((item, key) => {
|
||||
if (key > 0) {
|
||||
pathNames.push((pathNames[key - 1] + "-" + item).hyphenToHump())
|
||||
pathNames.push((pathNames[key - 1] + '-' + item).hyphenToHump())
|
||||
} else {
|
||||
pathNames.push(("-" + item).hyphenToHump())
|
||||
pathNames.push(('-' + item).hyphenToHump())
|
||||
}
|
||||
})
|
||||
const breads = pathNames.map((item, key) => {
|
||||
return (
|
||||
<Breadcrumb.Item key={key} {...pathNames.length - 1 == key ? '': { href:"#" + pathSet[item].path }}>
|
||||
<Breadcrumb.Item key={key} {...pathNames.length - 1 == key ? '' : { href: '#' + pathSet[item].path }}>
|
||||
{pathSet[item].icon
|
||||
? <Icon type={pathSet[item].icon}/>
|
||||
? <Icon type={pathSet[item].icon} />
|
||||
: ''}
|
||||
<span>{pathSet[item].name}</span>
|
||||
</Breadcrumb.Item>
|
||||
@@ -42,7 +42,7 @@ function Bread({location}) {
|
||||
return (
|
||||
<div className={styles.bread}>
|
||||
<Breadcrumb>
|
||||
<Breadcrumb.Item href="#/"><Icon type="home"/>
|
||||
<Breadcrumb.Item href="#/"><Icon type="home" />
|
||||
<span>主页</span>
|
||||
</Breadcrumb.Item>
|
||||
{breads}
|
||||
@@ -52,7 +52,7 @@ function Bread({location}) {
|
||||
}
|
||||
|
||||
Bread.propTypes = {
|
||||
location: PropTypes.object
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Bread
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import React, { PropTypes } from 'react'
|
||||
import styles from './main.less'
|
||||
import {config} from '../../utils'
|
||||
import { config } from '../../utils'
|
||||
|
||||
const Footer = () => <div className={styles.footer}>
|
||||
{config.footerText}
|
||||
|
||||
@@ -62,10 +62,13 @@
|
||||
margin: 24px 16px;
|
||||
|
||||
.content {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
min-height: e("calc(100vh - 168px)");
|
||||
position: relative;
|
||||
:global .content-inner{
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
min-height: e("calc(100vh - 168px)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,23 +1,23 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Menu, Icon} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Menu, Icon } from 'antd'
|
||||
import { Link } from 'dva/router'
|
||||
import styles from './main.less'
|
||||
import {config, menu} from '../../utils'
|
||||
import { config, menu } from '../../utils'
|
||||
|
||||
const getMenus = function (menuArray,parentPath){
|
||||
const getMenus = function (menuArray, parentPath) {
|
||||
parentPath = parentPath || '/'
|
||||
return menuArray.map(item =>{
|
||||
if(!!item.child){
|
||||
return menuArray.map(item => {
|
||||
if (!!item.child) {
|
||||
return (
|
||||
<Menu.SubMenu key={item.key} title={<span>{item.icon ? <Icon type={item.icon}/>: ''} {item.name}</span>}>
|
||||
{getMenus(item.child,parentPath + item.key + '/')}
|
||||
<Menu.SubMenu key={item.key} title={<span>{item.icon ? <Icon type={item.icon} /> : ''} {item.name}</span>}>
|
||||
{getMenus(item.child, parentPath + item.key + '/')}
|
||||
</Menu.SubMenu>
|
||||
)
|
||||
}else {
|
||||
} else {
|
||||
return (
|
||||
<Menu.Item key={item.key}>
|
||||
<Link to={parentPath + item.key}>
|
||||
{item.icon ? <Icon type={item.icon}/>: ''}
|
||||
{item.icon ? <Icon type={item.icon} /> : ''}
|
||||
{item.name}
|
||||
</Link>
|
||||
</Menu.Item>
|
||||
@@ -26,11 +26,11 @@ const getMenus = function (menuArray,parentPath){
|
||||
})
|
||||
}
|
||||
|
||||
function Sider({location}) {
|
||||
function Sider({ location }) {
|
||||
return (
|
||||
<div>
|
||||
<div className={styles.logo}>
|
||||
<img src={config.logoSrc}/>
|
||||
<img src={config.logoSrc} />
|
||||
<span>{config.logoText}</span>
|
||||
</div>
|
||||
<Menu mode="inline" theme="dark" defaultSelectedKeys={['dashboard']}>
|
||||
@@ -41,7 +41,7 @@ function Sider({location}) {
|
||||
}
|
||||
|
||||
Sider.propTypes = {
|
||||
location: PropTypes.object
|
||||
location: PropTypes.object,
|
||||
}
|
||||
|
||||
export default Sider
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Table, Popconfirm, Pagination} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Table, Popconfirm, Pagination } from 'antd'
|
||||
import styles from './list.less'
|
||||
|
||||
function list({
|
||||
@@ -8,7 +8,7 @@ function list({
|
||||
pagination,
|
||||
onPageChange,
|
||||
onDeleteItem,
|
||||
onEditItem
|
||||
onEditItem,
|
||||
}) {
|
||||
const columns = [
|
||||
{
|
||||
@@ -17,43 +17,43 @@ function list({
|
||||
key: 'avatar',
|
||||
width: 64,
|
||||
className: styles.avatar,
|
||||
render: (text) => <img width={24} src={text}/>
|
||||
render: (text) => <img width={24} src={text} />,
|
||||
}, {
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name'
|
||||
key: 'name',
|
||||
}, {
|
||||
title: '昵称',
|
||||
dataIndex: 'nickName',
|
||||
key: 'nickName'
|
||||
},{
|
||||
key: 'nickName',
|
||||
}, {
|
||||
title: '年龄',
|
||||
dataIndex: 'age',
|
||||
key: 'age',
|
||||
render: (text) => <span>{text}岁</span>
|
||||
render: (text) => <span>{text}岁</span>,
|
||||
}, {
|
||||
title: '性别',
|
||||
dataIndex: 'isMale',
|
||||
key: 'isMale',
|
||||
render: (text) => <span>{text
|
||||
? '男'
|
||||
: '女'}</span>
|
||||
},{
|
||||
: '女'}</span>,
|
||||
}, {
|
||||
title: '电话',
|
||||
dataIndex: 'phone',
|
||||
key: 'phone'
|
||||
},{
|
||||
key: 'phone',
|
||||
}, {
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
key: 'email'
|
||||
key: 'email',
|
||||
}, {
|
||||
title: '住址',
|
||||
dataIndex: 'address',
|
||||
key: 'address'
|
||||
key: 'address',
|
||||
}, {
|
||||
title: '创建时间',
|
||||
dataIndex: 'createTime',
|
||||
key: 'createTime'
|
||||
key: 'createTime',
|
||||
}, {
|
||||
title: '操作',
|
||||
key: 'operation',
|
||||
@@ -61,27 +61,28 @@ function list({
|
||||
render: (text, record) => (
|
||||
<p>
|
||||
<a onClick={() => onEditItem(record)} style={{
|
||||
marginRight: 4
|
||||
marginRight: 4,
|
||||
}}>编辑</a>
|
||||
<Popconfirm title="确定要删除吗?" onConfirm={() => onDeleteItem(record.id)}>
|
||||
<a>删除</a>
|
||||
</Popconfirm>
|
||||
</p>
|
||||
)
|
||||
}
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Table size="small"
|
||||
className={styles.table}
|
||||
bordered
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
loading={loading}
|
||||
onChange={onPageChange}
|
||||
pagination={pagination}
|
||||
rowKey={record => record.id}/>
|
||||
className={styles.table}
|
||||
bordered
|
||||
columns={columns}
|
||||
dataSource={dataSource}
|
||||
loading={loading}
|
||||
onChange={onPageChange}
|
||||
pagination={pagination}
|
||||
rowKey={record => record.id}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -92,7 +93,7 @@ list.propTypes = {
|
||||
onEditItem: PropTypes.func,
|
||||
dataSource: PropTypes.array,
|
||||
loading: PropTypes.any,
|
||||
pagination: PropTypes.any
|
||||
pagination: PropTypes.any,
|
||||
}
|
||||
|
||||
export default list
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Form, Input, InputNumber, Radio, Modal} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Form, Input, InputNumber, Radio, Modal } from 'antd'
|
||||
const FormItem = Form.Item
|
||||
|
||||
const formItemLayout = {
|
||||
labelCol: {
|
||||
span: 6
|
||||
span: 6,
|
||||
},
|
||||
wrapperCol: {
|
||||
span: 14
|
||||
}
|
||||
span: 14,
|
||||
},
|
||||
}
|
||||
|
||||
const modal = ({
|
||||
@@ -19,8 +19,8 @@ const modal = ({
|
||||
form: {
|
||||
getFieldDecorator,
|
||||
validateFields,
|
||||
getFieldsValue
|
||||
}
|
||||
getFieldsValue,
|
||||
},
|
||||
}) => {
|
||||
function handleOk() {
|
||||
validateFields((errors) => {
|
||||
@@ -29,7 +29,7 @@ const modal = ({
|
||||
}
|
||||
const data = {
|
||||
...getFieldsValue(),
|
||||
key: item.key
|
||||
key: item.key,
|
||||
}
|
||||
onOk(data)
|
||||
})
|
||||
@@ -40,7 +40,7 @@ const modal = ({
|
||||
visible,
|
||||
onOk: handleOk,
|
||||
onCancel,
|
||||
wrapClassName: "vertical-center-modal"
|
||||
wrapClassName: 'vertical-center-modal',
|
||||
}
|
||||
|
||||
return (
|
||||
@@ -52,10 +52,10 @@ const modal = ({
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '姓名未填写'
|
||||
}
|
||||
]
|
||||
})(<Input/>)}
|
||||
message: '姓名未填写',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
<FormItem label="昵称:" hasFeedback {...formItemLayout}>
|
||||
{getFieldDecorator('nickName', {
|
||||
@@ -63,10 +63,10 @@ const modal = ({
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '昵称未填写'
|
||||
}
|
||||
]
|
||||
})(<Input/>)}
|
||||
message: '昵称未填写',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
<FormItem label="性别" hasFeedback {...formItemLayout}>
|
||||
{getFieldDecorator('isMale', {
|
||||
@@ -75,12 +75,12 @@ const modal = ({
|
||||
{
|
||||
required: true,
|
||||
type: 'boolean',
|
||||
message: '请选择性别'
|
||||
}
|
||||
]
|
||||
message: '请选择性别',
|
||||
},
|
||||
],
|
||||
})(
|
||||
<Radio.Group>
|
||||
<Radio value={true}>男</Radio>
|
||||
<Radio value>男</Radio>
|
||||
<Radio value={false}>女</Radio>
|
||||
</Radio.Group>
|
||||
)}
|
||||
@@ -92,10 +92,10 @@ const modal = ({
|
||||
{
|
||||
required: true,
|
||||
type: 'number',
|
||||
message: '年龄未填写'
|
||||
}
|
||||
]
|
||||
})(<InputNumber min={18} max={100}/>)}
|
||||
message: '年龄未填写',
|
||||
},
|
||||
],
|
||||
})(<InputNumber min={18} max={100} />)}
|
||||
</FormItem>
|
||||
<FormItem label="电话:" hasFeedback {...formItemLayout}>
|
||||
{getFieldDecorator('phone', {
|
||||
@@ -103,10 +103,10 @@ const modal = ({
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '不能为空'
|
||||
}
|
||||
]
|
||||
})(<Input/>)}
|
||||
message: '不能为空',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
<FormItem label="邮箱:" hasFeedback {...formItemLayout}>
|
||||
{getFieldDecorator('email', {
|
||||
@@ -114,10 +114,10 @@ const modal = ({
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '不能为空'
|
||||
}
|
||||
]
|
||||
})(<Input/>)}
|
||||
message: '不能为空',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
<FormItem label="住址:" hasFeedback {...formItemLayout}>
|
||||
{getFieldDecorator('address', {
|
||||
@@ -125,10 +125,10 @@ const modal = ({
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '不能为空'
|
||||
}
|
||||
]
|
||||
})(<Input/>)}
|
||||
message: '不能为空',
|
||||
},
|
||||
],
|
||||
})(<Input />)}
|
||||
</FormItem>
|
||||
</Form>
|
||||
</Modal>
|
||||
@@ -140,7 +140,7 @@ modal.propTypes = {
|
||||
form: PropTypes.object,
|
||||
item: PropTypes.object,
|
||||
onOk: PropTypes.func,
|
||||
onCancel: PropTypes.func
|
||||
onCancel: PropTypes.func,
|
||||
}
|
||||
|
||||
export default Form.create()(modal)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React, {PropTypes} from 'react'
|
||||
import {Form, Input, Button, Select} from 'antd'
|
||||
import React, { PropTypes } from 'react'
|
||||
import { Form, Input, Button, Select } from 'antd'
|
||||
import styles from './search.less'
|
||||
|
||||
const search = ({
|
||||
@@ -10,8 +10,8 @@ const search = ({
|
||||
form: {
|
||||
getFieldDecorator,
|
||||
validateFields,
|
||||
getFieldsValue
|
||||
}
|
||||
getFieldsValue,
|
||||
},
|
||||
}) => {
|
||||
function handleSubmit(e) {
|
||||
e.preventDefault()
|
||||
@@ -29,7 +29,7 @@ const search = ({
|
||||
<Form inline onSubmit={handleSubmit}>
|
||||
<Form.Item>
|
||||
{getFieldDecorator('field', {
|
||||
initialValue: field || 'name'
|
||||
initialValue: field || 'name',
|
||||
})(
|
||||
<Select>
|
||||
<Select.Option value="name">名字</Select.Option>
|
||||
@@ -39,8 +39,8 @@ const search = ({
|
||||
</Form.Item>
|
||||
<Form.Item hasFeedback>
|
||||
{getFieldDecorator('keyword', {
|
||||
initialValue: keyword || ''
|
||||
})(<Input/>)}
|
||||
initialValue: keyword || '',
|
||||
})(<Input />)}
|
||||
</Form.Item>
|
||||
<Button type="primary" htmlType="submit">搜索</Button>
|
||||
</Form>
|
||||
@@ -57,7 +57,7 @@ search.propTypes = {
|
||||
onSearch: PropTypes.func,
|
||||
onAdd: PropTypes.func,
|
||||
field: PropTypes.string,
|
||||
keyword: PropTypes.string
|
||||
keyword: PropTypes.string,
|
||||
}
|
||||
|
||||
export default Form.create()(search)
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ export default function ({ history }) {
|
||||
<Router history={ history }>
|
||||
<Route path="/" component={ App } >
|
||||
<IndexRedirect to="/dashboard" />
|
||||
<Route path="dashboard" component={Dashboard}/>
|
||||
<Route path="dashboard" component={ Dashboard }/>
|
||||
<Route path="/users" component={ Users } />
|
||||
<Route path="*" component={ Error } />
|
||||
</Route>
|
||||
|
||||
@@ -10,6 +10,7 @@ import styles from '../components/layout/main.less'
|
||||
import '../components/layout/common.less'
|
||||
import {Spin,message} from 'antd'
|
||||
function App({children, location, dispatch, app}) {
|
||||
console.log(children);
|
||||
const {login, loading, loginButtonLoading, user} = app
|
||||
const loginProps = {
|
||||
loading,
|
||||
|
||||
+5
-3
@@ -2,9 +2,11 @@ import React from 'react'
|
||||
import {Icon} from 'antd'
|
||||
import styles from './error.less'
|
||||
|
||||
const Error = () => <div className={styles.error}>
|
||||
<Icon type="frown-o"/>
|
||||
<h1>404 Not Found</h1>
|
||||
const Error = () => <div className="content-inner">
|
||||
<div className={styles.error}>
|
||||
<Icon type="frown-o"/>
|
||||
<h1>404 Not Found</h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
export default Error
|
||||
|
||||
+1
-1
@@ -84,7 +84,7 @@ function Users({ location, dispatch, users }) {
|
||||
<UserModal {...userModalProps} />
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="content-inner">
|
||||
<UserSearch {...userSearchProps} />
|
||||
<UserList {...userListProps} />
|
||||
<UserModalGen />
|
||||
|
||||
Reference in New Issue
Block a user