前言
默认大家已经看过前面的文章,并成功完成前面步骤。这章主要写文章的CURD功能api的开发
文章功能
创建文章模型 models/post.js
const mongoose = require('mongoose');
const postSchema = new mongoose.Schema({
title: {
type: String,
required: true,
trim: true
},
content: {
type: String,
required: true
},
author: {
type: mongoose.Schema.Types.ObjectId,
ref: 'User',
required: true
},
tags: [{
type: String,
trim: true
}],
category: {
type: String,
required: true,
trim: true
},
status: {
type: String,
enum: ['draft', 'published'],
default: 'draft'
}
}, {
timestamps: true
});
const Post = mongoose.model('Post', postSchema);
module.exports = Post;
创建文章控制器controllers/postController.js
const Post = require('../models/Post');
// 创建文章
const createPost = async (req, res) => {
try {
const { title, content, tags, category } = req.body;
const post = await Post.create({
title,
content,
tags,
category,
author: req.user._id
});
res.status(201).json(post);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 获取所有文章
const getPosts = async (req, res) => {
try {
const { page = 1, limit = 10, category, tag } = req.query;
const query = {};
if (category) query.category = category;
if (tag) query.tags = tag;
const posts = await Post.find(query)
.populate('author', 'username')
.sort({ createdAt: -1 })
.limit(limit * 1)
.skip((page - 1) * limit);
const count = await Post.countDocuments(query);
res.json({
posts,
totalPages: Math.ceil(count / limit),
currentPage: page
});
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 获取单篇文章
const getPost = async (req, res) => {
try {
const post = await Post.findById(req.params.id)
.populate('author', 'username');
if (!post) {
return res.status(404).json({ message: '文章不存在' });
}
res.json(post);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 更新文章
const updatePost = async (req, res) => {
try {
const { title, content, tags, category, status } = req.body;
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({ message: '文章不存在' });
}
// 检查是否是作者或管理员
if (post.author.toString() !== req.user._id.toString() && req.user.role !== 'admin') {
return res.status(403).json({ message: '没有权限修改此文章' });
}
const updatedPost = await Post.findByIdAndUpdate(
req.params.id,
{ title, content, tags, category, status },
{ new: true }
).populate('author', 'username');
res.json(updatedPost);
} catch (error) {
res.status(500).json({ message: error.message });
}
};
// 删除文章
const deletePost = async (req, res) => {
try {
const post = await Post.findById(req.params.id);
if (!post) {
return res.status(404).json({ message: '文章不存在' });
}
// 检查是否是作者或管理员
if (post.author.toString() !== req.user._id.toString() && req.user.role !== 'admin') {
return res.status(403).json({ message: '没有权限删除此文章' });
}
await post.deleteOne();
res.json({ message: '文章已删除' });
} catch (error) {
res.status(500).json({ message: error.message });
}
};
module.exports = {
createPost,
getPosts,
getPost,
updatePost,
deletePost
};
创建文章路由routes/posts.js
const express = require('express');
const router = express.Router();
const {
createPost,
getPosts,
getPost,
updatePost,
deletePost
} = require('../controllers/postController');
const { protect } = require('../middleware/auth');
// 获取所有文章
router.get('/', getPosts);
// 获取单篇文章
router.get('/:id', getPost);
// 创建文章(需要登录)
router.post('/', protect, createPost);
// 更新文章(需要登录)
router.put('/:id', protect, updatePost);
// 删除文章(需要登录)
router.delete('/:id', protect, deletePost);
module.exports = router;
在app.js
中添加文章路由
const postRoutes = require('./routes/posts');
app.use('/api/posts', postRoutes);
OK 写完了。现在系统应该支持
- 文章创建
- 获取文章列表(支持分页、分类和标签筛选)
- 获取单篇文章
- 更新文章
- 删除文章
- 权限控制(只有作者和管理员可以修改/删除文章)
测试:
POST http://localhost:3000/posts
Content-Type: application/json
{
"title": "测试文章标题",
"content": "这是测试文章的内容",
"category": "技术", // 添加必填的 category 字段
"tags": "测试", // 可选的 tags 字段
"status": "draft" // 可选的 status 字段,默认为 "draft"
}
返回下列信息,创建文章接口成功
{
"title": "测试文章标题",
"content": "这是测试文章的内容",
"author": "68234d0c35c1531af74f8b21",
"tags": [
"测试"
],
"category": "技术",
"status": "draft",
"_id": "6825e0d1ab18230b995814ca",
"createdAt": "2025-05-15T12:40:49.553Z",
"updatedAt": "2025-05-15T12:40:49.553Z",
"__v": 0
}
其他接口不来发了,大家自己测试下把。记得对照下models/Post.js
里的数据