前端面试题

微信小程序 评论,回帖加载_ide微信小程序 评论,回帖加载_ide_02

* Cases.php

// ... 
 /**
     * 加载评论列表
     * @param Request $request
     * @return array
     */
    public function commentList(Request $request) {
        $caseId = $request->get("caseId");
        $user = $this->getLoginUser($request);
        $userId = $user->getId();

        $a = [];
        self::replyList($a, $userId, $caseId, 0);

        // 最外层回复列表 不显示 xx 回复 yy
        foreach($a as &$it) {
            foreach ($it['replyList'] as &$reply) {
                unset($reply['atUser']);
            }
        }
        // 压扁嵌套回复, 递归不要再赋值回去,直接操作引用
        foreach ($a as &$it) {
            self::flatten($it['replyList']);
        }

        return $this->renderSuccess($a);
    }

    /**
     * @param $a
     */
    private static function flatten(&$a) {
        for ($i = 0; $i < count($a); $i++) {
            if (self::hasSubReply($a[$i])) {
                // 递归 压扁多级数组
                self::flatten($a[$i]['replyList']);
                // 压扁后都是一维数组
                foreach ($a[$i]['replyList'] as &$it) {
                    $it['replyList'] = [];
                }
                // 有下级评论之后的同级评论
                $b = array_slice($a, $i+1);
                // 有下级评论之前的同级评论
                $a = array_slice($a, 0, $i+1);
                // 合并压扁之后的评论
                $a = array_merge($a, $a[$i]['replyList'], $b);
            }
        }
    }

    private static function hasSubReply($item) {
        return (is_array($item['replyList']) && count($item['replyList']) > 0);
    }

    /**
     * 递归取得 评论/回帖
     * @param $a
     * @param $userId
     * @param $caseId
     * @param $pthId
     */
    private static function replyList(&$a, $userId, $caseId, $pthId) {
        Logger::write("pthId=".$pthId);

        // 评论倒叙加载, 回帖按正常顺序加载
        if ($pthId == 0) {
            $seq = "desc";
        } else {
            $seq = "asc";
        }
        $a = Comment::all(function($query) use ($caseId, $pthId, $seq) {
            $query->where("case_id", $caseId)->where("pth_id", $pthId)->order('id', $seq);
        });
        foreach ($a as &$it) {
            /** @var $it Comment */
            if ($pthId == 0) {
                $it['user'] = User::getNicknameAvatar($it['user_id']);
                $it['thumbupCount'] = $it->getThumbupCount();
                $it['hasThumbup'] = $it->userHasThumbup($userId);
            } else {
                // 回帖不提供 点赞
                $it['user'] = User::getNicknameAvatar($it['user_id']);
                // 回帖@User
                $atComment = Comment::get($pthId);
                $atUserId = $atComment->getUserId();
                $it['atUser'] = User::getNicknameAvatar($atUserId);
            }

            $pthId = $it->getId();
            $list = [];
            // 递归读取回复列表
            self::replyList($list, $userId, $caseId, $pthId);

            $it = $it->toArray();
            $it['replyList'] = $list;
        }
    }

返回数据格式:

微信小程序 评论,回帖加载_ico_03

js加载数据 主要方法:

 // 加载评论列表
  loadComment: function() {
    var page = this;
    // 加载病例详情
    App._get("cases/commentList", { caseId: page.data.caseId }, function (body, header) { 
      console.log(body.data)
      

      var serverTs = header.Timestamp;
      console.log("server timestamp=" + serverTs);
      // var now = new Date(serverTs);
      var createTs = 0, delta = 0, timeDesc = "";
      for (var i = 0; i < body.data.length; i++) {        
        createTs = (new Date(body.data[i].created_at)).getTime()/1000;
        delta = serverTs - createTs;
        // console.log(delta);
        if (delta < 60) {
          timeDesc = "刚刚";
        } else if (delta < 3600) {
          timeDesc = Math.floor(delta / 60) +"分钟前";
        } else if (delta < 86400) {
          // timeDesc = Math.floor(delta / 3600) + "小时前";
          var c = new Date(body.data[i].created_at);
          var hh = c.getHours();
          if (hh < 10) {
            hh = "0" + hh;
          }
          var mm = c.getMinutes();
          if (mm < 10) {
            mm = "0" + mm;
          }
          timeDesc = "今天 " + hh + ":" + mm;
        } else if (delta < 172800) {
          var c = new Date(body.data[i].created_at);
          var hh = c.getHours();
          if (hh < 10) {
            hh = "0" + hh;
          }
          var mm = c.getMinutes();
          if (mm < 10) {
            mm = "0" + mm;
          }
          timeDesc = "昨天 " + hh + ":" + mm;
        } else if (delta < 604800) {
          timeDesc = Math.floor(delta / 86400) + "天前";
        } else {
          timeDesc = body.data[i].created_at;
        }
        body.data[i].created_at = timeDesc;        
      }
      page.setData({        
        commentList: body.data
      });    

    }, function (err) {
      console.log(err)
    }, function (o) {
      // complete handler      
    }, false);
  },

 

 

wxml文件:

  <view class="section">
    <view class="sectionTitle">
      <view class="baffle"></view>
      <text class="title">病例评论</text>
    </view>
    <view class="sectionBody">

      <view class="commentWrap" wx:for="{{commentList}}" wx:for-item="comment" wx:key="id">
        <view class="userMeta">
          <image class="avatarThumb" mode="heightFix" src="{{comment.user.avatar_url}}" />
          <text class="publisher">{{comment.user.nickname}}</text>
          <text class="hospital">{{comment.user.hospital}}</text>
          <text class="datetime">{{comment.created_at}}</text>
        </view>
        <view class="comment">
          <text>{{comment.content}}</text>
        </view>
        <view class="sns">
          <view class="reply" data-pthid="{{comment.id}}" data-atUserNickname="{{comment.user.nickname}}" bindtap="popupInput">
            <image class="icons" src="../../images/icons/reply.png" />
          </view>
          <view class="thumb_up" data-id="{{comment.id}}" bindtap="thumbUpHandler">
            <image wx:if="{{comment.hasThumbup}}" class="icons" src="../../images/icons/thumb_up_on.png" />
            <image wx:else class="icons" src="../../images/icons/thumb_up.png" />
            <text class="num">{{comment.thumbupCount}}</text>
          </view>
        </view> <!-- /.sns -->

        <!-- 回复列表 -->
        <view class="replyList">
          <view class="replyWrap" wx:for="{{comment.replyList}}" wx:for-item="reply" wx:key="id" data-pthid="{{reply.id}}" data-atUserNickname="{{reply.user.nickname}}" bindtap="popupInput">
          <view wx:if="{{reply.atUser}}">
            <text class="nickname">{{reply.user.nickname}}</text> 回复 <text class="nickname">{{reply.atUser.nickname}}</text>:<text class="replyContent">{{reply.content}}</text>
          </view>
          <view wx:else>
            <text class="nickname">{{reply.user.nickname}}</text>:<text class="replyContent">{{reply.content}}</text>
          </view>
          
          </view>
        </view>
      </view>
      <!-- /.commentWrap -->
    </view>
    <!--/.sectionBody -->
  </view>

实现效果图:

微信小程序 评论,回帖加载_ide_04

其他:

getLoginUser方法:

    /**
     * 根据token取得当前登录的用户
     * @param Request $request
     * @return User
     */
    public function getLoginUser(Request $request) {
        $token = $request->param("token");
        $a = Cache::get($token);
        if (!$a) {
            $this->renderError("Token不合法或未登录");
            exit(403);
        }
        // array(2) { ["session_key"]=> string(24) "7UZPORQWE/TjNov2GZcRQQ==" ["openid"]=> string(28) "oUrog5Reme5w-W5KDBU90VA_Heho" }
        $openId = $a['openid'];

        unset($a);
        return \app\api\model\User::get(function($query) use($openId) {
            $query->where('open_id', $openId);
        });
    }

封装wx.request, get方法

  /**
   * get请求
   */
  _get(url, data, success, fail, complete, check_login) {
    let App = this;
    wx.showNavigationBarLoading();

    // 构造请求参数
    data = Object.assign({
      wxapp_id: siteInfo.wxapp_id,
      token: wx.getStorageSync('token')
    }, data);

    // 构造get请求
    let request = () => {
      data.token = wx.getStorageSync('token');
      wx.request({
        url: App.api_root + url,
        header: {
          'content-type': 'application/json'
        },
        data,
        success(res) {
          if (res.statusCode !== 200 || typeof res.data !== 'object') {        
            App.showError('网络请求出错');
            return false;
          }
          if (res.data.code === -1) {
            // 登录态失效, 重新登录
            wx.hideNavigationBarLoading();
            App.doLogin();
          } else if (res.data.code !== 0) {
            App.showError(res.data.msg);
            return false;
          } else {
            // code==0 stands for ok            
            success && success(res.data, res.header);
          }
        },
        fail(res) {
          // console.log(res);
          App.showError(res.errMsg, () => {
            fail && fail(res);
          });
        },
        complete(res) {
          wx.hideNavigationBarLoading();
          complete && complete(res);
        },
      });
    };
    // 判断是否需要验证登录
    check_login ? App.doLogin(request) : request();
  },

利用这个开源微信商城二次开发: 

https://download.csdn.net/download/fareast_mzh/12369992