1.描述:
朋友圈模块主要是在时间轴模块基础上,增加点赞,取消点赞,评论和删除评论的功能,当然,时间轴只是展示自己发的动态,而朋友圈则是展示所有人的动态。第一阶段主要实现了点赞和取消点赞以及显示点赞的用户名功能。
2.效果展示:
3.思路:
进入朋友圈页面时,从数据库查询所有动态以及对应的发动态的用户信息,对应的点赞信息,评论信息等,将每个动态以及它对应的这些信息封装为一个动态扩展类,之后所有动态以集合形式传给页面,前端页面拿到这些信息进行拆箱遍历,在对应的地方显示对应的信息。当然,对我点过赞的动态和没有点过赞的要区分显示,就像上图中,进入页面后,我点过赞的动态点赞的按钮应该是实红心的,没有点过的是空红心的。
再说点赞部分,当页面加载时,除了向后台去请求动态扩展类信息,我还从数据库获取了我点过的所有赞信息,这部分只提取我给点赞的动态id编号,存入数组中:
这样,在前段页面遍历展示动态列表,判断显示实心赞还是空心赞时,我只需要在每条动态点赞按钮处判断该动态id是否在我点过赞的动态id数组中,如果在的话,那说明我给这条动态点过赞,就显示红色实心,反之,相反:
再说点赞或是取消赞的行为,点赞或是取消赞肯定是需要将对应的动态id和一些信息通过ajax传到后台取数据库操作相关信息的(当然,我这部分用户量比较少,只是测试,所以直接操作数据库,一般点赞的信息都是要经过redis缓存的,毕竟这种频繁操作如果直接操作数据库的话,大量IO操作服务器是受不了的。redis部分将在后续项目引入…)。点赞按钮的onclick函数,我传了四个参数,分别是登录用户的id)、动态的id、this、以及该动态的点赞数量,前两个信息用于数据库删除或者添加点赞信息,第三个参数用于ajax获取button按钮的id,最后一个参数主要是用来操作点赞数增加一或者减少一。
==注意:==第三个参数我们即button按钮的id我们为什么也要通过参数传给ajax呢?因为我们这里的button是在循环遍历动态列表中的组件:
每一条动态下面的按钮应该有自己唯一的id标识,所以我们应该在遍历过程中动态的给button赋id值:
这样,我们在ajax中通过标签的id属性去修改标签时,才不会出现给一个动态点赞后,所有动态的点赞按钮全都变成红实心。而这里因为是动态给button赋id值,所以我们需要将这个参数也传给ajax。至于onclick函数,通过获取的四个信息,判断当前是点赞还是取消点赞,去对应的请求controller函数即可。这里说一下我是怎么判断当前是点赞还是取消点赞的,用了一个笨办法:上面说到,在页面刚加载的时候,或通过判断我对某动态是否点过赞而对应的选择显示一下两个按钮:
然后两个按钮分别绑定了一个onclick函数,再来看这两个函数:
而红色实心按钮的onclick函数正好与上面的相反,在页面初始加载的时候,能触发unlike函数的,只有是我们点过赞的红实心按钮:
所以timeNumun%2是1,选择执行:
即取消点赞的请求,之后timeNumun+1,当再次点击各个按钮时,timeNumun%2是0,则执行添加点赞的请求。
4.主要代码:
4.1 Service层:
@Override
public List<DynamicWithinfo> findAllDynamics() {
List<Dynamic> allDynamics = dynamicMapper.findAllDynamics();//获取所有动态
List<DynamicWithinfo> dynamicWithinfos = new ArrayList<DynamicWithinfo>();
//遍历所有动态,获取每条动态的评论信息和点赞信息,封装为新的组合类
for (Dynamic dynamic : allDynamics) {
List<CommentWithinfo> commentsWithinfo = new ArrayList<>();
List<LikeWithinfo> likesWithinfo = new ArrayList<>();
String[] pictures = null;
DynamicWithinfo dynamicWithinfo = new DynamicWithinfo();
//拆分图片
pictures = dynamic.getImg().split(",");
dynamicWithinfo.setPictures(pictures);//动态封装类加载图片信息
dynamicWithinfo.setDynamic(dynamic);//动态封装类加载动态信息
User userown = userMapper.selectByPrimaryKey(dynamic.getOwnId());
dynamicWithinfo.setUser(userown);//动态封装类加载所属用户信息
//装载该动态所有评论
List<Comment> comments = null;
comments = commentMapper.findCommentsByToId(dynamic.getId());
if (comments != null) {
for (Comment comment : comments) {
CommentWithinfo comm = new CommentWithinfo();
User user = userMapper.selectByPrimaryKey(comment.getFromId());
comm.setComment(comment);
comm.setUser(user);
commentsWithinfo.add(comm);
}
}
//装载该动态点赞信息
List<Like> likes = null;
likes = likeMapper.findLikeBytoId(dynamic.getId());
if (likes != null) {
for (Like like : likes) {
LikeWithinfo likeIn = new LikeWithinfo();
User user = userMapper.selectByPrimaryKey(like.getFromId());
likeIn.setLike(like);
likeIn.setUser(user);
likesWithinfo.add(likeIn);
}
}
dynamicWithinfo.setComments(commentsWithinfo);//动态封装类加载评论信息
dynamicWithinfo.setLikes(likesWithinfo);//动态封装类加载点赞信息
dynamicWithinfos.add(dynamicWithinfo);
}
return dynamicWithinfos;
}
//取消点赞
@Override
public void unlike(Integer id, Integer toId) {
likeMapper.unlike(id,toId);
}
//添加点赞
@Override
public void like(Integer id, Integer toId) {
likeMapper.insertLike(id,toId);
}
4.2 Controller层:
@GetMapping("/dynamiclist")
public String findAlldynamics(HttpServletRequest request){
HttpSession session = request.getSession();
User user = (User) session.getAttribute("user");
List<DynamicWithinfo> allDynamics = dynamicService.findAllDynamics();
List<Like> likesList = dynamicService.findAllLikesById(user.getId());
List<Integer> list = new ArrayList<>();
//我的点赞列表
for (Like like : likesList) {
list.add(like.getToId());
}
session.setAttribute("allDynamics",allDynamics);
session.setAttribute("likesList",list);
return "dynamics";
}
@GetMapping("/unlike")
@ResponseBody
public String unlike(Integer id,Integer toId){
dynamicService.unlike(id,toId);
return "success";
}
@GetMapping("/like")
@ResponseBody
public String like(Integer id,Integer toId,HttpServletRequest request){
User user = (User) request.getSession().getAttribute("user");
dynamicService.like(id,toId);
return user.getUsername();
}
4.3 html:
<p>
<div class="btn-group">
<button th:id="${session.user.id}+unlike+${dynamics.dynamic.id}"
th:onclick="|unlike(${session.user.id},${dynamics.dynamic.id},this,${dynamics.likes.size()})|"
th:if="${session.likesList.contains(dynamics.dynamic.id)}" type="button" class="btn waves-effect btn-sm ml-1 waves-light btn-rounded btn-danger"
th:text="${dynamics.likes.size()}+' Love'">Action</button>
<button th:id="${session.user.id}+like+${dynamics.dynamic.id}"
th:onclick="|like(${session.user.id},${dynamics.dynamic.id},this,${dynamics.likes.size()})|"
th:if="!${session.likesList.contains(dynamics.dynamic.id)}" type="button" class="btn btn-outline-danger btn-sm ml-1 btn-rounded"
th:text="${dynamics.likes.size()}+' Love'">Action</button>
<button type="button" th:if="${dynamics.likes.size()} ne '0'"
class="btn btn-danger dropdown-toggle dropdown-toggle-split btn-sm btn-rounded"
data-toggle="collapse"
th:data-target="'#collapseExample'+${dynamics.dynamic.id}" aria-expanded="false"
th:aria-controls="collapseExample+${dynamics.dynamic.id}">
<span class="sr-only">Toggle Dropdown</span>
</button>
<button type="button" th:if="${dynamics.likes.size()} eq '0'"
class="btn btn-danger dropdown-toggle dropdown-toggle-split btn-sm btn-rounded">
<span class="sr-only">Toggle Dropdown</span>
</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-outline-danger btn-sm ml-1 btn-rounded" th:text="${dynamics.comments.size()}+' comment'">Action</button>
<button type="button" th:if="${dynamics.comments.size()} ne '0'"
class="btn btn-danger dropdown-toggle dropdown-toggle-split btn-sm btn-rounded"
data-toggle="collapse"
th:data-target="'#collapseComment'+${dynamics.dynamic.id}" aria-expanded="false"
th:aria-controls="collapseComment+${dynamics.dynamic.id}">
<span class="sr-only">Toggle Dropdown</span>
</button>
<button type="button" th:if="${dynamics.comments.size()} eq '0'"
class="btn btn-danger dropdown-toggle dropdown-toggle-split btn-sm btn-rounded">
<span class="sr-only">Toggle Dropdown</span>
</button>
</div>
</p>
var timeNumun = 1;
function unlike(id,toId,obj,size) {
var num = size;
if (timeNumun % 2 == 0) {
timeNumun = timeNumun + 1;
var likesToken = id + 'likes';
$.ajax({
type: "GET",
url: '/dynamic/like?id=' + id + '&toId=' + toId,//url
success: function (data) {
var showText = document.getElementById(obj.id);
showText.innerHTML = num + ' Love';
$('#' + obj.id).attr("class", "btn waves-effect btn-sm ml-1 waves-light btn-rounded btn-danger");
document.getElementById(likesToken).innerHTML = data;
},
error: function () {
alert("异常!");
}
});
return false;
} else if (timeNumun % 2 == 1) {
timeNumun = timeNumun + 1;
var likesToken = id + 'likes';
$.ajax({
type: "GET",
url: '/dynamic/unlike?id=' + id + '&toId=' + toId,//url
success: function (data) {
var showText = document.getElementById(obj.id);
showText.innerHTML = num - 1 + ' Love';
$('#' + obj.id).attr("class", "btn btn-outline-danger btn-sm ml-1 btn-rounded");
document.getElementById(likesToken).innerHTML = '';
},
error: function () {
alert("异常!");
}
});
return false;
}
}
存在的问题:
上面提到ajax前设置了一个点击次数的标记变量timeNumun,页面初始时为1,之后每点击点击一次增加1,模2以判断是点赞还是取消点赞,但是有一个问题,页面初始时,同一状态的按钮是共享这个参数的。这样的话,当我对两个动态先后点赞时,第一个动态点赞过程不会出现任何问题,但是,当第一次点赞之后,timeNumun增加一,当我们对第二个动态点赞时,由于timeNumun%2==0了,它会去执行一下删除操作做,但是数据库没有该记录,所以前端也不会执行success中的操作,当再次点击后,又可以正常的点赞了,即第二个动态的第一次点赞操作是没有任何反应的,这是个问题,需要解决…
ps
总觉得方法有点笨笨的,虽然功能实现了,哎,继续学习吧…