安装vue-draggable
npm i -S vuedraggable
子组件DragUpload.vue
<template>
<div v-loading="loading">
<draggable tag="ul" v-model="allListChild" v-bind="dragOptions" @update="datadragEnd" @start="drag = true" @end="drag = false" style="margin-left:-40px;">
<div class="img-wrapper" v-for="(item,index) in allListChild" :key="index">
<el-image :src="item.imgUrl">
</el-image>
<!-- 鼠标经过图片放大icon和删除icon -->
<div class="operate-wrap" :title="'拖曳图片可排序'">
<div class="operate-bg"></div> <!-- 遮罩 -->
<i class="el-icon-delete del-icon" @click="deleImg(item.URL,index)"></i> <!-- 删除图片 -->
<i class="el-icon-zoom-in preview-icon" @click="handlePictureCardPreview(item.imgUrl,index)"></i> <!-- 点击显示原图 -->
</div>
<!-- 原图显示弹框 -->
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="">
</el-dialog>
</div>
</draggable>
<el-upload ref='upload' list-type="picture-card" :limit="20" :show-file-list="false" multiple action="http://upload.qiniu.com/" :data="qiniuUploadForm" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-success="uploadAppSuccess" :on-error="handleImageError" :before-upload="beforeAvatarUpload" accept=".gif,.jpeg,.jpg,.JPG,.JPEG,.png,.svg,.ico" title="点击上传">
<i class="el-icon-plus"></i>
</el-upload>
</div>
</template>
<script>
import draggable from "vuedraggable";
export default {
name: "DragUpload",
props: {
allList: Array,
},
components: {
draggable,
},
data() {
return {
loading: false,
allListChild: [],
imgUrl: '',
drag: false,
qiniuUploadForm: {}, // 七牛图片的上传对象
dialogVisible: false,
dialogImageUrl: '',
};
},
methods: {
beforeAvatarUpload(file) {
this.loading = true;
const isLt10M = file.size / 1024 / 1024 < 10;
if (!isLt10M) {
this.$message.error('图片大小不超过10M')
return
}
return api.getQiniuToken().then((res) => { // 这里需要配置自己的七牛云api接口
// 配置上传的七牛token
this.qiniuUploadForm = {
token: res.retInfo,
name: file.name,
key: Math.floor(Math.random() * 10 + 1) + file.name,
};
});
},
handleRemove(file, fileList) {
console.log(file, fileList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file;
this.dialogVisible = true;
},
uploadAppSuccess(file) {
var temp = {
imgUrl: 'https://XXXX.com/' + file.retInfo,
orderNumber: this.allListChild.length
};
this.allListChild.push(temp) // 启动拖拽功能
this.$emit('allList', this.allListChild)
setTimeout(this.loading = false, 10000)
},
// 上传图片失败
handleImageError(err, file) {
if (err.status == 614) {
alert("七牛云上已存在同名称图片!");
} else {
alert(JSON.stringify(err));
}
this.loading = false
},
handlePreview(file) {
console.log(file);
this.dialogVisible = true;
},
//删除图片
deleImg(data, index) {
this.allListChild.splice(index, 1)
},
// 拖动排序
datadragEnd(evt) {
// console.log('拖动前的索引 :' + evt.oldIndex)
// console.log('拖动后的索引 :' + evt.newIndex)
this.allListChild.map((item, index) => {
item.orderNumber = index
})
this.$emit('allList', this.allListChild)
}
},
computed: {
dragOptions() {
return {
animation: 200,
group: "description",
disabled: false,
ghostClass: "ghost"
};
},
},
watch: {
allList(newVal) {
this.allListChild = newVal;
}
}
}
</script>
<style lang="less" scoped>
.img-list {
display: inline-block;
}
.img-wrapper {
float: left;
position: relative;
margin-right: 20px;
margin-bottom: 20px;
border: 1px dashed #c0ccda;
border-radius: 6px;
width: 148px;
height: 148px;
overflow: hidden;
&:hover {
.operate-wrap {
display: block;
}
}
}
.operate-wrap {
display: none;
}
.operate-bg {
background: #000000;
width: 148px;
height: 148px;
opacity: 0.4;
position: absolute;
top: 0;
left: 0;
z-index: 8;
}
.del-icon {
position: absolute;
top: 0;
right: 36px;
font-size: 25px;
line-height: 142px;
color: #ffffff;
z-index: 10;
}
.preview-icon {
position: absolute;
top: 0;
left: 36px;
font-size: 25px;
line-height: 142px;
color: #ffffff;
z-index: 10;
}
</style>
子组件Upload.vue
<template>
<div>
<div class="upload-wrap">
<!-- 编辑/查看时图片显示 -->
<div ref="ShowImg" v-if="imgUrl">
<div class="img-wrapper">
<el-image :src="imgUrl"></el-image>
<div class="operate-wrap">
<div class="operate-bg"></div>
<i class="el-icon-delete del-icon" @click="deleImg()"></i>
<i class="el-icon-zoom-in preview-icon" @click="handlePreview()"></i>
</div>
</div>
</div>
<!-- 新增时 点击上传图片 -->
<el-upload list-type="picture-card" :multiple='multiple' action="http://upload.qiniu.com/" :data="qiniuUploadForm" :on-preview="handlePictureCardPreview" :on-remove="handleRemove" :on-error="handleImageError" :on-success="handleCoverSuccess" :before-upload="beforeCoverUpload" accept=".gif,.jpeg,.jpg,.JPG,.JPEG,.png,.svg,.ico" title="点击上传">
<i class="el-icon-plus"></i>
</el-upload>
</div>
<!-- 弹框显示原图 -->
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="childImg||imgUrl" alt="">
</el-dialog>
<!-- 提示性文本 -->
<div class="row">
<div slot="tip" class="el-upload__tip" style="line-height:24px;color:#999999">
<slot name="advise-tip"></slot>
</div>
</div>
</div>
</template>
<script>
export default {
props: {
imgUrl: String,
},
data() {
return {
childImg: '',
qiniuUploadForm: {}, // 七牛图片的上传对象
dialogVisible: false,
multiple: false,
}
},
methods: {
// 上传图片成功
handleCoverSuccess(res) {
this.childImg = "https://XXXX.com/" + res.retInfo;
this.$emit('childImg', this.childImg);
},
// 上传图片失败
handleImageError(err, file) {
if (err.status == 614) {
this.$message.error("七牛云上已存在同名称图片!");
} else {
this.$message.error(JSON.stringify(err));
}
},
beforeCoverUpload(file) {
const isLt1M = file.size / 1024 / 1024 < 1;
if (!isLt1M) {
this.$message.error('图片大小不超过1M');
return;
}
return api.getQiniuToken().then((res) => { // 这里需要配置自己的七牛云api接口
// 配置上传的七牛token
this.qiniuUploadForm = {
token: res.retInfo,
name: file.name,
key: Math.floor(Math.random() * 10 + 1) + file.name,
};
});
},
handleRemove(file) {
console.log(file);
},
handlePictureCardPreview(file) {
this.childImg = file.url;
this.$emit('childImg', this.childImg);
this.dialogVisible = true;
},
// 删除图片
deleImg() {
this.childImg = '';
this.$refs.ShowImg.innerHTML = "";
this.$emit('childImg', this.childImg);
},
// 预览
handlePreview() {
this.dialogVisible = true;
},
},
}
</script>
<style lang="less" scoped>
.upload-wrap {
max-width: 150px;
overflow: hidden;
white-space: nowrap;
& > div {
display: inline-block;
vertical-align: middle;
}
}
.img-wrapper {
position: relative;
margin-right: 20px;
margin-bottom: 20px;
border: 1px dashed #c0ccda;
border-radius: 6px;
width: 148px;
height: 148px;
overflow: hidden;
&:hover {
.operate-wrap {
display: block;
}
}
}
.operate-wrap {
display: none;
}
.operate-bg {
background: #000000;
width: 148px;
height: 148px;
opacity: 0.4;
position: absolute;
top: 0;
left: 0;
z-index: 8;
}
.del-icon {
position: absolute;
top: 0;
right: 36px;
font-size: 25px;
line-height: 142px;
color: #ffffff;
z-index: 10;
}
.preview-icon {
position: absolute;
top: 0;
left: 36px;
font-size: 25px;
line-height: 142px;
color: #ffffff;
z-index: 10;
}
</style>
父页面 Home.vue
<template>
<div style="margin:40px">
<el-form :model="ruleForm" ref="ruleForm" label-width="126px">
<el-row style="width:980px">
<el-col :span="24">
<div class="grid-content bg-purple-dark">
<el-form-item label="上传图片:" prop="imgUrl" class="avatar-item">
<div class="row">
<Upload :imgUrl="ruleForm.imgUrl" v-on:childImg="childImgUrl">
<p slot="advise-tip">图片大小不超过1M</p>
</Upload>
</div>
</el-form-item>
<el-form-item label="图片可拖曳排序:" prop="trialImgs">
<div class="row">
<DragUpload :allList="ruleForm.trialImgs" v-on:allList="trialImgs">
</DragUpload>
<div class="el-upload__tip gray-tip">每张图片大小不超过10M</div>
</div>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')" v-show="!edit">保存</el-button>
</el-form-item>
</div>
</el-col>
</el-row>
</el-form>
</div>
</template>
<script>
import Upload from "../components/Upload";
import DragUpload from '../components/DragUpload'; // 引入vue-draggable
export default {
data() {
return {
name: "Home",
ruleForm: {
imgUrl: '',
trialImgs: [],
},
dialogImageUrl: '',
dialogVisible: false,
};
},
components: {
Upload,
DragUpload,
},
methods: {
// 上传图片
childImgUrl(childImg) {
this.ruleForm.imgUrl = childImg;
},
// 图片可拖曳排序
trialImgs(allList) {
this.ruleForm.trialImgs = allList
},
// 保存
submitForm(formName) {
this.$refs[formName].validate((valid) => {
if (valid) {
// console.log(this.ruleForm) // 所有数据
let tempRuleForm = JSON.parse(JSON.stringify(this.ruleForm))
let parmas = {
"id": this.$route.query.id * 1,
"imgUrl": tempRuleForm.imgUrl,
"triaTpicList": tempRuleForm.triaTpicList
}
console.log(parmas)
api.save(parmas).then((res) => {
console.log(res)
alert(res.msg);
})
} else {
console.log('保存失败');
return false;
}
});
},
// 获取数据
getDatas() {
let that = this;
let id = this.$route.query.id;
if (id) {
api.editDatas(id).then(res => {
if (res.data) {
const datas = res.data;
that.ruleForm = {
"imgUrl": datas.imgUrl,
"trialImgs": datas.trialImgs,
}
console.log(that.ruleForm)
}
})
}
},
}
}
</script>
完整项目下载:https://download.csdn.net/download/weixin_45421804/70037592