栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java > SpringBoot

微信小程序仿朋友圈发布商品信息及图片

SpringBoot 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

微信小程序仿朋友圈发布商品信息及图片


本文使用的技术栈:小程序开发、SpringBoot、MyBatis、Redis

今天要写一个商城项目中的发布商品模块,需求跟闲鱼这样的app基本一致,就是基本的上传表单数据和图片。图片模块我想采用类似朋友圈的方式来完成,符合大部分用户的操作逻辑。

现在朋友圈发图片已经可以拖拽改变图片顺序或删除图片了,但是用小程序实现拖拽功能太麻烦了。所以,我将换一种方式来实现图片删除和预览,最后,再写两个后端接口,把商品信息和图片存入数据库。

这里前端用到了Vant Weapp的UI库 https://github.com/youzan/vant-weapp

先来看看前端页面的代码

  

效果如下图:

表单部分代码很简单,所以这里主要分析添加图片的代码逻辑。第一步,找一张添加照片的图标绑定一个wx.chooseImage事件,定义一个全局变量count作为当前选择的图片数量,使用户选择的图片在9张以内;定义一个数组,用于存放当前图片的url,在用户选择完照片后,该数组会更新,并用wx:for渲染至前端页面。
 chooseimage: function () {
    var me = this;
    //动态更新当前用户可以上传的图片数
    var count = 9 - that.data.img_url.length;
    wx.chooseImage({
      count: count, // 默认9 
      sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 
      sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 
      success: function (res) {
 if (res.tempFilePaths.length > 0) {
   //把每次选择的图push进数组
   let img_url = that.data.img_url;
   for (let i = 0; i < res.tempFilePaths.length; i++) {
     img_url.push(res.tempFilePaths[i])
   }
   me.setData({
     img_url: img_url
   })
   
   //图如果满了9张,不显示添加图片图标
   if (that.data.img_url.length >= 8) {
     me.setData({
hideAdd: 1
     })
   } else {
     me.setData({
hideAdd: 0
     })
   }
 }
      }
    })
  }

当图片数量达到9张,隐藏添加图片图标

第二步,给图片加上预览和删除功能,预览功能使用wx.previewImage绑定图片的索引值即可;删除功能则是在图片右上角加上一个删除图标来绑定删除事件,删除后实时更新图片列表。

  //预览图片
  previewImg:function(e){
    var me = this;
    var img_url = me.data.img_url;
    var index = e.target.dataset.index;
    wx.previewImage({
      urls: img_url,
      current : img_url[index],
      success:function(res){
   console.log(res);
      }
    })
  },

  //删除图片
  deleteImg: function (e){
    var me = this;
    var img_url = me.data.img_url;
    var index = e.target.dataset.index;
    img_url.splice(index, 1); 
    me.setData({
      img_url: img_url,
      //若当前图片超过9张,则隐藏添加图标;少于9张则显示添加图标。
      hideAdd: me.data.img_url.length <9 ? false : true
    })
  },

第三步,上传商品信息和图片,我将这个功能分为两部分完成,首先将表单数据先上传,再将图片上传。这里假设用户已经成功使用微信登录小程序,且登录态保存已保存在本地缓存。在表单数据上传成功后,会返回一个商品ID到前端,再调用上传图片方法,将商品ID和每张图片的相对路径保存至数据库。实现代码如下。
//上传商品信息
send:function(e){
    var me = this;
    console.log(e);
    var goodsName = e.detail.value.goodsName;
    var goodsDesc = e.detail.value.goodsDesc;
    var goodsPrice = e.detail.value.goodsPrice;
    var goodsNum = e.detail.value.goodsNum;
    var goodsAddress = e.detail.value.goodsAddress;
    var goodsPhone = e.detail.value.goodsPhone;
    var thirdSession = wx.getStorageSync("thirdsession")
    wx.showLoading({
      title: '发布中--',
    })
    var serverUrl = app.serverUrl;
    wx.request({
      url: serverUrl + '/goods/uploadGoods',
      data: {
 thirdSession: thirdSession,
 goodsName: goodsName,  
 goodsDesc: goodsDesc,
 goodsPrice: goodsPrice,
 goodsNum: goodsNum,
 goodsAddress: goodsAddress,
 goodsPhone: goodsPhone,
      },
      method: "GET",
      success: function (res) {
 wx.hideLoading();
 console.log(res.data.data);
 //商品信息上传成功后,上传商品图片
 me.uploadGoodsImg(res.data.data);
      }
    })
  }

需要注意的是,小程序的wx.uploadFile接口的资源路径是String类的。所以多图上传时,我会递归调用这个接口来完成。

 //上传图片
 uploadGoodsImg: function (goodsId){
    var me = this;
    var imgFilePaths = me.data.img_url;
    var count = me.data.count;
    var serverUrl = app.serverUrl;
    wx.showLoading({
      title: '上传图片中--',
    })
    wx.uploadFile({
      url: serverUrl + '/goods/uploadGoodsImg', 
      filePath: imgFilePaths[count],
      name: 'file',
      formData: {
 goodsId: goodsId
      },
      success: function (res) {
   //可统计成功上传图片数
      },
      fail: function (res) {
   //可统计上传失败图片数
      },
      complete: function (res) {
 count++;
 me.setData({
   count: count
 })
 if (count >= imgFilePaths.length) {
   var data = JSON.parse(res.data);
   console.log(data);
   wx.hideLoading();
   if (data.status == 200) {
     wx.hideLoading();
     wx.showToast({
title: '上传成功!~~',
icon: 'success'
     });
     me.setData({
count: 0
     })
   } else if (data.status == 500) {
     wx.showToast({
title: data.msg,
     });
   }
 } else {
   //图片未上传完,递归调用本方法。
   me.uploadGoodsImg(goodsId);
 }
      }
    })
  }

第四步,后端接口使用IO流工具IOUtils将图片写入到指定的路径下,并将相对路径保存至数据库。这里存放图片路径采用了一个单独的表。具体代码如下:
    //保存商品信息
	@GetMapping("/uploadGoods")
	public IMoocJSonResult uploadFace(String thirdSession,String goodsName,
			String goodsDesc,double goodsPrice,String goodsPhone,
			int goodsNum,String goodsAddress) throws Exception {
		
		if (StringUtils.isBlank(thirdSession)) {
			return IMoocJSONResult.errorMsg("thirdSession is none");
		}

 String value = (String) redis.get("Wxuser-redis-session:"+thirdSession);
 System.out.println(value);
 if (StringUtils.isBlank(value)) {
     return IMoocJSONResult.errorMsg("session timeout");
 }
 //解析json格式的str
 JSonObject json = JSONObject.parseObject(value);
 String openId = json.getString("openid");
		
 String goodsId = sid.nextShort();
		
		Goods goods = new Goods();
		goods.setId(goodsId);
		goods.setSellerId(openId);
		goods.setSellerPhone(goodsPhone);
		goods.setAddress(goodsAddress);
		goods.setGoodsDesc(goodsDesc);
		goods.setLikeCounts(0);
		goods.setGoodsName(goodsName);
		goods.setPrice(goodsPrice);
		goods.setGoodsNum(goodsNum);
		
		goodsService.saveGoods(goods);
		
		return IMoocJSONResult.ok(goodsId);
	
	}

上传图片接口
@PostMapping(value="/uploadGoodsImg" ,headers="content-type=multipart/form-data")
public IMoocJSonResult uploadGoodsImg(String goodsId,@RequestParam("file") MultipartFile[] files) throws Exception {

		//文件保存的命名空间
		String fileSpace="D:/cunjin-xianyu-test";
		//保存到数据库的相对路径
		String uploadPathDB="/"+goodsId+"/img";
		FileOutputStream fileOutputStream=null;
		InputStream inputStream= null;
		try {
			if(files != null && files.length>0) {
				String fileName= files[0].getOriginalFilename();
				if (StringUtils.isNotBlank(fileName)) {
					//文件保存的最终路径
					String finalPath = fileSpace + uploadPathDB + "/" + fileName;
				    //设置数据库保存的路径
					uploadPathDB+=("/"+fileName);
					
					File outFile=new File(finalPath);
					
					if (outFile.getParentFile()!=null || !outFile.getParentFile().isDirectory()) {
						//创建父文件夹
						outFile.getParentFile().mkdirs();
					}
					fileOutputStream = new FileOutputStream(outFile);
					inputStream = files[0].getInputStream();
					IOUtils.copy(inputStream, fileOutputStream);
				}else {
					return IMoocJSONResult.errorMsg("上传出错");
				}
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return IMoocJSONResult.errorMsg("上传出错");
		}finally {
			if(fileOutputStream!=null) {
				fileOutputStream.flush();
				fileOutputStream.close();
			}
		}
		
		GoodsImg goodsImg = new GoodsImg();
		goodsImg.setGoodsId(goodsId);
		goodsImg.setImg(uploadPathDB);
		goodsService.saveGoodsImg(goodsImg);
		
		return IMoocJSONResult.ok("上传成功");

}

好了,代码写完了,现在来进行前后端联调,测试一下。我们先选几张图,输一些数据

在本地新建一个文件夹,用于存放图片,路径与代码的命名空间一致。

好了,现在我们点击发布,观察数据库和本地文件。

可以看到,我们发布的商品信息和图片相对路径都已经存入数据库了,同时,本地也已经保存了这两张图片。测试成功!

总结
  1. 数据库存放多张图片路径,除了用本文的方法,还可以使用一些特定符号将路径分隔开,存入商品信息表中,这样,即使上传多张图片也只会存入一行数据,不过这种方法也是在网上看过,自己还未实践过。
  2. 在使用wx.uploadFile接口时,要记得将content-type改为multipart/form-data。
  3. 使用IOUtils写文件的拷贝非常方便,无需各种输入流,然后读取line,输出到输出流。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号