评论功能
评论功能主要有:
发表评论 POST /comments/new
删除评论 GET /comments/:id/delete
router.post('/comments/new', isLoginUser, require('./comments').create)
router.get('/comments/:id/delete', isLoginUser, require('./comments').destroy)
设计评论的模型
// models/comment.js
const mongoose = require('mongoose')
const Schema = mongoose.Schema
const CommentSchema = new Schema({
postId: {
type: Schema.Types.ObjectId,
ref: 'Post'
},
from: {
type: Schema.Types.ObjectId,
ref: 'User',
require: true
},
to: {
type: Schema.Types.ObjectId,
ref: 'User'
},
content: {
type: String,
required: true
},
meta: {
createAt: {
type: Date,
default: Date.now()
}
}
})
module.exports = mongoose.model('Comment', CommentSchema)
postId
代表评论对应的文章ID,from
代表发表评论者,to
代表需要艾特的人(本文暂不实现该功能),content
为内容
发布留言
先来写一个发表评论的表单。同时将它引入到post.html
// components/comments.html
<form action="/comments/new" method="POST" class="media">
<div class="media-content">
<div class="field">
<input type="hidden" name="postId" value="{{post._id}}">
<p class="control">
<textarea name="content" class="textarea" placeholder="发表评论…"></textarea>
</p>
</div>
<button class="button is-info is-pulled-right">Submit</button>
</div>
</form>
注意,这儿加了个隐藏域来存放postId
编写留言控制器routes/comments.js
const CommentModel = require('../models/comment')
module.exports = {
async create (ctx, next) {
const comment = Object.assign(ctx.request.body, {
from: ctx.session.user._id
})
await CommentModel.create(comment)
ctx.flash = { success: '留言成功' }
ctx.redirect('back')
}
}
显示留言
更改components/comments.html
添加一个留言列表
<form action="/comments/new" method="POST" class="media">
<div class="media-content">
<div class="field">
<input type="hidden" name="postId" value="{{post._id}}">
<p class="control">
<textarea name="content" class="textarea" placeholder="发表评论…"></textarea>
</p>
</div>
<button class="button is-info is-pulled-right">Submit</button>
</div>
</form>
{% for comment in comments %}
<article class="media comment">
<figure class="media-left">
<p class="image is-24x24">
<img src="https://bulma.io/images/placeholders/128x128.png">
</p>
</figure>
<div class="media-content">
<div class="content">
<p>
<strong>{{comment.from.name}}</strong>
<br>
{{marked(comment.content) | safe}}
</p>
</div>
<nav>
</nav>
</div>
<div class="media-right is-invisible">
<button id="reply" class="button is-small is-primary">回复</button>
<a href="/comments/{{comment._id}}/delete" class="button is-small">删除</a>
</div>
</article>
{% endfor %}
我们让评论也支持了markdown。
修改posts.js
控制器
...
const CommentModel = require('../models/comment')
...
async show (ctx, next) {
const post = await PostModel.findById(ctx.params.id)
.populate({ path: 'author', select: 'name' })
// 查找评论
const comments = await CommentModel.find({ postId: ctx.params.id })
.populate({ path: 'from', select: 'name' })
await ctx.render('post', {
title: post.title,
post,
comments
})
}
现在我们就完成了评论以及评论的展示。接下来实现删除功能
删除留言
async destroy (ctx, next) {
const comment = await CommentModel.findById(ctx.params.id)
if (!comment) {
throw new Error('留言不存在')
}
if (comment.from.toString() !== ctx.session.user._id.toString()) {
throw new Error('没有权限')
}
await CommentModel.findByIdAndRemove(ctx.params.id)
ctx.flash = { success: '成功删除留言' }
ctx.redirect('back')
}