基于react + ant实现可编辑表格,可分页,可批量删除,保存等功能

在这里插入图片描述
最近因为工作需要,要基于react-ant做一个可编辑表格,具体功能如图所示,带分页可新增,删除,批量删除,保存等功能,
可编辑表格是依照官方文档实现的,具体参考https://3x.ant.design/components/table-cn/#components-table-demo-edit-cell;

/* eslint-disable no-duplicate-case */
/* eslint-disable no-const-assign */
/* eslint-disable react/jsx-no-duplicate-props */
/* eslint-disable react/prop-types */
/* eslint-disable no-undef */
/* eslint-disable no-unused-vars */
import React, { Component } from 'react';
// import PropTypes from 'prop-types';
import './unit-cost.less';
import {Table, Input, Button, Modal, Form, InputNumber } from 'antd';
import * as getUnitCost from '../../../actions/getUnitCost';
import { toast } from '../../toast';
const EditableContext = React.createContext();

const EditableRow = ({ form, index, ...props }) => (
   <EditableContext.Provider value={form}>
      <tr {...props} />
   </EditableContext.Provider>
);

const EditableFormRow = Form.create()(EditableRow);

class EditableCell extends React.Component {
   state = {
      editing: false,
   };
 
   toggleEdit = () => {
      const editing = !this.state.editing;
      this.setState({ editing }, () => {
         if(editing) {
            this.input.focus();
         }
      });
   };
 
   save = e => {
      const { record, handleSave } = this.props;
      this.form.validateFields((error, values) => {
         if(error && error[e.currentTarget.id]) {
            return;
         }
         this.toggleEdit();
         handleSave({ ...record, ...values });
      });
   };
  
   renderCell = form => {
      this.form = form;
      const { children, dataIndex, record, title } = this.props;
      const { editing } = this.state;
      return editing ? (
         <Form.Item style={{ margin: 0 }}>
            {form.getFieldDecorator(dataIndex, {
            //为可编辑表格设定规则,下面注释掉的是非空
               // rules: [
               //    {
               //       required: new RegExp(),
               //       message: `${title} is required.`,
               //    },
               // ],
               initialValue: record[dataIndex],
            })(<InputNumber className = 'number' ref={node => (this.input = node)} onChange={this.onChange} onPressEnter={this.save} onBlur={this.save} min={0}/>)}
         </Form.Item>
      ) : (
         <div
            className="editable-cell-value-wrap"
            style={{ paddingRight: 24 }}
            onClick={this.toggleEdit}
         >
            {children}
         </div>
      );
   };
  
   render() {
      const {
         editable,
         dataIndex,
         title,
         record,
         index,
         handleSave,
         children,
         ...restProps
      } = this.props;
      return (
         <td {...restProps}>
            {editable ? (
               <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
            ) : (
               children
            )}
         </td>
      );
   }
}

class UnitCost extends Component {
   constructor(props) {
      super(props);
      this.columns = [
         {
            title: '机组容量等级',
            dataIndex: 'title',
            width: '500',
         },
         {
            title: '20万千瓦级以下',
            dataIndex: 'January',
          
            width: '150',
            editable: true,
            children: [
               {
                  title: '出力(MW)',
                  dataIndex: 'costlt20',
                  editable: true,
                 
               },
               {
                  title: '边际成本(元/兆瓦时)',
                  dataIndex: 'pricelt20',
                  editable: true,
                 
                 
               }
            ],
          
         },
         {
            title: '20万千瓦级',
            dataIndex: 'February',
            width: '150',
            editable: true,
            children: [
               {
                  title: '出力(MW)',
                  dataIndex: 'costeq20',
                  editable: true,
                 
               },
               {
                  title: '边际成本(元/兆瓦时)',
                  dataIndex: 'priceeq20',
                  editable: true,
                  
               }
            ],
         },
         {
            title: '30万千瓦级',
            dataIndex: 'March',
            width: '150',
            editable: true,
            children: [
               {
                  title: '出力(MW)',
                  dataIndex: 'costeq30',
                  editable: true,
                 
               },
               {
                  title: '边际成本(元/兆瓦时)',
                  dataIndex: 'priceeq30',
                  editable: true,
                
               }
            ],
         },
         {
            title: '60万千瓦级',
            dataIndex: 'April',
           
            width: '150',
            editable: true,
            children: [
               {
                  title: '出力(MW)',
                  dataIndex: 'costeq60',
                  editable: true,
                
               },
               {
                  title: '边际成本(元/兆瓦时)',
                  dataIndex: 'priceeq60',
                  editable: true,
                 
               }
            ],
         },
         {
            title: '100万千瓦级',
            dataIndex: 'May',
            width: '150',
            editable: true,
            children: [
               {
                  title: '出力(MW)',
                  dataIndex: 'costeq100',
                  editable: true,
                  
               },
               {
                  title: '边际成本(元/兆瓦时)',
                  dataIndex: 'priceeq100',
                  editable: true,
                 
               }
            ],
         }
      ];
      this.state = {
         dataSource: [],
         count: 0,
         record: [],
         selectedRowKeys: [],
         visible: false,
         currentPage: 1, //当前页
         pageSize: 10,   //一页多少条数据
         total: 0    //数据总数
      };
   }

   componentWillMount = () => {
      this.getUnitCostData();
   }

   //获取表格数据
   getUnitCostData = () => {
      getUnitCost.getUnitCost((json) => {
         if(json) {
            let keys = 0;
            let data = [];
            if(json.length > 0) {
               json.map(((item, index)=> { 
                  data.push(Object.assign(
                     {}, item, {title: '机组边际成本'}, {key: index}
                  ));
               }));
               let key = [];
               console.log(data);
               for(let i = 0; i < data.length; i++) {
                  if(data[i].key) {
                     key.push(data[i].key);
                  } else {
                     key = [0];
                  }
               }
               keys = (Math.max(...key));
               //为保证key唯一,取出后台数据中最大的key
               this.setState({
                  dataSource: data,
                  count: keys + 1,
                  total: data.length
               });
            } else {
               this.setState({
                  dataSource: json,
                  count: keys,
                  total: 0
               });
            }
         }
      });
   }

   handleSave = row => {
      const newData = [...this.state.dataSource];
      const index = newData.findIndex(item => row.key === item.key);
      const item = newData[index];
      newData.splice(index, 1, {
         ...item,
         ...row,
      });
      this.setState({ dataSource: newData });  
   };

   //保存
   save = () => {
      let datalist = this.state.dataSource;
      //这里可以加一些数据校验
        getUnitCost.setUnitCost(datalist, (json) => {
            if(json) {
               if(json && json == 1) {
                  toast({ type: 'success', message: '保存成功' });
                  this.getUnitCostData();
               } else {
                  toast({ type: 'error', message: '保存失败' });
               }
            }
         });
      } 
   }
  
   
   //添加
   add = () => {
      const {dataSource, currentPage, pageSize, total, count } = this.state;

      //  总数为零:页数=1, 不为零:总数/每页的条数 = 整数,页数 = (总数/每页的条数+1) !=整数 页数 = (总数/每页的条数) 向上取整 
      let page = total == 0 ? currentPage : (total % pageSize == 0 ?  total / pageSize + 1 : Math.ceil(total / pageSize));
      this.setState({currentPage: page, total: total + 1}, () => {});
      
      const newData = {
         indexKey: count,
         title: '机组边际成本',
         costlt20: null,
         costeq20: null,
         costeq30: null,
         costeq60: null,
         costeq100: null,
         pricelt20: null,
         priceeq20: null,
         priceeq30: null,
         priceeq60: null,
         priceeq100: null,
         eq100: '100w千瓦级',
         eq20: '20w千瓦级',
         eq30: '30w千瓦级',
         eq60: '60w千瓦级',
         lt20: '20W千瓦级以下',
         key: count + 1,
      };
      this.setState({
         dataSource: [...dataSource, newData],
      });
   }
   deleteUnitCostData = (id) => {
      console.log(id);
      if(id.length == 0) {
         let newarr = this.state.dataSource.pop();
         this.setState({
            dataSource: this.state.dataSource,
            selectedRowKeys: []
         }); 
      } else {
         getUnitCost.deleteUnitCost(id, (json) => {
            if(json) {
               if(json && json == 1) {
                  toast({ type: 'success', message: '删除成功' });
                  this.getUnitCostData();
                  this.setState({ selectedRowKeys: []});
               } else {
                  toast({ type: 'error', message: '删除失败' });
               }
            }
         });
      }
   }; 
   //删除
   delete = ()=> {
      Modal.confirm({
         title: '确认删除?',
         okText: '确认',
         cancelText: '取消',
         onOk: () => {
            let datalist =  this.state.record;
            console.log(datalist);
            let id = [];
            for(let i = 0 ; i < datalist.length; i++) {
               if(datalist[i].id) {
                  let item = {
                     'id': datalist[i].id
                  };
                  id.push(item);
               }
            }
            this.deleteUnitCostData(id);
         }
      });
   }
   showModal = () => {
      this.setState({
         visible: true,
      });
   };

   onSelectChange = (selectedRowKeys, record) => {
      console.log(selectedRowKeys, record);
      this.setState({ selectedRowKeys, record});
   };
 
   //递归实现子级可编辑
   columnseditable = (data) => {
      let newdata = data.map(col => {
         if(!col.editable) {
            return {
               ...col,
            };
         }

         if(col.children) {
            col.children = this.columnseditable(col.children);
         }
      
         return {
            ...col,
            onCell: record => ({
               record,
               editable: col.editable,
               dataIndex: col.dataIndex,
               title: col.title,
               handleSave: this.handleSave,
            }),
         };
      });

      return newdata;
   }
 
   render() {
      const { dataSource, selectedRowKeys} = this.state;
      const components = {
         body: {
            row: EditableFormRow,
            cell: EditableCell,
         },
      };
      const rowSelection = {
         selectedRowKeys,
         onChange: this.onSelectChange,
      };
      const hasSelected = selectedRowKeys.length > 0;
      const columns = this.columnseditable(this.columns);
      return (
         <div className="unit_cost">
            <div className='title'>
               <span className="table-title">机组边际成本基本数据表</span>
               <span className="save">
                  <Button
                     type="primary"
                     style={{backgroundColor: '#40a9ff', border: 'none'}} 
                     onClick = {this.add}
                  >添加</Button></span>
               <span className="save">
                  <Button
                     type="primary"
                     onClick = {this.save}
                  >保存</Button></span>
               <span className="save">
                  <Button
                     style={{color: 'white'}} 
                     type="danger"
                     onClick = {this.delete}
                     disabled={!hasSelected}
                  >删除</Button></span>
               <Modal
                  title="Modal"
                  visible={this.state.visible}
               >
               </Modal>
            </div>
            <div className="table">
               <Table 
                  className="tables"
                  components={components}
                  rowClassName={() => 'editable-row'}
                  bordered
                  dataSource={dataSource}
                  // scroll={true}   //这个为true时,删除完所有数据后会有bug,目前解决办法就是变为false或者删除
                  columns={columns}
                  pagination={{
                     current: this.state.currentPage, 
                     pageSize: this.state.pageSize,
                     onChange: (page, pageSize) => this.setState({currentPage: page, pageSize: pageSize}),
                  }}
                  rowSelection={rowSelection}
                  rowKey={(record, index)=>record.id}
               />,
            </div>
         </div>
      );
   }
}
export default UnitCost;
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的实现示例: ```javascript import React from "react"; import { Table } from "antd"; const columns1 = [ { title: "姓名", dataIndex: "name", key: "name" }, { title: "年龄", dataIndex: "age", key: "age" }, { title: "住址", dataIndex: "address", key: "address" }, ]; const data1 = [ { key: "1", name: "John Brown", age: 32, address: "New York No. 1 Lake Park" }, { key: "2", name: "Jim Green", age: 42, address: "London No. 1 Lake Park" }, { key: "3", name: "Joe Black", age: 32, address: "Sidney No. 1 Lake Park" }, ]; const columns2 = [ { title: "科目", dataIndex: "subject", key: "subject" }, { title: "成绩", dataIndex: "score", key: "score" }, ]; const data2 = [ { key: "1", subject: "数学", score: 90 }, { key: "2", subject: "英语", score: 80 }, { key: "3", subject: "语文", score: 95 }, ]; const expandedRowRender = (record) => { const subTableData = [ { key: "1", subject: "数学", score: 90 }, { key: "2", subject: "英语", score: 80 }, { key: "3", subject: "语文", score: 95 }, ]; const subTableColumns = [ { title: "科目", dataIndex: "subject", key: "subject" }, { title: "成绩", dataIndex: "score", key: "score" }, ]; return <Table columns={subTableColumns} dataSource={subTableData} pagination={false} />; }; const TableWithNestedTable = () => { return ( <Table columns={columns1} dataSource={data1} pagination={false} expandedRowRender={expandedRowRender} /> ); }; export default TableWithNestedTable; ``` 首先,我们先定义两个表格的列和数据,分别为 `columns1` 和 `data1`,以及嵌套的表格的列和数据,分别为 `columns2` 和 `data2`。 然后,我们定义一个 `expandedRowRender` 函数,该函数接受一个参数 `record`,表示当前行的数据。在该函数中,我们返回一个嵌套的表格,该表格的列和数据为 `columns2` 和 `data2`。 最后,我们在主表格中添加 `expandedRowRender` 属性,并将其值设置为 `expandedRowRender` 函数,这样就可以实现表格嵌套两层表格的效果了。 注意,我们在嵌套的表格中将 `pagination` 属性设置为 `false`,以禁用分页功能

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值