<template>
    <div>
        <div id="global-uploader">

            <!-- 上传 -->
            <uploader
                    ref="uploader"
                    :options="options"
                    :autoStart="false"
                    @file-added="onFileAdded"
                    @file-success="onFileSuccess"
                    @file-progress="onFileProgress"
                    @file-error="onFileError"
                    :file-status-text="statusText"
                    class="uploader-app">
                <uploader-unsupport></uploader-unsupport>

                <uploader-btn  :attrs="attrs"  id="global-uploader-btn" ref="uploadBtn" @click="btnClick">{{btnText}}</uploader-btn>
                <span style="margin-left:10px" v-if="showFlag&&showUoloadStatus">文件上传成功!</span>

                <uploader-list v-show="panelShow">
                    <div class="file-panel" slot-scope="props" :class="{'collapse': collapse}">
                        <div class="file-title">
                            <h2>文件列表</h2>
                            <div class="operate">
                                <el-button @click="fileListShow" type="text" :title="collapse ? '展开':'折叠' ">
                                    <i class="iconfont" :class="collapse ? 'inuc-fullscreen': 'inuc-minus-round'"></i>
                                </el-button>
                                <el-button @click="close" type="text" title="关闭">
                                    <i class="iconfont icon-close"></i>
                                </el-button>
                            </div>
                        </div>

                        <ul class="file-list">
                            <li v-for="file in props.fileList" :key="file.id">
                                <uploader-file :class="'file_' + file.id" ref="files" :file="file"
                                               :list="true"></uploader-file>
                            </li>
                            <div class="no-file" v-if="!props.fileList.length"><i class="iconfont icon-empty-file"></i>
                                暂无待上传文件
                            </div>
                        </ul>
                    </div>
                </uploader-list>

            </uploader>

        </div>
        <el-dialog :close-on-click-modal="false"
                   :visible.sync="UploadingDialog"
                   center
                   class="uploading-dialog"
                   title=""
                   @close="closeUploadDialog"
        >
            <div class="uploading-dialog-box">
                <i></i>
                <p>正在上传中，请稍后……</p>
                <div class="warning"></div>
            </div>
        </el-dialog>
    </div>
</template>

<script>
    /**
     *   全局上传插件
     *   调用方法：Bus.$emit('openUploader', {}) 打开文件选择框，参数为需要传递的额外参数
     *   监听函数：Bus.$on('fileAdded', fn); 文件选择后的回调
     *            Bus.$on('fileSuccess', fn); 文件上传成功的回调
     */
    //import Bus              from './bus';
    import SparkMD5         from 'spark-md5';
    import { getUploadImg } from '@/api/AlCloud.js';
    import { videoPolicy } from '@/api/peixun/videoPolicy.js';
    import { mapGetters }   from 'vuex';
    import axios                from 'axios';

    export default {
        props:{
            //  describe: 文字 author: Wgy date:2020-05-28
            btnText:{
                type: String,
                default: '点击上传'
            },
            //  describe: attributes接收属性值 author: Wgy date:2020-05-28
            acceptConfig:{
                type: Array,
                default: () => []
            },
            //  describe: 状态 author: Wgy date:2020-05-28
            showUoloadStatus:{
                type: Boolean,
                default: false
            },
            //  describe: 状态 author: Wgy date:2020-05-28
            isVideo:{
                type: Boolean,
                default: false
            }
        },
        data() {
            return {
                //  describe: 配置信息 author: Wgy date:2020-05-26
                options:   {
                    target:       '',
                    chunkSize:                    '10240000',
                    fileParameterName:            'file',//与后端商议
                    maxChunkRetries:              3,
                    simultaneousUploads:          3,
                    testChunks:                   true,   //是否开启服务器分片校验
                    //  describe: 服务器分片校验函数 get请求检测是否每块是否上传成功 true为跳过 author: Wgy date:2020-05-26
                    checkChunkUploadedByResponse: function (chunk, message) {
                        let objMessage = JSON.parse(message);
                     /*   if (objMessage.skipUpload) {
                            //  describe:  此块 用于之后秒传功能 当前未实现   author: Wgy date:2020-05-26
                            return true;
                        }*/
                        return (objMessage.uploaded || []).indexOf(chunk.offset + 1) >= 0;
                    },
                    headers: {
                       // 'content-disposition':'form-data; name="file"; filename=1111'
                    },
                    query() {

                    },
                    singleFile:true
                },
                attrs:     {
                  //  describe: 校验类型 此版本未添加   author: Wgy date:2020-05-26
                  //  describe: :attrs="attrs"  btn中 author: Wgy date:2020-05-26
                    accept:this.acceptConfig||[]
                },
                statusText: {
                    success: '成功了',
                    error: '出错了',
                    uploading: '上传中',
                    paused: '暂停中',
                    waiting: '等待中'
                },
                panelShow: false,   //选择文件后，展示上传panel
                downloadUrl:'',
                collapse:  false,
                UploadingDialog:false,
                newFile:{},
                showFlag:false

            };
        },
        mounted() {
       /*     this.$on('openUploader', query => {
                this.params = query || {};
                console.log(this.params);
                if (this.$refs.uploadBtn) {
                    $('#global-uploader-btn').click();
                }
            });*/
        },
        computed:   {
            //Uploader实例
            uploader() {
                return this.$refs.uploader.uploader;
            },
            ...mapGetters([
                              'getTenantCode',
                          ]),
        },
        methods:    {

            btnClick(){
                this.$on('openUploader', query => {
                    this.params = query || {};
                    console.log(this.params);
                    if (this.$refs.uploadBtn) {
                        $('#global-uploader-btn').click();
                    }
                });
            },
            closeUploadDialog(){
                this.newFile.cancel()
                this.UploadingDialog=false
                console.log('cancel');
            },
            onFileAdded(file) {
                this.newFile = file
                const suffix = file.name.split('.').pop();
                if(this.isVideo){
                    var time = new Date().getTime();
                    const options = {
                        fileName: file.name,
                        title: this.getTenantCode + time,
                    };
                    videoPolicy(options).then(res => {
                        if (res.code === 0) {
                            //  console.log( this.$refs.uploader);
                            this.$refs.uploader.uploader.opts.target = res.data.partUrl;
                            this.downloadUrl = res.data.downloadUrl;
                            this.UploadingDialog = true;
                            this.computeMD5(file);
                            //  Bus.$emit('fileAdded');
                        }
                    });
                }else {
                    const options = {
                        prefix: 'resource/',
                        suffix: suffix,
                    };
                    getUploadImg(options).then(res => {
                        if (res.code === 0 && res.data.type !== 'oss') {
                            //  console.log( this.$refs.uploader);
                            this.$refs.uploader.uploader.opts.target = res.data.partUrl;
                            this.downloadUrl = res.data.downloadUrl;
                            this.UploadingDialog = true;
                            this.computeMD5(file);
                            //  Bus.$emit('fileAdded');
                        }else{
                            this.UploadingDialog = true;
                            // 二进制文件通过forData对象进行传递
                            const FormDataForAl = new FormData();
                            const multipartParams = Object.assign({}, res.data, {
                                Filename:              `images/${file.name}`,
                                success_action_status: '200',
                            });
                            console.log("FormDataForAl",FormDataForAl);
                            console.log("multipartParams",multipartParams)
                            // 参数数据
                            FormDataForAl.append('key', multipartParams.key);
                            FormDataForAl.append('policy', multipartParams.policy);
                            FormDataForAl.append('signature', multipartParams.signature);
                            FormDataForAl.append('OSSAccessKeyId', multipartParams.accessid);
                            FormDataForAl.append('success_action_status', multipartParams.success_action_status);
                            FormDataForAl.append('x-oss-object-acl','private');
                            FormDataForAl.append('Content-Disposition','form-data; name="file"; filename='+ file.name);

                            // OSS要求, file放到最后
                            FormDataForAl.append('file', file);

                            axios.post(multipartParams.uploadUrl, FormDataForAl).then(alRes => {
                                if (alRes.status === 200) {
                                    this.imageUrl = `${multipartParams.uploadUrl}/${multipartParams.key}`;
                                    this.$refs.uploader.uploader.opts.target = res.data.partUrl;
                                    this.downloadUrl = res.data.downloadUrl;
                                    this.$emit('filesuccess',{url:res.data.downloadUrl,fileName:file.name,fileSize:file.size});
                                    this.UploadingDialog = false;
                                    this.$message.error('文件上传成功');
                                } else {
                                    this.UploadingDialog = false;
                                    this.$message.error('文件上传失败');
                                }
                            });
                        }
                    });
                }

            },
            onFileProgress(rootFile, file, chunk) {
                //  describe: 上传进程 author: Wgy date:2020-05-26
                console.log(`上传中 ${file.name}，chunk：${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`);
            },
            onFileSuccess(rootFile, file, response, chunk) {
                let res = JSON.parse(response);
                // 服务器自定义的错误（即虽返回200，但是是错误的情况），这种错误是Uploader无法拦截的
                if (!res.result) {
                    this.$message({ message: res.message, type: 'error' });
                    // 文件状态设为“失败”
                    this.statusSet(file.id, 'failed');
                    return;
                }
                if(res.url){
                    this.UploadingDialog = false
                    let downloadUrl = this.downloadUrl+'/'+res.url
                    this.showFlag = true
                    this.$emit('filesuccess',{url:downloadUrl,fileName:file.name,fileSize:file.size});
                    console.log('上传成功');
                }else {
                    this.statusSet(file.id, 'failed');
                    this.UploadingDialog = false
                    return false;
                }
                /*// 如果服务端返回需要合并
                if (res.needMerge) {
                    // 文件状态设为“合并中”
                    this.statusSet(file.id, 'merging');

                    api.mergeSimpleUpload({
                                              tempName: res.tempName,
                                              fileName: file.name,
                                              ...this.params,
                                          }).then(res => {
                        // 文件合并成功
                        Bus.$emit('fileSuccess');

                        this.statusRemove(file.id);
                    }).catch(e => {
                    });

                    // 不需要合并
                } else {
                    Bus.$emit('fileSuccess',{url:res.url});
                    console.log('上传成功');
                }*/
            },
            onFileError(rootFile, file, response, chunk) {
                this.$message({
                                  message: response,
                                  type:    'error',
                              });
            },

            /**
             * 计算md5，实现断点续传及秒传
             * @param file
             */
            computeMD5(file) {
                //  describe: FileReader 异步读取存储在用户计算机上的文件（ author: Wgy date:2020-05-26
                let fileReader = new FileReader();
                let time = new Date().getTime();
                //  describe: //兼容方式获取slice方法 author: Wgy date:2020-05-26
                let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
                let currentChunk = 0;
                const chunkSize = 10 * 1024 * 1000;
                let chunks = Math.ceil(file.size / chunkSize);
                let spark = new SparkMD5.ArrayBuffer();

                // 文件状态设为"计算MD5"
                this.statusSet(file.id, 'md5');
                file.pause();

                loadNext();
                //  describe: 载入完毕后执行 author: Wgy date:2020-05-26
                fileReader.onload = (e => {
                    console.log(e);
                    spark.append(e.target.result);

                    if (currentChunk < chunks) {
                        currentChunk++;
                        loadNext();

                        // 实时展示MD5的计算进度
                        this.$nextTick(() => {
                            $(`.myStatus_${file.id}`).text('校验MD5 ' + ((currentChunk / chunks) * 100).toFixed(0) + '%');
                        });
                    } else {
                        let md5 = spark.end();
                        this.computeMD5Success(md5, file);
                        console.log(`MD5计算完毕：${file.name} \nMD5：${md5} \n分片：${chunks} 大小:${file.size} 用时：${new Date().getTime() - time} ms`);

                    }
                });

                fileReader.onerror = function () {
                    this.error(`文件${file.name}读取出错，请检查该文件`);
                    file.cancel();
                };

                function loadNext() {
                    let start = currentChunk * chunkSize;
                    let end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

                    fileReader.readAsArrayBuffer(blobSlice.call(file.file, start, end));
                }
            },
            //  describe: md5成功  author: Wgy date:2020-05-26
            computeMD5Success(md5, file) {
                // 将自定义参数直接加载uploader实例的opts上
                Object.assign(this.uploader.opts, {
                    query: {
                        ...this.params,
                    },
                });
                //  describe: file 自带唯一标示 author: Wgy date:2020-05-26
                file.uniqueIdentifier = md5;
                file.resume();
                this.statusRemove(file.id);
            },
            //  describe: 展开 author: Wgy date:2020-05-26
            fileListShow() {
                let $list = $('#global-uploader .file-list');

                if ($list.is(':visible')) {
                    $list.slideUp();
                    this.collapse = true;
                } else {
                    $list.slideDown();
                    this.collapse = false;
                }
            },
            close() {
                this.uploader.cancel();

                this.UploadingDialog = false;
            },

            /**
             * 新增的自定义的状态: 'md5'、'transcoding'、'failed'
             * @param id
             * @param status
             */
            statusSet(id, status) {
                let statusMap = {
                    md5:         {
                        text: '校验MD5',
                        bgc:  '#fff',
                    },
                    merging:     {
                        text: '合并中',
                        bgc:  '#e2eeff',
                    },
                    transcoding: {
                        text: '转码中',
                        bgc:  '#e2eeff',
                    },
                    failed:      {
                        text: '上传失败',
                        bgc:  '#e2eeff',
                    },
                };

                this.$nextTick(() => {
                    $(`<p class="myStatus_${id}"></p>`).appendTo(`.file_${id} .uploader-file-status`).css({
                                                                                                              'position':        'absolute',
                                                                                                              'top':             '0',
                                                                                                              'left':            '0',
                                                                                                              'right':           '0',
                                                                                                              'bottom':          '0',
                                                                                                              'zIndex':          '1',
                                                                                                              'backgroundColor': statusMap[status].bgc,
                                                                                                          }).text(statusMap[status].text);
                });
            },
            statusRemove(id) {
                this.$nextTick(() => {
                    $(`.myStatus_${id}`).remove();
                });
            },

            error(msg) {
                //  describe: 消息通知组件$notify author: Wgy date:2020-05-26
                this.$notify({
                                 title:    '错误',
                                 message:  msg,
                                 type:     'error',
                                 duration: 2000,
                             });
            },
        },
        watch:      {},
        destroyed() {
            this.$off('openUploader');
            this.$off('fileAdded');
            this.$off('fileSuccess');
        },
        components: {},
    };
</script>

<style scoped lang="scss">
    /* 隐藏上传按钮 */
  /*  #global-uploader-btn {
        position: absolute;
        clip: rect(0, 0, 0, 0);
    }*/
</style>
