• Antd Upload 和 Antd Form 结合的踩坑记录


    今天弄了半天这个上传组件结合表单组件的问题。

    这个上传文件列表,如果是当前正在修改或者上传成功,当然是可以正常工作的,但是想要增加一个功能:
    下次打开 Modal 时,表单字段中的上传文件字段,可以默认回显文件列表(该列表是 Upload 组件内部实现的)。

    由于该 Upload 组件已经使用 Form 组件统一代理,所以需要通过 initialValue 字段进行初始值的设定(如果有的话)。当然也可以不代理,单独处理,但这样最终提交数据还是要再增加上去,而且还需要自行实现必填项的校验。

    此时既要照顾到 Upload 自身所需字段(特别是 uid 字段),又要迎合最终向后端提交附件时方便新老文件统一处理(通过 JSON.stringify() 的第二个过滤器参数进行处理)。

    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);
    
    
  • 相关阅读:
    SQL Azure (17) SQL Azure V12
    Microsoft Azure News(5) Azure新DV2系列虚拟机上线
    Azure Redis Cache (3) 在Windows 环境下使用Redis Benchmark
    Azure PowerShell (11) 使用自定义虚拟机镜像模板,创建Azure虚拟机并绑定公网IP(VIP)和内网IP(DIP)
    Windows Azure Virtual Machine (31) 迁移Azure虚拟机
    Windows Azure Web Site (16) Azure Web Site HTTPS
    Azure China (12) 域名备案问题
    一分钟快速入门openstack
    管理员必备的Linux系统监控工具
    Keepalived+Nginx实现高可用和双主节点负载均衡
  • 原文地址:https://www.cnblogs.com/nicholaswang/p/10799782.html
Copyright © 2020-2023  润新知