<template>
    <div class="upload_box" :style="`width:${width};`">
        <div v-if="uploadType !== 3" class="demo-upload-list" v-for="(item, index) in uploadList" :key="index">
            <img :src="(item.url || item)+'?timestamp='+ Date.now()" v-if="uploadType === 1" />
            <video :src="item.url || item" autoplay v-else></video>
            <div class="demo-upload-list-cover">
                <Icon v-if="showEye" type="ios-eye-outline" @click.native="handleView(item)"></Icon>
                <Icon type="ios-trash-outline" @click.native="onRemove(item)"></Icon>
            </div>
        </div>
        <Upload v-show="uploadType === 3||(show && uploadList.length < this.multipleNum)" ref="upload" :show-upload-list="uploadType === 3"
            :default-file-list="defaultList" :format="fileFormat1" :accept="fileAccept1" :on-remove="handleRemove"
            :before-upload="handleBeforeUpload" :multiple="multiple" :disabled="disabled"
            :action="credentials.serverDomain + `/open/v1/file/upload`" :type="type" style="width: 100%;">
            <slot>
                <div class="upload_icon_box">
                    <img src="/img/add_circle_icon.png" class="add_circle_icon"></img>
                    <span>{{ faceName||$t('message.common.uploadImg') }}</span>
                </div>
            </slot>
        </Upload>
        <Progress v-if="fileUpload.fileProgressShow" :percent="fileUpload.fileProgress" :stroke-width="20"
            status="active" text-inside />
        <Modal title="预览" v-model="visible" footer-hide>
            <img :src="showImg" v-if="showImg && uploadType === 1" style="width: 100%">
            <video :src="showVideo" v-else-if="showVideo && uploadType === 4" controls style="width: 100%"></video>
            <audio :src="showAudio" v-else-if="showAudio && uploadType === 2" controls style="width: 100%"></audio>
        </Modal>
    </div>
</template>
<script>
import { mapState } from 'vuex'
import axios from 'axios'
/**
 * @author: xieMingCai
 * @description: 自定义素材的文件上传接口，适用于图片或者视频的回显。
 * import selectUpload from '_call/components/uploadFile/index'
 * @demo: 在父组件直接使用：<selectUpload
 ref="uploadImg"
 faceName = "上传视频"
 :multiple= "false"
 :imgBase="sopScheduleContentList[index].videoPath"
 v-model="sopScheduleContentList[index].videoPath"
 :uploadFilePathPrefix="uploadFilePathPrefix"
 * uploadFilePathPrefix 表示文件上传路径前缀
 * faceName 如果是图片类型，则不需要填，如果是视频类型则需要填写
 */
export default {
    data() {
        return {
            defaultList: [], // 已经上传的文件列表，里面各个子项是对象
            uploadList: [], // 已经上传的文件列表，里面各个子项是字符串
            action: '',
            show: true,
            fileFormat1: ['jpg', 'jpeg', 'png', 'webp'], // 支持的文件类型
            fileAccept1: 'image/jpeg,image/jpg,image/png', // 支持的文件类型
            disabled: false,
            fileUpload: {
                fileProgressShow: false, // 进度条
                fileProgress: 0, // 进度条进度
            },
            credentials: {
                bucket: '',
                Authorization: '',
                secretId: '',
                serverDomain: ''
            },
            baseURL: '',
            pathData: '',
            fileData: '',
            visible: false,
            showImg: '',
            showVideo: '',
            showAudio: '',
        }
    },
    props: {
        // 是否多选
        multiple: {
            type: Boolean,
            default: () => true,
        },
        // 上传多个图片或者视频时的最大数量,默认9个
        multipleNum: {
            type: Number,
            default: () => 9,
        },
        width: {
            type: String,
            default: () => '80px',
        },
        imgBase: {
            type: String || Array,
        },
        // 如果是图片，则该字段无需传，如果是视频则该字段填 '上传视频'
        faceName: {
            type: String,
            default: () => '', // 等同this.faceNameFont, 但这里不清楚怎么获取this对象，先这样写着吧
        },
        // 文件上传文件前缀, 根据业务模块名设置对应的前缀，如企微宝的前缀为qw，如果不确定业务类型，则使用默认值即可
        uploadFilePathPrefix: {
            type: String,
            default: () => 'scrm-center/',
        },
        // 图片最大限制大小
        fileRam: {
            type: Number,
            default: () => 3,
        },
        showEye: {
            type: Boolean,
            default: () => false,
        },
        filePathName: {
            type: String,
            default: () => '',
        },
        type: {
            type: String,
            default: () => 'drag',
        },
        uploadType: {
            type: Number,
            default: () => 1,
        },
        fileFormat: {
            type: Array,
        },
        fileAccept: {
            type: String,
        },
    },
    watch: {
        uploadType(val) {
            if (val === 1) {
                // 图片类型
                this.fileFormat1 = this.fileFormat || ['jpg', 'jpeg', 'png', 'webp']
                this.fileAccept1 = this.fileAccept || 'image/jpeg,image/jpg,image/png,image/webp'
            } else if (val === 2) {
                // 音频类型
                this.fileFormat1 = this.fileFormat || ['wav', 'mp3', 'aiff', 'aac', 'ogg', 'flac']
                this.fileAccept1 = this.fileAccept || 'audio/*'
            } else if (val === 3) {
                // 文件类型
                this.fileFormat1 = this.fileFormat || ['pdf', 'ppt', 'pptx', 'pptm']
                this.fileAccept1 = this.fileAccept || '.pdf,.ppt,.pptx,.pptm'
            } else {
                // 视频类型
                this.fileFormat1 = this.fileFormat || ['mp4', 'avi', 'm4v', 'mpeg', 'mov', 'x-flv', 'mpg', 'webm', 'wmv', '3gpp']
                this.fileAccept1 = this.fileAccept || 'video/*'
            }
        },
        imgBase (val) {
            if (typeof val === 'string') {
                // 如果传进来的是字符串，则把字符串加入到数组
                this.uploadList = val !== '' ? [val] : []
                this.show = false
            } else {
                // 如果传进来的是数组，则直接赋给数组
                this.uploadList = val
                this.show = true
            }
        },
        uploadList (val) {
            if (!val) {
                this.uploadList = []
                return
            }
            if (val.length >= 1 && this.multiple === false) {
                this.show = false
            } else {
                this.show = true
            }
            if (val === this.uploadList) {
                return
            }
            let demoList = this.uploadList.filter(Boolean)
            this.defaultList = demoList.map((item) => {
                return { url: item, name: item.name || item.split('/').pop() }
            })
        },
    },
    created() {
        this.getCosObj()
    },
    mounted() {
        /* if (this.imgBase) {
                this.uploadList = [this.imgBase]
            }*/
        if (typeof this.imgBase === 'string') {
            // 如果传进来的是字符串，则把字符串加入到数组
            this.uploadList = this.imgBase !== '' ? [this.imgBase] : []
            this.show = false
        } else {
            // 如果传进来的是数组，则直接赋给数组
            this.uploadList = this.imgBase
            this.show = true
        }
        if (this.uploadList) {
            let demoList = this.uploadList.filter(Boolean)
            this.defaultList = demoList.map((item) => {
                return { url: item, name: item.name || item.split('/').pop() }
            })
        }
        if (this.uploadType === 1) {
            // 图片类型
            this.fileFormat1 = this.fileFormat || ['jpg', 'jpeg', 'png', 'webp']
            this.fileAccept1 = this.fileAccept || 'image/jpeg,image/jpg,image/png,image/webp'
        } else if (this.uploadType === 2) {
            // 音频类型
            this.fileFormat1 = this.fileFormat || ['wav', 'mp3', 'aiff', 'aac', 'ogg', 'flac']
            this.fileAccept1 = this.fileAccept || 'audio/*'
        } else if (this.uploadType === 3) {
            // 文件类型
            this.fileFormat1 = this.fileFormat || ['pdf', 'ppt', 'pptx', 'pptm']
            this.fileAccept1 = this.fileAccept || '.pdf,.ppt,.pptx,.pptm'
        } else {
            // 视频类型
            this.fileFormat1 = this.fileFormat || ['mp4', 'avi', 'm4v', 'mpeg', 'mov', 'x-flv', 'mpg', 'webm', 'wmv', '3gpp']
            this.fileAccept1 = this.fileAccept || 'video/*'
        }
    },
    computed: {
    },
    methods: {
        // 获取腾讯COS对象存储的实例对象，为后续的文件上传做准备
        async getCosObj() {
            await this.$http.post(`/scrm/v1/oss/p/getAuthorization`, {}).then((response) => {
                if (response.code === 1) {
                    this.credentials = response.data.info
                    // 用正则将this.credentials.serverDomain链接中的协议与当前域名的协议保持一致
                    this.credentials.serverDomain = this.credentials.serverDomain.replace(/https:|http:/g, 'https:')
                } else {
                    this.$message.error(response.msg)
                }
            })
        },
        // 文件上传前的钩子函数，如果返回false，则停止上传
        handleBeforeUpload (data) {
            let regex = /^[\u4e00-\u9fa5a-zA-Z0-9._-]+$/
            let fileNameSuffix = data.name.substring(data.name.lastIndexOf('.') + 1).toLowerCase()
            const check = this.uploadList.length >= this.multipleNum
            if (check) {
                this.$Notice.warning({
                    title: `最多可上传${this.multipleNum}个文件`,
                })
            // } else if (!regex.test(data.name)) {
            //     this.$Notice.warning({
            //         title: `文件名不能包含汉字、空格或特殊字符`,
            //     })
            } else if (this.fileFormat1.indexOf(fileNameSuffix) === -1) {
                this.$Notice.warning({
                    title: '文件格式不正确，请重新选择',
                    desc:
                        '文件' +
                        data.name +
                        ' 不符合要求, 请选择' +
                        this.fileFormat1.join('、') +
                        '格式的文件',
                })
            } else if (data.size > this.fileRam * 1024 * 1024) {
                this.$Notice.warning({
                    title: '文件大小超限制',
                    desc: '文件  ' + data.name + ' 太大, 不能超过' + this.fileRam + 'M.',
                })
            } else {
                this.handleUpload(data)
            }
            return false
        },
        // 文件上传到腾讯云
        async handleUpload(data) {
            this.$Notice.success({
                title: this.$t('message.common.uploading'),
            })
            this.disabled = true
            // 判断uploadFilePathPrefix是否以/路径结尾，如果不是则添加
            this.pathData =
                this.uploadFilePathPrefix.indexOf('/') !== -1
                    ? this.uploadFilePathPrefix
                    : this.uploadFilePathPrefix + '/'
            let timestamp = Date.now() + Math.floor(Math.random() * 100000)
            // 构建文件上传路径：环境/项目模块名称/租户id/时间戳/文件原始名称
            this.fileData = `${process.env.NODE_ENV}/${this.pathData}1/${timestamp}/${data.name}`
            // 上传文件
            let formData = new FormData()
            if (this.filePathName) {
                formData.append('path', this.filePathName + '/' + data.name)
            } else {
                formData.append('path', this.fileData)
            }
            formData.append('file', data)
            await this.getCosObj()
            axios({
                method: 'post',
                data: formData,
                url: this.credentials.serverDomain + '/open/v1/file/upload',
                headers: {
                    'bucket': this.credentials.bucket,
                    'Authorization': this.credentials.authorization,
                    'secretId': this.credentials.secretId,
                },
            }).then(res => {
                if (res.code === 1) {
                    res.data.url = res.data.url.replace(/https:|http:/g, 'https:')
                    this.handleSuccess(res.data, data)
                } else {
                    this.$Notice.warning({
                        title: this.$t('message.common.uploadFail'),
                    })
                    this.disabled = false
                }
            })
        },
        // 上传成功
        handleSuccess(res, file) {
            let _data
            if (res.url) {
                _data = {
                    name: file.name,
                    url: res.url,
                }
            }
            let fileList = this.$refs.upload.fileList
            if (this.multiple) {
                fileList.push(_data)
            } else {
                fileList = [_data]
            }
            this.defaultList = fileList
            // this.$refs.upload.fileList = [_data]
            const files = fileList.filter(Boolean)
            let data
            try {
                if (this.multiple) {
                    data = files.map((item) => {
                        return item.url
                    })
                } else {
                    data = files[files.length - 1].url
                }
            } catch (error) { }
            this.uploadList = data
            this.$emit('input', data)
            this.$Notice.success({
                title: this.$t('message.common.uploadSuccess'),
            })
            this.fileUpload.fileProgressShow = false
            this.disabled = false
        },
        onRemove(file) {
            const index = this.$refs.upload.fileList.findIndex(
                (item) => item.url === file
            )
            this.$refs.upload.fileList.splice(index, 1)
            const fileList = this.$refs.upload.fileList
            this.defaultList = fileList
            // this.$refs.upload.fileList = [_data]
            const files = fileList.filter(Boolean)
            let data
            try {
                if (this.multiple) {
                    data = files.map((item) => {
                        return item.url
                    })
                } else {
                    data = files[files.length - 1].url
                }
            } catch (error) { }
            this.uploadList = data
            this.$emit('input', data)
            this.show = true
        },
        handleRemove () {
            const fileList = this.$refs.upload.fileList
            this.defaultList = fileList
            const files = fileList.filter(Boolean)
            let data
            try {
                if (this.multiple) {
                    data = files.map((item) => {
                        return item.url
                    })
                } else {
                    data = files[files.length - 1].url
                }
            } catch (error) { }
            this.uploadList = data
            this.$emit('input', data)
        },
        handleView(data) {
            if (this.uploadType === 4) {
                this.showVideo = data
            } else if (this.uploadType === 2) {
                this.showAudio = data
            } else {
                this.showImg = data
            }
            this.visible = true
        }
    },
}
</script>
<style>
.upload_box{
    display: flex;
    flex-direction: column;
}
.demo-upload-list {
    display: inline-block;
    width: 100%;
    height: 80px;
    text-align: center;
    line-height: 60px;
    border: 1px solid transparent;
    border-radius: 4px;
    overflow: hidden;
    background: #fff;
    position: relative;
    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
    margin-right: 4px;
}

.demo-upload-list img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

.demo-upload-list-cover {
    display: none;
    position: absolute;
    top: 0;
    bottom: 0;
    left: 0;
    right: 0;
    background: rgba(0, 0, 0, 0.6);
}

.demo-upload-list:hover .demo-upload-list-cover {
    display: block;
}

.demo-upload-list .demo-upload-list-cover .ivu-icon-ios-trash-outline {
    margin-top: 28px;
}

.demo-upload-list-cover i {
    color: #fff;
    font-size: 24px;
    cursor: pointer;
    margin: auto;
}
.upload_icon_box{
    width: 100%;
    height: 80px;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    color: #9ca3af;

}
.upload_icon_box .add_circle_icon{
    width: 10px;
    height: 10px;
}
.upload_icon_box span{
    line-height: 20px;
}
</style>
