一步步搭建自己的博客 .NET版(2、评论功能)
前言
这次开发的博客主要功能或特点:
第一:可以兼容各终端,特别是手机端。
第二:到时会用到大量html5,炫啊。
第三:导入博客园的精华文章,并做分类。(不要封我)
第四:做个插件,任何网站上的技术文章都可以转发收藏 到本博客。
所以打算写个系类:《一步步搭建自己的博客》
- 一步步开发自己的博客 .NET版(1、页面布局、blog迁移、数据加载)
- 一步步开发自己的博客 .NET版(2、评论功能)
- 一步步开发自己的博客 .NET版(3、注册登录功能)
- 一步步开发自己的博客 .NET版(4、文章发布功能)
- 一步步开发自己的博客 .NET版(5、搜索功能)
- 一步步开发自己的博客 .NET版(6、手机端的兼容)
演示地址:http://blog.haojima.net/ 群内共享源码:469075305
上一篇《一步步开发自己的博客(一)》发表之后得到的效应还不错,得到了二十几个赞。然后建的QQ群 两天不到 就有了进三十来个人。大家在群里关于建站经验讨论也是十分热烈。由此可见,大家对拥有自己的独立空间 是多么的渴望。
这篇主要是分析 评论功能。在这里,不得不吐槽下 博客园的评论功能。
第一、对于阅读者。大家有没有在看评论的时候,看着看着有往上翻?特别是有些对骂的评论,都不知道是谁在骂谁。不得不往上翻那个@的人发的是什么。不知道 这句话 是 对谁的哪句话做的回复。虽然有“引用”功能,但也有很多人没有使用。
第二、对于博主。在回复各位园友时,点击回复 ,然后 跳到 最下方,然后评论框 自动出现@*** 回复之后。想回复下一位,又要把滚动条拖上去。然后 又忘记 这个人是不是已经回复过了。又往下拖 看自己有没有回复过,或者有没有漏掉谁。如果评论够多的话 我相信 各位应该都这样的感觉,我的那个头 我的那个晕。
在这里 我就打算规避这类问题,像QQ空间的评论 就很爽,谁在和谁对话 一目了然。
表结构
对于这样的一个需求,没有做过的也许一时没有了头绪。这里最主要的关系就是,“引用”- 谁对谁说。是对哪条评论 展开的讨论。
其实我把表结构拿出来,相信大家就明白了。
这里 我再详细分析下每个字段。
ID:表主键
Content:评论的内容
CommentID:引用的评论内容的ID。
BlogUsersId:用户ID
BlogsId:博客ID
ReplyUserID:引用的评论的用户ID。
ReplyUserName:引用的评论的用户名。
CommentSort:没用(本来以为会用到)
ContentLevy:没用(本来以为会用到)
这里要说明下 CommentID:引用的评论内容的ID。其实并非真的是评论内容ID 而是"父评论ID"。我们为了简单起见,把评论分成两种。
父评论,子评论。什么是父评论,子评论?父:初始评论,子:在父评论的基础上进行评论,或者子评论的基础上进行评论。(这里就不分 子子评论 子子子评论了。我想递归应该也可以做到,但不想那么复杂了)
那么上面还有一个字段没有解释:
IsInitial 是否是"父评论"
如图:
实现
通过对表结构的简单分析,我相信 大家应该已经非常明白 我会怎么去实现了。
第一、评论提交
var BlogId = int.Parse(Request.Form["BlogId"]);
var UserId = MySession.UserInfoSessioin.Id; //int.Parse(Request.Form["UserId"]);
var CommentID = int.Parse(Request.Form["CommentID"]);
var Content = Request.Form["Content"];
var ReplyUserID = int.Parse(Request.Form["ReplyUser"]);
var ReplyUserName = string.Empty;
var User = BLL.Common.CacheData.GetUserInfo().Where(t => t.Id == ReplyUserID).FirstOrDefault();
if (null != User)
{
ReplyUserName = string.IsNullOrEmpty(User.UserNickname) ? User.UserName : User.UserNickname;
} BLL.BlogCommentBLL comment = new BLL.BlogCommentBLL();
comment.Add(new BlogComment()
{
BlogUsersId = UserId,
BlogsId = BlogId,
Content = Content,
CommentID = CommentID,
ReplyUserID = ReplyUserID,
ReplyUserName = ReplyUserName,
IsInitial = CommentID == -
});
comment.save();
一目了然,其实就是一个对象存入数据库了。至于每个字段的取值,你想怎么取看你自己的。
第二、加载评论
评论的加载 可能会比提交复杂那么一点。提交有前后 怎么去归类布局呢?
首先要对 父评论 的筛选,然后加载父评论 和 父评论下的子评论。感觉要进行多次数据库的查询,那么我们只能尝试尽可能少的查询。
下面来具体看实现代码。
int blogId = int.Parse(Request.Form["blogID"]);
int pageIndex = int.Parse(Request.Form["pageIndex"]);
BLL.CommentHandle com = new BLL.CommentHandle();
Dictionary<string, object> dic = new Dictionary<string, object>();
var comObj = com.GetComment(blogId, pageIndex);
if (null == comObj)
return PartialView("Null");
dic.Add("commentList", comObj);//对应的评论
dic.Add("SessionUser", BLL.Common.MySession.UserInfoSessioin);
return PartialView(dic);
com.GetComment(blogId, pageIndex) 方法 根据 博客ID 和 第几页评论 做为参数,取评论数据,下面给出方法的详细实现:
public List<List<BlogComment>> GetComment(int blogId, int pageIndex)
{
int total;
BLL.BlogCommentBLL com = new BlogCommentBLL();
//IsInitial == true 父评论 (第一次数据库查询:查询30条父评论)
List<int> disCom = com.GetList<int>(pageIndex, , out total, t => t.IsInitial == true && t.BlogsId == blogId,
false, t => t.Id).Select(t => t.Id).ToList();
if (pageIndex > total)//已经没有评论信息了
{
return null;
}
//第二次数据库查询:查询30条父评论 和30条父评论下的子评论
var listCom = com.GetList(t => disCom.Contains(t.CommentID) || disCom.Contains(t.Id)).ToList();
List<List<BlogComment>> ComObj = new List<List<BlogComment>>();
var ini = listCom.Where(t => t.IsInitial == true).ToList();//这里就不查数据库了直接进行集合筛选
//对评论进行分组(以父评论 分组)
foreach (BlogComment item in ini)
{
item.BlogUsers = CacheData.GetUserInfo().Where(t => t.Id == item.BlogUsersId).FirstOrDefault();
var userobj = CacheData.GetUserInfo().Where(t => t.Id == item.ReplyUserID).FirstOrDefault();
if (null != userobj)
item.ReplyUserName = userobj.UserNickname;
//添加 以父评论 为一分组 的评论
ComObj.Add(GetCom(item, listCom));
}
return ComObj;
}
上面进行了二次数据库查询,其余的时候 都是进行 数据集合的筛选。在上面的代码中 我们看到了 方法 GetCom(item, listCom)// 取 顶级评论 下的子评论
private List<BlogComment> GetCom(BlogComment com, List<BlogComment> list)
{
var li = list.Where(t => t.CommentID == com.Id).ToList();
li.Insert(, com);
return li;
}
效果图和演示地址
在此实现的全部过程都已经分析完了。我们来看看效果图和演示地址。
效果图:
演示地址:http://blog.haojima.net/admin/268.html (界面丑是丑了点,后期再美化。如果有美工愿意免费合作,非常欢迎~~)
如果您对本篇文章感兴趣,那就麻烦您点个赞,您的鼓励将是我的动力。 当然您还可以加入QQ群:讨论。
如果您有更好的处理方式,希望不要吝啬赐教。
一步步开发自己的博客 .NET版系列:http://www.cnblogs.com/zhaopei/tag/Hi-Blogs/
本文链接:http://www.cnblogs.com/zhaopei/p/4744846.html
疑问
我在构思开发博客的时候,有个疑问。那就是怎样更好的统计文章阅读量。
我知道的方式:
第一、通过Cookie。(缺点:如果要进行访问量排行的话,可以人为清理cookie,恶意刷新访问量)
第二、通过客户端取得IP(缺点:1.如果访问量大的话,每次插入数据库之前都要先查询是否存在。2.现在我们大多是公用外网IP,无法统计独立访客)
疑问:1.cnzz的独立访客(UV)是怎么统计的。2.博客园的文章阅读量是怎么统计的。(进过测试,文章刷新第二遍的时候可以看到 阅读量 加一 ,然后清理cookie 后刷新 阅读量 加一,然后不管怎么刷 都没反应了)
如果实在是找不到好的解决方案,我打算用 IP+系统版本+浏览器版本号 作为“联合主键”,如果“主键”24小时内重复两次以上,则不统计,如果cookie存在也不统计。
哪位大虾知道更好的解决方案能告诉我下,万分感谢。
一步步搭建自己的博客 .NET版(2、评论功能)的更多相关文章
- 一步步开发自己的博客 .NET版(11、Web.config文件的读取和修改)
Web.config的读取 对于Web.config的读取大家都很属性了.平时我们用得比较多的就是appSettings节点下配置.如: 我们对应的代码是: = ConfigurationManage ...
- 一步步开发自己的博客 .NET版(10、前端对话框和消息框的实现)
关于前端对话框.消息框的优秀插件多不胜数.造轮子是为了更好的使用轮子,并不是说自己造的轮子肯定好.所以,这个博客系统基本上都是自己实现的,包括日志记录.响应式布局.评论功能等等一些本可以使用插件的.好 ...
- 一步步开发自己的博客 .NET版(1、基本显示)
前言 我们每个猿都有一个搭建自己独立博客的梦,我也不例外.以前想 现在想 以后也想.之所以一直迟迟没有着手,是因为难以跨出第一步.每次心里想着,等我以后技术好了再说,然后就没有然后了.以前用过word ...
- 一步步开发自己的博客 .NET版(3、注册登录功能)
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做 ...
- 一步步开发自己的博客 .NET版(4、文章发布功能)百度编辑器
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做个插件,任何网站上的技术 ...
- 一步步开发自己的博客 .NET版(5、Lucenne.Net 和 必应站内搜索)
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做 ...
- 一步步开发自己的博客 .NET版 剧终篇(6、响应式布局 和 自定义样式)
前言 这次开发的博客主要功能或特点: 第一:可以兼容各终端,特别是手机端. 第二:到时会用到大量html5,炫啊. 第三:导入博客园的精华文章,并做分类.(不要封我) 第四:做 ...
- 为hexo博客添加基于gitment评论功能
关于gitment gitment其实就是利用你的代码仓库的Issues,来实现评论.每一篇文章对应该代码仓库中的 一个Issues,Issues中的评论对应你的博客每篇文章中的评论.如果你是用git ...
- 一步步开发自己的博客 .NET版(9、从model first替换成code first 问题记录)
为什么要改用code first 用过code first的基本上都不会再想用回model first或是db first(谁用谁知道).不要问我为什么不一开始就直接使用code first,因为那个 ...
随机推荐
- mobx @computed的解读
写在前面:我一开始看不懂官网的@computed的作用,因为即使我把@computed去掉,依然能正确的report,然后我百度谷歌都找不到答案,下面都是我自己的理解,如果是有问题的,不对的,请务必留 ...
- 玩转spring boot——快速开始
开发环境: IED环境:Eclipse JDK版本:1.8 maven版本:3.3.9 一.创建一个spring boot的mcv web应用程序 打开Eclipse,新建Maven项目 选择quic ...
- ASP.NET是如何在IIS下工作的
ASP.NET与IIS是紧密联系的,由于IIS6.0与IIS7.0的工作方式的不同,导致ASP.NET的工作原理也发生了相应的变化. IIS6(IIS7的经典模式)与IIS7的集成模式的不同 IIS6 ...
- 微信小程序前端源码逻辑和工作流
看完微信小程序的前端代码真的让我热血沸腾啊,代码逻辑和设计一目了然,没有多余的东西,真的是大道至简. 废话不多说,直接分析前端代码.个人观点,难免有疏漏,仅供参考. 文件基本结构: 先看入口app.j ...
- iOS 多线程之GCD的使用
在iOS开发中,遇到耗时操作,我们经常用到多线程技术.Grand Central Dispatch (GCD)是Apple开发的一个多核编程的解决方法,只需定义想要执行的任务,然后添加到适当的调度队列 ...
- wireshark 相关提示
Packet size limited during capture 提示说明标记的包没有抓全,在某些操作系统中,默认只抓96个字节,tcpdump中有"-s"参数可用于 ...
- 保护ASP.NET 应用免受 CSRF 攻击
CSRF是什么? CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/ ...
- .Net中的AOP读书笔记系列之AOP介绍
返回<.Net中的AOP>系列学习总目录 本篇目录 AOP是什么? Hello,World! 小结 本系列的源码本人已托管于Coding上:点击查看,想要注册Coding的可以点击该连接注 ...
- [译]DbContext API中使用SqlQuery和ExecuteSqlCommand获取存储过程的输入输出参数
水平有限,欢迎指正.原文:http://blogs.msdn.com/b/diego/archive/2012/01/10/how-to-execute-stored-procedures-sqlqu ...
- Memcached简介
在Web服务开发中,服务端缓存是服务实现中所常常采用的一种提高服务性能的方法.其通过记录某部分计算结果来尝试避免再次执行得到该结果所需要的复杂计算,从而提高了服务的运行效率. 除了能够提高服务的运行效 ...