mirror of
https://github.com/zuiidea/antd-admin
synced 2026-10-28 20:03:57 +00:00
user-dashbord
This commit is contained in:
+130
@@ -0,0 +1,130 @@
|
||||
'use strict';
|
||||
|
||||
const qs = require('qs');
|
||||
const mockjs = require('mockjs');
|
||||
|
||||
// 数据持久
|
||||
let tableListData = {};
|
||||
if (!global.tableListData) {
|
||||
const data = mockjs.mock({
|
||||
'data|100': [{
|
||||
'id|+1': 1,
|
||||
name: '@cname',
|
||||
'age|11-99': 1,
|
||||
address: '@region'
|
||||
}],
|
||||
page: {
|
||||
total: 100,
|
||||
current: 1
|
||||
}
|
||||
});
|
||||
tableListData = data;
|
||||
global.tableListData = tableListData;
|
||||
} else {
|
||||
tableListData = global.tableListData;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
|
||||
'GET /api/users' (req, res) {
|
||||
const page = qs.parse(req.query);
|
||||
const pageSize = page.pageSize || 10;
|
||||
const currentPage = page.page || 1;
|
||||
|
||||
let data;
|
||||
let newPage;
|
||||
|
||||
let newData = tableListData.data.concat();
|
||||
|
||||
if (page.field) {
|
||||
const d = newData.filter(function (item) {
|
||||
return item[page.field].indexOf(page.keyword) > -1;
|
||||
});
|
||||
|
||||
data = d.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
||||
|
||||
newPage = {
|
||||
current: currentPage * 1,
|
||||
total: d.length
|
||||
};
|
||||
} else {
|
||||
data = tableListData.data.slice((currentPage - 1) * pageSize, currentPage * pageSize);
|
||||
tableListData.page.current = currentPage * 1;
|
||||
newPage = {
|
||||
current: tableListData.page.current,
|
||||
total: tableListData.page.total
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
setTimeout(function () {
|
||||
res.json({
|
||||
success: true,
|
||||
data,
|
||||
page: newPage
|
||||
});
|
||||
}, 500);
|
||||
},
|
||||
|
||||
'POST /api/users' (req, res) {
|
||||
setTimeout(function () {
|
||||
const newData = qs.parse(req.body);
|
||||
|
||||
newData.id = tableListData.data.length + 1;
|
||||
tableListData.data.unshift(newData);
|
||||
|
||||
tableListData.page.total = tableListData.data.length;
|
||||
tableListData.page.current = 1;
|
||||
|
||||
global.tableListData = tableListData;
|
||||
res.json({
|
||||
success: true,
|
||||
data: tableListData.data,
|
||||
page: tableListData.page
|
||||
});
|
||||
}, 500);
|
||||
},
|
||||
|
||||
'DELETE /api/users' (req, res) {
|
||||
setTimeout(function () {
|
||||
const deleteItem = qs.parse(req.body);
|
||||
|
||||
tableListData.data = tableListData.data.filter(function (item) {
|
||||
if (item.id == deleteItem.id) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
tableListData.page.total = tableListData.data.length;
|
||||
|
||||
global.tableListData = tableListData;
|
||||
res.json({
|
||||
success: true,
|
||||
data: tableListData.data,
|
||||
page: tableListData.page
|
||||
});
|
||||
}, 500);
|
||||
},
|
||||
|
||||
'PUT /api/users' (req, res) {
|
||||
setTimeout(function () {
|
||||
const editItem = qs.parse(req.body);
|
||||
|
||||
tableListData.data = tableListData.data.map(function (item) {
|
||||
if (item.id == editItem.id) {
|
||||
return editItem;
|
||||
}
|
||||
return item;
|
||||
});
|
||||
|
||||
global.tableListData = tableListData;
|
||||
res.json({
|
||||
success: true,
|
||||
data: tableListData.data,
|
||||
page: tableListData.page
|
||||
});
|
||||
}, 500);
|
||||
}
|
||||
|
||||
};
|
||||
+9
-63
@@ -1,69 +1,15 @@
|
||||
import dva, { connect } from 'dva';
|
||||
import { Router, Route } from 'dva/router';
|
||||
import React from 'react';
|
||||
import styles from './index.less';
|
||||
import key from 'keymaster';
|
||||
import './index.html';
|
||||
import './index.less';
|
||||
import dva from 'dva';
|
||||
|
||||
// 1. Initialize
|
||||
const app = dva();
|
||||
|
||||
app.model({
|
||||
namespace: 'count',
|
||||
state: {
|
||||
record: 0,
|
||||
current: 0,
|
||||
},
|
||||
reducers: {
|
||||
add(state) {
|
||||
const newCurrent = state.current + 1;
|
||||
return { ...state,
|
||||
record: newCurrent > state.record ? newCurrent : state.record,
|
||||
current: newCurrent,
|
||||
};
|
||||
},
|
||||
minus(state) {
|
||||
return { ...state, current: state.current - 1};
|
||||
},
|
||||
},
|
||||
effects: {
|
||||
*add(action, { call, put }) {
|
||||
yield call(delay, 1000);
|
||||
yield put({ type: 'count/minus' });
|
||||
},
|
||||
},
|
||||
subscriptions: {
|
||||
keyboardWatcher(dispatch) {
|
||||
key('⌘+up, ctrl+up', () => { dispatch({type:'count/add'}) });
|
||||
},
|
||||
},
|
||||
});
|
||||
// 2. Model
|
||||
app.model(require('./models/users'));
|
||||
|
||||
const CountApp = ({count, dispatch}) => {
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<div className={styles.record}>Highest Record: {count.record}</div>
|
||||
<div className={styles.current}>{count.current}</div>
|
||||
<div className={styles.button}>
|
||||
<button onClick={() => { dispatch({type: 'count/add'}); }}>+</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return { count: state.count };
|
||||
}
|
||||
const HomePage = connect(mapStateToProps)(CountApp);
|
||||
|
||||
app.router(({history}) =>
|
||||
<Router history={history}>
|
||||
<Route path="/" component={HomePage} />
|
||||
</Router>
|
||||
);
|
||||
// 3. Router
|
||||
app.router(require('./router'));
|
||||
|
||||
// 4. Start
|
||||
app.start('#root');
|
||||
|
||||
function delay(timeout){
|
||||
return new Promise(resolve => {
|
||||
setTimeout(resolve, timeout);
|
||||
});
|
||||
}
|
||||
|
||||
+11
-6
@@ -1,11 +1,16 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { Router, Route, IndexRoute, Link } from 'dva/router';
|
||||
import IndexPage from './routes/IndexPage';
|
||||
import React from 'react';
|
||||
import { Router, Route } from 'dva/router';
|
||||
import HomePage from './routes/HomePage';
|
||||
import NotFound from './routes/NotFound';
|
||||
import Users from './routes/Users';
|
||||
|
||||
export default function({ history }) {
|
||||
/* eslint react/prop-types:0 */
|
||||
export default function ({ history }) {
|
||||
return (
|
||||
<Router history={history}>
|
||||
<Route path="/" component={IndexPage} />
|
||||
<Route path="/" component={HomePage} />
|
||||
<Route path="/users" component={Users} />
|
||||
<Route path="*" component={NotFound} />
|
||||
</Router>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import React from 'react';
|
||||
import { Link } from 'dva/router';
|
||||
import styles from './HomePage.less';
|
||||
|
||||
function HomePage() {
|
||||
return (
|
||||
<div className={styles.normal}>
|
||||
<h1>Hello Antd.</h1>
|
||||
<hr />
|
||||
<ul className={styles.list}>
|
||||
<li>You can go to <Link to="/users">/users</Link></li>
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
HomePage.propTypes = {
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
.normal {
|
||||
margin: 100px;
|
||||
}
|
||||
|
||||
.list {
|
||||
margin-top: 20px;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
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;
|
||||
@@ -0,0 +1,25 @@
|
||||
.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;
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
import React, { PropTypes } from 'react';
|
||||
import { routerRedux } from 'dva/router';
|
||||
import { connect } from 'dva';
|
||||
import MainLayout from '../components/MainLayout/MainLayout';
|
||||
import styles from './Users.less';
|
||||
import UserList from '../components/Users/UserList';
|
||||
import UserSearch from '../components/Users/UserSearch';
|
||||
import UserModal from '../components/Users/UserModal';
|
||||
|
||||
function Users({ location, dispatch, users }) {
|
||||
const {
|
||||
loading, list, total, current,
|
||||
currentItem, modalVisible, modalType,
|
||||
} = users;
|
||||
|
||||
const { field, keyword } = location.query;
|
||||
|
||||
const userModalProps = {
|
||||
item: modalType === 'create' ? {} : currentItem,
|
||||
type: modalType,
|
||||
visible: modalVisible,
|
||||
onOk(data) {
|
||||
dispatch({
|
||||
type: `users/${modalType}`,
|
||||
payload: data,
|
||||
});
|
||||
},
|
||||
onCancel() {
|
||||
dispatch({
|
||||
type: 'users/hideModal',
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const userListProps = {
|
||||
dataSource: list,
|
||||
loading,
|
||||
total,
|
||||
current,
|
||||
onPageChange(page) {
|
||||
dispatch(routerRedux.push({
|
||||
pathname: '/users',
|
||||
query: { page },
|
||||
}));
|
||||
},
|
||||
onDeleteItem(id) {
|
||||
dispatch({
|
||||
type: 'users/delete',
|
||||
payload: id,
|
||||
});
|
||||
},
|
||||
onEditItem(item) {
|
||||
dispatch({
|
||||
type: 'users/showModal',
|
||||
payload: {
|
||||
modalType: 'update',
|
||||
currentItem: item,
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
const userSearchProps = {
|
||||
field,
|
||||
keyword,
|
||||
onSearch(fieldsValue) {
|
||||
dispatch({
|
||||
type: 'users/query',
|
||||
payload: fieldsValue,
|
||||
});
|
||||
},
|
||||
onAdd() {
|
||||
dispatch({
|
||||
type: 'users/showModal',
|
||||
payload: {
|
||||
modalType: 'create',
|
||||
},
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
// 解决 Form.create initialValue 的问题
|
||||
// 每次创建一个全新的组件, 而不做diff
|
||||
// 如果你使用了redux, 请移步 http://react-component.github.io/form/examples/redux.html
|
||||
const UserModalGen = () =>
|
||||
<UserModal {...userModalProps} />;
|
||||
|
||||
return (
|
||||
<MainLayout location={location}>
|
||||
<div className={styles.normal}>
|
||||
<UserSearch {...userSearchProps} />
|
||||
<UserList {...userListProps} />
|
||||
<UserModalGen />
|
||||
</div>
|
||||
</MainLayout>
|
||||
);
|
||||
}
|
||||
|
||||
Users.propTypes = {
|
||||
users: PropTypes.object,
|
||||
location: PropTypes.object,
|
||||
dispatch: PropTypes.func,
|
||||
};
|
||||
|
||||
function mapStateToProps({ users }) {
|
||||
return { users };
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Users);
|
||||
@@ -0,0 +1,4 @@
|
||||
.normal {
|
||||
width: 800px;
|
||||
margin: 20px auto;
|
||||
}
|
||||
@@ -1,5 +0,0 @@
|
||||
import request from '../utils/request';
|
||||
|
||||
export async function query() {
|
||||
return request('/api/users');
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import request from '../utils/request';
|
||||
import qs from 'qs';
|
||||
|
||||
export async function query(params) {
|
||||
return request(`/api/users?${qs.stringify(params)}`);
|
||||
}
|
||||
|
||||
export async function create(params) {
|
||||
return request('/api/users', {
|
||||
method: 'post',
|
||||
body: qs.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
export async function remove(params) {
|
||||
return request('/api/users', {
|
||||
method: 'delete',
|
||||
body: qs.stringify(params),
|
||||
});
|
||||
}
|
||||
|
||||
export async function update(params) {
|
||||
return request('/api/users', {
|
||||
method: 'put',
|
||||
body: qs.stringify(params),
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
import fetch from 'dva/fetch';
|
||||
|
||||
function parseJSON(response) {
|
||||
return response.json();
|
||||
}
|
||||
|
||||
function checkStatus(response) {
|
||||
if (response.status >= 200 && response.status < 300) {
|
||||
return response;
|
||||
}
|
||||
|
||||
const error = new Error(response.statusText);
|
||||
error.response = response;
|
||||
throw error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a URL, returning a promise.
|
||||
*
|
||||
* @param {string} url The URL we want to request
|
||||
* @param {object} [options] The options we want to pass to "fetch"
|
||||
* @return {object} An object containing either "data" or "err"
|
||||
*/
|
||||
export default function request(url, options) {
|
||||
return fetch(url, options)
|
||||
.then(checkStatus)
|
||||
.then(parseJSON)
|
||||
.then((data) => ({ data }))
|
||||
.catch((err) => ({ err }));
|
||||
}
|
||||
Reference in New Issue
Block a user