mirror of
https://github.com/zuiidea/antd-admin
synced 2026-10-21 06:53:47 +00:00
error page
This commit is contained in:
@@ -1,25 +1,17 @@
|
||||
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 = ''
|
||||
try {
|
||||
key = pathname.match(/\/([^\/]*)/i)[1]
|
||||
/* eslint no-empty:0 */
|
||||
} catch (e) {}
|
||||
return key
|
||||
}
|
||||
|
||||
function Header({ location }) {
|
||||
console.log(getMenuKeyFromUrl(location.pathname),location.pathname);
|
||||
function Header({location}) {
|
||||
return (
|
||||
<div className={styles.header}>
|
||||
<Menu className="header-menu" mode="horizontal">
|
||||
<SubMenu style={{float:'right'}} title={<span><Icon type="user" />吴彦祖</span>}>
|
||||
<SubMenu style={{
|
||||
float: 'right'
|
||||
}} title={< span > <Icon type="user"/>吴彦祖 < /span>}>
|
||||
<Menu.Item key="signOut">
|
||||
<a>注销</a>
|
||||
</Menu.Item>
|
||||
@@ -30,7 +22,7 @@ function Header({ location }) {
|
||||
}
|
||||
|
||||
Header.propTypes = {
|
||||
location: PropTypes.object,
|
||||
location: PropTypes.object
|
||||
}
|
||||
|
||||
export default Header
|
||||
|
||||
@@ -2,16 +2,8 @@ import React, {PropTypes} from 'react'
|
||||
import styles from './main.less'
|
||||
import {config} from '../../utils'
|
||||
|
||||
function Footer({location}) {
|
||||
return (
|
||||
<div className={styles.footer}>
|
||||
{config.footerText}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
Footer.propTypes = {
|
||||
location: PropTypes.object
|
||||
}
|
||||
const Footer = () => <div className={styles.footer}>
|
||||
{config.footerText}
|
||||
</div>
|
||||
|
||||
export default Footer
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
import React from 'react'
|
||||
import { Router, Route , IndexRedirect , hashHistory} from 'dva/router'
|
||||
import App from './components/layout/main'
|
||||
import NotFound from './routes/NotFound'
|
||||
import Error from './routes/error'
|
||||
import Dashboard from './routes/dashboard'
|
||||
import Users from './routes/users'
|
||||
|
||||
@@ -12,7 +12,7 @@ export default function ({ history }) {
|
||||
<IndexRedirect to="/dashboard" />
|
||||
<Route path="dashboard" component={Dashboard}/>
|
||||
<Route path="/users" component={ Users } />
|
||||
<Route path="*" component={ NotFound } />
|
||||
<Route path="*" component={ Error } />
|
||||
</Route>
|
||||
</Router>
|
||||
)
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
import React from 'react';
|
||||
import { Button } from 'antd';
|
||||
import styles from './NotFound.less';
|
||||
|
||||
const NotFound = () =>
|
||||
<div className={styles.normal}>
|
||||
<div className={styles.container}>
|
||||
<h1 className={styles.title}>404</h1>
|
||||
<p className={styles.desc}>未找到该页面</p>
|
||||
<a href="/"><Button type="primary" style={{ marginTop: 5 }}>返回首页</Button></a>
|
||||
</div>
|
||||
</div>;
|
||||
|
||||
export default NotFound;
|
||||
@@ -1,25 +0,0 @@
|
||||
.normal {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 100vh;
|
||||
padding-top: 120px;
|
||||
}
|
||||
|
||||
.container {
|
||||
padding: 0;
|
||||
margin: 0 auto;
|
||||
width: 620px;
|
||||
height: 300px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 80px;
|
||||
color: #666;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.desc {
|
||||
font-size: 14px;
|
||||
}
|
||||
@@ -79,14 +79,11 @@ function Users({ location, dispatch, users }) {
|
||||
},
|
||||
}
|
||||
|
||||
// 解决 Form.create initialValue 的问题
|
||||
// 每次创建一个全新的组件, 而不做diff
|
||||
// 如果你使用了redux, 请移步 http://react-component.github.io/form/examples/redux.html
|
||||
const UserModalGen = () =>
|
||||
<UserModal {...userModalProps} />
|
||||
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<div>
|
||||
<UserSearch {...userSearchProps} />
|
||||
<UserList {...userListProps} />
|
||||
<UserModalGen />
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
.normal {
|
||||
width: 800px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
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>
|
||||
</div>
|
||||
|
||||
export default Error
|
||||
@@ -1,4 +1,4 @@
|
||||
.not-found {
|
||||
.error {
|
||||
color: black;
|
||||
text-align: center;
|
||||
position: absolute;
|
||||
@@ -7,9 +7,11 @@
|
||||
left: 50%;
|
||||
margin-left: -100px;
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
|
||||
:global .anticon{
|
||||
font-size: 48px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
h1 {
|
||||
font-family: "PingFang SC",;
|
||||
font-family: cursive;
|
||||
}
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import React from 'react'
|
||||
import { Icon } from 'antd'
|
||||
import './error.less'
|
||||
|
||||
const Error = React.createClass({
|
||||
render() {
|
||||
return (
|
||||
<div className="not-found">
|
||||
<div style={{ fontSize:32 }}><Icon type="frown"/></div>
|
||||
<h1>{this.props.errorMsg || '404 Not Found'}</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = Error
|
||||
@@ -1,140 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { ajax, config, Logger } from '../../utils/lib'
|
||||
import { Icon, message, Table, Button, Row, Col, Dropdown, Menu } from 'antd'
|
||||
import './list.less'
|
||||
|
||||
const logger = Logger.getLogger('List')
|
||||
|
||||
let List = React.createClass({
|
||||
getInitialState() {
|
||||
logger.info()
|
||||
const tableName = this.props.routes.pop().tableName
|
||||
return {
|
||||
tableName,
|
||||
pager:{
|
||||
showSizeChanger: true,
|
||||
showQuickJumper: true,
|
||||
showTotal: total => `共 ${total} 条`
|
||||
},
|
||||
data:[],
|
||||
params:{},
|
||||
loading: false,
|
||||
};
|
||||
},
|
||||
componentDidMount() {
|
||||
this.fetch()
|
||||
},
|
||||
handleTableChange(pagination, filters, sorter) {
|
||||
let pager = this.state.pager
|
||||
pager.current = pagination.current
|
||||
this.state.pager = pager
|
||||
this.state.params = {
|
||||
results: pagination.pageSize,
|
||||
page: pagination.current,
|
||||
sortField: sorter.field,
|
||||
sortOrder: sorter.order,
|
||||
...filters
|
||||
}
|
||||
this.fetch()
|
||||
},
|
||||
fetch() {
|
||||
const _this = this
|
||||
this.setState({loading: true})
|
||||
ajax({
|
||||
url: 'https://randomuser.me/api/',
|
||||
data: {
|
||||
results:10,
|
||||
..._this.state.params
|
||||
},
|
||||
success: function (result) {
|
||||
const pager = _this.state.pager
|
||||
const params = _this.state.params
|
||||
pager.total = 200
|
||||
_this.setState({
|
||||
loading: false,
|
||||
data: result.results,
|
||||
pager,
|
||||
params})
|
||||
}
|
||||
})
|
||||
},
|
||||
render() {
|
||||
const columns = [
|
||||
{
|
||||
title: '头像',
|
||||
dataIndex: 'picture',
|
||||
width:64,
|
||||
className:'avatar-col',
|
||||
render: text => <img width='24' src={text.thumbnail} />,
|
||||
},{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
sorter: true,
|
||||
render: text => `${text.first} ${text.last}`,
|
||||
}, {
|
||||
title: '性别',
|
||||
dataIndex: 'gender',
|
||||
filters: [
|
||||
{ text: 'Male', value: 'male' },
|
||||
{ text: 'Female', value: 'female' },
|
||||
],
|
||||
}, {
|
||||
title: '座机',
|
||||
dataIndex: 'cell',
|
||||
}, {
|
||||
title: '国家',
|
||||
dataIndex: 'nat',
|
||||
}, {
|
||||
title: '城市',
|
||||
dataIndex: 'location',
|
||||
render: text => text.city,
|
||||
},{
|
||||
title: '手机',
|
||||
dataIndex: 'phone',
|
||||
},{
|
||||
title: '邮箱',
|
||||
dataIndex: 'email',
|
||||
},{
|
||||
title: '时间',
|
||||
dataIndex: 'dob',
|
||||
render: text => new Date(text).format("yyyy-MM-dd hh:mm:ss"),
|
||||
},{
|
||||
title: '操作',
|
||||
dataIndex: 'login',
|
||||
render: (text,it) => {
|
||||
const menu = (
|
||||
<Menu>
|
||||
<Menu.Item>
|
||||
<a href='javascript:;'>编辑</a>
|
||||
</Menu.Item>
|
||||
<Menu.Item>
|
||||
<a href='javascript:;'>删除</a>
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
)
|
||||
return <Dropdown overlay={menu}>
|
||||
<a className="ant-dropdown-link" href="javascript:;">
|
||||
操作 <Icon type="down" />
|
||||
</a>
|
||||
</Dropdown>
|
||||
},
|
||||
}]
|
||||
return (
|
||||
<div>
|
||||
<Table
|
||||
bordered
|
||||
columns={columns}
|
||||
rowKey={record => record.registered}
|
||||
dataSource={this.state.data}
|
||||
pagination={this.state.pager}
|
||||
loading={this.state.loading}
|
||||
onChange={this.handleTableChange}
|
||||
className="list-table"
|
||||
size="small" />
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
module.exports = List
|
||||
@@ -1,9 +0,0 @@
|
||||
|
||||
.list-table{
|
||||
.avatar-col{
|
||||
line-height: 1;
|
||||
}
|
||||
td{
|
||||
height: 39px;
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import Header from '../components/Header'
|
||||
import Footer from '../components/Footer'
|
||||
import Sidebar from '../components/Sidebar'
|
||||
import SignIn from './user/SignIn'
|
||||
import Breadcrumb from '../components/Breadcrumb'
|
||||
import './index.less'
|
||||
import { ajax, config, Logger } from '../utils/lib.js'
|
||||
import { Spin, message, Icon } from 'antd'
|
||||
|
||||
const logger = Logger.getLogger('App')
|
||||
|
||||
const App = React.createClass({
|
||||
getInitialState() {
|
||||
let loading=false,
|
||||
login=true
|
||||
if (config.needLogin){
|
||||
loading=true
|
||||
login=false
|
||||
}
|
||||
return {
|
||||
loading,
|
||||
login,
|
||||
userName: '未登录',
|
||||
collapse: false,
|
||||
}
|
||||
},
|
||||
componentDidMount() {
|
||||
const _this = this
|
||||
if(localStorage.getItem("username")&&localStorage.getItem("username")=="guest"&&
|
||||
localStorage.getItem("password")&&localStorage.getItem("password")=='guest'){
|
||||
_this.loginSuccess("guest")
|
||||
return
|
||||
}
|
||||
if (!this.state.login) {
|
||||
const loading = message.loading('正在获取用户信息...', 0)
|
||||
ajax({
|
||||
url: config.user.info,
|
||||
success: function (result) {
|
||||
if (result.isSuccess) {
|
||||
loading()
|
||||
_this.loginSuccess(result.userName)
|
||||
} else {
|
||||
loading()
|
||||
_this.setState({loading: false})
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
loginSuccess(name) {
|
||||
logger.debug('callback logingSuccess, name = %s', name)
|
||||
this.setState({
|
||||
loading: false,
|
||||
login: true,
|
||||
userName: name,
|
||||
})
|
||||
},
|
||||
render() {
|
||||
if (this.state.loading) {
|
||||
return (<Spin spinning={this.state.loading} size="large">
|
||||
<SignIn loginSuccess= {this.loginSuccess} />
|
||||
</Spin>)
|
||||
} else if (!this.state.login) {
|
||||
return <SignIn loginSuccess={this.loginSuccess} />
|
||||
}
|
||||
const collapse = this.state.collapse
|
||||
return (
|
||||
<div className={collapse ? "ant-layout-aside ant-layout-aside-collapse" : "ant-layout-aside"}>
|
||||
<aside className="ant-layout-sider">
|
||||
<Sidebar />
|
||||
<div className="ant-aside-action" onClick={this.onCollapseChange}>
|
||||
{collapse ? <Icon type="right" /> : <Icon type="left" />}
|
||||
</div>
|
||||
</aside>
|
||||
<div className="ant-layout-main">
|
||||
<Header userName={this.state.userName} />
|
||||
<Breadcrumb {...this.props} />
|
||||
<div className="ant-layout-container">
|
||||
<div className="ant-layout-content">
|
||||
{this.props.children}
|
||||
</div>
|
||||
</div>
|
||||
<Footer />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
module.exports = App
|
||||
@@ -1,165 +0,0 @@
|
||||
body {
|
||||
height: 100%;
|
||||
overflow-y: hidden;
|
||||
background-color: #f8f8f8;
|
||||
}
|
||||
|
||||
.ant-layout-aside {
|
||||
position: relative;
|
||||
min-height: 100%;
|
||||
|
||||
.ant-layout-header {
|
||||
.ant-menu {
|
||||
line-height: 47px;
|
||||
}
|
||||
|
||||
.ant-menu-horizontal {
|
||||
border: none;
|
||||
}
|
||||
box-shadow: 0 0 20px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
width: 224px;
|
||||
background: #404040;
|
||||
position: absolute;
|
||||
overflow: visible;
|
||||
padding-bottom: 24px;
|
||||
height: 100%;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
& > .ant-menu {
|
||||
margin-bottom: 20px;
|
||||
|
||||
& > .anticon {
|
||||
transition: font-size 0.3s;
|
||||
}
|
||||
|
||||
& > .ant-menu-item {
|
||||
margin: 16px 0;
|
||||
|
||||
&.nav-text {
|
||||
vertical-align: baseline;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-logo {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-breadcrumb {
|
||||
height: 48px;
|
||||
line-height: 48px;
|
||||
padding: 0 16px;
|
||||
margin-bottom: -24px;
|
||||
}
|
||||
|
||||
.ant-layout-main {
|
||||
margin-left: 224px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.ant-aside-action {
|
||||
height: 42px;
|
||||
width: 224px;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
background: #474747;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
line-height: 42px;
|
||||
cursor: pointer;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.ant-layout-container {
|
||||
margin: 24px 16px;
|
||||
|
||||
.ant-layout-content {
|
||||
background: #fff;
|
||||
padding: 24px;
|
||||
min-height: e("calc(100vh - 168px)");
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.ant-layout-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%;
|
||||
}
|
||||
|
||||
&.ant-layout-aside-collapse {
|
||||
.ant-aside-action {
|
||||
width: 64px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.ant-layout-main {
|
||||
margin-left: 64px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.ant-layout-sider {
|
||||
width: 64px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
& > .ant-menu {
|
||||
& > .ant-menu-item {
|
||||
transition: all 0s ease;
|
||||
|
||||
&:hover {
|
||||
background: #2db7f5;
|
||||
color: #fff;
|
||||
transition: all 0s ease;
|
||||
|
||||
.nav-text {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
background: #2db7f5;
|
||||
color: #fff;
|
||||
padding-right: 16px;
|
||||
border-radius: 0 5px 5px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.nav-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
& > .anticon {
|
||||
font-size: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.ant-layout-main{
|
||||
height: 100vh;
|
||||
overflow-y:auto;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import React from 'react'
|
||||
import { ajax, config, Logger } from '../../utils/lib'
|
||||
import { Icon, message, Button, Row, Col, Form, Input, Select } from 'antd'
|
||||
import './dashboard.less'
|
||||
const logger = Logger.getLogger('Dashboard')
|
||||
|
||||
const Dashboard = React.createClass({
|
||||
render(){
|
||||
return(
|
||||
<div>hello</div>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
module.exports = Dashboard
|
||||
@@ -1,88 +0,0 @@
|
||||
import React from 'react'
|
||||
import ReactDOM from 'react-dom'
|
||||
import { ajax, config, Logger } from '../../utils/lib'
|
||||
import { Icon, message, Button, Row, Col, Form, Input, Select } from 'antd'
|
||||
import './signIn.less'
|
||||
|
||||
const FormItem = Form.Item
|
||||
const logger = Logger.getLogger('SignIn')
|
||||
|
||||
let SignIn = React.createClass({
|
||||
getInitialState() {
|
||||
return {
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
handleSubmit(e) {
|
||||
const _this = this
|
||||
e.preventDefault()
|
||||
this.props.form.validateFieldsAndScroll((errors, values) => {
|
||||
if (!!errors) {
|
||||
return
|
||||
}
|
||||
_this.setState({ loading: true })
|
||||
ajax({
|
||||
url:config.user.signIn,
|
||||
data:values,
|
||||
success:function(result){
|
||||
if(result.isSuccess){
|
||||
_this.props.loginSuccess(result.userName, true)
|
||||
}else {
|
||||
message.error(`登录失败: ${result.message}, 请联系管理员`)
|
||||
}
|
||||
},
|
||||
complete:function(){
|
||||
_this.setState({ loading: false })
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
render() {
|
||||
const { getFieldProps } = this.props.form
|
||||
const username = getFieldProps('username', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '不能为空',
|
||||
},
|
||||
],
|
||||
})
|
||||
const password = getFieldProps('password', {
|
||||
rules: [
|
||||
{
|
||||
required: true,
|
||||
message: '不能为空',
|
||||
},
|
||||
],
|
||||
})
|
||||
return (
|
||||
<div className="signIn-from">
|
||||
<div className="logo mb">
|
||||
<img src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg" />
|
||||
<span>Ant Design</span>
|
||||
</div>
|
||||
<form horizontal onSubmit={this.handleSubmit} form={this.props.form}>
|
||||
<FormItem hasFeedback>
|
||||
<Input {...username} size="large" placeholder="账户" />
|
||||
</FormItem>
|
||||
<FormItem hasFeedback>
|
||||
<Input {...password} size="large" type="password" placeholder="密码" />
|
||||
</FormItem>
|
||||
<Row className="self-modal-footer">
|
||||
<Button type="primary" size="large" onClick={this.handleSubmit} loading={this.state.loading}>
|
||||
登录
|
||||
</Button>
|
||||
</Row>
|
||||
<p style={{color:'#ccc',textAlign:'center'}} className='m-y-sm'>
|
||||
<span className='mr'>账号:guest</span>
|
||||
<span>密码:guest</span>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
})
|
||||
|
||||
SignIn = Form.create()(SignIn)
|
||||
|
||||
module.exports = SignIn
|
||||
@@ -1,36 +0,0 @@
|
||||
.signIn-from {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
margin: -160px 0 0 -160px;
|
||||
width: 320px;
|
||||
height: 320px;
|
||||
padding: 36px;
|
||||
box-shadow: 0 0 100px rgba(0,0,0,.08);
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.logo {
|
||||
text-align: center;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
cursor: pointer;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
span {
|
||||
vertical-align: text-bottom;
|
||||
font-size: 16px;
|
||||
text-transform: uppercase;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
.ant-spin-container,.ant-spin-nested-loading{
|
||||
height: 100%;
|
||||
}
|
||||
Reference in New Issue
Block a user