* 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;
}
}
返回数据格式:
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>
实现效果图:
其他:
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();
},
利用这个开源微信商城二次开发: