<template>
  <div>
    <div style="margin-bottom:20px;display: grid;grid-template-columns: 80px auto;">
      <span style="margin-top:20px;color: white;">选择目录：</span>
      <el-tree class="myTree" :data="treeData" node-key="id" show-checkbox :expand-on-click-node="false" :default-expanded-keys="[fl_type]"
        highlight-current :props="defaultProps" :check-strictly="true" ref="tree" @check-change="handleCheckChange"
        :indent=1>
      </el-tree>
    </div>
    <div class="uploadWrapper">
      <div class="btnUpload">
        <div id="picker" class="form-control-focus">点击选择文件上传</div>
        <el-button type="danger" plain size="mini" style="height: 26px;" v-if="fileList.length>0" @click="removeFileAll()">全部删除</el-button>
      </div>
      <div id="thelist" class="uploader-list">
        <ul>
          <li v-for="(item, index) in  fileList ">
            <div class="div-a">
              <span :title="item.name">{{ item.name }}</span>
              <i class="el-icon-circle-close" style="font-size: 20px;margin-left: 16px;cursor: pointer;color: #ff4040;" @click="removeFile(item, index)"></i>
            </div>
            <span
              :class="[item.state == 1 ? 'el-icon-loading' : item.state == 2 ? 'el-icon-success' : item.state == 3 ? 'el-icon-warning' : '']">{{
        item.description }}</span>
            <a @click="retry(item, index)" v-if="item.state == 3"><span title="点击重试"
                class="el-icon-refresh-right"></span></a>
            <el-progress :text-inside="true" :stroke-width="14" :percentage="item.percentage"
              status="success"></el-progress>
          </li>
        </ul>
      </div>
      <el-button class="startUpload" type="primary" @click="upload()">开始上传</el-button>
    </div>
  </div>
</template>
<script>
import $ from "jquery";
import WebUploader from "webuploader";
import "webuploader/dist/webuploader.css";
import { ACCESS_TOKEN, ACCESS_USER, HTTP_STATUS } from "../../constant/user";
import { format_file} from '../../util/http_util'
export default {
  props: {
    addFileInfo: {
      type: Function
    },
    checkFileExist: {
      type: Function
    },
    treeDataBig: {
      type: Array
    },
    flType:{
      type:Number
    }
  },
  data() {
    return {
      fileList: [],
      headers: { 'x-requested-with': 'XMLHttpRequest' },
      clientDetails_check_type: [],
      treeData: [],
      defaultProps: {
        children: 'children',
        label: 'label'
      },
      fl_type:0,
      size:0,
      maxSize:3*1024*1024*1024,//3个G
    };
  },
  mounted() {
    this.headers[ACCESS_TOKEN] = sessionStorage.getItem("token");
    var _self = this;
    //必须先注销原来的，否则服务会执行多次
    WebUploader.Uploader.unRegister("uploadBigFile");
    //监听分块上存过程中的三个时间点
    WebUploader.Uploader.register(
      {
        "name": "uploadBigFile",
        // 在文件发送之前执行
        "before-send-file": "beforeSendFile",
        // 在文件分片（如果没有启用分片，整个文件被当成一个分片）后，上传之前执行
        "before-send": "beforeSend",
        // 在文件所有分片都上传完后，且服务端没有错误返回后执行
        "after-send-file": "afterSendFile",
      },
      {
        //时间点1:所有分块进行上存之前触发该方法,即当每个文件开始上传第一个分块前就调用该方法
        beforeSendFile: function (file) {
          //定义一个异步对象
          var deferred = WebUploader.Deferred();
          uploader
            .md5File(file, 0, 3 * 1024 * 1024)
            .progress((percentage) => {
              _self.getProgressBar(file, percentage);
            })
            .then((val) => {
              file.md5 = val;
              file.uid = WebUploader.Base.guid();
              Promise.resolve()
                .then(res => {
                  if (_self.checkFileExist) {
                    return _self.checkFileExist(val);
                  } else {
                    return Promise.resolve(false);
                  }
                }).then(res => {
                  if (res) {
                    return Promise.reject({ message: "文件已存在" });
                  } else {
                    return _self.post(`api/rest/file/bigFile/check?fileMd5=${val}`);
                  }
                }).then(res => {
                  //  文件已经上传过,忽略上传过程，直接标识上传成功；
                  if (res) {
                    uploader.skipFile(file);
                    file.pass = true;
                    _self.getProgressBar(file, 1);
                  } else {
                    //文件没有上传过，下标为0 文件上传中断过，返回当前已经上传到的下标
                    file.indexcode = 0;
                  }
                  deferred.resolve();
                }).catch(err => {
                  deferred.reject(err.message);//触发error事件
                });
            });
          return deferred.promise();
        },
        //时间点2：如果有分块上传，则每个分块上传之前调用此函数
        //用于文件的续传
        beforeSend: function (block) {
          var indexchunk = block.file.indexcode;
          var deferred = WebUploader.Deferred();
          if (indexchunk > 0) {
            if (block.chunk > indexchunk) {
              //分块不存在，重新发送该分块内容
              deferred.resolve();
            } else {
              //分块存在，跳过
              deferred.reject();
            }
          } else {
            //分块不存在，重新发送该分块内容
            deferred.resolve();
          }
          //返回Deferred的Promise对象。
          return deferred.promise();
        },
        //时间点3:一个文件的所有分片上传成功后，调用该方法,让后台合并所有分片
        //该方法的在uploader.on("success")方法前执行。
        afterSendFile: function (file) {
          var deferred = WebUploader.Deferred();
          Promise.resolve(file.pass)
            .then(res => {
              if (res) {
                return Promise.resolve();
              } else {
                return _self.post(`api/rest/file/bigFile/merge?fileName=${encodeURIComponent(file.name)}&fileMd5=${file.md5}`);
              }
            })
            .then(res => {
              if (_self.addFileInfo) {
                return _self.addFileInfo({
                  md5: file.md5,
                  file: {
                    name: file.name,
                    size: file.size,
                    type: file.ext,
                    uuid: file.uid + "." + file.ext
                  },
                  treeId: _self.clientDetails_check_type
                });
              } else {
                return Promise.resolve(res);
              }
            }).then(res => {
              deferred.resolve();
            }).catch(err => {
              deferred.reject(err.message);
            });
          return deferred.promise();
        },
      }
    );
    
    //获取指定的文件格式
    let fileTypes = format_file()+"";
    let fileTypesArr = fileTypes.split(',');
    let fileType = fileTypesArr.map(item=> item.slice(1));
    //创建实例
    var uploader = WebUploader.create({
      accept: {
        extensions: fileType.join(','),
        mimeTypes: fileTypes
      },
      pick: {
        id: '#picker',
        label: '点击选择文件'
      },
      duplicate: true,//去重， 根据文件名字、文件大小和最后修改时间来生成hash Key
      swf: 'WebUploader/uploader.swf',
      chunked: true,
      chunkSize: 10 * 1024 * 1024, // 10M 每个分片的大小限制
      threads: 3,
      server: 'api/rest/file/bigFile/part',
      // auto: true,
      // 禁掉全局的拖拽功能。这样不会出现图片拖进页面的时候，把图片打开。
      disableGlobalDnd: true,
      fileNumLimit: 1024,
      fileSizeLimit: 3 * 1024 * 1024 * 1024,//3G 验证文件总大小是否超出限制, 超出则不允许加入队列
      fileSingleSizeLimit: 3 * 1024 * 1024 * 1024 //3G 验证单个文件大小是否超出限制, 超出则不允许加入队列
    });
    /**
     * 当某个文件的分块在发送前触发，主要用来询问是否要添加附带参数，大文件在开起分片上传的前提下此事件可能会触发多次。
     */
    uploader.onUploadBeforeSend = function (obj, data, headers) {
      //增加请求参数
      var file = obj.file;
      data.md5 = file.md5 || "";
      data.uid = file.uid;
      //增加请求token
      $.extend(headers, _self.headers);
    };
    // 当有文件被添加进队列的时候触发
    uploader.on("fileQueued", function (file,fileList) {
      _self.size = _self.size + file.size;
      if(_self.size>_self.maxSize){
        _self.$message({
            type: "warning",
            message: "总文件只能小于3G!",
        });
        return 
      }
      _self.fileList.push({ name: file.name, id: file.id, percentage: 0, state: 0 ,file:file});
    });
    //单个文件开始上传
    uploader.on("uploadStart", (file) => {
      _self.fileList.filter(e => e.id == file.id)[0].state = 1;
      console.log("uploadStart");
    });
    /**
     * 上传过程中，一直会执行该方法
     */
    uploader.on("uploadProgress", function (file, percentage) {
      _self.getProgressBar(file, percentage);
    });
    /**
     * 文件上传成功后，就在该文件对应的位置上，显示上传成功，file.id,作为上传文件位置标签的id,
     */
    uploader.on("uploadSuccess", (file, response) => {
      _self.fileList.filter(e => e.id == file.id)[0].state = 2;
      _self.fileList.filter(e => e.id == file.id)[0].percentage = 100;
      console.log("uploadSuccess");
    });
    /**
     * 发生错误时
     */
    uploader.on("uploadError", function (file, reason) {
      _self.fileList.filter(e => e.id == file.id)[0].state = 3;
      _self.fileList.filter(e => e.id == file.id)[0].description = reason;
      console.log("uploadError");
    });
    /**
     * 不管所有分片发送成功或者失败都会执行该方法
     */
    uploader.on("uploadComplete", function (file) {
      console.log("uploadComplete");
    });
    //所有文件上传结束
    uploader.on("uploadFinished", () => {
      _self.$emit("Finished", {});
      console.log("uploadFinished");
    });
    //设置全局变量
    this.uploader = uploader;
  },
  methods: {
    removeFileAll(){
      this.fileList = [];
      this.size = 0;
    },
    upload() {
      if(this.fileList.length==0){
        this.$message({
          type: "warning",
          message: "文件不能为空",
        });
        return;
      }
      if (this.clientDetails_check_type.length == 0 || this.clientDetails_check_type.includes(1) || this.clientDetails_check_type.includes(2) || this.clientDetails_check_type.includes(3) || this.clientDetails_check_type.includes(4)) {
        this.$message({
          type: "warning",
          message: "请选择文档列表子节点",
        });
        return;
      }
      this.uploader.upload();
    },
    removeFile(item, index) {
      if (item.state == 1) {//上传中的文件无法删除
        return;
      }
      this.uploader.removeFile(item.id);
      this.fileList.splice(index, 1);
      this.size = this.size - item.file.size;
    },
    retry(item, index) {
      item.description = "";
      let file = this.filelist.filter(e =>e.id == item.id)[0];
      file.pass = false;
      this.uploader.retry(file.id);
      // this.uploader.retry(this.fileList.filter(e => e.id == item.id)[0].id);
    },
    getProgressBar(file, percentage) {
      let item = this.fileList.find(e => e.id == file.id);
      //在分片合并之后在设置进度百分之百
      item && (item.percentage = percentage == 1 ? 99.9 : Math.floor(percentage * 100 * 100) / 100);
    },
    post(url) {
      return new Promise((resolve, reject) => {
        fetch(url, {
          method: "POST",
          headers: new Headers(this.headers)
        }).then(res => {
          if (res.status == 200) {
            return res.text();
          } else {
            console.log(res.statusText);
            reject(HTTP_STATUS);
          }
        }).then(res => {
          let result = JSON.parse(res);
          if (result.code == 9000) {
            resolve(result.data);
          } else {
            console.log(result);
            reject(result);
          }
        }).catch(err => reject(err));
      })
    },
    handleCheckChange(node, isSelected) {
      if (isSelected) {
        this.clientDetails_check_type.push(node.id);
      } else {
        this.clientDetails_check_type = this.clientDetails_check_type.filter(item => {
          return item != node.id
        })
      }
      console.log(this.clientDetails_check_type);
    }
  },
  watch: {
    treeDataBig: {
      handler(newVal, oldVal) {
        this.treeData = newVal;
        this.clientDetails_check_type = [];
      },
      immediate: true
    },
    flType:{
      handler(newVal, oldVal) {
        this.fl_type = newVal;
      },
      immediate: true
    }
  }
};
</script>
<style lang="scss" scope>
.uploadWrapper {
  min-height: 300px;
}

#picker>div:nth-child(2) {
  width: 126px !important;
  height: 40px !important;
}

.btnUpload {
  // height: 50px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

#thelist {
  height: auto;
  overflow-y: auto;
  max-height: calc(100% - 130px);
}

#thelist .div-a {
  // text-decoration: underline;
  // cursor: pointer;
  font-size: 14px;
  color: white;
  display: flex;
  align-items: center;
  flex-direction: row;
  height: 26px;
}
#thelist .div-a span{
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
#thelist li {
  /* 去掉li前面的小圆点 */
  list-style: none;
  margin: 10px 0px;

  .el-progress {
    width: 95%;
    margin-top: 3px;

    .el-progress-bar {
      .el-progress-bar__outer {
        height: 12px !important;
      }
    }
  }
}

.startUpload {
  margin-top: 5px;
}

.el-icon-loading {
  color: white;
  font-size: 11px;
  font-weight: 600;
}

.el-icon-warning {
  color: #ff5555;
  font-size: 11px;
  font-weight: 600;
}

.el-icon-success {
  color: green;
  font-size: 11px;
  font-weight: 600;
}
</style>
