import React, { Suspense } from 'react';
import { FormItem, FormControlProps, FormBaseControl } from '../../../Form/Item';
// import 'cropperjs/dist/cropper.css';
const Cropper = React.lazy(() => import('react-cropper'));
import DropZone from 'react-dropzone';
import { FileRejection } from 'react-dropzone';
import 'blueimp-canvastoblob';
import find from 'lodash/find';
import {
  guid,
  isEmpty,
  isMobile,
} from '../../../../utils/helper';
import { Icon } from '../../../../components/icons';
import Button from '../../../../components/Button';
import accepts from 'attr-accept';
import { getNameFromUrl } from '../../../Form/InputFile';
import ImageComponent, { ImageThumbProps } from '../../../Image';
import { TranslateFn } from '../../../../locale';
import { dataMapping } from '../../../../utils/tpl-builtin';
import {
  SchemaApi,
  SchemaClassName,
  SchemaTokenizeableString,
  SchemaUrlPath
} from '../../../../Schema';
import { filter } from '../../../../utils/tpl';
import isPlainObject from 'lodash/isPlainObject';
import merge from 'lodash/merge';
import { isPdf, isImg, getMediaIcon, isCon, downloadFile, downFile } from '../../utils/utils'
import SparkMD5 from 'spark-md5';
import Axios from 'axios';
import { compressAccurately, compress } from 'image-conversion';
import Tooltip from 'antd/lib/Tooltip';
import { WrapperFileView } from '../../Table/LionCellFile/style'
import { CloseCircleOutlined, PlusCircleOutlined } from '@ant-design/icons';
import Popover from 'antd/lib/popover';
import CellPopover from '../../Table/LionCellImg/CellPopover';
import { LionCellImgRenderer } from '../../Table/LionCellImg/LionCellImg';
import Modal from 'antd/lib/modal/Modal';
import Video from '../../../Video';
import { getLodop } from '../../../../utils/print/LodopFuncs';
import { ModalPrint } from '../../LabelPrint';
import { Shell } from '../../../../utils/shell';
import { Progress } from 'antd';

/**
 * Image 图片上传控件
 * 文档：https://baidu.gitee.io/amis/docs/components/form/image
 */
export interface ImageControlSchema extends FormBaseControl {
  /**
   * 指定为图片上传控件
   */
  type: 'input-image';

  /**
   * 默认展示图片的链接
   */
  src?: SchemaUrlPath;

  /**
   * 默认展示图片的类名
   */
  imageClassName?: string;

  /**
   * 配置接收的图片类型
   *
   * 建议直接填写文件后缀
   * 如：.txt,.csv
   *
   * 多个类型用逗号隔开。
   */
  accept?: string;

  /**
   * 默认都是通过用户选择图片后上传返回图片地址，如果开启此选项，则可以允许用户图片地址。
   */
  allowInput?: boolean;

  /**
   * 是否自动开始上传
   */
  autoUpload?: boolean;

  /**
   * 选择图片按钮的 CSS 类名
   */
  btnClassName?: SchemaClassName;

  /**
   * 上传按钮的 CSS 类名
   */
  btnUploadClassName?: SchemaClassName;

  /**
   * @deprecated
   */
  compress?: boolean;

  /**
   * @deprecated
   */
  compressOptions?: {
    maxHeight?: number;
    maxWidth?: number;
  };

  crop?:
  | boolean
  | {
    /**
     * 默认 `1` 即 `1:1`
     *
     * 留空将不限制
     */
    aspectRatio?: number;

    guides?: boolean;
    dragMode?: string;
    viewMode?: number;
    rotatable?: boolean;
    scalable?: boolean;
  };

  /**
   * 裁剪后的图片类型
   */
  cropFormat?: string;

  /**
   * 裁剪后的质量
   */
  cropQuality?: number;

  /**
   * 是否允许二次裁剪。
   */
  reCropable?: boolean;

  /**
   * 是否隐藏上传按钮
   */
  hideUploadButton?: boolean;

  /**
   * 限制图片大小，超出不让上传。
   */
  limit?: {
    /**
     * 比率不对时的提示文字
     */
    aspectRatioLabel?: string;
    /**
     * 限制比率
     */
    aspectRatio?: number;

    /**
     * 限制图片高度
     */
    height?: number;

    /**
     *  限制图片宽度
     */
    width?: number;

    /**
     * 限制图片最大高度
     */
    maxHeight?: number;

    /**
     * 限制图片最大宽度
     */
    maxWidth?: number;

    /**
     * 限制图片最小高度
     */
    minHeight?: number;

    /**
     *  限制图片最小宽度
     */
    minWidth?: number;
  };

  /**
   * 最多的个数
   */
  maxLength?: number;

  /**
   * 默认10MB，当设置后，文件大小大于此值将不允许上传。
   */
  maxSize?: number;

  /**
   * 默认 `/api/upload` 如果想自己存储，请设置此选项。
   */
  receiver?: SchemaApi;

  /**
   * 默认为 false, 开启后，允许用户输入压缩选项。
   *
   * @deprecated
   */
  showCompressOptions?: boolean;

  /**
   * 是否为多选
   */
  multiple?: boolean;

  /**
   * 单选模式：当用户选中某个选项时，选项中的 value 将被作为该表单项的值提交，否则，整个选项对象都会作为该表单项的值提交。
   * 多选模式：选中的多个选项的 `value` 会通过 `delimiter` 连接起来，否则直接将以数组的形式提交值。
   */
  joinValues?: boolean;

  /**
   * 分割符
   */
  delimiter?: string;

  /**
   * 开启后将选中的选项 value 的值封装为数组，作为当前表单项的值。
   */
  extractValue?: boolean;

  /**
   * 清除时设置的值
   */
  resetValue?: any;

  /**
   * 缩路图展示模式
   */
  thumbMode?: 'w-full' | 'h-full' | 'contain' | 'cover';

  /**
   * 缩路图展示比率。
   */
  thumbRatio?: '1:1' | '4:3' | '16:9';

  /**
   * 上传后把其他字段同步到表单内部。
   */
  autoFill?: {
    [propName: string]: SchemaTokenizeableString;
  };

  /**
   * 默认占位图图片地址
   */
  frameImage?: SchemaUrlPath;

  /**
   * 是否开启固定尺寸
   */
  fixedSize?: boolean;

  /**
   * 固定尺寸的 CSS类名
   */
  fixedSizeClassName?: SchemaClassName;

  /**
   * 只读模式，只提供展示功能，不能编辑、不能进行上传删除等操作
   */
  readonly?: boolean;

  /**
   * 是否在文件赋值地址前，对地址进行读取容错，针对地址不存在或返回了错误信息
   */
  preAjax?: boolean;

  /**
   * 上传的提示文字
   */
  uploadText?: string;

  /**
   * 图片压缩的宽度
   */
  pressWidth?: number;
  /**
   * 展示形式。默认false
   */
  beauty?: boolean;
  /**
  * 判断是否在表格,默认false
  */
  tabSample?: boolean;

}

let preventEvent = (e: any) => e.stopPropagation();

export interface ImageProps
  extends FormControlProps,
  Omit<
  ImageControlSchema,
  'type' | 'className' | 'descriptionClassName' | 'inputClassName'
  > {
  onImageEnlarge?: (
    info: Pick<ImageThumbProps, 'src' | 'originalSrc' | 'title' | 'caption'> & {
      index?: number;
      list?: Array<
        Pick<ImageThumbProps, 'src' | 'originalSrc' | 'title' | 'caption'>
      >;
    }
  ) => void;
  _print_visible?: boolean;
  ctx?: {
    items: Array<any>;
    rows: Array<any>;
    selectedItems: Array<any>;
    unSelectedItems: Array<any>;
    ids: string;
    primaryField?: string;
    [key: string]: any;
  }
}

export interface LionUploadState {
  uploading: boolean;
  locked: boolean;
  lockedReason?: string;
  files: Array<FileValue | FileX>;
  crop?: any;
  error?: string;
  cropFile?: FileValue;
  cropFileName?: string; // 主要是用于后续上传的时候获得用户名
  submitOnChange?: boolean;
  frameImageWidth?: number;
  [propName: string]: any;

}

export interface FileValue {
  value?: any;
  state: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid';
  url?: string;
  error?: string;
  info?: {
    width: number;
    height: number;
    len?: number;
  };
  [propName: string]: any;
}

export interface FileX extends File {
  id?: string | number;
  preview?: string;
  state?: 'init' | 'error' | 'pending' | 'uploading' | 'uploaded' | 'invalid';
  progress?: number;
  [propName: string]: any;
}
export default class LionUpload extends React.Component<
  ImageProps,
  any
> {
  static defaultProps = {
    limit: undefined,
    accept: '',
    receiver: '/api/upload',
    hideUploadButton: false,
    placeholder: 'Image.placeholder',
    joinValues: true,
    extractValue: false,
    delimiter: ',',
    autoUpload: true,
    multiple: false,
    maxSize: 10 * 1024 * 1024,
    beauty: false,
    tabSample: false,
    _print_visible: false,
    ctx: {
      items: [],
      rows: [],
      selectedItems: [],
      unSelectedItems: [],
      ids: ''
    }
  };

  static formatFileSize(
    size: number | string,
    units = [' B', ' KB', ' M', ' G']
  ) {
    size = parseInt(size as string, 10) || 0;

    while (size > 1024 && units.length > 1) {
      size /= 1024;
      units.shift();
    }

    return size.toFixed(2) + units[0];
  }

  static sizeInfo(
    width: number | undefined,
    height: number | undefined,
    __: TranslateFn
  ): string {
    if (!width) {
      return __('Image.height', { height: height });
    } else if (!height) {
      return __('Image.width', { width: width });
    }

    return __('Image.size', { width, height });
  }

  state: LionUploadState = {
    uploading: false,
    locked: false,
    files: [],

    // visible: false,
    // uploading: false,
    // params: '',
    // init: false,
    // formItemName: '',
    // removeIcon: true,
    // loading: false,
    // 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,
  };

  baseURL: string = '';

  files: Array<FileValue | FileX> = [];
  fileUploadCancelExecutors: Array<{
    file: any;
    executor: () => void;
  }> = [];
  cropper: Cropper;
  dropzone = React.createRef<any>();
  frameImageRef = React.createRef<any>();
  current: FileValue | FileX | null = null;
  resolve?: (value?: any) => void;
  emitValue: any;
  unmounted = false;
  errImg: string;
  constructor(props: ImageProps) {
    super(props);
    this.baseURL = props.env?.axiosInstance?.defaults?.baseURL || props.env?.ajaxApi || ''
    // this.baseURL = 'https://sasdev.sanfu.com/saas_dev'
    // this.baseURL = 'https://bwt.sanfu.com/saas'

    this.state = {
      ...this.state,
      crop: this.buildCrop(props),
      frameImageWidth: 0,
      selectList: [],
      setvideo: false,
      structure: {},
      content: {}
    };
    this.errImg = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAMIAAADDCAYAAADQvc6UAAABRWlDQ1BJQ0MgUHJvZmlsZQAAKJFjYGASSSwoyGFhYGDIzSspCnJ3UoiIjFJgf8LAwSDCIMogwMCcmFxc4BgQ4ANUwgCjUcG3awyMIPqyLsis7PPOq3QdDFcvjV3jOD1boQVTPQrgSkktTgbSf4A4LbmgqISBgTEFyFYuLykAsTuAbJEioKOA7DkgdjqEvQHEToKwj4DVhAQ5A9k3gGyB5IxEoBmML4BsnSQk8XQkNtReEOBxcfXxUQg1Mjc0dyHgXNJBSWpFCYh2zi+oLMpMzyhRcASGUqqCZ16yno6CkYGRAQMDKMwhqj/fAIcloxgHQqxAjIHBEugw5sUIsSQpBobtQPdLciLEVJYzMPBHMDBsayhILEqEO4DxG0txmrERhM29nYGBddr//5/DGRjYNRkY/l7////39v///y4Dmn+LgeHANwDrkl1AuO+pmgAAADhlWElmTU0AKgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAAqACAAQAAAABAAAAwqADAAQAAAABAAAAwwAAAAD9b/HnAAAHlklEQVR4Ae3dP3PTWBSGcbGzM6GCKqlIBRV0dHRJFarQ0eUT8LH4BnRU0NHR0UEFVdIlFRV7TzRksomPY8uykTk/zewQfKw/9znv4yvJynLv4uLiV2dBoDiBf4qP3/ARuCRABEFAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghggQAQZQKAnYEaQBAQaASKIAQJEkAEEegJmBElAoBEgghgg0Aj8i0JO4OzsrPv69Wv+hi2qPHr0qNvf39+iI97soRIh4f3z58/u7du3SXX7Xt7Z2enevHmzfQe+oSN2apSAPj09TSrb+XKI/f379+08+A0cNRE2ANkupk+ACNPvkSPcAAEibACyXUyfABGm3yNHuAECRNgAZLuYPgEirKlHu7u7XdyytGwHAd8jjNyng4OD7vnz51dbPT8/7z58+NB9+/bt6jU/TI+AGWHEnrx48eJ/EsSmHzx40L18+fLyzxF3ZVMjEyDCiEDjMYZZS5wiPXnyZFbJaxMhQIQRGzHvWR7XCyOCXsOmiDAi1HmPMMQjDpbpEiDCiL358eNHurW/5SnWdIBbXiDCiA38/Pnzrce2YyZ4//59F3ePLNMl4PbpiL2J0L979+7yDtHDhw8vtzzvdGnEXdvUigSIsCLAWavHp/+qM0BcXMd/q25n1vF57TYBp0a3mUzilePj4+7k5KSLb6gt6ydAhPUzXnoPR0dHl79WGTNCfBnn1uvSCJdegQhLI1vvCk+fPu2ePXt2tZOYEV6/fn31dz+shwAR1sP1cqvLntbEN9MxA9xcYjsxS1jWR4AIa2Ibzx0tc44fYX/16lV6NDFLXH+YL32jwiACRBiEbf5KcXoTIsQSpzXx4N28Ja4BQoK7rgXiydbHjx/P25TaQAJEGAguWy0+2Q8PD6/Ki4R8EVl+bzBOnZY95fq9rj9zAkTI2SxdidBHqG9+skdw43borCXO/ZcJdraPWdv22uIEiLA4q7nvvCug8WTqzQveOH26fodo7g6uFe/a17W3+nFBAkRYENRdb1vkkz1CH9cPsVy/jrhr27PqMYvENYNlHAIesRiBYwRy0V+8iXP8+/fvX11Mr7L7ECueb/r48eMqm7FuI2BGWDEG8cm+7G3NEOfmdcTQw4h9/55lhm7DekRYKQPZF2ArbXTAyu4kDYB2YxUzwg0gi/41ztHnfQG26HbGel/crVrm7tNY+/1btkOEAZ2M05r4FB7r9GbAIdxaZYrHdOsgJ/wCEQY0J74TmOKnbxxT9n3FgGGWWsVdowHtjt9Nnvf7yQM2aZU/TIAIAxrw6dOnAWtZZcoEnBpNuTuObWMEiLAx1HY0ZQJEmHJ3HNvGCBBhY6jtaMoEiJB0Z29vL6ls58vxPcO8/zfrdo5qvKO+d3Fx8Wu8zf1dW4p/cPzLly/dtv9Ts/EbcvGAHhHyfBIhZ6NSiIBTo0LNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiECRCjUbEPNCRAhZ6NSiAARCjXbUHMCRMjZqBQiQIRCzTbUnAARcjYqhQgQoVCzDTUnQIScjUohAkQo1GxDzQkQIWejUogAEQo121BzAkTI2agUIkCEQs021JwAEXI2KoUIEKFQsw01J0CEnI1KIQJEKNRsQ80JECFno1KIABEKNdtQcwJEyNmoFCJAhELNNtScABFyNiqFCBChULMNNSdAhJyNSiEC/wGgKKC4YMA4TAAAAABJRU5ErkJggg==';

    this.sendFile = this.sendFile.bind(this);
    this.removeFile = this.removeFile.bind(this);
    this.handleDrop = this.handleDrop.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleClick = this.handleClick.bind(this);
    this.handleCrop = this.handleCrop.bind(this);
    this.handleDropRejected = this.handleDropRejected.bind(this);
    this.cancelCrop = this.cancelCrop.bind(this);
    this.rotatableCrop = this.rotatableCrop.bind(this);
    this.handleFrameImageLoaded = this.handleFrameImageLoaded.bind(this);
    this.startUpload = this.startUpload.bind(this);
    this.stopUpload = this.stopUpload.bind(this);
    this.toggleUpload = this.toggleUpload.bind(this);
    this.tick = this.tick.bind(this);
    this.onChange = this.onChange.bind(this);
    this.addFiles = this.addFiles.bind(this);
    this.handleSelect = this.handleSelect.bind(this);
    this.handlePaste = this.handlePaste.bind(this);
    this.syncAutoFill = this.syncAutoFill.bind(this);
    this.initFiles = this.initFiles.bind(this)
    this.formatfileAddr = this.formatfileAddr.bind(this)
    this.updateFiles = this.updateFiles.bind(this)
    this.previewImage = this.previewImage.bind(this)
    this.handprogress.bind = this.handprogress.bind(this)
    this.chunks.bind = this.chunks.bind(this)
  }



  componentDidMount() {
    // this.syncAutoFill();
    this.updateFiles()
  }

  updateFiles() {
    this.initFiles().then((files: Array<FileValue>) => {
      this.setState({
        files: (this.files = files)
      }, this.syncAutoFill)
    })
  }

  componentDidUpdate(prevProps: ImageProps) {
    const props = this.props;

    if (prevProps.value !== props.value && this.emitValue !== props.value) {
      this.updateFiles()

    }

    if (prevProps.crop !== props.crop) {
      this.setState({
        crop: this.buildCrop(props)
      });
    }
  }

  componentWillUnmount() {
    this.unmounted = true;
  }

  getBatchAddrInfo(files: Array<FileValue>) {
    const requests = files.map(item => Axios(item.thumbnailAddr))
    return Promise.allSettled(requests)
  }

  analyzingAddrInfo(files: Array<FileValue>, allResponse: any) {
    let list = files.concat()
    allResponse.map((item: any, index: number) => {
      if (item.status === 'fulfilled') {
        const result = item?.value
        if (result.status === 200) {
          list[index].notNull = true
          if (result.data.status) {
            list[index].errorMsg = result.data.msg
            list[index].state = 'error'
          } else {
            // list[index].thumbnailAddr = result.data
          }
        }

      }

    })
    return list.filter((item: any) => item.notNull)

  }

  initFiles() {
    const { value, preAjax } = this.props
    let files: Array<FileValue> = []

    if (value) {
      const { value: fileValue, info: fileInfo } = value
      if (fileValue && Array.isArray(fileInfo) && fileInfo.length) {
        const fileValueArr = fileValue.split(',')
        files = fileInfo.map((item, index) => {
          return this.formatfileAddr(Object.assign({
            state: 'init',
            value: fileValueArr[index]
          }, item))
        })
      }
    }

    // files = testdata
    return new Promise(resolve => {
      if (preAjax && files.length) {
        this.getBatchAddrInfo(files).then(allResponse => {
          let list = this.analyzingAddrInfo(files, allResponse)
          resolve(list)
        })
      } else {
        resolve(files)
      }
    })

  }

  buildCrop(props: ImageProps) {
    let crop = props.crop;
    const __ = this.props.translate;

    if (crop && props.multiple) {
      props.env && props.env.alert && props.env.alert(__('Image.configError'));
      return null;
    }

    if (crop === true) {
      crop = {};
    }

    if (crop) {
      crop = {
        aspectRatio: undefined, // 默认不限制
        guides: true,
        dragMode: 'move',
        viewMode: 1,
        rotatable: true,
        scalable: true,
        ...crop
      };
    }

    return crop;
  }

  handleDropRejected(
    rejectedFiles: FileRejection[],
    evt: React.DragEvent<any>
  ) {
    if (evt.type !== 'change' && evt.type !== 'drop') {
      return;
    }
    const { multiple, env, accept, translate: __ } = this.props;

    const files = rejectedFiles.map(fileRejection => ({
      ...fileRejection.file,
      state: 'invalid',
      id: guid(),
      name: fileRejection.file.name
    }));

    env.alert(
      __('File.invalidType', {
        files: files.map((file: any) => `「${file.name}」`).join(' '),
        accept
      })
    );
  }

  // 开始上传
  startUpload(retry: boolean = false) {
    if (this.state.uploading) {
      return;
    }

    this.setState(
      {
        uploading: true,
        locked: true,
        files: (this.files = this.files.map(file => {
          if (retry && file.state === 'error') {
            file.state = 'pending';
            file.progress = 0;
          }

          return file;
        }))
      },
      this.tick
    );
  }

  toggleUpload() {
    return this.state.uploading ? this.stopUpload() : this.startUpload();
  }

  stopUpload() {
    if (!this.state.uploading) {
      return;
    }

    this.setState({
      uploading: false
    });
  }

  // 统一处理下，省的后续的组件重复去拼地址
  formatfileAddr(fileData: Omit<FileValue, 'state'>) {
    if (!fileData) return
    let obj = JSON.parse(JSON.stringify(fileData))
    if (obj.preview) {
      obj.preview = this.baseURL + obj.preview
    }

    // 非图片格式去本地拿图标
    if (isImg(obj.name)) {
      obj.thumbnailAddr = this.baseURL + (obj.thumbnailAddr || obj?.url || obj?.addr)
      // 给个标识，留给样式调整空间，以及调用不同的预览组件
      obj.isNotImg = false
    } else {
      obj.thumbnailAddr = getMediaIcon(obj.name)
      obj.isNotImg = true
    }
    obj.downloadSrc = this.baseURL + (obj?.url || obj?.addr)
    return obj
  }

  tick() {
    if (this.current || !this.state.uploading) {
      return;
    }

    const env = this.props.env;
    const __ = this.props.translate;
    const file = find(this.files, item => item.state === 'pending') as FileX;
    if (file) {
      this.current = file;

      file.state = 'uploading';
      this.setState(
        {
          files: (this.files = this.files.concat())
        },
        () =>
          this.sendFile(
            file as FileX,
            (error, file, obj) => {
              const files = this.files.concat();
              const idx = files.indexOf(file);

              if (!~idx) {
                return;
              }

              let newFile: FileX | FileValue = file;

              if (error) {
                newFile.state =
                  file.state !== 'uploading' ? file.state : 'error';
                newFile.error = error;

                if (!this.props.multiple && newFile.state === 'invalid') {
                  files.splice(idx, 1);
                  this.current = null;

                  return this.setState(
                    {
                      files: (this.files = files),
                      error: error
                    },
                    this.tick
                  );
                }

                env.notify('error', error || __('File.errorRetry'));
              } else {
                newFile = this.formatfileAddr({
                  name: file.name || this.state.cropFileName,
                  size: file.size,
                  ...obj
                })
              }
              files.splice(idx, 1, newFile);
              this.current = null;
              this.setState(
                {
                  files: (this.files = files)
                },
                this.tick
              );
            },
            progress => {
              const files = this.files.concat();
              const idx = files.indexOf(file);

              if (!~idx) {
                return;
              }

              // file 是个非 File 对象，先不copy了直接改。
              file.progress = progress;
              this.setState({
                files: (this.files = files)
              });
            }
          )
      );
    } else {
      this.setState(
        {
          uploading: false,
          locked: false
        },
        () => {
          this.onChange(!!this.resolve);

          if (this.resolve) {
            this.resolve(
              this.files.some(file => file.state === 'error')
                ? __('File.errorRetry')
                : null
            );
            this.resolve = undefined;
          }
        }
      );
    }
  }

  removeFile(file: FileValue, index: number) {
    const files = this.files.concat();
    this.removeFileCanelExecutor(file, true);
    files.splice(index, 1);
    const isUploading = this.current === file;
    if (isUploading) {
      this.current = null;
    }

    this.setState(
      {
        files: (this.files = files)
      },
      isUploading ? this.tick : this.onChange
    );
  }

  previewImage(file: FileX, index: number, e: React.MouseEvent<any>) {
    e.preventDefault();
    if (isCon(file.name)) {
      Shell.hasShell() ?
        Shell.handleExternalUrl({
          "externalUrl": file.downloadSrc,
          "fileName": file.name,
          "handleType": "open"
        })
        :
        this.setState({
          setvideo: true,
          structure: {
            "type": "video",
            "src": file.downloadSrc,
            "poster": file.thumbnailAddr,
            "aspectRatio": "16:9"
          }
        })
    } else {
      const { onImageEnlarge } = this.props;
      if (onImageEnlarge) {
        const files = this.files;
        onImageEnlarge({
          // 预览地址
          src: file.thumbnailAddr as string,
          originalSrc: file.preview as string || this.errImg,
          index,
          list: files.map(file => ({
            src: file.thumbnailAddr as string,
            originalSrc: file.preview as string || this.errImg,
            title: file.name || getNameFromUrl(file.value || file.url),
            isNotImg: file.isNotImg as boolean,
          }))

        });

      }

    }
  }

  editImage(index: number) {
    const files = this.files;

    this.setState({
      cropFile: {
        preview: files[index].preview || (files[index].url as string),
        name: files[index].name,
        state: 'init'
      },
      cropFileName: files[index].name
    });
  }

  onChange(changeImmediately?: boolean) {
    const { onChange } = this.props;

    let newValue: any = this.files.reduce((t: any, c) => {
      if (c.state == 'uploaded' || c.state == 'init') {
        t.value += ((t.value ? ',' : '') + c.value)
        t.info.push({
          size: c.size,
          name: c.name
        })
      }
      return t
    }, {
      value: "",
      info: []
    })

    onChange((this.emitValue = newValue), undefined, changeImmediately);
    this.syncAutoFill();
  }

  syncAutoFill() {
    const { autoFill, multiple, onBulkChange, data } = this.props;
    if (!isEmpty(autoFill) && onBulkChange) {
      const files = this.state.files.filter(
        file => ~['uploaded', 'init', 'ready'].indexOf(file.state as string)
      );
      const toSync = dataMapping(
        autoFill,
        multiple
          ? {
            items: files
          }
          : files[0]
      );

      Object.keys(toSync).forEach(key => {
        if (isPlainObject(toSync[key]) && isPlainObject(data[key])) {
          toSync[key] = merge({}, data[key], toSync[key]);
        }
      });
      onBulkChange(toSync);
    }
  }

  handleSelect() {
    this.dropzone.current && this.dropzone.current.open();
  }

  handleRetry(index: number) {
    const files = this.files.concat();
    const file = files[index];

    if (file.state !== 'invalid' && file.state !== 'error') {
      return;
    }

    file.state = 'pending';
    file.progress = 0;

    this.setState(
      {
        files: files
      },
      this.startUpload
    );
  }

  handleDrop(files: Array<FileX>) {
    const { multiple, crop } = this.props;

    if (crop && !multiple) {
      const file: any = files[0] as FileValue;
      if (!file.preview || !file.url) {
        file.preview = window.URL.createObjectURL(file);
      }

      return this.setState({
        cropFile: file,
        cropFileName: file.name
      });
    }

    this.addFiles(files);
  }

  handlePaste(e: React.ClipboardEvent<any>) {
    const event = e.nativeEvent as any;
    const files: Array<FileX> = [];
    const items = event.clipboardData.items;
    const accept = this.props.accept || '*';

    [].slice.call(items).forEach((item: DataTransferItem) => {
      let blob: FileX;

      if (
        item.kind !== 'file' ||
        !(blob = item.getAsFile() as File) ||
        !accepts(blob, accept)
      ) {
        return;
      }

      blob.id = guid();
      files.push(blob);
    });

    this.handleDrop(files);
  }

  // 裁剪
  handleCrop() {
    const { cropFormat, cropQuality } = this.props;
    this.cropper.getCroppedCanvas().toBlob(
      (file: File) => {
        this.addFiles([file]);
        this.setState({
          cropFile: undefined,
          locked: false,
          lockedReason: ''
        });
      },
      cropFormat || 'image/png',
      cropQuality || 1
    );
  }

  cancelCrop() {
    this.setState(
      {
        cropFile: undefined,
        cropFileName: undefined,
        locked: false,
        lockedReason: ''
      },
      this.onChange
    );
  }

  rotatableCrop() {
    this.cropper.rotate(45);
  }

  async addFiles(files: Array<FileX>) {
    const { pressWidth = 640 } = this.props
    if (!files.length) {
      return;
    }

    const { multiple, maxLength, maxSize, accept, translate: __ } = this.props;
    let currentFiles = this.files;

    if (!multiple && currentFiles.length) {
      currentFiles = [];
    }

    const allowed =
      (multiple
        ? maxLength
          ? maxLength
          : files.length + currentFiles.length
        : 1) - currentFiles.length;
    let inputFiles: Array<FileX> = [];

    let list = [].slice.call(files, 0, allowed)

    for await (const file of list) {
      if (maxSize && file.size > maxSize) {
        this.props.env.alert(
          __('File.maxSize', {
            filename: file.name,
            actualSize: LionUpload.formatFileSize(file.size),
            maxSize: LionUpload.formatFileSize(maxSize)
          })
        );
        return;
      }
      if (pressWidth && this.props.isImage) {
        let img = new Image();
        img.src = URL.createObjectURL(file);
        img.onload = async () => {
          const { width } = img;
          let upFilez = file;
          if (width > pressWidth) {
            const res = await compress(file, { width: pressWidth, quality: 1 })
            upFilez = new window.File([res], file.name, { type: file.type })
            upFilez.state = 'pending';
            upFilez.path = file.path;
            upFilez.id = guid();
            if (!upFilez.preview || !upFilez.url) {
              upFilez.preview = URL.createObjectURL(upFilez);
            }
            inputFiles.push(upFilez);
          } else {
            file.state = 'pending';
            file.id = guid();
            if (!file.preview || !file.url) {
              file.preview = URL.createObjectURL(file);
            }
            inputFiles.push(file);
          }

          this.setState(
            {
              error: undefined,
              files: (this.files = currentFiles.concat(inputFiles)),
              locked: true
            },
            () => {
              const { autoUpload } = this.props;

              if (autoUpload) {
                this.startUpload();
              }
            }
          );
        }
      } else {
        file.state = 'pending';
        file.id = guid();
        if (!file.preview || !file.url) {
          file.preview = URL.createObjectURL(file);
        }
        inputFiles.push(file);
      }
    }

    if (!inputFiles.length) {
      return;
    }

    this.setState(
      {
        error: undefined,
        files: (this.files = currentFiles.concat(inputFiles)),
        locked: true
      },
      () => {
        const { autoUpload } = this.props;

        if (autoUpload) {
          this.startUpload();
        }
      }
    );
  }

  sendFile(
    file: FileX,
    cb: (error: null | string, file: FileX, obj?: FileValue) => void,
    onProgress: (progress: number) => void
  ) {

    const { limit, translate: __ } = this.props;

    if (!limit) {
      return this._upload(file, cb, onProgress);
    }

    const image = new Image();
    image.onload = () => {
      const width = image.width;
      const height = image.height;
      let error = '';

      if (
        (limit.width && limit.width != width) ||
        (limit.height && limit.height != height)
      ) {
        error = __('Image.sizeNotEqual', {
          info: LionUpload.sizeInfo(limit.width, limit.height, __)
        });
      } else if (
        (limit.maxWidth && limit.maxWidth < width) ||
        (limit.maxHeight && limit.maxHeight < height)
      ) {
        error = __('Image.limitMax', {
          info: LionUpload.sizeInfo(limit.maxWidth, limit.maxHeight, __)
        });
      } else if (
        (limit.minWidth && limit.minWidth > width) ||
        (limit.minHeight && limit.minHeight > height)
      ) {
        error = __('Image.limitMin', {
          info: LionUpload.sizeInfo(limit.minWidth, limit.minHeight, __)
        });
      } else if (
        limit.aspectRatio &&
        Math.abs(width / height - limit.aspectRatio) > 0.01
      ) {
        error = __(limit.aspectRatioLabel || 'Image.limitRatio', {
          ratio: (+limit.aspectRatio).toFixed(2)
        });
      }

      if (error) {
        file.state = 'invalid';
        cb(error, file);
      } else {
        this._upload(file, cb, onProgress);
      }
    };
    image.src = (file.preview || file.url) as string;
  }

  // 自lion-input-file迁徙而来的上传方法1
  _upload(
    file: FileX,
    cb: (error: null | string, file: Blob, obj?: any) => void,
    onProgress: (progress: number) => void
  ) {
    const { url, receiver, env, name, translate: __ } = this.props;

    const formData = new FormData();
    this.handleFile(file).then(() => {
      const { uploadParams } = this.state;
      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 || receiver,
        data: formData,
        method: 'post',
        dataType: 'form-data'
      }).then((res: any) => {
        if (res?.status === 0 && res?.data) {
          const { exist } = res?.data;
          switch (exist) {
            case true:
              const obj: FileValue = {
                ...res.data,
                state: 'uploaded'
              };
              obj.value = obj.value || obj.url;

              cb(null, file, obj);
              break;
            case false:
              this.setState({
                upload_cmd: 'chunk_upload'
              }, () => {
                // 上传分片文件
                this.handlePartUpload(file, cb)
              });
              break;
            default:
              break;
          }
        } else {
          throw new Error(res.msg || __('File.errorRetry'));
        }
      }).catch(error => cb(error.message || __('File.errorRetry'), file))
    })

  }

  // 自lion-input-file迁徙而来的上传方法2
  handleFile = (config: any) => {
    return new Promise((resolve: any, reject: any) => {
      let fileSize = config?.size;
      let file = config;

      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?.type;
      let file_name = config?.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 || this.state.cropFileName;
      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()
        } 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: params.file.fileName,
            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();
    })
  }

  // 自lion-input-file迁徙而来的上传方法3
  handlePartUpload = (originalFile: FileX, cb: Function) => {
    const { upload_cmd, upload_name, chunksSize, file_type, uploadParams } = this.state;
    const { chunks: uploadList, file } = uploadParams
    const { fileMd5 } = file;
    const { url, receiver, env, name } = this.props;

    // 遍历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 || receiver,
            data: formData,
            method: 'post'
          }).then((res: any) => {
            if (res.status === 0) {
              resolve(res?.data)
            } else {
              reject({ _err: res?.msg, _data: formData })
            }
          }).catch(e => reject(e))
        })
      })).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 || receiver,
            data: formData,
            method: 'post'
          }).then((_merge_res: any) => {
            if (_merge_res?.status === 0) {
              const obj: FileValue = {
                ..._merge_res?.data,
                state: 'uploaded'
              };
              obj.value = obj.value || obj.url;
              cb(null, originalFile, obj);
            } else {
              cb(_merge_res?.msg, originalFile)
            }
          }).catch((_file_merge_res: any) => {
            cb('上传失败', originalFile)
            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) => {
        cb(_err, originalFile)
        return;
      })
    } catch (error) {
      cb(error, originalFile)
      return;
    }
  }

  removeFileCanelExecutor(file: any, execute = false) {
    this.fileUploadCancelExecutors = this.fileUploadCancelExecutors.filter(
      item => {
        if (execute && item.file === file) {
          item.executor();
        }

        return item.file !== file;
      }
    );
  }

  handleClick() {
    (this.refs.dropzone as any).open();
  }

  handleFrameImageLoaded(e: React.UIEvent<any>) {
    const imgDom = e.currentTarget;
    const img = new Image();
    const { clientHeight } = this.frameImageRef.current;

    const _this = this;
    img.onload = function () {
      const ratio = (this as any).width / (this as any).height;
      const finalWidth = (ratio * (clientHeight - 2)).toFixed(2);
      _this.setState({
        frameImageWidth: +finalWidth
      });
    };
    img.src = imgDom.src;
  }

  validate(): any {
    const __ = this.props.translate;

    if (this.state.locked && this.state.lockedReason) {
      return this.state.lockedReason;
    } else if (this.state.cropFile) {
      return new Promise(resolve => {
        this.resolve = resolve;
        this.handleCrop();
      });
    } else if (
      this.state.uploading ||
      this.files.some(item => item.state === 'pending')
    ) {
      return new Promise(resolve => {
        this.resolve = resolve;
        this.startUpload();
      });
    } else if (this.files.some(item => item.state === 'error')) {
      return __('File.errorRetry');
    }
  }
  //图片无法显示默认图片
  handleImageError(el: string, index: number) {
    const files = this.state.files.concat()
    const file = files[index]
    file.src = el ? el : this.errImg
    file.err = true
    files.splice(index, 1, file)
    this.setState({ files })
  }
  // 打印
  handleLabelPrint = (item: FileX) => {
    let list = item
    this.setState({
      ctx: {
        ...this.state.ctx,
        items: [list],
        rows: [list],
        selectedItems: [list],
        unSelectedItems: []
      }
    }, () => {
      const LODOP = getLodop()
      if (LODOP) {
        this.setState({
          _print_visible: true
        })
      }
    });
  }
  // 判断是否是pdf，图片，视频
  handlementCategory = (item: FileX) => {
    if (isImg(item.name) || isPdf(item.name)) {
      return true
    } else {
      return false
    }
  }
  // 进度条

  handprogress = (name: any) => {
    let { percent, size } = this.state.content[name]
    let speed: any = this.state.content
    const value = Number(((percent / size) * 100).toFixed(0))
    speed[name] = { ...this.state.content[name], percent: ++percent, pent: value !== Infinity ? value : 0 }
    this.setState({ content: speed }, () => {
      if (Number(((percent / size) * 100).toFixed(0)) == 100) {
        speed[name] = { ...this.state.content[name], percent: 0, pent: 0 }
        this.setState({ content: speed })
      }
    })
  }

  // 获取文件大小判断是否分流还有分流多大
  chunks = async (url: any, chunkSize = 524288, name: string) => {
    // "https://amis.bj.bcebos.com/amis/2019-12/1577157317579/trailer_hd.mp4"
    let staging = url.split("?").pop()
    let chunk = staging.split("=").pop()
    if (chunk === "1") {
      const datacontent = (await fetch(url, { method: "HEAD" })).headers.get("Content-Length") as string
      const contentSize = parseInt(datacontent);
      let previewvalue: any = this.state.content
      let speed: any = this.state.content
      previewvalue[name] = { "size": 0, "percent": 0, "pent": 0 }
      this.setState({ content: previewvalue }, () => {
        speed[name] = { ...this.state.content[name], size: Number((contentSize / chunkSize).toFixed(0)) }
        this.setState({ content: speed })
      })
      return contentSize;
    }
    return false
  }



  render() {
    const {
      className,
      classnames: cx,
      placeholder,
      disabled,
      multiple,
      accept,
      maxLength,
      autoUpload,
      hideUploadButton,
      thumbMode,
      thumbRatio,
      reCropable,
      frameImage,
      fixedSize,
      fixedSizeClassName,
      readonly,
      uploadText,
      translate: __,
      beauty,
      data,
      isImage,
      tabSample,
      name,
      popOverContainer
    } = this.props;
    const isMobileUI = isMobile();
    let data_detail = data[name as string];
    const { files, error, crop, uploading, cropFile, frameImageWidth, selectList, structure, setvideo, content } =
      this.state;
    let frameImageStyle: any = {};
    if (fixedSizeClassName && frameImageWidth && fixedSize) {
      frameImageStyle.width = frameImageWidth;
    }
    const filterFrameImage = filter(frameImage, this.props.data, '| raw');
    const hasPending = files.some(file => file.state == 'pending');
    return (
      <div className={cx(`ImageControl`, className, {
        'isMobile': isMobileUI
      })}>
        {cropFile ? (
          <div className={cx('ImageControl-cropperWrapper')}>
            <Suspense fallback={<div>...</div>}>
              <Cropper
                {...crop}
                onInitialized={instance => {
                  this.cropper = instance;
                }}
                src={cropFile.preview}
              />
            </Suspense>
            <div className={cx('ImageControl-croperToolbar')}>
              {crop.rotatable && (
                <a
                  className={cx('ImageControl-cropRotatable')}
                  onClick={this.rotatableCrop}
                  data-tooltip={__('rotate')}
                  data-position="left"
                >
                  <Icon icon="retry" className="icon" />
                </a>
              )}
              <a
                className={cx('ImageControl-cropCancel')}
                onClick={this.cancelCrop}
                data-tooltip={__('cancel')}
                data-position="left"
              >
                <Icon icon="close" className="icon" />
              </a>
              <a
                className={cx('ImageControl-cropConfirm')}
                onClick={this.handleCrop}
                data-tooltip={__('confirm')}
                data-position="left"
              >
                <Icon icon="check" className="icon" />
              </a>
            </div>
          </div>
        ) : (
          <DropZone
            key="drop-zone"
            ref={this.dropzone}
            onDrop={this.handleDrop}
            onDropRejected={this.handleDropRejected}
            accept={accept === '*' ? '' : accept}
            multiple={multiple}
            disabled={disabled}
          >
            {({
              getRootProps,
              getInputProps,
              isDragActive,
              isDragAccept,
              isDragReject,
              isFocused
            }) => {
              return (
                <div
                  {...getRootProps({
                    onClick: preventEvent,
                    onPaste: this.handlePaste,
                    className: cx('ImageControl-dropzone', {
                      'is-disabled': disabled,
                      'is-empty': !files.length,
                      'is-active': isDragActive
                    },
                      tabSample ? "ImageControl-formfile" : '')
                  })}
                  style={{ display: 'flex' }}
                >
                  <input {...getInputProps()} />

                  {isDragActive || isDragAccept || isDragReject ? (
                    <div
                      className={cx('ImageControl-acceptTip', {
                        'is-accept': isDragAccept,
                        'is-reject': isDragReject
                      })}
                    >
                      {__('Image.dragDrop')}
                    </div>
                  ) : (
                    <>
                      {
                        // 控制是否为链接形式文件
                        beauty ? (
                          <>
                            <div className="Papers-cell-view" style={{ display: 'flex', cursor: 'pointer', alignItems: 'center' }}>
                              <Tooltip
                                placement="bottom"
                                overlayInnerStyle={{
                                  background: '#fff',
                                  width: '298px',
                                  zIndex: 1000,
                                  borderRadius: '4px',
                                  border: '1px solid #ebeef5',
                                  lineHeight: '1.4',
                                  textAlign: 'justify',
                                  fontSize: '14px',
                                  wordBreak: "break-all",
                                  boxShadow: '0 2px 12px 0 rgb(0 0 0 / 10%)',
                                  padding: '3px 4px'
                                }}
                                zIndex={1000}
                                title={
                                  data_detail && data_detail.info && data_detail.info?.length > 0 ? <div className="Papers-cell-list" style={{ width: "290px", background: '#fff', color: '#333' }}>
                                    {
                                      data_detail.info.map((item: any, idx: number) => {
                                        return <WrapperFileView className="Papers-cell-list-item" key={item.name}>
                                          <Tooltip
                                            placement={idx === data_detail.info.length - 1 ? 'bottom' : 'top'}
                                            title={item.name}
                                            arrowPointAtCenter={true}
                                            overlayInnerStyle={{
                                              zIndex: 1000
                                            }}
                                            zIndex={1000}
                                          >
                                            <span className="Papers-cell-list-item-tooltip" style={{
                                              display: 'flex',
                                              justifyContent: 'space-between',
                                              alignItems: 'center',
                                              whiteSpace: 'nowrap',
                                              overflow: 'hidden',
                                              textOverflow: 'ellipsis',
                                            }}>
                                              <span className="fa fa-link" style={{
                                                fontSize: '13px'
                                              }} ></span>
                                              &nbsp;&nbsp;
                                              <span style={{
                                                whiteSpace: 'nowrap',
                                                overflow: 'hidden',
                                                textOverflow: 'ellipsis',
                                                fontSize: '12px',
                                                width: "150px"
                                              }}>

                                                {item.name}

                                              </span>
                                            </span>
                                          </Tooltip>
                                          {/* 删除按钮 */}
                                          <Tooltip overlayInnerStyle={{ zIndex: 1000 }} zIndex={9999} placement='top' title='删除'>
                                            <span style={{ border: 0, cursor: 'pointer' }} onClick={() => { this.removeFile(item, idx) }}> <span className="fa fa-remove" style={{ fontSize: '13px' }} ></span></span>
                                          </Tooltip>
                                          <Tooltip overlayInnerStyle={{ zIndex: 1000 }} zIndex={9999} placement='top' title='下载'>
                                            <span onClick={() => { downloadFile(item.downloadSrc, item.name) }} style={{ border: 0, cursor: 'pointer' }}><span className="fa fa-download" style={{ fontSize: '13px' }} ></span></span>
                                          </Tooltip>
                                          <Tooltip overlayInnerStyle={{ zIndex: 1000 }} zIndex={9999} placement='top' title='打开'>
                                            <span onClick={(e) => { this.previewImage(item, idx, e) }} style={{ border: 0, cursor: 'pointer', marginRight: '5px' }}><span className="fa fa-folder-open-o" style={{ fontSize: '13px' }} ></span></span>
                                          </Tooltip>
                                          {/* 打印 */}
                                          {/* <Tooltip overlayInnerStyle={{ zIndex: 1000 }} zIndex={9999} placement='top' title='打印'>
                                          <span onClick={() => { this.handleLabelPrint(item) }} style={{ border: 0, marginRight: '5px', cursor: this.matchPdfImg(item?.name) ? 'pointer' : 'not-allowed', color: this.matchPdfImg(item?.name) ? 'inherit' : '#999' }}><span className="fa fa-print" style={{ fontSize: '13px' }} ></span></span>
                                        </Tooltip> */}
                                        </WrapperFileView>
                                      })
                                    }
                                  </div> : null
                                }
                              >
                                <Tooltip
                                  overlayInnerStyle={{
                                    background: '#303133',
                                    width: '278px',
                                    height: 'auto',
                                    padding: '5px 8px',
                                    zIndex: 9000
                                  }}
                                  zIndex={9000}
                                  title={
                                    data_detail && data_detail.info && data_detail.info.length > 1 ? <div style={{ background: '#303133', display: 'flex', height: "auto", alignItems: 'center' }}
                                    >
                                      <span style={{
                                        color: '#fff'
                                      }}>
                                        <span style={{
                                          color: "#999",
                                          width: '50px'
                                        }}>附件：</span>
                                        {data_detail ? <span className="fa fa-link" style={{
                                          fontSize: '12px'
                                        }} ></span> : null}
                                        {data_detail ? data_detail?.info?.length : null}
                                        &nbsp;&nbsp;
                                        {
                                          data_detail && data_detail.info ?
                                            data_detail.info[0].name : null
                                        }
                                      </span>

                                    </div>
                                      : null
                                  }
                                  placement="top"
                                  mouseEnterDelay={0.5}
                                >
                                  <span
                                    style={{
                                      display: 'flex',
                                      cursor: data_detail ? 'pointer' : 'text',
                                      alignItems: 'center',
                                      color: "blue"
                                    }}>
                                    <span style={{
                                      display: 'flex',
                                      alignItems: 'center'
                                    }}>
                                      {data_detail ? <span className="fa fa-link" style={{
                                        fontSize: '12px'
                                      }} ></span> : null}
                                      {data_detail && data_detail.info && data_detail.info?.length > 0 ? data_detail?.info?.length : null}
                                      &nbsp;&nbsp;
                                      <span style={{
                                        whiteSpace: 'nowrap',
                                        overflow: 'hidden',
                                        textOverflow: 'ellipsis',
                                        maxWidth: '200px',
                                        minWidth: "100px",
                                        marginRight: "10px"
                                      }}>
                                        {
                                          data_detail && data_detail.info && data_detail.info?.length > 0 ?
                                            data_detail.info[0].name : '暂无附件'
                                        }
                                      </span>
                                      {data_detail && data_detail.info ? (data_detail.info.length > 1 ? <span className="fa fa-angle-down" style={{
                                        marginLeft: '10px',
                                        fontWeight: 400,
                                        fontSize: '12px',
                                        color: "#999"

                                      }} ></span> : null) : null}
                                    </span>
                                  </span>
                                </Tooltip>
                              </Tooltip>
                            </div>
                            {
                              // 上传
                              !readonly && ((multiple && (!maxLength || files.length < maxLength)) ||
                                (!multiple && !files.length)) ? (
                                <label
                                  className={cx(
                                    'ImageControl-addBtn',
                                    {
                                      'is-disabled': disabled,
                                    },
                                    fixedSize ? 'ImageControl-fixed-size' : '',
                                    fixedSize ? fixedSizeClassName : '',
                                    beauty ? 'ImageControl-beauty' : ''
                                  )}
                                  style={frameImageStyle}
                                  onClick={this.handleSelect}
                                  data-tooltip={isMobile() ? null : __(placeholder)}
                                  data-position="right"
                                  ref={this.frameImageRef}
                                >
                                  {filterFrameImage ? (
                                    <ImageComponent
                                      key="upload-default-image"
                                      src={filterFrameImage}
                                      className={cx(
                                        fixedSize ? 'Image-thumb--fixed-size' : ''
                                      )}
                                      onLoad={this.handleFrameImageLoaded.bind(this)}
                                      thumbMode={thumbMode}
                                      thumbRatio={thumbRatio}
                                    />
                                  ) : (
                                    <>
                                      <Icon icon="upload" className="icon" />
                                      {/* 上传文件 */}
                                      <span>{uploadText || __('File.upload')}</span>
                                    </>
                                  )}


                                </label>
                              ) : null
                            }
                          </>
                        ) : (

                          <>
                            {
                              tabSample ?
                                (files && files.length ?
                                  (
                                    files.map((item: any, index: number) => {
                                      return < Popover
                                        content={
                                          <CellPopover
                                            tabSample={tabSample}
                                            mediaList={files}
                                            singlePhoto={item}
                                            selectList={selectList}
                                            readonly={readonly}
                                            isImage={isImage}
                                            formatFileSize={LionUpload.formatFileSize}
                                            Print={() => this.handlementCategory(item)}
                                            // 打印
                                            printMedia={() => this.handleLabelPrint(item)}
                                            //删除
                                            remove={() => { this.removeFile(item, index) }}
                                            // 下载
                                            downloadMedia={
                                              () => downFile(
                                                // 获取文件大小判断是否分流还有分流多大
                                                this.chunks,
                                                // url
                                                item.downloadSrc,
                                                //名字
                                                item.name,
                                                // 进度条
                                                this.handprogress

                                              )
                                            }
                                            previewMedia={(e: any) => { this.previewImage?.(item, index, e) }}
                                          />
                                        }
                                        trigger={isMobile() ? [] : 'hover'}
                                        // trigger="click"
                                        placement='bottom'
                                        destroyTooltipOnHide={true}
                                        getPopupContainer={popOverContainer}
                                        overlayClassName='table-media-format-popover'
                                      >
                                        <div className={cx('Cell-img-wrapper')}>
                                          <img
                                            key={item.value || index}
                                            src={item.thumbnailAddr || item.url}
                                            className={cx('Cell-img')}
                                            onClick={(e) => {
                                              this.previewImage?.(item, index, e)
                                            }}
                                            onError={(e) => this.handleImageError(item.src, index)}
                                          />
                                          {
                                            content[item.name]?.pent !== "Infinity" && content[item.name]?.pent > 0 &&
                                            <div style={{ display: "inline-block", width: 30, height: 30 }}>
                                              < Progress type="circle" style={{ margin: "auto" }} key={index} percent={content[item.name]?.pent} width={25} />
                                            </div>
                                          }
                                        </div>
                                      </Popover>
                                    })
                                  )
                                  : "-")

                                :
                                files && files.length
                                  ? files.map((file, key) => (
                                    <div
                                      key={file.id || key}
                                      className={cx(
                                        'ImageControl-item',
                                        {
                                          'is-uploaded': file.state !== 'uploading',
                                          'is-invalid':
                                            file.state === 'error' ||
                                            file.state === 'invalid',
                                          'readonly-mode': readonly || (!multiple && files.length),

                                        },
                                        fixedSize ? 'ImageControl-fixed-size' : '',
                                        fixedSize ? fixedSizeClassName : ''
                                      )}
                                      style={frameImageStyle}
                                    >
                                      {file.state === 'invalid' || file.state === 'error' ? (
                                        <div className={cx('ImageControl-image')}>
                                          {
                                            !readonly
                                              ? <a
                                                className={cx('ImageControl-itemClear')}
                                                data-tooltip={__('Select.clear')}
                                                data-position="bottom"
                                                onClick={this.removeFile.bind(
                                                  this,
                                                  file,
                                                  key
                                                )}
                                              >
                                                <Icon icon="close" className="icon" />
                                              </a>
                                              : null
                                          }

                                          {
                                            !file.errorMsg
                                              ? <a
                                                className={cx(
                                                  'ImageControl-retryBtn',
                                                  {
                                                    'is-disabled': disabled
                                                  },
                                                  fixedSize ? 'ImageControl-fixed-size' : '',
                                                  fixedSize ? fixedSizeClassName : ''
                                                )}
                                                onClick={this.handleRetry.bind(this, key)}
                                              >
                                                <Icon icon="retry" className="icon" />
                                                <p className="ImageControl-itemInfoError">
                                                  {__('File.repick')}
                                                </p>
                                              </a>
                                              : <a className={cx('ImageControl-retryBtn')}>
                                                <p className="errorMsg">
                                                  {file.errorMsg}
                                                </p>
                                              </a>
                                          }

                                        </div>
                                      ) : file.state === 'uploading' ? (
                                        <div className={cx('ImageControl-image')}>
                                          <a
                                            onClick={this.removeFile.bind(
                                              this,
                                              file,
                                              key
                                            )}
                                            key="clear"
                                            className={cx('ImageControl-itemClear')}
                                            data-tooltip={__('Select.clear')}
                                          >
                                            <Icon icon="close" className="icon" />
                                          </a>
                                          <div
                                            key="info"
                                            className={cx(
                                              'ImageControl-itemInfo',
                                              fixedSize ? 'ImageControl-fixed-size' : '',
                                              fixedSize ? fixedSizeClassName : ''
                                            )}
                                          >
                                            <p>{__('File.uploading')}</p>
                                            <div className={cx('ImageControl-progress')}>
                                              <span
                                                style={{
                                                  width: `${Math.round(
                                                    file.progress * 100
                                                  )}%`
                                                }}
                                                className={cx(
                                                  'ImageControl-progressValue'
                                                )}
                                              />
                                            </div>
                                            <p>{__('File.uploading')}</p>
                                          </div>
                                        </div>
                                      ) : (
                                        <>
                                          {isMobileUI ? <div className='show-img-container'>
                                            <div className='img-left'>
                                              <img onClick={(e) => {
                                                this.previewImage(file as FileX, key, e)
                                              }} style={{ width: '100%' }} src={file.thumbnailAddr || file.url} />
                                            </div>
                                            <div className='img-right'>
                                              <div className='img-name'>{file.fileName || file.name}</div>
                                              <div className='img-size'>{LionUpload.formatFileSize(file.size)}</div>
                                            </div>
                                            {!readonly && !disabled ? <div className='img-del'>
                                              <CloseCircleOutlined onClick={this.removeFile.bind(this, file, key)} />
                                            </div> : null}
                                          </div> : <ImageComponent
                                            key="image"
                                            className={cx(
                                              'ImageControl-image',
                                              fixedSize ? 'Image-thumb--fixed-size' : '',
                                              isImage ? "" : "ImageControl-file"
                                            )}
                                            src={file.thumbnailAddr || file.url}
                                            originalSrc={file.preview}
                                            alt={file.fileName}
                                            thumbMode={thumbMode}
                                            thumbRatio={thumbRatio}
                                            // fileName={file.fileName}
                                            // 非图片格式缩略图使用图标填充
                                            imageClassName={file.isNotImg ? 'icon-fill' : ''}
                                            overlays={
                                              <>
                                                {/* 查看大图 */}
                                                <a
                                                  data-tooltip={isCon(file.name) ? "查看视频" : __('Image.zoomIn')}
                                                  data-position="bottom"
                                                  target="_blank"
                                                  rel="noopener"
                                                  href={file.url || file.preview}
                                                  onClick={this.previewImage.bind(
                                                    this,
                                                    file,
                                                    key
                                                  )}
                                                >
                                                  <Icon icon="view" className="icon" />
                                                </a>
                                                {/* 剪裁编辑 */}
                                                {!!crop &&
                                                  reCropable !== false &&
                                                  !disabled ? (
                                                  <a
                                                    data-tooltip={__('Image.crop')}
                                                    data-position="bottom"
                                                    onClick={this.editImage.bind(
                                                      this,
                                                      key
                                                    )}
                                                  >
                                                    <Icon
                                                      icon="pencil"
                                                      className="icon"
                                                    />
                                                  </a>
                                                ) : null}
                                                {/* 下载 */}
                                                <a
                                                  data-tooltip={__('download')}
                                                  data-position="bottom"
                                                  onClick={() => downloadFile(file.downloadSrc, file.name)}
                                                >
                                                  <Icon icon="download" className="icon" />
                                                </a>
                                                {/* 移除 */}
                                                {!readonly && !disabled ? (
                                                  <a
                                                    data-tooltip={__('Select.clear')}
                                                    data-position="bottom"
                                                    onClick={this.removeFile.bind(
                                                      this,
                                                      file,
                                                      key
                                                    )}
                                                  >
                                                    <Icon icon="remove" className="icon" />
                                                  </a>
                                                ) : null}

                                              </>
                                            }
                                          />}
                                          {/* 判断是不是图片，图片无文字，文件有文字 */
                                            !isMobile() && (isImage ? null :
                                              (
                                                <>
                                                  <p className='image-info'>{file.name}</p>
                                                  <p className='image-info'>{file.size && LionUpload.formatFileSize(file.size)}</p>
                                                </>
                                              ))
                                          }
                                        </>
                                      )}
                                    </div>
                                  ))
                                  : null
                            }
                            {
                              // 上传
                              !readonly && ((multiple && (!maxLength || files.length < maxLength)) ||
                                (!multiple && !files.length)) ? (

                                <label
                                  className={cx(
                                    'ImageControl-addBtn',
                                    {
                                      'is-disabled': disabled
                                    },
                                    fixedSize ? 'ImageControl-fixed-size' : '',
                                    fixedSize ? fixedSizeClassName : ''
                                  )}
                                  style={frameImageStyle}
                                  onClick={this.handleSelect}
                                  data-tooltip={isMobile() ? null : __(placeholder)}
                                  data-position="right"
                                  ref={this.frameImageRef}
                                >
                                  {filterFrameImage ? (
                                    <ImageComponent
                                      key="upload-default-image"
                                      src={filterFrameImage}
                                      className={cx(
                                        fixedSize ? 'Image-thumb--fixed-size' : ''
                                      )}
                                      onLoad={this.handleFrameImageLoaded.bind(this)}
                                      thumbMode={thumbMode}
                                      thumbRatio={thumbRatio}
                                    />
                                  ) : (
                                    isMobileUI ? <PlusCircleOutlined /> : tabSample ?
                                      <Icon icon="plus" className="icon" />
                                      :
                                      <>
                                        <Icon icon="plus" className="icon" />
                                        {/* 上传文件 */}
                                        <span>{uploadText || __('File.upload')}</span>
                                      </>
                                  )}

                                  {
                                    isFocused && !isMobile ? (
                                      <span className={cx('ImageControl-pasteTip')}>
                                        {__('Image.pasteTip')}
                                      </span>
                                    ) : null}
                                </label>
                              ) : null
                            }
                          </>
                        )
                      }

                      {!autoUpload && !hideUploadButton && files.length ? (
                        <Button
                          level="default"
                          className={cx('ImageControl-uploadBtn')}
                          disabled={!hasPending}
                          onClick={this.toggleUpload}
                        >
                          {__(uploading ? 'File.pause' : 'File.start')}
                        </Button>
                      ) : null}


                      {error ? (
                        <div className={cx('ImageControl-errorMsg')}>{error}</div>
                      ) : null}
                      {/*视频 */}


                      {/* 打印弹窗 */}
                      {this.state._print_visible && <ModalPrint printType='file' {...this.props as any} isSingleFilePrint={true} ctx={this.state.ctx as any} show={this.state._print_visible} onHide={() => { this.setState({ _print_visible: false }) }}></ModalPrint>}
                    </>
                  )
                  }
                </div>
              )
            }}
          </DropZone>
        )
        }
        {
          setvideo && <Modal title="视频" visible={setvideo} zIndex={1011}
            maskClosable={false}
            destroyOnClose={true}
            width={isMobile() ? "100%" : "55%"}
            keyboard={false}
            okText='关闭'
            cancelButtonProps={{ style: { display: 'none' } }}
            onOk={() => { this.setState({ setvideo: false }) }}
            onCancel={() => { this.setState({ setvideo: false }) }}
            getContainer={this.props.env.getModalContainer}
          >
            {
              this.props.render("Video", structure)
            }
          </Modal >
        }
      </div >
    );
  }
}

@FormItem({
  type: 'lion-upload',
  sizeMutable: false
})
export class LionUploadRenderer extends LionUpload { }
