var _excluded = ["encrypt", "validFileType", "filterErrorFile", "maxSize", "bucketName", "AppKey", "trunkSize", "maxCount", "transformType", "onChange", "getInstance", "fileList", "extra", "dragger", "canRepeat", "text", "children"];
function _typeof(obj) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (obj) { return typeof obj; } : function (obj) { return obj && "function" == typeof Symbol && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }, _typeof(obj); }
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
/**
 * 大附件直传、加密上传组件
 * @author 施阳 2020-07-18
 * @description
 * 1、支持加密的文件格式组件内部会自动根据文件类型进行加密；文档类型KM转码加密，音视频文件云信转码加密。
 * 2、不支持加密的文件格式若采用加密上传组件，会通过nos直传的模式上传
 * @param {Boolean} dragger 是否为拖拽上传组件
 * @param {Boolean} canRepeat 是否能重复上传相同附件
 * @param {String} text 上传按钮文件
 * @param {Number} trunkSize 分片附件大小 默认4M（4 * 1024 * 1024）
 * @param {Array} validFileType 支持上传的附件类型
 * @param {Array | Object} fileList 附件
 * @param {Number} maxCount 最大上传个数
 * @param {Number} maxSize 最大上传文件大小
 * @param {ReactNode} extra 额外展示内容
 */
import React, { useState, useEffect, useMemo, useRef, useContext } from 'react';
import { Upload, Button, message, Modal, Tooltip, Image } from 'antd';
import { UploadOutlined, InboxOutlined, LockOutlined, PaperClipOutlined, DownloadOutlined, DeleteOutlined } from '@ant-design/icons';
import $ from 'jquery/src/core';
import 'jquery/src/ajax';
import 'jquery/src/ajax/xhr';
import MD5 from 'crypto-js/md5';
import { useConfig } from "../_util/hooks";
import { EHR_SERVICE } from "../_util/constants";
import { FilePreview } from "../preview";
import NosUploader from "./nos-js-sdk";
import VCloudUploader from "./vcloud-js-sdk";
import { ConfigContext } from "../config-provider/context";
var MAX_SIZE = 5 * 1024 * 1024 * 1024; // 最大上传文件大小，默认5G
var TRUNK_SIZE = 4 * 1024 * 1024; // 默认分片大小4M，合法值[0, 4M]
var kmType = ['pdf', 'ppt', 'pptx', 'doc', 'docx']; // 能KM加密的文档格式
var videoType = ['wmv', 'asf', 'asx', 'rm', 'rmvb', 'mp4', '3gp', 'mov', 'm4v', 'avi', 'dat', 'mkv', 'flv', 'vob']; // 能云信加密的视频格式
var audioType = ['wav', 'flac', 'ape', 'alac', 'wv', 'mp3', 'aac', 'ogg', 'vorbis', 'opusdeng']; // 音频格式

// 格式化参数(手动添加uid)
var formatData = function formatData(data) {
  if (!data) return [];
  return Array.isArray(data) ? data.map(function (item) {
    return item = _objectSpread({
      uid: item.nosKey || item.uid
    }, item);
  }) : [_objectSpread({
    uid: data.nosKey || data.uid
  }, data)];
};

// 获取文件类型
var getFileType = function getFileType(fileName) {
  var _fileName$split$pop;
  return ((_fileName$split$pop = fileName.split('.').pop()) === null || _fileName$split$pop === void 0 ? void 0 : _fileName$split$pop.toLowerCase()) || '';
};

// 获取加密方式
var getEncryptType = function getEncryptType() {
  var transformType = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : ['KM', 'YX'];
  var fileType = arguments.length > 1 ? arguments[1] : undefined;
  var encrypt = arguments.length > 2 ? arguments[2] : undefined;
  // 加密上传时才会有转码类型
  if (encrypt) {
    // 视频格式，且支持云信加密
    if (videoType.includes(fileType) && transformType.includes('YX')) {
      return 'YX_VIDEO';
    }

    // 音频格式，且支持云信加密
    if (audioType.includes(fileType) && transformType.includes('YX')) {
      return 'YX_AUDIO';
    }
  }

  // 文档格式，且支持KM文档加密
  if (kmType.includes(fileType) && transformType.includes('KM')) {
    return 'KM';
  }
  return 'NONE';
};
export default (function (props) {
  var componentContext = useContext(ConfigContext);
  var uiLocale = componentContext.uiLocale;
  var _props$encrypt = props.encrypt,
    encrypt = _props$encrypt === void 0 ? false : _props$encrypt,
    validFileType = props.validFileType,
    _props$filterErrorFil = props.filterErrorFile,
    filterErrorFile = _props$filterErrorFil === void 0 ? true : _props$filterErrorFil,
    _props$maxSize = props.maxSize,
    maxSize = _props$maxSize === void 0 ? MAX_SIZE : _props$maxSize,
    _props$bucketName = props.bucketName,
    bucketName = _props$bucketName === void 0 ? 'rms' : _props$bucketName,
    _props$AppKey = props.AppKey,
    AppKey = _props$AppKey === void 0 ? '765c863df7ec8f8e2f545a4cf2633fcf' : _props$AppKey,
    _props$trunkSize = props.trunkSize,
    trunkSize = _props$trunkSize === void 0 ? TRUNK_SIZE : _props$trunkSize,
    _props$maxCount = props.maxCount,
    maxCount = _props$maxCount === void 0 ? Infinity : _props$maxCount,
    transformType = props.transformType,
    onChange = props.onChange,
    getInstance = props.getInstance,
    fileList = props.fileList,
    extra = props.extra,
    _props$dragger = props.dragger,
    dragger = _props$dragger === void 0 ? false : _props$dragger,
    _props$canRepeat = props.canRepeat,
    canRepeat = _props$canRepeat === void 0 ? false : _props$canRepeat,
    _props$text = props.text,
    text = _props$text === void 0 ? uiLocale.Upload.text : _props$text,
    children = props.children,
    rest = _objectWithoutProperties(props, _excluded);
  var isImg = ['picture-card', 'picture'].includes(rest.listType || ''); // 是否为图片

  var prefixCls = 'ehr-ui';
  var _useState = useState(fileList),
    _useState2 = _slicedToArray(_useState, 2),
    value = _useState2[0],
    setValue = _useState2[1];
  var tempTransformType = useRef();

  // 记录直传实例，以{ uid: uploader } 形式存储，方便在组件卸载的时候暂停正在上传的文件
  var uploaderRef = useRef({});
  useEffect(function () {
    setValue(fileList);
  }, [fileList]);

  // 格式化fileList
  var formatValue = useMemo(function () {
    return formatData(value);
  }, [value]);

  // 组件卸载时，中断文件上传（目前云信上传SDK不支持中断上传功能）
  useEffect(function () {
    return function () {
      Object.keys(uploaderRef.current).map(function (uid) {
        uploaderRef.current[uid].pauseUpload();
      });
    };
  }, []);

  // 附件上传前的钩子函数(即使return false 还是会触发一次onChange)
  var beforeUpload = function beforeUpload(file, fileList) {
    var fileType = getFileType(file.name);
    tempTransformType.current = getEncryptType(transformType, fileType, encrypt);

    // 校验文件名称长度
    if (file.name.length > 100) {
      message.error(uiLocale.Upload.fileNameLongError);
      return false;
    }

    // 校验文件格式
    if (validFileType && (!fileType || !validFileType.map(function (item) {
      return item.toLocaleLowerCase();
    }).includes(fileType))) {
      message.error(uiLocale.Upload.fileTypeError);
      return false;
    }

    // 校验文件大小
    if (file.size > maxSize) {
      message.error(uiLocale.Upload.maxSizeError);
      return false;
    }

    // 校验是否重复上传
    if (!canRepeat && formatValue.some(function (item) {
      return item.name === file.name;
    })) {
      message.warning(uiLocale.Upload.repeatError);
      return false;
    }

    // 自定义校验规则
    if (rest.beforeUpload) return rest.beforeUpload(file, fileList);
    return true;
  };

  // KM 转码（转码成功后会输出文档转码ID）
  var KMTransform = function KMTransform(nosKey, fileName, url) {
    return new Promise(function (resolve, reject) {
      $.ajax({
        type: 'post',
        url: EHR_SERVICE + '/api/office/km/file/convert',
        data: JSON.stringify({
          dataId: nosKey,
          fileName: fileName,
          fileUrl: url
        }),
        dataType: 'json',
        contentType: 'application/json;charset=utf-8',
        // 数据必须转换为字符串
        success: function success(res) {
          var _res$data;
          return resolve(res === null || res === void 0 ? void 0 : (_res$data = res.data) === null || _res$data === void 0 ? void 0 : _res$data.fileId);
        },
        error: function error() {
          message.error(uiLocale.Upload.convertError);
          reject();
        }
      });
    });
  };

  // 获取nos文件url
  var getNosUrl = function getNosUrl(nosKey, bucketName, fileName) {
    return new Promise(function (resolve, reject) {
      $.ajax({
        type: 'get',
        url: EHR_SERVICE + '/api/file/nos/url',
        data: {
          nosKey: nosKey,
          bucketName: bucketName,
          fileName: encodeURIComponent(fileName),
          fileNameEncode: 'URL_ENCODE'
        },
        // 数据必须转换为字符串
        success: function success(res) {
          return res.code === 200 ? resolve(res.data) : reject();
        },
        error: reject
      });
    });
  };

  // nos 上传模式
  var nosUpload = function nosUpload(option) {
    var file = option.file,
      _onProgress = option.onProgress,
      _onError = option.onError,
      onSuccess = option.onSuccess;
    var _ref = file,
      name = _ref.name,
      size = _ref.size,
      uid = _ref.uid;
    if (file) {
      // 初始化配置
      var uploader = NosUploader({
        onProgress: function onProgress(curFile) {
          _onProgress && _onProgress({
            percent: +curFile.progress
          });
        },
        onError: function onError(errObj) {
          message.error(uiLocale.Upload.commonError);
          _onError && _onError(errObj);
        }
      });

      // 添加文件
      uploader.addFile(file, function () {
        var nosKey = MD5(name + ':' + size + ':' + new Date().getTime()).toString(); // 存储在NOS的对象名(前端生成一个唯一索引)

        // 获取
        $.ajax({
          type: 'get',
          url: EHR_SERVICE + '/api/file/nos/token',
          // 获取上传凭证接口
          data: {
            nosKey: nosKey,
            bucketName: bucketName
          },
          dataType: 'json',
          success: function success(_ref2) {
            var _ref2$data = _ref2.data,
              token = _ref2$data === void 0 ? '' : _ref2$data;
            // 文件上传
            var param = {
              bucketName: bucketName,
              // 桶名
              objectName: nosKey,
              // 存储在NOS的对象名(前端生成一个唯一索引)
              token: token,
              // 上传凭证
              trunkSize: trunkSize
            };
            uploader.upload(param, function (curFile) {
              getNosUrl(nosKey, bucketName, curFile.fileName).then(function (url) {
                var rep = {
                  nosKey: nosKey,
                  url: url
                }; // 组装response

                // KM转码流程
                if (tempTransformType.current === 'KM') {
                  KMTransform(nosKey, curFile.fileName, url).then(function (transformId) {
                    return onSuccess && onSuccess(_objectSpread(_objectSpread({}, rep), {}, {
                      transformType: 'KM',
                      transformId: transformId
                    }), new XMLHttpRequest());
                  }).catch(function () {
                    _onError && _onError(new Error());
                  });
                } else {
                  onSuccess && onSuccess(_objectSpread(_objectSpread({}, rep), {}, {
                    transformType: tempTransformType.current
                  }), new XMLHttpRequest());
                }
              }).catch(function (errObj) {
                message.error(uiLocale.Upload.commonError);
                _onError && _onError(errObj);
              });
            });
          },
          error: function error(errObj) {
            message.error(uiLocale.Upload.commonError);
            _onError && _onError(errObj);
          }
        });
      });
      uploaderRef.current = _objectSpread(_objectSpread({}, uploaderRef.current), {}, _defineProperty({}, uid, uploader));
    }
  };

  // 云信上传模式
  var yxUpload = function yxUpload(option) {
    var file = option.file,
      _onProgress2 = option.onProgress,
      _onError2 = option.onError,
      _onSuccess = option.onSuccess;
    if (file) {
      $.ajax({
        type: 'get',
        url: EHR_SERVICE + '/api/yunxin/yunxin/checkSum',
        dataType: 'json',
        success: function success(res) {
          var data = res.data || {};
          // 初始化配置
          var uploader = VCloudUploader({
            AppKey: AppKey,
            nonce: data.nonce,
            curTime: data.curTime,
            checkSum: data.checkSum,
            onProgress: function onProgress(curFile) {
              _onProgress2 && _onProgress2({
                percent: +curFile.progress
              });
            },
            onSuccess: function onSuccess(res) {
              var url = res.downloadOrigUrl.replace('http://', 'https://');
              _onSuccess && _onSuccess({
                yxInfo: res,
                transformType: tempTransformType.current,
                nosKey: 'yx-' + res.vid,
                transformId: res.vid,
                url: url
              }, new XMLHttpRequest());
            },
            onError: function onError(errObj) {
              message.error(uiLocale.Upload.commonError);
              _onError2 && _onError2(errObj);
            }
          });
          uploader.initCustom(file);
        },
        error: function error(errObj) {
          message.error(uiLocale.Upload.commonError);
          _onError2 && _onError2(errObj);
        }
      });
    }
  };

  // 自定义上传
  var customRequest = function customRequest(e) {
    if (tempTransformType.current === 'YX_VIDEO') {
      yxUpload(e);
    } else {
      nosUpload(e);
    }
  };

  // 文件上传进行中持续调用
  var onChangeFile = function onChangeFile(info) {
    var file = info.file,
      fileList = info.fileList;

    /**
     * beforeUpload钩子函数即使返回值为false任然会触发一次onChange
     * 此时我们需要过滤掉不满足校验规则的附件，过滤规则是判断附件是否有status属性
     * 不把校验逻辑写在onChange方法中是因为文件上传时，该方法会持续调用，而beforeUpload函数只会调用一次
     * https://github.com/ant-design/ant-design/issues/15561
     */
    if (file.status === undefined) return;

    // 自定义上传列表(过滤掉上传失败的文件)
    if (filterErrorFile) {
      fileList = fileList.filter(function (item) {
        return item.status !== 'error';
      });
    }

    // 解构服务器响应的内容（避免在业务层取response中的内容）
    fileList = fileList.map(function (item) {
      return _objectSpread(_objectSpread({
        canDownload: !encrypt
      }, item), item.response || {});
    });
    file = _objectSpread(_objectSpread({
      canDownload: !encrypt
    }, file), file.response || {});
    setValue(fileList);

    // 单个附件上传返回文件对象
    onChange && onChange(maxCount === 1 ? fileList[0] : fileList, file);
  };

  // 删除文件（删除正在上传的文件则暂停上传）
  var onRemove = function onRemove(file) {
    uploaderRef.current[file.uid] && uploaderRef.current[file.uid].pauseUpload();
    rest.onRemove && rest.onRemove(file);
  };

  // 预览(目前只支持KM文件预览、照片预览)
  var _useState3 = useState({}),
    _useState4 = _slicedToArray(_useState3, 2),
    currFile = _useState4[0],
    setFile = _useState4[1]; // 当前上传文件

  var onPreview = function onPreview(file) {
    if (!(file.transformType === 'KM' || isImg)) {
      message.warning(uiLocale.Upload.notSupportPreview);
      return;
    }
    setFile(_objectSpread({}, file));
  };

  // 暴露内置方法
  useEffect(function () {
    getInstance === null || getInstance === void 0 ? void 0 : getInstance({
      nosUpload: nosUpload,
      yxUpload: yxUpload
    });
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  // 组件参数
  var params = _objectSpread(_objectSpread({
    progress: {
      size: 'small',
      format: function format(percent) {
        return percent && "".concat(parseFloat(percent.toFixed(1)), "%");
      }
    },
    fileList: formatValue,
    onRemove: onRemove,
    onPreview: onPreview,
    showUploadList: {
      showPreviewIcon: true,
      showRemoveIcon: true,
      showDownloadIcon: true,
      downloadIcon: function downloadIcon() {
        return /*#__PURE__*/React.createElement(DownloadOutlined, null);
      },
      removeIcon: function removeIcon() {
        return /*#__PURE__*/React.createElement(DeleteOutlined, {
          style: {
            color: '#ff4d4f'
          }
        });
      }
    },
    iconRender: function iconRender(file) {
      return !file.canDownload ? /*#__PURE__*/React.createElement(Tooltip, {
        title: uiLocale.Upload.lockTooltip
      }, /*#__PURE__*/React.createElement(LockOutlined, null)) : /*#__PURE__*/React.createElement(PaperClipOutlined, null);
    }
  }, rest), {}, {
    beforeUpload: beforeUpload,
    onChange: onChangeFile,
    customRequest: customRequest
  });
  return useConfig( /*#__PURE__*/React.createElement(React.Fragment, null, dragger ? /*#__PURE__*/React.createElement(Upload.Dragger, _extends({}, params, {
    style: {
      display: formatValue.length < maxCount ? 'block' : 'none'
    }
  }), children ? children : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("p", {
    className: "".concat(prefixCls, "-upload-drag-icon")
  }, /*#__PURE__*/React.createElement(InboxOutlined, null)), /*#__PURE__*/React.createElement("p", {
    className: "".concat(prefixCls, "-upload-text")
  }, uiLocale.Upload.dragUploadText), extra && /*#__PURE__*/React.createElement("p", {
    className: "".concat(prefixCls, "-upload-hint")
  }, props.extra))) : /*#__PURE__*/React.createElement(Upload, params, formatValue.length < maxCount && (children ? children : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Button, {
    type: "primary"
  }, /*#__PURE__*/React.createElement(UploadOutlined, null), " ", text), extra && /*#__PURE__*/React.createElement("p", {
    className: "".concat(prefixCls, "-upload-hint")
  }, extra)))), isImg && /*#__PURE__*/React.createElement(Image, {
    width: 0,
    src: currFile.url,
    preview: {
      visible: !!currFile.url,
      onVisibleChange: function onVisibleChange() {
        return setFile({});
      }
    }
  }), currFile.transformType === 'KM' && /*#__PURE__*/React.createElement(Modal, {
    destroyOnClose: true,
    footer: null,
    open: !!currFile.url,
    width: 1000,
    onCancel: function onCancel() {
      return setFile({});
    }
  }, /*#__PURE__*/React.createElement(FilePreview, {
    file: currFile
  }))));
});