TypeScript 语言 实战项目 内容管理系统 CMS

TypeScript阿木 发布于 2025-05-28 8 次阅读


TypeScript实战项目:内容管理系统(CMS)开发指南

内容管理系统(Content Management System,简称CMS)是一种用于创建、编辑、发布和管理网站内容的软件。在当今数字化时代,CMS已经成为企业、组织和个人管理网站内容的重要工具。TypeScript作为一种JavaScript的超集,提供了类型系统、模块化和编译时类型检查等特性,使得开发大型、复杂的应用程序变得更加容易。本文将围绕TypeScript语言,实战开发一个内容管理系统(CMS)。

项目概述

本篇文章将介绍如何使用TypeScript开发一个简单的CMS。我们将实现以下功能:

1. 用户注册与登录
2. 文章管理
3. 分类管理
4. 文章发布与预览
5. 文章搜索

技术栈

- TypeScript
- Node.js
- Express
- MongoDB
- Mongoose
- Bootstrap
- Axios

开发环境搭建

1. 安装Node.js和npm(Node Package Manager)
2. 创建一个新的TypeScript项目

bash
mkdir my-cms
cd my-cms
npm init -y
npm install typescript --save-dev
npx tsc --init

3. 安装项目依赖

bash
npm install express mongoose body-parser cors --save
npm install @types/node @types/express @types/mongoose @types/body-parser @types/cors --save-dev

4. 配置tsconfig.json

json
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"strict": true,
"esModuleInterop": true
}
}

5. 创建项目结构


my-cms/
├── src/
│ ├── models/
│ │ └── article.ts
│ ├── routes/
│ │ └── articleRoutes.ts
│ ├── controllers/
│ │ └── articleController.ts
│ ├── app.ts
│ └── server.ts
├── public/
│ └── index.html
├── package.json
└── tsconfig.json

用户注册与登录

1. 创建用户模型

在`src/models/article.ts`中定义用户模型:

typescript
import mongoose, { Document, Schema } from 'mongoose';

interface IUser extends Document {
username: string;
password: string;
}

const userSchema: Schema = new Schema({
username: { type: String, required: true },
password: { type: String, required: true }
});

export default mongoose.model('User', userSchema);

2. 创建用户控制器

在`src/controllers/articleController.ts`中创建用户控制器:

typescript
import { Request, Response } from 'express';
import User from '../models/article';

export const register = async (req: Request, res: Response) => {
const { username, password } = req.body;
try {
const user = new User({ username, password });
await user.save();
res.status(201).send('User registered successfully');
} catch (error) {
res.status(500).send('Error registering new user');
}
};

export const login = async (req: Request, res: Response) => {
const { username, password } = req.body;
try {
const user = await User.findOne({ username, password });
if (!user) {
return res.status(401).send('Invalid credentials');
}
res.status(200).send('Login successful');
} catch (error) {
res.status(500).send('Error logging in');
}
};

3. 创建用户路由

在`src/routes/articleRoutes.ts`中创建用户路由:

typescript
import { Router } from 'express';
import articleController from '../controllers/articleController';

const router: Router = Router();

router.post('/register', articleController.register);
router.post('/login', articleController.login);

export default router;

4. 配置Express应用

在`src/app.ts`中配置Express应用:

typescript
import express from 'express';
import articleRoutes from './routes/articleRoutes';

const app: express.Application = express();

app.use(express.json());
app.use('/api', articleRoutes);

export default app;

5. 启动服务器

在`src/server.ts`中启动服务器:

typescript
import app from './app';

const PORT = process.env.PORT || 3000;

app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});

文章管理

1. 创建文章模型

在`src/models/article.ts`中定义文章模型:

typescript
import mongoose, { Document, Schema } from 'mongoose';

interface IArticle extends Document {
title: string;
content: string;
author: mongoose.Types.ObjectId;
category: mongoose.Types.ObjectId;
publishedAt: Date;
}

const articleSchema: Schema = new Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
publishedAt: { type: Date, default: Date.now }
});

export default mongoose.model('Article', articleSchema);

2. 创建文章控制器

在`src/controllers/articleController.ts`中创建文章控制器:

typescript
import { Request, Response } from 'express';
import Article from '../models/article';

export const createArticle = async (req: Request, res: Response) => {
const { title, content, author, category } = req.body;
try {
const article = new Article({ title, content, author, category });
await article.save();
res.status(201).send('Article created successfully');
} catch (error) {
res.status(500).send('Error creating article');
}
};

export const getArticles = async (req: Request, res: Response) => {
try {
const articles = await Article.find();
res.status(200).send(articles);
} catch (error) {
res.status(500).send('Error fetching articles');
}
};

3. 创建文章路由

在`src/routes/articleRoutes.ts`中创建文章路由:

typescript
import { Router } from 'express';
import articleController from '../controllers/articleController';

const router: Router = Router();

router.post('/create', articleController.createArticle);
router.get('/', articleController.getArticles);

export default router;

4. 修改Express应用配置

在`src/app.ts`中修改Express应用配置:

typescript
import express from 'express';
import articleRoutes from './routes/articleRoutes';

const app: express.Application = express();

app.use(express.json());
app.use('/api', articleRoutes);

export default app;

分类管理

1. 创建分类模型

在`src/models/article.ts`中定义分类模型:

typescript
import mongoose, { Document, Schema } from 'mongoose';

interface ICategory extends Document {
name: string;
}

const categorySchema: Schema = new Schema({
name: { type: String, required: true }
});

export default mongoose.model('Category', categorySchema);

2. 创建分类控制器

在`src/controllers/articleController.ts`中创建分类控制器:

typescript
import { Request, Response } from 'express';
import Category from '../models/article';

export const createCategory = async (req: Request, res: Response) => {
const { name } = req.body;
try {
const category = new Category({ name });
await category.save();
res.status(201).send('Category created successfully');
} catch (error) {
res.status(500).send('Error creating category');
}
};

export const getCategories = async (req: Request, res: Response) => {
try {
const categories = await Category.find();
res.status(200).send(categories);
} catch (error) {
res.status(500).send('Error fetching categories');
}
};

3. 创建分类路由

在`src/routes/articleRoutes.ts`中创建分类路由:

typescript
import { Router } from 'express';
import articleController from '../controllers/articleController';

const router: Router = Router();

router.post('/create-category', articleController.createCategory);
router.get('/categories', articleController.getCategories);

export default router;

4. 修改Express应用配置

在`src/app.ts`中修改Express应用配置:

typescript
import express from 'express';
import articleRoutes from './routes/articleRoutes';

const app: express.Application = express();

app.use(express.json());
app.use('/api', articleRoutes);

export default app;

文章发布与预览

1. 修改文章模型

在`src/models/article.ts`中修改文章模型,添加`published`字段:

typescript
import mongoose, { Document, Schema } from 'mongoose';

interface IArticle extends Document {
title: string;
content: string;
author: mongoose.Types.ObjectId;
category: mongoose.Types.ObjectId;
publishedAt: Date;
published: boolean;
}

const articleSchema: Schema = new Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
publishedAt: { type: Date, default: Date.now },
published: { type: Boolean, default: false }
});

export default mongoose.model('Article', articleSchema);

2. 修改文章控制器

在`src/controllers/articleController.ts`中修改文章控制器,添加发布和预览文章的方法:

typescript
import { Request, Response } from 'express';
import Article from '../models/article';

export const publishArticle = async (req: Request, res: Response) => {
const { id } = req.params;
try {
const article = await Article.findByIdAndUpdate(id, { published: true }, { new: true });
res.status(200).send('Article published successfully');
} catch (error) {
res.status(500).send('Error publishing article');
}
};

export const previewArticle = async (req: Request, res: Response) => {
const { id } = req.params;
try {
const article = await Article.findById(id);
res.status(200).send(article);
} catch (error) {
res.status(500).send('Error previewing article');
}
};

3. 修改文章路由

在`src/routes/articleRoutes.ts`中修改文章路由,添加发布和预览文章的路由:

typescript
import { Router } from 'express';
import articleController from '../controllers/articleController';

const router: Router = Router();

router.post('/create', articleController.createArticle);
router.get('/', articleController.getArticles);
router.post('/publish/:id', articleController.publishArticle);
router.get('/preview/:id', articleController.previewArticle);

export default router;

4. 修改Express应用配置

在`src/app.ts`中修改Express应用配置:

typescript
import express from 'express';
import articleRoutes from './routes/articleRoutes';

const app: express.Application = express();

app.use(express.json());
app.use('/api', articleRoutes);

export default app;

文章搜索

1. 修改文章模型

在`src/models/article.ts`中修改文章模型,添加`searchable`字段:

typescript
import mongoose, { Document, Schema } from 'mongoose';

interface IArticle extends Document {
title: string;
content: string;
author: mongoose.Types.ObjectId;
category: mongoose.Types.ObjectId;
publishedAt: Date;
published: boolean;
searchable: string;
}

const articleSchema: Schema = new Schema({
title: { type: String, required: true },
content: { type: String, required: true },
author: { type: mongoose.Schema.Types.ObjectId, ref: 'User', required: true },
category: { type: mongoose.Schema.Types.ObjectId, ref: 'Category', required: true },
publishedAt: { type: Date, default: Date.now },
published: { type: Boolean, default: false },
searchable: { type: String, required: true }
});

export default mongoose.model('Article', articleSchema);

2. 修改文章控制器

在`src/controllers/articleController.ts`中修改文章控制器,添加搜索文章的方法:

typescript
import { Request, Response } from 'express';
import Article from '../models/article';

export const searchArticles = async (req: Request, res: Response) => {
const { query } = req.query;
try {
const articles = await Article.find({ searchable: { $regex: query, $options: 'i' } });
res.status(200).send(articles);
} catch (error) {
res.status(500).send('Error searching articles');
}
};

3. 修改文章路由

在`src/routes/articleRoutes.ts`中修改文章路由,添加搜索文章的路由:

typescript
import { Router } from 'express';
import articleController from '../controllers/articleController';

const router: Router = Router();

router.post('/create', articleController.createArticle);
router.get('/', articleController.getArticles);
router.post('/publish/:id', articleController.publishArticle);
router.get('/preview/:id', articleController.previewArticle);
router.get('/search', articleController.searchArticles);

export default router;

4. 修改Express应用配置

在`src/app.ts`中修改Express应用配置:

typescript
import express from 'express';
import articleRoutes from './routes/articleRoutes';

const app: express.Application = express();

app.use(express.json());
app.use('/api', articleRoutes);

export default app;

总结

本文介绍了如何使用TypeScript开发一个简单的CMS。通过实现用户注册与登录、文章管理、分类管理、文章发布与预览以及文章搜索等功能,我们构建了一个功能完善的内容管理系统。在实际项目中,您可以根据需求扩展更多功能,如用户权限管理、评论系统、标签管理等。希望本文对您在TypeScript开发CMS方面有所帮助。