微信小程序仿朋友圈发布动态功能


Posted in Javascript onJuly 15, 2018

仿照微信朋友圈做了一个界面如下,先看效果:

1、点开界面

微信小程序仿朋友圈发布动态功能

2、选择图片

微信小程序仿朋友圈发布动态功能

3、点击上传

微信小程序仿朋友圈发布动态功能

4、动态显示

微信小程序仿朋友圈发布动态功能

第一个页面的wxml:

<view class='page'>
 <textarea class='text' bindinput="input" placeholder="分享动态" auto-height/>
 <view class="image_content">
 <view class='image' wx:for="{{img_url}}">
  <image class="moment_img" src="{{item}}"></image>
 </view>
 <view class='image' style='display:{{hideAdd?"none":"block"}}'>
  <image bindtap="chooseimage" class="moment_img" src='../../images/add.jpg'></image>
 </view>
 </view>
 <button bindtap="send" style='margin-right:5px;margin-left:5px'>发布</button>
</view>

第一个页面的wcss:

.page{
 padding: 20px
}
.text{
 width: 100%;
 margin-bottom: 40px;
 font-size: 20px;
 padding: 5px
}
.image{
 width:31%;
 height: 100px;
 padding: 2px
}
.moment_img{
 width: 98px;
 height: 98px;
}
.image_content{
 width: 100%;
 display: flex;
 flex-wrap: wrap;
 margin-bottom: 20px
}

第一个页面的js:

Page({
 data: {
 img_url: [],
 content:''
 },
 onLoad: function (options) {
 },
 input:function(e){
 this.setData({
  content:e.detail.value
 })
 },
 chooseimage:function(){
 var that = this;
 wx.chooseImage({
  count: 9, // 默认9 
  sizeType: ['original', 'compressed'], // 可以指定是原图还是压缩图,默认二者都有 
  sourceType: ['album', 'camera'], // 可以指定来源是相册还是相机,默认二者都有 
  success: function (res) {
  if (res.tempFilePaths.length>0){
   //图如果满了9张,不显示加图
   if (res.tempFilePaths.length == 9){
   that.setData({
    hideAdd:1
   })
   }else{
   that.setData({
    hideAdd: 0
   })
   }
   //把每次选择的图push进数组
   let img_url = that.data.img_url;
   for (let i = 0; i < res.tempFilePaths.length; i++) {
   img_url.push(res.tempFilePaths[i])
   }
   that.setData({
   img_url: img_url
   })
  }
  }
 }) 
 },
 //发布按钮事件
 send:function(){
 var that = this;
 var user_id = wx.getStorageSync('userid')
 wx.showLoading({
  title: '上传中',
 })
 that.img_upload()
 },
 //图片上传
 img_upload: function () {
 let that = this;
 let img_url = that.data.img_url;
 let img_url_ok = [];
 //由于图片只能一张一张地上传,所以用循环
 for (let i = 0; i < img_url.length; i++) {
  wx.uploadFile({
  //路径填你上传图片方法的地址
  url: 'http://wechat.homedoctor.com/Moments/upload_do',
  filePath: img_url[i],
  name: 'file',
  formData: {
   'user': 'test'
  },
  success: function (res) {
   console.log('上传成功');
   //把上传成功的图片的地址放入数组中
   img_url_ok.push(res.data)
   //如果全部传完,则可以将图片路径保存到数据库
   if (img_url_ok.length == img_url.length) {
   var userid = wx.getStorageSync('userid');
   var content = that.data.content;
   wx.request({
    url: 'http://wechat.homedoctor.com/Moments/adds',
    data: {
    user_id: userid,
    images: img_url_ok,
    content: content,
    },
    success: function (res) {
    if (res.data.status == 1) {
     wx.hideLoading()
     wx.showModal({
     title: '提交成功',
     showCancel: false,
     success: function (res) {
      if (res.confirm) {
      wx.navigateTo({
       url: '/pages/my_moments/my_moments',
      })
      }
     }
     })
    }
    }
   })
   }
  },
  fail: function (res) {
   console.log('上传失败')
  }
  })
 }
 } 
})

我认为难点在于请求后台上传图片的方法,虽然我也没搞懂,不过直接使用,他会返回放在服务器的哪个位置,代码如下:

public function upload_do(){
  extract(generateRequestParamVars());
  /**
   * upload.php
   *
   * Copyright 2013, Moxiecode Systems AB
   * Released under GPL License.
   *
   * License: http://www.plupload.com/license
   * Contributing: http://www.plupload.com/contributing
   */
  #!! IMPORTANT:
  #!! this file is just an example, it doesn't incorporate any security checks and
  #!! is not recommended to be used in production environment as it is. Be sure to
  #!! revise it and customize to your needs.
  // Make sure file is not cached (as it happens for example on iOS devices)
  header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
  header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
  header("Cache-Control: no-store, no-cache, must-revalidate");
  header("Cache-Control: post-check=0, pre-check=0", false);
  header("Pragma: no-cache");
  echo $fileName;
  // Support CORS
  // header("Access-Control-Allow-Origin: *");
  // other CORS headers if any...
  if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
   exit; // finish preflight CORS requests here
  }
  if ( !empty($_REQUEST[ 'debug' ]) ) {
   $random = rand(0, intval($_REQUEST[ 'debug' ]) );
   if ( $random === 0 ) {
    header("HTTP/1.0 500 Internal Server Error");
    exit;
   }
  }
  // header("HTTP/1.0 500 Internal Server Error");
  // exit;
  // 5 minutes execution time
  @set_time_limit(5 * 60);
  // Uncomment this one to fake upload time
  usleep(5000);
  // Settings
  // $targetDir = ini_get("upload_tmp_dir") . DIRECTORY_SEPARATOR . "plupload";
  $targetDir = C('CACHE_DIR').DIRECTORY_SEPARATOR.'Uploads'.DIRECTORY_SEPARATOR.'Tmps';
  $uploadDir = C('CACHE_DIR').DIRECTORY_SEPARATOR.'Uploads'.DIRECTORY_SEPARATOR.'Tmps'.DIRECTORY_SEPARATOR.date('Y').DIRECTORY_SEPARATOR.date('m').DIRECTORY_SEPARATOR.date('d');
  $uploadUrl = '/Uploads/Tmps/'.date('Y').'/'.date('m').'/'.date('d');
  //创建文件夹
  if(!is_dir($uploadDir)){
   @mkdir($uploadDir,0777,true);
  }
  $cleanupTargetDir = true; // Remove old files
  $maxFileAge = 5 * 3600; // Temp file age in seconds
  // Create target dir
  if (!file_exists($targetDir)) {
   @mkdir($targetDir);
  }
  // Create target dir
  if (!file_exists($uploadDir)) {
   @mkdir($uploadDir);
  }
  // Get a file name
  if (isset($_REQUEST["name"])) {
   $fileName = $_REQUEST["name"];
  } elseif (!empty($_FILES)) {
   $fileName = $_FILES["file"]["name"];
  } else {
   $fileName = uniqid();
  }
  //$fileName = uniqid("file_").'.'.pathinfo($fileName, PATHINFO_EXTENSION);
  $extension=pathinfo($fileName, PATHINFO_EXTENSION);
  if($extension){
   $fileName = uniqid().'.'.$extension;
  }else{
   $fileName = uniqid();
  }
  $md5File = @file('md5list.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
  $md5File = $md5File ? $md5File : array();
  if (isset($_REQUEST["md5"]) && array_search($_REQUEST["md5"], $md5File ) !== FALSE ) {
   die('{"jsonrpc" : "2.0", "result" : null, "id" : "id", "exist": 1}');
  }
  $filePath = $targetDir . DIRECTORY_SEPARATOR . $fileName;
  $uploadPath = $uploadDir . DIRECTORY_SEPARATOR . $fileName;
  // Chunking might be enabled
  $chunk = isset($_REQUEST["chunk"]) ? intval($_REQUEST["chunk"]) : 0;
  $chunks = isset($_REQUEST["chunks"]) ? intval($_REQUEST["chunks"]) : 1;
  // echo $_REQUEST["chunks"];
  // echo $_REQUEST["chunk"];
  // Remove old temp files
  if ($cleanupTargetDir) {
   if (!is_dir($targetDir) || !$dir = opendir($targetDir)) {
    die('{"jsonrpc" : "2.0", "error" : {"code": 100, "message": "Failed to open temp directory."}, "id" : "id"}');
   }
   while (($file = readdir($dir)) !== false) {
    $tmpfilePath = $targetDir . DIRECTORY_SEPARATOR . $file;
    // If temp file is current file proceed to the next
    if ($tmpfilePath == "{$filePath}_{$chunk}.part" || $tmpfilePath == "{$filePath}_{$chunk}.parttmp") {
     continue;
    }
    // Remove temp file if it is older than the max age and is not the current file
    if (preg_match('/\.(part|parttmp)$/', $file) && (@filemtime($tmpfilePath) < time() - $maxFileAge)) {
     @unlink($tmpfilePath);
    }
   }
   closedir($dir);
  }
  // Open temp file
  if (!$out = @fopen("{$filePath}_{$chunk}.parttmp", "wb")) {
   die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
  }
  if (!empty($_FILES)) {
   if ($_FILES["file"]["error"] || !is_uploaded_file($_FILES["file"]["tmp_name"])) {
    die('{"jsonrpc" : "2.0", "error" : {"code": 103, "message": "Failed to move uploaded file."}, "id" : "id"}');
   }
   // Read binary input stream and append it to temp file
   if (!$in = @fopen($_FILES["file"]["tmp_name"], "rb")) {
    die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
   }
  } else {
   if (!$in = @fopen("php://input", "rb")) {
    die('{"jsonrpc" : "2.0", "error" : {"code": 101, "message": "Failed to open input stream."}, "id" : "id"}');
   }
  }
  while ($buff = fread($in, 4096)) {
   fwrite($out, $buff);
  }
  @fclose($out);
  @fclose($in);
  rename("{$filePath}_{$chunk}.parttmp", "{$filePath}_{$chunk}.part");
  $index = 0;
  $done = true;
  for( $index = 0; $index < $chunks; $index++ ) {
   if ( !file_exists("{$filePath}_{$index}.part") ) {
    $done = false;
    break;
   }
  }
  if ( $done ) {
   if (!$out = @fopen($uploadPath, "wb")) {
    die('{"jsonrpc" : "2.0", "error" : {"code": 102, "message": "Failed to open output stream."}, "id" : "id"}');
   }
   if ( flock($out, LOCK_EX) ) {
    for( $index = 0; $index < $chunks; $index++ ) {
     if (!$in = @fopen("{$filePath}_{$index}.part", "rb")) {
      break;
     }
     while ($buff = fread($in, 4096)) {
      fwrite($out, $buff);
     }
     @fclose($in);
     @unlink("{$filePath}_{$index}.part");
    }
    flock($out, LOCK_UN);
   }
   @fclose($out);
  }
  // Return Success JSON-RPC response
  //die('{"jsonrpc" : "2.0", "result" : null, "id" : "id"}');
  die($uploadUrl .'/'. $fileName);
 }

这个函数会将图片保存到项目文件的Cache目录的Upload/....什么什么的目录下。而且也返回了这个完整路径跟前端,前端拿着这个再去请求后台接口保存这个路径。保存图片的后台代码如下:

首先是控制层:

public function adds()
 {
  try{
   D(self::$MOMENTS_MODEL)->adds();
   $ajaxReturnData['status'] = 1;
   $ajaxReturnData['message'] = 'success';
  }catch (\Exception $e){
   $ajaxReturnData['status'] = 0;
   $ajaxReturnData['message'] = 'fail';
  }
  $this->ajaxReturn($ajaxReturnData);
 }

然后是模型层:(我之前犯傻的是,应该直接把数组,也就是$images直接保存进去就行了,不用json_encode())

public function adds()
 {
  extract(generateRequestParamVars());
  $user = D(self::$WECHAT_USER)->find($user_id);
  $data = [];
  $data['user_id'] = $user_id;
  $data['user_name'] = $user['nickname'];
  $data['user_img'] = $user['imageurl'];
  $data['content'] = $content;
  $data['images'] = $images;
  $data['create_time'] = time();
 
  if ($this->add($data) === false) {
   throw new \Exception('OPERATION_FAILED');
  }
 }

保存好了之后,接下来如何在前端中显示图片呢?关键在于保存图片数组到数据库里,如何让它取出来的时候转为数组。代码如下:

控制层:

public function my_moments()
 {
  try{
   $data = D(self::$MOMENTS_MODEL)->my_moments();
   $ajaxReturnData['status'] = 1;
   $ajaxReturnData['message'] = 'success';
   $ajaxReturnData['data'] = $data;
  }catch (\Exception $e){
   $ajaxReturnData['status'] = 0;
   $ajaxReturnData['message'] = 'fail';
  }
  $this->ajaxReturn($ajaxReturnData);
 }

模型层:(这里使用了json_decode($array,true)方法,打印出来就是数组了)

public function my_moments()
 {
  extract(generateRequestParamVars());
  $user = D(self::$WECHAT_USER)->find($user_id);
  if($user['is_doctor'] == 1){
   $conditions = [];
   $conditions['user_id'] = $user_id;
   $doctor = D(self::$DOCTOR_MODEL)->where($conditions)->find();
   $identity = $doctor['hospital']. "" . $doctor['grade'];
  }else{
   $identity = '';
  }
  $conditions = [];
  $conditions['user_id'] = $user_id;
  $moments = $this->where($conditions)->order('create_time desc')->select();
  for($i = 0 ; $i < count($moments) ; $i ++){
   $moments[$i]['images'] = json_decode($moments[$i]['images'],true);
  }
  $data = [];
  $data[0] = $user;
  $data[1] = $moments;
  $data[2] = $identity;
  return $data;
 }

最后,动态页面如何显示图片呢?

主要我还在做九宫格图片的适配,就不贴代码了,主要是图片src需要加前缀,也就是你的域名。这样就能显示出来啦~

<image class="moment_img" src="http://wechat.homedoctor.com{{image}}"></image>

不相信你能看到最后,哈哈~我写的太多了

总结

以上所述是小编给大家介绍的微信小程序仿朋友圈发布动态界面,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的!

Javascript 相关文章推荐
js中匿名函数的N种写法
Sep 08 Javascript
JS 仿腾讯发表微博的效果代码
Dec 25 Javascript
Chrome下ifame父窗口调用子窗口的问题示例探讨
Mar 17 Javascript
jQuery与getJson结合的用法实例
Aug 07 Javascript
angularjs学习笔记之简单介绍
Sep 26 Javascript
基于JQuery实现图片轮播效果(焦点图)
Feb 02 Javascript
JavaScript动态生成二维码图片
Apr 20 Javascript
javascript入门之string对象【新手必看】
Nov 22 Javascript
vue实现动态数据绑定
Apr 28 Javascript
Angular(5.2-&gt;6.1)升级小结
Dec 27 Javascript
Bootstrap4 gulp 配置详解
Jan 06 Javascript
jQuery插件实现非常实用的tab栏切换功能【案例】
Feb 18 jQuery
Bootstrap Table中的多选框删除功能
Jul 15 #Javascript
详解JavaScript 中 if / if...else...替换方式
Jul 15 #Javascript
简述JS控制台的使用
Jul 15 #Javascript
简述JS浏览器的三种弹窗
Jul 15 #Javascript
Vue路由钩子之afterEach beforeEach的区别详解
Jul 15 #Javascript
js+SVG实现动态时钟效果
Jul 14 #Javascript
vue实现通讯录功能
Jul 14 #Javascript
You might like
PHP使用正则表达式获取微博中的话题和对象名
2015/07/18 PHP
善用事件代理,警惕闭包的性能陷阱。
2011/01/20 Javascript
HTTP 304错误的详细讲解
2013/11/13 Javascript
原生js和jquery中有关透明度设置的相关问题
2014/01/08 Javascript
Javascript中this的用法详解
2014/09/22 Javascript
javascript实现了照片拖拽点击置顶的照片墙代码
2015/04/03 Javascript
微信小程序 连续旋转动画(this.animation.rotate)详解
2017/04/07 Javascript
nodejs超出最大的调用栈错误问题
2017/12/27 NodeJs
JS实现非首屏图片延迟加载的示例
2018/01/06 Javascript
基于vue监听滚动事件实现锚点链接平滑滚动的方法
2018/01/17 Javascript
vue element-ui table表格滚动加载方法
2018/03/02 Javascript
Vue.js进阶知识点总结
2018/04/01 Javascript
React事件处理的机制及原理
2018/12/03 Javascript
深入理解js A*寻路算法原理与具体实现过程
2018/12/13 Javascript
JavaScript 继承 封装 多态实现及原理详解
2019/07/29 Javascript
[27:39]Ti4 循环赛第二日 LGD vs Fnatic
2014/07/11 DOTA
RC4文件加密的python实现方法
2015/06/30 Python
使用Python写CUDA程序的方法
2017/03/27 Python
python实现人民币大写转换
2018/06/20 Python
Linux下python与C++使用dlib实现人脸检测
2018/06/29 Python
如何使用python爬虫爬取要登陆的网站
2019/07/12 Python
python并发编程多进程 互斥锁原理解析
2019/08/20 Python
python 绘制国旗的示例
2020/09/27 Python
CSS3教程(5):网页背景图片
2009/04/02 HTML / CSS
AmazeUI 图标的示例代码
2020/08/13 HTML / CSS
linux面试题参考答案(8)
2016/04/19 面试题
JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗?
2013/07/02 面试题
职高毕业生自我鉴定
2013/10/21 职场文书
物流专业大学应届生求职信
2013/11/03 职场文书
体育系毕业生求职自荐信
2014/04/16 职场文书
英语分层教学实施方案
2014/06/15 职场文书
捐书倡议书
2014/08/29 职场文书
贫困证明书格式及范文
2014/10/15 职场文书
2014年教育教学工作总结
2014/11/13 职场文书
python学习之panda数据分析核心支持库
2021/05/07 Python
详解MongoDB的条件查询和排序
2021/06/23 MongoDB