後臺管理系統經常使用到表單的增刪改,這裏也作了個封裝css
例如:user/index.jsreact
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.jsios
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.scssajax
@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.jsjson
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.jsaxios
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); } }) }); } }
效果api