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


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类定义原型方法的两种实现的区别评论很多
Sep 12 Javascript
jQuery 对象中的类数组操作
Apr 27 Javascript
使用jquery的ajax需要注意的地方dataType的设置
Aug 12 Javascript
常见的原始JS选择器使用方法总结
Apr 09 Javascript
jquery Easyui快速开发总结
Aug 20 Javascript
使用原生的javascript来实现轮播图
Feb 24 Javascript
jquery实现的table排序功能示例
Mar 10 Javascript
基于vue2.0+vuex的日期选择组件功能实现
Mar 13 Javascript
JS实现发送短信验证后按钮倒计时功能(防止刷新倒计时失效)
Jul 07 Javascript
js计算两个日期间的天数月的实例代码
Sep 20 Javascript
浅谈layer的Icon样式以及一些常用的layer窗口使用方法
Sep 11 Javascript
ES2020让代码更优美的运算符 (?.) (??)
Jan 04 Javascript
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
如何让搜索引擎抓取AJAX内容解决方案
2014/08/25 PHP
PHP邮箱验证示例教程
2016/06/01 PHP
Yii2框架配置文件(Application属性)与调试技巧实例分析
2019/05/27 PHP
VBScript版代码高亮
2006/06/26 Javascript
Ajax+Json 级联菜单实现代码
2009/10/27 Javascript
JQuery 弹出框定位实现方法
2010/12/02 Javascript
jquery复选框全选/取消示例
2013/12/30 Javascript
jQuery实现监控页面所有ajax请求的方法
2015/12/10 Javascript
XML、HTML、CSS与JS的区别整理
2016/02/18 Javascript
基于JavaScript实现报警器提示音效果
2017/10/27 Javascript
详解node child_process模块学习笔记
2018/01/24 Javascript
解决JavaScript layui 下拉框不显示的问题
2018/08/14 Javascript
微信小游戏之使用three.js 绘制一个旋转的三角形
2019/06/10 Javascript
小程序调用微信支付的方法
2019/09/26 Javascript
Vue 解决多级动态面包屑导航的问题
2019/11/04 Javascript
vue.js的状态管理vuex中store的使用详解
2019/11/08 Javascript
原生JS实现弹幕效果的简单操作指南
2020/11/10 Javascript
javascript全局自定义鼠标右键菜单
2020/12/08 Javascript
[02:47]DOTA2英雄基础教程 野性怒吼兽王
2013/12/05 DOTA
[51:36]Optic vs Newbee 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
Python实现删除文件但保留指定文件
2015/06/21 Python
python中string模块各属性以及函数的用法介绍
2016/05/30 Python
13个最常用的Python深度学习库介绍
2017/10/28 Python
Python入门之三角函数全解【收藏】
2017/11/08 Python
python skimage 连通性区域检测方法
2018/06/21 Python
Pandas0.25来了千万别错过这10大好用的新功能
2019/08/07 Python
python函数局部变量、全局变量、递归知识点总结
2019/11/15 Python
python turtle工具绘制四叶草的实例分享
2020/02/14 Python
金宝贝童装官网:Gymboree
2016/08/31 全球购物
Melissa鞋英国官方网站:Nonnon
2019/05/01 全球购物
N:Philanthropy官网:美国洛杉矶基础款服装
2020/06/09 全球购物
大学生优秀团员事迹材料
2014/01/30 职场文书
行政人事经理职位说明书
2014/03/05 职场文书
青年干部培训班学习心得体会
2016/01/06 职场文书
5行Python代码实现一键批量扣图
2021/06/29 Python
vue3 自定义图片放大器效果的示例代码
2022/07/23 Vue.js