vue2+elementUI+vuedraggable图片上传后可拖曳排序

安装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

上一篇:即将2022年了,Vue3.x详细版为尔奉上(对比Vue2.x,打包带走)


下一篇:VUE2常见的知识点(冲)