Node.js 博客实例(十五)转载和转载统计功能
2014-08-29 13:28
573 查看
原教程 https://github.com/nswbmw/N-blog/wiki/_pages的第十五章,由于版本等的原因,在原教程基础上稍加改动即可实现。
我们的设计思路是:当在线用户满足特定条件时,文章页面才会显示 转载 链接字样,当用户点击 转载 后,复制一份存储当前文章的文档,修改后以新文档的形式存入数据库,而不是单纯的添加一条指向被转载的文档的 "引用" ,这种设计是合理的,因为这样我们也可以将转载来的文章进行修改。
首先,我们来完成转载文章的功能。
打开 post.js ,将 Post.prototype.save 内的:
这里我们在 Post.reprint() 内实现了被转载的原文章的更新和转载后文章的存储。
注意这一句:doc.title = (doc.title.search(/[reprint]/) > -1) ? doc.title : "[reprint]" + doc.title;
原教程里是doc.title = (doc.title.search(/[转载]/) > -1) ? doc.title : "[转载]" + doc.title;
汉字的话就会报错:
打开 index.js ,在 app.get('/remove/:name/:day/:title') 后添加如下代码:
注意:我们需要通过 Post.edit() 返回一篇文章 markdown 格式的文本,而不是通过 Post.getOne 返回一篇转义后的 HTML 文本,因为我们还要将修改后的文档存入数据库,而数据库中应该存储 markdown 格式的文本。
最后,我们在文章页(article.ejs)添加转载链接。
打开 article.ejs ,在:
<% if (user && (user.name == post.name)) { %>
<span><a class="edit" href="/edit/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">编辑</a></span>
<span><a class="edit" href="/remove/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">删除</a></span>
<% } %>
后添加如下代码:
最后,我们需要添加一个 原文链接 来指向被转载的文章。
打开 index.ejs 、user.ejs 、article.ejs,在第一个 <p class="info"> 里最后添加如下代码:
接下来我们添加转载统计。
打开 index.ejs 、user.ejs 、article.ejs ,将:
<p class="info">阅读:<%= post.pv %> | 评论:<%= post.comments.length %></p>
修改为:
现在我们就给博客添加了转载统计的功能。但工作还没有完成,假如我们要删除一篇转载来的文章时,还要将被转载的原文章所在文档的 reprint_to 删除遗留的转载信息。
打开 post.js ,将 Post.remove 修改为:
再登录用户‘123’,转载这篇文章:
转载:
顺着教程做到这里,其实还是存在一些问题的,将在最后一篇总结里贴出这些问题
我们的设计思路是:当在线用户满足特定条件时,文章页面才会显示 转载 链接字样,当用户点击 转载 后,复制一份存储当前文章的文档,修改后以新文档的形式存入数据库,而不是单纯的添加一条指向被转载的文档的 "引用" ,这种设计是合理的,因为这样我们也可以将转载来的文章进行修改。
首先,我们来完成转载文章的功能。
打开 post.js ,将 Post.prototype.save 内的:
var post = { name: this.name, head: this.head, time: time, title:this.title, tags: this.tags, post: this.post, comments: [], pv: 0 };修改为:
var post = { name: this.name, head: this.head, time: time, title:this.title, tags: this.tags, post: this.post, comments: [], reprint_info: {}, pv: 0 };打开 post.js ,在最后添加如下代码:
//转载一篇文章 Post.reprint = function(reprint_from, reprint_to, callback) { mongodb.open(function (err, db) { if (err) { return callback(err); } db.collection('posts', function (err, collection) { if (err) { mongodb.close(); return callback(err); } //找到被转载的文章的原文档 collection.findOne({ "name": reprint_from.name, "time.day": reprint_from.day, "title": reprint_from.title }, function (err, doc) { if (err) { mongodb.close(); return callback(err); } var date = new Date(); var time = { date: date, year : date.getFullYear(), month : date.getFullYear() + "-" + (date.getMonth() + 1), day : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(), minute : date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + (date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes()) } delete doc._id;//注意要删掉原来的 _id doc.name = reprint_to.name; doc.head = reprint_to.head; doc.time = time; doc.title = (doc.title.search(/[reprint]/) > -1) ? doc.title : "[reprint]" + doc.title; doc.comments = []; doc.reprint_info = {"reprint_from": reprint_from}; doc.pv = 0; //更新被转载的原文档的 reprint_info 内的 reprint_to collection.update({ "name": reprint_from.name, "time.day": reprint_from.day, "title": reprint_from.title }, { $push: { "reprint_info.reprint_to": { "name": doc.name, "day": time.day, "title": doc.title }} }, function (err) { if (err) { mongodb.close(); return callback(err); } }); //将转载生成的副本修改后存入数据库,并返回存储后的文档 collection.insert(doc, { safe: true }, function (err, post) { mongodb.close(); if (err) { return callback(err); } callback(err, post[0]); }); }); }); }); };
这里我们在 Post.reprint() 内实现了被转载的原文章的更新和转载后文章的存储。
注意这一句:doc.title = (doc.title.search(/[reprint]/) > -1) ? doc.title : "[reprint]" + doc.title;
原教程里是doc.title = (doc.title.search(/[转载]/) > -1) ? doc.title : "[转载]" + doc.title;
汉字的话就会报错:
Express 500 TypeError: E:\nodejs\blog\views\article.ejs:3 1| <%- include header %> 2| <p> >> 3| <% if (user && (user.name == post.name)) { %> 4| <span><a class="edit" href="/edit/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">编辑</a></span> 5| <span><a class="edit" href="/remove/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">删除</a></span> 6| <% } %> Cannot read property 'name' of null 1| <%- include header %> 2| <p> >> 3| <% if (user && (user.name == post.name)) { %> 4| <span><a class="edit" href="/edit/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">编辑</a></span> 5| <span><a class="edit" href="/remove/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">删除</a></span> 6| <% } %> Cannot read property 'name' of null at eval (eval at <anonymous> (E:\nodejs\blog\node_modules\ejs\lib\ejs.js:242:14), <anonymous>:31:89) at eval (eval at <anonymous> (E:\nodejs\blog\node_modules\ejs\lib\ejs.js:242:14), <anonymous>:35:35) at E:\nodejs\blog\node_modules\ejs\lib\ejs.js:255:15 at Object.exports.render (E:\nodejs\blog\node_modules\ejs\lib\ejs.js:293:13) at View.exports.renderFile [as engine] (E:\nodejs\blog\node_modules\ejs\lib\ejs.js:323:20) at View.render (E:\nodejs\blog\node_modules\express\lib\view.js:76:8) at Function.app.render (E:\nodejs\blog\node_modules\express\lib\application.js:523:10) at ServerResponse.res.render (E:\nodejs\blog\node_modules\express\lib\response.js:828:7) at E:\nodejs\blog\routes\index.js:282:8 at E:\nodejs\blog\models\post.js:146:5问题是处在转载之后返回的URL,本来是http://localhost:3000/u/123/2014-8-4/title 的形式,到但是如果这里title包含汉字就会报错。数据库里的数据是正常的。
打开 index.js ,在 app.get('/remove/:name/:day/:title') 后添加如下代码:
app.get('/reprint/:name/:day/:title', checkLogin); app.get('/reprint/:name/:day/:title', function (req, res) { Post.edit(req.params.name, req.params.day, req.params.title, function (err, post) { if (err) { req.flash('error', err); return res.redirect(back); } var currentUser = req.session.user, reprint_from = {name: post.name, day: post.time.day, title: post.title}, reprint_to = {name: currentUser.name, head: currentUser.head}; Post.reprint(reprint_from, reprint_to, function (err, post) { if (err) { req.flash('error', err); return res.redirect('back'); } req.flash('success', '转载成功!'); var url = '/u/' + post.name + '/' + post.time.day + '/' + post.title; //跳转到转载后的文章页面 res.redirect(url); }); }); });至此,我们给 转载 链接注册了路由响应。
注意:我们需要通过 Post.edit() 返回一篇文章 markdown 格式的文本,而不是通过 Post.getOne 返回一篇转义后的 HTML 文本,因为我们还要将修改后的文档存入数据库,而数据库中应该存储 markdown 格式的文本。
最后,我们在文章页(article.ejs)添加转载链接。
打开 article.ejs ,在:
<% if (user && (user.name == post.name)) { %>
<span><a class="edit" href="/edit/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">编辑</a></span>
<span><a class="edit" href="/remove/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">删除</a></span>
<% } %>
后添加如下代码:
<% var flag = 1 %> <% if (user && (user.name != post.name)) { %> <% if ((post.reprint_info.reprint_from != undefined) && (user.name == post.reprint_info.reprint_from.name)) { %> <% flag = 0 %> <% } %> <% if ((post.reprint_info.reprint_to != undefined)) { %> <% post.reprint_info.reprint_to.forEach(function (reprint_to, index) { %> <% if (user.name == reprint_to.name) { %> <% flag = 0 %> <% } %> <% }) %> <% } %> <% } else { %> <% flag = 0 %> <% } %> <% if (flag) { %> <span><a class="edit" href="/reprint/<%= post.name %>/<%= post.time.day %>/<%= post.title %>">转载</a></span> <% } %>以上代码的意思是:我们设置一个 flag 标志,如果用户是游客,或者是该文章的目前作者,或者是该文章的上一级作者,或者已经转载过该文章,都会将 flag 设置为 0 ,即不显示 转载 链接,即不能转载该文章。最后判断 flag 为 1 时才会显示 转载 链接,即才可以转载这篇文章。
最后,我们需要添加一个 原文链接 来指向被转载的文章。
打开 index.ejs 、user.ejs 、article.ejs,在第一个 <p class="info"> 里最后添加如下代码:
<% if (post.reprint_info.reprint_from) { %> <br><a href="/u/<%= post.reprint_info.reprint_from.name %>/<%= post.reprint_info.reprint_from.day %>/<%= post.reprint_info.reprint_from.title %>">原文链接</a> <% } %>现在我们就给博客添加了转载功能。
接下来我们添加转载统计。
打开 index.ejs 、user.ejs 、article.ejs ,将:
<p class="info">阅读:<%= post.pv %> | 评论:<%= post.comments.length %></p>
修改为:
<p class="info"> 阅读:<%= post.pv %> | 评论:<%= post.comments.length %> | 转载: <% if (post.reprint_info.reprint_to) { %> <%= post.reprint_info.reprint_to.length %> <% } else { %> <%= 0 %> <% } %> </p>
现在我们就给博客添加了转载统计的功能。但工作还没有完成,假如我们要删除一篇转载来的文章时,还要将被转载的原文章所在文档的 reprint_to 删除遗留的转载信息。
打开 post.js ,将 Post.remove 修改为:
Post.remove = function(name, day, title, callback) { //打开数据库 mongodb.open(function (err, db) { if (err) { return callback(err); } //读取 posts 集合 db.collection('posts', function (err, collection) { if (err) { mongodb.close(); return callback(err); } //查询要删除的文档 collection.findOne({ "name": name, "time.day": day, "title": title }, function (err, doc) { if (err) { mongodb.close(); return callback(err); } //如果有 reprint_from,即该文章是转载来的,先保存下来 reprint_from var reprint_from = ""; if (doc.reprint_info.reprint_from) { reprint_from = doc.reprint_info.reprint_from; } if (reprint_from != "") { //更新原文章所在文档的 reprint_to collection.update({ "name": reprint_from.name, "time.day": reprint_from.day, "title": reprint_from.title }, { $pull: { "reprint_info.reprint_to": { "name": name, "day": day, "title": title }} }, function (err) { if (err) { mongodb.close(); return callback(err); } }); } //删除转载来的文章所在的文档 collection.remove({ "name": name, "time.day": day, "title": title }, { w: 1 }, function (err) { mongodb.close(); if (err) { return callback(err); } callback(null); }); }); }); }); };看看效果,用户‘123’将转载用户‘dss’的一片文章:
再登录用户‘123’,转载这篇文章:
转载:
顺着教程做到这里,其实还是存在一些问题的,将在最后一篇总结里贴出这些问题
相关文章推荐
- Node.js 博客实例(六)留言功能
- Node.js 博客实例(十一)文章检索功能
- Node.js 博客实例(五)编辑与删除功能
- Node.js 博客实例(十六)日志功能
- Node.js 博客实例(三)增加文件上传功能
- Node.js 博客实例(六)留言功能
- Node.js 博客实例(十)pv统计和留言统计
- Node.js 博客实例(十二)友情链接功能
- Node.js 博客实例(五)编辑与删除功能
- Node.js 博客实例(三)添加文件上传功能
- Node.js 博客实例(七)分页功能
- Node.js 博客实例(一)简单博客
- Node.js 博客实例(四)实现用户页面和文章页面
- node.js学习博客转载
- Node.js 博客实例(补充一)使用KindEditor
- node.js+express+ejs+MongoDB模板修改写《node.js开发指南》中的博客网站实例
- Node.js 博客实例(九)标签和标签页面
- Node.js 博客实例(二)使用 Markdown
- Node.js 博客实例(八)增加存档页面
- Node.js 博客实例(十三)增加404页面