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


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 相关文章推荐
showModalDialog 和 showModelessDialog
Jan 22 Javascript
跟着Jquery API学Jquery之一 选择器
Apr 07 Javascript
ExtJS中文乱码之GBK格式编码解决方案及代码
Jan 20 Javascript
JScript中的条件注释详解
Apr 24 Javascript
Bootstrap插件全集
Jul 18 Javascript
jQuery图片轮播实现并封装(一)
Dec 03 Javascript
Bootstrap显示与隐藏简单实现代码
Mar 06 Javascript
基于JavaScript实现图片剪切效果
Mar 07 Javascript
原生javascript上传图片带进度条【实例分享】
Apr 06 Javascript
vuejs 单文件组件.vue 文件的使用
Jul 28 Javascript
详解jquery和vue对比
Apr 16 jQuery
vue postcss-px2rem 自适应布局
May 15 Vue.js
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
通过文字传递创建的图形按钮
2006/10/09 PHP
PHP生成月历代码
2007/06/14 PHP
深入php处理整数函数的详解
2013/06/09 PHP
php保存任意网络图片到服务器的方法
2015/04/14 PHP
Zend Framework校验器Zend_Validate用法详解
2016/12/09 PHP
thinkphp5实现微信扫码支付
2019/12/23 PHP
50个优秀经典PHP算法大集合 附源码
2020/08/26 PHP
在JavaScript中typeof的用途介绍
2013/04/11 Javascript
原生js实现复制对象、扩展对象 类似jquery中的extend()方法
2014/08/30 Javascript
使用控制台破解百小度一个月只准改一次名字
2015/08/13 Javascript
javascript实现图片延迟加载方法汇总(三种方法)
2015/08/27 Javascript
干货分享:让你分分钟学会javascript闭包
2015/12/25 Javascript
JavaScript  cookie 跨域访问之广告推广
2016/04/20 Javascript
javascript连接mysql与php通过odbc连接任意数据库的实例
2017/12/27 Javascript
详解webpack模块加载器兼打包工具
2018/09/11 Javascript
Vue项目pdf(base64)转图片遇到的问题及解决方法
2018/10/19 Javascript
微信小程序使用swiper组件实现层叠轮播图
2018/11/04 Javascript
微信小程序textarea层级过高的解决方法
2019/03/04 Javascript
JS实现的雪花飘落特效示例
2019/12/03 Javascript
小程序websocket心跳库(websocket-heartbeat-miniprogram)
2020/02/23 Javascript
JavaScript仿京东秒杀倒计时
2020/03/17 Javascript
Element Backtop回到顶部的具体使用
2020/07/27 Javascript
vue实现井字棋游戏
2020/09/29 Javascript
vue 基于abstract 路由模式 实现页面内嵌的示例代码
2020/12/14 Vue.js
[01:31]完美与DOTA2历程
2014/07/31 DOTA
[01:16:37]【全国守擂赛】第三周决赛 Dark Knight vs. 一个弱队
2020/05/04 DOTA
python实现Floyd算法
2018/01/03 Python
浅谈python元素如何去重,去重后如何保持原来元素的顺序不变
2020/02/28 Python
Python替换NumPy数组中大于某个值的所有元素实例
2020/06/08 Python
最新PyCharm 2020.2.3永久激活码(亲测有效)
2020/11/26 Python
元旦晚会策划方案
2014/02/18 职场文书
建筑工地文明标语
2014/10/09 职场文书
2019初中学生入团申请书
2019/06/27 职场文书
Redis IP地址的绑定的实现
2021/05/08 Redis
详解Flask开发技巧之异常处理
2021/06/15 Python
MySQL中IO问题的深入分析与优化
2022/04/02 MySQL