
import { UploadFile, UploadFileStatus } from 'antd/lib/upload/interface'
import React from 'react';
import { RendererProps } from '../../../../../factory';
import { FormItem, FormControlProps, FormBaseControl } from '../../../../Form/Item'
import Upload, { UploadProps } from 'antd/lib/Upload';
import Modal from 'antd/lib/Modal';

import './LionFormImg.css';
import styled from 'styled-components';
import MSG from '../../../utils/msgsub';
import SparkMD5 from 'spark-md5';
import { Binary } from '@babel/types';

interface FileParams {
  upload_cmd: 'check_exist' | 'chunk_upload' | 'chunk_merge' | {} & string;
  // 接口标识 check_exist : 文件存在校验 chunk_upload： 分片接口chunk_merge： 分片合并
  upload_name: string; // 文件名
  upload_field: string; // 文件对应字段
  file_md5?: string; // 文件md5
  chunk_index?: number; // 文件当前分片索引
  chunk_total?: number; // 文件分片总数
  chunk_size?: number; // 分片大小
  type?: string; // 文件类型
  chunk_file?: Binary; // 文件分片
  file_type: string;
  preUploading: boolean;  //预处理
  chunksSize: number; // 上传文件分块的总个数
  currentChunks: number; // 当前上传的队列个数 当前还剩下多少个分片没上传
  uploadPercent: number;  // 上传率
  preUploadPercent: number; // 预处理率
  uploadRequest: boolean; // 上传请求，即进行第一个过程中
  uploaded: boolean; // 表示文件是否上传成功
  uploadParams: any;
  arrayBufferData: any;
  formItemName: string;
  fileSize: number;
}

// interface FileUploadState {
//   visible: boolean;
//   showfilelist: any;
//   params: string;
//   turtyfilelist: any;
//   loading: boolean;
//   preUploading: boolean;  //预处理
//   chunksSize: number; // 上传文件分块的总个数
//   currentChunks: number; // 当前上传的队列个数 当前还剩下多少个分片没上传
//   uploadPercent: number;  // 上传率
//   preUploadPercent: number; // 预处理率
//   uploadRequest: boolean; // 上传请求，即进行第一个过程中
//   uploaded: boolean; // 表示文件是否上传成功
//   uploading: boolean; // 上传中状态
//   uploadParams: any;
//   arrayBufferData: any;
//   formItemName: string;
//   current: any;
//   fileSize: number;
// }

interface IState {
  fileList: any;
  previewVisible: boolean;
  previewImage: string;
  previewTitle: string;
  showfileList: any;
  loading: boolean;
  errorImage: UploadFile;
  type: string;
  params: string;
  turtyfilelist: any[];
  init: boolean;
  formItemName: string;
  imgHeight: string;
}

function getBase64(file: any) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.readAsDataURL(file);
    reader.onload = () => resolve(reader.result);
    reader.onerror = error => reject(error);
  });
}

export interface LionInputImgSchema extends FormBaseControl {
  type: 'lion-input-img';
}

const Warpper = styled.div.attrs({
  marginTop: 'calc((1.875rem - 1.4285714286 *0.875rem)/2)'
})`
  .ant-upload-picture-card-wrapper{
    .ant-upload-list-picture-card{
      .ant-upload-select-picture-card{
        width:${(props: any) => props.width ? props.width : '60px'};
        height:${(props: any) => props.height ? props.height : '60px'};
        border-radius:4px;
        position:relative;
        display:inline-block;
        font-size:22px;
      }
      .ant-upload-list-picture-card-container{
        position:relative;
        display:inline-block;
        width:${(props: any) => props.width ? props.width : '68px'};
        height:${(props: any) => props.height ? props.height : '68px'};
        .ant-upload-list-item{
          border-radius:4px;
          border:0px;
          width:100%;
          height:${(props: any) => props.thumbMode === 'cover' ? '100%' : props.imgHeight};
          padding:${(props: any) => props.padding ? props.padding : '0px'};
          display: flex;
          align-items: center;
          justify-content: center;
          border:1px solid #d9d9d9;

          .ant-upload-list-item-info{
            position:relative;
            overflow:hidden;
            width:100%;
            height:100%;
            .ant-upload-span{
              width:100%;
              height:100%;
              img {
                position: ${(props: any) => props.thumbMode === 'w-full' || props.thumbMode === 'h-full' ? 'absolute' : 'static'};
                width: ${(props: any) => props.thumbMode === 'w-full' ? '100%' : (props.thumbMode === 'h-full' ? 'auto' : '100% !important')};
                object-fit:${(props: any) => props.thumbMode === 'w-full' || props.thumbMode === 'h-full' ? 'unset' : props.thumbMode};
                height: ${(props: any) => props.thumbMode === 'w-full' ? 'auto' : (props.thumbMode === 'h-full' ? '' : '100% !important')};
                transform:  ${(props: any) => props.thumbMode === 'w-full' || props.thumbMode === 'h-full' ? 'translate(-50%,-50%)' : 'translate(0,0)'};
                max-height:100%;
                top: ${(props: any) => props.thumbMode === 'w-full' || props.thumbMode === 'h-full' ? '50%' : '0'};
                left: ${(props: any) => props.thumbMode === 'w-full' || props.thumbMode === 'h-full' ? '50%' : '0'};
              }
            }
          }
        }
      }
    }
  }
`

export interface LionInputImgProps extends FormControlProps, Omit<LionInputImgSchema, 'type' | 'className' | 'descriptionClassName' | 'inputClassName'> { }

export class LionInputImg extends React.PureComponent<LionInputImgProps & UploadProps & RendererProps, FileParams & IState>{

  unHook: Function;

  state = {
    imgHeight: '100%',
    previewVisible: false,
    previewImage: '',
    previewTitle: '',
    errorImage: {
      url: 'data:image/png;base64,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',
      uid: 'error',
      status: 'error.png' as UploadFileStatus,
      name: 'error,'
    },
    fileList: [
    ],
    showfileList: [] as any,
    turtyfilelist: [] as any,
    loading: false,
    type: '',
    params: '',
    init: false,
    formItemName: '',
    preUploading: false,   //预处理
    chunksSize: 0,   // 上传文件分块的总个数
    currentChunks: 0,  // 当前上传的队列个数 当前还剩下多少个分片没上传
    uploadPercent: -1,  // 上传率
    preUploadPercent: -1, // 预处理率
    uploadRequest: false, // 上传请求，即进行第一个过程中
    uploaded: false, // 表示文件是否上传成功
    uploadParams: {} as any,
    arrayBufferData: [] as any,
    upload_cmd: 'check_exist',
    upload_name: '',
    upload_field: '',
    file_type: '',
    fileSize: 0
  };

  initFileData() {
    const { data, name, store } = this.props;
    let content;
    content = data[name as string] || store?.data[name as string];
    const { thumbRatio, env } = this.props;
    const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi || ''
    switch (thumbRatio) {
      case '4:3':
        this.setState({
          imgHeight: '75%'
        })
        break;
      case '16:9':
        this.setState({
          imgHeight: '56.25%'
        })
        break;
      case '1:1':
      default:
        this.setState({
          imgHeight: '100%'
        })
        break;

    }
    this.setState({
      formItemName: 'temp_' + name
    })
    // this.props.onBulkChange({ ['temp_' + name as string]: '' });
    if (content) {
      const { info, value } = content;

      if (info && value?.length && info.length !== 0) {
        const md5Map = value.split(',');
        let initialList: any = [];
        info.map((ele: any, idx: number) => {
          initialList.push({
            uid: md5Map[idx],
            status: 'done',
            name: ele.name || ele.fileName,
            // url: (baseUrl ? baseUrl : '') + (ele?.url ? ele?.url : ele.addr),
            preview: baseUrl + (ele?.url ? ele?.url : ele.addr),// 预览显示大图
            url: baseUrl + ele?.thumbnailAddr, // 显示缩略图地址
            size: ele?.size
          })
        })
        this.setState({
          loading: false,
          params: value,
          showfileList: [
            ...initialList
          ],
          turtyfilelist: [
            ...initialList
          ]
        });
        // this.props.onBulkChange({ ['temp_' + name as string]: value });
      }
    }
  }

  componentDidUpdate(prevProps: any, prevState: any) {
    const { data, name } = this.props;
    let content = data[name as string];
    if (content && (content !== prevProps.data[name as string])) {
      this.initFileData()
    }
  }

  componentDidMount() {
    this.initFileData()
  }


  handleCancel = () => this.setState({ previewVisible: false });

  handlePreview = async (file: any) => {
    if (file?.status === 'error') {
      return
    }
    if (!file.url && !file.preview) {
      file.preview = await getBase64(file.originFileObj);
    }

    this.setState({
      previewImage: file.preview || file.url,
      previewVisible: true,
      previewTitle: file.name || file.url.substring(file.url.lastIndexOf('/') + 1),
    });
  };

  handleChange = (file: any) => {
    const limitType = this.props.limitType;
    if (!limitType && file.file?.type?.startsWith('image/')) {
      this.setState({ type: 'image', fileList: file.fileList });
    } else if (limitType && limitType.split(',').some((_: any) => {
      return file.file?.type?.endsWith(_)
    })) {
      this.setState({ type: limitType, fileList: file.fileList });
    }

  };

  handleFile = (config: any) => {
    const { limitSize } = this.props;
    return new Promise((resolve: any, reject: any) => {
      let fileSize = config?.file?.size;
      let file = config?.file;
      if (limitSize && (fileSize > limitSize)) {
        MSG._error(`文件大小不能超过${limitSize}KB`);
        this.setState({
          loading: false
        })
        reject()
        return;
      }

      let blobSlice = File.prototype.slice; // 切片使用

      let _this = this;

      let chunkSize = 1024 * 1024 * 2;   // 切片每次2M
      let chunks = Math.ceil(file.size / chunkSize); // 切片数
      let currentChunk = 0; // 当前上传的chunk索引

      let file_type = config?.file?.type;
      let file_name = config?.file?.name;

      let spark = new SparkMD5.ArrayBuffer(); // 对arrayBuffer数据进行md5加密，产生一个md5字符串
      let chunkFileReader = new FileReader(); // 用于计算出每个chunkMd5
      let totalFileReader = new FileReader();  // 用于计算出总文件的fileMd5

      let params: any = { chunks: [], file: {} };  // 用于上传所有分片的md5信息

      let arrayBufferData: any = [];  // 用于存储每个chunk的arrayBuffer对象,用于分片上传使用

      params.file.fileName = file.name;
      params.file.fileSize = file.size;

      totalFileReader.readAsArrayBuffer(file);

      totalFileReader.onload = function (e: any) {
        // 对整个totalFile生成md5
        spark.append(e.target.result)
        params.file.fileMd5 = spark.end() // 计算整个文件的fileMd5
      }

      chunkFileReader.onload = function (e: any) {
        // 对每一片分片进行md5加密
        spark.append(e.target.result)
        // 每一个分片需要包含的信息
        let obj = {
          chunk: currentChunk + 1,
          start: currentChunk * chunkSize, // 计算分片的起始位置
          end: ((currentChunk * chunkSize + chunkSize) >= file.size) ? file.size : currentChunk * chunkSize + chunkSize, // 计算分片的结束位置
          chunkMd5: spark.end(),
          chunks
        }
        // 每一次分片onload,currentChunk都需要增加，以便来计算分片的次数
        currentChunk++;
        params.chunks.push(obj)

        // 将每一块分片的arrayBuffer存储起来，用来partUpload
        let tmp = {
          chunk: obj.chunk,
          currentBuffer: e.target.result
        }
        arrayBufferData.push(tmp)

        if (currentChunk < chunks) {
          // 当前切片总数没有达到总数时
          loadNext()

          // 计算预处理进度
          _this.setState({
            preUploading: true,
            preUploadPercent: Number((currentChunk / chunks * 100).toFixed(2))
          })
        } else {
          //记录所有chunks的长度
          params.file.fileChunks = params.chunks.length
          // 表示预处理结束，将上传的参数，arrayBuffer的数据存储起来
          _this.setState({
            preUploading: false,
            uploadParams: params,
            arrayBufferData,
            chunksSize: chunks,
            preUploadPercent: 100,
            file_type: file_type,
            upload_name: file_name,
            fileSize: fileSize
          }, () => {
            resolve()
          })
        }
      }

      chunkFileReader.onerror = function () {
        console.warn('oops, something went wrong.');
      };

      function loadNext() {
        var start = currentChunk * chunkSize,
          end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;
        chunkFileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
      }

      loadNext();
    })
  }


  handleUpload = (config: any) => {
    // 上传逻辑
    const { type, showfileList, turtyfilelist, params } = this.state;
    const { env, multiple, limitType } = this.props;
    const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi
    if (type !== 'image') {
      MSG._error('请选择图片类型的文件!');
      this.setState({
        type: ''
      })
      return;
    }

    if (limitType && type !== limitType) {
      MSG._error(`请上传 ${limitType} 类型的图片!`);
      this.setState({
        type: ''
      })
      return
    }
    const { url, name } = this.props;
    let fileSize = config?.file?.size;
    this.setState({
      loading: true,
      fileSize: 0
    });

    this.handleFile(config).then(() => {
      const { uploadParams } = this.state;
      const formData = new FormData();
      formData.append('upload_cmd', 'check_exist');
      formData.append('upload_field', String(name));
      formData.append('file_name', uploadParams?.file.fileName);
      formData.append('file_md5', uploadParams?.file.fileMd5);

      env.fetcher({
        url: url,
        data: formData,
        method: 'post',
        dataType: 'form-data'
      }).then((res: any) => {
        if (res?.status === 0 && res?.data) {
          const { exist } = res?.data;
          switch (exist) {
            case true:
              MSG._info('文件上传成功');
              let _url = res?.data?.url;
              let value = res?.data?.value;
              let str = typeof params === 'string' && params.length === 0 ? value : params + ',' + value;
              let _item_val: any = {
                value: str,
                info: turtyfilelist.map((_file: any) => {
                  return {
                    name: _file.name,
                    size: _file.size,
                    url: _file.url,
                  }
                }).concat([{ name: uploadParams?.file.fileName, url: _url, size: fileSize }])
              };

              if (multiple) {
                this.setState({
                  loading: false,
                  showfileList: [
                    ...showfileList,
                    { name: uploadParams?.file.fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ],
                  turtyfilelist: [
                    ...turtyfilelist,
                    { name: uploadParams?.file.fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ]
                });
              } else {
                this.setState({
                  loading: false,
                  turtyfilelist: [
                    { name: uploadParams?.file.fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ],
                  showfileList: [
                    { name: uploadParams?.file.fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ]
                });
              };
              this.props.onBulkChange({ [name as any]: _item_val })
              this.setState({
                uploadParams: { chunks: [], file: {} },
                arrayBufferData: [],
                chunksSize: 0,
                preUploading: false,
                file_type: '',
                upload_name: '',
                loading: false,
                params: value
              })
              break;
            case false:
              this.setState({
                upload_cmd: 'chunk_upload'
              }, () => {
                this.handleMergeFile()
                // 上传分片文件
              });
              break;
            default:
              break;
          }
        } else {
          this.setState({
            loading: false
          })
          MSG._error('文件上传失败，系统异常');
          return;
        }
      }).catch((err: any) => {
        if (err) {
          MSG._error(err)
        }
        this.setState({
          loading: false
        })
        return;
      })
    })
    return;

  }

  handlePartUpload = (uploadList: any, file: any) => {
    const { upload_cmd, upload_name, turtyfilelist, errorImage, showfileList, chunksSize, file_type, params, fileSize } = this.state;
    const { fileMd5 } = file;
    const { url, multiple, env, name } = this.props;
    const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi

    // 遍历uploadList
    try {
      // @ts-ignore
      Promise.allSettled(uploadList.map((_uploadItem: any) => {
        return new Promise((resolve: any, reject: any) => {
          const { chunkMd5, chunk, start, end } = _uploadItem;


          let formData = new FormData(),
            //新建一个Blob对象，将对应分片的arrayBuffer加入Blob中
            blob = new Blob([this.state.arrayBufferData[chunk - 1].currentBuffer], { type: 'application/octet-stream' });
          // 上传的参数
          let params = `fileMd5=${fileMd5}&chunkMd5=${chunkMd5}&chunk=${chunk}&start=${start}&end=${end}&chunks=${this.state.arrayBufferData.length}`

          // 通过formData将上传参数传入
          formData.append('upload_cmd', upload_cmd);
          formData.append('upload_field', String(name));
          formData.append('file_name', upload_name);
          formData.append('file_md5', fileMd5);
          formData.append('chunk_index', chunk);
          formData.append('chunk_total', String(chunksSize));
          formData.append('chunk_size', String(end - start));
          formData.append('type', file_type);
          formData.append('chunk_file', blob);

          env.fetcher({
            url: url,
            data: formData,
            method: 'post'
          }).then((res: any) => {
            if (res.status === 0) {
              resolve(res?.data)
            } else {
              reject({ _err: res?.msg, _data: formData })
            }
          })
        })
      })).then((_res: any) => {

        let _chunk_success_count: number = 0;
        let _chunk_error_arr: any = [];

        _res.map((_upload_res: any) => {
          if (_upload_res?.status === 'fulfilled') {
            _chunk_success_count++
          } else {
            _chunk_error_arr.push(_upload_res.reason._data)
          }
        })

        if (_chunk_success_count === chunksSize) {
          let formData = new FormData();
          // 通过formData将上传参数传入，发起文件分片合并通知
          formData.append('upload_cmd', 'chunk_merge');
          formData.append('upload_field', String(name));
          formData.append('file_name', upload_name);
          formData.append('file_md5', fileMd5);
          env.fetcher({
            url: url,
            data: formData,
            method: 'post'
          }).then((_merge_res: any) => {
            if (_merge_res?.status === 0) {
              const data: any = _merge_res?.data;
              let fileName: string = data?.fileName;
              let _url = data?.url;
              let value = data?.value;
              let str = params.slice();
              let _item_val: any;
              if (typeof str === 'string' && str.length === 0) {
                _item_val = {
                  value: value,
                  info: turtyfilelist.map((_file: any) => {
                    return {
                      name: _file.name,
                      size: _file.size,
                      url: _file.url,
                    }
                  }).concat([{ name: fileName, url: _url, size: fileSize }])
                };
                this.setState({
                  params: value
                });
              } else {
                _item_val = {
                  value: str + ',' + value,
                  info: turtyfilelist.map((_file: any) => {
                    return {
                      name: _file.name,
                      size: _file.size,
                      url: _file.url,
                    }
                  }).concat([{ name: fileName, url: _url, size: fileSize }])
                };
                this.setState({
                  params: str + ',' + value
                })
              }
              this.props.onBulkChange({ [String(name)]: _item_val });
              // this.props.onChange(_item_val)
              if (multiple) {
                this.setState({
                  loading: false,
                  showfileList: [
                    ...showfileList,
                    { name: fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ],
                  turtyfilelist: [
                    ...turtyfilelist,
                    { name: fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ]
                });
              } else {
                this.setState({
                  loading: false,
                  turtyfilelist: [
                    { name: fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ],
                  showfileList: [
                    { name: fileName, url: (!baseUrl ? '' : (this.matchLocalhost(baseUrl) ? '' : baseUrl)) + _url, uid: value, status: 'done', size: fileSize }
                  ]
                });
              }
              MSG._success('文件上传成功');
            } else {
              if (multiple) {
                this.setState({
                  loading: false,
                  showfileList: [
                    ...showfileList,
                    {
                      url: errorImage.url,
                      uid: this.uuid(),
                      status: 'error',
                      name: upload_name,
                    }
                  ]
                });
              } else {
                this.setState({
                  loading: false,
                  showfileList: [
                    {
                      url: errorImage.url,
                      uid: this.uuid(),
                      status: 'error',
                      name: upload_name,
                    }
                  ]
                });
              }
              MSG._error(_merge_res?.msg)
            }
          }).catch((_file_merge_res: any) => {
            if (multiple) {
              this.setState({
                loading: false,
                showfileList: [
                  ...showfileList,
                  {
                    url: errorImage.url,
                    uid: this.uuid(),
                    status: 'error',
                    name: upload_name,
                  }
                ]
              });
            } else {
              this.setState({
                loading: false,
                showfileList: [
                  {
                    url: errorImage.url,
                    uid: this.uuid(),
                    status: 'error',
                    name: upload_name,
                  }
                ]
              });
            }
            MSG._error('上传失败');
            return;
          })
        } else {
          _chunk_error_arr.map((_chunk_error_item: any) => {
            env.fetcher({
              url: url,
              data: _chunk_error_item,
              method: 'post'
            }).then((_error_res: any) => {
            })
          })
          throw new Error('chunk file upload error!')
        }
      }).catch((_err: any) => {
        this.setState({
          loading: false
        })
        MSG._error(_err);
        return;
      })
    } catch (error) {
      this.setState({
        loading: false
      });
      MSG._error(error);
      return;
    }
  }

  uuid = () => {
    const temp_url = URL.createObjectURL(new Blob());
    const uuid = temp_url.toString();
    URL.revokeObjectURL(temp_url);
    return uuid.substr(uuid.lastIndexOf("/") + 1);
  }

  handleMergeFile = () => {
    const { uploadParams } = this.state;
    this.handlePartUpload(uploadParams?.chunks, uploadParams?.file)
  }

  matchLocalhost = (str: any): boolean => {
    if (!str) {
      return false
    }
    return /localhost\:(\d)+/.test(str)
  }


  handleRemove = (file: any) => {
    const { showfileList, turtyfilelist, params } = this.state;
    const { multiple, name } = this.props;
    let _item_val: any = {};
    if (multiple) {
      const index = showfileList.indexOf(file);
      const isexist = turtyfilelist.findIndex((item: any, idx: any) => {
        return item.name === file.name && item.uid === file.uid && item.url === file.url
      })
      const newturtyfilelist = turtyfilelist.slice();
      let newparams = params.slice();
      const newFileList = showfileList.slice();
      if (index !== -1 && isexist !== -1) {
        let example: any = params.split(',');
        newturtyfilelist.splice(isexist, 1);
        example.splice(isexist, 1);
        newparams = example.join(',');
      }


      newFileList.splice(index, 1);
      this.setState({
        showfileList: newFileList,
        type: '',
        params: newparams,
        turtyfilelist: newturtyfilelist
      });

      _item_val = {
        value: newparams,
        info: turtyfilelist.map((_file: any) => {
          return {
            name: _file.name,
            size: _file.size,
            url: _file.url,
          }
        })
      }

      this.props.onBulkChange({ [name as any]: _item_val });

    } else {
      this.setState({
        showfileList: [],
        type: '',
        params: '',
        turtyfilelist: []
      });
      this.props.onBulkChange({ [name as any]: _item_val });
    }
  }

  render() {
    const { url, multiple, classnames: cx, className, thumbMode, width, height, env } = this.props;
    const baseUrl = env?.axiosInstance?.defaults?.baseURL || env?.ajaxApi
    const { previewVisible, previewImage, loading, previewTitle, showfileList, errorImage } = this.state;
    const uploadButton = (
      loading ? <span className="fa fa-circle-o-notch fa-spin"></span> : <span className="fa fa-plus"></span>
    );

    const uploadProps: UploadProps = {
      action: (baseUrl ? baseUrl : '') + url,
      disabled: loading || this.props.disabled,
      listType: "picture-card",
      showUploadList: true,
      fileList: showfileList,
      progress: {
        strokeColor: {
          '0%': '#108ee9',
          '100%': '#87d068',
        },
        strokeWidth: 3,
        format: (percent: number) => `${parseFloat(percent.toFixed(2))}%`
      },
      onPreview: this.handlePreview,
      onChange: this.handleChange,
      onRemove: this.handleRemove,
      customRequest: this.handleUpload,
    };

    return (
      <Warpper {...this.props as any} imgHeight={this.state.imgHeight}>
        <Upload
          {...uploadProps}
        >
          {multiple ? uploadButton : (showfileList.length >= 1 ? null : uploadButton)}
        </Upload>
        <Modal
          className='fastlion-modal'
          visible={previewVisible}
          title={previewTitle}
          footer={null}
          onCancel={this.handleCancel}
          zIndex={9999}
          maskStyle={{
            zIndex: 9999
          }}
        >
          <img
            onError={() => {
              this.setState({
                previewImage: errorImage?.url
              })
            }}
            title={previewTitle}
            alt={previewTitle}
            style={{ width: '100%' }}
            src={previewImage}
          />
        </Modal>
      </Warpper>
    )
  }
}

@FormItem({
  type: 'lion-input-img',
  strictMode: false
})
export class LionInputImgRenderer extends LionInputImg { }
