微信小程序上传图片插件

微信小程序上传图片简易插件

先看看成果

在这里插入图片描述
在这里插入图片描述
目前代码仍然有些许BUG,如图单页面上存在 单图,多图,多图时 上传图片会出现丢图的情况。
但是单个页面单次使用多图上传功能时没有问题。
正常情况下需要手动点击进行上传。
可以在提交事件中验证是否上传,进行自动上传图片。

附代码:

  • 实现页面的代码
<view>
    <view class="imageUpload" bindtap="selectIcon" wx:if="{{!goods.icon_url}}">+</view>
    <view class="imageItem" wx:for-key="index" wx:if="{{goods.icon_url}}">
      <image src="{{goods.icon_url}}" draggable="true" bindtap="previewImage"></image>
      <view wx:if="isShowDel" class="imageDel" bindtap="deleteIcon">x</view>
    </view>
  </view>
  <upload-image bind:getImageList="getSwiperImageList" image-list="{{goods.swiper}}"></upload-image>
    <upload-image bind:getImageList="getDescImageList" image-list="{{goods.desc}}"></upload-image>
  • 页面JS
// pages/admin/goods/add.js
import Utils from '../../../static/utils/utils';
import Toast from '../../../static/dist/toast/toast';
const db = wx.cloud.database()
const cloud = wx.cloud;
Page({

  /**
   * 页面的初始数据
   */
  data: {
    goods: {}
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function(options) {
    this.setData({
      goods_id: options.id
    })
    this.init();
  },
  selectIcon() {
    let that = this;
    let goods = this.data.goods;
    wx.chooseImage({
      count: 1,
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success(res) {
        let tempPath = res.tempFilePaths[0];
        let fileName = new Date().getTime() + '.' + tempPath.substring(tempPath.lastIndexOf('.') + 1, tempPath.length);
        wx.cloud.uploadFile({
          cloudPath: 'goods/icon/' + new Date().getTime() + fileName,
          filePath: tempPath, // 文件路径
        }).then(res => {
          console.log(res);
          let fileID = res.fileID;

          wx.cloud.getTempFileURL({
            fileList: [fileID],
            success: res => {
              // get temp file URL
              console.log(res.fileList)
              console.log(res)
              goods.icon_id = res.fileList[0].fileID;
              goods.icon_url = res.fileList[0].tempFileURL;
              console.log(goods);
              that.setData({
                goods: goods
              })
            },
            fail: err => {
              console.log(err)
              // handle error
            }
          })

        }).catch(console.error)
      },
      fail(res) {
        console.log(res);
      },
      complete(res) {
        console.log(res);
      }
    })
  },

  deleteIcon(e) {
    let goods = this.data.goods;
    goods.icon_id = '';
    goods.icon_url = '';
    this.setData({
      goods: goods
    })
  },
  getSwiperImageList(e) {
    let imageList = e.detail;
    let goods = this.data.goods;
    goods.swiper = imageList;
    this.setData({
      goods: goods
    })
    console.log(goods);
    Toast.success('上传成功');
  },
  getDescImageList(e) {
    let imageList = e.detail;
    let goods = this.data.goods;
    goods.desc = imageList;
    this.setData({
      goods: goods
    })
    Toast.success('上传成功');
  },
  // 提交
  submit(e) {
    let goods = this.data.goods;
    console.log(goods);
    let flag = this.check(goods);
    if (!flag) {
      return;
    }
    let _id = goods._id;
    if (_id) {
      delete goods._id;
      delete goods._openid;

      wx.cloud.callFunction({
        // 要调用的云函数名称
        name: 'update',
        // 传递给云函数的event参数
        data: {
          _id: _id,
          data: goods,
        }
      }).then(res => {
        console.log(res)
        Toast.success('修改成功');
      }).catch(console.error)

    } else {
      db.collection('goods').add({
        // data 字段表示需新增的 JSON 数据
        data: goods
      }).then(res => {
        console.log(res)
        Toast.success('提交成功');
      }).catch(console.error)
    }
  },
  check(goods) {
    if (!goods.ptype_id) {
      Toast.fail('请选择类型');
      return false;
    }
    if (!goods.brand_id) {
      Toast.fail('请选择品牌');
      return false;
    }
    if (!goods.model_id) {
      Toast.fail('请选择型号');
      return false;
    }
    let min_price = goods.min_price;
    let max_price = goods.max_price;
    if (min_price > max_price) {
      Toast.fail('最低价格大于最高价格');
      return false;
    }
    if (!goods.icon_url) {
      Toast.fail('请上传图标');
      return false;
    }
    if (!goods.swiper || goods.swiper.length == 0) {
      Toast.fail('请上传顶部轮播图');
      return false;
    }
    if (!goods.desc || goods.desc.length == 0) {
      Toast.fail('请上传图标');
      return false;
    }
    return true;
  },
  // 选择类型三个方法
  focusPtype(e) {
    console.log(e)
    let that = this;
    db.collection('ptype').where({
      is_stop: 1
    }).get().then(res => {
      let ptypeArray = res.data;
      let ptypeList = [];
      for (let item of ptypeArray) {
        ptypeList.push(item.name);
      }
      that.setData({
        ptypeShow: true,
        ptypeList: ptypeList,
        ptypeArray: ptypeArray
      })
    }).catch(console.error)
  },
  cancelPtype(e) {
    this.setData({
      ptypeShow: false
    })
  },
  selectPtype(e) {
    let goods = this.data.goods;
    let index = e.detail.index;
    let ptypeArray = this.data.ptypeArray;
    goods.ptype_id = ptypeArray[index]._id;
    goods.ptype_name = e.detail.value;
    this.setData({
      ptypeShow: false,
      goods: goods
    })
  },
  // 选择品牌三个方法
  focusBrand(e) {
    console.log(e)
    let that = this;
    db.collection('brand').where({
      is_stop: 1
    }).get().then(res => {
      let brandArray = res.data;
      let brandList = [];
      for (let item of brandArray) {
        brandList.push(item.name);
      }
      that.setData({
        brandShow: true,
        brandList: brandList,
        brandArray: brandArray
      })
    }).catch(console.error)
  },
  cancelBrand(e) {
    this.setData({
      brandShow: false
    })
  },
  selectBrand(e) {
    let goods = this.data.goods;
    let index = e.detail.index;
    let brandArray = this.data.brandArray;
    goods.brand_id = brandArray[index]._id;
    goods.brand_name = e.detail.value;
    this.setData({
      brandShow: false,
      goods: goods
    })
  },
  // 选择系列三个方法
  focusSeries(e) {
    let ptype_id = this.data.goods.ptype_id;
    let brand_id = this.data.goods.brand_id;
    if (!ptype_id && !brand_id) {
      Toast.fail("请先选择系列和品牌");
      return;
    }
    let that = this;
    wx.cloud.callFunction({
      // 要调用的云函数名称
      name: 'getSeries',
      // 传递给云函数的event参数
      data: {
        ptype_id: ptype_id,
        brand_id: brand_id,
        is_stop: 1
      }
    }).then(res => {
      let seriesArray = res.result.seriesList;
      let seriesList = [];
      let n = -1;
      for (let i = 0; i < seriesArray.length; i++) {
        let item = seriesArray[i];
        if (!item.name) {
          n = i;
          continue;
        }
        seriesList.push(item.name);
      }
      seriesArray.splice(n, 1);
      that.setData({
        seriesShow: true,
        seriesList: seriesList,
        seriesArray: seriesArray
      })
    }).catch(console.error)
  },
  cancelSeries(e) {
    this.setData({
      seriesShow: false
    })
  },
  selectSeries(e) {
    let goods = this.data.goods;
    let index = e.detail.index;
    let seriesArray = this.data.seriesArray;
    let phoneArray = seriesArray[index].phoneList;
    goods.series_id = seriesArray[index]._id;
    goods.series_name = e.detail.value;
    this.setData({
      seriesShow: false,
      goods: goods,
      phoneArray: phoneArray
    })
  },
  // 选择系列三个方法
  focusModel(e) {
    console.log(this.data.goods)
    let ptype_id = this.data.goods.ptype_id;
    let brand_id = this.data.goods.brand_id;
    let series_id = this.data.goods.series_id;
    if (!ptype_id && !brand_id) {
      Toast.fail("请先选择系列和品牌");
      return;
    }
    let that = this;
    console.log(series_id);

    if (series_id) {
      let modelArray = this.data.phoneArray;
      console.log(modelArray)
      let modelList = [];
      for (let item of modelArray) {
        modelList.push(item.name);
      }

      that.setData({
        modelShow: true,
        modelList: modelList,
        modelArray: modelArray
      })

    } else {
      wx.cloud.callFunction({
        // 要调用的云函数名称
        name: 'getSeries',
        // 传递给云函数的event参数
        data: {
          ptype_id: ptype_id,
          brand_id: brand_id,
          is_stop: 1
        }
      }).then(res => {
        let seriesArray = res.result.seriesList;
        let modelList = [];
        let modelArray = [];
        for (let item of seriesArray) {
          if (!item.name) {
            modelArray = item.phoneList;
            break;
          }
        }
        for (let item of modelArray) {
          modelList.push(item.name);
        }
        that.setData({
          modelShow: true,
          modelList: modelList,
          modelArray: modelArray
        })
      }).catch(console.error)
    }

  },
  cancelModel(e) {
    this.setData({
      modelShow: false
    })
  },
  selectModel(e) {
    let goods = this.data.goods;
    let index = e.detail.index;
    let modelArray = this.data.modelArray;
    goods.model_id = modelArray[index]._id;
    goods.model_name = e.detail.value;
    this.setData({
      modelShow: false,
      goods: goods
    })
  },
  inputMinPrice(e) {
    console.log(e);
    let minPrice = e.detail;
    let goods = this.data.goods;
    goods.min_price = parseFloat(minPrice);
    this.setData({
      goods: goods
    })
  },
  inputMaxPrice(e) {
    console.log(e);
    let maxPrice = e.detail;
    let goods = this.data.goods;
    goods.max_price = parseFloat(maxPrice);
    this.setData({
      goods: goods
    })
  },

  // 页面初始化
  init() {
    let goods_id = this.data.goods_id;
    let that = this;
    db.collection('goods').where({
      _id: goods_id, // 填入当前用户 openid
    }).get().then(res => {
      that.setData({
        goods: res.data[0]
      })
    }).catch(err => {
      console.error(err)
    })
  }
})
  • 页面CSS
/* pages/admin/goods/add.wxss */

.min_price {
  width: 100rpx !important;
  display: inline-block;
}

.max_price {
  width: 100rpx !important;
  display: inline-block;
}

.imageUpload {
  line-height: 130rpx;
  text-align: center;
  font-size: 150rpx;
  color: #d9d9d9;
  border: 1px solid #d9d9d9;
  border-radius: 8rpx;
  width: 160rpx;
  height: 160rpx;
  margin: 10rpx;
}

.imageItem, .imageUpload {
  width: 160rpx;
  height: 160rpx;
  margin: 10rpx;
}

.imageDel {
  position: relative;
  left: 120rpx;
  bottom: 165rpx;
  background-color: rgba(0, 0, 0, 0.5);
  width: 36rpx;
  text-align: center;
  line-height: 35rpx;
  border-radius: 17rpx;
  color: white;
  font-size: 30rpx;
  padding-bottom: 2rpx;
}

.imageItem image {
  width: 160rpx;
  height: 160rpx;
  border-radius: 8rpx;
}

.submit {
  width: 100%;
}

  • 页面json
{
  "usingComponents": {
    "upload-image": "/static/components/upload-image"
  }
}

重点:插件本身

  • components/upload-image.wxml
<view class="imageUploadContainer">
  <view class="imageUploadList">
    <view class="imageItem" wx:for-key="index" wx:for="{{imageList}}">
      <image src="{{item.path}}" class="{{item.dragging == '' ? isDragging(index):''}}" draggable="true" bindtap="previewImage" data-index="{{index}}" bindtouchstart="start" bindtouchmove="move" bindtouchend="stop"></image>
      <view wx:if="isShowDel" class="imageDel" bindtap="deleteImage" data-index="{{index}}">x</view>
    </view>
    <view wx:if="isShowAdd" class="imageUpload" bindtap="selectImage">+</view>
  </view>
  <image wx:if="showMoveImage" class="moveImage {{showMoveImage ? '':'hide'}}" style="left:{{moveLeft}}px; top:{{moveTop}}px" src="{{moveImagePath}}"></image>
</view>
<button size="mini" type="primary" class="upload" bindtap="getImageList">上传</button>
  • components/upload-image.js
// static/components/upload-image.js
Component({
  /**
   * 组件的属性列表
   */
  properties: {
    imageList: {
      type: Array,
      value: [],
      observer: function() {

      }
    }
  },
  created() {

    // this.setData({
    //   imageList: imageList
    // })
  },
  /**
   * 组件的初始数据
   */
  data: {
    imageBasePos: {
      x0: -1,
      y0: -1,
      w: -1,
      h: -1,
    },
    showMoveImage: false,
    moveImagePath: '',
    moveLeft: 0,
    moveTop: 0,
    deltaLeft: 0,
    deltaTop: 0,
    dragIndex: null,
    targetImageIndex: null,
    // imageList:[]
  },

  /**
   * 组件的方法列表
   */
  methods: {
    selectImage: function() {
      console.log('selectImage');
      let that = this;
      wx.chooseImage({
        count: 9,
        sizeType: ['original', 'compressed'],
        sourceType: ['album', 'camera'],
        success(res) {
          console.log(res);
          // tempFilePath可以作为img标签的src属性显示图片
          const tempFilePaths = res.tempFilePaths;
          let tempFiles = res.tempFiles;
          let imgList = [];
          for (let item of tempFiles) {
            let url = item.path;

            wx.cloud.uploadFile({
              cloudPath: 'goods/' + new Date().getTime() + '.' + url.substring(url.lastIndexOf('.') + 1, url.length),
              filePath: item.path,
            }).then(res => {
              console.log(res.fileID)
              imgList.push({
                file_id: res.fileID,
                path: item.path
              })
              that.setData({
                imageList: that.data.imageList.concat(imgList)
              })
              imgList = [];
            }).catch(error => {
              console.error
              // handle error
            })

          }
          // that.setData({
          //   imageList: that.data.imageList.concat(imgList)
          // })
        },
        fail(res) {
          console.log(res);
        },
        complete(res) {
          console.log(res);
        }
      })
    },
    deleteImage: function(e) {
      console.log('deleteImage');
      var imageIndex = e.currentTarget.dataset.index
      var deletedImagePath = this.data.imageList[imageIndex]
      let imageList = this.data.imageList;
      imageList.splice(imageIndex, 1)
      this.setData({
        imageList: imageList
      })
    },
    previewImage: function(e) {
      var imageIndex = e.currentTarget.dataset.index
      let imageList = this.data.imageList;
      let imgurls = [];
      for (let item of imageList) {
        imgurls.push(item.path);
      }
      wx.previewImage({
        current: imageList[imageIndex].path, // 当前显示图片的http链接
        urls: imgurls // 需要预览的图片http链接列表
      })
    },
    initImageBasePos: function() {
      let paddingRate = 0.024
      let _self = this
      let imageBasePos = this.data.imageBasePos;
      //计算图片基准位置
      wx.getSystemInfo({
        success: function(obj) {
          let screenWidth = obj.screenWidth
          let leftPadding = Math.ceil(paddingRate * screenWidth)
          let imageWidth = Math.ceil((screenWidth - 2 * leftPadding) / 4)

          imageBasePos.x0 = leftPadding
          imageBasePos.w = imageWidth
          imageBasePos.h = imageWidth
          _self.setData({
            imageBasePos: imageBasePos
          })
        }
      })
    },
    findOverlapImage: function(posX, posY) {
      let rows = Math.floor((posX - this.data.imageBasePos.x0) / this.data.imageBasePos.w)
      let cols = Math.floor((posY - this.data.imageBasePos.y0) / this.data.imageBasePos.h)
      let indx = cols * 4 + rows
      return indx
    },
    isDragging: function(indx) {
      return this.dragIndex === indx
    },
    start: function(e) {
      console.log('start')
      // console.log(this.data.isDragable)
      // if (!this.data.isDragable) {
      //   return
      // }
      let dragIndex = e.currentTarget.dataset.index
      let moveImagePath = this.data.imageList[dragIndex].path;
      let showMoveImage = true;
      let imageBasePos = this.data.imageBasePos;
      //计算纵向图片基准位置
      if (imageBasePos.y0 === -1) {
        this.initImageBasePos()

        let basePosY = Math.floor(dragIndex / 4) * imageBasePos.h
        let currentImageOffsetTop = e.currentTarget.offsetTop
        imageBasePos.y0 = currentImageOffsetTop - basePosY
      }

      //设置选中图片当前左上角的坐标
      let moveLeft = e.target.offsetLeft
      let moveTop = e.target.offsetTop
      this.setData({
        dragIndex: dragIndex,
        imageBasePos: imageBasePos,
        moveImagePath: moveImagePath,
        moveLeft: moveLeft,
        showMoveImage: showMoveImage,
        moveTop: moveTop
      })
    },
    move: function(e) {
      console.log('move');
      // if (!this.isDragable) {
      // return
      // }
      console.log(e)
      const touch = e.touches[0]
      let targetImageIndex = this.findOverlapImage(touch.clientX, touch.clientY)

      //初始化deltaLeft/deltaTop
      let deltaLeft = this.data.deltaLeft;
      let deltaTop = this.data.deltaTop;
      if (deltaLeft === 0) {
        deltaLeft = touch.clientX - this.data.moveLeft
        deltaTop = touch.clientY - this.data.moveTop
      }
      //设置移动图片位置
      let moveLeft = touch.clientX - this.data.deltaLeft
      let moveTop = touch.clientY - this.data.deltaTop
      console.log(targetImageIndex);
      this.setData({
        targetImageIndex: targetImageIndex,
        deltaLeft: deltaLeft,
        deltaTop: deltaTop || this.data.deltaTop,
        moveLeft: moveLeft,
        moveTop: moveTop
      })
    },
    stop: function(e) {
      console.log('stop')
      // if (!this.isDragable) {
      //   return
      // }
      let dragIndex = this.data.dragIndex;
      let targetImageIndex = this.data.targetImageIndex;
      console.log(dragIndex)
      console.log(targetImageIndex)
      let imageList = this.data.imageList;
      if (dragIndex !== null && targetImageIndex !== null) {
        if (targetImageIndex < 0) {
          targetImageIndex = 0
        }

        if (targetImageIndex >= imageList.length) {
          targetImageIndex = imageList.length - 1
        }
        console.log(dragIndex)
        console.log(targetImageIndex)
        //交换图片
        if (dragIndex !== targetImageIndex) {
          let item = imageList[dragIndex]
          imageList[dragIndex] = imageList[targetImageIndex]
          imageList[targetImageIndex] = item
        }
      }
      this.setData({
        dragIndex: null,
        targetImageIndex: null,
        deltaLeft: 0,
        deltaTop: 0,
        showMoveImage: false,
        imageList: imageList,
        dragIndex: dragIndex,
        targetImageIndex: targetImageIndex
      })
      console.log(this.data.showMoveImage);
      // this.$emit('input', this.imageList)
    },
    getImageList() {
      let imageList = this.data.imageList;
      console.log(imageList)
      this.triggerEvent("getImageList", imageList);
    }
  },

})
  • components/upload-image.css
.imageUploadContainer {
  padding: 10rpx 5rpx;
  margin: 10rpx 5rpx;
}

.dragging {
  transform: scale(1.2);
}

.imageUploadList {
  display: flex;
  flex-wrap: wrap;
}

.imageItem, .imageUpload {
  width: 160rpx;
  height: 160rpx;
  margin: 10rpx;
}

.imageDel {
  position: relative;
  left: 120rpx;
  bottom: 165rpx;
  background-color: rgba(0, 0, 0, 0.5);
  width: 36rpx;
  text-align: center;
  line-height: 35rpx;
  border-radius: 17rpx;
  color: white;
  font-size: 30rpx;
  padding-bottom: 2rpx;
}

.imageItem image, .moveImage {
  width: 160rpx;
  height: 160rpx;
  border-radius: 8rpx;
}

.imageUpload {
  line-height: 130rpx;
  text-align: center;
  font-size: 150rpx;
  color: #d9d9d9;
  border: 1px solid #d9d9d9;
  border-radius: 8rpx;
}

.moveImage {
  position: absolute;
  z-index: -1;
}

page {
  position: relative;
}

.hide {
  display: none;
}

.upload {
  text-align: right;
  margin-left: 80%;
}

  • components/upload-image.json
{
  "component": true,
  "usingComponents": {}
}

附完整的插件
https://download.csdn.net/download/weixin_39608271/12115313

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值