从零打造个人任务管理系统:一个完整的 Node.js + SQLite 实战项目
折
折腾侠
2026/04/26 发布
0约 6 分钟765 字 / 851 词00
从零打造个人任务管理系统:一个完整的 Node.js + SQLite 实战项目
项目概述
本文将带你从零开始构建一个实用的个人任务管理系统(Personal Task Manager)。这个项目适合 Node.js 初学者,涵盖了后端 API 开发、数据库设计、RESTful 接口实现等核心技能。完成这个项目后,你将掌握构建完整 Web 应用的基础能力。
功能说明
本系统提供以下核心功能:
- 任务创建:添加新任务,支持设置标题、描述、优先级和截止日期
- 任务列表:查看所有任务,支持按状态(待完成/已完成)筛选
- 任务更新:修改任务信息,标记任务完成状态
- 任务删除:删除不需要的任务
- 数据统计:展示任务完成情况和统计信息
技术栈选择
| 技术 | 版本 | 用途 |
|---|---|---|
| Node.js | 18.x+ | 运行时环境 |
| Express | 4.x | Web 框架 |
| SQLite3 | 5.x | 轻量级数据库 |
| Better-SQLite3 | 9.x | 同步数据库驱动 |
| CORS | 2.x | 跨域支持 |
| Body-Parser | 1.x | 请求体解析 |
选择 SQLite 的原因:无需安装额外数据库服务,数据存储在单个文件中,非常适合小型项目和学习用途。
项目结构
task-manager/
├── package.json # 项目配置和依赖
├── server.js # 主入口文件
├── database.js # 数据库初始化和操作
├── routes/
│ └── tasks.js # 任务相关路由
├── middleware/
│ └── validation.js # 请求验证中间件
└── data/
└── tasks.db # SQLite 数据库文件(运行时生成)
核心代码实现
1. 项目初始化
首先创建项目目录并初始化:
Bash
mkdir task-manager
cd task-manager
npm init -y
npm install express better-sqlite3 cors body-parser
2. 数据库模块(database.js)
JavaScript
const Database = require('better-sqlite3');
const path = require('path');
const dbPath = path.join(__dirname, 'data', 'tasks.db');
const db = new Database(dbPath);
// 初始化数据库表
db.exec(`
CREATE TABLE IF NOT EXISTS tasks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
description TEXT,
priority TEXT DEFAULT 'medium',
status TEXT DEFAULT 'pending',
due_date TEXT,
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
)
`);
module.exports = db;
3. 主服务器(server.js)
JavaScript
const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');
const taskRoutes = require('./routes/tasks');
const app = express();
const PORT = process.env.PORT || 3000;
// 中间件
app.use(cors());
app.use(bodyParser.json());
// 路由
app.use('/api/tasks', taskRoutes);
// 健康检查
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date().toISOString() });
});
// 404 处理
app.use((req, res) => {
res.status(404).json({ error: 'Not Found' });
});
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
});
4. 任务路由(routes/tasks.js)
JavaScript
const express = require('express');
const router = express.Router();
const db = require('../database');
// 获取所有任务
router.get('/', (req, res) => {
const { status, priority } = req.query;
let query = 'SELECT * FROM tasks ORDER BY created_at DESC';
const params = [];
if (status) {
query = 'SELECT * FROM tasks WHERE status = ? ORDER BY created_at DESC';
params.push(status);
}
const tasks = db.prepare(query).all(...params);
res.json({ success: true, data: tasks, count: tasks.length });
});
// 获取单个任务
router.get('/:id', (req, res) => {
const { id } = req.params;
const task = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
if (!task) {
return res.status(404).json({ success: false, error: 'Task not found' });
}
res.json({ success: true, data: task });
});
// 创建任务
router.post('/', (req, res) => {
const { title, description, priority, due_date } = req.body;
if (!title) {
return res.status(400).json({ success: false, error: 'Title is required' });
}
const stmt = db.prepare(`
INSERT INTO tasks (title, description, priority, due_date)
VALUES (?, ?, ?, ?)
`);
const result = stmt.run(title, description || '', priority || 'medium', due_date || null);
const newTask = db.prepare('SELECT * FROM tasks WHERE id = ?').get(result.lastInsertRowid);
res.status(201).json({ success: true, data: newTask });
});
// 更新任务
router.put('/:id', (req, res) => {
const { id } = req.params;
const { title, description, priority, status, due_date } = req.body;
const existing = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
if (!existing) {
return res.status(404).json({ success: false, error: 'Task not found' });
}
const stmt = db.prepare(`
UPDATE tasks
SET title = ?, description = ?, priority = ?, status = ?, due_date = ?, updated_at = CURRENT_TIMESTAMP
WHERE id = ?
`);
stmt.run(
title || existing.title,
description !== undefined ? description : existing.description,
priority || existing.priority,
status || existing.status,
due_date || existing.due_date,
id
);
const updated = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
res.json({ success: true, data: updated });
});
// 删除任务
router.delete('/:id', (req, res) => {
const { id } = req.params;
const existing = db.prepare('SELECT * FROM tasks WHERE id = ?').get(id);
if (!existing) {
return res.status(404).json({ success: false, error: 'Task not found' });
}
db.prepare('DELETE FROM tasks WHERE id = ?').run(id);
res.json({ success: true, message: 'Task deleted successfully' });
});
// 获取统计信息
router.get('/stats/summary', (req, res) => {
const total = db.prepare('SELECT COUNT(*) as count FROM tasks').get().count;
const completed = db.prepare("SELECT COUNT(*) as count FROM tasks WHERE status = 'completed'").get().count;
const pending = db.prepare("SELECT COUNT(*) as count FROM tasks WHERE status = 'pending'").get().count;
res.json({
success: true,
data: { total, completed, pending, completionRate: total > 0 ? Math.round((completed / total) * 100) : 0 }
});
});
module.exports = router;
运行步骤
第一步:准备环境
确保已安装 Node.js 18.x 或更高版本:
Bash
node -v # 应显示 v18.x.x 或更高
npm -v
第二步:创建项目
Bash
# 创建项目目录
mkdir task-manager
cd task-manager
# 初始化项目
npm init -y
# 安装依赖
npm install express better-sqlite3 cors body-parser
第三步:创建文件结构
按照上方项目结构创建所有文件,将对应代码复制到各文件中。
第四步:创建数据目录
Bash
mkdir data
第五步:启动服务器
Bash
node server.js
看到输出 INLINE_CODE_0 表示启动成功。
第六步:测试 API
使用 curl 或 Postman 测试接口:
Bash
# 健康检查
curl http://localhost:3000/health
# 创建任务
curl -X POST http://localhost:3000/api/tasks \
-H "Content-Type: application/json" \
-d '{"title":"学习 Node.js","description":"完成教程","priority":"high"}'
# 获取任务列表
curl http://localhost:3000/api/tasks
# 获取统计信息
curl http://localhost:3000/api/tasks/stats/summary
扩展建议
完成基础功能后,可以考虑以下扩展方向:
- 用户认证:添加 JWT 认证,支持多用户
- 前端界面:使用 React/Vue 构建可视化界面
- 任务分类:添加标签和分类功能
- 定时提醒:集成 node-cron 实现到期提醒
- 数据导出:支持导出为 CSV/JSON 格式
- 搜索功能:添加全文搜索能力
总结
通过这个项目,你掌握了:
- Express 框架的基础用法
- RESTful API 设计规范
- SQLite 数据库操作
- 中间件的使用
- 项目模块化组织
这是一个完整可运行的项目,代码简洁清晰,非常适合作为学习 Node.js 后端开发的入门实战。建议在此基础上继续扩展功能,加深理解。