现在,我们来实现发表话题、话题页以及评论的功能。首先,我们来实现发表页的功能,修改 default.scheme.js,在适当位置添加如下代码:
"(GET|POST) /create": {
"request": {
"session": checkLogin
}
},
"POST /create": {
"request": {
"body": checkCreateBody
}
}
function checkCreateBody() {
var body = this.request.body;
var flash;
if (!body || !body.title || body.title.length < 10) {
flash = {error: '请填写合法标题!'};
}
else if (!body.tab) {
flash = {error: '请选择版块!'};
}
else if (!body.content) {
flash = {error: '请填写内容!'};
}
if (flash) {
this.flash = flash;
this.redirect('back');
return false;
}
body.title = validator.trim(body.title);
body.tab = validator.trim(body.tab);
body.content = validator.trim(body.content);
return true;
}
以上代码用来验证用户状态以及发帖内容是否合法,并对请求体格式化。修改 create.js,添加如下代码:
var Models = require('../lib/core');
var $Topic = Models.$Topic;
exports.get = function* () {
yield this.render('create');
};
exports.post = function* () {
var data = this.request.body;
data.user = this.session.user;
var topic = yield $Topic.addTopic(data);
this.flash = {success: '发布成功!'};
this.redirect('/topic/' + topic._id);
};
最后,将 create.ejs 的内容修改如下:
<% include header %>
<div class="container">
<div class="ui two column centered grid">
<div class="right floated left aligned four wide column">
<% var name = this.session.user.name; %>
<% include partials/userCard %>
<% include partials/noReplyCard %>
</div>
<div class="left floated twelve wide column">
<form method="post">
<div class="ui form segment">
<h2 style="margin-top:0">发表话题</h2>
<div class="field">
<div class="fields">
<div class="field required">
<label>版块</label>
<div class="ui selection dropdown">
<input type="hidden" name="tab">
<div class="default text">版块</div>
<i class="dropdown icon"></i>
<div class="menu">
<% $app.tabs.slice(1).forEach(function (tab) { %>
<div class="item" data-value="<%= tab %>">
<%= tab %>
</div>
<% }) %>
</div>
</div>
</div>
</div>
</div>
<div class="field required">
<label>标题</label>
<input placeholder="标题字数不少于10字" type="text" name="title">
</div>
<div class="field required">
<label>内容</label>
<textarea name="content"></textarea>
</div>
<input type="submit" class="ui button" value="发布">
</div>
</form>
</div>
</div>
</div>
<script type="text/javascript">
$('.ui.dropdown').dropdown();
</script>
<% include footer %>
至此就完成了发帖的功能,接下来实现话题页和评论的功能。修改 default.scheme.js,在适当位置添加如下代码:
"POST /topic/:id": {
"request": {
"session": checkLogin,
"body": checkReplyTopic
}
}
function checkReplyTopic() {
var body = this.request.body;
var flash;
if (!body || !body.topic_id || !validator.isMongoId(body.topic_id)) {
flash = {error: '回复的帖子不存在!'};
}
else if (!body.content) {
flash = {error: '回复的内容为空!'};
}
if (flash) {
this.flash = flash;
this.redirect('back');
return false;
}
body.content = validator.trim(body.content);
return true;
}
修改 topic/*id.js,添加如下代码:
var Models = require('../../lib/core');
var $Topic = Models.$Topic;
var $Comment = Models.$Comment;
exports.get = function* (id) {
yield this.render('topic', {
topic: $Topic.getTopicById(id),
comments: $Comment.getCommentsByTopicId(id)
});
};
exports.post = function* (id) {
var data = this.request.body;
data.user = this.session.user;
yield [
$Comment.addComment(data),
$Topic.incCommentById(id)
];
this.flash = {success: '回复成功!'};
this.redirect(this.query.redirect || 'back');
};
需要说明的是,因为在 co 或者 koa 中,yield 后面跟的数组或对象,都是并行执行的,所以我们在传入 topic.ejs 中的两个数据库查询的函数都是并行执行的。同样,添加一条评论以及更新评论数这两个操作也是并行执行的。
修改 topic.ejs,添加如下代码:
<% include header %>
<div class="container">
<div class="ui two column centered grid">
<div class="right floated left aligned four wide column">
<% var name = topic.user.name; %>
<% include partials/userCard %>
<% include partials/noReplyCard %>
</div>
<div class="left floated twelve wide column">
<div class="ui segment">
<h2 style="margin-top:0">
<%= topic.title %>
</h2>
<div class="topic">
发布于<%=: topic.created_at | fromNow %> •
作者 <%= topic.user.name %> •
<%= topic.pv %> 次浏览 •
<%= topic.comment %> 个回复 •
<%= topic.tab %>
</div>
<div class="ui divider"></div>
<div class="content">
<%-: topic.content | markdown %>
</div>
</div>
<% include comment %>
</div>
</div>
</div>
<% include footer %>
修改 comment.ejs,添加如下代码:
<div class="ui segment">
<div class="ui comments">
<h3 class="ui header">评论</h3>
<div class="ui divider"></div>
<% comments.forEach(function (comment) { %>
<div class="comment">
<a class="avatar" href="/user/<%= comment.user.name %>">
<img src="<%=: comment.user.email | gravatar %>">
</a>
<div class="content">
<a class="author" href="/user/<%= comment.user.name %>">
<%= comment.user.name %>
</a>
<div class="metadata">
<span class="date">
<%=: comment.updated_at | fromNow %>
</span>
</div>
<div class="text">
<%-: comment.content | markdown %>
</div>
</div>
</div>
<% }) %>
<% if ($this.session.user) { %>
<form class="ui reply form" method="post">
<input type="hidden" name="topic_id" value="<%= topic._id %>">
<div class="field">
<textarea name="content"></textarea>
</div>
<input type="submit" class="ui button" value="留言">
</form>
<% } %>
</div>
</div>
至此,我们就完成了论坛的所有功能,重启下程序试试吧。