今天弄了半天這個上傳組件結合表單組件的問題。react
這個上傳文件列表,若是是當前正在修改或者上傳成功,固然是能夠正常工做的,可是想要增長一個功能:
下次打開 Modal 時,表單字段中的上傳文件字段,能夠默認回顯文件列表(該列表是 Upload 組件內部實現的)。後端
因爲該 Upload 組件已經使用 Form 組件統一代理,因此須要經過 initialValue
字段進行初始值的設定(若是有的話)。固然也能夠不代理,單獨處理,但這樣最終提交數據仍是要再增長上去,並且還須要自行實現必填項的校驗。antd
此時既要照顧到 Upload 自身所需字段(特別是 uid 字段),又要迎合最終向後端提交附件時方便新老文件統一處理(經過 JSON.stringify() 的第二個過濾器參數進行處理)。app
import React from 'react'; import { message, Modal, Row, Col, Form, Select, Button, Input, Spin, Radio, DatePicker, Upload, Icon } from 'antd'; import moment from 'moment'; const FormItem = Form.Item; const Option = Select.Option; const TextArea = Input.TextArea; class MakeBill extends React.Component { state = { loading: false, disabledOk: false, confirmLoading: false, fileList: [], } handleSubmit = () => { this.props.form.validateFieldsAndScroll((err, values) => { if (!err) { this.setState({ loading: true, confirmLoading: true }); const submitInfo = JSON.parse(JSON.stringify(values, (key, value) => { if (key === 'pay_time') { return moment(value).format('YYYY-MM-DD'); } else if (key === 'attachments') { return value.map(f => ({ ...f.saveParams, type: 1 })); } return value; })); commerceApi.saveInvoiceOfFinance(submitInfo).then(result => { message.success('提交成功!'); this.props.form.resetFields(); this.props.onClose('refresh'); this.setState({ loading: false, confirmLoading: false }); }, () => { this.setState({ loading: false, confirmLoading: false }); }); } }); } closeForm = () => { this.props.form.resetFields(); this.props.onClose(); } getContactInfo = (id) => { commerceApi.getContactDetail({ id, isedit: true }, (result) => { this.setState({ relationContactInfo: result }); }); } render() { let { loading, disabledOk, confirmLoading, fileList } = this.state; let { form, show, incomeId, busId, details } = this.props; let _this = this; const { getFieldDecorator } = form; if (!Object.keys(details).length) { // 若是沒有歷史數據,則須要提供一些默認值 details['invoice_type'] = 0; } const formItemLayout = { labelCol: { sm: { span: 8 }, }, wrapperCol: { sm: { span: 16 }, }, }; const fullLayout = { labelCol: { sm: { span: 4 }, }, wrapperCol: { sm: { span: 20 }, }, }; /** * 上傳組件操做思路: * 當文件大於10M時,在調接口前,就提示報錯,而且調用onRemove移除 */ const props = { accept: ".rar,.zip,.doc,.docx,.pdf,.jpg,.png", name: 'file', action: '/cmp/crm/upload', beforeUpload(file) { const isLt10M = file.size / 1024 / 1024 <= 10; if (!isLt10M) { message.error("文件大小限制在10M如下!"); this.onRemove(file); return false; } }, onRemove(file) { _this.setState({ fileList: fileList.filter(item => item.name !== file.name) }, () => { _this.props.form.setFieldsValue({ fileList: fileList }); }); }, onChange(info) { // 上傳中、完成、失敗都會調用這個函數 let curFileList = info.fileList; curFileList = curFileList.map((file) => { if (file.response) { // 這裏上傳組件回調的數據,有些是提供給上傳組件自身使用的,因此不能不要 // 而須要向後端提交的數據這裏提早封裝起來,以方便最終的提交 let saveParams = {}; saveParams["filename"] = file.response.data[0].filename; saveParams["url"] = file.response.data[0].url; saveParams["size"] = file.response.data[0].size; file["saveParams"] = saveParams; file['url'] = file.response.data[0].url; } return file; }); curFileList = curFileList.filter(file => { if (file.size / 1024 / 1024 <= 10) { if (file.response) { return file.response.code === 0; } return true; } else { return false; } }); _this.setState({ fileList: curFileList }); }, // fileList: fileList, // 上傳組件已使用Form進行代理,因此不要再直接設置 }; return ( <div> { show ? <Modal wrapClassName="vertical-center-modal" className="company-form-modal" title="申請發票" visible={show} width={750} maskClosable={false} onCancel={this.closeForm} footer={[ <Button key="cancel" onClick={this.closeForm}>取消</Button>, <Button key="confirm" type="primary" loading={confirmLoading} disabled={disabledOk} onClick={this.handleSubmit}>肯定</Button> ]}> <Spin spinning={loading}> <div className="modal-content-wrap"> <Form> <Row> <FormItem {...fullLayout} label="證實材料"> {getFieldDecorator('attachments', { initialValue: (details.attachments || []).map(f => ({ // 爲了提供給上傳組件回顯 uid: f.id, // 這是上傳組件規定的文件惟一標識,內部會提供給Form以便正常渲染回顯列表 name: f.filename, status: 'done', url: f.url, // 爲了迎合最終向後端提交附件時方便新老文件統一處理 saveParams: { filename: f.filename, url: f.url, size: f.size } })), rules: [{ required: true, message: '請上傳證實材料' }], valuePropName: 'fileList', getValueFromEvent: (e) => { if (Array.isArray(e)) { return e; } return e && e.fileList; } })( <Upload {...props}> <Button> <Icon type="upload" /> 上傳文件 </Button> <p className="upload-desc">支持擴展名:.rar .zip .doc .pdf .jpg .png</p> <p className="upload-desc">材料包括:合同,驗收單,訂單截圖,打款記錄</p> </Upload> )} </FormItem> </Row> </Form> </div> </Spin> </Modal> : null } </div> ) } } export default Form.create()(MakeBill);