拖拽批量上传的图片 vue2

<template>
    <div>
        <a-modal
            centered
            title="批量上传图片"
            v-model="dataVisible"
            :keyboard="false"
            class="img-modal"
            :mask-closable="maskClosable"
            ref="imgModal"
            @cancel="closemodel"
        >
            <div class="many_pic">
                <input type="file" v-show="false" class="img-file-input" ref="fileInput" multiple :accept="accept" @change="addImg2"/>
                <div class="drag_upload_items" :class="changeclass" style="position: relative">
                    <a-upload-dragger
                        :accept="fileAccept"
                        v-show="showupload"
                        name="file"
                        :multiple="true"
                        :before-upload="()=>false"
                        @change="handleChange"
                        :show-upload-list="false"
                    >
                        <div class="ant-upload-drag-icon">
                            <img  src="~@assets/images/pic_view/drag.png" alt="">
                            <a-button style="height: 31px;width: 111px;font-size: 14px" shape="round" type="primary">添加图片</a-button>
                        </div>
                    </a-upload-dragger>

                    <ul class="img-list" v-if="imgListShow">
                        <li class="img-li" v-for="({ src }, index) in imgList" :key="index">
                            <div class="img-li-inner">
                                <div class="img-wrapper" @mousedown.prevent="dragStart($event, index)" ref="imgWrapperList">
                                    <img class="img" :src="src" ref="imgList"/>
                                    <div class="img-del-btn-wrapper">
                                        <a-button class="img-del-btn" size="small" type="danger" title="删除图片" @click="delImg(index)" @mousedown.stop>删除图片</a-button>
                                    </div>
                                    <div class="img-name">{{items[index] && items[index].supplierPartId}}</div>
                                </div>
                            </div>
                        </li>

                        <li class="img-li">
                            <a-button class="img-add-btn" @click="addImgTip" title="上传图片" v-show="!showupload">
                                <a-icon type="plus" style="font-size: 21px;color: #3D97D4;font-weight: 400"/>
                                添加图片
                            </a-button>
                        </li>
                    </ul>

                    <a-spin style="position: absolute;top: 50%;left: 50%" size="large" v-show="loadings"/>
                </div>

            </div>

            <template #footer>
                <a-button title="保存" type="primary" @click="save" class="footer-btn">保存</a-button>
                <a-button title="清空" class="form-right-btn empty" @click="clearimglist">清空</a-button>
            </template>
        </a-modal>
        <div class="drag-img-outer" v-show="dragShow" ref="dragObj">
            <div class="drag-img-inner">
                <img class="drag-img" :src="dragSrc"/>
            </div>
        </div>
    </div>
</template>

<script>
import ModalMixin from "@/mixins/ModalMixin";
import BaseMsg from "@/tools/BaseMsg";

const getElementToPageTop = element => {
    const { offsetParent, offsetTop } = element;
    return offsetParent ? (getElementToPageTop(offsetParent) + offsetTop) : offsetTop;
};
const getElementToPageLeft = element => {
    const { offsetParent, offsetLeft } = element;
    return offsetParent ? (getElementToPageLeft(offsetParent) + offsetLeft) : offsetLeft;
};
const MODAL_DIALOG_SELECTOR = "[role=dialog]";

export default {
    data() {
        return {
            imgType: ["image/jpeg", "image/png"],
            imgList: [],
            dragShow: false,
            dragSrc: "",
            dragSpeed: 10,
            dragMouseX: null,
            dragMouseY: null,
            dragIndex: null,
            showupload:true,
            changeflag:true,
            items:[],
            hasup:0,
            fileType: ["image/jpeg", "image/png", "image/jpg"],
            loadings:false,
        }
    },
    computed: {
        imgListShow() {
            return this.imgList && this.imgList.length > 0;
        },
        accept() {
            return this.imgType.join(',');
        },
        maxCount() {
            return this.items ? (this.items.length > 10 ? 10 : this.items.length) : 0;
        },
        changeclass(){
            let changeclass = this.changeflag ? "changeclass": ""
            return changeclass
        },
        fileAccept() {
            return this.fileType.length === 0 ? "*" : this.fileType.join(",");
        },
    },
    methods: {
        getItems(e){
            this.items = e
            this.showupload = true
            this.changeflag = true;
            this.hasup = 0;
        },
        //第二种新增
        addImg2({ target: { files, value } }) {
            if (!value) {
                return;
            }
            this.addImg(files)
        },

        // 新增图片
        addImg(files) {
            const { error } = BaseMsg;
            if (files && files.length > 0) {
                const promises = [];
                const length = files.length > this.maxCount ? this.maxCount : files.length;
                for (let i = 0; i < length; i++) {
                    const file = files[i];
                    const { type, size, name } = file;
                    if (!this.imgType.includes(type)) {
                        error('请选择JPG或PNG格式图片');
                        return;
                    }
                    const MAX_FILE_NAME_LENGTH = 128;
                    if (name.length > MAX_FILE_NAME_LENGTH) {
                        error(`文件名称不能超过${MAX_FILE_NAME_LENGTH}个字符`);
                        return;
                    }
                    if (size < 10240) {
                        error('图片需大于10KB');
                        return;
                    }
                    const formData = new FormData();
                    formData.append('reapPicUrl', file);
                    this.loadings = true
                    applyReapPicV2(
                        formData
                    ).then(({data}) => {
                        this.imgList.push({MD5Name:data.md5Name,src:data.url})
                    }).finally(()=> this.loadings = false)
                }
                //Promise.all(promises).then(imgList => this.imgList.push(...imgList));
            }
        },
        // 删除图片
        delImg(index) {
            this.imgList.splice(index, 1);
            if(this.imgList.length ===0){
                this.showupload = true;
                this.changeflag = true;
            }
        },
        save() {
            if (!this.imgListShow) {
                BaseMsg.error("至少上传一张图片");
                return;
            }
            const itemIdList = this.items.map(({ itemId,supplierOrderId }) => ({itemId,supplierOrderId}));
            const fileList = this.imgList.map(e => ({ MD5Name: e.MD5Name }));
            const mergedArray = [];
            let size_sum = 0
            if(itemIdList.length > fileList.length){
                itemIdList.forEach((e,index)=>{
                    if(index < fileList.length){
                        const reapPicUrl = fileList[index];
                        mergedArray.push({ ...reapPicUrl, ...e });
                        //size_sum += reapPicUrl.size
                    }else{
                        const reapPicUrl = fileList[fileList.length -1];
                        mergedArray.push({ ...reapPicUrl, ...e });
                        //size_sum += reapPicUrl.size
                    }
                })
            }else{
                fileList.forEach((reapPicUrl, index) => {
                    const objB = itemIdList[index];
                    mergedArray.push({ ...reapPicUrl, ...objB });
                    //size_sum += reapPicUrl.size
                });
            }

            if(size_sum > 20971520){
                BaseMsg.error("图片总大小超过20M")
            }



            let param = {
                "reapPicApplyReqVOS":mergedArray
            }
            BaseMsg.confirm({
                content: "确认保存?",
                onOk: () => batchBuyerApplyReapPic(
                    param
                ).then(({data}) => {
                    this.$emit("ok");
                    BaseMsg.success("已保存");
                    this.$emit("manyImg",data)
                    this.close();
                })
            });
        },
        show() {
            this.imgList = [];
        },
        addImgTip() {
            if (this.imgList.length < this.maxCount) {
                const { fileInput } = this.$refs;
                if (fileInput) {
                    fileInput.value = "";
                    fileInput.click();
                }
            } else {
                BaseMsg.info("图片文件数不能大于选中的商品数量(一次最多10张)");
            }
        },
        // 开始拖动
        dragStart({ currentTarget, pageX, pageY }, index) {
            const { imgList, dragObj, imgModal } = this.$refs;
            const { src, width, height } = imgList?.[index];
            this.dragSrc = src;
            const pageLeft = getElementToPageLeft(currentTarget);
            const pageTop = getElementToPageTop(currentTarget);
            const imgModalDialog = imgModal.$el.querySelector(MODAL_DIALOG_SELECTOR);
            const { scrollTop, scrollLeft } = imgModalDialog;
            // edge浏览器和其他浏览器不一致
            const bodyScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            const bodyScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
            dragObj.style.left = `${pageLeft - scrollLeft}px`;
            dragObj.style.top = `${pageTop - scrollTop}px`;
            dragObj.style.width = `${width}px`;
            dragObj.style.height = `${height}px`;
            this.dragShow = true;
            this.dragMouseX = pageX - bodyScrollLeft + scrollLeft - pageLeft;
            this.dragMouseY = pageY - bodyScrollTop + scrollTop - pageTop;
            this.dragIndex = index;
            document.addEventListener("mousemove", this.drag);
            document.addEventListener("mouseup", this.dragEnd);
        },
        // 拖动
        drag($event) {
            debugger
            $event.preventDefault();
            const { $refs: { dragObj, imgModal }, dragMouseX, dragMouseY } = this;
            const { pageX, pageY } = $event;
            const imgModalDialog = imgModal.$el.querySelector(MODAL_DIALOG_SELECTOR);
            const { scrollTop, scrollLeft } = imgModalDialog;
            // edge浏览器和其他浏览器不一致
            const bodyScrollTop = document.documentElement.scrollTop || document.body.scrollTop;
            const bodyScrollLeft = document.documentElement.scrollLeft || document.body.scrollLeft;
            const { offsetHeight } = dragObj;
            const { clientHeight } = document.documentElement;
            const left = pageX - bodyScrollLeft - dragMouseX;
            const top = pageY - bodyScrollTop - dragMouseY;
            // 拖动到边缘
            if (top <= 5) {
                imgModalDialog.scrollTop = scrollTop - this.dragSpeed;
                if (top <= -40) {
                    if (this.dragSpeed < 100) {
                        this.dragSpeed++;
                    }
                } else {
                    this.dragSpeed = 10;
                }
            } else if (top + offsetHeight >= clientHeight - 5) {
                imgModalDialog.scrollTop = scrollTop + this.dragSpeed;
                if (top + offsetHeight >= clientHeight + 40) {
                    if (this.dragSpeed < 100) {
                        this.dragSpeed++;
                    }
                } else {
                    this.dragSpeed = 10;
                }
            } else {
                this.dragSpeed = 10;
            }
            dragObj.style.left = `${left}px`;
            dragObj.style.top = `${top}px`;
        },
        // 拖动结束
        dragEnd($event) {
            $event.preventDefault();
            document.removeEventListener("mousemove", this.drag);
            document.removeEventListener("mouseup", this.dragEnd);
            const { imgWrapperList, dragObj, imgModal } = this.$refs;
            if (dragObj) {
                const { offsetLeft, offsetTop, clientHeight, clientWidth } = dragObj;
                if (imgWrapperList) {
                    let column = 1;
                    let row = 1;
                    const ROW_COUNT = 5;
                    const imgModalDialog = imgModal.$el.querySelector(MODAL_DIALOG_SELECTOR);
                    const { scrollTop, scrollLeft } = imgModalDialog;
                    for (const verticalIndex in imgWrapperList) {
                        if (verticalIndex > 0 && verticalIndex % ROW_COUNT == 0) {
                            const imgWrapper = imgWrapperList[verticalIndex];
                            const top = getElementToPageTop(imgWrapper) - scrollTop;
                            const dragBottom = offsetTop + clientHeight;
                            const imgMiddle = top + imgWrapper.clientHeight / 2;
                            if (dragBottom < imgMiddle) {
                                column = (+verticalIndex) / ROW_COUNT;
                                break;
                            }
                            const tempColumn = Math.floor((imgWrapperList.length - 1) / ROW_COUNT);
                            if (verticalIndex == tempColumn * ROW_COUNT) {
                                column = tempColumn + 1;
                            }
                        }
                    }
                    for (const horizontalIndex in imgWrapperList) {
                        if (horizontalIndex >= ROW_COUNT) {
                            break;
                        }
                        if (horizontalIndex > 0) {
                            const imgWrapper = imgWrapperList[horizontalIndex];
                            const left = getElementToPageLeft(imgWrapper) - scrollLeft;
                            const dragRight = offsetLeft + clientWidth;
                            const imgMiddle = left + imgWrapper.clientWidth / 2;
                            if (dragRight < imgMiddle) {
                                row = +horizontalIndex;
                                break;
                            }
                            if (horizontalIndex == imgWrapperList.length - 1) {
                                row = imgWrapperList.length;
                            } else if (horizontalIndex == ROW_COUNT - 1) {
                                row = ROW_COUNT;
                            }
                        }
                    }
                    let newIndex = (column - 1) * ROW_COUNT + row - 1;
                    if (newIndex >= this.imgList.length) {
                        newIndex = this.imgList.length - 1;
                    }
                    const { dragIndex } = this;
                    const [oldImg] = this.imgList.splice(dragIndex, 1);
                    this.imgList.splice(newIndex, 0, oldImg);
                }
            }
            this.dragShow = false;
        },
        handleChange({file}){
            this.hasup++
            if(this.hasup > 10){
                BaseMsg.error("单次最多可选择10张图片")
            }
            else if(10 > this.hasup && this.hasup > this.maxCount){
                return false
            }else{
                let a = [file]
                this.addImg(a)
                this.showupload = false
                this.changeflag = false;
            }
        },
        closemodel(){
            this.hasup = 0
        },
        clearimglist(){
            this.showupload = true
            this.changeflag = true;
            this.hasup = 0;
            this.imgList = [];
        }
    },
    mounted() {
        const { dragObj } = this.$refs;
        if (dragObj) {
            document.body.appendChild(dragObj);
        }
    },
    beforeDestroy() {
        const { dragObj } = this.$refs;
        if (dragObj) {
            document.body.removeChild(dragObj);
        }
        document.removeEventListener("mousemove", this.drag);
        document.removeEventListener("mouseup", this.dragEnd);
    }
};
</script>

<style lang="less" scoped>
@import "~@assets/less/base-mixin.less";
.img-modal{
    .img-file-tip{
        color: @main-color;
        font-size: 14px;
        margin-bottom: 10px;
    }
    .img-list{
        .clearfix;
        margin: 10px -5px;
        .img-li{
            float: left;
            padding: 5px;
            width: 132px;
            height: 132px;
            margin: 0 5px;
            .img-li-inner{
                border: 1px solid #DDD;
                .radius(5px);
                padding: 5px;
                cursor: pointer;
                .img-wrapper{
                    height: 0;
                    padding-bottom: 100%;
                    display: block;
                    position: relative;
                    text-align: center;
                    .img{
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                    }
                    .img-del-btn-wrapper{
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                        .opacity(0);
                        .baseTransition;
                        .img-del-btn{
                            display: inline-block;
                            vertical-align: middle;
                            z-index: 2;
                        }
                        &::before{
                            content: "";
                            height: 100%;
                            display: inline-block;
                            vertical-align: middle;
                        }
                    }
                    .img-name {
                        position: absolute;
                        bottom: 0;
                        left: 0;
                        right: 0;
                        color: #FFF;
                        background-color: @main-color;
                        padding: 2px 0;
                    }
                }
                &:hover .img-wrapper{
                    &::before{
                        content: "";
                        position: absolute;
                        top: 0;
                        left: 0;
                        width: 100%;
                        height: 100%;
                        background-color: rgba(0, 0, 0, 0.1);
                        z-index: 1;
                    }
                    .img-del-btn-wrapper{
                        .opacity(1);
                    }
                }
            }
        }
    }
}
.drag-img-outer{
    position: fixed;
    overflow: hidden;
    z-index: 9999;
    .opacity(0.7);
    .drag-img-inner{
        width: 100%;
        height: $width;
        .drag-img{
            width: 100%;
            height: $width;
        }
    }
}
.many_pic{
    min-height: 313px;
    width: 100%;
    display: flex;
    flex-direction: column;
    .drag_upload_items{
        flex: 1;
        display: flex;
        span{
            display: block;
            width: 322px;
            height: 173px;
        }
    }

}

.img-add-btn{
    width: 122px;
    height: 122px;
    color: #3D97D4;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}
/deep/ .ant-modal-body .ant-upload-drag{
    background-color: #fff;
}
.drag_icon{
    width: 132px;
    height: 13px;
    font-size: 12px;
    font-family: Microsoft YaHei;
    font-weight: 300;
    color: #999999;
}
.ant-upload-drag-icon{
    display: flex;
    flex-direction: column;
    justify-content: space-around;
    align-items: center;
    height: 80%;
    img {
        width: 31px;
        height: 26px;
    }
}

.changeclass{
    justify-content: center;
    align-items: center;
}

</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值