后台管理系统常用到表单的增删改,这里也做了个封装
例如:user/index.js
import React from \'react\' import { Card, Button, Table, Form, Input, Checkbox,Select,Radio, Icon, message, Modal, DatePicker } from \'antd\' import axios from \'../../axios/index\' import Utils from \'../../utils/utils\' import ETable from \'../../components/ETable/index\' import Moment from \'moment\' const FormItem = Form.Item; const Option = Select.Option; const RadioGroup = Radio.Group; export default class User extends React.Component{ state = { list:[] } params = { page:1 } requestList = ()=>{ axios.ajax({ url:\'/table/list1\', data:{ params:{ page:this.params.page } } }).then((res)=>{ let _this = this; this.setState({ list:res.result.list.map((item,index)=>{ item.key=index return item; }), pagination:Utils.pagination(res,(current)=>{ _this.params.page = current; _this.requestList(); }) }) }) } componentDidMount(){ this.requestList(); } // 操作员工 handleOperator = (type)=>{ let item = this.state.selectedItem; if(type ==\'create\'){ this.setState({ title:\'创建员工\', isVisible:true, type }) }else if(type=="edit" || type==\'detail\'){ if(!item){ Modal.info({ title: \'信息\', content: \'请选择一个用户\' }) return; } this.setState({ title:type==\'edit\'?\'编辑用户\':\'查看详情\', isVisible:true, userInfo:item, type }) }else if(type=="delete"){ if(!item){ Modal.info({ title: \'信息\', content: \'请选择一个用户\' }) return; } Utils.ui.confirm({ text:\'确定要删除此用户吗?\', onOk:()=>{ axios.ajax({ url:\'/user/delete\', data:{ params:{ id:item.id } } }).then((res)=>{ if(res.code ==0){ this.setState({ isVisible:false }) this.requestList(); } }) } }) } } handleSubmit = ()=>{ let type = this.state.type; let data = this.userForm.props.form.getFieldsValue(); axios.ajax({ url:type == \'create\'?\'/user/add\':\'/user/edit\', data:{ params:{ ...data } } }).then((res)=>{ if(res.code ==0){ this.setState({ isVisible:false }) this.requestList(); } }) } render(){ const columns = [{ title: \'id\', dataIndex: \'id\' }, { title: \'用户名\', dataIndex: \'username\' }, { title: \'性别\', dataIndex: \'sex\', render(sex){ return sex ==1 ?\'男\':\'女\' } }, { title: \'状态\', dataIndex: \'state\', render(state){ let config = { \'1\':\'咸鱼一条\', \'2\':\'风华浪子\', \'3\':\'北大才子一枚\', \'4\':\'百度FE\', \'5\':\'创业者\' } return config[state]; } },{ title: \'爱好\', dataIndex: \'interest\', render(interest){ let config = { \'1\':\'游泳\', \'2\':\'打篮球\', \'3\':\'踢足球\', \'4\':\'跑步\', \'5\':\'爬山\', \'6\':\'骑行\', \'7\':\'桌球\', \'8\':\'麦霸\' } return config[interest]; } },{ title: \'婚姻\', dataIndex: \'isMarried\', render(isMarried){ return isMarried?\'已婚\':\'未婚\' } },{ title: \'生日\', dataIndex: \'birthday\' },{ title: \'联系地址\', dataIndex: \'address\' },{ title: \'早起时间\', dataIndex: \'time\' } ]; return ( <div> <Card> <Form layout="inline"> <FormItem> <Input placeholder="请输入用户名"/> </FormItem> <FormItem> <Input type="password" placeholder="请输入密码"/> </FormItem> <FormItem> <Button type="primary">登 录</Button> </FormItem> </Form> </Card> <Card style={{marginTop:10}}> <Button type="primary" icon="plus" onClick={()=>this.handleOperator(\'create\')}>创建员工</Button> <Button icon="edit" onClick={()=>this.handleOperator(\'edit\')}>编辑员工</Button> <Button onClick={()=>this.handleOperator(\'detail\')}>员工详情</Button> <Button type="danger" icon="delete" onClick={()=>this.handleOperator(\'delete\')}>删除员工</Button> </Card> <div className="content-wrap"> <ETable columns={columns} updateSelectedItem={Utils.updateSelectedItem.bind(this)} selectedRowKeys={this.state.selectedRowKeys} dataSource={this.state.list} pagination={this.state.pagination} /> </div> <Modal title={this.state.title} visible={this.state.isVisible} onOk={this.handleSubmit} width={800} onCancel={()=>{ this.userForm.props.form.resetFields(); this.setState({ isVisible:false, userInfo:\'\' }) }} > <UserForm userInfo={this.state.userInfo} type={this.state.type} wrappedComponentRef={(inst) => this.userForm = inst }/> </Modal> </div> ); } } class UserForm extends React.Component{ getState = (state)=>{ return { \'1\':\'咸鱼一条\', \'2\':\'风华浪子\', \'3\':\'北大才子一枚\', \'4\':\'百度FE\', \'5\':\'创业者\' }[state] } render(){ const { getFieldDecorator } = this.props.form; const formItemLayout = { labelCol: {span: 5}, wrapperCol: {span: 16} }; const userInfo = this.props.userInfo || {}; const type = this.props.type; return ( <Form layout="horizontal"> <FormItem label="姓名" {...formItemLayout}> { userInfo && type==\'detail\'?userInfo.username: getFieldDecorator(\'user_name\',{ initialValue:userInfo.username })( <Input type="text" placeholder="请输入姓名"/> ) } </FormItem> <FormItem label="性别" {...formItemLayout}> { userInfo && type==\'detail\'?userInfo.sex==1?\'男\':\'女\': getFieldDecorator(\'sex\',{ initialValue:userInfo.sex })( <RadioGroup> <Radio value={1}>男</Radio> <Radio value={2}>女</Radio> </RadioGroup> )} </FormItem> <FormItem label="状态" {...formItemLayout}> { userInfo && type==\'detail\'?this.getState(userInfo.state): getFieldDecorator(\'state\',{ initialValue:userInfo.state })( <Select> <Option value={1}>咸鱼一条</Option> <Option value={2}>风华浪子</Option> <Option value={3}>北大才子一枚</Option> <Option value={4}>百度FE</Option> <Option value={5}>创业者</Option> </Select> )} </FormItem> <FormItem label="生日" {...formItemLayout}> { userInfo && type==\'detail\'?userInfo.birthday: getFieldDecorator(\'birthday\',{ initialValue:Moment(userInfo.birthday) })( <DatePicker /> )} </FormItem> <FormItem label="联系地址" {...formItemLayout}> { userInfo && type==\'detail\'?userInfo.address: getFieldDecorator(\'address\',{ initialValue:userInfo.address })( <Input.TextArea rows={3} placeholder="请输入联系地址"/> )} </FormItem> </Form> ); } } UserForm = Form.create({})(UserForm);
ETable/index.js
import React from \'react\' import Utils from \'../../utils/utils\' import {Table} from \'antd\' import "./index.less" export default class ETable extends React.Component { state = {} //处理行点击事件 onRowClick = (record, index) => { let rowSelection = this.props.rowSelection; if(rowSelection == \'checkbox\'){ let selectedRowKeys = this.props.selectedRowKeys; let selectedIds = this.props.selectedIds; let selectedItem = this.props.selectedItem || []; if (selectedIds) { const i = selectedIds.indexOf(record.id); if (i == -1) {//避免重复添加 selectedIds.push(record.id) selectedRowKeys.push(index); selectedItem.push(record); }else{ selectedIds.splice(i,1); selectedRowKeys.splice(i,1); selectedItem.splice(i,1); } } else { selectedIds = [record.id]; selectedRowKeys = [index] selectedItem = [record]; } this.props.updateSelectedItem(selectedRowKeys,selectedItem || {},selectedIds); }else{ let selectKey = [index]; const selectedRowKeys = this.props.selectedRowKeys; if (selectedRowKeys && selectedRowKeys[0] == index){ return; } this.props.updateSelectedItem(selectKey,record || {}); } }; // 选择框变更 onSelectChange = (selectedRowKeys, selectedRows) => { let rowSelection = this.props.rowSelection; const selectedIds = []; if(rowSelection == \'checkbox\'){ selectedRows.map((item)=>{ selectedIds.push(item.id); }); this.setState({ selectedRowKeys, selectedIds:selectedIds, selectedItem: selectedRows[0] }); } this.props.updateSelectedItem(selectedRowKeys,selectedRows[0],selectedIds); }; onSelectAll = (selected, selectedRows, changeRows) => { let selectedIds = []; let selectKey = []; selectedRows.forEach((item,i)=> { selectedIds.push(item.id); selectKey.push(i); }); this.props.updateSelectedItem(selectKey,selectedRows[0] || {},selectedIds); } getOptions = () => { let p = this.props; const name_list = { "订单编号":170, "车辆编号":80, "手机号码":96, "用户姓名":70, "密码":70, "运维区域":300, "车型":42, "故障编号":76, "代理商编码":97, "角色ID":64 }; if (p.columns && p.columns.length > 0) { p.columns.forEach((item)=> { //开始/结束 时间 if(!item.title){ return } if(!item.width){ if(item.title.indexOf("时间") > -1 && item.title.indexOf("持续时间") < 0){ item.width = 132 }else if(item.title.indexOf("图片") > -1){ item.width = 86 }else if(item.title.indexOf("权限") > -1 || item.title.indexOf("负责城市") > -1){ item.width = \'40%\'; item.className = "text-left"; }else{ if(name_list[item.title]){ item.width = name_list[item.title]; } } } item.bordered = true; }); } const { selectedRowKeys } = this.props; const rowSelection = { type: \'radio\', selectedRowKeys, onChange: this.onSelectChange, onSelect:(record, selected, selectedRows)=>{ console.log(\'...\') }, onSelectAll:this.onSelectAll }; let row_selection = this.props.rowSelection; // 当属性未false或者null时,说明没有单选或者复选列 if(row_selection===false || row_selection === null){ row_selection = false; }else if(row_selection == \'checkbox\'){ //设置类型未复选框 rowSelection.type = \'checkbox\'; }else{ //默认未单选 row_selection = \'radio\'; } return <Table className="card-wrap page-table" bordered {...this.props} rowSelection={row_selection?rowSelection:null} onRow={(record,index) => ({ onClick: ()=>{ if(!row_selection){ return; } this.onRowClick(record,index) } })} /> }; render = () => { return ( <div> {this.getOptions()} </div> ) } }
ETable/index.scss
@import \'../../style/default\'; .ant-table{ &-thead > tr > th, &-tbody > tr > td{ padding:14px 6px; text-align:center; } .ant-table-selection-column{ min-width:42px!important; width:42px!important;; } .text-center { text-align: center; } .text-left { text-align: left; } &.ant-table-middle{ &-thead > tr > th, &-tbody > tr > td{ padding:10px 6px; } } &.ant-table-small{ &-thead > tr > th, &-tbody > tr > td{ padding:8px 6px; } } } .ant-table-pagination{ padding:0 20px; }
utils/utils.js
import React from \'react\'; import { Select } from \'antd\' const Option = Select.Option; export default { formateDate(time){ if(!time)return \'\'; let date = new Date(time); return date.getFullYear()+\'-\'+(date.getMonth()+1)+\'-\'+date.getDate()+\' \'+date.getHours()+\':\'+date.getMinutes()+\':\'+date.getSeconds(); }, pagination(data,callback){ return { onChange:(current)=>{ callback(current) }, current:data.result.page, pageSize:data.result.page_size, total: data.result.total_count, showTotal:()=>{ return `共${data.result.total_count}条` }, showQuickJumper:true } }, // 格式化金额,单位:分(eg:430分=4.30元) formatFee(fee, suffix = \'\') { if (!fee) { return 0; } return Number(fee).toFixed(2) + suffix; }, // 格式化公里(eg:3000 = 3公里) formatMileage(mileage, text) { if (!mileage) { return 0; } if (mileage >= 1000) { text = text || " km"; return Math.floor(mileage / 100) / 10 + text; } else { text = text || " m"; return mileage + text; } }, // 隐藏手机号中间4位 formatPhone(phone) { phone += \'\'; return phone.replace(/(\d{3})\d*(\d{4})/g, \'$1***$2\') }, // 隐藏身份证号中11位 formatIdentity(number) { number += \'\'; return number.replace(/(\d{3})\d*(\d{4})/g, \'$1***********$2\') }, getOptionList(data){ if(!data){ return []; } let options = [] //[<Option value="0" key="all_key">全部</Option>]; data.map((item)=>{ options.push(<Option value={item.id} key={item.id}>{item.name}</Option>) }) return options; }, /** * ETable 行点击通用函数 * @param {*选中行的索引} selectedRowKeys * @param {*选中行对象} selectedItem */ updateSelectedItem(selectedRowKeys, selectedRows, selectedIds) { if (selectedIds) { this.setState({ selectedRowKeys, selectedIds: selectedIds, selectedItem: selectedRows }) } else { this.setState({ selectedRowKeys, selectedItem: selectedRows }) } }, }
axios/index.js
import JsonP from \'jsonp\' import axios from \'axios\' import { Modal } from \'antd\' export default class Axios { static jsonp(options) { return new Promise((resolve, reject) => { JsonP(options.url, { param: \'callback\' }, function (err, response) { if (response.status == \'success\') { resolve(response); } else { reject(response.messsage); } }) }) } static ajax(options){ let loading; if (options.data && options.data.isShowLoading !== false){ loading = document.getElementById(\'ajaxLoading\'); loading.style.display = \'block\'; } let baseApi = \'https://www.easy-mock.com/mock/5a7278e28d0c633b9c4adbd7/api\'; return new Promise((resolve,reject)=>{ axios({ url:options.url, method:\'get\', baseURL:baseApi, timeout:5000, params: (options.data && options.data.params) || \'\' }).then((response)=>{ if (options.data && options.data.isShowLoading !== false) { loading = document.getElementById(\'ajaxLoading\'); loading.style.display = \'none\'; } if (response.status == \'200\'){ let res = response.data; if (res.code == \'0\'){ resolve(res); }else{ Modal.info({ title:"提示", content:res.msg }) } }else{ reject(response.data); } }) }); } }
效果