項目使用的是ant-pro模板
有個可編輯表格的需求,效果圖如下

ant-pro提供了EditableProTable 組件,我使用的是這種
https://procomponents.ant.design/components/editable-table

不過這里展示的默認都是input輸入框,我這里是需要下拉框和上傳組件
下拉框可以直接用select組件,不過upload需要自己封裝一下
因為這個可編輯表格獲取數據是根據綁定的value值,改變數據是onChange事件.upload組件沒有value值,對應的是defaultFileList, 而onChange事件返回的是file.fileList.
我們可以對這兩個屬性重新封裝,改成需要的格式
可編輯表格代碼
EditZTTable.tsx
import React, { useState } from 'react' import { Row, Col, Select, Button } from 'antd' import type { ProColumns } from '@ant-design/pro-table' import { EditableProTable } from '@ant-design/pro-table' import ComUpload from '@/components/ComUpload' const { Option } = Select type DataSourceType = { id: React.Key title?: string role?: string state?: string created_at?: string [propName: string]: any } const EditZTTable: React.FC = () => { // 表格數據 const defaultData: DataSourceType[] = [ { id: 624748504, title: '活動名稱一', role: '這個活動真好玩', state: 'open', created_at: '2020-05-26T09:42:56Z', // attachments: [ // { // uid: '1', // name: 'xxx.png', // status: 'done', // response: 'Server Error 500', // custom error message to show // url: 'http://www.baidu.com/xxx.png', // } // ] }, { id: 624691229, title: '活動名稱二', role: '這個活動真好玩', state: 'closed', created_at: '2020-05-26T08:19:22Z', attachments: [ { uid: '1', name: 'xxx.png', status: 'done', response: 'Server Error 500', // custom error message to show url: 'http://www.baidu.com/xxx.png', }, { uid: '2', name: 'yyy.png', status: 'done', url: 'http://www.baidu.com/yyy.png', } ] }, ] // 設置選中的表格key const [editableKeys, setEditableRowKeys] = useState<React.Key[]>(() => defaultData.map((item) => item.id), ) // 設置表格數據 const [dataSource, setDataSource] = useState<DataSourceType[]>(() => defaultData) const fileColumns: ProColumns<DataSourceType>[] = [ { title: '序號', dataIndex: 'num', width: 55, editable: false, render: (_, record, index) => ( <span>{index + 1}</span> ) }, { title: '附件類型', dataIndex: 'businessType', renderFormItem: () => { return <Select showSearch> <Option value="jack">Jack</Option> <Option value="lucy">Lucy</Option> </Select> }, formItemProps: { rules: [ { required: true, whitespace: true, message: '此項是必填項', }, ], }, }, { title: '附件上傳', width: '50%', dataIndex: 'attachments', renderFormItem: () => (<ComUpload />), }, { title: '操作', valueType: 'option', width: 60, render: (text, record) => [ <a key="delete" onClick={() => { setDataSource(dataSource.filter((item) => item.id !== record.id)) }} > 刪除 </a>, ], }, ] return ( <> <Row> <Col span={24}> <EditableProTable<DataSourceType> columns={columns} rowKey="id" value={dataSource} recordCreatorProps={{ newRecordType: 'dataSource', record: () => ({ id: Date.now(), }), }} editable={{ type: 'multiple', editableKeys, actionRender: (row, config, defaultDoms) => { return [defaultDoms.delete] }, onValuesChange: (record, recordList) => { setDataSource(recordList) }, onChange: (editableKeyss, editableRows: DataSourceType[]) => { setEditableRowKeys(editableKeyss) setDataSource(editableRows) }, }} /> </Col> </Row> <Row> <Col span={24} style={{ textAlign: 'right' }}> <Button style={{ margin: '15px 8px 0' }} onClick={ () => { }}>重置</Button> <Button type="primary" onClick={onSave}>保存</Button> </Col> </Row> </> ) } export default EditZTTable
upload組件封裝
ComUpload.tsx
import React from 'react' import { Button, Upload } from 'antd' import { UploadOutlined } from '@ant-design/icons' type comuploadProps = { value?: { key: string; label: string; }[] onChange?: () => void } const ComUpload: React.FC<comuploadProps> = (props: comuploadProps) => { const attachments = props.value const { onChange } = props const action = `${URL_PREFIX}/file/upload` const changeFile = ({ file, fileList }) => { if (file.status !== 'uploading') { // console.log(file, fileList) const arr: any[] = [] fileList.forEach((item: any) => { if (item.response) { arr.push({ name: item.name, id: item.response.data }) } else { arr.push(item) } }) onChange(arr) } } return ( <Upload action={action} onChange={changeFile} defaultFileList={attachments} > <Button icon={<UploadOutlined />} type="text" /> </Upload> ) } export default ComUpload