项目中需要有文章的留言功能,作为使用百度贴吧较多的用户,我想借鉴贴吧的留言功能,开发项目文章的留言。经过简单的搜索,我并未发现比较系统的想法及资料,按照自我想法做了文章留言功能,以此纪念自我成长及为他人开发提供一点参考。
一、效果展示
具体效果如图1.1所示:
图:1.1效果展示
二、整体设计思路:
1.针对留言的效果分析,得出以下结论:a.对文章进行整体回复及评论时,可以认为是对文章进行盖楼 b.当楼层内出现回复时存在两种情况,分别是对楼层进行回复及对楼层内留言的回复。
2.可以得出解决思路:对文章评论时,被评论人为文章,产生了楼层。其他的留言都是依附于楼层存在的,只要找准楼层就可以展现楼层内的留言。
3.实施起来可以分解为: a.查询文章下的楼层 b.循环楼层将楼层内留言插入楼层 c.前台界面显示。
三、解决方案:
1.首先是数据库表的设计,具体数据库表效果如图1.2所示
图1.2为数据库表结构
sql代码片段如下:
Table structure for `t_comment`
-- ----------------------------
DROP TABLE IF EXISTS `t_comment`;
CREATE TABLE `t_comment` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID(自增主键)',
`article_id` varchar(32) DEFAULT NULL COMMENT '文章id',
`comment_id` int(11) DEFAULT NULL COMMENT '评论id(一级评论)',
`ruser` varchar(32) DEFAULT NULL COMMENT '被回复人(用户名)',
`user` varchar(32) DEFAULT NULL COMMENT '回复人(用户名)',
`content` varchar(360) DEFAULT NULL COMMENT '内容',
`user_type` varchar(2) DEFAULT NULL COMMENT '用户类型(U用户、D医生)',
`comment_date` datetime DEFAULT NULL COMMENT '评论时间',
`flag` int(11) DEFAULT NULL COMMENT '评论状态(默认0,审核通过1,审核不通过2,删除3)',
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=119 DEFAULT CHARSET=utf8;
a. comment_id为文章的楼层数,comment_id为空的数据代表对文章留言,若comment_id不为空,则数目代表留言所处的楼层数。
b. ruser代表被回复者,在有楼层数的情况下,如果没有ruser则代表单纯对楼层回复,如果有ruser则代表留言有被回复者及回复者。
c. user则代表留言用户,content代表留言的内容,usertype代表用户类型,comment_date代表评论产生的时间,flag代表评论的状态,决定是不是要显示。
2.具体代码情况,由于项目是基于ssh框架来开发的并进行了封装,可能看起来有些差别,但是思路解决方案没有区别。
具体代码如下:
public void listComment(BaseDhccDto dto) {
StringBuilder instb = new StringBuilder("");
// 查询文章的楼层
commentDao.listFlow(dto);
PagerModel pagerModel = dto.getPageModel();
pagerModel.setCountProName("id");
commonService.fillPagerModelData(pagerModel);
List<Comment> comments = (List<Comment>) dto.getPageModel().getPageData();
List<Integer> ins = new ArrayList<Integer>();
Map<Integer, Comment> map = new HashMap<Integer, Comment>();
//循环楼层信息,取出楼层id
for (Comment dc : comments) {
map.put(dc.getId(), dc);
//分离出楼层id ,id1,id2,id3
ins.add(dc.getId());
}
// 生成疾病分类in条件,将id中的,去掉变成id1,id2,id3
dto.addParam("commentId",ins);
//查询条件放入dto中,调用方法时再使用。
List<Comment> commentSub = commentDao.listComment(dto);
// 遍历楼层,添加回复到楼层中
for (Comment c : commentSub) {
map.get(c.getCommentId()).addComment(c);
}
}
a.此处代码为查询文章下的楼层,使用pagemodel来限制查询的楼层数目,例如只取前五楼。取出文章的楼层信息后,进行循环取出楼层的comment_id,根据comment_id取出留言信息,并再将信息插入楼层内。
dao中代码如下所示:
public void listFlow(BaseDhccDto dto){
Map<String, Object> params = new HashMap<String, Object>();
String artId = dto.getStringValue("articleId");
StringBuilder hql = new StringBuilder();
params.put("artId", artId);
hql.append(" from Comment c where c.articleId=:artId ")
.append(" and commentId is null ")
.append(" order by commentDate ");
PagerModel pagerModel = dto.getPageModel();
pagerModel.setQueryHql(hql.toString());
pagerModel.setHqlParamMap(params);
}
/*
* * 方法名: list
* 方法功能描述: 查询文章的回复记录
* @param:
* @return:
* @Author:
* @Create Date: 2015年01月09日11:43:37
* */
public List<Comment> listComment(BaseDhccDto dto) {
Map<String, Object> params = new HashMap<String, Object>();
String artId = dto.getStringValue("articleId");
List<Integer> commentId = (List<Integer>) dto.getParamValue("commentId");
StringBuilder hql = new StringBuilder();
params.put("artId", artId);
hql.append(" from Comment c where c.articleId=:artId ");
if(commentId==null || commentId.size() == 0) {
hql.append(" and commentId is null ");
}else{
hql.append(" and commentId in (:comment_id) ");
params.put("comment_id", commentId);
}
hql.append(" order by commentDate ");
return this.findByHqlWithValuesMap(hql.toString(), params, false, true);
}
3.在前端的实现:
<c:forEach items="${dto.pageModel.pageData}" var="comment" >
<div class="pt10 clearfix b_b1_d_gray pb20" id="${comment.id}">
<div class="w50 h50 fl mr20">
<a href="#"><img class="w" src="<c:url value='/imgs/login/user_icon.png'/>"/></a>
</div>
<div class="w590 fl">
<p class="clearfix">
<span class="font_green fl">用户${comment.user}</span>
<span class="fl">:</span>
<span class="font_gray fr"><fmt:formatDate value="${comment.commentDate}" pattern="yyyy-MM-dd HH:mm"/> </span>
</p>
<p class="font_black">${comment.content}</p>
<p class="tr"><a href="javascript:void(0);" class="font_blue comment_a" flowno="${comment.id}">我也说一句</a></p>
</div>
<c:forEach items="${comment.comments}" var="commentSub" >
<div class="w590 bg_color_blue3 pt5 pb5 pl15 pr15 fl b_b1_d_gray">
<c:if test="${ empty commentSub.ruser }">
<p>
<span class="font_green">${commentSub.user}</span>
<span> : </span>
<span>${commentSub.content}</span>
</p>
<a href="javascript:void(0);" class="font_blue fr comment_a" flowno="${comment.id}">回复</a>
</c:if>
<c:if test="${not empty commentSub.ruser }">
<p>
<span class="font_green">${commentSub.user}</span>
<span> 回复 </span>
<span class="font_gray">${commentSub.ruser}:</span>
<span>${commentSub.content}</span>
</p>
<a href="javascript:void(0);" class="font_blue fr comment_a" flowno="${comment.id}">回复</a>
</c:if>
</div>
</c:forEach>
</div>
</c:forEach>
4.点击回复需要插入输入框,此处用js来控制。
$(function() {
var reply = '<div class="clearfix comment_reply ml10 mt5 mb5"> <textarea id="contentTex" class="w400 h50 textarea_reply fl"></textarea> <a href="#" οnclick="shareComment(this);" class="btn btn_blue1 display_i w60 fl ml20" style="padding:0px;">发表</a> </div>';
$(".comment_a").live('click',function() {
$(".comment_reply").remove();
$(".comment_a").show();
$(this).after(reply).hide();
ruser = $(this).prev().children().first().text();
flowno = $(this).attr("flowno");
});
});
5.当回复请求发送完成后,如果是新增楼层那就刷新楼层来显示,如果是楼层内产生的留言,那就js控制来插入$().appned();
function(data) {
var comId = data.commentId;
if(comId != ""){
if(data.ruser == ""){
//无被回复人
$("#"+comId).append(
'<div class="w590 bg_color_blue3 pt5 pb5 pl15 pr15 fl b_b1_d_gray">'
+'<p><span class="font_green">'+data.user+'</span> <span> : </span>'
+'<span>'+data.content+'</span></p>'
+'<a href="javascript:void(0);" class="font_blue fr comment_a isLogin" flowno="'+data.commentId+'">回复</a> </div>'
);
}else{
$("#"+comId).append(
'<div class="w590 bg_color_blue3 pt5 pb5 pl15 pr15 fl b_b1_d_gray">'
+'<p> <span class="font_green">'+data.user+'</span> <span> 回复 </span>'
+'<span class="font_gray">'+data.ruser+':</span><span>'+data.content+'</span> </p>'
+'<a href="javascript:void(0);" class="font_blue fr comment_a isLogin" flowno="'+data.commentId+'">回复</a> </div>'
);
}
$(".comment_reply").remove();
// $("#"+comId).focus();
}
四、总结:
1.这个功能是自己一步一步从一个困难走向另一个困难来解决的,有很多地方还不够完善,代码功底也不是很扎实,希望自己能够一步一步不断前进,在迷茫时能够给自己提供动力。
2.感谢公司内的同事给我提供的帮助