多图上传可拖拽组件
HTML片段
<template>
<div class="image-list">
<vuedraggable
class="vue-draggable"
:class="{ single: isSingle, maxHidden: isMaxHidden }"
v-model="dataList"
tag="ul"
draggable=".draggable-item"
@end="emitResult('draggable')"
>
<!-- @start="onDragStart"
@end="onDragEnd" -->
<!-- 拖拽元素 -->
<li
v-for="(item, index) in dataList"
:key="index"
class="draggable-item"
style="width:146px;height:146px;"
>
<!-- :style="style" -->
<div class="status-label">
<i class="status-upload-success el-icon-check"></i>
</div>
<el-image :src="item.url" :preview-src-list="srcList"></el-image>
<div class="shadow">
<i class="el-icon-delete shadow-icon" @click="onRemoveHandler(item)"></i>
</div>
</li>
<!-- 上传按钮 -->
<el-upload
ref="uploadRef"
class="uploadBox"
:class="options.hidePlus ? 'hide-plus' : ''"
:style="style"
:disabled="!!options.disabled"
:file-list="dataList"
action="https://jsonplaceholder.typicode.com/posts/"
:headers="设置上传的请求头部"
accept=".jpg,.jpeg,.png,.gif"
:show-file-list="false"
:multiple="!isSingle"
:limit="limit"
:list-type="options.listType || 'picture-card'"
:http-request="options.httpRequest || httpRequest"
:before-upload="options.beforeUpload || beforeUpload"
:on-remove="options.onRemove || onRemove"
:on-exceed="onExceed"
>
<i class="el-icon-plus uploadIcon">
<span class="uploading" v-show="isUploading">正在上传...</span>
<span
v-if="!isUploading && limit && limit!==99 && !isSingle"
class="limitTxt"
>最多{{ limit }}张</span>
</i>
</el-upload>
</vuedraggable>
</div>
</template>
js片段
<script> import { FileMx } from '@/mixins'; import { UNIT_PX } from '@/utils/adapter'; import vuedraggable from 'vuedraggable' // import draggable from 'vuedraggable' import { SERVER_FILE_API } from '@/config/config'; import { mapState, mapGetters } from 'vuex'; import { upLoadFile } from '@/api/UpLoadApi'; export default { name: 'UploadDraggable', mixins: [FileMx], props: { options: { type: Object, default: () => ({}) }, fileList: { // type: [Array, String] }, // 后端各模块前缀 URL: { type: String, default: '' }, // 图片数据(图片url组成的数组) 通过v-model传递 // value: { // type: Array, // default () { // return [] // } // }, // 限制上传的图片数量 limit: { type: Number, default: 99 }, // 限制上传图片的文件大小(kb) size: { type: Number, default: 500 }, // 是否是单图上传(单图上传就是已传图片和上传按钮重叠) isSingle: { type: Boolean, default: false }, // 是否使用图片压缩 useCompress: { type: Boolean, default: false }, // 图片显示的宽度(px) // width: { // type: Number, // default: 100 // }, // // 图片显示的高度(px) // height: { // type: Number, // default: 100 // } }, data () { return { // 拖拽时显示的列表 list:[1,2,3,4,5,], style: { width: this.options.width || 200 + UNIT_PX, height: this.options.height || 200 + UNIT_PX, overflow: 'auto' }, isUploading: false, // 正在上传状态 isFirstMount: true // 控制防止重复回显 } }, computed: { ...mapState(['authorizationHeader', 'uploadFileApi']), // dataList() { // debugger; // console.log('========') // // 如果是字符串或者空 // if (!this.fileList || typeof this.fileList === 'string') { // if (this.fileList) // return this.fileList.split(',').map(item => { // return { name: item, url: SERVER_FILE_API + item }; // }); // } else { // return this.fileList; // } // return []; // }, dataList: { get: function () { // 如果是字符串或者空 if (!this.fileList || typeof this.fileList === 'string') { if (this.fileList) return this.fileList.split(',').map(item => { return { name: item, url: SERVER_FILE_API + item }; }); } else { return this.fileList; } return []; }, set: function (newValue) { this.$emit('update:fileList', newValue); } }, srcList() { console.log("+++++++++==") return this.dataList.map(item => item.url); }, // 控制达到最大限制时隐藏上传按钮 isMaxHidden () { console.log("isMaxHidden") return this.dataList.length >= this.limit } }, watch: { // value: { // handler (val) { // if (this.isFirstMount && this.value.length > 0) { // this.syncElUpload() // } // }, // deep: true // } }, mounted () { // if (this.value.length > 0) { // this.syncElUpload() // } }, methods: { ...mapGetters(['getToken2']), // 同步el-upload数据 syncElUpload (val) { // const imgList = val || this.imgList // this.$refs.uploadRef.uploadFiles = imgList.map((v, i) => { // return { // name: 'pic' + i, // url: v, // status: 'success', // uid: tools.createUniqueString() // } // }) // this.isFirstMount = false }, // 上传图片之前 beforeUpload (file) { // 更改验证类型 if (file.type.indexOf('jpeg') !== -1||file.type.indexOf('png') !== -1) { return true; } this.$message.error('确保为图片类型!'); return false; // this.isFirstMount = false // if (this.useCompress) { // // 图片压缩 // return new Promise((resolve, reject) => { // lrz(file, { width: 1920 }).then((rst) => { // file = rst.file // }).always(() => { // if (validImgUpload(file, this.size)) { // this.isUploading = true // resolve() // } else { // reject(new Error()) // } // }) // }) // } else { // if (validImgUpload(file, this.size)) { // this.isUploading = true // return true // } else { // return false // } // } }, /** * 成功回调 * @param res * @param file */ // 上传完单张图片 onSuccess (res, file, fileList) { // 加100400提示 if(res.code==100400){ this.$message.error(res.msg) return false } // this.imgUrl = URL.createObjectURL(file.raw); // this.$emit('update:imgUrl', res.data); // 这里需要根据你自己的接口返回数据格式和层级来自行修改 // if (res.files) { // // 判断接口上传成功 // if (this.imgList.length < this.limit) { // // 未超限时,把接口返回的图片url地址添加到imgList // this.imgList.push(res.files.file) // } // } else { // // 判断接口上传失败 // this.syncElUpload() // this.$message({ type: 'error', message: res.msg }) // } // this.isUploading = false }, onRemove(item) { console.log("onRemove") this.dataList.splice( this.dataList.findIndex(o => o.name === item.name), 1 ); this.emitResult(); }, // 通知父级 emitResult(val) { console.log(typeof this.fileList === 'string',"emitResult") // 如果是字符串或者空 if (!this.fileList || typeof this.fileList === 'string'||val=='draggable') { console.log('111111111111') this.$emit( 'update:fileList', this.dataList.map(item => item.url.replace(SERVER_FILE_API, '')).join(',') ); } else { this.$emit('update:fileList', this.fileList); } }, // 移除单张图片 onRemoveHandler (item) { console.log(item,78787878987) this.dataList.splice( this.dataList.findIndex(o => o.name === item.name), 1 ); this.emitResult(); // this.$confirm('确定删除该图片?', '提示', { // confirmButtonText: '确定', // cancelButtonText: '取消', // type: 'warning' // }) // .then(() => { // this.imgList = this.imgList.filter((v, i) => { // return i !== index // }) // }) // .catch(() => {}) }, // 超限 onExceed () { // this.$refs.uploadRef.abort() // 取消剩余接口请求 // this.syncElUpload() // this.$message({ // type: 'warning', // message: `图片超限,最多可上传${this.limit}张图片` // }) }, onDragStart (e) { console.log(e,22222222222); e.target.classList.add('hideShadow') }, onDragEnd (e) { console.log(e,'-----------') e.target.classList.remove('hideShadow') }, // 完成上传 httpRequest(res) { console.log("httpRequest") upLoadFile.call(this, res, res => { let fileName = res.data.data; this.dataList.push({ name: fileName, url: SERVER_FILE_API + fileName }); this.emitResult(); }); }, }, components: { vuedraggable, // draggable } } </script>
样式
<style lang="scss" scoped> // 隐藏添加图标 .hide-plus { & ::v-deep .el-upload--picture-card { display: none; } } .image-list { margin-left: 20px; & /deep/ .el-icon-circle-close:before { color: #fff; } } /deep/ .el-upload { width:150px; height:150px; // width: 100%; // height: 100%; } // 上传按钮 .uploadIcon { width: 100%; height: 100%; position: relative; display: flex; align-items: center; justify-content: center; border: 1px dashed #c0ccda; background-color: #fbfdff; border-radius: 6px; font-size: 28px; color: #999; .limitTxt, .uploading { position: absolute; bottom: 10%; left: 0; width: 100%; font-size: 14px; text-align: center; } } // 拖拽 .vue-draggable { display: flex; flex-wrap: wrap; /deep/ li { width: 146px;; } .draggable-item { margin-right: 5px; margin-bottom: 5px; border: 1px solid #ddd; border-radius: 6px; position: relative; overflow: hidden; .el-image { width: 100%; height: 100%; } .status-label { position: absolute; right: -15px; top: -6px; width: 40px; height: 24px; background: #13ce66; text-align: center; transform: rotate(45deg); z-index: 1; & .status-upload-success { color: #fff; line-height: 24px; transform: rotate(-45deg); left: 15px; top: 6px; position: absolute; font-size: 10px; } } .shadow { width: 100%; height: 100%; position: absolute; top: 0; right: 0; background-color: rgba(0,0,0,.5); opacity: 0; transition: opacity .3s; color: #fff; font-size: 20px; line-height: 20px; padding: 2px; } &:hover { .shadow { opacity: 1; } } & .shadow-icon { margin: 0; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); cursor: pointer; } } &.hideShadow { .shadow { display: none; } } &.single { overflow: hidden; position: relative; .draggable-item { position: absolute; left: 0; top: 0; z-index: 1; } } &.maxHidden { .uploadBox { display: none; } } } // el-image .el-image-viewer__wrapper { .el-image-viewer__mask { opacity: .8; } .el-icon-circle-close { color: #fff; } } </style>
浙公网安备 33010602011771号