This commit is contained in:
zuiidea
2016-10-10 22:25:56 +08:00
parent fda47b362c
commit 34ccb19f4c
11 changed files with 393 additions and 24 deletions
+67
View File
@@ -0,0 +1,67 @@
import React, { PropTypes } from 'react';
import { Table, Popconfirm, Pagination } from 'antd';
function UserList({
total, current, loading, dataSource,
onPageChange,
onDeleteItem,
onEditItem,
}) {
const columns = [{
title: '姓名',
dataIndex: 'name',
key: 'name',
render: (text) => <a href="#">{text}</a>,
}, {
title: '年龄',
dataIndex: 'age',
key: 'age',
}, {
title: '住址',
dataIndex: 'address',
key: 'address',
}, {
title: '操作',
key: 'operation',
render: (text, record) => (
<p>
<a onClick={() => onEditItem(record)}>编辑</a>
&nbsp;
<Popconfirm title="确定要删除吗?" onConfirm={() => onDeleteItem(record.id)}>
<a>删除</a>
</Popconfirm>
</p>
),
}];
return (
<div>
<Table
columns={columns}
dataSource={dataSource}
loading={loading}
rowKey={record => record.id}
pagination={false}
/>
<Pagination
className="ant-table-pagination"
total={total}
current={current}
pageSize={10}
onChange={onPageChange}
/>
</div>
);
}
UserList.propTypes = {
onPageChange: PropTypes.func,
onDeleteItem: PropTypes.func,
onEditItem: PropTypes.func,
dataSource: PropTypes.array,
loading: PropTypes.any,
total: PropTypes.any,
current: PropTypes.any,
};
export default UserList;
+109
View File
@@ -0,0 +1,109 @@
import React, { PropTypes } from 'react'
import { Form, Input, Modal } from 'antd'
const FormItem = Form.Item
const formItemLayout = {
labelCol: {
span: 6,
},
wrapperCol: {
span: 14,
},
}
const UserModal = ({
visible,
item = {},
onOk,
onCancel,
form: {
getFieldDecorator,
validateFields,
getFieldsValue,
},
}) => {
function handleOk() {
validateFields((errors) => {
if (errors) {
return
}
const data = { ...getFieldsValue(), key: item.key }
onOk(data)
})
}
function checkNumber(rule, value, callback) {
if (!/^[\d]{1,2}$/.test(value)) {
callback(new Error('年龄不合法'))
} else {
callback()
}
}
const modalOpts = {
title: '修改用户',
visible,
onOk: handleOk,
onCancel,
}
return (
<Modal {...modalOpts}>
<Form horizontal>
<FormItem
label="姓名:"
hasFeedback
{...formItemLayout}
>
{getFieldDecorator('name', {
initialValue: item.name,
rules: [
{ required: true, message: '名称未填写' },
],
})(
<Input type="text" />
)}
</FormItem>
<FormItem
label="年龄:"
hasFeedback
{...formItemLayout}
>
{getFieldDecorator('age', {
initialValue: item.age,
rules: [
{ required: true, message: '年龄未填写' },
{ validator: checkNumber },
],
})(
<Input type="text" />
)}
</FormItem>
<FormItem
label="住址:"
hasFeedback
{...formItemLayout}
>
{getFieldDecorator('address', {
initialValue: item.address,
rules: [
{ required: true, message: '不能为空' },
],
})(
<Input type="address" />
)}
</FormItem>
</Form>
</Modal>
)
}
UserModal.propTypes = {
visible: PropTypes.any,
form: PropTypes.object,
item: PropTypes.object,
onOk: PropTypes.func,
onCancel: PropTypes.func,
}
export default Form.create()(UserModal)
+65
View File
@@ -0,0 +1,65 @@
import React, {PropTypes} from 'react'
import {Form, Input, Button, Select} from 'antd'
import styles from './UserSearch.less'
const UserSearch = ({
field,
keyword,
onSearch,
onAdd,
form: {
getFieldDecorator,
validateFields,
getFieldsValue
}
}) => {
function handleSubmit(e) {
e.preventDefault()
validateFields((errors) => {
if (!!errors) {
return
}
onSearch(getFieldsValue())
})
}
return (
<div className={styles.normal}>
<div className={styles.search}>
<Form inline onSubmit={handleSubmit}>
<Form.Item>
{getFieldDecorator('field', {
initialValue: field || 'name'
})(
<Select>
<Select.Option value="name">名字</Select.Option>
<Select.Option value="address">地址</Select.Option>
</Select>
)}
</Form.Item>
<Form.Item hasFeedback>
{getFieldDecorator('keyword', {
initialValue: keyword || ''
})(<Input type="text"/>)}
</Form.Item>
<Button style={{
marginRight: '10px'
}} type="primary" htmlType="submit">搜索</Button>
</Form>
</div>
<div className={styles.create}>
<Button type="ghost" onClick={onAdd}>添加</Button>
</div>
</div>
)
}
UserSearch.propTypes = {
form: PropTypes.object.isRequired,
onSearch: PropTypes.func,
onAdd: PropTypes.func,
field: PropTypes.string,
keyword: PropTypes.string
}
export default Form.create()(UserSearch)
+8
View File
@@ -0,0 +1,8 @@
.normal {
display: flex;
margin-bottom: 20px;
}
.search {
flex: 1;
}
-24
View File
@@ -1,24 +0,0 @@
export default {
namespace: 'example',
state: {},
subscriptions: {
setup({ dispatch, history }) {
},
},
effects: {
*fetchRemote({ payload }, { call, put }) {
},
},
reducers: {
fetch(state, action) {
return { ...state, ...action.payload };
},
},
}
+144
View File
@@ -0,0 +1,144 @@
import {create, remove, update, query} from '../services/users'
import {parse} from 'qs'
export default {
namespace : 'users',
state : {
list: [],
loading: false,
total: null,
current: 1,
currentItem: {},
modalVisible: false,
modalType: 'create'
},
subscriptions : {
setup({dispatch, history}) {
history.listen(location => {
if (location.pathname === '/users') {
dispatch({type: 'query', payload: location.query})
}
})
}
},
effects : {
*query({
payload
}, {call, put}) {
yield put({type: 'showLoading'})
const {data} = yield call(query, parse(payload))
if (data) {
yield put({
type: 'querySuccess',
payload: {
list: data.data,
total: data.page.total,
current: data.page.current
}
})
}
},
* 'delete' ({
payload
}, {call, put}) {
yield put({type: 'showLoading'})
const {data} = yield call(remove, {id: payload})if (data && data.success) {
yield put({type: 'deleteSuccess', payload})
}
},
*create({
payload
}, {call, put}) {
yield put({type: 'hideModal'})
yield put({type: 'showLoading'})
const {data} = yield call(create, payload)
if (data && data.success) {
yield put({type: 'createSuccess', payload})
}
},
*update({
payload
}, {select, call, put}) {
yield put({type: 'hideModal'})
yield put({type: 'showLoading'})
const id = yield select(({users}) => users.currentItem.id)
const newUser = {
...payload,
id
}
const {data} = yield call(update, newUser)
if (data && data.success) {
yield put({type: 'updateSuccess', payload: newUser})
}
}
},
reducers : {
showLoading(state) {
return {
...state,
loading: true
}
},
createSuccess(state, action) {
const newUser = action.payload
return {
...state,
list: [
newUser, ...state.list
],
loading: false
}
},
deleteSuccess(state, action) {
const id = action.payload
const newList = state.list.filter(user => user.id !== id)
return {
...state,
list: newList,
loading: false
}
},
updateSuccess(state, action) {
const updateUser = action.payload
const newList = state.list.map(user => {
if (user.id === updateUser.id) {
return {
...user,
...updateUser
}
}
return user
})
return {
...state,
list: newList,
loading: false
}
},
querySuccess(state, action) {
return {
...state,
...action.payload,
loading: false
}
},
showModal(state, action) {
return {
...state,
...action.payload,
modalVisible: true
}
},
hideModal(state) {
return {
...state,
modalVisible: false
}
}
}
}