安装vue-draggable
npm i -S vuedraggable
子组件DragUpload.vue
<template>
<div>
<draggable
v-model="uploadList"
@update="datadragEnd"
@start="drag = true"
@end="drag = false"
>
<div class="img-wrapper" v-for="(item, index) in uploadList" :key="index">
<el-image :src="item" :key="imageKey"></el-image>
<div class="operate-wrap" :title="'拖曳图片可排序'">
<div class="operate-bg"></div>
<span class="icon-row">
<i class="el-icon-delete" @click="handleRemove(index)"></i>
<i class="el-icon-zoom-in" @click="handlePictureCardPreview(item)"></i>
</span>
</div>
</div>
</draggable>
<el-upload
:action="ishttps + '//XXXX.XXXXX.com/'"
list-type="picture-card"
:before-upload="handleBefore"
:on-success="handleSuccess"
:on-error="handleError"
:data="qiniuUploadDatas"
:accept="accepts"
title="点击上传"
multiple
v-show="uploadList.length < allListLen"
>
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="dialogVisible">
<img width="100%" :src="dialogImageUrl" alt="" />
</el-dialog>
</div>
</template>
<script>
import draggable from "vuedraggable";
import api from "../../api/index";
export default {
name: "drag-upload",
props: {
// 图片路径
allList: {
type: Array,
default() {
return [];
},
},
// 图片文件大小
imgSize: {
type: Number,
default: 10,
},
// 最大上传数量
allListLen: {
type: Number,
default: 5,
},
// 可上传的文件格式
accepts: {
type: String,
default:
"image/gif,image/jpeg,image/jpg,image/JPG,image/JPEG,image/png,image/svg,image/ico",
},
},
components: {
draggable,
},
data() {
return {
dialogImageUrl: "",
dialogVisible: false,
uploadList: [],
qiniuUploadDatas: {},
drag: false,
imageKey: 0,
ishttps: "",
flag: 0,
};
},
created() {
this.ishttps = document.location.protocol;
},
methods: {
handleRemove(index) {
this.flag = 0;
this.uploadList.splice(index, 1);
this.$emit("allList", this.uploadList);
},
handlePictureCardPreview(file) {
this.dialogImageUrl = file;
this.dialogVisible = true;
},
handleBefore(file) {
const type = this.accepts;
if (!type.includes(file.type)) {
alert(`请上传${this.accepts}类型文件`);
return false;
}
const isLtM = file.size / 1024 / 1024 < this.imgSize;
if (!isLtM) {
alert(`图片大小不超过${this.imgSize}M`);
return false;
}
return api.getQiniuToken().then((res) => {
// 配置上传的七牛token
this.qiniuUploadDatas = {
token: res.retInfo,
name: file.name,
key: new Date().getTime() + "-" + file.name,
};
});
},
handleSuccess(res) {
if (this.uploadList.length >= this.allListLen) {
this.flag++;
if (this.flag == 1) {
alert("最多可上传" + this.allListLen + "张图片");
}
return false;
}
this.flag = 0;
const url = "https://XXXX.XXXXX.com/" + res.retInfo; // 拼接七牛云的图片路径
this.imageKey++;
this.uploadList.push(url);
this.$emit("allList", this.uploadList);
},
handleError(error) {
if (error.status == 614) {
alert("七牛云上已存在相同名称图片");
return false;
} else {
alert(JSON.stringify(error));
return false;
}
},
// 拖动排序
datadragEnd() {
this.$emit("allList", this.uploadList);
},
},
watch: {
allList: {
handler: function (val) {
this.uploadList = val;
},
immediate: true,
deep: true,
},
},
};
</script>
<style lang="less" scoped>
.img-wrapper {
float: left;
position: relative;
margin-right: 20px;
margin-bottom: 20px;
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;
}
.icon-row {
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: row;
align-items: center;
font-size: 25px;
color: #ffffff;
z-index: 10;
width: 100%;
height: 100%;
justify-content: center;
i {
margin: 0 10px;
}
}
/deep/.el-upload-list__item {
display: none;
}
</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://xxxx.xxxx.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>
完整DEMO下载:https://download.csdn.net/download/weixin_45421804/70037592