<template> <div :id="containerId" style="position: relative"> <!-- ---------------------------- begin 图片左右换位置 ------------------------------------- --> <div class="movety-container" :style="{top:top+'px',left:left+'px',display:moveDisplay}" style="padding:0 8px;position: absolute;z-index: 91;height: 32px;width: 104px;text-align: center;"> <div :id="containerId+'-mover'" :class="showMoverTask?'uploadty-mover-mask':'movety-opt'" style="margin-top: 12px"> <a @click="moveLast" style="margin: 0 5px;"> <a-icon type="arrow-left" style="color: #fff;font-size: 16px"/> </a> <a @click="moveNext" style="margin: 0 5px;"> <a-icon type="arrow-right" style="color: #fff;font-size: 16px"/> </a> </div> </div> <!-- ---------------------------- end 图片左右换位置 ------------------------------------- --> <a-upload name="file" :multiple="multiple" :action="uploadAction" :headers="headers" :data="{'biz':bizPath}" :fileList="fileList" :beforeUpload="doBeforeUpload" @change="handleChange" :disabled="disabled" :returnUrl="returnUrl" :listType="complistType" @preview="handlePreview" :class="{'uploadty-disabled':disabled}"> <template> <div v-if="isImageComp"> <a-icon type="plus"/> <div class="ant-upload-text">{{ text }}</div> </div> <a-button v-else-if="buttonVisible"> <a-icon type="upload"/> {{ text }} </a-button> </template> </a-upload> <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel"> <img alt="example" style="width: 100%" :src="previewImage"/> </a-modal> </div> </template> <script> import Vue from 'vue' import {ACCESS_TOKEN} from "@/store/mutation-types" import {getFileAccessHttpUrl} from '@/api/manage'; const FILE_TYPE_ALL = "all" const FILE_TYPE_IMG = "image" const FILE_TYPE_TXT = "file" const uidGenerator = () => { return '-' + parseInt(Math.random() * 10000 + 1, 10); } const getFileName = (path) => { if (path.lastIndexOf("\\") >= 0) { let reg = new RegExp("\\\\", "g"); path = path.replace(reg, "/"); } return path.substring(path.lastIndexOf("/") + 1); } export default { name: 'JUpload', data() { return { uploadAction: window._CONFIG['domianURL'] + "/sys/common/upload", headers: {}, fileList: [], newFileList: [], uploadGoOn: true, previewVisible: false, //---------------------------- begin 图片左右换位置 ------------------------------------- previewImage: '', containerId: '', top: '', left: '', moveDisplay: 'none', showMoverTask: false, moverHold: false, currentImg: '' //---------------------------- end 图片左右换位置 ------------------------------------- } }, props: { text: { type: String, required: false, default: "点击上传" }, fileType: { type: String, required: false, default: FILE_TYPE_ALL }, /*这个属性用于控制文件上传的业务路径*/ bizPath: { type: String, required: false, default: "temp" }, value: { type: [String, Array], required: false }, // update-begin- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击 disabled: { type: Boolean, required: false, default: false }, // update-end- --- author:wangshuai ------ date:20190929 ---- for:Jupload组件增加是否能够点击 //此属性被废弃了 triggerChange: { type: Boolean, required: false, default: false }, /** * update -- author:lvdandan -- date:20190219 -- for:Jupload组件增加是否返回url, * true:仅返回url * false:返回fileName filePath fileSize */ returnUrl: { type: Boolean, required: false, default: true }, number: { type: Number, required: false, default: 0 }, buttonVisible: { type: Boolean, required: false, default: true }, multiple: { type: Boolean, default: true }, beforeUpload: { type: Function }, }, watch: { value: { immediate: true, handler() { let val = this.value if (val instanceof Array) { if (this.returnUrl) { this.initFileList(val.join(',')) } else { this.initFileListArr(val); } } else { this.initFileList(val) } } } }, computed: { isImageComp() { return this.fileType === FILE_TYPE_IMG }, complistType() { return this.fileType === FILE_TYPE_IMG ? 'picture-card' : 'text' } }, created() { const token = Vue.ls.get(ACCESS_TOKEN); //---------------------------- begin 图片左右换位置 ------------------------------------- this.headers = {"X-Access-Token": token}; this.containerId = 'container-ty-' + new Date().getTime(); //---------------------------- end 图片左右换位置 ------------------------------------- }, methods: { initFileListArr(val) { if (!val || val.length == 0) { this.fileList = []; return; } let fileList = []; for (var a = 0; a < val.length; a++) { let url = getFileAccessHttpUrl(val[a].filePath); fileList.push({ uid: uidGenerator(), name: val[a].fileName, status: 'done', url: url, response: { status: "history", message: val[a].filePath } }) } this.fileList = fileList }, initFileList(paths) { if (!paths || paths.length == 0) { //return []; // update-begin- --- author:os_chengtgen ------ date:20190729 ---- for:issues:326,Jupload组件初始化bug this.fileList = []; return; // update-end- --- author:os_chengtgen ------ date:20190729 ---- for:issues:326,Jupload组件初始化bug } let fileList = []; let arr = paths.split(",") for (var a = 0; a < arr.length; a++) { let url = getFileAccessHttpUrl(arr[a]); fileList.push({ uid: uidGenerator(), name: getFileName(arr[a]), status: 'done', url: url, response: { status: "history", message: arr[a] } }) } this.fileList = fileList }, handlePathChange() { let uploadFiles = this.fileList let path = '' if (!uploadFiles || uploadFiles.length == 0) { path = '' } let arr = []; for (var a = 0; a < uploadFiles.length; a++) { // update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错 if (uploadFiles[a].status === 'done') { arr.push(uploadFiles[a].response.message) } else { return; } // update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错 } if (arr.length > 0) { path = arr.join(",") } this.$emit('change', path); }, doBeforeUpload(file) { this.uploadGoOn = true var fileType = file.type; if (this.fileType === FILE_TYPE_IMG) { if (fileType.indexOf('image') < 0) { this.$message.warning('请上传图片'); this.uploadGoOn = false return false; } } // 扩展 beforeUpload 验证 if (typeof this.beforeUpload === 'function') { return this.beforeUpload(file) } return true }, handleChange(info) { console.log("--文件列表改变--") if (!info.file.status && this.uploadGoOn === false) { info.fileList.pop(); } let fileList = info.fileList if (info.file.status === 'done') { if (this.number > 0) { fileList = fileList.slice(-this.number); } if (info.file.response.success) { fileList = fileList.map((file) => { if (file.response) { let reUrl = file.response.message; file.url = getFileAccessHttpUrl(reUrl); } return file; }); } //this.$message.success(`${info.file.name} 上传成功!`); } else if (info.file.status === 'error') { this.$message.error(`${info.file.name} 上传失败.`); } else if (info.file.status === 'removed') { this.handleDelete(info.file) } this.fileList = fileList if (info.file.status === 'done' || info.file.status === 'removed') { //returnUrl为true时仅返回文件路径 if (this.returnUrl) { this.handlePathChange() } else { //returnUrl为false时返回文件名称、文件路径及文件大小 this.newFileList = []; for (var a = 0; a < fileList.length; a++) { // update-begin-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错 if (fileList[a].status === 'done') { var fileJson = { fileName: fileList[a].name, filePath: fileList[a].response.message, fileSize: fileList[a].size }; this.newFileList.push(fileJson); } else { return; } // update-end-author:lvdandan date:20200603 for:【TESTA-514】【开源issue】多个文件同时上传时,控制台报错 } this.$emit('change', this.newFileList); } } }, handleDelete(file) { //如有需要新增 删除逻辑 console.log(file) }, handlePreview(file) { if (this.fileType === FILE_TYPE_IMG) { this.previewImage = file.url || file.thumbUrl; this.previewVisible = true; } else { location.href = file.url } }, handleCancel() { this.previewVisible = false; }, //---------------------------- begin 图片左右换位置 ------------------------------------- moveLast() { //console.log(ev) //console.log(this.fileList) //console.log(this.currentImg) let index = this.getIndexByUrl(); if (index == 0) { this.$message.warn('未知的操作') } else { let curr = this.fileList[index].url; let last = this.fileList[index - 1].url; let arr = [] for (let i = 0; i < this.fileList.length; i++) { if (i == index - 1) { arr.push(curr) } else if (i == index) { arr.push(last) } else { arr.push(this.fileList[i].url) } } this.currentImg = last this.$emit('change', arr.join(',')) } }, moveNext() { let index = this.getIndexByUrl(); if (index == this.fileList.length - 1) { this.$message.warn('已到最后~') } else { let curr = this.fileList[index].url; let next = this.fileList[index + 1].url; let arr = [] for (let i = 0; i < this.fileList.length; i++) { if (i == index + 1) { arr.push(curr) } else if (i == index) { arr.push(next) } else { arr.push(this.fileList[i].url) } } this.currentImg = next this.$emit('change', arr.join(',')) } }, getIndexByUrl() { for (let i = 0; i < this.fileList.length; i++) { if (this.fileList[i].url === this.currentImg || encodeURI(this.fileList[i].url) === this.currentImg) { return i; } } return -1; } }, mounted() { const moverObj = document.getElementById(this.containerId + '-mover'); if (moverObj) { moverObj.addEventListener('mouseover', () => { this.moverHold = true this.moveDisplay = 'block'; }); moverObj.addEventListener('mouseout', () => { this.moverHold = false this.moveDisplay = 'none'; }); } let picList = document.getElementById(this.containerId) ? document.getElementById(this.containerId).getElementsByClassName('ant-upload-list-picture-card') : []; if (picList && picList.length > 0) { picList[0].addEventListener('mouseover', (ev) => { ev = ev || window.event; let target = ev.target || ev.srcElement; if ('ant-upload-list-item-info' == target.className) { this.showMoverTask = false let item = target.parentElement this.left = item.offsetLeft this.top = item.offsetTop + item.offsetHeight - 50; this.moveDisplay = 'block'; this.currentImg = target.getElementsByTagName('img')[0].src } }); picList[0].addEventListener('mouseout', (ev) => { ev = ev || window.event; let target = ev.target || ev.srcElement; //console.log('移除',target) if ('ant-upload-list-item-info' == target.className) { this.showMoverTask = true setTimeout(() => { if (this.moverHold === false) this.moveDisplay = 'none'; }, 100) } if ('ant-upload-list-item ant-upload-list-item-done' == target.className || 'ant-upload-list ant-upload-list-picture-card' == target.className) { this.moveDisplay = 'none'; } }) //---------------------------- end 图片左右换位置 ------------------------------------- } }, model: { prop: 'value', event: 'change' } } </script> <style lang="less"> .uploadty-disabled { .ant-upload-list-item { .anticon-close { display: none; } .anticon-delete { display: none; } } } //---------------------------- begin 图片左右换位置 ------------------------------------- .uploadty-mover-mask { background-color: rgba(0, 0, 0, 0.5); opacity: .8; color: #fff; height: 28px; line-height: 28px; } //---------------------------- end 图片左右换位置 ------------------------------------- </style>