user-dashbord

This commit is contained in:
zuiidea
2016-10-11 22:16:28 +08:00
parent 34ccb19f4c
commit 24998e990f
12 changed files with 387 additions and 74 deletions
+130
View File
@@ -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
View File
@@ -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
View File
@@ -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>
);
};
}
+20
View File
@@ -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;
+8
View File
@@ -0,0 +1,8 @@
.normal {
margin: 100px;
}
.list {
margin-top: 20px;
}
+14
View File
@@ -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;
+25
View File
@@ -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;
}
+109
View File
@@ -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);
+4
View File
@@ -0,0 +1,4 @@
.normal {
width: 800px;
margin: 20px auto;
}
-5
View File
@@ -1,5 +0,0 @@
import request from '../utils/request';
export async function query() {
return request('/api/users');
}
+27
View File
@@ -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),
});
}
+30
View File
@@ -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 }));
}